diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index f7f70ff79..11cb52c9f 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -10,23 +10,26 @@ configurations { compile.exclude module: 'support-v4' } +configurations.all { + exclude group: 'com.google.firebase', module: 'firebase-core' +} + dependencies { + implementation 'androidx.core:core:1.1.0-beta01' + implementation 'androidx.palette:palette:1.0.0' + implementation 'androidx.exifinterface:exifinterface:1.0.0' + + implementation 'com.airbnb.android:lottie:3.0.1' + compileOnly 'org.checkerframework:checker-qual:2.5.2' compileOnly 'org.checkerframework:checker-compat-qual:2.5.0' - implementation 'com.google.firebase:firebase-core:16.0.7' - implementation 'com.google.firebase:firebase-messaging:17.3.4' - implementation 'com.google.firebase:firebase-config:16.1.3' - implementation 'com.google.android.gms:play-services-maps:16.0.0' + implementation 'com.google.firebase:firebase-messaging:18.0.0' + implementation 'com.google.firebase:firebase-config:16.5.0' + implementation 'com.google.android.gms:play-services-maps:16.1.0' implementation 'com.google.android.gms:play-services-auth:16.0.1' implementation 'com.google.android.gms:play-services-vision:16.2.0' implementation 'com.google.android.gms:play-services-wallet:16.0.1' implementation 'com.google.android.gms:play-services-wearable:16.0.1' - implementation 'com.android.support:support-core-ui:28.0.0' - implementation 'com.android.support:support-compat:28.0.0' - implementation 'com.android.support:support-core-utils:28.0.0' - implementation 'com.android.support:support-v13:28.0.0' - implementation 'com.android.support:palette-v7:28.0.0' - implementation 'com.android.support:exifinterface:28.0.0' implementation 'net.hockeyapp.android:HockeySDK:5.1.1' implementation 'com.googlecode.mp4parser:isoparser:1.0.6' implementation 'com.stripe:stripe-android:2.0.2' @@ -89,11 +92,11 @@ android { debugMultidex { initWith debug minifyEnabled false - multiDexEnabled true - dependencies{ + multiDexEnabled true + dependencies { implementation 'com.android.support:multidex:1.0.3' } - manifestPlaceholders = [applicationClassName:"MultiDexApplicationLoader"] + manifestPlaceholders = [applicationClassName: "MultiDexApplicationLoader"] } HA { @@ -115,15 +118,13 @@ android { } } - defaultConfig.versionCode = 1517 - sourceSets.debug { manifest.srcFile 'config/debug/AndroidManifest.xml' } sourceSets.debugMultidex { manifest.srcFile 'config/debug/AndroidManifest.xml' - java.srcDirs = ['src/multidex/java'] + java.srcDirs = ['src/multidex/java'] } sourceSets.HA { @@ -242,12 +243,24 @@ android { } } + defaultConfig.versionCode = 1591 + applicationVariants.all { variant -> variant.outputs.all { output -> - output.processManifest.doLast { + output.getProcessManifestProvider().get().doLast { def abiVersion = variant.productFlavors.get(0).abiVersionCode - String manifestPath = "$manifestOutputDirectory/AndroidManifest.xml" + + def outputDir = manifestOutputDirectory + File directory + if (outputDir instanceof File) { + directory = outputDir + } else { + directory = outputDir.get().asFile + } + + String manifestPath = directory.toString() + "/AndroidManifest.xml" def manifestContent = file(manifestPath).getText() + manifestContent = manifestContent.replace(String.format('android:versionCode="%d"', defaultConfig.versionCode), String.format('android:versionCode="%s"', defaultConfig.versionCode * 10 + abiVersion)) file(manifestPath).write(manifestContent) } @@ -256,7 +269,7 @@ android { variantFilter { variant -> def names = variant.flavors*.name - if(variant.buildType.name!="release" && !names.contains("afat")){ + if (variant.buildType.name != "release" && !names.contains("afat")) { setIgnore(true) } } @@ -264,9 +277,9 @@ android { defaultConfig { minSdkVersion 16 targetSdkVersion 27 - versionName "5.4.0" + versionName "5.6.1" - vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi'] + vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi'] externalNativeBuild { ndkBuild { @@ -275,7 +288,7 @@ android { } } - manifestPlaceholders = [applicationClassName:"ApplicationLoader"] + manifestPlaceholders = [applicationClassName: "ApplicationLoader"] } } diff --git a/TMessagesProj/config/debug/AndroidManifest.xml b/TMessagesProj/config/debug/AndroidManifest.xml index a0b63326b..0add1a21d 100644 --- a/TMessagesProj/config/debug/AndroidManifest.xml +++ b/TMessagesProj/config/debug/AndroidManifest.xml @@ -19,11 +19,10 @@ + + + + + - - - - - - - diff --git a/TMessagesProj/config/release/AndroidManifest.xml b/TMessagesProj/config/release/AndroidManifest.xml index db1b72d38..9600f7b57 100644 --- a/TMessagesProj/config/release/AndroidManifest.xml +++ b/TMessagesProj/config/release/AndroidManifest.xml @@ -19,8 +19,8 @@ + + + + + + + GetStringUTFChars(extension, NULL); - const char *destStr = env->GetStringUTFChars(dest, NULL); - const char *tempStr = env->GetStringUTFChars(temp, NULL); - - if (extensionStr == nullptr || destStr == nullptr || tempStr == nullptr) { - error = true; - } - - jbyte *keyBuff = nullptr; - jbyte *ivBuff = nullptr; - - if (!error && encKey != nullptr) { - keyBuff = env->GetByteArrayElements(encKey, NULL); - ivBuff = env->GetByteArrayElements(encIv, NULL); - if (keyBuff == nullptr || ivBuff == nullptr) { - error = true; - } - } - if (!error) { - if (delegate != nullptr) { - delegate = env->NewGlobalRef(delegate); - } - loadOperation = new FileLoadOperation(dc_id, id, volume_id, access_hash, local_id, (uint8_t *) keyBuff, (uint8_t *) ivBuff, extensionStr, version, size, destStr, tempStr); - loadOperation->setDelegate([delegate](std::string path) { - jstring pathText = jniEnv->NewStringUTF(path.c_str()); - if (delegate != nullptr) { - jniEnv->CallVoidMethod(delegate, jclass_FileLoadOperationDelegate_onFinished, pathText); - } - if (pathText != nullptr) { - jniEnv->DeleteLocalRef(pathText); - } - }, [delegate](FileLoadFailReason reason) { - if (delegate != nullptr) { - jniEnv->CallVoidMethod(delegate, jclass_FileLoadOperationDelegate_onFailed, reason); - } - }, [delegate](float progress) { - if (delegate != nullptr) { - jniEnv->CallVoidMethod(delegate, jclass_FileLoadOperationDelegate_onProgressChanged, progress); - } - }); - loadOperation->ptr1 = delegate; - } - if (keyBuff != nullptr) { - env->ReleaseByteArrayElements(encKey, keyBuff, JNI_ABORT); - } - if (ivBuff != nullptr) { - env->ReleaseByteArrayElements(encIv, ivBuff, JNI_ABORT); - } - if (extensionStr != nullptr) { - env->ReleaseStringUTFChars(extension, extensionStr); - } - if (destStr != nullptr) { - env->ReleaseStringUTFChars(dest, destStr); - } - if (tempStr != nullptr) { - env->ReleaseStringUTFChars(temp, tempStr); - } - - return (jint) loadOperation; -} - -void startLoadOperation(JNIEnv *env, jclass c, jint address) { - if (address != 0) { - ((FileLoadOperation *) address)->start(); - } -} - -void cancelLoadOperation(JNIEnv *env, jclass c, jint address) { - if (address != 0) { - ((FileLoadOperation *) address)->cancel(); - } -} - -static const char *FileLoadOperationClassPathName = "org/telegram/tgnet/FileLoadOperation"; -static JNINativeMethod FileLoadOperationMethods[] = { - {"native_createLoadOpetation", "(IJJJI[B[BLjava/lang/String;IILjava/lang/String;Ljava/lang/String;Ljava/lang/Object;)I", (void *) createLoadOpetation}, - {"native_startLoadOperation", "(I)V", (void *) startLoadOperation}, - {"native_cancelLoadOperation", "(I)V", (void *) cancelLoadOperation} -};*/ - jlong getFreeBuffer(JNIEnv *env, jclass c, jint length) { return (jlong) (intptr_t) BuffersStorage::getInstance().getFreeBuffer((uint32_t) length); } @@ -400,17 +308,10 @@ class Delegate : public ConnectiosManagerDelegate { jniEnv[instanceNum]->CallStaticVoidMethod(jclass_ConnectionsManager, jclass_ConnectionsManager_onProxyError); } - std::string getHostByName(std::string domain, int32_t instanceNum) { + void getHostByName(std::string domain, int32_t instanceNum, ConnectionSocket *socket) { jstring domainName = jniEnv[instanceNum]->NewStringUTF(domain.c_str()); - jstring address = (jstring) jniEnv[instanceNum]->CallStaticObjectMethod(jclass_ConnectionsManager, jclass_ConnectionsManager_getHostByName, domainName, instanceNum); - const char *addressStr = jniEnv[instanceNum]->GetStringUTFChars(address, 0); - std::string result = std::string(addressStr); - if (addressStr != 0) { - jniEnv[instanceNum]->ReleaseStringUTFChars(address, addressStr); - } + jniEnv[instanceNum]->CallStaticVoidMethod(jclass_ConnectionsManager, jclass_ConnectionsManager_getHostByName, domainName, (jlong) (intptr_t) socket); jniEnv[instanceNum]->DeleteLocalRef(domainName); - jniEnv[instanceNum]->DeleteLocalRef(address); - return result; } int32_t getInitFlags(int32_t instanceNum) { @@ -418,6 +319,21 @@ class Delegate : public ConnectiosManagerDelegate { } }; +void onHostNameResolved(JNIEnv *env, jclass c, jstring host, jlong address, jstring ip) { + const char *ipStr = env->GetStringUTFChars(ip, 0); + const char *hostStr = env->GetStringUTFChars(host, 0); + std::string i = std::string(ipStr); + std::string h = std::string(hostStr); + if (ipStr != 0) { + env->ReleaseStringUTFChars(ip, ipStr); + } + if (hostStr != 0) { + env->ReleaseStringUTFChars(host, hostStr); + } + ConnectionSocket *socket = (ConnectionSocket *) (intptr_t) address; + socket->onHostNameResolved(h, i, false); +} + void setLangCode(JNIEnv *env, jclass c, jint instanceNum, jstring langCode) { const char *langCodeStr = env->GetStringUTFChars(langCode, 0); @@ -506,7 +422,8 @@ static JNINativeMethod ConnectionsManagerMethods[] = { {"native_setPushConnectionEnabled", "(IZ)V", (void *) setPushConnectionEnabled}, {"native_setJava", "(Z)V", (void *) setJava}, {"native_applyDnsConfig", "(IJLjava/lang/String;)V", (void *) applyDnsConfig}, - {"native_checkProxy", "(ILjava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Lorg/telegram/tgnet/RequestTimeDelegate;)J", (void *) checkProxy} + {"native_checkProxy", "(ILjava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Lorg/telegram/tgnet/RequestTimeDelegate;)J", (void *) checkProxy}, + {"native_onHostNameResolved", "(Ljava/lang/String;JLjava/lang/String;)V", (void *) onHostNameResolved} }; inline int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods, int methodsCount) { @@ -527,10 +444,6 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) { if (!registerNativeMethods(env, NativeByteBufferClassPathName, NativeByteBufferMethods, sizeof(NativeByteBufferMethods) / sizeof(NativeByteBufferMethods[0]))) { return JNI_FALSE; } - - //if (!registerNativeMethods(env, FileLoadOperationClassPathName, FileLoadOperationMethods, sizeof(FileLoadOperationMethods) / sizeof(FileLoadOperationMethods[0]))) { - // return JNI_FALSE; - //} if (!registerNativeMethods(env, ConnectionsManagerClassPathName, ConnectionsManagerMethods, sizeof(ConnectionsManagerMethods) / sizeof(ConnectionsManagerMethods[0]))) { return JNI_FALSE; @@ -571,27 +484,6 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) { if (jclass_WriteToSocketDelegate_run == 0) { return JNI_FALSE; } - - jclass_FileLoadOperationDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/FileLoadOperationDelegate")); - if (jclass_FileLoadOperationDelegate == 0) { - return JNI_FALSE; - } - - jclass_FileLoadOperationDelegate_onFinished = env->GetMethodID(jclass_FileLoadOperationDelegate, "onFinished", "(Ljava/lang/String;)V"); - if (jclass_FileLoadOperationDelegate_onFinished == 0) { - return JNI_FALSE; - } - - jclass_FileLoadOperationDelegate_onFailed = env->GetMethodID(jclass_FileLoadOperationDelegate, "onFailed", "(I)V"); - if (jclass_FileLoadOperationDelegate_onFailed == 0) { - return JNI_FALSE; - } - - jclass_FileLoadOperationDelegate_onProgressChanged = env->GetMethodID(jclass_FileLoadOperationDelegate, "onProgressChanged", "(F)V"); - if (jclass_FileLoadOperationDelegate_onProgressChanged == 0) { - return JNI_FALSE; - } - jclass_ConnectionsManager = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/ConnectionsManager")); if (jclass_ConnectionsManager == 0) { return JNI_FALSE; @@ -640,7 +532,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) { if (jclass_ConnectionsManager_onProxyError == 0) { return JNI_FALSE; } - jclass_ConnectionsManager_getHostByName = env->GetStaticMethodID(jclass_ConnectionsManager, "getHostByName", "(Ljava/lang/String;I)Ljava/lang/String;"); + jclass_ConnectionsManager_getHostByName = env->GetStaticMethodID(jclass_ConnectionsManager, "getHostByName", "(Ljava/lang/String;J)V"); if (jclass_ConnectionsManager_getHostByName == 0) { return JNI_FALSE; } diff --git a/TMessagesProj/jni/emoji/emoji_suggestions.cpp b/TMessagesProj/jni/emoji/emoji_suggestions.cpp deleted file mode 100755 index 03f85279a..000000000 --- a/TMessagesProj/jni/emoji/emoji_suggestions.cpp +++ /dev/null @@ -1,452 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ - -#include "emoji_suggestions.h" - -#include -#include -#include "emoji_suggestions_data.h" - -checksum Crc32Table[256]; -class Crc32Initializer { -public: - Crc32Initializer() { - checksum poly = 0x04C11DB7U; - for (auto i = 0; i != 256; ++i) { - Crc32Table[i] = reflect(i, 8) << 24; - for (auto j = 0; j != 8; ++j) { - Crc32Table[i] = (Crc32Table[i] << 1) ^ (Crc32Table[i] & (1 << 31) ? poly : 0); - } - Crc32Table[i] = reflect(Crc32Table[i], 32); - } - } - -private: - checksum reflect(checksum val, char ch) { - checksum result = 0; - for (int i = 1; i < (ch + 1); ++i) { - if (val & 1) { - result |= 1 << (ch - i); - } - val >>= 1; - } - return result; - } - -}; - -checksum countChecksum(const void *data, std::size_t size) { - static Crc32Initializer InitTable; - - auto buffer = static_cast(data); - auto result = checksum(0xFFFFFFFFU); - for (auto i = std::size_t(0); i != size; ++i) { - result = (result >> 8) ^ Crc32Table[(result & 0xFFU) ^ buffer[i]]; - } - return (result ^ 0xFFFFFFFFU); -} - -class string_span { -public: - string_span() = default; - string_span(const utf16string *data, std::size_t size) : begin_(data), size_(size) { - } - string_span(const std::vector &data) : begin_(data.data()), size_(data.size()) { - } - string_span(const string_span &other) = default; - string_span &operator=(const string_span &other) = default; - - const utf16string *begin() const { - return begin_; - } - const utf16string *end() const { - return begin_ + size_; - } - std::size_t size() const { - return size_; - } - - string_span subspan(std::size_t offset, std::size_t size) { - return string_span(begin_ + offset, size); - } - -private: - const utf16string *begin_ = nullptr; - std::size_t size_ = 0; - -}; - -bool IsNumber(utf16char ch) { - return (ch >= '0' && ch <= '9'); -} - -bool IsLetterOrNumber(utf16char ch) { - return (ch >= 'a' && ch <= 'z') || IsNumber(ch); -} - -using Replacement = Replacement; - -class Completer { -public: - Completer(utf16string query); - - std::vector resolve(); - -private: - struct Result { - const Replacement *replacement; - int wordsUsed; - }; - - static std::vector NormalizeQuery(utf16string query); - void addResult(const Replacement *replacement); - bool isDuplicateOfLastResult(const Replacement *replacement) const; - bool isBetterThanLastResult(const Replacement *replacement) const; - void processInitialList(); - void filterInitialList(); - void initWordsTracking(); - bool matchQueryForCurrentItem(); - bool matchQueryTailStartingFrom(int position); - string_span findWordsStartingWith(utf16char ch); - int findEqualCharsCount(int position, const utf16string *word); - std::vector prepareResult(); - bool startsWithQuery(utf16string word); - bool isExactMatch(utf16string replacement); - - std::vector _result; - - utf16string _initialQuery; - const std::vector _query; - const utf16char *_queryBegin = nullptr; - int _querySize = 0; - - const std::vector *_initialList = nullptr; - - string_span _currentItemWords; - int _currentItemWordsUsedCount = 0; - - class UsedWordGuard { - public: - UsedWordGuard(std::vector &map, int index); - UsedWordGuard(const UsedWordGuard &other) = delete; - UsedWordGuard(UsedWordGuard &&other); - UsedWordGuard &operator=(const UsedWordGuard &other) = delete; - UsedWordGuard &operator=(UsedWordGuard &&other) = delete; - explicit operator bool() const; - ~UsedWordGuard(); - - private: - std::vector &_map; - int _index = 0; - bool _guarded = false; - - }; - std::vector _currentItemWordsUsedMap; - -}; - -Completer::UsedWordGuard::UsedWordGuard(std::vector &map, int index) : _map(map), _index(index) { - if (!_map[_index]) { - _guarded = _map[_index] = 1; - } -} - -Completer::UsedWordGuard::UsedWordGuard(UsedWordGuard &&other) : _map(other._map), _index(other._index), _guarded(other._guarded) { - other._guarded = 0; -} - -Completer::UsedWordGuard::operator bool() const { - return _guarded; -} - -Completer::UsedWordGuard::~UsedWordGuard() { - if (_guarded) { - _map[_index] = 0; - } -} - -Completer::Completer(utf16string query) : _initialQuery(query), _query(NormalizeQuery(query)) { -} - -// Remove all non-letters-or-numbers. -// Leave '-' and '+' only if they're followed by a number or -// at the end of the query (so it is possibly followed by a number). -std::vector Completer::NormalizeQuery(utf16string query) { - auto result = std::vector(); - result.reserve(query.size()); - auto copyFrom = query.data(); - auto e = copyFrom + query.size(); - auto copyTo = result.data(); - for (auto i = query.data(); i != e; ++i) { - if (IsLetterOrNumber(*i)) { - continue; - } else if (*i == '-' || *i == '+') { - if (i + 1 == e || IsNumber(*(i + 1))) { - continue; - } - } - if (i > copyFrom) { - result.resize(result.size() + (i - copyFrom)); - memcpy(copyTo, copyFrom, (i - copyFrom) * sizeof(utf16char)); - copyTo += (i - copyFrom); - } - copyFrom = i + 1; - } - if (e > copyFrom) { - result.resize(result.size() + (e - copyFrom)); - memcpy(copyTo, copyFrom, (e - copyFrom) * sizeof(utf16char)); - copyTo += (e - copyFrom); - } - return result; -} - -std::vector Completer::resolve() { - _queryBegin = _query.data(); - _querySize = _query.size(); - if (!_querySize) { - return std::vector(); - } - _initialList = GetReplacements(*_queryBegin); - if (!_initialList) { - return std::vector(); - } - _result.reserve(_initialList->size()); - processInitialList(); - return prepareResult(); -} - -bool Completer::isDuplicateOfLastResult(const Replacement *item) const { - if (_result.empty()) { - return false; - } - return (_result.back().replacement->emoji == item->emoji); -} - -bool Completer::isBetterThanLastResult(const Replacement *item) const { - auto &last = _result.back(); - if (_currentItemWordsUsedCount < last.wordsUsed) { - return true; - } - - auto firstCharOfQuery = _query[0]; - auto firstCharAfterColonLast = last.replacement->replacement[1]; - auto firstCharAfterColonCurrent = item->replacement[1]; - auto goodLast = (firstCharAfterColonLast == firstCharOfQuery); - auto goodCurrent = (firstCharAfterColonCurrent == firstCharOfQuery); - return !goodLast && goodCurrent; -} - -void Completer::addResult(const Replacement *item) { - if (!isDuplicateOfLastResult(item)) { - _result.push_back({ item, _currentItemWordsUsedCount }); - } else if (isBetterThanLastResult(item)) { - _result.back() = { item, _currentItemWordsUsedCount }; - } -} - -void Completer::processInitialList() { - if (_querySize > 1) { - filterInitialList(); - } else { - _currentItemWordsUsedCount = 1; - for (auto item : *_initialList) { - addResult(item); - } - } -} - -void Completer::initWordsTracking() { - auto maxWordsCount = 0; - for (auto item : *_initialList) { - auto wordsCount = item->words.size(); - if (maxWordsCount < wordsCount) { - maxWordsCount = wordsCount; - } - } - _currentItemWordsUsedMap = std::vector(maxWordsCount, 0); -} - -void Completer::filterInitialList() { - initWordsTracking(); - for (auto item : *_initialList) { - _currentItemWords = string_span(item->words); - _currentItemWordsUsedCount = 1; - if (matchQueryForCurrentItem()) { - addResult(item); - } - _currentItemWordsUsedCount = 0; - } -} - -bool Completer::matchQueryForCurrentItem() { - if (_currentItemWords.size() < 2) { - return startsWithQuery(*_currentItemWords.begin()); - } - return matchQueryTailStartingFrom(0); -} - -bool Completer::startsWithQuery(utf16string word) { - if (word.size() < _query.size()) { - return false; - } - for (auto i = std::size_t(0), size = _query.size(); i != size; ++i) { - if (word[i] != _query[i]) { - return false; - } - } - return true; -} - -bool Completer::isExactMatch(utf16string replacement) { - if (replacement.size() != _initialQuery.size() + 1) { - return false; - } - for (auto i = std::size_t(0), size = _initialQuery.size(); i != size; ++i) { - if (replacement[i] != _initialQuery[i]) { - return false; - } - } - return true; -} - -bool Completer::matchQueryTailStartingFrom(int position) { - auto charsLeftToMatch = (_querySize - position); - if (!charsLeftToMatch) { - return true; - } - - auto firstCharToMatch = *(_queryBegin + position); - auto foundWords = findWordsStartingWith(firstCharToMatch); - - for (auto word = foundWords.begin(), foundWordsEnd = word + foundWords.size(); word != foundWordsEnd; ++word) { - auto wordIndex = word - _currentItemWords.begin(); - if (auto guard = UsedWordGuard(_currentItemWordsUsedMap, wordIndex)) { - ++_currentItemWordsUsedCount; - auto equalCharsCount = findEqualCharsCount(position, word); - for (auto check = equalCharsCount; check != 0; --check) { - if (matchQueryTailStartingFrom(position + check)) { - return true; - } - } - --_currentItemWordsUsedCount; - } - } - return false; -} - -int Completer::findEqualCharsCount(int position, const utf16string *word) { - auto charsLeft = (_querySize - position); - auto wordBegin = word->data(); - auto wordSize = word->size(); - auto possibleEqualCharsCount = (charsLeft > wordSize ? wordSize : charsLeft); - for (auto equalTill = 1; equalTill != possibleEqualCharsCount; ++equalTill) { - auto wordCh = *(wordBegin + equalTill); - auto queryCh = *(_queryBegin + position + equalTill); - if (wordCh != queryCh) { - return equalTill; - } - } - return possibleEqualCharsCount; -} - -std::vector Completer::prepareResult() { - auto firstCharOfQuery = _query[0]; - std::stable_partition(_result.begin(), _result.end(), [firstCharOfQuery](Result &result) { - auto firstCharAfterColon = result.replacement->replacement[1]; - return (firstCharAfterColon == firstCharOfQuery); - }); - std::stable_partition(_result.begin(), _result.end(), [](Result &result) { - return (result.wordsUsed < 2); - }); - std::stable_partition(_result.begin(), _result.end(), [](Result &result) { - return (result.wordsUsed < 3); - }); - std::stable_partition(_result.begin(), _result.end(), [this](Result &result) { - return isExactMatch(result.replacement->replacement); - }); - - auto result = std::vector(); - result.reserve(_result.size()); - for (auto &item : _result) { - result.emplace_back(item.replacement->emoji, item.replacement->replacement, item.replacement->replacement); - } - return result; -} - -string_span Completer::findWordsStartingWith(utf16char ch) { - auto begin = std::lower_bound(_currentItemWords.begin(), _currentItemWords.end(), ch, [](utf16string word, utf16char ch) { - return word[0] < ch; - }); - auto end = std::upper_bound(_currentItemWords.begin(), _currentItemWords.end(), ch, [](utf16char ch, utf16string word) { - return ch < word[0]; - }); - return _currentItemWords.subspan(begin - _currentItemWords.begin(), end - begin); -} - -std::vector GetSuggestions(utf16string query) { - return Completer(query).resolve(); -} - -int GetSuggestionMaxLength() { - return kReplacementMaxLength; -} - -jclass jclass_Suggestion = nullptr; -jmethodID jclass_Suggestion_constructor; - -extern "C" { - -jobjectArray -Java_org_telegram_messenger_Emoji_getSuggestion(JNIEnv *env, jobject object, jstring query) { - const jchar *raw = env->GetStringChars(query, 0); - jsize len = env->GetStringLength(query); - std::vector suggestions = GetSuggestions(utf16string(raw, len)); - env->ReleaseStringChars(query, raw); - - if (suggestions.empty()) { - return nullptr; - } - - if (jclass_Suggestion == nullptr) { - jclass_Suggestion = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/messenger/EmojiSuggestion")); - jclass_Suggestion_constructor = env->GetMethodID(jclass_Suggestion, "", - "(Ljava/lang/String;Ljava/lang/String;)V"); - } - - jobjectArray result = env->NewObjectArray(suggestions.size(), jclass_Suggestion, nullptr); - size_t size = suggestions.size(); - for (size_t a = 0; a < size; a++) { - Suggestion &suggestion = suggestions[a]; - utf16string emoji = suggestion.emoji(); - utf16string label = suggestion.label(); - jstring emojiStr = env->NewString(emoji.data(), emoji.size()); - jstring labelStr = env->NewString(label.data(), label.size()); - object = env->NewObject(jclass_Suggestion, jclass_Suggestion_constructor, emojiStr, labelStr); - env->SetObjectArrayElement(result, a, object); - env->DeleteLocalRef(object); - env->DeleteLocalRef(emojiStr); - env->DeleteLocalRef(labelStr); - } - - return result; -} - -} diff --git a/TMessagesProj/jni/emoji/emoji_suggestions.h b/TMessagesProj/jni/emoji/emoji_suggestions.h deleted file mode 100755 index 3c8da9281..000000000 --- a/TMessagesProj/jni/emoji/emoji_suggestions.h +++ /dev/null @@ -1,97 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#pragma once - -#include -#include - -using small = unsigned char; -using medium = unsigned short; -using utf16char = unsigned short; - -static_assert(sizeof(utf16char) == 2, "Bad UTF-16 character size."); - -class utf16string { -public: - utf16string() = default; - utf16string(const utf16char *data, std::size_t size) : data_(data), size_(size) { - } - utf16string(const utf16string &other) = default; - utf16string &operator=(const utf16string &other) = default; - - const utf16char *data() const { - return data_; - } - std::size_t size() const { - return size_; - } - - utf16char operator[](int index) const { - return data_[index]; - } - -private: - const utf16char *data_ = nullptr; - std::size_t size_ = 0; - -}; - -inline bool operator==(utf16string a, utf16string b) { - return (a.size() == b.size()) && (!a.size() || !memcmp(a.data(), b.data(), a.size() * sizeof(utf16char))); -} - -using checksum = unsigned int; -checksum countChecksum(const void *data, std::size_t size); - -utf16string GetReplacementEmoji(utf16string replacement); - -class Suggestion { -public: - Suggestion() = default; - Suggestion(utf16string emoji, utf16string label, utf16string replacement) : emoji_(emoji), label_(label), replacement_(replacement) { - } - Suggestion(const Suggestion &other) = default; - Suggestion &operator=(const Suggestion &other) = default; - - utf16string emoji() const { - return emoji_; - } - utf16string label() const { - return label_; - } - utf16string replacement() const { - return replacement_; - } - -private: - utf16string emoji_; - utf16string label_; - utf16string replacement_; - -}; - -std::vector GetSuggestions(utf16string query); - -inline utf16string GetSuggestionEmoji(utf16string replacement) { - return GetReplacementEmoji(replacement); -} - -int GetSuggestionMaxLength(); diff --git a/TMessagesProj/jni/emoji/emoji_suggestions_data.cpp b/TMessagesProj/jni/emoji/emoji_suggestions_data.cpp deleted file mode 100755 index 414e7d289..000000000 --- a/TMessagesProj/jni/emoji/emoji_suggestions_data.cpp +++ /dev/null @@ -1,6670 +0,0 @@ -/* -WARNING! All changes made in this file will be lost! -Created from 'empty' by 'codegen_emoji' - -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#include "emoji_suggestions_data.h" - -#include - -struct ReplacementStruct { - small emojiSize; - small replacementSize; - small wordsCount; -}; - -const utf16char ReplacementData[] = { - 0xd83d, 0xde00, 0x3a, 0x67, 0x72, 0x69, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x3a, - 0x67, 0x72, 0x69, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0xd83d, 0xde03, 0x3a, 0x73, - 0x6d, 0x69, 0x6c, 0x65, 0x79, 0x3a, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0x79, - 0xd83d, 0xde04, 0x3a, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0x3a, 0x73, 0x6d, 0x69, - 0x6c, 0x65, 0xd83d, 0xde01, 0x3a, 0x67, 0x72, 0x69, 0x6e, 0x3a, 0x67, 0x72, - 0x69, 0x6e, 0xd83d, 0xde06, 0x3a, 0x73, 0x61, 0x74, 0x69, 0x73, 0x66, 0x69, - 0x65, 0x64, 0x3a, 0x73, 0x61, 0x74, 0x69, 0x73, 0x66, 0x69, 0x65, 0x64, - 0xd83d, 0xde06, 0x3a, 0x6c, 0x61, 0x75, 0x67, 0x68, 0x69, 0x6e, 0x67, 0x3a, - 0x6c, 0x61, 0x75, 0x67, 0x68, 0x69, 0x6e, 0x67, 0xd83d, 0xde05, 0x3a, 0x73, - 0x77, 0x65, 0x61, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0x3a, 0x73, - 0x6d, 0x69, 0x6c, 0x65, 0x73, 0x77, 0x65, 0x61, 0x74, 0xd83d, 0xde02, 0x3a, - 0x6a, 0x6f, 0x79, 0x3a, 0x6a, 0x6f, 0x79, 0xd83e, 0xdd23, 0x3a, 0x72, 0x6f, - 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x6e, 0x5f, 0x74, 0x68, 0x65, - 0x5f, 0x66, 0x6c, 0x6f, 0x6f, 0x72, 0x5f, 0x6c, 0x61, 0x75, 0x67, 0x68, - 0x69, 0x6e, 0x67, 0x3a, 0x66, 0x6c, 0x6f, 0x6f, 0x72, 0x6c, 0x61, 0x75, - 0x67, 0x68, 0x69, 0x6e, 0x67, 0x6f, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x69, - 0x6e, 0x67, 0x74, 0x68, 0x65, 0xd83e, 0xdd23, 0x3a, 0x72, 0x6f, 0x66, 0x6c, - 0x3a, 0x72, 0x6f, 0x66, 0x6c, 0x263a, 0xfe0f, 0x3a, 0x72, 0x65, 0x6c, 0x61, - 0x78, 0x65, 0x64, 0x3a, 0x72, 0x65, 0x6c, 0x61, 0x78, 0x65, 0x64, 0xd83d, - 0xde0a, 0x3a, 0x62, 0x6c, 0x75, 0x73, 0x68, 0x3a, 0x62, 0x6c, 0x75, 0x73, - 0x68, 0xd83d, 0xde07, 0x3a, 0x69, 0x6e, 0x6e, 0x6f, 0x63, 0x65, 0x6e, 0x74, - 0x3a, 0x69, 0x6e, 0x6e, 0x6f, 0x63, 0x65, 0x6e, 0x74, 0xd83d, 0xde42, 0x3a, - 0x73, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6c, 0x79, 0x5f, 0x73, 0x6d, 0x69, - 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, - 0x63, 0x65, 0x73, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6c, 0x79, 0x73, 0x6d, - 0x69, 0x6c, 0x69, 0x6e, 0x67, 0xd83d, 0xde42, 0x3a, 0x73, 0x6c, 0x69, 0x67, - 0x68, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0x3a, 0x73, 0x6c, 0x69, - 0x67, 0x68, 0x74, 0x73, 0x6d, 0x69, 0x6c, 0x65, 0xd83d, 0xde43, 0x3a, 0x75, - 0x70, 0x73, 0x69, 0x64, 0x65, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x5f, 0x66, - 0x61, 0x63, 0x65, 0x3a, 0x64, 0x6f, 0x77, 0x6e, 0x66, 0x61, 0x63, 0x65, - 0x75, 0x70, 0x73, 0x69, 0x64, 0x65, 0xd83d, 0xde43, 0x3a, 0x75, 0x70, 0x73, - 0x69, 0x64, 0x65, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x3a, 0x64, 0x6f, 0x77, - 0x6e, 0x75, 0x70, 0x73, 0x69, 0x64, 0x65, 0xd83d, 0xde09, 0x3a, 0x77, 0x69, - 0x6e, 0x6b, 0x3a, 0x77, 0x69, 0x6e, 0x6b, 0xd83d, 0xde0c, 0x3a, 0x72, 0x65, - 0x6c, 0x69, 0x65, 0x76, 0x65, 0x64, 0x3a, 0x72, 0x65, 0x6c, 0x69, 0x65, - 0x76, 0x65, 0x64, 0xd83d, 0xde0d, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x5f, - 0x65, 0x79, 0x65, 0x73, 0x3a, 0x65, 0x79, 0x65, 0x73, 0x68, 0x65, 0x61, - 0x72, 0x74, 0xd83d, 0xde18, 0x3a, 0x6b, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, - 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, - 0x6b, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0xd83d, 0xde17, 0x3a, 0x6b, 0x69, - 0x73, 0x73, 0x69, 0x6e, 0x67, 0x3a, 0x6b, 0x69, 0x73, 0x73, 0x69, 0x6e, - 0x67, 0xd83d, 0xde19, 0x3a, 0x6b, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, - 0x73, 0x6d, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x79, 0x65, 0x73, - 0x3a, 0x65, 0x79, 0x65, 0x73, 0x6b, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, - 0x73, 0x6d, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0xd83d, 0xde1a, 0x3a, 0x6b, 0x69, - 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, - 0x5f, 0x65, 0x79, 0x65, 0x73, 0x3a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, - 0x65, 0x79, 0x65, 0x73, 0x6b, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0xd83d, - 0xde0b, 0x3a, 0x79, 0x75, 0x6d, 0x3a, 0x79, 0x75, 0x6d, 0xd83d, 0xde1b, 0x3a, - 0x73, 0x74, 0x75, 0x63, 0x6b, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x74, 0x6f, - 0x6e, 0x67, 0x75, 0x65, 0x3a, 0x6f, 0x75, 0x74, 0x73, 0x74, 0x75, 0x63, - 0x6b, 0x74, 0x6f, 0x6e, 0x67, 0x75, 0x65, 0xd83d, 0xde1d, 0x3a, 0x73, 0x74, - 0x75, 0x63, 0x6b, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x74, 0x6f, 0x6e, 0x67, - 0x75, 0x65, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x5f, 0x65, 0x79, - 0x65, 0x73, 0x3a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x65, 0x79, 0x65, - 0x73, 0x6f, 0x75, 0x74, 0x73, 0x74, 0x75, 0x63, 0x6b, 0x74, 0x6f, 0x6e, - 0x67, 0x75, 0x65, 0xd83d, 0xde1c, 0x3a, 0x73, 0x74, 0x75, 0x63, 0x6b, 0x5f, - 0x6f, 0x75, 0x74, 0x5f, 0x74, 0x6f, 0x6e, 0x67, 0x75, 0x65, 0x5f, 0x77, - 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x79, 0x65, 0x3a, 0x65, - 0x79, 0x65, 0x6f, 0x75, 0x74, 0x73, 0x74, 0x75, 0x63, 0x6b, 0x74, 0x6f, - 0x6e, 0x67, 0x75, 0x65, 0x77, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0xd83e, - 0xdd2a, 0x3a, 0x63, 0x72, 0x61, 0x7a, 0x79, 0x5f, 0x66, 0x61, 0x63, 0x65, - 0x3a, 0x63, 0x72, 0x61, 0x7a, 0x79, 0x66, 0x61, 0x63, 0x65, 0xd83e, 0xdd28, - 0x3a, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x72, - 0x61, 0x69, 0x73, 0x65, 0x64, 0x5f, 0x65, 0x79, 0x65, 0x62, 0x72, 0x6f, - 0x77, 0x3a, 0x65, 0x79, 0x65, 0x62, 0x72, 0x6f, 0x77, 0x66, 0x61, 0x63, - 0x65, 0x72, 0x61, 0x69, 0x73, 0x65, 0x64, 0x77, 0x69, 0x74, 0x68, 0xd83e, - 0xddd0, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, - 0x6d, 0x6f, 0x6e, 0x6f, 0x63, 0x6c, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, - 0x6d, 0x6f, 0x6e, 0x6f, 0x63, 0x6c, 0x65, 0x77, 0x69, 0x74, 0x68, 0xd83e, - 0xdd13, 0x3a, 0x6e, 0x65, 0x72, 0x64, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, - 0x66, 0x61, 0x63, 0x65, 0x6e, 0x65, 0x72, 0x64, 0xd83e, 0xdd13, 0x3a, 0x6e, - 0x65, 0x72, 0x64, 0x3a, 0x6e, 0x65, 0x72, 0x64, 0xd83d, 0xde0e, 0x3a, 0x73, - 0x75, 0x6e, 0x67, 0x6c, 0x61, 0x73, 0x73, 0x65, 0x73, 0x3a, 0x73, 0x75, - 0x6e, 0x67, 0x6c, 0x61, 0x73, 0x73, 0x65, 0x73, 0xd83e, 0xdd29, 0x3a, 0x73, - 0x74, 0x61, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x6b, 0x3a, 0x73, - 0x74, 0x61, 0x72, 0x73, 0x74, 0x72, 0x75, 0x63, 0x6b, 0xd83d, 0xde0f, 0x3a, - 0x73, 0x6d, 0x69, 0x72, 0x6b, 0x3a, 0x73, 0x6d, 0x69, 0x72, 0x6b, 0xd83d, - 0xde12, 0x3a, 0x75, 0x6e, 0x61, 0x6d, 0x75, 0x73, 0x65, 0x64, 0x3a, 0x75, - 0x6e, 0x61, 0x6d, 0x75, 0x73, 0x65, 0x64, 0xd83d, 0xde1e, 0x3a, 0x64, 0x69, - 0x73, 0x61, 0x70, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x3a, 0x64, - 0x69, 0x73, 0x61, 0x70, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, 0xd83d, - 0xde14, 0x3a, 0x70, 0x65, 0x6e, 0x73, 0x69, 0x76, 0x65, 0x3a, 0x70, 0x65, - 0x6e, 0x73, 0x69, 0x76, 0x65, 0xd83d, 0xde1f, 0x3a, 0x77, 0x6f, 0x72, 0x72, - 0x69, 0x65, 0x64, 0x3a, 0x77, 0x6f, 0x72, 0x72, 0x69, 0x65, 0x64, 0xd83d, - 0xde15, 0x3a, 0x63, 0x6f, 0x6e, 0x66, 0x75, 0x73, 0x65, 0x64, 0x3a, 0x63, - 0x6f, 0x6e, 0x66, 0x75, 0x73, 0x65, 0x64, 0xd83d, 0xde41, 0x3a, 0x73, 0x6c, - 0x69, 0x67, 0x68, 0x74, 0x6c, 0x79, 0x5f, 0x66, 0x72, 0x6f, 0x77, 0x6e, - 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, - 0x65, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x6c, 0x69, - 0x67, 0x68, 0x74, 0x6c, 0x79, 0xd83d, 0xde41, 0x3a, 0x73, 0x6c, 0x69, 0x67, - 0x68, 0x74, 0x5f, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x3a, 0x66, 0x72, 0x6f, - 0x77, 0x6e, 0x73, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2639, 0xfe0f, 0x3a, 0x77, - 0x68, 0x69, 0x74, 0x65, 0x5f, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, 0x6e, - 0x67, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x66, - 0x72, 0x6f, 0x77, 0x6e, 0x69, 0x6e, 0x67, 0x77, 0x68, 0x69, 0x74, 0x65, - 0x2639, 0xfe0f, 0x3a, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, 0x6e, 0x67, 0x32, - 0x3a, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, 0x6e, 0x67, 0x32, 0xd83d, 0xde23, - 0x3a, 0x70, 0x65, 0x72, 0x73, 0x65, 0x76, 0x65, 0x72, 0x65, 0x3a, 0x70, - 0x65, 0x72, 0x73, 0x65, 0x76, 0x65, 0x72, 0x65, 0xd83d, 0xde16, 0x3a, 0x63, - 0x6f, 0x6e, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x65, 0x64, 0x3a, 0x63, 0x6f, - 0x6e, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x65, 0x64, 0xd83d, 0xde2b, 0x3a, 0x74, - 0x69, 0x72, 0x65, 0x64, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, - 0x63, 0x65, 0x74, 0x69, 0x72, 0x65, 0x64, 0xd83d, 0xde29, 0x3a, 0x77, 0x65, - 0x61, 0x72, 0x79, 0x3a, 0x77, 0x65, 0x61, 0x72, 0x79, 0xd83d, 0xde22, 0x3a, - 0x63, 0x72, 0x79, 0x3a, 0x63, 0x72, 0x79, 0xd83d, 0xde2d, 0x3a, 0x73, 0x6f, - 0x62, 0x3a, 0x73, 0x6f, 0x62, 0xd83d, 0xde24, 0x3a, 0x74, 0x72, 0x69, 0x75, - 0x6d, 0x70, 0x68, 0x3a, 0x74, 0x72, 0x69, 0x75, 0x6d, 0x70, 0x68, 0xd83d, - 0xde20, 0x3a, 0x61, 0x6e, 0x67, 0x72, 0x79, 0x3a, 0x61, 0x6e, 0x67, 0x72, - 0x79, 0xd83d, 0xde21, 0x3a, 0x72, 0x61, 0x67, 0x65, 0x3a, 0x72, 0x61, 0x67, - 0x65, 0xd83e, 0xdd2c, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x77, 0x69, 0x74, - 0x68, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x5f, 0x6f, 0x76, - 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x3a, 0x66, 0x61, 0x63, - 0x65, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x79, - 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x77, 0x69, 0x74, 0x68, 0xd83e, 0xdd2f, 0x3a, - 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x65, - 0x61, 0x64, 0x3a, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x64, 0x69, 0x6e, 0x67, - 0x68, 0x65, 0x61, 0x64, 0xd83d, 0xde33, 0x3a, 0x66, 0x6c, 0x75, 0x73, 0x68, - 0x65, 0x64, 0x3a, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x65, 0x64, 0xd83d, 0xde31, - 0x3a, 0x73, 0x63, 0x72, 0x65, 0x61, 0x6d, 0x3a, 0x73, 0x63, 0x72, 0x65, - 0x61, 0x6d, 0xd83d, 0xde28, 0x3a, 0x66, 0x65, 0x61, 0x72, 0x66, 0x75, 0x6c, - 0x3a, 0x66, 0x65, 0x61, 0x72, 0x66, 0x75, 0x6c, 0xd83d, 0xde30, 0x3a, 0x63, - 0x6f, 0x6c, 0x64, 0x5f, 0x73, 0x77, 0x65, 0x61, 0x74, 0x3a, 0x63, 0x6f, - 0x6c, 0x64, 0x73, 0x77, 0x65, 0x61, 0x74, 0xd83d, 0xde25, 0x3a, 0x64, 0x69, - 0x73, 0x61, 0x70, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x5f, 0x72, - 0x65, 0x6c, 0x69, 0x65, 0x76, 0x65, 0x64, 0x3a, 0x64, 0x69, 0x73, 0x61, - 0x70, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x72, 0x65, 0x6c, 0x69, - 0x65, 0x76, 0x65, 0x64, 0xd83d, 0xde13, 0x3a, 0x73, 0x77, 0x65, 0x61, 0x74, - 0x3a, 0x73, 0x77, 0x65, 0x61, 0x74, 0xd83e, 0xdd17, 0x3a, 0x68, 0x75, 0x67, - 0x67, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, - 0x63, 0x65, 0x68, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0xd83e, 0xdd17, 0x3a, - 0x68, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x3a, 0x68, 0x75, 0x67, 0x67, - 0x69, 0x6e, 0x67, 0xd83e, 0xdd14, 0x3a, 0x68, 0x6d, 0x6d, 0x3a, 0x68, 0x6d, - 0x6d, 0xd83e, 0xdd14, 0x3a, 0x74, 0x68, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, - 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x74, 0x68, - 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0xd83e, 0xdd14, 0x3a, 0x74, 0x68, 0x69, - 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x74, 0x68, 0x69, 0x6e, 0x6b, 0x69, - 0x6e, 0x67, 0xd83e, 0xdd2d, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x77, 0x69, - 0x74, 0x68, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x5f, 0x6f, 0x76, 0x65, 0x72, - 0x5f, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x68, - 0x61, 0x6e, 0x64, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x6f, 0x76, 0x65, 0x72, - 0x77, 0x69, 0x74, 0x68, 0xd83e, 0xdd2b, 0x3a, 0x73, 0x68, 0x75, 0x73, 0x68, - 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, - 0x65, 0x73, 0x68, 0x75, 0x73, 0x68, 0x69, 0x6e, 0x67, 0xd83e, 0xdd25, 0x3a, - 0x6c, 0x69, 0x61, 0x72, 0x3a, 0x6c, 0x69, 0x61, 0x72, 0xd83e, 0xdd25, 0x3a, - 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, - 0x61, 0x63, 0x65, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0xd83d, 0xde36, 0x3a, 0x6e, - 0x6f, 0x5f, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x3a, 0x6d, 0x6f, 0x75, 0x74, - 0x68, 0x6e, 0x6f, 0xd83d, 0xde10, 0x3a, 0x6e, 0x65, 0x75, 0x74, 0x72, 0x61, - 0x6c, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x6e, - 0x65, 0x75, 0x74, 0x72, 0x61, 0x6c, 0xd83d, 0xde11, 0x3a, 0x65, 0x78, 0x70, - 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x6c, 0x65, 0x73, 0x73, 0x3a, - 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x6c, 0x65, - 0x73, 0x73, 0xd83d, 0xde2c, 0x3a, 0x67, 0x72, 0x69, 0x6d, 0x61, 0x63, 0x69, - 0x6e, 0x67, 0x3a, 0x67, 0x72, 0x69, 0x6d, 0x61, 0x63, 0x69, 0x6e, 0x67, - 0xd83d, 0xde44, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, - 0x5f, 0x72, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x79, 0x65, - 0x73, 0x3a, 0x65, 0x79, 0x65, 0x73, 0x66, 0x61, 0x63, 0x65, 0x72, 0x6f, - 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xde44, 0x3a, - 0x72, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x79, 0x65, 0x73, - 0x3a, 0x65, 0x79, 0x65, 0x73, 0x72, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, - 0xd83d, 0xde2f, 0x3a, 0x68, 0x75, 0x73, 0x68, 0x65, 0x64, 0x3a, 0x68, 0x75, - 0x73, 0x68, 0x65, 0x64, 0xd83d, 0xde26, 0x3a, 0x66, 0x72, 0x6f, 0x77, 0x6e, - 0x69, 0x6e, 0x67, 0x3a, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, 0x6e, 0x67, - 0xd83d, 0xde27, 0x3a, 0x61, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x65, 0x64, - 0x3a, 0x61, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x65, 0x64, 0xd83d, 0xde2e, - 0x3a, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x3a, - 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x6f, 0x70, 0x65, 0x6e, 0xd83d, 0xde32, 0x3a, - 0x61, 0x73, 0x74, 0x6f, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x3a, 0x61, - 0x73, 0x74, 0x6f, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0xd83d, 0xde34, 0x3a, - 0x73, 0x6c, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x3a, 0x73, 0x6c, 0x65, - 0x65, 0x70, 0x69, 0x6e, 0x67, 0xd83e, 0xdd24, 0x3a, 0x64, 0x72, 0x6f, 0x6f, - 0x6c, 0x3a, 0x64, 0x72, 0x6f, 0x6f, 0x6c, 0xd83e, 0xdd24, 0x3a, 0x64, 0x72, - 0x6f, 0x6f, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, - 0x64, 0x72, 0x6f, 0x6f, 0x6c, 0x69, 0x6e, 0x67, 0x66, 0x61, 0x63, 0x65, - 0xd83d, 0xde2a, 0x3a, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x79, 0x3a, 0x73, 0x6c, - 0x65, 0x65, 0x70, 0x79, 0xd83d, 0xde35, 0x3a, 0x64, 0x69, 0x7a, 0x7a, 0x79, - 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x64, 0x69, 0x7a, 0x7a, 0x79, 0x66, - 0x61, 0x63, 0x65, 0xd83e, 0xdd10, 0x3a, 0x7a, 0x69, 0x70, 0x70, 0x65, 0x72, - 0x5f, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, - 0x66, 0x61, 0x63, 0x65, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x7a, 0x69, 0x70, - 0x70, 0x65, 0x72, 0xd83e, 0xdd10, 0x3a, 0x7a, 0x69, 0x70, 0x70, 0x65, 0x72, - 0x5f, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x3a, 0x6d, 0x6f, 0x75, 0x74, 0x68, - 0x7a, 0x69, 0x70, 0x70, 0x65, 0x72, 0xd83e, 0xdd22, 0x3a, 0x73, 0x69, 0x63, - 0x6b, 0x3a, 0x73, 0x69, 0x63, 0x6b, 0xd83e, 0xdd22, 0x3a, 0x6e, 0x61, 0x75, - 0x73, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, - 0x66, 0x61, 0x63, 0x65, 0x6e, 0x61, 0x75, 0x73, 0x65, 0x61, 0x74, 0x65, - 0x64, 0xd83e, 0xdd2e, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x76, 0x6f, 0x6d, - 0x69, 0x74, 0x69, 0x6e, 0x67, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x76, 0x6f, - 0x6d, 0x69, 0x74, 0x69, 0x6e, 0x67, 0xd83e, 0xdd27, 0x3a, 0x73, 0x6e, 0x65, - 0x65, 0x7a, 0x65, 0x3a, 0x73, 0x6e, 0x65, 0x65, 0x7a, 0x65, 0xd83e, 0xdd27, - 0x3a, 0x73, 0x6e, 0x65, 0x65, 0x7a, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, - 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x73, 0x6e, 0x65, 0x65, 0x7a, - 0x69, 0x6e, 0x67, 0xd83d, 0xde37, 0x3a, 0x6d, 0x61, 0x73, 0x6b, 0x3a, 0x6d, - 0x61, 0x73, 0x6b, 0xd83e, 0xdd12, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x77, - 0x69, 0x74, 0x68, 0x5f, 0x74, 0x68, 0x65, 0x72, 0x6d, 0x6f, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x6d, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x77, 0x69, 0x74, 0x68, 0xd83e, - 0xdd12, 0x3a, 0x74, 0x68, 0x65, 0x72, 0x6d, 0x6f, 0x6d, 0x65, 0x74, 0x65, - 0x72, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x74, - 0x68, 0x65, 0x72, 0x6d, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0xd83e, 0xdd15, - 0x3a, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x68, - 0x65, 0x61, 0x64, 0x5f, 0x62, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x65, 0x3a, - 0x62, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x65, 0x66, 0x61, 0x63, 0x65, 0x68, - 0x65, 0x61, 0x64, 0x77, 0x69, 0x74, 0x68, 0xd83e, 0xdd15, 0x3a, 0x68, 0x65, - 0x61, 0x64, 0x5f, 0x62, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x65, 0x3a, 0x62, - 0x61, 0x6e, 0x64, 0x61, 0x67, 0x65, 0x68, 0x65, 0x61, 0x64, 0xd83e, 0xdd11, - 0x3a, 0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x75, 0x74, 0x68, - 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x6d, 0x6f, - 0x6e, 0x65, 0x79, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0xd83e, 0xdd11, 0x3a, 0x6d, - 0x6f, 0x6e, 0x65, 0x79, 0x5f, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x3a, 0x6d, - 0x6f, 0x6e, 0x65, 0x79, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0xd83e, 0xdd20, 0x3a, - 0x66, 0x61, 0x63, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x63, 0x6f, - 0x77, 0x62, 0x6f, 0x79, 0x5f, 0x68, 0x61, 0x74, 0x3a, 0x63, 0x6f, 0x77, - 0x62, 0x6f, 0x79, 0x66, 0x61, 0x63, 0x65, 0x68, 0x61, 0x74, 0x77, 0x69, - 0x74, 0x68, 0xd83e, 0xdd20, 0x3a, 0x63, 0x6f, 0x77, 0x62, 0x6f, 0x79, 0x3a, - 0x63, 0x6f, 0x77, 0x62, 0x6f, 0x79, 0xd83d, 0xde08, 0x3a, 0x73, 0x6d, 0x69, - 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6d, 0x70, 0x3a, 0x69, 0x6d, 0x70, - 0x73, 0x6d, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0xd83d, 0xdc7f, 0x3a, 0x69, 0x6d, - 0x70, 0x3a, 0x69, 0x6d, 0x70, 0xd83d, 0xdc79, 0x3a, 0x6a, 0x61, 0x70, 0x61, - 0x6e, 0x65, 0x73, 0x65, 0x5f, 0x6f, 0x67, 0x72, 0x65, 0x3a, 0x6a, 0x61, - 0x70, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x6f, 0x67, 0x72, 0x65, 0xd83d, 0xdc7a, - 0x3a, 0x6a, 0x61, 0x70, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x5f, 0x67, 0x6f, - 0x62, 0x6c, 0x69, 0x6e, 0x3a, 0x67, 0x6f, 0x62, 0x6c, 0x69, 0x6e, 0x6a, - 0x61, 0x70, 0x61, 0x6e, 0x65, 0x73, 0x65, 0xd83e, 0xdd21, 0x3a, 0x63, 0x6c, - 0x6f, 0x77, 0x6e, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x63, 0x6c, 0x6f, - 0x77, 0x6e, 0x66, 0x61, 0x63, 0x65, 0xd83e, 0xdd21, 0x3a, 0x63, 0x6c, 0x6f, - 0x77, 0x6e, 0x3a, 0x63, 0x6c, 0x6f, 0x77, 0x6e, 0xd83d, 0xdca9, 0x3a, 0x70, - 0x6f, 0x6f, 0x3a, 0x70, 0x6f, 0x6f, 0xd83d, 0xdca9, 0x3a, 0x68, 0x61, 0x6e, - 0x6b, 0x65, 0x79, 0x3a, 0x68, 0x61, 0x6e, 0x6b, 0x65, 0x79, 0xd83d, 0xdca9, - 0x3a, 0x73, 0x68, 0x69, 0x74, 0x3a, 0x73, 0x68, 0x69, 0x74, 0xd83d, 0xdca9, - 0x3a, 0x70, 0x6f, 0x6f, 0x70, 0x3a, 0x70, 0x6f, 0x6f, 0x70, 0xd83d, 0xdc7b, - 0x3a, 0x67, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x67, 0x68, 0x6f, 0x73, 0x74, - 0xd83d, 0xdc80, 0x3a, 0x73, 0x6b, 0x65, 0x6c, 0x65, 0x74, 0x6f, 0x6e, 0x3a, - 0x73, 0x6b, 0x65, 0x6c, 0x65, 0x74, 0x6f, 0x6e, 0xd83d, 0xdc80, 0x3a, 0x73, - 0x6b, 0x75, 0x6c, 0x6c, 0x3a, 0x73, 0x6b, 0x75, 0x6c, 0x6c, 0x2620, 0xfe0f, - 0x3a, 0x73, 0x6b, 0x75, 0x6c, 0x6c, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x63, - 0x72, 0x6f, 0x73, 0x73, 0x62, 0x6f, 0x6e, 0x65, 0x73, 0x3a, 0x61, 0x6e, - 0x64, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x62, 0x6f, 0x6e, 0x65, 0x73, 0x73, - 0x6b, 0x75, 0x6c, 0x6c, 0x2620, 0xfe0f, 0x3a, 0x73, 0x6b, 0x75, 0x6c, 0x6c, - 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x62, 0x6f, 0x6e, 0x65, 0x73, 0x3a, - 0x63, 0x72, 0x6f, 0x73, 0x73, 0x62, 0x6f, 0x6e, 0x65, 0x73, 0x73, 0x6b, - 0x75, 0x6c, 0x6c, 0xd83d, 0xdc7d, 0x3a, 0x61, 0x6c, 0x69, 0x65, 0x6e, 0x3a, - 0x61, 0x6c, 0x69, 0x65, 0x6e, 0xd83d, 0xdc7e, 0x3a, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x64, 0x65, 0x72, 0x3a, 0x69, 0x6e, - 0x76, 0x61, 0x64, 0x65, 0x72, 0x73, 0x70, 0x61, 0x63, 0x65, 0xd83e, 0xdd16, - 0x3a, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, - 0x66, 0x61, 0x63, 0x65, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0xd83e, 0xdd16, 0x3a, - 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x3a, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0xd83c, - 0xdf83, 0x3a, 0x6a, 0x61, 0x63, 0x6b, 0x5f, 0x6f, 0x5f, 0x6c, 0x61, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x3a, 0x6a, 0x61, 0x63, 0x6b, 0x6c, 0x61, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x6f, 0xd83d, 0xde3a, 0x3a, 0x73, 0x6d, 0x69, 0x6c, - 0x65, 0x79, 0x5f, 0x63, 0x61, 0x74, 0x3a, 0x63, 0x61, 0x74, 0x73, 0x6d, - 0x69, 0x6c, 0x65, 0x79, 0xd83d, 0xde38, 0x3a, 0x73, 0x6d, 0x69, 0x6c, 0x65, - 0x5f, 0x63, 0x61, 0x74, 0x3a, 0x63, 0x61, 0x74, 0x73, 0x6d, 0x69, 0x6c, - 0x65, 0xd83d, 0xde39, 0x3a, 0x6a, 0x6f, 0x79, 0x5f, 0x63, 0x61, 0x74, 0x3a, - 0x63, 0x61, 0x74, 0x6a, 0x6f, 0x79, 0xd83d, 0xde3b, 0x3a, 0x68, 0x65, 0x61, - 0x72, 0x74, 0x5f, 0x65, 0x79, 0x65, 0x73, 0x5f, 0x63, 0x61, 0x74, 0x3a, - 0x63, 0x61, 0x74, 0x65, 0x79, 0x65, 0x73, 0x68, 0x65, 0x61, 0x72, 0x74, - 0xd83d, 0xde3c, 0x3a, 0x73, 0x6d, 0x69, 0x72, 0x6b, 0x5f, 0x63, 0x61, 0x74, - 0x3a, 0x63, 0x61, 0x74, 0x73, 0x6d, 0x69, 0x72, 0x6b, 0xd83d, 0xde3d, 0x3a, - 0x6b, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x61, 0x74, 0x3a, - 0x63, 0x61, 0x74, 0x6b, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0xd83d, 0xde40, - 0x3a, 0x73, 0x63, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x63, 0x61, 0x74, 0x3a, - 0x63, 0x61, 0x74, 0x73, 0x63, 0x72, 0x65, 0x61, 0x6d, 0xd83d, 0xde3f, 0x3a, - 0x63, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x61, 0x74, 0x5f, 0x66, - 0x61, 0x63, 0x65, 0x3a, 0x63, 0x61, 0x74, 0x63, 0x72, 0x79, 0x69, 0x6e, - 0x67, 0x66, 0x61, 0x63, 0x65, 0xd83d, 0xde3e, 0x3a, 0x70, 0x6f, 0x75, 0x74, - 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x61, 0x74, 0x3a, 0x63, 0x61, 0x74, 0x70, - 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0xd83e, 0xdd32, 0x3a, 0x70, 0x61, 0x6c, - 0x6d, 0x73, 0x5f, 0x75, 0x70, 0x5f, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, - 0x65, 0x72, 0x3a, 0x70, 0x61, 0x6c, 0x6d, 0x73, 0x74, 0x6f, 0x67, 0x65, - 0x74, 0x68, 0x65, 0x72, 0x75, 0x70, 0xd83d, 0xdc50, 0x3a, 0x6f, 0x70, 0x65, - 0x6e, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x3a, 0x68, 0x61, 0x6e, 0x64, - 0x73, 0x6f, 0x70, 0x65, 0x6e, 0xd83d, 0xde4c, 0x3a, 0x72, 0x61, 0x69, 0x73, - 0x65, 0x64, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x3a, 0x68, 0x61, 0x6e, - 0x64, 0x73, 0x72, 0x61, 0x69, 0x73, 0x65, 0x64, 0xd83d, 0xdc4f, 0x3a, 0x63, - 0x6c, 0x61, 0x70, 0x3a, 0x63, 0x6c, 0x61, 0x70, 0xd83e, 0xdd1d, 0x3a, 0x73, - 0x68, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x73, - 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x73, 0x68, 0x61, 0x6b, 0x69, 0x6e, - 0x67, 0xd83e, 0xdd1d, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, - 0x65, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0xd83d, - 0xdc4d, 0x3a, 0x6c, 0x69, 0x6b, 0x65, 0x3a, 0x6c, 0x69, 0x6b, 0x65, 0xd83d, - 0xdc4d, 0x3a, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x75, 0x70, 0x3a, 0x74, 0x68, - 0x75, 0x6d, 0x62, 0x75, 0x70, 0xd83d, 0xdc4d, 0x3a, 0x2b, 0x31, 0x3a, 0x2b, - 0x31, 0xd83d, 0xdc4d, 0x3a, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x73, 0x75, 0x70, - 0x3a, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x73, 0x75, 0x70, 0xd83d, 0xdc4e, 0x3a, - 0x64, 0x69, 0x73, 0x6c, 0x69, 0x6b, 0x65, 0x3a, 0x64, 0x69, 0x73, 0x6c, - 0x69, 0x6b, 0x65, 0xd83d, 0xdc4e, 0x3a, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x64, - 0x6f, 0x77, 0x6e, 0x3a, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x64, 0x6f, 0x77, - 0x6e, 0xd83d, 0xdc4e, 0x3a, 0x2d, 0x31, 0x3a, 0x2d, 0x31, 0xd83d, 0xdc4e, 0x3a, - 0x74, 0x68, 0x75, 0x6d, 0x62, 0x73, 0x64, 0x6f, 0x77, 0x6e, 0x3a, 0x74, - 0x68, 0x75, 0x6d, 0x62, 0x73, 0x64, 0x6f, 0x77, 0x6e, 0xd83d, 0xdc4a, 0x3a, - 0x70, 0x75, 0x6e, 0x63, 0x68, 0x3a, 0x70, 0x75, 0x6e, 0x63, 0x68, 0x270a, - 0x3a, 0x66, 0x69, 0x73, 0x74, 0x3a, 0x66, 0x69, 0x73, 0x74, 0xd83e, 0xdd1b, - 0x3a, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x66, 0x69, 0x73, 0x74, 0x3a, 0x66, - 0x69, 0x73, 0x74, 0x6c, 0x65, 0x66, 0x74, 0xd83e, 0xdd1b, 0x3a, 0x6c, 0x65, - 0x66, 0x74, 0x5f, 0x66, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, - 0x73, 0x74, 0x3a, 0x66, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x66, 0x69, 0x73, - 0x74, 0x6c, 0x65, 0x66, 0x74, 0xd83e, 0xdd1c, 0x3a, 0x72, 0x69, 0x67, 0x68, - 0x74, 0x5f, 0x66, 0x69, 0x73, 0x74, 0x3a, 0x66, 0x69, 0x73, 0x74, 0x72, - 0x69, 0x67, 0x68, 0x74, 0xd83e, 0xdd1c, 0x3a, 0x72, 0x69, 0x67, 0x68, 0x74, - 0x5f, 0x66, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x69, 0x73, 0x74, - 0x3a, 0x66, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x66, 0x69, 0x73, 0x74, 0x72, - 0x69, 0x67, 0x68, 0x74, 0xd83e, 0xdd1e, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x5f, - 0x77, 0x69, 0x74, 0x68, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x61, - 0x6e, 0x64, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x5f, 0x66, 0x69, - 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x65, 0x64, - 0x3a, 0x61, 0x6e, 0x64, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x65, 0x64, 0x66, - 0x69, 0x6e, 0x67, 0x65, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x69, 0x74, 0x68, - 0xd83e, 0xdd1e, 0x3a, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x5f, 0x63, - 0x72, 0x6f, 0x73, 0x73, 0x65, 0x64, 0x3a, 0x63, 0x72, 0x6f, 0x73, 0x73, - 0x65, 0x64, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x270c, 0xfe0f, 0x3a, - 0x76, 0x3a, 0x76, 0xd83e, 0xdd1f, 0x3a, 0x6c, 0x6f, 0x76, 0x65, 0x5f, 0x79, - 0x6f, 0x75, 0x5f, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x65, 0x3a, 0x67, - 0x65, 0x73, 0x74, 0x75, 0x72, 0x65, 0x6c, 0x6f, 0x76, 0x65, 0x79, 0x6f, - 0x75, 0xd83e, 0xdd18, 0x3a, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x6f, 0x66, 0x5f, - 0x74, 0x68, 0x65, 0x5f, 0x68, 0x6f, 0x72, 0x6e, 0x73, 0x3a, 0x68, 0x6f, - 0x72, 0x6e, 0x73, 0x6f, 0x66, 0x73, 0x69, 0x67, 0x6e, 0x74, 0x68, 0x65, - 0xd83e, 0xdd18, 0x3a, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x3a, 0x6d, 0x65, 0x74, - 0x61, 0x6c, 0xd83d, 0xdc4c, 0x3a, 0x6f, 0x6b, 0x5f, 0x68, 0x61, 0x6e, 0x64, - 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x6f, 0x6b, 0xd83d, 0xdc48, 0x3a, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x5f, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x6c, 0x65, 0x66, - 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0xd83d, 0xdc49, 0x3a, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x5f, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x72, 0x69, 0x67, 0x68, 0x74, 0xd83d, 0xdc46, 0x3a, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x5f, 0x75, 0x70, 0x5f, 0x32, 0x3a, 0x32, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x75, 0x70, 0xd83d, 0xdc47, 0x3a, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x3a, 0x64, 0x6f, 0x77, 0x6e, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x261d, 0xfe0f, 0x3a, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x5f, 0x75, 0x70, 0x3a, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x75, 0x70, 0x270b, - 0x3a, 0x72, 0x61, 0x69, 0x73, 0x65, 0x64, 0x5f, 0x68, 0x61, 0x6e, 0x64, - 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x72, 0x61, 0x69, 0x73, 0x65, 0x64, 0xd83e, - 0xdd1a, 0x3a, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x6f, 0x66, 0x5f, 0x68, 0x61, - 0x6e, 0x64, 0x3a, 0x62, 0x61, 0x63, 0x6b, 0x68, 0x61, 0x6e, 0x64, 0x6f, - 0x66, 0xd83e, 0xdd1a, 0x3a, 0x72, 0x61, 0x69, 0x73, 0x65, 0x64, 0x5f, 0x62, - 0x61, 0x63, 0x6b, 0x5f, 0x6f, 0x66, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x3a, - 0x62, 0x61, 0x63, 0x6b, 0x68, 0x61, 0x6e, 0x64, 0x6f, 0x66, 0x72, 0x61, - 0x69, 0x73, 0x65, 0x64, 0xd83d, 0xdd90, 0x3a, 0x72, 0x61, 0x69, 0x73, 0x65, - 0x64, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, - 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x5f, 0x73, 0x70, 0x6c, 0x61, - 0x79, 0x65, 0x64, 0x3a, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x68, - 0x61, 0x6e, 0x64, 0x72, 0x61, 0x69, 0x73, 0x65, 0x64, 0x73, 0x70, 0x6c, - 0x61, 0x79, 0x65, 0x64, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdd90, 0x3a, 0x68, - 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x64, 0x3a, - 0x68, 0x61, 0x6e, 0x64, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x64, 0xd83d, - 0xdd96, 0x3a, 0x72, 0x61, 0x69, 0x73, 0x65, 0x64, 0x5f, 0x68, 0x61, 0x6e, - 0x64, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x5f, - 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x5f, 0x6d, 0x69, 0x64, 0x64, - 0x6c, 0x65, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x72, 0x69, 0x6e, 0x67, 0x5f, - 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x3a, 0x61, 0x6e, 0x64, 0x62, - 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, - 0x73, 0x68, 0x61, 0x6e, 0x64, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x70, - 0x61, 0x72, 0x74, 0x72, 0x61, 0x69, 0x73, 0x65, 0x64, 0x72, 0x69, 0x6e, - 0x67, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdd96, 0x3a, 0x76, 0x75, 0x6c, 0x63, - 0x61, 0x6e, 0x3a, 0x76, 0x75, 0x6c, 0x63, 0x61, 0x6e, 0xd83d, 0xdc4b, 0x3a, - 0x77, 0x61, 0x76, 0x65, 0x3a, 0x77, 0x61, 0x76, 0x65, 0xd83e, 0xdd19, 0x3a, - 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x65, 0x5f, 0x68, 0x61, 0x6e, 0x64, - 0x3a, 0x63, 0x61, 0x6c, 0x6c, 0x68, 0x61, 0x6e, 0x64, 0x6d, 0x65, 0xd83e, - 0xdd19, 0x3a, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x65, 0x3a, 0x63, 0x61, - 0x6c, 0x6c, 0x6d, 0x65, 0xd83d, 0xdcaa, 0x3a, 0x6d, 0x75, 0x73, 0x63, 0x6c, - 0x65, 0x3a, 0x6d, 0x75, 0x73, 0x63, 0x6c, 0x65, 0xd83d, 0xdd95, 0x3a, 0x72, - 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x64, 0x5f, 0x68, 0x61, 0x6e, 0x64, - 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, - 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x65, 0x78, 0x74, 0x65, - 0x6e, 0x64, 0x65, 0x64, 0x3a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, - 0x64, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x6d, - 0x69, 0x64, 0x64, 0x6c, 0x65, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, - 0x64, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdd95, 0x3a, 0x6d, 0x69, 0x64, 0x64, - 0x6c, 0x65, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x3a, 0x66, 0x69, - 0x6e, 0x67, 0x65, 0x72, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x270d, 0xfe0f, - 0x3a, 0x77, 0x72, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x6e, - 0x64, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x77, 0x72, 0x69, 0x74, 0x69, 0x6e, - 0x67, 0xd83d, 0xde4f, 0x3a, 0x70, 0x72, 0x61, 0x79, 0x3a, 0x70, 0x72, 0x61, - 0x79, 0xd83d, 0xdc84, 0x3a, 0x6c, 0x69, 0x70, 0x73, 0x74, 0x69, 0x63, 0x6b, - 0x3a, 0x6c, 0x69, 0x70, 0x73, 0x74, 0x69, 0x63, 0x6b, 0xd83d, 0xdc8b, 0x3a, - 0x6b, 0x69, 0x73, 0x73, 0x3a, 0x6b, 0x69, 0x73, 0x73, 0xd83d, 0xdc44, 0x3a, - 0x6c, 0x69, 0x70, 0x73, 0x3a, 0x6c, 0x69, 0x70, 0x73, 0xd83d, 0xdc45, 0x3a, - 0x74, 0x6f, 0x6e, 0x67, 0x75, 0x65, 0x3a, 0x74, 0x6f, 0x6e, 0x67, 0x75, - 0x65, 0xd83d, 0xdc42, 0x3a, 0x65, 0x61, 0x72, 0x3a, 0x65, 0x61, 0x72, 0xd83d, - 0xdc43, 0x3a, 0x6e, 0x6f, 0x73, 0x65, 0x3a, 0x6e, 0x6f, 0x73, 0x65, 0xd83d, - 0xdc63, 0x3a, 0x66, 0x6f, 0x6f, 0x74, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, - 0x3a, 0x66, 0x6f, 0x6f, 0x74, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0xd83d, - 0xdc41, 0x3a, 0x65, 0x79, 0x65, 0x3a, 0x65, 0x79, 0x65, 0xd83d, 0xdc40, 0x3a, - 0x65, 0x79, 0x65, 0x73, 0x3a, 0x65, 0x79, 0x65, 0x73, 0xd83e, 0xdde0, 0x3a, - 0x62, 0x72, 0x61, 0x69, 0x6e, 0x3a, 0x62, 0x72, 0x61, 0x69, 0x6e, 0xd83d, - 0xdde3, 0x3a, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x5f, 0x68, - 0x65, 0x61, 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x6c, 0x68, 0x6f, - 0x75, 0x65, 0x74, 0x74, 0x65, 0x3a, 0x68, 0x65, 0x61, 0x64, 0x69, 0x6e, - 0x73, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x70, - 0x65, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0xd83d, 0xdde3, 0x3a, 0x73, 0x70, 0x65, - 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x3a, 0x68, - 0x65, 0x61, 0x64, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0xd83d, - 0xdc64, 0x3a, 0x62, 0x75, 0x73, 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x69, - 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x3a, 0x62, 0x75, 0x73, - 0x74, 0x69, 0x6e, 0x73, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, - 0x65, 0xd83d, 0xdc65, 0x3a, 0x62, 0x75, 0x73, 0x74, 0x73, 0x5f, 0x69, 0x6e, - 0x5f, 0x73, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x3a, - 0x62, 0x75, 0x73, 0x74, 0x73, 0x69, 0x6e, 0x73, 0x69, 0x6c, 0x68, 0x6f, - 0x75, 0x65, 0x74, 0x74, 0x65, 0xd83d, 0xdc76, 0x3a, 0x62, 0x61, 0x62, 0x79, - 0x3a, 0x62, 0x61, 0x62, 0x79, 0xd83d, 0xdc67, 0x3a, 0x67, 0x69, 0x72, 0x6c, - 0x3a, 0x67, 0x69, 0x72, 0x6c, 0xd83e, 0xddd2, 0x3a, 0x63, 0x68, 0x69, 0x6c, - 0x64, 0x3a, 0x63, 0x68, 0x69, 0x6c, 0x64, 0xd83d, 0xdc66, 0x3a, 0x62, 0x6f, - 0x79, 0x3a, 0x62, 0x6f, 0x79, 0xd83d, 0xdc69, 0x3a, 0x77, 0x6f, 0x6d, 0x61, - 0x6e, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83e, 0xddd1, 0x3a, 0x61, 0x64, - 0x75, 0x6c, 0x74, 0x3a, 0x61, 0x64, 0x75, 0x6c, 0x74, 0xd83d, 0xdc68, 0x3a, - 0x6d, 0x61, 0x6e, 0x3a, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc71, 0x200d, 0x2640, 0xfe0f, - 0x3a, 0x62, 0x6c, 0x6f, 0x6e, 0x64, 0x2d, 0x68, 0x61, 0x69, 0x72, 0x65, - 0x64, 0x5f, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x3a, 0x62, 0x6c, 0x6f, 0x6e, - 0x64, 0x68, 0x61, 0x69, 0x72, 0x65, 0x64, 0x77, 0x6f, 0x6d, 0x61, 0x6e, - 0xd83d, 0xdc71, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x62, 0x6c, 0x6f, 0x6e, 0x64, 0x2d, - 0x68, 0x61, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x6d, 0x61, 0x6e, 0x3a, 0x62, - 0x6c, 0x6f, 0x6e, 0x64, 0x68, 0x61, 0x69, 0x72, 0x65, 0x64, 0x6d, 0x61, - 0x6e, 0xd83d, 0xdc71, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, - 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x62, 0x6c, 0x6f, 0x6e, 0x64, - 0x5f, 0x68, 0x61, 0x69, 0x72, 0x3a, 0x62, 0x6c, 0x6f, 0x6e, 0x64, 0x68, - 0x61, 0x69, 0x72, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x77, 0x69, 0x74, - 0x68, 0xd83d, 0xdc71, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x62, 0x6c, 0x6f, 0x6e, 0x64, - 0x5f, 0x68, 0x61, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x73, - 0x6f, 0x6e, 0x3a, 0x62, 0x6c, 0x6f, 0x6e, 0x64, 0x68, 0x61, 0x69, 0x72, - 0x65, 0x64, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83e, 0xddd4, 0x3a, 0x62, - 0x65, 0x61, 0x72, 0x64, 0x65, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x73, 0x6f, - 0x6e, 0x3a, 0x62, 0x65, 0x61, 0x72, 0x64, 0x65, 0x64, 0x70, 0x65, 0x72, - 0x73, 0x6f, 0x6e, 0xd83d, 0xdc75, 0x3a, 0x67, 0x72, 0x61, 0x6e, 0x64, 0x6d, - 0x61, 0x3a, 0x67, 0x72, 0x61, 0x6e, 0x64, 0x6d, 0x61, 0xd83d, 0xdc75, 0x3a, - 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x3a, - 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83e, 0xddd3, - 0x3a, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x75, 0x6c, 0x74, - 0x3a, 0x61, 0x64, 0x75, 0x6c, 0x74, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0xd83d, - 0xdc74, 0x3a, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x61, 0x6e, 0x3a, - 0x6d, 0x61, 0x6e, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0xd83d, 0xdc72, 0x3a, 0x6d, - 0x61, 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x67, 0x75, 0x61, 0x5f, - 0x70, 0x69, 0x5f, 0x6d, 0x61, 0x6f, 0x3a, 0x67, 0x75, 0x61, 0x6d, 0x61, - 0x6e, 0x6d, 0x61, 0x6f, 0x70, 0x69, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdc72, - 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x63, 0x68, - 0x69, 0x6e, 0x65, 0x73, 0x65, 0x5f, 0x63, 0x61, 0x70, 0x3a, 0x63, 0x61, - 0x70, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x77, - 0x69, 0x74, 0x68, 0xd83d, 0xdc73, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0x5f, 0x77, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x74, - 0x75, 0x72, 0x62, 0x61, 0x6e, 0x3a, 0x74, 0x75, 0x72, 0x62, 0x61, 0x6e, - 0x77, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, - 0xd83d, 0xdc73, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x77, 0x65, - 0x61, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x75, 0x72, 0x62, 0x61, 0x6e, - 0x3a, 0x6d, 0x61, 0x6e, 0x74, 0x75, 0x72, 0x62, 0x61, 0x6e, 0x77, 0x65, - 0x61, 0x72, 0x69, 0x6e, 0x67, 0xd83d, 0xdc73, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, - 0x61, 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x74, 0x75, 0x72, 0x62, - 0x61, 0x6e, 0x3a, 0x6d, 0x61, 0x6e, 0x74, 0x75, 0x72, 0x62, 0x61, 0x6e, - 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdc73, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, - 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x77, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, - 0x5f, 0x74, 0x75, 0x72, 0x62, 0x61, 0x6e, 0x3a, 0x70, 0x65, 0x72, 0x73, - 0x6f, 0x6e, 0x74, 0x75, 0x72, 0x62, 0x61, 0x6e, 0x77, 0x65, 0x61, 0x72, - 0x69, 0x6e, 0x67, 0xd83e, 0xddd5, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, - 0x77, 0x69, 0x74, 0x68, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, - 0x72, 0x66, 0x3a, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x72, 0x66, - 0x77, 0x69, 0x74, 0x68, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc6e, 0x200d, - 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x65, 0x5f, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x72, 0x3a, - 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x72, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x65, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc6e, 0x200d, 0x2642, 0xfe0f, 0x3a, - 0x6d, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x65, 0x5f, 0x6f, - 0x66, 0x66, 0x69, 0x63, 0x65, 0x72, 0x3a, 0x6d, 0x61, 0x6e, 0x6f, 0x66, - 0x66, 0x69, 0x63, 0x65, 0x72, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x65, 0xd83d, - 0xdc6e, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x63, 0x6f, 0x70, 0x3a, 0x63, 0x6f, 0x70, - 0xd83d, 0xdc6e, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x65, - 0x5f, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x72, 0x3a, 0x6f, 0x66, 0x66, - 0x69, 0x63, 0x65, 0x72, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x65, 0xd83d, 0xdc77, - 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x63, 0x6f, - 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x77, - 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x3a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, - 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x77, - 0x6f, 0x72, 0x6b, 0x65, 0x72, 0xd83d, 0xdc77, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, - 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x3a, 0x63, - 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x6d, - 0x61, 0x6e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0xd83d, 0xdc77, 0x200d, 0x2642, - 0xfe0f, 0x3a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x3a, 0x63, 0x6f, - 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x77, 0x6f, - 0x72, 0x6b, 0x65, 0x72, 0xd83d, 0xdc82, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, - 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x75, 0x61, 0x72, 0x64, 0x3a, 0x67, 0x75, - 0x61, 0x72, 0x64, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc82, 0x200d, 0x2642, - 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x75, 0x61, 0x72, 0x64, 0x3a, - 0x67, 0x75, 0x61, 0x72, 0x64, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc82, 0x200d, 0x2642, - 0xfe0f, 0x3a, 0x67, 0x75, 0x61, 0x72, 0x64, 0x73, 0x6d, 0x61, 0x6e, 0x3a, - 0x67, 0x75, 0x61, 0x72, 0x64, 0x73, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc82, 0x200d, - 0x2642, 0xfe0f, 0x3a, 0x67, 0x75, 0x61, 0x72, 0x64, 0x3a, 0x67, 0x75, 0x61, - 0x72, 0x64, 0xd83d, 0xdd75, 0xfe0f, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, - 0x3a, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x77, 0x6f, - 0x6d, 0x61, 0x6e, 0xd83d, 0xdd75, 0xfe0f, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, - 0x6e, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x3a, - 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x6d, 0x61, 0x6e, - 0xd83d, 0xdd75, 0xfe0f, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x73, 0x6c, 0x65, 0x75, 0x74, - 0x68, 0x5f, 0x6f, 0x72, 0x5f, 0x73, 0x70, 0x79, 0x3a, 0x6f, 0x72, 0x73, - 0x6c, 0x65, 0x75, 0x74, 0x68, 0x73, 0x70, 0x79, 0xd83d, 0xdd75, 0xfe0f, 0x200d, - 0x2642, 0xfe0f, 0x3a, 0x73, 0x70, 0x79, 0x3a, 0x73, 0x70, 0x79, 0xd83d, 0xdd75, - 0xfe0f, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, - 0x76, 0x65, 0x3a, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, - 0xd83d, 0xdc69, 0x200d, 0x2695, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, - 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, - 0x72, 0x3a, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x77, 0x6f, 0x6d, 0x61, - 0x6e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0xd83d, 0xdc68, 0x200d, 0x2695, 0xfe0f, - 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, - 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x3a, 0x68, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x6d, 0x61, 0x6e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0xd83d, 0xdc69, - 0x200d, 0xd83c, 0xdf3e, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x66, 0x61, - 0x72, 0x6d, 0x65, 0x72, 0x3a, 0x66, 0x61, 0x72, 0x6d, 0x65, 0x72, 0x77, - 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83c, 0xdf3e, 0x3a, 0x6d, 0x61, - 0x6e, 0x5f, 0x66, 0x61, 0x72, 0x6d, 0x65, 0x72, 0x3a, 0x66, 0x61, 0x72, - 0x6d, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, 0xd83c, 0xdf73, 0x3a, - 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x6f, 0x6b, 0x3a, 0x63, - 0x6f, 0x6f, 0x6b, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83c, - 0xdf73, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x6f, 0x6b, 0x3a, 0x63, - 0x6f, 0x6f, 0x6b, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, 0xd83c, 0xdf93, 0x3a, - 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, - 0x74, 0x3a, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83c, 0xdf93, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, - 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x3a, 0x6d, 0x61, 0x6e, 0x73, - 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0xd83d, 0xdc69, 0x200d, 0xd83c, 0xdfa4, 0x3a, - 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x73, 0x69, 0x6e, 0x67, 0x65, 0x72, - 0x3a, 0x73, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x77, 0x6f, 0x6d, 0x61, 0x6e, - 0xd83d, 0xdc68, 0x200d, 0xd83c, 0xdfa4, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x73, 0x69, - 0x6e, 0x67, 0x65, 0x72, 0x3a, 0x6d, 0x61, 0x6e, 0x73, 0x69, 0x6e, 0x67, - 0x65, 0x72, 0xd83d, 0xdc69, 0x200d, 0xd83c, 0xdfeb, 0x3a, 0x77, 0x6f, 0x6d, 0x61, - 0x6e, 0x5f, 0x74, 0x65, 0x61, 0x63, 0x68, 0x65, 0x72, 0x3a, 0x74, 0x65, - 0x61, 0x63, 0x68, 0x65, 0x72, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, - 0x200d, 0xd83c, 0xdfeb, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x74, 0x65, 0x61, 0x63, - 0x68, 0x65, 0x72, 0x3a, 0x6d, 0x61, 0x6e, 0x74, 0x65, 0x61, 0x63, 0x68, - 0x65, 0x72, 0xd83d, 0xdc69, 0x200d, 0xd83c, 0xdfed, 0x3a, 0x77, 0x6f, 0x6d, 0x61, - 0x6e, 0x5f, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x77, 0x6f, - 0x72, 0x6b, 0x65, 0x72, 0x3a, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, - 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0xd83d, - 0xdc68, 0x200d, 0xd83c, 0xdfed, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x66, 0x61, 0x63, - 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x3a, - 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x6d, 0x61, 0x6e, 0x77, 0x6f, - 0x72, 0x6b, 0x65, 0x72, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdcbb, 0x3a, 0x77, 0x6f, - 0x6d, 0x61, 0x6e, 0x5f, 0x74, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, - 0x67, 0x69, 0x73, 0x74, 0x3a, 0x74, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, - 0x6f, 0x67, 0x69, 0x73, 0x74, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, - 0x200d, 0xd83d, 0xdcbb, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x74, 0x65, 0x63, 0x68, - 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x73, 0x74, 0x3a, 0x6d, 0x61, 0x6e, - 0x74, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x69, 0x73, 0x74, - 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdcbc, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, - 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, - 0x72, 0x3a, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x77, 0x6f, 0x6d, 0x61, - 0x6e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdcbc, - 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x5f, - 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x3a, 0x6d, 0x61, 0x6e, 0x6f, 0x66, - 0x66, 0x69, 0x63, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0xd83d, 0xdc69, - 0x200d, 0xd83d, 0xdd27, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x6d, 0x65, - 0x63, 0x68, 0x61, 0x6e, 0x69, 0x63, 0x3a, 0x6d, 0x65, 0x63, 0x68, 0x61, - 0x6e, 0x69, 0x63, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83d, - 0xdd27, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, - 0x69, 0x63, 0x3a, 0x6d, 0x61, 0x6e, 0x6d, 0x65, 0x63, 0x68, 0x61, 0x6e, - 0x69, 0x63, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdd2c, 0x3a, 0x77, 0x6f, 0x6d, 0x61, - 0x6e, 0x5f, 0x73, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x73, 0x74, 0x3a, - 0x73, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x73, 0x74, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdd2c, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, - 0x73, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x73, 0x74, 0x3a, 0x6d, 0x61, - 0x6e, 0x73, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x73, 0x74, 0xd83d, 0xdc69, - 0x200d, 0xd83c, 0xdfa8, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x61, 0x72, - 0x74, 0x69, 0x73, 0x74, 0x3a, 0x61, 0x72, 0x74, 0x69, 0x73, 0x74, 0x77, - 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83c, 0xdfa8, 0x3a, 0x6d, 0x61, - 0x6e, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x73, 0x74, 0x3a, 0x61, 0x72, 0x74, - 0x69, 0x73, 0x74, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xde92, 0x3a, - 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x66, 0x69, 0x72, 0x65, 0x66, 0x69, - 0x67, 0x68, 0x74, 0x65, 0x72, 0x3a, 0x66, 0x69, 0x72, 0x65, 0x66, 0x69, - 0x67, 0x68, 0x74, 0x65, 0x72, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, - 0x200d, 0xd83d, 0xde92, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x66, 0x69, 0x72, 0x65, - 0x66, 0x69, 0x67, 0x68, 0x74, 0x65, 0x72, 0x3a, 0x66, 0x69, 0x72, 0x65, - 0x66, 0x69, 0x67, 0x68, 0x74, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, - 0x200d, 0x2708, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x70, 0x69, - 0x6c, 0x6f, 0x74, 0x3a, 0x70, 0x69, 0x6c, 0x6f, 0x74, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0x2708, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, - 0x70, 0x69, 0x6c, 0x6f, 0x74, 0x3a, 0x6d, 0x61, 0x6e, 0x70, 0x69, 0x6c, - 0x6f, 0x74, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xde80, 0x3a, 0x77, 0x6f, 0x6d, 0x61, - 0x6e, 0x5f, 0x61, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x61, 0x75, 0x74, 0x3a, - 0x61, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x61, 0x75, 0x74, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xde80, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, - 0x61, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x61, 0x75, 0x74, 0x3a, 0x61, 0x73, - 0x74, 0x72, 0x6f, 0x6e, 0x61, 0x75, 0x74, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, - 0x200d, 0x2696, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x6a, 0x75, - 0x64, 0x67, 0x65, 0x3a, 0x6a, 0x75, 0x64, 0x67, 0x65, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0x2696, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, - 0x6a, 0x75, 0x64, 0x67, 0x65, 0x3a, 0x6a, 0x75, 0x64, 0x67, 0x65, 0x6d, - 0x61, 0x6e, 0xd83d, 0xdc70, 0x3a, 0x62, 0x72, 0x69, 0x64, 0x65, 0x5f, 0x77, - 0x69, 0x74, 0x68, 0x5f, 0x76, 0x65, 0x69, 0x6c, 0x3a, 0x62, 0x72, 0x69, - 0x64, 0x65, 0x76, 0x65, 0x69, 0x6c, 0x77, 0x69, 0x74, 0x68, 0xd83e, 0xdd35, - 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x69, 0x6e, 0x5f, 0x74, 0x75, 0x78, 0x65, - 0x64, 0x6f, 0x3a, 0x69, 0x6e, 0x6d, 0x61, 0x6e, 0x74, 0x75, 0x78, 0x65, - 0x64, 0x6f, 0xd83d, 0xdc78, 0x3a, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, - 0x73, 0x3a, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x73, 0xd83e, 0xdd34, - 0x3a, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x3a, 0x70, 0x72, 0x69, 0x6e, - 0x63, 0x65, 0xd83e, 0xdd36, 0x3a, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, - 0x63, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x3a, 0x63, 0x68, - 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x6d, 0x6f, 0x74, 0x68, 0x65, - 0x72, 0xd83e, 0xdd36, 0x3a, 0x6d, 0x72, 0x73, 0x5f, 0x63, 0x6c, 0x61, 0x75, - 0x73, 0x3a, 0x63, 0x6c, 0x61, 0x75, 0x73, 0x6d, 0x72, 0x73, 0xd83c, 0xdf85, - 0x3a, 0x73, 0x61, 0x6e, 0x74, 0x61, 0x3a, 0x73, 0x61, 0x6e, 0x74, 0x61, - 0xd83e, 0xddd9, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, - 0x6d, 0x61, 0x67, 0x65, 0x3a, 0x6d, 0x61, 0x67, 0x65, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0xd83e, 0xddd9, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x6d, 0x61, 0x67, 0x65, - 0x3a, 0x6d, 0x61, 0x67, 0x65, 0xd83e, 0xddd9, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, - 0x61, 0x6e, 0x5f, 0x6d, 0x61, 0x67, 0x65, 0x3a, 0x6d, 0x61, 0x67, 0x65, - 0x6d, 0x61, 0x6e, 0xd83e, 0xdddd, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0x5f, 0x65, 0x6c, 0x66, 0x3a, 0x65, 0x6c, 0x66, 0x77, 0x6f, - 0x6d, 0x61, 0x6e, 0xd83e, 0xdddd, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x65, 0x6c, 0x66, - 0x3a, 0x65, 0x6c, 0x66, 0xd83e, 0xdddd, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, - 0x6e, 0x5f, 0x65, 0x6c, 0x66, 0x3a, 0x65, 0x6c, 0x66, 0x6d, 0x61, 0x6e, - 0xd83e, 0xdddb, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, - 0x76, 0x61, 0x6d, 0x70, 0x69, 0x72, 0x65, 0x3a, 0x76, 0x61, 0x6d, 0x70, - 0x69, 0x72, 0x65, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83e, 0xdddb, 0x200d, 0x2640, - 0xfe0f, 0x3a, 0x76, 0x61, 0x6d, 0x70, 0x69, 0x72, 0x65, 0x3a, 0x76, 0x61, - 0x6d, 0x70, 0x69, 0x72, 0x65, 0xd83e, 0xdddb, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, - 0x61, 0x6e, 0x5f, 0x76, 0x61, 0x6d, 0x70, 0x69, 0x72, 0x65, 0x3a, 0x6d, - 0x61, 0x6e, 0x76, 0x61, 0x6d, 0x70, 0x69, 0x72, 0x65, 0xd83e, 0xdddf, 0x200d, - 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x7a, 0x6f, 0x6d, - 0x62, 0x69, 0x65, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x7a, 0x6f, 0x6d, - 0x62, 0x69, 0x65, 0xd83e, 0xdddf, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x7a, 0x6f, 0x6d, - 0x62, 0x69, 0x65, 0x3a, 0x7a, 0x6f, 0x6d, 0x62, 0x69, 0x65, 0xd83e, 0xdddf, - 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x7a, 0x6f, 0x6d, 0x62, - 0x69, 0x65, 0x3a, 0x6d, 0x61, 0x6e, 0x7a, 0x6f, 0x6d, 0x62, 0x69, 0x65, - 0xd83e, 0xddde, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, - 0x67, 0x65, 0x6e, 0x69, 0x65, 0x3a, 0x67, 0x65, 0x6e, 0x69, 0x65, 0x77, - 0x6f, 0x6d, 0x61, 0x6e, 0xd83e, 0xddde, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x67, 0x65, - 0x6e, 0x69, 0x65, 0x3a, 0x67, 0x65, 0x6e, 0x69, 0x65, 0xd83e, 0xddde, 0x200d, - 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x65, 0x6e, 0x69, 0x65, - 0x3a, 0x67, 0x65, 0x6e, 0x69, 0x65, 0x6d, 0x61, 0x6e, 0xd83e, 0xdddc, 0x200d, - 0x2640, 0xfe0f, 0x3a, 0x6d, 0x65, 0x72, 0x6d, 0x61, 0x69, 0x64, 0x3a, 0x6d, - 0x65, 0x72, 0x6d, 0x61, 0x69, 0x64, 0xd83e, 0xdddc, 0x200d, 0x2640, 0xfe0f, 0x3a, - 0x6d, 0x65, 0x72, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x3a, 0x6d, 0x65, - 0x72, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83e, 0xdddc, 0x200d, 0x2642, 0xfe0f, - 0x3a, 0x6d, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x3a, 0x6d, 0x65, 0x72, 0x6d, - 0x61, 0x6e, 0xd83e, 0xddda, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, - 0x6e, 0x5f, 0x66, 0x61, 0x69, 0x72, 0x79, 0x3a, 0x66, 0x61, 0x69, 0x72, - 0x79, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83e, 0xddda, 0x200d, 0x2640, 0xfe0f, 0x3a, - 0x66, 0x61, 0x69, 0x72, 0x79, 0x3a, 0x66, 0x61, 0x69, 0x72, 0x79, 0xd83e, - 0xddda, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x66, 0x61, 0x69, - 0x72, 0x79, 0x3a, 0x66, 0x61, 0x69, 0x72, 0x79, 0x6d, 0x61, 0x6e, 0xd83d, - 0xdc7c, 0x3a, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x3a, 0x61, 0x6e, 0x67, 0x65, - 0x6c, 0xd83e, 0xdd30, 0x3a, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x69, 0x6e, - 0x67, 0x5f, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x3a, 0x65, 0x78, 0x70, 0x65, - 0x63, 0x74, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83e, 0xdd30, - 0x3a, 0x70, 0x72, 0x65, 0x67, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x77, 0x6f, - 0x6d, 0x61, 0x6e, 0x3a, 0x70, 0x72, 0x65, 0x67, 0x6e, 0x61, 0x6e, 0x74, - 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83e, 0xdd31, 0x3a, 0x62, 0x72, 0x65, 0x61, - 0x73, 0x74, 0x5f, 0x66, 0x65, 0x65, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x62, - 0x72, 0x65, 0x61, 0x73, 0x74, 0x66, 0x65, 0x65, 0x64, 0x69, 0x6e, 0x67, - 0xd83d, 0xde47, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, - 0x62, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x6f, 0x77, 0x69, 0x6e, - 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xde47, 0x200d, 0x2642, 0xfe0f, 0x3a, - 0x6d, 0x61, 0x6e, 0x5f, 0x62, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x62, - 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0xd83d, 0xde47, 0x200d, 0x2642, - 0xfe0f, 0x3a, 0x62, 0x6f, 0x77, 0x3a, 0x62, 0x6f, 0x77, 0xd83d, 0xde47, 0x200d, - 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x62, 0x6f, - 0x77, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x70, - 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83d, 0xdc81, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, - 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x74, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x74, 0x69, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc81, - 0x200d, 0x2640, 0xfe0f, 0x3a, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x73, 0x6b, 0x5f, 0x70, 0x65, 0x72, - 0x73, 0x6f, 0x6e, 0x3a, 0x64, 0x65, 0x73, 0x6b, 0x69, 0x6e, 0x66, 0x6f, - 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x70, 0x65, 0x72, 0x73, 0x6f, - 0x6e, 0xd83d, 0xdc81, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, - 0x6e, 0x5f, 0x74, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, - 0x6e, 0x64, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x70, 0x65, 0x72, 0x73, 0x6f, - 0x6e, 0x74, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xd83d, 0xdc81, 0x200d, 0x2642, - 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x74, 0x69, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x6d, - 0x61, 0x6e, 0x74, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xd83d, 0xde45, 0x200d, - 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x65, 0x73, - 0x74, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x6f, 0x3a, 0x67, 0x65, - 0x73, 0x74, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x6e, 0x6f, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0xd83d, 0xde45, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x6e, 0x6f, 0x5f, 0x67, - 0x6f, 0x6f, 0x64, 0x3a, 0x67, 0x6f, 0x6f, 0x64, 0x6e, 0x6f, 0xd83d, 0xde45, - 0x200d, 0x2640, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x67, - 0x65, 0x73, 0x74, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x6f, 0x3a, - 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x6e, 0x6f, 0x70, - 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83d, 0xde45, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, - 0x61, 0x6e, 0x5f, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x69, 0x6e, 0x67, - 0x5f, 0x6e, 0x6f, 0x3a, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x69, 0x6e, - 0x67, 0x6d, 0x61, 0x6e, 0x6e, 0x6f, 0xd83d, 0xde46, 0x200d, 0x2640, 0xfe0f, 0x3a, - 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, - 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x6b, 0x3a, 0x67, 0x65, 0x73, 0x74, 0x75, - 0x72, 0x69, 0x6e, 0x67, 0x6f, 0x6b, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, - 0xde46, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x6f, 0x6b, 0x5f, 0x77, 0x6f, 0x6d, 0x61, - 0x6e, 0x3a, 0x6f, 0x6b, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xde46, 0x200d, - 0x2640, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x67, 0x65, - 0x73, 0x74, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x6b, 0x3a, 0x67, - 0x65, 0x73, 0x74, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x6f, 0x6b, 0x70, 0x65, - 0x72, 0x73, 0x6f, 0x6e, 0xd83d, 0xde46, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, - 0x6e, 0x5f, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x5f, - 0x6f, 0x6b, 0x3a, 0x67, 0x65, 0x73, 0x74, 0x75, 0x72, 0x69, 0x6e, 0x67, - 0x6d, 0x61, 0x6e, 0x6f, 0x6b, 0xd83d, 0xde4b, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, - 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x72, 0x61, 0x69, 0x73, 0x69, 0x6e, 0x67, - 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x72, 0x61, - 0x69, 0x73, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xde4b, - 0x200d, 0x2640, 0xfe0f, 0x3a, 0x72, 0x61, 0x69, 0x73, 0x69, 0x6e, 0x67, 0x5f, - 0x68, 0x61, 0x6e, 0x64, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x72, 0x61, 0x69, - 0x73, 0x69, 0x6e, 0x67, 0xd83d, 0xde4b, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x70, 0x65, - 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x72, 0x61, 0x69, 0x73, 0x69, 0x6e, 0x67, - 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x70, 0x65, - 0x72, 0x73, 0x6f, 0x6e, 0x72, 0x61, 0x69, 0x73, 0x69, 0x6e, 0x67, 0xd83d, - 0xde4b, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x72, 0x61, 0x69, - 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x3a, 0x68, 0x61, - 0x6e, 0x64, 0x6d, 0x61, 0x6e, 0x72, 0x61, 0x69, 0x73, 0x69, 0x6e, 0x67, - 0xd83e, 0xdd26, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, - 0x66, 0x61, 0x63, 0x65, 0x70, 0x61, 0x6c, 0x6d, 0x69, 0x6e, 0x67, 0x3a, - 0x66, 0x61, 0x63, 0x65, 0x70, 0x61, 0x6c, 0x6d, 0x69, 0x6e, 0x67, 0x77, - 0x6f, 0x6d, 0x61, 0x6e, 0xd83e, 0xdd26, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, - 0x6e, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x70, 0x61, 0x6c, 0x6d, 0x69, 0x6e, - 0x67, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x70, 0x61, 0x6c, 0x6d, 0x69, 0x6e, - 0x67, 0x6d, 0x61, 0x6e, 0xd83e, 0xdd26, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x66, 0x61, - 0x63, 0x65, 0x70, 0x61, 0x6c, 0x6d, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x70, - 0x61, 0x6c, 0x6d, 0xd83e, 0xdd26, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x66, 0x61, 0x63, - 0x65, 0x5f, 0x70, 0x61, 0x6c, 0x6d, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x70, - 0x61, 0x6c, 0x6d, 0xd83e, 0xdd26, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, - 0x73, 0x6f, 0x6e, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x70, 0x61, 0x6c, 0x6d, - 0x69, 0x6e, 0x67, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x70, 0x61, 0x6c, 0x6d, - 0x69, 0x6e, 0x67, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83e, 0xdd37, 0x200d, - 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x73, 0x68, 0x72, - 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x3a, 0x73, 0x68, 0x72, 0x75, 0x67, - 0x67, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83e, 0xdd37, 0x200d, - 0x2640, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x73, 0x68, - 0x72, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x3a, 0x70, 0x65, 0x72, 0x73, - 0x6f, 0x6e, 0x73, 0x68, 0x72, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0xd83e, - 0xdd37, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x73, 0x68, 0x72, - 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x3a, 0x6d, 0x61, 0x6e, 0x73, 0x68, - 0x72, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0xd83d, 0xde4e, 0x200d, 0x2640, 0xfe0f, - 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x75, 0x74, 0x69, - 0x6e, 0x67, 0x3a, 0x70, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x77, 0x6f, - 0x6d, 0x61, 0x6e, 0xd83d, 0xde4e, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, - 0x73, 0x6f, 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x70, 0x6f, 0x75, - 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, - 0x63, 0x65, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x70, 0x6f, 0x75, 0x74, - 0x69, 0x6e, 0x67, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xde4e, 0x200d, 0x2640, 0xfe0f, - 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x75, 0x74, - 0x69, 0x6e, 0x67, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x70, 0x6f, - 0x75, 0x74, 0x69, 0x6e, 0x67, 0xd83d, 0xde4e, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, - 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x3a, 0x6d, - 0x61, 0x6e, 0x70, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0xd83d, 0xde4d, 0x200d, - 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x66, 0x72, 0x6f, - 0x77, 0x6e, 0x69, 0x6e, 0x67, 0x3a, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, - 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xde4d, 0x200d, 0x2640, 0xfe0f, - 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x66, 0x72, 0x6f, 0x77, - 0x6e, 0x69, 0x6e, 0x67, 0x3a, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, 0x6e, - 0x67, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83d, 0xde4d, 0x200d, 0x2642, 0xfe0f, - 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, 0x6e, - 0x67, 0x3a, 0x66, 0x72, 0x6f, 0x77, 0x6e, 0x69, 0x6e, 0x67, 0x6d, 0x61, - 0x6e, 0xd83d, 0xdc87, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, - 0x5f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x69, - 0x72, 0x63, 0x75, 0x74, 0x3a, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x68, 0x61, 0x69, 0x72, 0x63, 0x75, 0x74, 0x77, 0x6f, 0x6d, 0x61, 0x6e, - 0xd83d, 0xdc87, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x68, 0x61, 0x69, 0x72, 0x63, 0x75, - 0x74, 0x3a, 0x68, 0x61, 0x69, 0x72, 0x63, 0x75, 0x74, 0xd83d, 0xdc87, 0x200d, - 0x2640, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x67, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x69, 0x72, 0x63, 0x75, - 0x74, 0x3a, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x68, 0x61, 0x69, - 0x72, 0x63, 0x75, 0x74, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83d, 0xdc87, - 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x69, 0x72, 0x63, 0x75, 0x74, 0x3a, - 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x72, 0x63, - 0x75, 0x74, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc86, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, - 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x5f, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x6d, 0x61, 0x73, 0x73, 0x61, 0x67, 0x65, 0x77, 0x6f, 0x6d, 0x61, - 0x6e, 0xd83d, 0xdc86, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x6d, 0x61, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x3a, 0x6d, 0x61, 0x73, 0x73, 0x61, 0x67, 0x65, 0xd83d, 0xdc86, - 0x200d, 0x2640, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x67, - 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x6d, 0x61, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x3a, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x6d, 0x61, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83d, - 0xdc86, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x6d, 0x61, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x67, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0x6d, 0x61, 0x73, 0x73, - 0x61, 0x67, 0x65, 0xd83e, 0xddd6, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x65, 0x61, 0x6d, 0x79, - 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x3a, 0x69, 0x6e, 0x72, 0x6f, 0x6f, 0x6d, - 0x73, 0x74, 0x65, 0x61, 0x6d, 0x79, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83e, - 0xddd6, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, - 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x65, 0x61, 0x6d, 0x79, 0x5f, 0x72, 0x6f, - 0x6f, 0x6d, 0x3a, 0x69, 0x6e, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x72, - 0x6f, 0x6f, 0x6d, 0x73, 0x74, 0x65, 0x61, 0x6d, 0x79, 0xd83e, 0xddd6, 0x200d, - 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x74, - 0x65, 0x61, 0x6d, 0x79, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x3a, 0x69, 0x6e, - 0x6d, 0x61, 0x6e, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x74, 0x65, 0x61, 0x6d, - 0x79, 0xd83d, 0xdc85, 0x3a, 0x6e, 0x61, 0x69, 0x6c, 0x5f, 0x63, 0x61, 0x72, - 0x65, 0x3a, 0x63, 0x61, 0x72, 0x65, 0x6e, 0x61, 0x69, 0x6c, 0xd83e, 0xdd33, - 0x3a, 0x73, 0x65, 0x6c, 0x66, 0x69, 0x65, 0x3a, 0x73, 0x65, 0x6c, 0x66, - 0x69, 0x65, 0xd83d, 0xdc83, 0x3a, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x3a, - 0x64, 0x61, 0x6e, 0x63, 0x65, 0x72, 0xd83d, 0xdd7a, 0x3a, 0x6d, 0x61, 0x6c, - 0x65, 0x5f, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x3a, 0x64, 0x61, 0x6e, - 0x63, 0x65, 0x72, 0x6d, 0x61, 0x6c, 0x65, 0xd83d, 0xdd7a, 0x3a, 0x6d, 0x61, - 0x6e, 0x5f, 0x64, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x3a, 0x64, 0x61, - 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc6f, 0x200d, 0x2640, - 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, - 0x5f, 0x62, 0x75, 0x6e, 0x6e, 0x79, 0x5f, 0x65, 0x61, 0x72, 0x73, 0x5f, - 0x70, 0x61, 0x72, 0x74, 0x79, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x75, 0x6e, - 0x6e, 0x79, 0x65, 0x61, 0x72, 0x73, 0x70, 0x61, 0x72, 0x74, 0x79, 0x69, - 0x6e, 0x67, 0x77, 0x69, 0x74, 0x68, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0xd83d, - 0xdc6f, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x73, - 0x3a, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x73, 0xd83d, 0xdc6f, 0x200d, 0x2640, - 0xfe0f, 0x3a, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x5f, 0x77, 0x69, 0x74, - 0x68, 0x5f, 0x62, 0x75, 0x6e, 0x6e, 0x79, 0x5f, 0x65, 0x61, 0x72, 0x73, - 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x75, - 0x6e, 0x6e, 0x79, 0x65, 0x61, 0x72, 0x73, 0x70, 0x61, 0x72, 0x74, 0x79, - 0x69, 0x6e, 0x67, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x77, 0x69, 0x74, - 0x68, 0xd83d, 0xdc6f, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x65, 0x6e, 0x5f, 0x77, - 0x69, 0x74, 0x68, 0x5f, 0x62, 0x75, 0x6e, 0x6e, 0x79, 0x5f, 0x65, 0x61, - 0x72, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x69, 0x6e, 0x67, 0x3a, - 0x62, 0x75, 0x6e, 0x6e, 0x79, 0x65, 0x61, 0x72, 0x73, 0x6d, 0x65, 0x6e, - 0x70, 0x61, 0x72, 0x74, 0x79, 0x69, 0x6e, 0x67, 0x77, 0x69, 0x74, 0x68, - 0xd83d, 0xdd74, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x69, 0x6e, 0x5f, 0x62, 0x75, - 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x5f, - 0x6c, 0x65, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x3a, 0x62, - 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x6c, 0x65, 0x76, - 0x69, 0x74, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0x73, 0x75, - 0x69, 0x74, 0xd83d, 0xdeb6, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, - 0x6e, 0x5f, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x77, 0x61, - 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdeb6, - 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x77, 0x61, 0x6c, 0x6b, - 0x69, 0x6e, 0x67, 0x3a, 0x6d, 0x61, 0x6e, 0x77, 0x61, 0x6c, 0x6b, 0x69, - 0x6e, 0x67, 0xd83d, 0xdeb6, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x77, 0x61, 0x6c, 0x6b, - 0x69, 0x6e, 0x67, 0x3a, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0xd83d, - 0xdeb6, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, - 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x70, 0x65, 0x72, 0x73, - 0x6f, 0x6e, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0xd83c, 0xdfc3, 0x200d, - 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x72, 0x75, 0x6e, - 0x6e, 0x69, 0x6e, 0x67, 0x3a, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, - 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83c, 0xdfc3, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, - 0x61, 0x6e, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x3a, 0x6d, - 0x61, 0x6e, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0xd83c, 0xdfc3, 0x200d, - 0x2642, 0xfe0f, 0x3a, 0x72, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x3a, 0x72, 0x75, - 0x6e, 0x6e, 0x65, 0x72, 0xd83c, 0xdfc3, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, - 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, - 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x72, 0x75, 0x6e, 0x6e, 0x69, - 0x6e, 0x67, 0xd83d, 0xdc6b, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x3a, - 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0xd83d, 0xdc6d, 0x3a, 0x74, 0x77, 0x6f, - 0x5f, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x5f, 0x68, 0x6f, 0x6c, 0x64, 0x69, - 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x3a, 0x68, 0x61, 0x6e, - 0x64, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x74, 0x77, 0x6f, - 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0xd83d, 0xdc6c, 0x3a, 0x74, 0x77, 0x6f, 0x5f, - 0x6d, 0x65, 0x6e, 0x5f, 0x68, 0x6f, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x5f, - 0x68, 0x61, 0x6e, 0x64, 0x73, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x68, - 0x6f, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x77, 0x6f, - 0xd83d, 0xdc91, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x5f, 0x77, 0x69, - 0x74, 0x68, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x3a, 0x63, 0x6f, 0x75, - 0x70, 0x6c, 0x65, 0x68, 0x65, 0x61, 0x72, 0x74, 0x77, 0x69, 0x74, 0x68, - 0xd83d, 0xdc91, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x5f, 0x77, 0x69, - 0x74, 0x68, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x5f, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0x5f, 0x6d, 0x61, 0x6e, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, - 0x65, 0x68, 0x65, 0x61, 0x72, 0x74, 0x6d, 0x61, 0x6e, 0x77, 0x69, 0x74, - 0x68, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, 0x2764, 0xfe0f, 0x200d, - 0xd83d, 0xdc69, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x5f, 0x77, 0x69, - 0x74, 0x68, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x5f, 0x77, 0x77, 0x3a, - 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x68, 0x65, 0x61, 0x72, 0x74, 0x77, - 0x69, 0x74, 0x68, 0x77, 0x77, 0xd83d, 0xdc69, 0x200d, 0x2764, 0xfe0f, 0x200d, 0xd83d, - 0xdc69, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x5f, 0x77, 0x77, 0x3a, - 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x77, 0x77, 0xd83d, 0xdc68, 0x200d, 0x2764, - 0xfe0f, 0x200d, 0xd83d, 0xdc68, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x5f, - 0x77, 0x69, 0x74, 0x68, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x5f, 0x6d, - 0x6d, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x68, 0x65, 0x61, 0x72, - 0x74, 0x6d, 0x6d, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdc68, 0x200d, 0x2764, 0xfe0f, - 0x200d, 0xd83d, 0xdc68, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x5f, 0x6d, - 0x6d, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x6d, 0x6d, 0xd83d, 0xdc8f, - 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x6b, 0x69, 0x73, 0x73, 0x3a, - 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x6b, 0x69, 0x73, 0x73, 0xd83d, 0xdc8f, - 0x3a, 0x6b, 0x69, 0x73, 0x73, 0x5f, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, - 0x6d, 0x61, 0x6e, 0x3a, 0x6b, 0x69, 0x73, 0x73, 0x6d, 0x61, 0x6e, 0x77, - 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, 0x2764, 0xfe0f, 0x200d, 0xd83d, 0xdc8b, - 0x200d, 0xd83d, 0xdc69, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, 0x6b, 0x69, - 0x73, 0x73, 0x5f, 0x77, 0x77, 0x3a, 0x63, 0x6f, 0x75, 0x70, 0x6c, 0x65, - 0x6b, 0x69, 0x73, 0x73, 0x77, 0x77, 0xd83d, 0xdc69, 0x200d, 0x2764, 0xfe0f, 0x200d, - 0xd83d, 0xdc8b, 0x200d, 0xd83d, 0xdc69, 0x3a, 0x6b, 0x69, 0x73, 0x73, 0x5f, 0x77, - 0x77, 0x3a, 0x6b, 0x69, 0x73, 0x73, 0x77, 0x77, 0xd83d, 0xdc68, 0x200d, 0x2764, - 0xfe0f, 0x200d, 0xd83d, 0xdc8b, 0x200d, 0xd83d, 0xdc68, 0x3a, 0x63, 0x6f, 0x75, 0x70, - 0x6c, 0x65, 0x6b, 0x69, 0x73, 0x73, 0x5f, 0x6d, 0x6d, 0x3a, 0x63, 0x6f, - 0x75, 0x70, 0x6c, 0x65, 0x6b, 0x69, 0x73, 0x73, 0x6d, 0x6d, 0xd83d, 0xdc68, - 0x200d, 0x2764, 0xfe0f, 0x200d, 0xd83d, 0xdc8b, 0x200d, 0xd83d, 0xdc68, 0x3a, 0x6b, 0x69, - 0x73, 0x73, 0x5f, 0x6d, 0x6d, 0x3a, 0x6b, 0x69, 0x73, 0x73, 0x6d, 0x6d, - 0xd83d, 0xdc6a, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x66, 0x61, - 0x6d, 0x69, 0x6c, 0x79, 0xd83d, 0xdc6a, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, - 0x79, 0x5f, 0x6d, 0x61, 0x6e, 0x5f, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, - 0x62, 0x6f, 0x79, 0x3a, 0x62, 0x6f, 0x79, 0x66, 0x61, 0x6d, 0x69, 0x6c, - 0x79, 0x6d, 0x61, 0x6e, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, - 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc67, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, - 0x5f, 0x6d, 0x77, 0x67, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x6d, - 0x77, 0x67, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc67, 0x200d, 0xd83d, - 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, 0x77, 0x67, - 0x62, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x6d, 0x77, 0x67, 0x62, - 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc66, 0x200d, 0xd83d, 0xdc66, 0x3a, - 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, 0x77, 0x62, 0x62, 0x3a, - 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x6d, 0x77, 0x62, 0x62, 0xd83d, 0xdc68, - 0x200d, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc67, 0x200d, 0xd83d, 0xdc67, 0x3a, 0x66, 0x61, - 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, 0x77, 0x67, 0x67, 0x3a, 0x66, 0x61, - 0x6d, 0x69, 0x6c, 0x79, 0x6d, 0x77, 0x67, 0x67, 0xd83d, 0xdc69, 0x200d, 0xd83d, - 0xdc69, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, - 0x77, 0x77, 0x62, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x77, 0x77, - 0x62, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc67, 0x3a, 0x66, 0x61, - 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x77, 0x77, 0x67, 0x3a, 0x66, 0x61, 0x6d, - 0x69, 0x6c, 0x79, 0x77, 0x77, 0x67, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc69, 0x200d, - 0xd83d, 0xdc67, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, - 0x5f, 0x77, 0x77, 0x67, 0x62, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, - 0x77, 0x77, 0x67, 0x62, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc66, - 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x77, - 0x77, 0x62, 0x62, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x77, 0x77, - 0x62, 0x62, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc67, 0x200d, 0xd83d, - 0xdc67, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x77, 0x77, 0x67, - 0x67, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x77, 0x77, 0x67, 0x67, - 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, - 0x69, 0x6c, 0x79, 0x5f, 0x6d, 0x6d, 0x62, 0x3a, 0x66, 0x61, 0x6d, 0x69, - 0x6c, 0x79, 0x6d, 0x6d, 0x62, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc68, 0x200d, 0xd83d, - 0xdc67, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, 0x6d, 0x67, - 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x6d, 0x6d, 0x67, 0xd83d, 0xdc68, - 0x200d, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc67, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, - 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, 0x6d, 0x67, 0x62, 0x3a, 0x66, 0x61, - 0x6d, 0x69, 0x6c, 0x79, 0x6d, 0x6d, 0x67, 0x62, 0xd83d, 0xdc68, 0x200d, 0xd83d, - 0xdc68, 0x200d, 0xd83d, 0xdc66, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, - 0x6c, 0x79, 0x5f, 0x6d, 0x6d, 0x62, 0x62, 0x3a, 0x66, 0x61, 0x6d, 0x69, - 0x6c, 0x79, 0x6d, 0x6d, 0x62, 0x62, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc68, 0x200d, - 0xd83d, 0xdc67, 0x200d, 0xd83d, 0xdc67, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, - 0x5f, 0x6d, 0x6d, 0x67, 0x67, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, - 0x6d, 0x6d, 0x67, 0x67, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, - 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x62, - 0x6f, 0x79, 0x3a, 0x62, 0x6f, 0x79, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, - 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, 0xd83d, 0xdc67, 0x3a, 0x66, - 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, - 0x67, 0x69, 0x72, 0x6c, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x67, - 0x69, 0x72, 0x6c, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, 0xd83d, - 0xdc67, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, - 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x69, 0x72, 0x6c, 0x5f, 0x62, - 0x6f, 0x79, 0x3a, 0x62, 0x6f, 0x79, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, - 0x67, 0x69, 0x72, 0x6c, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, - 0xd83d, 0xdc66, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, - 0x5f, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x62, 0x6f, 0x79, 0x5f, 0x62, - 0x6f, 0x79, 0x3a, 0x62, 0x6f, 0x79, 0x62, 0x6f, 0x79, 0x66, 0x61, 0x6d, - 0x69, 0x6c, 0x79, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc69, 0x200d, 0xd83d, - 0xdc67, 0x200d, 0xd83d, 0xdc67, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, - 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x69, 0x72, 0x6c, 0x5f, 0x67, - 0x69, 0x72, 0x6c, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x67, 0x69, - 0x72, 0x6c, 0x67, 0x69, 0x72, 0x6c, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, - 0xdc68, 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, - 0x6d, 0x61, 0x6e, 0x5f, 0x62, 0x6f, 0x79, 0x3a, 0x62, 0x6f, 0x79, 0x66, - 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83d, - 0xdc67, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, 0x61, 0x6e, - 0x5f, 0x67, 0x69, 0x72, 0x6c, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, - 0x67, 0x69, 0x72, 0x6c, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc67, - 0x200d, 0xd83d, 0xdc66, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, - 0x61, 0x6e, 0x5f, 0x67, 0x69, 0x72, 0x6c, 0x5f, 0x62, 0x6f, 0x79, 0x3a, - 0x62, 0x6f, 0x79, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x67, 0x69, 0x72, - 0x6c, 0x6d, 0x61, 0x6e, 0xd83d, 0xdc68, 0x200d, 0xd83d, 0xdc66, 0x200d, 0xd83d, 0xdc66, - 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6d, 0x61, 0x6e, 0x5f, - 0x62, 0x6f, 0x79, 0x5f, 0x62, 0x6f, 0x79, 0x3a, 0x62, 0x6f, 0x79, 0x62, - 0x6f, 0x79, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x6d, 0x61, 0x6e, 0xd83d, - 0xdc68, 0x200d, 0xd83d, 0xdc67, 0x200d, 0xd83d, 0xdc67, 0x3a, 0x66, 0x61, 0x6d, 0x69, - 0x6c, 0x79, 0x5f, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x69, 0x72, 0x6c, 0x5f, - 0x67, 0x69, 0x72, 0x6c, 0x3a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x67, - 0x69, 0x72, 0x6c, 0x67, 0x69, 0x72, 0x6c, 0x6d, 0x61, 0x6e, 0xd83e, 0xdde5, - 0x3a, 0x63, 0x6f, 0x61, 0x74, 0x3a, 0x63, 0x6f, 0x61, 0x74, 0xd83d, 0xdc5a, - 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x73, 0x5f, 0x63, 0x6c, 0x6f, 0x74, - 0x68, 0x65, 0x73, 0x3a, 0x63, 0x6c, 0x6f, 0x74, 0x68, 0x65, 0x73, 0x77, - 0x6f, 0x6d, 0x61, 0x6e, 0x73, 0xd83d, 0xdc55, 0x3a, 0x73, 0x68, 0x69, 0x72, - 0x74, 0x3a, 0x73, 0x68, 0x69, 0x72, 0x74, 0xd83d, 0xdc56, 0x3a, 0x6a, 0x65, - 0x61, 0x6e, 0x73, 0x3a, 0x6a, 0x65, 0x61, 0x6e, 0x73, 0xd83d, 0xdc54, 0x3a, - 0x6e, 0x65, 0x63, 0x6b, 0x74, 0x69, 0x65, 0x3a, 0x6e, 0x65, 0x63, 0x6b, - 0x74, 0x69, 0x65, 0xd83d, 0xdc57, 0x3a, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, - 0x64, 0x72, 0x65, 0x73, 0x73, 0xd83d, 0xdc59, 0x3a, 0x62, 0x69, 0x6b, 0x69, - 0x6e, 0x69, 0x3a, 0x62, 0x69, 0x6b, 0x69, 0x6e, 0x69, 0xd83d, 0xdc58, 0x3a, - 0x6b, 0x69, 0x6d, 0x6f, 0x6e, 0x6f, 0x3a, 0x6b, 0x69, 0x6d, 0x6f, 0x6e, - 0x6f, 0xd83d, 0xdc60, 0x3a, 0x68, 0x69, 0x67, 0x68, 0x5f, 0x68, 0x65, 0x65, - 0x6c, 0x3a, 0x68, 0x65, 0x65, 0x6c, 0x68, 0x69, 0x67, 0x68, 0xd83d, 0xdc61, - 0x3a, 0x73, 0x61, 0x6e, 0x64, 0x61, 0x6c, 0x3a, 0x73, 0x61, 0x6e, 0x64, - 0x61, 0x6c, 0xd83d, 0xdc62, 0x3a, 0x62, 0x6f, 0x6f, 0x74, 0x3a, 0x62, 0x6f, - 0x6f, 0x74, 0xd83d, 0xdc5e, 0x3a, 0x6d, 0x61, 0x6e, 0x73, 0x5f, 0x73, 0x68, - 0x6f, 0x65, 0x3a, 0x6d, 0x61, 0x6e, 0x73, 0x73, 0x68, 0x6f, 0x65, 0xd83d, - 0xdc5f, 0x3a, 0x61, 0x74, 0x68, 0x6c, 0x65, 0x74, 0x69, 0x63, 0x5f, 0x73, - 0x68, 0x6f, 0x65, 0x3a, 0x61, 0x74, 0x68, 0x6c, 0x65, 0x74, 0x69, 0x63, - 0x73, 0x68, 0x6f, 0x65, 0xd83e, 0xdde6, 0x3a, 0x73, 0x6f, 0x63, 0x6b, 0x73, - 0x3a, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0xd83e, 0xdde4, 0x3a, 0x67, 0x6c, 0x6f, - 0x76, 0x65, 0x73, 0x3a, 0x67, 0x6c, 0x6f, 0x76, 0x65, 0x73, 0xd83e, 0xdde3, - 0x3a, 0x73, 0x63, 0x61, 0x72, 0x66, 0x3a, 0x73, 0x63, 0x61, 0x72, 0x66, - 0xd83c, 0xdfa9, 0x3a, 0x74, 0x6f, 0x70, 0x68, 0x61, 0x74, 0x3a, 0x74, 0x6f, - 0x70, 0x68, 0x61, 0x74, 0xd83e, 0xdde2, 0x3a, 0x62, 0x69, 0x6c, 0x6c, 0x65, - 0x64, 0x5f, 0x63, 0x61, 0x70, 0x3a, 0x62, 0x69, 0x6c, 0x6c, 0x65, 0x64, - 0x63, 0x61, 0x70, 0xd83d, 0xdc52, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x73, - 0x5f, 0x68, 0x61, 0x74, 0x3a, 0x68, 0x61, 0x74, 0x77, 0x6f, 0x6d, 0x61, - 0x6e, 0x73, 0xd83c, 0xdf93, 0x3a, 0x6d, 0x6f, 0x72, 0x74, 0x61, 0x72, 0x5f, - 0x62, 0x6f, 0x61, 0x72, 0x64, 0x3a, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x6d, - 0x6f, 0x72, 0x74, 0x61, 0x72, 0x26d1, 0x3a, 0x68, 0x65, 0x6c, 0x6d, 0x65, - 0x74, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x77, 0x68, 0x69, 0x74, 0x65, - 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x3a, 0x63, 0x72, 0x6f, 0x73, 0x73, - 0x68, 0x65, 0x6c, 0x6d, 0x65, 0x74, 0x77, 0x68, 0x69, 0x74, 0x65, 0x77, - 0x69, 0x74, 0x68, 0x26d1, 0x3a, 0x68, 0x65, 0x6c, 0x6d, 0x65, 0x74, 0x5f, - 0x77, 0x69, 0x74, 0x68, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x3a, 0x63, - 0x72, 0x6f, 0x73, 0x73, 0x68, 0x65, 0x6c, 0x6d, 0x65, 0x74, 0x77, 0x69, - 0x74, 0x68, 0xd83d, 0xdc51, 0x3a, 0x63, 0x72, 0x6f, 0x77, 0x6e, 0x3a, 0x63, - 0x72, 0x6f, 0x77, 0x6e, 0xd83d, 0xdc8d, 0x3a, 0x72, 0x69, 0x6e, 0x67, 0x3a, - 0x72, 0x69, 0x6e, 0x67, 0xd83d, 0xdc5d, 0x3a, 0x70, 0x6f, 0x75, 0x63, 0x68, - 0x3a, 0x70, 0x6f, 0x75, 0x63, 0x68, 0xd83d, 0xdc5b, 0x3a, 0x70, 0x75, 0x72, - 0x73, 0x65, 0x3a, 0x70, 0x75, 0x72, 0x73, 0x65, 0xd83d, 0xdc5c, 0x3a, 0x68, - 0x61, 0x6e, 0x64, 0x62, 0x61, 0x67, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x62, - 0x61, 0x67, 0xd83d, 0xdcbc, 0x3a, 0x62, 0x72, 0x69, 0x65, 0x66, 0x63, 0x61, - 0x73, 0x65, 0x3a, 0x62, 0x72, 0x69, 0x65, 0x66, 0x63, 0x61, 0x73, 0x65, - 0xd83c, 0xdf92, 0x3a, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x5f, 0x73, 0x61, - 0x74, 0x63, 0x68, 0x65, 0x6c, 0x3a, 0x73, 0x61, 0x74, 0x63, 0x68, 0x65, - 0x6c, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0xd83d, 0xdc53, 0x3a, 0x65, 0x79, - 0x65, 0x67, 0x6c, 0x61, 0x73, 0x73, 0x65, 0x73, 0x3a, 0x65, 0x79, 0x65, - 0x67, 0x6c, 0x61, 0x73, 0x73, 0x65, 0x73, 0xd83d, 0xdd76, 0x3a, 0x64, 0x61, - 0x72, 0x6b, 0x5f, 0x73, 0x75, 0x6e, 0x67, 0x6c, 0x61, 0x73, 0x73, 0x65, - 0x73, 0x3a, 0x64, 0x61, 0x72, 0x6b, 0x73, 0x75, 0x6e, 0x67, 0x6c, 0x61, - 0x73, 0x73, 0x65, 0x73, 0xd83c, 0xdf02, 0x3a, 0x63, 0x6c, 0x6f, 0x73, 0x65, - 0x64, 0x5f, 0x75, 0x6d, 0x62, 0x72, 0x65, 0x6c, 0x6c, 0x61, 0x3a, 0x63, - 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x75, 0x6d, 0x62, 0x72, 0x65, 0x6c, 0x6c, - 0x61, 0xd83d, 0xdc36, 0x3a, 0x64, 0x6f, 0x67, 0x3a, 0x64, 0x6f, 0x67, 0xd83d, - 0xdc31, 0x3a, 0x63, 0x61, 0x74, 0x3a, 0x63, 0x61, 0x74, 0xd83d, 0xdc2d, 0x3a, - 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x3a, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0xd83d, - 0xdc39, 0x3a, 0x68, 0x61, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x68, 0x61, - 0x6d, 0x73, 0x74, 0x65, 0x72, 0xd83d, 0xdc30, 0x3a, 0x72, 0x61, 0x62, 0x62, - 0x69, 0x74, 0x3a, 0x72, 0x61, 0x62, 0x62, 0x69, 0x74, 0xd83e, 0xdd8a, 0x3a, - 0x66, 0x6f, 0x78, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, - 0x65, 0x66, 0x6f, 0x78, 0xd83e, 0xdd8a, 0x3a, 0x66, 0x6f, 0x78, 0x3a, 0x66, - 0x6f, 0x78, 0xd83d, 0xdc3b, 0x3a, 0x62, 0x65, 0x61, 0x72, 0x3a, 0x62, 0x65, - 0x61, 0x72, 0xd83d, 0xdc3c, 0x3a, 0x70, 0x61, 0x6e, 0x64, 0x61, 0x5f, 0x66, - 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x70, 0x61, 0x6e, 0x64, - 0x61, 0xd83d, 0xdc28, 0x3a, 0x6b, 0x6f, 0x61, 0x6c, 0x61, 0x3a, 0x6b, 0x6f, - 0x61, 0x6c, 0x61, 0xd83d, 0xdc2f, 0x3a, 0x74, 0x69, 0x67, 0x65, 0x72, 0x3a, - 0x74, 0x69, 0x67, 0x65, 0x72, 0xd83e, 0xdd81, 0x3a, 0x6c, 0x69, 0x6f, 0x6e, - 0x3a, 0x6c, 0x69, 0x6f, 0x6e, 0xd83e, 0xdd81, 0x3a, 0x6c, 0x69, 0x6f, 0x6e, - 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x6c, 0x69, - 0x6f, 0x6e, 0xd83d, 0xdc2e, 0x3a, 0x63, 0x6f, 0x77, 0x3a, 0x63, 0x6f, 0x77, - 0xd83d, 0xdc37, 0x3a, 0x70, 0x69, 0x67, 0x3a, 0x70, 0x69, 0x67, 0xd83d, 0xdc3d, - 0x3a, 0x70, 0x69, 0x67, 0x5f, 0x6e, 0x6f, 0x73, 0x65, 0x3a, 0x6e, 0x6f, - 0x73, 0x65, 0x70, 0x69, 0x67, 0xd83d, 0xdc38, 0x3a, 0x66, 0x72, 0x6f, 0x67, - 0x3a, 0x66, 0x72, 0x6f, 0x67, 0xd83d, 0xdc35, 0x3a, 0x6d, 0x6f, 0x6e, 0x6b, - 0x65, 0x79, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, - 0x6d, 0x6f, 0x6e, 0x6b, 0x65, 0x79, 0xd83d, 0xde48, 0x3a, 0x73, 0x65, 0x65, - 0x5f, 0x6e, 0x6f, 0x5f, 0x65, 0x76, 0x69, 0x6c, 0x3a, 0x65, 0x76, 0x69, - 0x6c, 0x6e, 0x6f, 0x73, 0x65, 0x65, 0xd83d, 0xde49, 0x3a, 0x68, 0x65, 0x61, - 0x72, 0x5f, 0x6e, 0x6f, 0x5f, 0x65, 0x76, 0x69, 0x6c, 0x3a, 0x65, 0x76, - 0x69, 0x6c, 0x68, 0x65, 0x61, 0x72, 0x6e, 0x6f, 0xd83d, 0xde4a, 0x3a, 0x73, - 0x70, 0x65, 0x61, 0x6b, 0x5f, 0x6e, 0x6f, 0x5f, 0x65, 0x76, 0x69, 0x6c, - 0x3a, 0x65, 0x76, 0x69, 0x6c, 0x6e, 0x6f, 0x73, 0x70, 0x65, 0x61, 0x6b, - 0xd83d, 0xdc12, 0x3a, 0x6d, 0x6f, 0x6e, 0x6b, 0x65, 0x79, 0x3a, 0x6d, 0x6f, - 0x6e, 0x6b, 0x65, 0x79, 0xd83d, 0xdc14, 0x3a, 0x63, 0x68, 0x69, 0x63, 0x6b, - 0x65, 0x6e, 0x3a, 0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0xd83d, 0xdc27, - 0x3a, 0x70, 0x65, 0x6e, 0x67, 0x75, 0x69, 0x6e, 0x3a, 0x70, 0x65, 0x6e, - 0x67, 0x75, 0x69, 0x6e, 0xd83d, 0xdc26, 0x3a, 0x62, 0x69, 0x72, 0x64, 0x3a, - 0x62, 0x69, 0x72, 0x64, 0xd83d, 0xdc24, 0x3a, 0x62, 0x61, 0x62, 0x79, 0x5f, - 0x63, 0x68, 0x69, 0x63, 0x6b, 0x3a, 0x62, 0x61, 0x62, 0x79, 0x63, 0x68, - 0x69, 0x63, 0x6b, 0xd83d, 0xdc23, 0x3a, 0x68, 0x61, 0x74, 0x63, 0x68, 0x69, - 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x69, 0x63, 0x6b, 0x3a, 0x63, 0x68, 0x69, - 0x63, 0x6b, 0x68, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0xd83d, 0xdc25, - 0x3a, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x63, 0x68, 0x69, - 0x63, 0x6b, 0x3a, 0x63, 0x68, 0x69, 0x63, 0x6b, 0x68, 0x61, 0x74, 0x63, - 0x68, 0x65, 0x64, 0xd83e, 0xdd86, 0x3a, 0x64, 0x75, 0x63, 0x6b, 0x3a, 0x64, - 0x75, 0x63, 0x6b, 0xd83e, 0xdd85, 0x3a, 0x65, 0x61, 0x67, 0x6c, 0x65, 0x3a, - 0x65, 0x61, 0x67, 0x6c, 0x65, 0xd83e, 0xdd89, 0x3a, 0x6f, 0x77, 0x6c, 0x3a, - 0x6f, 0x77, 0x6c, 0xd83e, 0xdd87, 0x3a, 0x62, 0x61, 0x74, 0x3a, 0x62, 0x61, - 0x74, 0xd83d, 0xdc3a, 0x3a, 0x77, 0x6f, 0x6c, 0x66, 0x3a, 0x77, 0x6f, 0x6c, - 0x66, 0xd83d, 0xdc17, 0x3a, 0x62, 0x6f, 0x61, 0x72, 0x3a, 0x62, 0x6f, 0x61, - 0x72, 0xd83d, 0xdc34, 0x3a, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x3a, 0x68, 0x6f, - 0x72, 0x73, 0x65, 0xd83e, 0xdd84, 0x3a, 0x75, 0x6e, 0x69, 0x63, 0x6f, 0x72, - 0x6e, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x75, - 0x6e, 0x69, 0x63, 0x6f, 0x72, 0x6e, 0xd83e, 0xdd84, 0x3a, 0x75, 0x6e, 0x69, - 0x63, 0x6f, 0x72, 0x6e, 0x3a, 0x75, 0x6e, 0x69, 0x63, 0x6f, 0x72, 0x6e, - 0xd83d, 0xdc1d, 0x3a, 0x62, 0x65, 0x65, 0x3a, 0x62, 0x65, 0x65, 0xd83d, 0xdc1b, - 0x3a, 0x62, 0x75, 0x67, 0x3a, 0x62, 0x75, 0x67, 0xd83e, 0xdd8b, 0x3a, 0x62, - 0x75, 0x74, 0x74, 0x65, 0x72, 0x66, 0x6c, 0x79, 0x3a, 0x62, 0x75, 0x74, - 0x74, 0x65, 0x72, 0x66, 0x6c, 0x79, 0xd83d, 0xdc0c, 0x3a, 0x73, 0x6e, 0x61, - 0x69, 0x6c, 0x3a, 0x73, 0x6e, 0x61, 0x69, 0x6c, 0xd83d, 0xdc1e, 0x3a, 0x62, - 0x65, 0x65, 0x74, 0x6c, 0x65, 0x3a, 0x62, 0x65, 0x65, 0x74, 0x6c, 0x65, - 0xd83d, 0xdc1c, 0x3a, 0x61, 0x6e, 0x74, 0x3a, 0x61, 0x6e, 0x74, 0xd83e, 0xdd97, - 0x3a, 0x63, 0x72, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x3a, 0x63, 0x72, 0x69, - 0x63, 0x6b, 0x65, 0x74, 0xd83d, 0xdd77, 0x3a, 0x73, 0x70, 0x69, 0x64, 0x65, - 0x72, 0x3a, 0x73, 0x70, 0x69, 0x64, 0x65, 0x72, 0xd83d, 0xdd78, 0x3a, 0x73, - 0x70, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x77, 0x65, 0x62, 0x3a, 0x73, 0x70, - 0x69, 0x64, 0x65, 0x72, 0x77, 0x65, 0x62, 0xd83e, 0xdd82, 0x3a, 0x73, 0x63, - 0x6f, 0x72, 0x70, 0x69, 0x6f, 0x6e, 0x3a, 0x73, 0x63, 0x6f, 0x72, 0x70, - 0x69, 0x6f, 0x6e, 0xd83d, 0xdc22, 0x3a, 0x74, 0x75, 0x72, 0x74, 0x6c, 0x65, - 0x3a, 0x74, 0x75, 0x72, 0x74, 0x6c, 0x65, 0xd83d, 0xdc0d, 0x3a, 0x73, 0x6e, - 0x61, 0x6b, 0x65, 0x3a, 0x73, 0x6e, 0x61, 0x6b, 0x65, 0xd83e, 0xdd8e, 0x3a, - 0x6c, 0x69, 0x7a, 0x61, 0x72, 0x64, 0x3a, 0x6c, 0x69, 0x7a, 0x61, 0x72, - 0x64, 0xd83e, 0xdd96, 0x3a, 0x74, 0x5f, 0x72, 0x65, 0x78, 0x3a, 0x72, 0x65, - 0x78, 0x74, 0xd83e, 0xdd95, 0x3a, 0x73, 0x61, 0x75, 0x72, 0x6f, 0x70, 0x6f, - 0x64, 0x3a, 0x73, 0x61, 0x75, 0x72, 0x6f, 0x70, 0x6f, 0x64, 0xd83d, 0xdc19, - 0x3a, 0x6f, 0x63, 0x74, 0x6f, 0x70, 0x75, 0x73, 0x3a, 0x6f, 0x63, 0x74, - 0x6f, 0x70, 0x75, 0x73, 0xd83e, 0xdd91, 0x3a, 0x73, 0x71, 0x75, 0x69, 0x64, - 0x3a, 0x73, 0x71, 0x75, 0x69, 0x64, 0xd83e, 0xdd90, 0x3a, 0x73, 0x68, 0x72, - 0x69, 0x6d, 0x70, 0x3a, 0x73, 0x68, 0x72, 0x69, 0x6d, 0x70, 0xd83e, 0xdd80, - 0x3a, 0x63, 0x72, 0x61, 0x62, 0x3a, 0x63, 0x72, 0x61, 0x62, 0xd83d, 0xdc21, - 0x3a, 0x62, 0x6c, 0x6f, 0x77, 0x66, 0x69, 0x73, 0x68, 0x3a, 0x62, 0x6c, - 0x6f, 0x77, 0x66, 0x69, 0x73, 0x68, 0xd83d, 0xdc20, 0x3a, 0x74, 0x72, 0x6f, - 0x70, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x66, 0x69, 0x73, 0x68, 0x3a, 0x66, - 0x69, 0x73, 0x68, 0x74, 0x72, 0x6f, 0x70, 0x69, 0x63, 0x61, 0x6c, 0xd83d, - 0xdc1f, 0x3a, 0x66, 0x69, 0x73, 0x68, 0x3a, 0x66, 0x69, 0x73, 0x68, 0xd83d, - 0xdc2c, 0x3a, 0x64, 0x6f, 0x6c, 0x70, 0x68, 0x69, 0x6e, 0x3a, 0x64, 0x6f, - 0x6c, 0x70, 0x68, 0x69, 0x6e, 0xd83d, 0xdc33, 0x3a, 0x77, 0x68, 0x61, 0x6c, - 0x65, 0x3a, 0x77, 0x68, 0x61, 0x6c, 0x65, 0xd83d, 0xdc0b, 0x3a, 0x77, 0x68, - 0x61, 0x6c, 0x65, 0x32, 0x3a, 0x77, 0x68, 0x61, 0x6c, 0x65, 0x32, 0xd83e, - 0xdd88, 0x3a, 0x73, 0x68, 0x61, 0x72, 0x6b, 0x3a, 0x73, 0x68, 0x61, 0x72, - 0x6b, 0xd83d, 0xdc0a, 0x3a, 0x63, 0x72, 0x6f, 0x63, 0x6f, 0x64, 0x69, 0x6c, - 0x65, 0x3a, 0x63, 0x72, 0x6f, 0x63, 0x6f, 0x64, 0x69, 0x6c, 0x65, 0xd83d, - 0xdc05, 0x3a, 0x74, 0x69, 0x67, 0x65, 0x72, 0x32, 0x3a, 0x74, 0x69, 0x67, - 0x65, 0x72, 0x32, 0xd83d, 0xdc06, 0x3a, 0x6c, 0x65, 0x6f, 0x70, 0x61, 0x72, - 0x64, 0x3a, 0x6c, 0x65, 0x6f, 0x70, 0x61, 0x72, 0x64, 0xd83e, 0xdd93, 0x3a, - 0x7a, 0x65, 0x62, 0x72, 0x61, 0x3a, 0x7a, 0x65, 0x62, 0x72, 0x61, 0xd83e, - 0xdd8d, 0x3a, 0x67, 0x6f, 0x72, 0x69, 0x6c, 0x6c, 0x61, 0x3a, 0x67, 0x6f, - 0x72, 0x69, 0x6c, 0x6c, 0x61, 0xd83d, 0xdc18, 0x3a, 0x65, 0x6c, 0x65, 0x70, - 0x68, 0x61, 0x6e, 0x74, 0x3a, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x61, 0x6e, - 0x74, 0xd83e, 0xdd8f, 0x3a, 0x72, 0x68, 0x69, 0x6e, 0x6f, 0x63, 0x65, 0x72, - 0x6f, 0x73, 0x3a, 0x72, 0x68, 0x69, 0x6e, 0x6f, 0x63, 0x65, 0x72, 0x6f, - 0x73, 0xd83e, 0xdd8f, 0x3a, 0x72, 0x68, 0x69, 0x6e, 0x6f, 0x3a, 0x72, 0x68, - 0x69, 0x6e, 0x6f, 0xd83d, 0xdc2a, 0x3a, 0x64, 0x72, 0x6f, 0x6d, 0x65, 0x64, - 0x61, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x3a, 0x63, 0x61, - 0x6d, 0x65, 0x6c, 0x64, 0x72, 0x6f, 0x6d, 0x65, 0x64, 0x61, 0x72, 0x79, - 0xd83d, 0xdc2b, 0x3a, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x3a, 0x63, 0x61, 0x6d, - 0x65, 0x6c, 0xd83e, 0xdd92, 0x3a, 0x67, 0x69, 0x72, 0x61, 0x66, 0x66, 0x65, - 0x3a, 0x67, 0x69, 0x72, 0x61, 0x66, 0x66, 0x65, 0xd83d, 0xdc03, 0x3a, 0x77, - 0x61, 0x74, 0x65, 0x72, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x61, 0x6c, 0x6f, - 0x3a, 0x62, 0x75, 0x66, 0x66, 0x61, 0x6c, 0x6f, 0x77, 0x61, 0x74, 0x65, - 0x72, 0xd83d, 0xdc02, 0x3a, 0x6f, 0x78, 0x3a, 0x6f, 0x78, 0xd83d, 0xdc04, 0x3a, - 0x63, 0x6f, 0x77, 0x32, 0x3a, 0x63, 0x6f, 0x77, 0x32, 0xd83d, 0xdc0e, 0x3a, - 0x72, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x3a, 0x72, 0x61, - 0x63, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0xd83d, 0xdc16, 0x3a, 0x70, 0x69, - 0x67, 0x32, 0x3a, 0x70, 0x69, 0x67, 0x32, 0xd83d, 0xdc0f, 0x3a, 0x72, 0x61, - 0x6d, 0x3a, 0x72, 0x61, 0x6d, 0xd83d, 0xdc11, 0x3a, 0x73, 0x68, 0x65, 0x65, - 0x70, 0x3a, 0x73, 0x68, 0x65, 0x65, 0x70, 0xd83d, 0xdc10, 0x3a, 0x67, 0x6f, - 0x61, 0x74, 0x3a, 0x67, 0x6f, 0x61, 0x74, 0xd83e, 0xdd8c, 0x3a, 0x64, 0x65, - 0x65, 0x72, 0x3a, 0x64, 0x65, 0x65, 0x72, 0xd83d, 0xdc15, 0x3a, 0x64, 0x6f, - 0x67, 0x32, 0x3a, 0x64, 0x6f, 0x67, 0x32, 0xd83d, 0xdc29, 0x3a, 0x70, 0x6f, - 0x6f, 0x64, 0x6c, 0x65, 0x3a, 0x70, 0x6f, 0x6f, 0x64, 0x6c, 0x65, 0xd83d, - 0xdc08, 0x3a, 0x63, 0x61, 0x74, 0x32, 0x3a, 0x63, 0x61, 0x74, 0x32, 0xd83d, - 0xdc13, 0x3a, 0x72, 0x6f, 0x6f, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x72, 0x6f, - 0x6f, 0x73, 0x74, 0x65, 0x72, 0xd83e, 0xdd83, 0x3a, 0x74, 0x75, 0x72, 0x6b, - 0x65, 0x79, 0x3a, 0x74, 0x75, 0x72, 0x6b, 0x65, 0x79, 0xd83d, 0xdd4a, 0x3a, - 0x64, 0x6f, 0x76, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x70, 0x65, 0x61, 0x63, - 0x65, 0x3a, 0x64, 0x6f, 0x76, 0x65, 0x6f, 0x66, 0x70, 0x65, 0x61, 0x63, - 0x65, 0xd83d, 0xdd4a, 0x3a, 0x64, 0x6f, 0x76, 0x65, 0x3a, 0x64, 0x6f, 0x76, - 0x65, 0xd83d, 0xdc07, 0x3a, 0x72, 0x61, 0x62, 0x62, 0x69, 0x74, 0x32, 0x3a, - 0x72, 0x61, 0x62, 0x62, 0x69, 0x74, 0x32, 0xd83d, 0xdc01, 0x3a, 0x6d, 0x6f, - 0x75, 0x73, 0x65, 0x32, 0x3a, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x32, 0xd83d, - 0xdc00, 0x3a, 0x72, 0x61, 0x74, 0x3a, 0x72, 0x61, 0x74, 0xd83d, 0xdc3f, 0x3a, - 0x63, 0x68, 0x69, 0x70, 0x6d, 0x75, 0x6e, 0x6b, 0x3a, 0x63, 0x68, 0x69, - 0x70, 0x6d, 0x75, 0x6e, 0x6b, 0xd83e, 0xdd94, 0x3a, 0x68, 0x65, 0x64, 0x67, - 0x65, 0x68, 0x6f, 0x67, 0x3a, 0x68, 0x65, 0x64, 0x67, 0x65, 0x68, 0x6f, - 0x67, 0xd83d, 0xdc3e, 0x3a, 0x70, 0x61, 0x77, 0x5f, 0x70, 0x72, 0x69, 0x6e, - 0x74, 0x73, 0x3a, 0x70, 0x61, 0x77, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, - 0xd83d, 0xdc3e, 0x3a, 0x66, 0x65, 0x65, 0x74, 0x3a, 0x66, 0x65, 0x65, 0x74, - 0xd83d, 0xdc09, 0x3a, 0x64, 0x72, 0x61, 0x67, 0x6f, 0x6e, 0x3a, 0x64, 0x72, - 0x61, 0x67, 0x6f, 0x6e, 0xd83d, 0xdc32, 0x3a, 0x64, 0x72, 0x61, 0x67, 0x6f, - 0x6e, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x64, 0x72, 0x61, 0x67, 0x6f, - 0x6e, 0x66, 0x61, 0x63, 0x65, 0xd83c, 0xdf35, 0x3a, 0x63, 0x61, 0x63, 0x74, - 0x75, 0x73, 0x3a, 0x63, 0x61, 0x63, 0x74, 0x75, 0x73, 0xd83c, 0xdf84, 0x3a, - 0x63, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x5f, 0x74, 0x72, - 0x65, 0x65, 0x3a, 0x63, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, - 0x74, 0x72, 0x65, 0x65, 0xd83c, 0xdf32, 0x3a, 0x65, 0x76, 0x65, 0x72, 0x67, - 0x72, 0x65, 0x65, 0x6e, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x3a, 0x65, 0x76, - 0x65, 0x72, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x74, 0x72, 0x65, 0x65, 0xd83c, - 0xdf33, 0x3a, 0x64, 0x65, 0x63, 0x69, 0x64, 0x75, 0x6f, 0x75, 0x73, 0x5f, - 0x74, 0x72, 0x65, 0x65, 0x3a, 0x64, 0x65, 0x63, 0x69, 0x64, 0x75, 0x6f, - 0x75, 0x73, 0x74, 0x72, 0x65, 0x65, 0xd83c, 0xdf34, 0x3a, 0x70, 0x61, 0x6c, - 0x6d, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x3a, 0x70, 0x61, 0x6c, 0x6d, 0x74, - 0x72, 0x65, 0x65, 0xd83c, 0xdf31, 0x3a, 0x73, 0x65, 0x65, 0x64, 0x6c, 0x69, - 0x6e, 0x67, 0x3a, 0x73, 0x65, 0x65, 0x64, 0x6c, 0x69, 0x6e, 0x67, 0xd83c, - 0xdf3f, 0x3a, 0x68, 0x65, 0x72, 0x62, 0x3a, 0x68, 0x65, 0x72, 0x62, 0x2618, - 0xfe0f, 0x3a, 0x73, 0x68, 0x61, 0x6d, 0x72, 0x6f, 0x63, 0x6b, 0x3a, 0x73, - 0x68, 0x61, 0x6d, 0x72, 0x6f, 0x63, 0x6b, 0xd83c, 0xdf40, 0x3a, 0x66, 0x6f, - 0x75, 0x72, 0x5f, 0x6c, 0x65, 0x61, 0x66, 0x5f, 0x63, 0x6c, 0x6f, 0x76, - 0x65, 0x72, 0x3a, 0x63, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6f, 0x75, - 0x72, 0x6c, 0x65, 0x61, 0x66, 0xd83c, 0xdf8d, 0x3a, 0x62, 0x61, 0x6d, 0x62, - 0x6f, 0x6f, 0x3a, 0x62, 0x61, 0x6d, 0x62, 0x6f, 0x6f, 0xd83c, 0xdf8b, 0x3a, - 0x74, 0x61, 0x6e, 0x61, 0x62, 0x61, 0x74, 0x61, 0x5f, 0x74, 0x72, 0x65, - 0x65, 0x3a, 0x74, 0x61, 0x6e, 0x61, 0x62, 0x61, 0x74, 0x61, 0x74, 0x72, - 0x65, 0x65, 0xd83c, 0xdf43, 0x3a, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x73, 0x3a, - 0x6c, 0x65, 0x61, 0x76, 0x65, 0x73, 0xd83c, 0xdf42, 0x3a, 0x66, 0x61, 0x6c, - 0x6c, 0x65, 0x6e, 0x5f, 0x6c, 0x65, 0x61, 0x66, 0x3a, 0x66, 0x61, 0x6c, - 0x6c, 0x65, 0x6e, 0x6c, 0x65, 0x61, 0x66, 0xd83c, 0xdf41, 0x3a, 0x6d, 0x61, - 0x70, 0x6c, 0x65, 0x5f, 0x6c, 0x65, 0x61, 0x66, 0x3a, 0x6c, 0x65, 0x61, - 0x66, 0x6d, 0x61, 0x70, 0x6c, 0x65, 0xd83c, 0xdf44, 0x3a, 0x6d, 0x75, 0x73, - 0x68, 0x72, 0x6f, 0x6f, 0x6d, 0x3a, 0x6d, 0x75, 0x73, 0x68, 0x72, 0x6f, - 0x6f, 0x6d, 0xd83d, 0xdc1a, 0x3a, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x3a, 0x73, - 0x68, 0x65, 0x6c, 0x6c, 0xd83c, 0xdf3e, 0x3a, 0x65, 0x61, 0x72, 0x5f, 0x6f, - 0x66, 0x5f, 0x72, 0x69, 0x63, 0x65, 0x3a, 0x65, 0x61, 0x72, 0x6f, 0x66, - 0x72, 0x69, 0x63, 0x65, 0xd83d, 0xdc90, 0x3a, 0x62, 0x6f, 0x75, 0x71, 0x75, - 0x65, 0x74, 0x3a, 0x62, 0x6f, 0x75, 0x71, 0x75, 0x65, 0x74, 0xd83c, 0xdf37, - 0x3a, 0x74, 0x75, 0x6c, 0x69, 0x70, 0x3a, 0x74, 0x75, 0x6c, 0x69, 0x70, - 0xd83c, 0xdf39, 0x3a, 0x72, 0x6f, 0x73, 0x65, 0x3a, 0x72, 0x6f, 0x73, 0x65, - 0xd83e, 0xdd40, 0x3a, 0x77, 0x69, 0x6c, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x6c, - 0x6f, 0x77, 0x65, 0x72, 0x3a, 0x66, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x77, - 0x69, 0x6c, 0x74, 0x65, 0x64, 0xd83e, 0xdd40, 0x3a, 0x77, 0x69, 0x6c, 0x74, - 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x73, 0x65, 0x3a, 0x72, 0x6f, 0x73, 0x65, - 0x77, 0x69, 0x6c, 0x74, 0x65, 0x64, 0xd83c, 0xdf3a, 0x3a, 0x68, 0x69, 0x62, - 0x69, 0x73, 0x63, 0x75, 0x73, 0x3a, 0x68, 0x69, 0x62, 0x69, 0x73, 0x63, - 0x75, 0x73, 0xd83c, 0xdf38, 0x3a, 0x63, 0x68, 0x65, 0x72, 0x72, 0x79, 0x5f, - 0x62, 0x6c, 0x6f, 0x73, 0x73, 0x6f, 0x6d, 0x3a, 0x62, 0x6c, 0x6f, 0x73, - 0x73, 0x6f, 0x6d, 0x63, 0x68, 0x65, 0x72, 0x72, 0x79, 0xd83c, 0xdf3c, 0x3a, - 0x62, 0x6c, 0x6f, 0x73, 0x73, 0x6f, 0x6d, 0x3a, 0x62, 0x6c, 0x6f, 0x73, - 0x73, 0x6f, 0x6d, 0xd83c, 0xdf3b, 0x3a, 0x73, 0x75, 0x6e, 0x66, 0x6c, 0x6f, - 0x77, 0x65, 0x72, 0x3a, 0x73, 0x75, 0x6e, 0x66, 0x6c, 0x6f, 0x77, 0x65, - 0x72, 0xd83c, 0xdf1e, 0x3a, 0x73, 0x75, 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, - 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x73, 0x75, - 0x6e, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdf1d, 0x3a, 0x66, 0x75, 0x6c, 0x6c, - 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x66, - 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x66, 0x75, 0x6c, 0x6c, - 0x6d, 0x6f, 0x6f, 0x6e, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdf1b, 0x3a, 0x66, - 0x69, 0x72, 0x73, 0x74, 0x5f, 0x71, 0x75, 0x61, 0x72, 0x74, 0x65, 0x72, - 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x66, - 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, 0x66, 0x69, 0x72, 0x73, - 0x74, 0x6d, 0x6f, 0x6f, 0x6e, 0x71, 0x75, 0x61, 0x72, 0x74, 0x65, 0x72, - 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdf1c, 0x3a, 0x6c, 0x61, 0x73, 0x74, 0x5f, - 0x71, 0x75, 0x61, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, - 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, - 0x61, 0x63, 0x65, 0x6c, 0x61, 0x73, 0x74, 0x6d, 0x6f, 0x6f, 0x6e, 0x71, - 0x75, 0x61, 0x72, 0x74, 0x65, 0x72, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdf1a, - 0x3a, 0x6e, 0x65, 0x77, 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x5f, 0x77, 0x69, - 0x74, 0x68, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x61, 0x63, 0x65, - 0x6d, 0x6f, 0x6f, 0x6e, 0x6e, 0x65, 0x77, 0x77, 0x69, 0x74, 0x68, 0xd83c, - 0xdf15, 0x3a, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x3a, - 0x66, 0x75, 0x6c, 0x6c, 0x6d, 0x6f, 0x6f, 0x6e, 0xd83c, 0xdf16, 0x3a, 0x77, - 0x61, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x69, 0x62, 0x62, 0x6f, 0x75, - 0x73, 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x3a, 0x67, 0x69, 0x62, 0x62, 0x6f, - 0x75, 0x73, 0x6d, 0x6f, 0x6f, 0x6e, 0x77, 0x61, 0x6e, 0x69, 0x6e, 0x67, - 0xd83c, 0xdf17, 0x3a, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x71, 0x75, 0x61, 0x72, - 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x3a, 0x6c, 0x61, 0x73, - 0x74, 0x6d, 0x6f, 0x6f, 0x6e, 0x71, 0x75, 0x61, 0x72, 0x74, 0x65, 0x72, - 0xd83c, 0xdf18, 0x3a, 0x77, 0x61, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x72, - 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x3a, - 0x63, 0x72, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x6d, 0x6f, 0x6f, 0x6e, - 0x77, 0x61, 0x6e, 0x69, 0x6e, 0x67, 0xd83c, 0xdf11, 0x3a, 0x6e, 0x65, 0x77, - 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x3a, 0x6d, 0x6f, 0x6f, 0x6e, 0x6e, 0x65, - 0x77, 0xd83c, 0xdf12, 0x3a, 0x77, 0x61, 0x78, 0x69, 0x6e, 0x67, 0x5f, 0x63, - 0x72, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, - 0x3a, 0x63, 0x72, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x6d, 0x6f, 0x6f, - 0x6e, 0x77, 0x61, 0x78, 0x69, 0x6e, 0x67, 0xd83c, 0xdf13, 0x3a, 0x66, 0x69, - 0x72, 0x73, 0x74, 0x5f, 0x71, 0x75, 0x61, 0x72, 0x74, 0x65, 0x72, 0x5f, - 0x6d, 0x6f, 0x6f, 0x6e, 0x3a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x6d, 0x6f, - 0x6f, 0x6e, 0x71, 0x75, 0x61, 0x72, 0x74, 0x65, 0x72, 0xd83c, 0xdf14, 0x3a, - 0x77, 0x61, 0x78, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x69, 0x62, 0x62, 0x6f, - 0x75, 0x73, 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x3a, 0x67, 0x69, 0x62, 0x62, - 0x6f, 0x75, 0x73, 0x6d, 0x6f, 0x6f, 0x6e, 0x77, 0x61, 0x78, 0x69, 0x6e, - 0x67, 0xd83c, 0xdf19, 0x3a, 0x63, 0x72, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, - 0x5f, 0x6d, 0x6f, 0x6f, 0x6e, 0x3a, 0x63, 0x72, 0x65, 0x73, 0x63, 0x65, - 0x6e, 0x74, 0x6d, 0x6f, 0x6f, 0x6e, 0xd83c, 0xdf0e, 0x3a, 0x65, 0x61, 0x72, - 0x74, 0x68, 0x5f, 0x61, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x73, 0x3a, - 0x61, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x73, 0x65, 0x61, 0x72, 0x74, - 0x68, 0xd83c, 0xdf0d, 0x3a, 0x65, 0x61, 0x72, 0x74, 0x68, 0x5f, 0x61, 0x66, - 0x72, 0x69, 0x63, 0x61, 0x3a, 0x61, 0x66, 0x72, 0x69, 0x63, 0x61, 0x65, - 0x61, 0x72, 0x74, 0x68, 0xd83c, 0xdf0f, 0x3a, 0x65, 0x61, 0x72, 0x74, 0x68, - 0x5f, 0x61, 0x73, 0x69, 0x61, 0x3a, 0x61, 0x73, 0x69, 0x61, 0x65, 0x61, - 0x72, 0x74, 0x68, 0xd83d, 0xdcab, 0x3a, 0x64, 0x69, 0x7a, 0x7a, 0x79, 0x3a, - 0x64, 0x69, 0x7a, 0x7a, 0x79, 0x2b50, 0xfe0f, 0x3a, 0x73, 0x74, 0x61, 0x72, - 0x3a, 0x73, 0x74, 0x61, 0x72, 0xd83c, 0xdf1f, 0x3a, 0x73, 0x74, 0x61, 0x72, - 0x32, 0x3a, 0x73, 0x74, 0x61, 0x72, 0x32, 0x2728, 0x3a, 0x73, 0x70, 0x61, - 0x72, 0x6b, 0x6c, 0x65, 0x73, 0x3a, 0x73, 0x70, 0x61, 0x72, 0x6b, 0x6c, - 0x65, 0x73, 0x26a1, 0xfe0f, 0x3a, 0x7a, 0x61, 0x70, 0x3a, 0x7a, 0x61, 0x70, - 0x2604, 0xfe0f, 0x3a, 0x63, 0x6f, 0x6d, 0x65, 0x74, 0x3a, 0x63, 0x6f, 0x6d, - 0x65, 0x74, 0xd83d, 0xdca5, 0x3a, 0x62, 0x6f, 0x6f, 0x6d, 0x3a, 0x62, 0x6f, - 0x6f, 0x6d, 0xd83d, 0xdd25, 0x3a, 0x66, 0x6c, 0x61, 0x6d, 0x65, 0x3a, 0x66, - 0x6c, 0x61, 0x6d, 0x65, 0xd83d, 0xdd25, 0x3a, 0x66, 0x69, 0x72, 0x65, 0x3a, - 0x66, 0x69, 0x72, 0x65, 0xd83c, 0xdf2a, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x74, 0x6f, 0x72, 0x6e, 0x61, 0x64, - 0x6f, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x74, 0x6f, 0x72, 0x6e, 0x61, - 0x64, 0x6f, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdf2a, 0x3a, 0x63, 0x6c, 0x6f, - 0x75, 0x64, 0x5f, 0x74, 0x6f, 0x72, 0x6e, 0x61, 0x64, 0x6f, 0x3a, 0x63, - 0x6c, 0x6f, 0x75, 0x64, 0x74, 0x6f, 0x72, 0x6e, 0x61, 0x64, 0x6f, 0xd83c, - 0xdf08, 0x3a, 0x72, 0x61, 0x69, 0x6e, 0x62, 0x6f, 0x77, 0x3a, 0x72, 0x61, - 0x69, 0x6e, 0x62, 0x6f, 0x77, 0x2600, 0xfe0f, 0x3a, 0x73, 0x75, 0x6e, 0x6e, - 0x79, 0x3a, 0x73, 0x75, 0x6e, 0x6e, 0x79, 0xd83c, 0xdf24, 0x3a, 0x77, 0x68, - 0x69, 0x74, 0x65, 0x5f, 0x73, 0x75, 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, - 0x5f, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x73, - 0x75, 0x6e, 0x77, 0x68, 0x69, 0x74, 0x65, 0x77, 0x69, 0x74, 0x68, 0xd83c, - 0xdf24, 0x3a, 0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x75, 0x6e, 0x5f, - 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x3a, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x73, 0x75, - 0x6e, 0x77, 0x68, 0x69, 0x74, 0x65, 0x26c5, 0xfe0f, 0x3a, 0x70, 0x61, 0x72, - 0x74, 0x6c, 0x79, 0x5f, 0x73, 0x75, 0x6e, 0x6e, 0x79, 0x3a, 0x70, 0x61, - 0x72, 0x74, 0x6c, 0x79, 0x73, 0x75, 0x6e, 0x6e, 0x79, 0xd83c, 0xdf25, 0x3a, - 0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x75, 0x6e, 0x5f, 0x62, 0x65, - 0x68, 0x69, 0x6e, 0x64, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x3a, 0x62, - 0x65, 0x68, 0x69, 0x6e, 0x64, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x75, - 0x6e, 0x77, 0x68, 0x69, 0x74, 0x65, 0xd83c, 0xdf25, 0x3a, 0x77, 0x68, 0x69, - 0x74, 0x65, 0x5f, 0x73, 0x75, 0x6e, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x75, 0x6e, 0x77, 0x68, 0x69, - 0x74, 0x65, 0x2601, 0xfe0f, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x3a, 0x63, - 0x6c, 0x6f, 0x75, 0x64, 0xd83c, 0xdf26, 0x3a, 0x77, 0x68, 0x69, 0x74, 0x65, - 0x5f, 0x73, 0x75, 0x6e, 0x5f, 0x62, 0x65, 0x68, 0x69, 0x6e, 0x64, 0x5f, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x72, - 0x61, 0x69, 0x6e, 0x3a, 0x62, 0x65, 0x68, 0x69, 0x6e, 0x64, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x72, 0x61, 0x69, 0x6e, 0x73, 0x75, 0x6e, 0x77, 0x68, - 0x69, 0x74, 0x65, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdf26, 0x3a, 0x77, 0x68, - 0x69, 0x74, 0x65, 0x5f, 0x73, 0x75, 0x6e, 0x5f, 0x72, 0x61, 0x69, 0x6e, - 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x72, 0x61, 0x69, 0x6e, 0x73, 0x75, 0x6e, 0x77, 0x68, 0x69, 0x74, 0x65, - 0xd83c, 0xdf27, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x77, 0x69, 0x74, - 0x68, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x72, 0x61, 0x69, 0x6e, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdf27, 0x3a, 0x63, - 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x3a, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x72, 0x61, 0x69, 0x6e, 0x26c8, 0x3a, 0x74, 0x68, 0x75, - 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x61, - 0x6e, 0x64, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x3a, 0x61, 0x6e, 0x64, 0x63, - 0x6c, 0x6f, 0x75, 0x64, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x68, 0x75, 0x6e, - 0x64, 0x65, 0x72, 0x26c8, 0x3a, 0x74, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, - 0x5f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x72, 0x61, 0x69, 0x6e, 0x3a, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x68, 0x75, - 0x6e, 0x64, 0x65, 0x72, 0xd83c, 0xdf29, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, - 0x69, 0x6e, 0x67, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x6c, 0x69, 0x67, - 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdf29, - 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x6c, 0x69, 0x67, 0x68, 0x74, - 0x6e, 0x69, 0x6e, 0x67, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x6c, 0x69, - 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0xd83c, 0xdf28, 0x3a, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x73, 0x6e, 0x6f, - 0x77, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x6e, 0x6f, 0x77, 0x77, - 0x69, 0x74, 0x68, 0xd83c, 0xdf28, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, - 0x73, 0x6e, 0x6f, 0x77, 0x3a, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x6e, - 0x6f, 0x77, 0x2744, 0xfe0f, 0x3a, 0x73, 0x6e, 0x6f, 0x77, 0x66, 0x6c, 0x61, - 0x6b, 0x65, 0x3a, 0x73, 0x6e, 0x6f, 0x77, 0x66, 0x6c, 0x61, 0x6b, 0x65, - 0x2603, 0xfe0f, 0x3a, 0x73, 0x6e, 0x6f, 0x77, 0x6d, 0x61, 0x6e, 0x32, 0x3a, - 0x73, 0x6e, 0x6f, 0x77, 0x6d, 0x61, 0x6e, 0x32, 0x26c4, 0xfe0f, 0x3a, 0x73, - 0x6e, 0x6f, 0x77, 0x6d, 0x61, 0x6e, 0x3a, 0x73, 0x6e, 0x6f, 0x77, 0x6d, - 0x61, 0x6e, 0xd83c, 0xdf2c, 0x3a, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x62, 0x6c, - 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x62, - 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x66, 0x61, 0x63, 0x65, 0x77, 0x69, - 0x6e, 0x64, 0xd83d, 0xdca8, 0x3a, 0x64, 0x61, 0x73, 0x68, 0x3a, 0x64, 0x61, - 0x73, 0x68, 0xd83d, 0xdca7, 0x3a, 0x64, 0x72, 0x6f, 0x70, 0x6c, 0x65, 0x74, - 0x3a, 0x64, 0x72, 0x6f, 0x70, 0x6c, 0x65, 0x74, 0xd83d, 0xdca6, 0x3a, 0x73, - 0x77, 0x65, 0x61, 0x74, 0x5f, 0x64, 0x72, 0x6f, 0x70, 0x73, 0x3a, 0x64, - 0x72, 0x6f, 0x70, 0x73, 0x73, 0x77, 0x65, 0x61, 0x74, 0x2614, 0xfe0f, 0x3a, - 0x75, 0x6d, 0x62, 0x72, 0x65, 0x6c, 0x6c, 0x61, 0x3a, 0x75, 0x6d, 0x62, - 0x72, 0x65, 0x6c, 0x6c, 0x61, 0x2602, 0xfe0f, 0x3a, 0x75, 0x6d, 0x62, 0x72, - 0x65, 0x6c, 0x6c, 0x61, 0x32, 0x3a, 0x75, 0x6d, 0x62, 0x72, 0x65, 0x6c, - 0x6c, 0x61, 0x32, 0xd83c, 0xdf0a, 0x3a, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x3a, - 0x6f, 0x63, 0x65, 0x61, 0x6e, 0xd83c, 0xdf2b, 0x3a, 0x66, 0x6f, 0x67, 0x3a, - 0x66, 0x6f, 0x67, 0xd83c, 0xdf4f, 0x3a, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x5f, - 0x61, 0x70, 0x70, 0x6c, 0x65, 0x3a, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x67, - 0x72, 0x65, 0x65, 0x6e, 0xd83c, 0xdf4e, 0x3a, 0x61, 0x70, 0x70, 0x6c, 0x65, - 0x3a, 0x61, 0x70, 0x70, 0x6c, 0x65, 0xd83c, 0xdf50, 0x3a, 0x70, 0x65, 0x61, - 0x72, 0x3a, 0x70, 0x65, 0x61, 0x72, 0xd83c, 0xdf4a, 0x3a, 0x74, 0x61, 0x6e, - 0x67, 0x65, 0x72, 0x69, 0x6e, 0x65, 0x3a, 0x74, 0x61, 0x6e, 0x67, 0x65, - 0x72, 0x69, 0x6e, 0x65, 0xd83c, 0xdf4b, 0x3a, 0x6c, 0x65, 0x6d, 0x6f, 0x6e, - 0x3a, 0x6c, 0x65, 0x6d, 0x6f, 0x6e, 0xd83c, 0xdf4c, 0x3a, 0x62, 0x61, 0x6e, - 0x61, 0x6e, 0x61, 0x3a, 0x62, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0xd83c, 0xdf49, - 0x3a, 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x6c, 0x6f, 0x6e, 0x3a, - 0x77, 0x61, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x6c, 0x6f, 0x6e, 0xd83c, 0xdf47, - 0x3a, 0x67, 0x72, 0x61, 0x70, 0x65, 0x73, 0x3a, 0x67, 0x72, 0x61, 0x70, - 0x65, 0x73, 0xd83c, 0xdf53, 0x3a, 0x73, 0x74, 0x72, 0x61, 0x77, 0x62, 0x65, - 0x72, 0x72, 0x79, 0x3a, 0x73, 0x74, 0x72, 0x61, 0x77, 0x62, 0x65, 0x72, - 0x72, 0x79, 0xd83c, 0xdf48, 0x3a, 0x6d, 0x65, 0x6c, 0x6f, 0x6e, 0x3a, 0x6d, - 0x65, 0x6c, 0x6f, 0x6e, 0xd83c, 0xdf52, 0x3a, 0x63, 0x68, 0x65, 0x72, 0x72, - 0x69, 0x65, 0x73, 0x3a, 0x63, 0x68, 0x65, 0x72, 0x72, 0x69, 0x65, 0x73, - 0xd83c, 0xdf51, 0x3a, 0x70, 0x65, 0x61, 0x63, 0x68, 0x3a, 0x70, 0x65, 0x61, - 0x63, 0x68, 0xd83c, 0xdf4d, 0x3a, 0x70, 0x69, 0x6e, 0x65, 0x61, 0x70, 0x70, - 0x6c, 0x65, 0x3a, 0x70, 0x69, 0x6e, 0x65, 0x61, 0x70, 0x70, 0x6c, 0x65, - 0xd83e, 0xdd65, 0x3a, 0x63, 0x6f, 0x63, 0x6f, 0x6e, 0x75, 0x74, 0x3a, 0x63, - 0x6f, 0x63, 0x6f, 0x6e, 0x75, 0x74, 0xd83e, 0xdd5d, 0x3a, 0x6b, 0x69, 0x77, - 0x69, 0x66, 0x72, 0x75, 0x69, 0x74, 0x3a, 0x6b, 0x69, 0x77, 0x69, 0x66, - 0x72, 0x75, 0x69, 0x74, 0xd83e, 0xdd5d, 0x3a, 0x6b, 0x69, 0x77, 0x69, 0x3a, - 0x6b, 0x69, 0x77, 0x69, 0xd83c, 0xdf45, 0x3a, 0x74, 0x6f, 0x6d, 0x61, 0x74, - 0x6f, 0x3a, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x6f, 0xd83c, 0xdf46, 0x3a, 0x65, - 0x67, 0x67, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x3a, 0x65, 0x67, 0x67, 0x70, - 0x6c, 0x61, 0x6e, 0x74, 0xd83e, 0xdd51, 0x3a, 0x61, 0x76, 0x6f, 0x63, 0x61, - 0x64, 0x6f, 0x3a, 0x61, 0x76, 0x6f, 0x63, 0x61, 0x64, 0x6f, 0xd83e, 0xdd66, - 0x3a, 0x62, 0x72, 0x6f, 0x63, 0x63, 0x6f, 0x6c, 0x69, 0x3a, 0x62, 0x72, - 0x6f, 0x63, 0x63, 0x6f, 0x6c, 0x69, 0xd83e, 0xdd52, 0x3a, 0x63, 0x75, 0x63, - 0x75, 0x6d, 0x62, 0x65, 0x72, 0x3a, 0x63, 0x75, 0x63, 0x75, 0x6d, 0x62, - 0x65, 0x72, 0xd83c, 0xdf36, 0x3a, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x65, 0x70, - 0x70, 0x65, 0x72, 0x3a, 0x68, 0x6f, 0x74, 0x70, 0x65, 0x70, 0x70, 0x65, - 0x72, 0xd83c, 0xdf3d, 0x3a, 0x63, 0x6f, 0x72, 0x6e, 0x3a, 0x63, 0x6f, 0x72, - 0x6e, 0xd83e, 0xdd55, 0x3a, 0x63, 0x61, 0x72, 0x72, 0x6f, 0x74, 0x3a, 0x63, - 0x61, 0x72, 0x72, 0x6f, 0x74, 0xd83e, 0xdd54, 0x3a, 0x70, 0x6f, 0x74, 0x61, - 0x74, 0x6f, 0x3a, 0x70, 0x6f, 0x74, 0x61, 0x74, 0x6f, 0xd83c, 0xdf60, 0x3a, - 0x73, 0x77, 0x65, 0x65, 0x74, 0x5f, 0x70, 0x6f, 0x74, 0x61, 0x74, 0x6f, - 0x3a, 0x70, 0x6f, 0x74, 0x61, 0x74, 0x6f, 0x73, 0x77, 0x65, 0x65, 0x74, - 0xd83e, 0xdd50, 0x3a, 0x63, 0x72, 0x6f, 0x69, 0x73, 0x73, 0x61, 0x6e, 0x74, - 0x3a, 0x63, 0x72, 0x6f, 0x69, 0x73, 0x73, 0x61, 0x6e, 0x74, 0xd83c, 0xdf5e, - 0x3a, 0x62, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x62, 0x72, 0x65, 0x61, 0x64, - 0xd83e, 0xdd56, 0x3a, 0x62, 0x61, 0x67, 0x75, 0x65, 0x74, 0x74, 0x65, 0x5f, - 0x62, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x62, 0x61, 0x67, 0x75, 0x65, 0x74, - 0x74, 0x65, 0x62, 0x72, 0x65, 0x61, 0x64, 0xd83e, 0xdd56, 0x3a, 0x66, 0x72, - 0x65, 0x6e, 0x63, 0x68, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x62, - 0x72, 0x65, 0x61, 0x64, 0x66, 0x72, 0x65, 0x6e, 0x63, 0x68, 0xd83e, 0xdd68, - 0x3a, 0x70, 0x72, 0x65, 0x74, 0x7a, 0x65, 0x6c, 0x3a, 0x70, 0x72, 0x65, - 0x74, 0x7a, 0x65, 0x6c, 0xd83e, 0xddc0, 0x3a, 0x63, 0x68, 0x65, 0x65, 0x73, - 0x65, 0x5f, 0x77, 0x65, 0x64, 0x67, 0x65, 0x3a, 0x63, 0x68, 0x65, 0x65, - 0x73, 0x65, 0x77, 0x65, 0x64, 0x67, 0x65, 0xd83e, 0xddc0, 0x3a, 0x63, 0x68, - 0x65, 0x65, 0x73, 0x65, 0x3a, 0x63, 0x68, 0x65, 0x65, 0x73, 0x65, 0xd83e, - 0xdd5a, 0x3a, 0x65, 0x67, 0x67, 0x3a, 0x65, 0x67, 0x67, 0xd83c, 0xdf73, 0x3a, - 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x63, 0x6f, 0x6f, 0x6b, - 0x69, 0x6e, 0x67, 0xd83e, 0xdd5e, 0x3a, 0x70, 0x61, 0x6e, 0x63, 0x61, 0x6b, - 0x65, 0x73, 0x3a, 0x70, 0x61, 0x6e, 0x63, 0x61, 0x6b, 0x65, 0x73, 0xd83e, - 0xdd53, 0x3a, 0x62, 0x61, 0x63, 0x6f, 0x6e, 0x3a, 0x62, 0x61, 0x63, 0x6f, - 0x6e, 0xd83e, 0xdd69, 0x3a, 0x63, 0x75, 0x74, 0x5f, 0x6f, 0x66, 0x5f, 0x6d, - 0x65, 0x61, 0x74, 0x3a, 0x63, 0x75, 0x74, 0x6d, 0x65, 0x61, 0x74, 0x6f, - 0x66, 0xd83c, 0xdf57, 0x3a, 0x70, 0x6f, 0x75, 0x6c, 0x74, 0x72, 0x79, 0x5f, - 0x6c, 0x65, 0x67, 0x3a, 0x6c, 0x65, 0x67, 0x70, 0x6f, 0x75, 0x6c, 0x74, - 0x72, 0x79, 0xd83c, 0xdf56, 0x3a, 0x6d, 0x65, 0x61, 0x74, 0x5f, 0x6f, 0x6e, - 0x5f, 0x62, 0x6f, 0x6e, 0x65, 0x3a, 0x62, 0x6f, 0x6e, 0x65, 0x6d, 0x65, - 0x61, 0x74, 0x6f, 0x6e, 0xd83c, 0xdf2d, 0x3a, 0x68, 0x6f, 0x74, 0x5f, 0x64, - 0x6f, 0x67, 0x3a, 0x64, 0x6f, 0x67, 0x68, 0x6f, 0x74, 0xd83c, 0xdf2d, 0x3a, - 0x68, 0x6f, 0x74, 0x64, 0x6f, 0x67, 0x3a, 0x68, 0x6f, 0x74, 0x64, 0x6f, - 0x67, 0xd83c, 0xdf54, 0x3a, 0x68, 0x61, 0x6d, 0x62, 0x75, 0x72, 0x67, 0x65, - 0x72, 0x3a, 0x68, 0x61, 0x6d, 0x62, 0x75, 0x72, 0x67, 0x65, 0x72, 0xd83c, - 0xdf5f, 0x3a, 0x66, 0x72, 0x69, 0x65, 0x73, 0x3a, 0x66, 0x72, 0x69, 0x65, - 0x73, 0xd83c, 0xdf55, 0x3a, 0x70, 0x69, 0x7a, 0x7a, 0x61, 0x3a, 0x70, 0x69, - 0x7a, 0x7a, 0x61, 0xd83e, 0xdd6a, 0x3a, 0x73, 0x61, 0x6e, 0x64, 0x77, 0x69, - 0x63, 0x68, 0x3a, 0x73, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x63, 0x68, 0xd83e, - 0xdd59, 0x3a, 0x73, 0x74, 0x75, 0x66, 0x66, 0x65, 0x64, 0x5f, 0x70, 0x69, - 0x74, 0x61, 0x3a, 0x70, 0x69, 0x74, 0x61, 0x73, 0x74, 0x75, 0x66, 0x66, - 0x65, 0x64, 0xd83e, 0xdd59, 0x3a, 0x73, 0x74, 0x75, 0x66, 0x66, 0x65, 0x64, - 0x5f, 0x66, 0x6c, 0x61, 0x74, 0x62, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x66, - 0x6c, 0x61, 0x74, 0x62, 0x72, 0x65, 0x61, 0x64, 0x73, 0x74, 0x75, 0x66, - 0x66, 0x65, 0x64, 0xd83c, 0xdf2e, 0x3a, 0x74, 0x61, 0x63, 0x6f, 0x3a, 0x74, - 0x61, 0x63, 0x6f, 0xd83c, 0xdf2f, 0x3a, 0x62, 0x75, 0x72, 0x72, 0x69, 0x74, - 0x6f, 0x3a, 0x62, 0x75, 0x72, 0x72, 0x69, 0x74, 0x6f, 0xd83e, 0xdd57, 0x3a, - 0x67, 0x72, 0x65, 0x65, 0x6e, 0x5f, 0x73, 0x61, 0x6c, 0x61, 0x64, 0x3a, - 0x67, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x61, 0x6c, 0x61, 0x64, 0xd83e, 0xdd57, - 0x3a, 0x73, 0x61, 0x6c, 0x61, 0x64, 0x3a, 0x73, 0x61, 0x6c, 0x61, 0x64, - 0xd83e, 0xdd58, 0x3a, 0x70, 0x61, 0x65, 0x6c, 0x6c, 0x61, 0x3a, 0x70, 0x61, - 0x65, 0x6c, 0x6c, 0x61, 0xd83e, 0xdd58, 0x3a, 0x73, 0x68, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x5f, 0x70, 0x61, 0x6e, 0x5f, 0x6f, 0x66, 0x5f, 0x66, 0x6f, - 0x6f, 0x64, 0x3a, 0x66, 0x6f, 0x6f, 0x64, 0x6f, 0x66, 0x70, 0x61, 0x6e, - 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0xd83e, 0xdd6b, 0x3a, 0x63, 0x61, - 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x66, 0x6f, 0x6f, 0x64, 0x3a, 0x63, 0x61, - 0x6e, 0x6e, 0x65, 0x64, 0x66, 0x6f, 0x6f, 0x64, 0xd83c, 0xdf5d, 0x3a, 0x73, - 0x70, 0x61, 0x67, 0x68, 0x65, 0x74, 0x74, 0x69, 0x3a, 0x73, 0x70, 0x61, - 0x67, 0x68, 0x65, 0x74, 0x74, 0x69, 0xd83c, 0xdf5c, 0x3a, 0x72, 0x61, 0x6d, - 0x65, 0x6e, 0x3a, 0x72, 0x61, 0x6d, 0x65, 0x6e, 0xd83c, 0xdf72, 0x3a, 0x73, - 0x74, 0x65, 0x77, 0x3a, 0x73, 0x74, 0x65, 0x77, 0xd83c, 0xdf5b, 0x3a, 0x63, - 0x75, 0x72, 0x72, 0x79, 0x3a, 0x63, 0x75, 0x72, 0x72, 0x79, 0xd83c, 0xdf63, - 0x3a, 0x73, 0x75, 0x73, 0x68, 0x69, 0x3a, 0x73, 0x75, 0x73, 0x68, 0x69, - 0xd83c, 0xdf71, 0x3a, 0x62, 0x65, 0x6e, 0x74, 0x6f, 0x3a, 0x62, 0x65, 0x6e, - 0x74, 0x6f, 0xd83e, 0xdd5f, 0x3a, 0x64, 0x75, 0x6d, 0x70, 0x6c, 0x69, 0x6e, - 0x67, 0x3a, 0x64, 0x75, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0xd83c, 0xdf64, - 0x3a, 0x66, 0x72, 0x69, 0x65, 0x64, 0x5f, 0x73, 0x68, 0x72, 0x69, 0x6d, - 0x70, 0x3a, 0x66, 0x72, 0x69, 0x65, 0x64, 0x73, 0x68, 0x72, 0x69, 0x6d, - 0x70, 0xd83c, 0xdf59, 0x3a, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x62, 0x61, 0x6c, - 0x6c, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x72, 0x69, 0x63, 0x65, 0xd83c, 0xdf5a, - 0x3a, 0x72, 0x69, 0x63, 0x65, 0x3a, 0x72, 0x69, 0x63, 0x65, 0xd83c, 0xdf58, - 0x3a, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x72, 0x61, 0x63, 0x6b, 0x65, - 0x72, 0x3a, 0x63, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x72, 0x69, 0x63, - 0x65, 0xd83c, 0xdf65, 0x3a, 0x66, 0x69, 0x73, 0x68, 0x5f, 0x63, 0x61, 0x6b, - 0x65, 0x3a, 0x63, 0x61, 0x6b, 0x65, 0x66, 0x69, 0x73, 0x68, 0xd83e, 0xdd60, - 0x3a, 0x66, 0x6f, 0x72, 0x74, 0x75, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x6f, - 0x6b, 0x69, 0x65, 0x3a, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x66, 0x6f, - 0x72, 0x74, 0x75, 0x6e, 0x65, 0xd83c, 0xdf62, 0x3a, 0x6f, 0x64, 0x65, 0x6e, - 0x3a, 0x6f, 0x64, 0x65, 0x6e, 0xd83c, 0xdf61, 0x3a, 0x64, 0x61, 0x6e, 0x67, - 0x6f, 0x3a, 0x64, 0x61, 0x6e, 0x67, 0x6f, 0xd83c, 0xdf67, 0x3a, 0x73, 0x68, - 0x61, 0x76, 0x65, 0x64, 0x5f, 0x69, 0x63, 0x65, 0x3a, 0x69, 0x63, 0x65, - 0x73, 0x68, 0x61, 0x76, 0x65, 0x64, 0xd83c, 0xdf68, 0x3a, 0x69, 0x63, 0x65, - 0x5f, 0x63, 0x72, 0x65, 0x61, 0x6d, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x6d, - 0x69, 0x63, 0x65, 0xd83c, 0xdf66, 0x3a, 0x69, 0x63, 0x65, 0x63, 0x72, 0x65, - 0x61, 0x6d, 0x3a, 0x69, 0x63, 0x65, 0x63, 0x72, 0x65, 0x61, 0x6d, 0xd83e, - 0xdd67, 0x3a, 0x70, 0x69, 0x65, 0x3a, 0x70, 0x69, 0x65, 0xd83c, 0xdf70, 0x3a, - 0x63, 0x61, 0x6b, 0x65, 0x3a, 0x63, 0x61, 0x6b, 0x65, 0xd83c, 0xdf82, 0x3a, - 0x62, 0x69, 0x72, 0x74, 0x68, 0x64, 0x61, 0x79, 0x3a, 0x62, 0x69, 0x72, - 0x74, 0x68, 0x64, 0x61, 0x79, 0xd83c, 0xdf6e, 0x3a, 0x66, 0x6c, 0x61, 0x6e, - 0x3a, 0x66, 0x6c, 0x61, 0x6e, 0xd83c, 0xdf6e, 0x3a, 0x70, 0x75, 0x64, 0x64, - 0x69, 0x6e, 0x67, 0x3a, 0x70, 0x75, 0x64, 0x64, 0x69, 0x6e, 0x67, 0xd83c, - 0xdf6e, 0x3a, 0x63, 0x75, 0x73, 0x74, 0x61, 0x72, 0x64, 0x3a, 0x63, 0x75, - 0x73, 0x74, 0x61, 0x72, 0x64, 0xd83c, 0xdf6d, 0x3a, 0x6c, 0x6f, 0x6c, 0x6c, - 0x69, 0x70, 0x6f, 0x70, 0x3a, 0x6c, 0x6f, 0x6c, 0x6c, 0x69, 0x70, 0x6f, - 0x70, 0xd83c, 0xdf6c, 0x3a, 0x63, 0x61, 0x6e, 0x64, 0x79, 0x3a, 0x63, 0x61, - 0x6e, 0x64, 0x79, 0xd83c, 0xdf6b, 0x3a, 0x63, 0x68, 0x6f, 0x63, 0x6f, 0x6c, - 0x61, 0x74, 0x65, 0x5f, 0x62, 0x61, 0x72, 0x3a, 0x62, 0x61, 0x72, 0x63, - 0x68, 0x6f, 0x63, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0xd83c, 0xdf7f, 0x3a, 0x70, - 0x6f, 0x70, 0x63, 0x6f, 0x72, 0x6e, 0x3a, 0x70, 0x6f, 0x70, 0x63, 0x6f, - 0x72, 0x6e, 0xd83c, 0xdf69, 0x3a, 0x64, 0x6f, 0x75, 0x67, 0x68, 0x6e, 0x75, - 0x74, 0x3a, 0x64, 0x6f, 0x75, 0x67, 0x68, 0x6e, 0x75, 0x74, 0xd83c, 0xdf6a, - 0x3a, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x3a, 0x63, 0x6f, 0x6f, 0x6b, - 0x69, 0x65, 0xd83c, 0xdf30, 0x3a, 0x63, 0x68, 0x65, 0x73, 0x74, 0x6e, 0x75, - 0x74, 0x3a, 0x63, 0x68, 0x65, 0x73, 0x74, 0x6e, 0x75, 0x74, 0xd83e, 0xdd5c, - 0x3a, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x5f, 0x70, 0x65, 0x61, - 0x6e, 0x75, 0x74, 0x3a, 0x70, 0x65, 0x61, 0x6e, 0x75, 0x74, 0x73, 0x68, - 0x65, 0x6c, 0x6c, 0x65, 0x64, 0xd83e, 0xdd5c, 0x3a, 0x70, 0x65, 0x61, 0x6e, - 0x75, 0x74, 0x73, 0x3a, 0x70, 0x65, 0x61, 0x6e, 0x75, 0x74, 0x73, 0xd83c, - 0xdf6f, 0x3a, 0x68, 0x6f, 0x6e, 0x65, 0x79, 0x5f, 0x70, 0x6f, 0x74, 0x3a, - 0x68, 0x6f, 0x6e, 0x65, 0x79, 0x70, 0x6f, 0x74, 0xd83e, 0xdd5b, 0x3a, 0x67, - 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x6d, 0x69, 0x6c, 0x6b, - 0x3a, 0x67, 0x6c, 0x61, 0x73, 0x73, 0x6d, 0x69, 0x6c, 0x6b, 0x6f, 0x66, - 0xd83e, 0xdd5b, 0x3a, 0x6d, 0x69, 0x6c, 0x6b, 0x3a, 0x6d, 0x69, 0x6c, 0x6b, - 0xd83c, 0xdf7c, 0x3a, 0x62, 0x61, 0x62, 0x79, 0x5f, 0x62, 0x6f, 0x74, 0x74, - 0x6c, 0x65, 0x3a, 0x62, 0x61, 0x62, 0x79, 0x62, 0x6f, 0x74, 0x74, 0x6c, - 0x65, 0x2615, 0xfe0f, 0x3a, 0x63, 0x6f, 0x66, 0x66, 0x65, 0x65, 0x3a, 0x63, - 0x6f, 0x66, 0x66, 0x65, 0x65, 0xd83c, 0xdf75, 0x3a, 0x74, 0x65, 0x61, 0x3a, - 0x74, 0x65, 0x61, 0xd83e, 0xdd64, 0x3a, 0x63, 0x75, 0x70, 0x5f, 0x77, 0x69, - 0x74, 0x68, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x77, 0x3a, 0x63, 0x75, 0x70, - 0x73, 0x74, 0x72, 0x61, 0x77, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdf76, 0x3a, - 0x73, 0x61, 0x6b, 0x65, 0x3a, 0x73, 0x61, 0x6b, 0x65, 0xd83c, 0xdf7a, 0x3a, - 0x62, 0x65, 0x65, 0x72, 0x3a, 0x62, 0x65, 0x65, 0x72, 0xd83c, 0xdf7b, 0x3a, - 0x62, 0x65, 0x65, 0x72, 0x73, 0x3a, 0x62, 0x65, 0x65, 0x72, 0x73, 0xd83e, - 0xdd42, 0x3a, 0x63, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x5f, 0x67, - 0x6c, 0x61, 0x73, 0x73, 0x3a, 0x63, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, - 0x67, 0x67, 0x6c, 0x61, 0x73, 0x73, 0xd83e, 0xdd42, 0x3a, 0x63, 0x68, 0x61, - 0x6d, 0x70, 0x61, 0x67, 0x6e, 0x65, 0x5f, 0x67, 0x6c, 0x61, 0x73, 0x73, - 0x3a, 0x63, 0x68, 0x61, 0x6d, 0x70, 0x61, 0x67, 0x6e, 0x65, 0x67, 0x6c, - 0x61, 0x73, 0x73, 0xd83c, 0xdf77, 0x3a, 0x77, 0x69, 0x6e, 0x65, 0x5f, 0x67, - 0x6c, 0x61, 0x73, 0x73, 0x3a, 0x67, 0x6c, 0x61, 0x73, 0x73, 0x77, 0x69, - 0x6e, 0x65, 0xd83e, 0xdd43, 0x3a, 0x77, 0x68, 0x69, 0x73, 0x6b, 0x79, 0x3a, - 0x77, 0x68, 0x69, 0x73, 0x6b, 0x79, 0xd83e, 0xdd43, 0x3a, 0x74, 0x75, 0x6d, - 0x62, 0x6c, 0x65, 0x72, 0x5f, 0x67, 0x6c, 0x61, 0x73, 0x73, 0x3a, 0x67, - 0x6c, 0x61, 0x73, 0x73, 0x74, 0x75, 0x6d, 0x62, 0x6c, 0x65, 0x72, 0xd83c, - 0xdf78, 0x3a, 0x63, 0x6f, 0x63, 0x6b, 0x74, 0x61, 0x69, 0x6c, 0x3a, 0x63, - 0x6f, 0x63, 0x6b, 0x74, 0x61, 0x69, 0x6c, 0xd83c, 0xdf79, 0x3a, 0x74, 0x72, - 0x6f, 0x70, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x64, 0x72, 0x69, 0x6e, 0x6b, - 0x3a, 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x74, 0x72, 0x6f, 0x70, 0x69, 0x63, - 0x61, 0x6c, 0xd83c, 0xdf7e, 0x3a, 0x62, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x5f, - 0x77, 0x69, 0x74, 0x68, 0x5f, 0x70, 0x6f, 0x70, 0x70, 0x69, 0x6e, 0x67, - 0x5f, 0x63, 0x6f, 0x72, 0x6b, 0x3a, 0x62, 0x6f, 0x74, 0x74, 0x6c, 0x65, - 0x63, 0x6f, 0x72, 0x6b, 0x70, 0x6f, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x77, - 0x69, 0x74, 0x68, 0xd83c, 0xdf7e, 0x3a, 0x63, 0x68, 0x61, 0x6d, 0x70, 0x61, - 0x67, 0x6e, 0x65, 0x3a, 0x63, 0x68, 0x61, 0x6d, 0x70, 0x61, 0x67, 0x6e, - 0x65, 0xd83e, 0xdd44, 0x3a, 0x73, 0x70, 0x6f, 0x6f, 0x6e, 0x3a, 0x73, 0x70, - 0x6f, 0x6f, 0x6e, 0xd83c, 0xdf74, 0x3a, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x61, - 0x6e, 0x64, 0x5f, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x3a, 0x61, 0x6e, 0x64, - 0x66, 0x6f, 0x72, 0x6b, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0xd83c, 0xdf7d, 0x3a, - 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x6b, 0x6e, 0x69, - 0x66, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x70, 0x6c, 0x61, 0x74, - 0x65, 0x3a, 0x61, 0x6e, 0x64, 0x66, 0x6f, 0x72, 0x6b, 0x6b, 0x6e, 0x69, - 0x66, 0x65, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x77, 0x69, 0x74, 0x68, 0xd83c, - 0xdf7d, 0x3a, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x6b, 0x6e, 0x69, 0x66, 0x65, - 0x5f, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3a, 0x66, 0x6f, 0x72, 0x6b, 0x6b, - 0x6e, 0x69, 0x66, 0x65, 0x70, 0x6c, 0x61, 0x74, 0x65, 0xd83e, 0xdd63, 0x3a, - 0x62, 0x6f, 0x77, 0x6c, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x73, 0x70, - 0x6f, 0x6f, 0x6e, 0x3a, 0x62, 0x6f, 0x77, 0x6c, 0x73, 0x70, 0x6f, 0x6f, - 0x6e, 0x77, 0x69, 0x74, 0x68, 0xd83e, 0xdd61, 0x3a, 0x74, 0x61, 0x6b, 0x65, - 0x6f, 0x75, 0x74, 0x5f, 0x62, 0x6f, 0x78, 0x3a, 0x62, 0x6f, 0x78, 0x74, - 0x61, 0x6b, 0x65, 0x6f, 0x75, 0x74, 0xd83e, 0xdd62, 0x3a, 0x63, 0x68, 0x6f, - 0x70, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x73, 0x3a, 0x63, 0x68, 0x6f, 0x70, - 0x73, 0x74, 0x69, 0x63, 0x6b, 0x73, 0x26bd, 0xfe0f, 0x3a, 0x73, 0x6f, 0x63, - 0x63, 0x65, 0x72, 0x3a, 0x73, 0x6f, 0x63, 0x63, 0x65, 0x72, 0xd83c, 0xdfc0, - 0x3a, 0x62, 0x61, 0x73, 0x6b, 0x65, 0x74, 0x62, 0x61, 0x6c, 0x6c, 0x3a, - 0x62, 0x61, 0x73, 0x6b, 0x65, 0x74, 0x62, 0x61, 0x6c, 0x6c, 0xd83c, 0xdfc8, - 0x3a, 0x66, 0x6f, 0x6f, 0x74, 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x66, 0x6f, - 0x6f, 0x74, 0x62, 0x61, 0x6c, 0x6c, 0x26be, 0xfe0f, 0x3a, 0x62, 0x61, 0x73, - 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x62, 0x61, 0x73, 0x65, 0x62, 0x61, - 0x6c, 0x6c, 0xd83c, 0xdfbe, 0x3a, 0x74, 0x65, 0x6e, 0x6e, 0x69, 0x73, 0x3a, - 0x74, 0x65, 0x6e, 0x6e, 0x69, 0x73, 0xd83c, 0xdfd0, 0x3a, 0x76, 0x6f, 0x6c, - 0x6c, 0x65, 0x79, 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x76, 0x6f, 0x6c, 0x6c, - 0x65, 0x79, 0x62, 0x61, 0x6c, 0x6c, 0xd83c, 0xdfc9, 0x3a, 0x72, 0x75, 0x67, - 0x62, 0x79, 0x5f, 0x66, 0x6f, 0x6f, 0x74, 0x62, 0x61, 0x6c, 0x6c, 0x3a, - 0x66, 0x6f, 0x6f, 0x74, 0x62, 0x61, 0x6c, 0x6c, 0x72, 0x75, 0x67, 0x62, - 0x79, 0xd83c, 0xdfb1, 0x3a, 0x38, 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x38, 0x62, - 0x61, 0x6c, 0x6c, 0xd83c, 0xdfd3, 0x3a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, - 0x74, 0x65, 0x6e, 0x6e, 0x69, 0x73, 0x3a, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x74, 0x65, 0x6e, 0x6e, 0x69, 0x73, 0xd83c, 0xdfd3, 0x3a, 0x70, 0x69, 0x6e, - 0x67, 0x5f, 0x70, 0x6f, 0x6e, 0x67, 0x3a, 0x70, 0x69, 0x6e, 0x67, 0x70, - 0x6f, 0x6e, 0x67, 0xd83c, 0xdff8, 0x3a, 0x62, 0x61, 0x64, 0x6d, 0x69, 0x6e, - 0x74, 0x6f, 0x6e, 0x3a, 0x62, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x74, 0x6f, - 0x6e, 0xd83c, 0xdfd2, 0x3a, 0x68, 0x6f, 0x63, 0x6b, 0x65, 0x79, 0x3a, 0x68, - 0x6f, 0x63, 0x6b, 0x65, 0x79, 0xd83c, 0xdfd1, 0x3a, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x5f, 0x68, 0x6f, 0x63, 0x6b, 0x65, 0x79, 0x3a, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x68, 0x6f, 0x63, 0x6b, 0x65, 0x79, 0xd83c, 0xdfcf, 0x3a, 0x63, - 0x72, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x62, 0x61, 0x74, 0x5f, 0x62, - 0x61, 0x6c, 0x6c, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x74, 0x63, - 0x72, 0x69, 0x63, 0x6b, 0x65, 0x74, 0xd83c, 0xdfcf, 0x3a, 0x63, 0x72, 0x69, - 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x67, 0x61, 0x6d, 0x65, 0x3a, 0x63, 0x72, - 0x69, 0x63, 0x6b, 0x65, 0x74, 0x67, 0x61, 0x6d, 0x65, 0xd83e, 0xdd45, 0x3a, - 0x67, 0x6f, 0x61, 0x6c, 0x5f, 0x6e, 0x65, 0x74, 0x3a, 0x67, 0x6f, 0x61, - 0x6c, 0x6e, 0x65, 0x74, 0xd83e, 0xdd45, 0x3a, 0x67, 0x6f, 0x61, 0x6c, 0x3a, - 0x67, 0x6f, 0x61, 0x6c, 0x26f3, 0xfe0f, 0x3a, 0x67, 0x6f, 0x6c, 0x66, 0x3a, - 0x67, 0x6f, 0x6c, 0x66, 0xd83c, 0xdff9, 0x3a, 0x61, 0x72, 0x63, 0x68, 0x65, - 0x72, 0x79, 0x3a, 0x61, 0x72, 0x63, 0x68, 0x65, 0x72, 0x79, 0xd83c, 0xdff9, - 0x3a, 0x62, 0x6f, 0x77, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x61, 0x72, 0x72, - 0x6f, 0x77, 0x3a, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x62, - 0x6f, 0x77, 0xd83c, 0xdfa3, 0x3a, 0x66, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, - 0x5f, 0x70, 0x6f, 0x6c, 0x65, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x66, 0x69, - 0x73, 0x68, 0x3a, 0x61, 0x6e, 0x64, 0x66, 0x69, 0x73, 0x68, 0x66, 0x69, - 0x73, 0x68, 0x69, 0x6e, 0x67, 0x70, 0x6f, 0x6c, 0x65, 0xd83e, 0xdd4a, 0x3a, - 0x62, 0x6f, 0x78, 0x69, 0x6e, 0x67, 0x5f, 0x67, 0x6c, 0x6f, 0x76, 0x65, - 0x73, 0x3a, 0x62, 0x6f, 0x78, 0x69, 0x6e, 0x67, 0x67, 0x6c, 0x6f, 0x76, - 0x65, 0x73, 0xd83e, 0xdd4a, 0x3a, 0x62, 0x6f, 0x78, 0x69, 0x6e, 0x67, 0x5f, - 0x67, 0x6c, 0x6f, 0x76, 0x65, 0x3a, 0x62, 0x6f, 0x78, 0x69, 0x6e, 0x67, - 0x67, 0x6c, 0x6f, 0x76, 0x65, 0xd83e, 0xdd4b, 0x3a, 0x6b, 0x61, 0x72, 0x61, - 0x74, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x6b, - 0x61, 0x72, 0x61, 0x74, 0x65, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, - 0xd83e, 0xdd4b, 0x3a, 0x6d, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x61, - 0x72, 0x74, 0x73, 0x5f, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x3a, - 0x61, 0x72, 0x74, 0x73, 0x6d, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x75, - 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0xd83c, 0xdfbd, 0x3a, 0x72, 0x75, 0x6e, - 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x68, 0x69, 0x72, 0x74, 0x5f, 0x77, - 0x69, 0x74, 0x68, 0x5f, 0x73, 0x61, 0x73, 0x68, 0x3a, 0x72, 0x75, 0x6e, - 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x61, 0x73, 0x68, 0x73, 0x68, 0x69, 0x72, - 0x74, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdef7, 0x3a, 0x73, 0x6c, 0x65, 0x64, - 0x3a, 0x73, 0x6c, 0x65, 0x64, 0x26f8, 0x3a, 0x69, 0x63, 0x65, 0x5f, 0x73, - 0x6b, 0x61, 0x74, 0x65, 0x3a, 0x69, 0x63, 0x65, 0x73, 0x6b, 0x61, 0x74, - 0x65, 0xd83e, 0xdd4c, 0x3a, 0x63, 0x75, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x5f, - 0x73, 0x74, 0x6f, 0x6e, 0x65, 0x3a, 0x63, 0x75, 0x72, 0x6c, 0x69, 0x6e, - 0x67, 0x73, 0x74, 0x6f, 0x6e, 0x65, 0xd83c, 0xdfbf, 0x3a, 0x73, 0x6b, 0x69, - 0x3a, 0x73, 0x6b, 0x69, 0x26f7, 0x3a, 0x73, 0x6b, 0x69, 0x65, 0x72, 0x3a, - 0x73, 0x6b, 0x69, 0x65, 0x72, 0xd83c, 0xdfc2, 0x3a, 0x73, 0x6e, 0x6f, 0x77, - 0x62, 0x6f, 0x61, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x73, 0x6e, 0x6f, 0x77, - 0x62, 0x6f, 0x61, 0x72, 0x64, 0x65, 0x72, 0xd83c, 0xdfcb, 0xfe0f, 0x200d, 0x2640, - 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x6c, 0x69, 0x66, 0x74, - 0x69, 0x6e, 0x67, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x3a, - 0x6c, 0x69, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x77, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x73, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83c, 0xdfcb, 0xfe0f, 0x200d, 0x2642, - 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x6c, 0x69, 0x66, 0x74, 0x69, 0x6e, - 0x67, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x3a, 0x6c, 0x69, - 0x66, 0x74, 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0x77, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x73, 0xd83c, 0xdfcb, 0xfe0f, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x77, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x5f, 0x6c, 0x69, 0x66, 0x74, 0x65, 0x72, 0x3a, - 0x6c, 0x69, 0x66, 0x74, 0x65, 0x72, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, - 0xd83c, 0xdfcb, 0xfe0f, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6c, 0x69, 0x66, 0x74, 0x65, - 0x72, 0x3a, 0x6c, 0x69, 0x66, 0x74, 0x65, 0x72, 0xd83c, 0xdfcb, 0xfe0f, 0x200d, - 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x6c, 0x69, - 0x66, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x73, 0x3a, 0x6c, 0x69, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x70, 0x65, 0x72, - 0x73, 0x6f, 0x6e, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0xd83e, 0xdd3c, - 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x5f, 0x77, 0x72, - 0x65, 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0x3a, 0x77, 0x6f, 0x6d, 0x65, - 0x6e, 0x77, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0xd83e, 0xdd3c, - 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x65, 0x6e, 0x5f, 0x77, 0x72, 0x65, 0x73, - 0x74, 0x6c, 0x69, 0x6e, 0x67, 0x3a, 0x6d, 0x65, 0x6e, 0x77, 0x72, 0x65, - 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0xd83e, 0xdd3c, 0x200d, 0x2642, 0xfe0f, 0x3a, - 0x77, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0x3a, 0x77, 0x72, - 0x65, 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0xd83e, 0xdd3c, 0x200d, 0x2642, 0xfe0f, - 0x3a, 0x77, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x65, 0x72, 0x73, 0x3a, 0x77, - 0x72, 0x65, 0x73, 0x74, 0x6c, 0x65, 0x72, 0x73, 0xd83e, 0xdd3c, 0x200d, 0x2642, - 0xfe0f, 0x3a, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x5f, 0x77, 0x72, 0x65, - 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0x3a, 0x70, 0x65, 0x6f, 0x70, 0x6c, - 0x65, 0x77, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0xd83e, 0xdd38, - 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x63, 0x61, - 0x72, 0x74, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x69, 0x6e, 0x67, 0x3a, 0x63, - 0x61, 0x72, 0x74, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x69, 0x6e, 0x67, 0x77, - 0x6f, 0x6d, 0x61, 0x6e, 0xd83e, 0xdd38, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, - 0x6e, 0x5f, 0x63, 0x61, 0x72, 0x74, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x69, - 0x6e, 0x67, 0x3a, 0x63, 0x61, 0x72, 0x74, 0x77, 0x68, 0x65, 0x65, 0x6c, - 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0xd83e, 0xdd38, 0x200d, 0x2642, 0xfe0f, 0x3a, - 0x63, 0x61, 0x72, 0x74, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x3a, 0x63, 0x61, - 0x72, 0x74, 0x77, 0x68, 0x65, 0x65, 0x6c, 0xd83e, 0xdd38, 0x200d, 0x2642, 0xfe0f, - 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x64, 0x6f, 0x69, 0x6e, - 0x67, 0x5f, 0x63, 0x61, 0x72, 0x74, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x3a, - 0x63, 0x61, 0x72, 0x74, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x64, 0x6f, 0x69, - 0x6e, 0x67, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x26f9, 0xfe0f, 0x200d, 0x2640, - 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x62, 0x6f, 0x75, 0x6e, - 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x62, 0x61, - 0x6c, 0x6c, 0x62, 0x6f, 0x75, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x77, 0x6f, - 0x6d, 0x61, 0x6e, 0x26f9, 0xfe0f, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, - 0x5f, 0x62, 0x6f, 0x75, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x61, - 0x6c, 0x6c, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x62, 0x6f, 0x75, 0x6e, 0x63, - 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0x26f9, 0xfe0f, 0x200d, 0x2642, 0xfe0f, 0x3a, - 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, - 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x70, 0x65, 0x72, - 0x73, 0x6f, 0x6e, 0x77, 0x69, 0x74, 0x68, 0x26f9, 0xfe0f, 0x200d, 0x2642, 0xfe0f, - 0x3a, 0x62, 0x61, 0x73, 0x6b, 0x65, 0x74, 0x62, 0x61, 0x6c, 0x6c, 0x5f, - 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x3a, 0x62, 0x61, 0x73, 0x6b, 0x65, - 0x74, 0x62, 0x61, 0x6c, 0x6c, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x26f9, - 0xfe0f, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, - 0x62, 0x6f, 0x75, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x61, 0x6c, - 0x6c, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x62, 0x6f, 0x75, 0x6e, 0x63, 0x69, - 0x6e, 0x67, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83e, 0xdd3a, 0x3a, 0x66, - 0x65, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x3a, 0x66, 0x65, 0x6e, 0x63, 0x69, - 0x6e, 0x67, 0xd83e, 0xdd3a, 0x3a, 0x66, 0x65, 0x6e, 0x63, 0x65, 0x72, 0x3a, - 0x66, 0x65, 0x6e, 0x63, 0x65, 0x72, 0xd83e, 0xdd3a, 0x3a, 0x70, 0x65, 0x72, - 0x73, 0x6f, 0x6e, 0x5f, 0x66, 0x65, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x3a, - 0x66, 0x65, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x70, 0x65, 0x72, 0x73, 0x6f, - 0x6e, 0xd83e, 0xdd3e, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, - 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x6e, - 0x64, 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x62, 0x61, - 0x6c, 0x6c, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0xd83e, 0xdd3e, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x68, 0x61, 0x6e, 0x64, - 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x62, 0x61, 0x6c, - 0x6c, 0xd83e, 0xdd3e, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, - 0x6e, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, - 0x6e, 0x64, 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x62, - 0x61, 0x6c, 0x6c, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x70, 0x6c, 0x61, - 0x79, 0x69, 0x6e, 0x67, 0xd83e, 0xdd3e, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, - 0x6e, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, - 0x6e, 0x64, 0x62, 0x61, 0x6c, 0x6c, 0x3a, 0x68, 0x61, 0x6e, 0x64, 0x62, - 0x61, 0x6c, 0x6c, 0x6d, 0x61, 0x6e, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, - 0x67, 0xd83c, 0xdfcc, 0xfe0f, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, - 0x6e, 0x5f, 0x67, 0x6f, 0x6c, 0x66, 0x69, 0x6e, 0x67, 0x3a, 0x67, 0x6f, - 0x6c, 0x66, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83c, 0xdfcc, - 0xfe0f, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x67, 0x6f, 0x6c, - 0x66, 0x69, 0x6e, 0x67, 0x3a, 0x67, 0x6f, 0x6c, 0x66, 0x69, 0x6e, 0x67, - 0x6d, 0x61, 0x6e, 0xd83c, 0xdfcc, 0xfe0f, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x67, 0x6f, - 0x6c, 0x66, 0x65, 0x72, 0x3a, 0x67, 0x6f, 0x6c, 0x66, 0x65, 0x72, 0xd83c, - 0xdfcc, 0xfe0f, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, - 0x5f, 0x67, 0x6f, 0x6c, 0x66, 0x69, 0x6e, 0x67, 0x3a, 0x67, 0x6f, 0x6c, - 0x66, 0x69, 0x6e, 0x67, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83c, 0xdfc7, - 0x3a, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x5f, 0x72, 0x61, 0x63, 0x69, 0x6e, - 0x67, 0x3a, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x72, 0x61, 0x63, 0x69, 0x6e, - 0x67, 0xd83e, 0xddd8, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, - 0x5f, 0x69, 0x6e, 0x5f, 0x6c, 0x6f, 0x74, 0x75, 0x73, 0x5f, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x69, 0x6e, 0x6c, 0x6f, 0x74, - 0x75, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x77, 0x6f, - 0x6d, 0x61, 0x6e, 0xd83e, 0xddd8, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, - 0x73, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x5f, 0x6c, 0x6f, 0x74, 0x75, 0x73, - 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x69, 0x6e, - 0x6c, 0x6f, 0x74, 0x75, 0x73, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0xd83e, 0xddd8, 0x200d, 0x2642, 0xfe0f, - 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x69, 0x6e, 0x5f, 0x6c, 0x6f, 0x74, 0x75, - 0x73, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x69, - 0x6e, 0x6c, 0x6f, 0x74, 0x75, 0x73, 0x6d, 0x61, 0x6e, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0xd83c, 0xdfc4, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, - 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x73, 0x75, 0x72, 0x66, 0x69, 0x6e, 0x67, - 0x3a, 0x73, 0x75, 0x72, 0x66, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, - 0x6e, 0xd83c, 0xdfc4, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x73, - 0x75, 0x72, 0x66, 0x69, 0x6e, 0x67, 0x3a, 0x6d, 0x61, 0x6e, 0x73, 0x75, - 0x72, 0x66, 0x69, 0x6e, 0x67, 0xd83c, 0xdfc4, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x73, - 0x75, 0x72, 0x66, 0x65, 0x72, 0x3a, 0x73, 0x75, 0x72, 0x66, 0x65, 0x72, - 0xd83c, 0xdfc4, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, - 0x5f, 0x73, 0x75, 0x72, 0x66, 0x69, 0x6e, 0x67, 0x3a, 0x70, 0x65, 0x72, - 0x73, 0x6f, 0x6e, 0x73, 0x75, 0x72, 0x66, 0x69, 0x6e, 0x67, 0xd83c, 0xdfca, - 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x73, 0x77, - 0x69, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x3a, 0x73, 0x77, 0x69, 0x6d, 0x6d, - 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83c, 0xdfca, 0x200d, 0x2642, - 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x73, 0x77, 0x69, 0x6d, 0x6d, 0x69, - 0x6e, 0x67, 0x3a, 0x6d, 0x61, 0x6e, 0x73, 0x77, 0x69, 0x6d, 0x6d, 0x69, - 0x6e, 0x67, 0xd83c, 0xdfca, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x73, 0x77, 0x69, 0x6d, - 0x6d, 0x65, 0x72, 0x3a, 0x73, 0x77, 0x69, 0x6d, 0x6d, 0x65, 0x72, 0xd83c, - 0xdfca, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, - 0x73, 0x77, 0x69, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x3a, 0x70, 0x65, 0x72, - 0x73, 0x6f, 0x6e, 0x73, 0x77, 0x69, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0xd83e, - 0xdd3d, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x70, - 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x77, 0x61, 0x74, 0x65, 0x72, - 0x5f, 0x70, 0x6f, 0x6c, 0x6f, 0x3a, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, - 0x67, 0x70, 0x6f, 0x6c, 0x6f, 0x77, 0x61, 0x74, 0x65, 0x72, 0x77, 0x6f, - 0x6d, 0x61, 0x6e, 0xd83e, 0xdd3d, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, - 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x77, 0x61, 0x74, - 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x6f, 0x3a, 0x6d, 0x61, 0x6e, 0x70, - 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x70, 0x6f, 0x6c, 0x6f, 0x77, 0x61, - 0x74, 0x65, 0x72, 0xd83e, 0xdd3d, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x77, 0x61, 0x74, - 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x6f, 0x3a, 0x70, 0x6f, 0x6c, 0x6f, - 0x77, 0x61, 0x74, 0x65, 0x72, 0xd83e, 0xdd3d, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, - 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, - 0x67, 0x5f, 0x77, 0x61, 0x74, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x6c, 0x6f, - 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x70, 0x6c, 0x61, 0x79, 0x69, - 0x6e, 0x67, 0x70, 0x6f, 0x6c, 0x6f, 0x77, 0x61, 0x74, 0x65, 0x72, 0xd83d, - 0xdea3, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x72, - 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x6f, 0x61, 0x74, 0x3a, 0x62, - 0x6f, 0x61, 0x74, 0x72, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0xd83d, 0xdea3, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, - 0x72, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x6f, 0x61, 0x74, 0x3a, - 0x62, 0x6f, 0x61, 0x74, 0x6d, 0x61, 0x6e, 0x72, 0x6f, 0x77, 0x69, 0x6e, - 0x67, 0xd83d, 0xdea3, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x72, 0x6f, 0x77, 0x62, 0x6f, - 0x61, 0x74, 0x3a, 0x72, 0x6f, 0x77, 0x62, 0x6f, 0x61, 0x74, 0xd83d, 0xdea3, - 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x72, - 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x6f, 0x61, 0x74, 0x3a, 0x62, - 0x6f, 0x61, 0x74, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x72, 0x6f, 0x77, - 0x69, 0x6e, 0x67, 0xd83e, 0xddd7, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0x5f, 0x63, 0x6c, 0x69, 0x6d, 0x62, 0x69, 0x6e, 0x67, 0x3a, - 0x63, 0x6c, 0x69, 0x6d, 0x62, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, - 0x6e, 0xd83e, 0xddd7, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, - 0x6e, 0x5f, 0x63, 0x6c, 0x69, 0x6d, 0x62, 0x69, 0x6e, 0x67, 0x3a, 0x63, - 0x6c, 0x69, 0x6d, 0x62, 0x69, 0x6e, 0x67, 0x70, 0x65, 0x72, 0x73, 0x6f, - 0x6e, 0xd83e, 0xddd7, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x63, - 0x6c, 0x69, 0x6d, 0x62, 0x69, 0x6e, 0x67, 0x3a, 0x63, 0x6c, 0x69, 0x6d, - 0x62, 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0xd83d, 0xdeb5, 0x200d, 0x2640, 0xfe0f, - 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x5f, 0x62, 0x69, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x62, - 0x69, 0x6b, 0x69, 0x6e, 0x67, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0xd83d, 0xdeb5, 0x200d, 0x2642, 0xfe0f, 0x3a, - 0x6d, 0x61, 0x6e, 0x5f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x5f, 0x62, 0x69, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x69, 0x6b, 0x69, - 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0xd83d, 0xdeb5, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x5f, 0x62, 0x69, 0x63, 0x79, 0x63, 0x6c, 0x69, 0x73, - 0x74, 0x3a, 0x62, 0x69, 0x63, 0x79, 0x63, 0x6c, 0x69, 0x73, 0x74, 0x6d, - 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0xd83d, 0xdeb5, 0x200d, 0x2642, 0xfe0f, - 0x3a, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x5f, 0x62, 0x69, 0x6b, 0x69, 0x6e, 0x67, 0x3a, - 0x62, 0x69, 0x6b, 0x69, 0x6e, 0x67, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0xd83d, 0xdeb4, 0x200d, 0x2640, - 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x5f, 0x62, 0x69, 0x6b, 0x69, - 0x6e, 0x67, 0x3a, 0x62, 0x69, 0x6b, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0xd83d, 0xdeb4, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, - 0x62, 0x69, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x69, 0x6b, 0x69, 0x6e, - 0x67, 0x6d, 0x61, 0x6e, 0xd83d, 0xdeb4, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x62, 0x69, - 0x63, 0x79, 0x63, 0x6c, 0x69, 0x73, 0x74, 0x3a, 0x62, 0x69, 0x63, 0x79, - 0x63, 0x6c, 0x69, 0x73, 0x74, 0xd83d, 0xdeb4, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, - 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5f, 0x62, 0x69, 0x6b, 0x69, 0x6e, 0x67, - 0x3a, 0x62, 0x69, 0x6b, 0x69, 0x6e, 0x67, 0x70, 0x65, 0x72, 0x73, 0x6f, - 0x6e, 0xd83c, 0xdfc6, 0x3a, 0x74, 0x72, 0x6f, 0x70, 0x68, 0x79, 0x3a, 0x74, - 0x72, 0x6f, 0x70, 0x68, 0x79, 0xd83e, 0xdd47, 0x3a, 0x66, 0x69, 0x72, 0x73, - 0x74, 0x5f, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x64, 0x61, - 0x6c, 0x3a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x6d, 0x65, 0x64, 0x61, 0x6c, - 0x70, 0x6c, 0x61, 0x63, 0x65, 0xd83e, 0xdd47, 0x3a, 0x66, 0x69, 0x72, 0x73, - 0x74, 0x5f, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x3a, 0x66, 0x69, 0x72, 0x73, - 0x74, 0x70, 0x6c, 0x61, 0x63, 0x65, 0xd83e, 0xdd48, 0x3a, 0x73, 0x65, 0x63, - 0x6f, 0x6e, 0x64, 0x5f, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x6d, 0x65, - 0x64, 0x61, 0x6c, 0x3a, 0x6d, 0x65, 0x64, 0x61, 0x6c, 0x70, 0x6c, 0x61, - 0x63, 0x65, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0xd83e, 0xdd48, 0x3a, 0x73, - 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x5f, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x3a, - 0x70, 0x6c, 0x61, 0x63, 0x65, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0xd83e, - 0xdd49, 0x3a, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x6c, 0x61, 0x63, - 0x65, 0x5f, 0x6d, 0x65, 0x64, 0x61, 0x6c, 0x3a, 0x6d, 0x65, 0x64, 0x61, - 0x6c, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x74, 0x68, 0x69, 0x72, 0x64, 0xd83e, - 0xdd49, 0x3a, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x6c, 0x61, 0x63, - 0x65, 0x3a, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x74, 0x68, 0x69, 0x72, 0x64, - 0xd83c, 0xdfc5, 0x3a, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x5f, 0x6d, 0x65, - 0x64, 0x61, 0x6c, 0x3a, 0x6d, 0x65, 0x64, 0x61, 0x6c, 0x73, 0x70, 0x6f, - 0x72, 0x74, 0x73, 0xd83c, 0xdfc5, 0x3a, 0x6d, 0x65, 0x64, 0x61, 0x6c, 0x3a, - 0x6d, 0x65, 0x64, 0x61, 0x6c, 0xd83c, 0xdf96, 0x3a, 0x6d, 0x69, 0x6c, 0x69, - 0x74, 0x61, 0x72, 0x79, 0x5f, 0x6d, 0x65, 0x64, 0x61, 0x6c, 0x3a, 0x6d, - 0x65, 0x64, 0x61, 0x6c, 0x6d, 0x69, 0x6c, 0x69, 0x74, 0x61, 0x72, 0x79, - 0xd83c, 0xdff5, 0x3a, 0x72, 0x6f, 0x73, 0x65, 0x74, 0x74, 0x65, 0x3a, 0x72, - 0x6f, 0x73, 0x65, 0x74, 0x74, 0x65, 0xd83c, 0xdf97, 0x3a, 0x72, 0x65, 0x6d, - 0x69, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x72, 0x69, 0x62, 0x62, 0x6f, 0x6e, - 0x3a, 0x72, 0x65, 0x6d, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x72, 0x69, 0x62, - 0x62, 0x6f, 0x6e, 0xd83c, 0xdfab, 0x3a, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, - 0x3a, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0xd83c, 0xdf9f, 0x3a, 0x61, 0x64, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x63, 0x6b, - 0x65, 0x74, 0x73, 0x3a, 0x61, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x73, 0xd83c, 0xdf9f, 0x3a, 0x74, - 0x69, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x3a, 0x74, 0x69, 0x63, 0x6b, 0x65, - 0x74, 0x73, 0xd83c, 0xdfaa, 0x3a, 0x63, 0x69, 0x72, 0x63, 0x75, 0x73, 0x5f, - 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x63, 0x69, 0x72, 0x63, 0x75, 0x73, 0x74, - 0x65, 0x6e, 0x74, 0xd83e, 0xdd39, 0x200d, 0x2640, 0xfe0f, 0x3a, 0x77, 0x6f, 0x6d, - 0x61, 0x6e, 0x5f, 0x6a, 0x75, 0x67, 0x67, 0x6c, 0x69, 0x6e, 0x67, 0x3a, - 0x6a, 0x75, 0x67, 0x67, 0x6c, 0x69, 0x6e, 0x67, 0x77, 0x6f, 0x6d, 0x61, - 0x6e, 0xd83e, 0xdd39, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6d, 0x61, 0x6e, 0x5f, 0x6a, - 0x75, 0x67, 0x67, 0x6c, 0x69, 0x6e, 0x67, 0x3a, 0x6a, 0x75, 0x67, 0x67, - 0x6c, 0x69, 0x6e, 0x67, 0x6d, 0x61, 0x6e, 0xd83e, 0xdd39, 0x200d, 0x2642, 0xfe0f, - 0x3a, 0x6a, 0x75, 0x67, 0x67, 0x6c, 0x65, 0x72, 0x3a, 0x6a, 0x75, 0x67, - 0x67, 0x6c, 0x65, 0x72, 0xd83e, 0xdd39, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x6a, 0x75, - 0x67, 0x67, 0x6c, 0x69, 0x6e, 0x67, 0x3a, 0x6a, 0x75, 0x67, 0x67, 0x6c, - 0x69, 0x6e, 0x67, 0xd83e, 0xdd39, 0x200d, 0x2642, 0xfe0f, 0x3a, 0x70, 0x65, 0x72, - 0x73, 0x6f, 0x6e, 0x5f, 0x6a, 0x75, 0x67, 0x67, 0x6c, 0x69, 0x6e, 0x67, - 0x3a, 0x6a, 0x75, 0x67, 0x67, 0x6c, 0x69, 0x6e, 0x67, 0x70, 0x65, 0x72, - 0x73, 0x6f, 0x6e, 0xd83c, 0xdfad, 0x3a, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, - 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x73, 0x3a, 0x61, 0x72, - 0x74, 0x73, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x69, 0x6e, 0x67, - 0xd83c, 0xdfa8, 0x3a, 0x61, 0x72, 0x74, 0x3a, 0x61, 0x72, 0x74, 0xd83c, 0xdfac, - 0x3a, 0x63, 0x6c, 0x61, 0x70, 0x70, 0x65, 0x72, 0x3a, 0x63, 0x6c, 0x61, - 0x70, 0x70, 0x65, 0x72, 0xd83c, 0xdfa4, 0x3a, 0x6d, 0x69, 0x63, 0x72, 0x6f, - 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x3a, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x70, - 0x68, 0x6f, 0x6e, 0x65, 0xd83c, 0xdfa7, 0x3a, 0x68, 0x65, 0x61, 0x64, 0x70, - 0x68, 0x6f, 0x6e, 0x65, 0x73, 0x3a, 0x68, 0x65, 0x61, 0x64, 0x70, 0x68, - 0x6f, 0x6e, 0x65, 0x73, 0xd83c, 0xdfbc, 0x3a, 0x6d, 0x75, 0x73, 0x69, 0x63, - 0x61, 0x6c, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x3a, 0x6d, 0x75, 0x73, - 0x69, 0x63, 0x61, 0x6c, 0x73, 0x63, 0x6f, 0x72, 0x65, 0xd83c, 0xdfb9, 0x3a, - 0x6d, 0x75, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x6b, 0x65, 0x79, 0x62, - 0x6f, 0x61, 0x72, 0x64, 0x3a, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, - 0x64, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x61, 0x6c, 0xd83e, 0xdd41, 0x3a, 0x64, - 0x72, 0x75, 0x6d, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x64, 0x72, 0x75, - 0x6d, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x73, 0x3a, 0x64, 0x72, 0x75, 0x6d, - 0x64, 0x72, 0x75, 0x6d, 0x73, 0x74, 0x69, 0x63, 0x6b, 0x73, 0x77, 0x69, - 0x74, 0x68, 0xd83e, 0xdd41, 0x3a, 0x64, 0x72, 0x75, 0x6d, 0x3a, 0x64, 0x72, - 0x75, 0x6d, 0xd83c, 0xdfb7, 0x3a, 0x73, 0x61, 0x78, 0x6f, 0x70, 0x68, 0x6f, - 0x6e, 0x65, 0x3a, 0x73, 0x61, 0x78, 0x6f, 0x70, 0x68, 0x6f, 0x6e, 0x65, - 0xd83c, 0xdfba, 0x3a, 0x74, 0x72, 0x75, 0x6d, 0x70, 0x65, 0x74, 0x3a, 0x74, - 0x72, 0x75, 0x6d, 0x70, 0x65, 0x74, 0xd83c, 0xdfb8, 0x3a, 0x67, 0x75, 0x69, - 0x74, 0x61, 0x72, 0x3a, 0x67, 0x75, 0x69, 0x74, 0x61, 0x72, 0xd83c, 0xdfbb, - 0x3a, 0x76, 0x69, 0x6f, 0x6c, 0x69, 0x6e, 0x3a, 0x76, 0x69, 0x6f, 0x6c, - 0x69, 0x6e, 0xd83c, 0xdfb2, 0x3a, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x64, 0x69, - 0x65, 0x3a, 0x64, 0x69, 0x65, 0x67, 0x61, 0x6d, 0x65, 0xd83c, 0xdfaf, 0x3a, - 0x64, 0x61, 0x72, 0x74, 0x3a, 0x64, 0x61, 0x72, 0x74, 0xd83c, 0xdfb3, 0x3a, - 0x62, 0x6f, 0x77, 0x6c, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x6f, 0x77, 0x6c, - 0x69, 0x6e, 0x67, 0xd83c, 0xdfae, 0x3a, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x5f, - 0x67, 0x61, 0x6d, 0x65, 0x3a, 0x67, 0x61, 0x6d, 0x65, 0x76, 0x69, 0x64, - 0x65, 0x6f, 0xd83c, 0xdfb0, 0x3a, 0x73, 0x6c, 0x6f, 0x74, 0x5f, 0x6d, 0x61, - 0x63, 0x68, 0x69, 0x6e, 0x65, 0x3a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, - 0x65, 0x73, 0x6c, 0x6f, 0x74, 0xd83d, 0xde97, 0x3a, 0x72, 0x65, 0x64, 0x5f, - 0x63, 0x61, 0x72, 0x3a, 0x63, 0x61, 0x72, 0x72, 0x65, 0x64, 0xd83d, 0xde95, - 0x3a, 0x74, 0x61, 0x78, 0x69, 0x3a, 0x74, 0x61, 0x78, 0x69, 0xd83d, 0xde99, - 0x3a, 0x62, 0x6c, 0x75, 0x65, 0x5f, 0x63, 0x61, 0x72, 0x3a, 0x62, 0x6c, - 0x75, 0x65, 0x63, 0x61, 0x72, 0xd83d, 0xde8c, 0x3a, 0x62, 0x75, 0x73, 0x3a, - 0x62, 0x75, 0x73, 0xd83d, 0xde8e, 0x3a, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, - 0x79, 0x62, 0x75, 0x73, 0x3a, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x79, - 0x62, 0x75, 0x73, 0xd83c, 0xdfce, 0x3a, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, - 0x5f, 0x63, 0x61, 0x72, 0x3a, 0x63, 0x61, 0x72, 0x72, 0x61, 0x63, 0x69, - 0x6e, 0x67, 0xd83c, 0xdfce, 0x3a, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x63, 0x61, - 0x72, 0x3a, 0x63, 0x61, 0x72, 0x72, 0x61, 0x63, 0x65, 0xd83d, 0xde93, 0x3a, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x61, 0x72, 0x3a, 0x63, - 0x61, 0x72, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x65, 0xd83d, 0xde91, 0x3a, 0x61, - 0x6d, 0x62, 0x75, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x3a, 0x61, 0x6d, 0x62, - 0x75, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0xd83d, 0xde92, 0x3a, 0x66, 0x69, 0x72, - 0x65, 0x5f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x3a, 0x65, 0x6e, 0x67, - 0x69, 0x6e, 0x65, 0x66, 0x69, 0x72, 0x65, 0xd83d, 0xde90, 0x3a, 0x6d, 0x69, - 0x6e, 0x69, 0x62, 0x75, 0x73, 0x3a, 0x6d, 0x69, 0x6e, 0x69, 0x62, 0x75, - 0x73, 0xd83d, 0xde9a, 0x3a, 0x74, 0x72, 0x75, 0x63, 0x6b, 0x3a, 0x74, 0x72, - 0x75, 0x63, 0x6b, 0xd83d, 0xde9b, 0x3a, 0x61, 0x72, 0x74, 0x69, 0x63, 0x75, - 0x6c, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6c, 0x6f, 0x72, 0x72, 0x79, 0x3a, - 0x61, 0x72, 0x74, 0x69, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x6c, - 0x6f, 0x72, 0x72, 0x79, 0xd83d, 0xde9c, 0x3a, 0x74, 0x72, 0x61, 0x63, 0x74, - 0x6f, 0x72, 0x3a, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6f, 0x72, 0xd83d, 0xdef4, - 0x3a, 0x73, 0x63, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x3a, 0x73, 0x63, 0x6f, - 0x6f, 0x74, 0x65, 0x72, 0xd83d, 0xdeb2, 0x3a, 0x62, 0x69, 0x6b, 0x65, 0x3a, - 0x62, 0x69, 0x6b, 0x65, 0xd83d, 0xdef5, 0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, - 0x62, 0x69, 0x6b, 0x65, 0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x62, 0x69, - 0x6b, 0x65, 0xd83d, 0xdef5, 0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x5f, 0x73, - 0x63, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, - 0x73, 0x63, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0xd83c, 0xdfcd, 0x3a, 0x72, 0x61, - 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x63, 0x79, - 0x63, 0x6c, 0x65, 0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x63, 0x79, 0x63, - 0x6c, 0x65, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0xd83c, 0xdfcd, 0x3a, 0x6d, - 0x6f, 0x74, 0x6f, 0x72, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x3a, 0x6d, 0x6f, - 0x74, 0x6f, 0x72, 0x63, 0x79, 0x63, 0x6c, 0x65, 0xd83d, 0xdea8, 0x3a, 0x72, - 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x69, 0x67, 0x68, - 0x74, 0x3a, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x72, 0x6f, 0x74, 0x61, 0x74, - 0x69, 0x6e, 0x67, 0xd83d, 0xde94, 0x3a, 0x6f, 0x6e, 0x63, 0x6f, 0x6d, 0x69, - 0x6e, 0x67, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x61, - 0x72, 0x3a, 0x63, 0x61, 0x72, 0x6f, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, - 0x67, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x65, 0xd83d, 0xde8d, 0x3a, 0x6f, 0x6e, - 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x73, 0x3a, 0x62, - 0x75, 0x73, 0x6f, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0xd83d, 0xde98, - 0x3a, 0x6f, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x75, - 0x74, 0x6f, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x3a, 0x61, 0x75, 0x74, - 0x6f, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6f, 0x6e, 0x63, 0x6f, 0x6d, - 0x69, 0x6e, 0x67, 0xd83d, 0xde96, 0x3a, 0x6f, 0x6e, 0x63, 0x6f, 0x6d, 0x69, - 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x78, 0x69, 0x3a, 0x6f, 0x6e, 0x63, 0x6f, - 0x6d, 0x69, 0x6e, 0x67, 0x74, 0x61, 0x78, 0x69, 0xd83d, 0xdea1, 0x3a, 0x61, - 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x74, 0x72, 0x61, 0x6d, 0x77, 0x61, - 0x79, 0x3a, 0x61, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x74, 0x72, 0x61, 0x6d, - 0x77, 0x61, 0x79, 0xd83d, 0xdea0, 0x3a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x5f, 0x63, 0x61, 0x62, 0x6c, 0x65, 0x77, 0x61, 0x79, 0x3a, - 0x63, 0x61, 0x62, 0x6c, 0x65, 0x77, 0x61, 0x79, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0xd83d, 0xde9f, 0x3a, 0x73, 0x75, 0x73, 0x70, 0x65, - 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61, 0x69, 0x6c, 0x77, 0x61, - 0x79, 0x3a, 0x72, 0x61, 0x69, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x75, 0x73, - 0x70, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0xd83d, 0xde83, 0x3a, 0x72, 0x61, - 0x69, 0x6c, 0x77, 0x61, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x3a, 0x63, 0x61, - 0x72, 0x72, 0x61, 0x69, 0x6c, 0x77, 0x61, 0x79, 0xd83d, 0xde8b, 0x3a, 0x74, - 0x72, 0x61, 0x69, 0x6e, 0x3a, 0x74, 0x72, 0x61, 0x69, 0x6e, 0xd83d, 0xde9e, - 0x3a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x5f, 0x72, 0x61, - 0x69, 0x6c, 0x77, 0x61, 0x79, 0x3a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x72, 0x61, 0x69, 0x6c, 0x77, 0x61, 0x79, 0xd83d, 0xde9d, 0x3a, - 0x6d, 0x6f, 0x6e, 0x6f, 0x72, 0x61, 0x69, 0x6c, 0x3a, 0x6d, 0x6f, 0x6e, - 0x6f, 0x72, 0x61, 0x69, 0x6c, 0xd83d, 0xde84, 0x3a, 0x62, 0x75, 0x6c, 0x6c, - 0x65, 0x74, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x64, 0x65, - 0x3a, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x74, 0x72, 0x61, 0x69, 0x6e, - 0x73, 0x69, 0x64, 0x65, 0xd83d, 0xde85, 0x3a, 0x62, 0x75, 0x6c, 0x6c, 0x65, - 0x74, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, - 0x3a, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x74, 0x72, 0x61, 0x69, 0x6e, - 0x66, 0x72, 0x6f, 0x6e, 0x74, 0xd83d, 0xde88, 0x3a, 0x6c, 0x69, 0x67, 0x68, - 0x74, 0x5f, 0x72, 0x61, 0x69, 0x6c, 0x3a, 0x6c, 0x69, 0x67, 0x68, 0x74, - 0x72, 0x61, 0x69, 0x6c, 0xd83d, 0xde82, 0x3a, 0x73, 0x74, 0x65, 0x61, 0x6d, - 0x5f, 0x6c, 0x6f, 0x63, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x76, 0x65, 0x3a, - 0x6c, 0x6f, 0x63, 0x6f, 0x6d, 0x6f, 0x74, 0x69, 0x76, 0x65, 0x73, 0x74, - 0x65, 0x61, 0x6d, 0xd83d, 0xde86, 0x3a, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x32, - 0x3a, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x32, 0xd83d, 0xde87, 0x3a, 0x6d, 0x65, - 0x74, 0x72, 0x6f, 0x3a, 0x6d, 0x65, 0x74, 0x72, 0x6f, 0xd83d, 0xde8a, 0x3a, - 0x74, 0x72, 0x61, 0x6d, 0x3a, 0x74, 0x72, 0x61, 0x6d, 0xd83d, 0xde89, 0x3a, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2708, 0xfe0f, 0x3a, 0x61, 0x69, 0x72, 0x70, 0x6c, 0x61, - 0x6e, 0x65, 0x3a, 0x61, 0x69, 0x72, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0xd83d, - 0xdeeb, 0x3a, 0x61, 0x69, 0x72, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x5f, 0x64, - 0x65, 0x70, 0x61, 0x72, 0x74, 0x75, 0x72, 0x65, 0x3a, 0x61, 0x69, 0x72, - 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x75, - 0x72, 0x65, 0xd83d, 0xdeec, 0x3a, 0x61, 0x69, 0x72, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x5f, 0x61, 0x72, 0x72, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x3a, 0x61, - 0x69, 0x72, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x61, 0x72, 0x72, 0x69, 0x76, - 0x69, 0x6e, 0x67, 0xd83d, 0xdee9, 0x3a, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, - 0x61, 0x69, 0x72, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x3a, 0x61, 0x69, 0x72, - 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0xd83d, 0xdee9, - 0x3a, 0x61, 0x69, 0x72, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x5f, 0x73, 0x6d, - 0x61, 0x6c, 0x6c, 0x3a, 0x61, 0x69, 0x72, 0x70, 0x6c, 0x61, 0x6e, 0x65, - 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0xd83d, 0xdcba, 0x3a, 0x73, 0x65, 0x61, 0x74, - 0x3a, 0x73, 0x65, 0x61, 0x74, 0xd83d, 0xdef0, 0x3a, 0x73, 0x61, 0x74, 0x65, - 0x6c, 0x6c, 0x69, 0x74, 0x65, 0x5f, 0x6f, 0x72, 0x62, 0x69, 0x74, 0x61, - 0x6c, 0x3a, 0x6f, 0x72, 0x62, 0x69, 0x74, 0x61, 0x6c, 0x73, 0x61, 0x74, - 0x65, 0x6c, 0x6c, 0x69, 0x74, 0x65, 0xd83d, 0xde80, 0x3a, 0x72, 0x6f, 0x63, - 0x6b, 0x65, 0x74, 0x3a, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0xd83d, 0xdef8, - 0x3a, 0x66, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x61, 0x75, 0x63, - 0x65, 0x72, 0x3a, 0x66, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x73, 0x61, 0x75, - 0x63, 0x65, 0x72, 0xd83d, 0xde81, 0x3a, 0x68, 0x65, 0x6c, 0x69, 0x63, 0x6f, - 0x70, 0x74, 0x65, 0x72, 0x3a, 0x68, 0x65, 0x6c, 0x69, 0x63, 0x6f, 0x70, - 0x74, 0x65, 0x72, 0xd83d, 0xdef6, 0x3a, 0x6b, 0x61, 0x79, 0x61, 0x6b, 0x3a, - 0x6b, 0x61, 0x79, 0x61, 0x6b, 0xd83d, 0xdef6, 0x3a, 0x63, 0x61, 0x6e, 0x6f, - 0x65, 0x3a, 0x63, 0x61, 0x6e, 0x6f, 0x65, 0x26f5, 0xfe0f, 0x3a, 0x73, 0x61, - 0x69, 0x6c, 0x62, 0x6f, 0x61, 0x74, 0x3a, 0x73, 0x61, 0x69, 0x6c, 0x62, - 0x6f, 0x61, 0x74, 0xd83d, 0xdea4, 0x3a, 0x73, 0x70, 0x65, 0x65, 0x64, 0x62, - 0x6f, 0x61, 0x74, 0x3a, 0x73, 0x70, 0x65, 0x65, 0x64, 0x62, 0x6f, 0x61, - 0x74, 0xd83d, 0xdee5, 0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x62, 0x6f, 0x61, - 0x74, 0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x62, 0x6f, 0x61, 0x74, 0xd83d, - 0xdef3, 0x3a, 0x70, 0x61, 0x73, 0x73, 0x65, 0x6e, 0x67, 0x65, 0x72, 0x5f, - 0x73, 0x68, 0x69, 0x70, 0x3a, 0x70, 0x61, 0x73, 0x73, 0x65, 0x6e, 0x67, - 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0xd83d, 0xdef3, 0x3a, 0x63, 0x72, 0x75, - 0x69, 0x73, 0x65, 0x5f, 0x73, 0x68, 0x69, 0x70, 0x3a, 0x63, 0x72, 0x75, - 0x69, 0x73, 0x65, 0x73, 0x68, 0x69, 0x70, 0x26f4, 0x3a, 0x66, 0x65, 0x72, - 0x72, 0x79, 0x3a, 0x66, 0x65, 0x72, 0x72, 0x79, 0xd83d, 0xdea2, 0x3a, 0x73, - 0x68, 0x69, 0x70, 0x3a, 0x73, 0x68, 0x69, 0x70, 0x2693, 0xfe0f, 0x3a, 0x61, - 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x3a, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, - 0x26fd, 0xfe0f, 0x3a, 0x66, 0x75, 0x65, 0x6c, 0x70, 0x75, 0x6d, 0x70, 0x3a, - 0x66, 0x75, 0x65, 0x6c, 0x70, 0x75, 0x6d, 0x70, 0xd83d, 0xdea7, 0x3a, 0x63, - 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, - 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0xd83d, 0xdea6, 0x3a, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, - 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x6c, 0x69, 0x67, 0x68, - 0x74, 0x3a, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x74, 0x72, 0x61, 0x66, 0x66, - 0x69, 0x63, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0xd83d, 0xdea5, - 0x3a, 0x74, 0x72, 0x61, 0x66, 0x66, 0x69, 0x63, 0x5f, 0x6c, 0x69, 0x67, - 0x68, 0x74, 0x3a, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x74, 0x72, 0x61, 0x66, - 0x66, 0x69, 0x63, 0xd83d, 0xde8f, 0x3a, 0x62, 0x75, 0x73, 0x73, 0x74, 0x6f, - 0x70, 0x3a, 0x62, 0x75, 0x73, 0x73, 0x74, 0x6f, 0x70, 0xd83d, 0xddfa, 0x3a, - 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x70, 0x3a, 0x6d, 0x61, - 0x70, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0xd83d, 0xddfa, 0x3a, 0x6d, 0x61, 0x70, - 0x3a, 0x6d, 0x61, 0x70, 0xd83d, 0xddff, 0x3a, 0x6d, 0x6f, 0x79, 0x61, 0x69, - 0x3a, 0x6d, 0x6f, 0x79, 0x61, 0x69, 0xd83d, 0xddfd, 0x3a, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x6c, 0x69, 0x62, 0x65, 0x72, - 0x74, 0x79, 0x3a, 0x6c, 0x69, 0x62, 0x65, 0x72, 0x74, 0x79, 0x6f, 0x66, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x65, 0xd83d, 0xddfc, 0x3a, 0x74, 0x6f, 0x6b, - 0x79, 0x6f, 0x5f, 0x74, 0x6f, 0x77, 0x65, 0x72, 0x3a, 0x74, 0x6f, 0x6b, - 0x79, 0x6f, 0x74, 0x6f, 0x77, 0x65, 0x72, 0xd83c, 0xdff0, 0x3a, 0x65, 0x75, - 0x72, 0x6f, 0x70, 0x65, 0x61, 0x6e, 0x5f, 0x63, 0x61, 0x73, 0x74, 0x6c, - 0x65, 0x3a, 0x63, 0x61, 0x73, 0x74, 0x6c, 0x65, 0x65, 0x75, 0x72, 0x6f, - 0x70, 0x65, 0x61, 0x6e, 0xd83c, 0xdfef, 0x3a, 0x6a, 0x61, 0x70, 0x61, 0x6e, - 0x65, 0x73, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x74, 0x6c, 0x65, 0x3a, 0x63, - 0x61, 0x73, 0x74, 0x6c, 0x65, 0x6a, 0x61, 0x70, 0x61, 0x6e, 0x65, 0x73, - 0x65, 0xd83c, 0xdfdf, 0x3a, 0x73, 0x74, 0x61, 0x64, 0x69, 0x75, 0x6d, 0x3a, - 0x73, 0x74, 0x61, 0x64, 0x69, 0x75, 0x6d, 0xd83c, 0xdfa1, 0x3a, 0x66, 0x65, - 0x72, 0x72, 0x69, 0x73, 0x5f, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x3a, 0x66, - 0x65, 0x72, 0x72, 0x69, 0x73, 0x77, 0x68, 0x65, 0x65, 0x6c, 0xd83c, 0xdfa2, - 0x3a, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x61, 0x73, - 0x74, 0x65, 0x72, 0x3a, 0x63, 0x6f, 0x61, 0x73, 0x74, 0x65, 0x72, 0x72, - 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0xd83c, 0xdfa0, 0x3a, 0x63, 0x61, 0x72, 0x6f, - 0x75, 0x73, 0x65, 0x6c, 0x5f, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x3a, 0x63, - 0x61, 0x72, 0x6f, 0x75, 0x73, 0x65, 0x6c, 0x68, 0x6f, 0x72, 0x73, 0x65, - 0x26f2, 0xfe0f, 0x3a, 0x66, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x3a, - 0x66, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x26f1, 0x3a, 0x75, 0x6d, - 0x62, 0x72, 0x65, 0x6c, 0x6c, 0x61, 0x5f, 0x6f, 0x6e, 0x5f, 0x67, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x6f, - 0x6e, 0x75, 0x6d, 0x62, 0x72, 0x65, 0x6c, 0x6c, 0x61, 0x26f1, 0x3a, 0x62, - 0x65, 0x61, 0x63, 0x68, 0x5f, 0x75, 0x6d, 0x62, 0x72, 0x65, 0x6c, 0x6c, - 0x61, 0x3a, 0x62, 0x65, 0x61, 0x63, 0x68, 0x75, 0x6d, 0x62, 0x72, 0x65, - 0x6c, 0x6c, 0x61, 0xd83c, 0xdfd6, 0x3a, 0x62, 0x65, 0x61, 0x63, 0x68, 0x5f, - 0x77, 0x69, 0x74, 0x68, 0x5f, 0x75, 0x6d, 0x62, 0x72, 0x65, 0x6c, 0x6c, - 0x61, 0x3a, 0x62, 0x65, 0x61, 0x63, 0x68, 0x75, 0x6d, 0x62, 0x72, 0x65, - 0x6c, 0x6c, 0x61, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdfd6, 0x3a, 0x62, 0x65, - 0x61, 0x63, 0x68, 0x3a, 0x62, 0x65, 0x61, 0x63, 0x68, 0xd83c, 0xdfdd, 0x3a, - 0x64, 0x65, 0x73, 0x65, 0x72, 0x74, 0x5f, 0x69, 0x73, 0x6c, 0x61, 0x6e, - 0x64, 0x3a, 0x64, 0x65, 0x73, 0x65, 0x72, 0x74, 0x69, 0x73, 0x6c, 0x61, - 0x6e, 0x64, 0xd83c, 0xdfdd, 0x3a, 0x69, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x3a, - 0x69, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0xd83c, 0xdfdc, 0x3a, 0x64, 0x65, 0x73, - 0x65, 0x72, 0x74, 0x3a, 0x64, 0x65, 0x73, 0x65, 0x72, 0x74, 0xd83c, 0xdf0b, - 0x3a, 0x76, 0x6f, 0x6c, 0x63, 0x61, 0x6e, 0x6f, 0x3a, 0x76, 0x6f, 0x6c, - 0x63, 0x61, 0x6e, 0x6f, 0x26f0, 0x3a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x3a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0xd83c, - 0xdfd4, 0x3a, 0x73, 0x6e, 0x6f, 0x77, 0x5f, 0x63, 0x61, 0x70, 0x70, 0x65, - 0x64, 0x5f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x3a, 0x63, - 0x61, 0x70, 0x70, 0x65, 0x64, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x73, 0x6e, 0x6f, 0x77, 0xd83c, 0xdfd4, 0x3a, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x6e, 0x6f, 0x77, 0x3a, 0x6d, 0x6f, - 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x6e, 0x6f, 0x77, 0xd83d, 0xddfb, - 0x3a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x66, 0x75, 0x6a, 0x69, 0x3a, - 0x66, 0x75, 0x6a, 0x69, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0xd83c, 0xdfd5, 0x3a, - 0x63, 0x61, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x3a, 0x63, 0x61, 0x6d, 0x70, - 0x69, 0x6e, 0x67, 0x26fa, 0xfe0f, 0x3a, 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x74, - 0x65, 0x6e, 0x74, 0xd83c, 0xdfe0, 0x3a, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x3a, - 0x68, 0x6f, 0x75, 0x73, 0x65, 0xd83c, 0xdfe1, 0x3a, 0x68, 0x6f, 0x75, 0x73, - 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x67, 0x61, 0x72, 0x64, 0x65, - 0x6e, 0x3a, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x68, 0x6f, 0x75, 0x73, - 0x65, 0x77, 0x69, 0x74, 0x68, 0xd83c, 0xdfd8, 0x3a, 0x68, 0x6f, 0x75, 0x73, - 0x65, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x3a, - 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x68, 0x6f, 0x75, - 0x73, 0x65, 0xd83c, 0xdfd8, 0x3a, 0x68, 0x6f, 0x6d, 0x65, 0x73, 0x3a, 0x68, - 0x6f, 0x6d, 0x65, 0x73, 0xd83c, 0xdfda, 0x3a, 0x64, 0x65, 0x72, 0x65, 0x6c, - 0x69, 0x63, 0x74, 0x5f, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x5f, 0x62, 0x75, - 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x75, 0x69, 0x6c, 0x64, - 0x69, 0x6e, 0x67, 0x64, 0x65, 0x72, 0x65, 0x6c, 0x69, 0x63, 0x74, 0x68, - 0x6f, 0x75, 0x73, 0x65, 0xd83c, 0xdfda, 0x3a, 0x68, 0x6f, 0x75, 0x73, 0x65, - 0x5f, 0x61, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x64, 0x3a, 0x61, - 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x64, 0x68, 0x6f, 0x75, 0x73, - 0x65, 0xd83c, 0xdfd7, 0x3a, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, - 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x3a, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x63, 0x6f, - 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0xd83c, 0xdfd7, - 0x3a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x73, 0x69, 0x74, 0x65, 0x3a, 0x63, 0x6f, 0x6e, 0x73, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x69, 0x74, 0x65, 0xd83c, - 0xdfed, 0x3a, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x3a, 0x66, 0x61, - 0x63, 0x74, 0x6f, 0x72, 0x79, 0xd83c, 0xdfe2, 0x3a, 0x6f, 0x66, 0x66, 0x69, - 0x63, 0x65, 0x3a, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0xd83c, 0xdfec, 0x3a, - 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x74, 0x6f, 0x72, 0x65, 0xd83c, 0xdfe3, 0x3a, 0x70, - 0x6f, 0x73, 0x74, 0x5f, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x3a, 0x6f, - 0x66, 0x66, 0x69, 0x63, 0x65, 0x70, 0x6f, 0x73, 0x74, 0xd83c, 0xdfe4, 0x3a, - 0x65, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x73, - 0x74, 0x5f, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x3a, 0x65, 0x75, 0x72, - 0x6f, 0x70, 0x65, 0x61, 0x6e, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x70, - 0x6f, 0x73, 0x74, 0xd83c, 0xdfe5, 0x3a, 0x68, 0x6f, 0x73, 0x70, 0x69, 0x74, - 0x61, 0x6c, 0x3a, 0x68, 0x6f, 0x73, 0x70, 0x69, 0x74, 0x61, 0x6c, 0xd83c, - 0xdfe6, 0x3a, 0x62, 0x61, 0x6e, 0x6b, 0x3a, 0x62, 0x61, 0x6e, 0x6b, 0xd83c, - 0xdfe8, 0x3a, 0x68, 0x6f, 0x74, 0x65, 0x6c, 0x3a, 0x68, 0x6f, 0x74, 0x65, - 0x6c, 0xd83c, 0xdfea, 0x3a, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x6e, 0x69, 0x65, - 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x63, 0x6f, - 0x6e, 0x76, 0x65, 0x6e, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, - 0x72, 0x65, 0xd83c, 0xdfeb, 0x3a, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x3a, - 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0xd83c, 0xdfe9, 0x3a, 0x6c, 0x6f, 0x76, - 0x65, 0x5f, 0x68, 0x6f, 0x74, 0x65, 0x6c, 0x3a, 0x68, 0x6f, 0x74, 0x65, - 0x6c, 0x6c, 0x6f, 0x76, 0x65, 0xd83d, 0xdc92, 0x3a, 0x77, 0x65, 0x64, 0x64, - 0x69, 0x6e, 0x67, 0x3a, 0x77, 0x65, 0x64, 0x64, 0x69, 0x6e, 0x67, 0xd83c, - 0xdfdb, 0x3a, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x5f, - 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x62, 0x75, 0x69, - 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x63, - 0x61, 0x6c, 0x26ea, 0xfe0f, 0x3a, 0x63, 0x68, 0x75, 0x72, 0x63, 0x68, 0x3a, - 0x63, 0x68, 0x75, 0x72, 0x63, 0x68, 0xd83d, 0xdd4c, 0x3a, 0x6d, 0x6f, 0x73, - 0x71, 0x75, 0x65, 0x3a, 0x6d, 0x6f, 0x73, 0x71, 0x75, 0x65, 0xd83d, 0xdd4d, - 0x3a, 0x73, 0x79, 0x6e, 0x61, 0x67, 0x6f, 0x67, 0x75, 0x65, 0x3a, 0x73, - 0x79, 0x6e, 0x61, 0x67, 0x6f, 0x67, 0x75, 0x65, 0xd83d, 0xdd4b, 0x3a, 0x6b, - 0x61, 0x61, 0x62, 0x61, 0x3a, 0x6b, 0x61, 0x61, 0x62, 0x61, 0x26e9, 0x3a, - 0x73, 0x68, 0x69, 0x6e, 0x74, 0x6f, 0x5f, 0x73, 0x68, 0x72, 0x69, 0x6e, - 0x65, 0x3a, 0x73, 0x68, 0x69, 0x6e, 0x74, 0x6f, 0x73, 0x68, 0x72, 0x69, - 0x6e, 0x65, 0xd83d, 0xdee4, 0x3a, 0x72, 0x61, 0x69, 0x6c, 0x72, 0x6f, 0x61, - 0x64, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x3a, 0x72, 0x61, 0x69, 0x6c, - 0x72, 0x6f, 0x61, 0x64, 0x74, 0x72, 0x61, 0x63, 0x6b, 0xd83d, 0xdee4, 0x3a, - 0x72, 0x61, 0x69, 0x6c, 0x77, 0x61, 0x79, 0x5f, 0x74, 0x72, 0x61, 0x63, - 0x6b, 0x3a, 0x72, 0x61, 0x69, 0x6c, 0x77, 0x61, 0x79, 0x74, 0x72, 0x61, - 0x63, 0x6b, 0xd83d, 0xdee3, 0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x77, 0x61, - 0x79, 0x3a, 0x6d, 0x6f, 0x74, 0x6f, 0x72, 0x77, 0x61, 0x79, 0xd83d, 0xddfe, - 0x3a, 0x6a, 0x61, 0x70, 0x61, 0x6e, 0x3a, 0x6a, 0x61, 0x70, 0x61, 0x6e, - 0xd83c, 0xdf91, 0x3a, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x73, 0x63, 0x65, 0x6e, - 0x65, 0x3a, 0x72, 0x69, 0x63, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x65, 0xd83c, - 0xdfde, 0x3a, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x70, - 0x61, 0x72, 0x6b, 0x3a, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, - 0x70, 0x61, 0x72, 0x6b, 0xd83c, 0xdfde, 0x3a, 0x70, 0x61, 0x72, 0x6b, 0x3a, - 0x70, 0x61, 0x72, 0x6b, 0xd83c, 0xdf05, 0x3a, 0x73, 0x75, 0x6e, 0x72, 0x69, - 0x73, 0x65, 0x3a, 0x73, 0x75, 0x6e, 0x72, 0x69, 0x73, 0x65, 0xd83c, 0xdf04, - 0x3a, 0x73, 0x75, 0x6e, 0x72, 0x69, 0x73, 0x65, 0x5f, 0x6f, 0x76, 0x65, - 0x72, 0x5f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x3a, - 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x6f, 0x76, 0x65, - 0x72, 0x73, 0x75, 0x6e, 0x72, 0x69, 0x73, 0x65, 0xd83c, 0xdf20, 0x3a, 0x73, - 0x74, 0x61, 0x72, 0x73, 0x3a, 0x73, 0x74, 0x61, 0x72, 0x73, 0xd83c, 0xdf87, - 0x3a, 0x73, 0x70, 0x61, 0x72, 0x6b, 0x6c, 0x65, 0x72, 0x3a, 0x73, 0x70, - 0x61, 0x72, 0x6b, 0x6c, 0x65, 0x72, 0xd83c, 0xdf86, 0x3a, 0x66, 0x69, 0x72, - 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x3a, 0x66, 0x69, 0x72, 0x65, 0x77, - 0x6f, 0x72, 0x6b, 0x73, 0xd83c, 0xdf07, 0x3a, 0x63, 0x69, 0x74, 0x79, 0x5f, - 0x73, 0x75, 0x6e, 0x72, 0x69, 0x73, 0x65, 0x3a, 0x63, 0x69, 0x74, 0x79, - 0x73, 0x75, 0x6e, 0x72, 0x69, 0x73, 0x65, 0xd83c, 0xdf07, 0x3a, 0x63, 0x69, - 0x74, 0x79, 0x5f, 0x73, 0x75, 0x6e, 0x73, 0x65, 0x74, 0x3a, 0x63, 0x69, - 0x74, 0x79, 0x73, 0x75, 0x6e, 0x73, 0x65, 0x74, 0xd83c, 0xdf06, 0x3a, 0x63, - 0x69, 0x74, 0x79, 0x5f, 0x64, 0x75, 0x73, 0x6b, 0x3a, 0x63, 0x69, 0x74, - 0x79, 0x64, 0x75, 0x73, 0x6b, 0xd83c, 0xdfd9, 0x3a, 0x63, 0x69, 0x74, 0x79, - 0x73, 0x63, 0x61, 0x70, 0x65, 0x3a, 0x63, 0x69, 0x74, 0x79, 0x73, 0x63, - 0x61, 0x70, 0x65, 0xd83c, 0xdf03, 0x3a, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x5f, - 0x77, 0x69, 0x74, 0x68, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x73, 0x3a, 0x6e, - 0x69, 0x67, 0x68, 0x74, 0x73, 0x74, 0x61, 0x72, 0x73, 0x77, 0x69, 0x74, - 0x68, 0xd83c, 0xdf0c, 0x3a, 0x6d, 0x69, 0x6c, 0x6b, 0x79, 0x5f, 0x77, 0x61, - 0x79, 0x3a, 0x6d, 0x69, 0x6c, 0x6b, 0x79, 0x77, 0x61, 0x79, 0xd83c, 0xdf09, - 0x3a, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x61, 0x74, 0x5f, 0x6e, - 0x69, 0x67, 0x68, 0x74, 0x3a, 0x61, 0x74, 0x62, 0x72, 0x69, 0x64, 0x67, - 0x65, 0x6e, 0x69, 0x67, 0x68, 0x74, 0xd83c, 0xdf01, 0x3a, 0x66, 0x6f, 0x67, - 0x67, 0x79, 0x3a, 0x66, 0x6f, 0x67, 0x67, 0x79, 0x231a, 0xfe0f, 0x3a, 0x77, - 0x61, 0x74, 0x63, 0x68, 0x3a, 0x77, 0x61, 0x74, 0x63, 0x68, 0xd83d, 0xdcf1, - 0x3a, 0x69, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x3a, 0x69, 0x70, 0x68, 0x6f, - 0x6e, 0x65, 0xd83d, 0xdcf2, 0x3a, 0x63, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x67, - 0x3a, 0x63, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0xd83d, 0xdcbb, 0x3a, 0x63, - 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x3a, 0x63, 0x6f, 0x6d, 0x70, - 0x75, 0x74, 0x65, 0x72, 0x2328, 0xfe0f, 0x3a, 0x6b, 0x65, 0x79, 0x62, 0x6f, - 0x61, 0x72, 0x64, 0x3a, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, - 0xd83d, 0xdda5, 0x3a, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x5f, 0x63, - 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x3a, 0x63, 0x6f, 0x6d, 0x70, - 0x75, 0x74, 0x65, 0x72, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0xd83d, - 0xdda5, 0x3a, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x3a, 0x64, 0x65, - 0x73, 0x6b, 0x74, 0x6f, 0x70, 0xd83d, 0xdda8, 0x3a, 0x70, 0x72, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x3a, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0xd83d, - 0xddb1, 0x3a, 0x74, 0x68, 0x72, 0x65, 0x65, 0x5f, 0x62, 0x75, 0x74, 0x74, - 0x6f, 0x6e, 0x5f, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x3a, 0x62, 0x75, 0x74, - 0x74, 0x6f, 0x6e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x74, 0x68, 0x72, 0x65, - 0x65, 0xd83d, 0xddb1, 0x3a, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x5f, 0x74, 0x68, - 0x72, 0x65, 0x65, 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x62, - 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x6d, 0x6f, 0x75, 0x73, 0x65, 0x74, 0x68, - 0x72, 0x65, 0x65, 0xd83d, 0xddb2, 0x3a, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x62, - 0x61, 0x6c, 0x6c, 0x3a, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x62, 0x61, 0x6c, - 0x6c, 0xd83d, 0xdd79, 0x3a, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, - 0x3a, 0x6a, 0x6f, 0x79, 0x73, 0x74, 0x69, 0x63, 0x6b, 0xd83d, 0xdddc, 0x3a, - 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3a, - 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0xd83d, - 0xdcbd, 0x3a, 0x6d, 0x69, 0x6e, 0x69, 0x64, 0x69, 0x73, 0x63, 0x3a, 0x6d, - 0x69, 0x6e, 0x69, 0x64, 0x69, 0x73, 0x63, 0xd83d, 0xdcbe, 0x3a, 0x66, 0x6c, - 0x6f, 0x70, 0x70, 0x79, 0x5f, 0x64, 0x69, 0x73, 0x6b, 0x3a, 0x64, 0x69, - 0x73, 0x6b, 0x66, 0x6c, 0x6f, 0x70, 0x70, 0x79, 0xd83d, 0xdcbf, 0x3a, 0x63, - 0x64, 0x3a, 0x63, 0x64, 0xd83d, 0xdcc0, 0x3a, 0x64, 0x76, 0x64, 0x3a, 0x64, - 0x76, 0x64, 0xd83d, 0xdcfc, 0x3a, 0x76, 0x68, 0x73, 0x3a, 0x76, 0x68, 0x73, - 0xd83d, 0xdcf7, 0x3a, 0x63, 0x61, 0x6d, 0x65, 0x72, 0x61, 0x3a, 0x63, 0x61, - 0x6d, 0x65, 0x72, 0x61, 0xd83d, 0xdcf8, 0x3a, 0x63, 0x61, 0x6d, 0x65, 0x72, - 0x61, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x66, 0x6c, 0x61, 0x73, 0x68, - 0x3a, 0x63, 0x61, 0x6d, 0x65, 0x72, 0x61, 0x66, 0x6c, 0x61, 0x73, 0x68, - 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdcf9, 0x3a, 0x76, 0x69, 0x64, 0x65, 0x6f, - 0x5f, 0x63, 0x61, 0x6d, 0x65, 0x72, 0x61, 0x3a, 0x63, 0x61, 0x6d, 0x65, - 0x72, 0x61, 0x76, 0x69, 0x64, 0x65, 0x6f, 0xd83c, 0xdfa5, 0x3a, 0x6d, 0x6f, - 0x76, 0x69, 0x65, 0x5f, 0x63, 0x61, 0x6d, 0x65, 0x72, 0x61, 0x3a, 0x63, - 0x61, 0x6d, 0x65, 0x72, 0x61, 0x6d, 0x6f, 0x76, 0x69, 0x65, 0xd83d, 0xdcfd, - 0x3a, 0x66, 0x69, 0x6c, 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x3a, 0x66, 0x69, 0x6c, 0x6d, 0x70, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0xd83d, 0xdcfd, 0x3a, 0x70, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x3a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0xd83c, 0xdf9e, 0x3a, 0x66, 0x69, 0x6c, 0x6d, 0x5f, 0x66, - 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3a, 0x66, 0x69, 0x6c, 0x6d, 0x66, 0x72, - 0x61, 0x6d, 0x65, 0x73, 0xd83d, 0xdcde, 0x3a, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x68, 0x6f, 0x6e, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, - 0x72, 0x3a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x260e, 0xfe0f, 0x3a, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x3a, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x68, 0x6f, 0x6e, 0x65, 0xd83d, 0xdcdf, 0x3a, 0x70, 0x61, 0x67, 0x65, - 0x72, 0x3a, 0x70, 0x61, 0x67, 0x65, 0x72, 0xd83d, 0xdce0, 0x3a, 0x66, 0x61, - 0x78, 0x3a, 0x66, 0x61, 0x78, 0xd83d, 0xdcfa, 0x3a, 0x74, 0x76, 0x3a, 0x74, - 0x76, 0xd83d, 0xdcfb, 0x3a, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x3a, 0x72, 0x61, - 0x64, 0x69, 0x6f, 0xd83c, 0xdf99, 0x3a, 0x73, 0x74, 0x75, 0x64, 0x69, 0x6f, - 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x3a, - 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x73, 0x74, - 0x75, 0x64, 0x69, 0x6f, 0xd83c, 0xdf99, 0x3a, 0x6d, 0x69, 0x63, 0x72, 0x6f, - 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x32, 0x3a, 0x6d, 0x69, 0x63, 0x72, 0x6f, - 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x32, 0xd83c, 0xdf9a, 0x3a, 0x6c, 0x65, 0x76, - 0x65, 0x6c, 0x5f, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x3a, 0x6c, 0x65, - 0x76, 0x65, 0x6c, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x72, 0xd83c, 0xdf9b, 0x3a, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x6b, 0x6e, 0x6f, 0x62, - 0x73, 0x3a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6b, 0x6e, 0x6f, - 0x62, 0x73, 0x23f1, 0x3a, 0x73, 0x74, 0x6f, 0x70, 0x77, 0x61, 0x74, 0x63, - 0x68, 0x3a, 0x73, 0x74, 0x6f, 0x70, 0x77, 0x61, 0x74, 0x63, 0x68, 0x23f2, - 0x3a, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x6f, 0x63, 0x6b, - 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x23f2, - 0x3a, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x3a, 0x74, 0x69, 0x6d, 0x65, 0x72, - 0x23f0, 0x3a, 0x61, 0x6c, 0x61, 0x72, 0x6d, 0x5f, 0x63, 0x6c, 0x6f, 0x63, - 0x6b, 0x3a, 0x61, 0x6c, 0x61, 0x72, 0x6d, 0x63, 0x6c, 0x6f, 0x63, 0x6b, - 0xd83d, 0xdd70, 0x3a, 0x6d, 0x61, 0x6e, 0x74, 0x6c, 0x65, 0x70, 0x69, 0x65, - 0x63, 0x65, 0x5f, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x3a, 0x63, 0x6c, 0x6f, - 0x63, 0x6b, 0x6d, 0x61, 0x6e, 0x74, 0x6c, 0x65, 0x70, 0x69, 0x65, 0x63, - 0x65, 0xd83d, 0xdd70, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x3a, 0x63, 0x6c, - 0x6f, 0x63, 0x6b, 0x231b, 0xfe0f, 0x3a, 0x68, 0x6f, 0x75, 0x72, 0x67, 0x6c, - 0x61, 0x73, 0x73, 0x3a, 0x68, 0x6f, 0x75, 0x72, 0x67, 0x6c, 0x61, 0x73, - 0x73, 0x23f3, 0x3a, 0x68, 0x6f, 0x75, 0x72, 0x67, 0x6c, 0x61, 0x73, 0x73, - 0x5f, 0x66, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x61, 0x6e, - 0x64, 0x3a, 0x66, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x68, 0x6f, 0x75, - 0x72, 0x67, 0x6c, 0x61, 0x73, 0x73, 0x73, 0x61, 0x6e, 0x64, 0xd83d, 0xdce1, - 0x3a, 0x73, 0x61, 0x74, 0x65, 0x6c, 0x6c, 0x69, 0x74, 0x65, 0x3a, 0x73, - 0x61, 0x74, 0x65, 0x6c, 0x6c, 0x69, 0x74, 0x65, 0xd83d, 0xdd0b, 0x3a, 0x62, - 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x3a, 0x62, 0x61, 0x74, 0x74, 0x65, - 0x72, 0x79, 0xd83d, 0xdd0c, 0x3a, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x69, - 0x63, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x3a, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x72, 0x69, 0x63, 0x70, 0x6c, 0x75, 0x67, 0xd83d, 0xdca1, 0x3a, 0x62, 0x75, - 0x6c, 0x62, 0x3a, 0x62, 0x75, 0x6c, 0x62, 0xd83d, 0xdd26, 0x3a, 0x66, 0x6c, - 0x61, 0x73, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x66, 0x6c, 0x61, - 0x73, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0xd83d, 0xdd6f, 0x3a, 0x63, 0x61, - 0x6e, 0x64, 0x6c, 0x65, 0x3a, 0x63, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0xd83d, - 0xdee2, 0x3a, 0x6f, 0x69, 0x6c, 0x5f, 0x64, 0x72, 0x75, 0x6d, 0x3a, 0x64, - 0x72, 0x75, 0x6d, 0x6f, 0x69, 0x6c, 0xd83d, 0xdee2, 0x3a, 0x6f, 0x69, 0x6c, - 0x3a, 0x6f, 0x69, 0x6c, 0xd83d, 0xdcb8, 0x3a, 0x6d, 0x6f, 0x6e, 0x65, 0x79, - 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x77, 0x69, 0x6e, 0x67, 0x73, 0x3a, - 0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x77, 0x69, 0x6e, 0x67, 0x73, 0x77, 0x69, - 0x74, 0x68, 0xd83d, 0xdcb5, 0x3a, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3a, - 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0xd83d, 0xdcb4, 0x3a, 0x79, 0x65, 0x6e, - 0x3a, 0x79, 0x65, 0x6e, 0xd83d, 0xdcb6, 0x3a, 0x65, 0x75, 0x72, 0x6f, 0x3a, - 0x65, 0x75, 0x72, 0x6f, 0xd83d, 0xdcb7, 0x3a, 0x70, 0x6f, 0x75, 0x6e, 0x64, - 0x3a, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0xd83d, 0xdcb0, 0x3a, 0x6d, 0x6f, 0x6e, - 0x65, 0x79, 0x62, 0x61, 0x67, 0x3a, 0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x62, - 0x61, 0x67, 0xd83d, 0xdcb3, 0x3a, 0x63, 0x72, 0x65, 0x64, 0x69, 0x74, 0x5f, - 0x63, 0x61, 0x72, 0x64, 0x3a, 0x63, 0x61, 0x72, 0x64, 0x63, 0x72, 0x65, - 0x64, 0x69, 0x74, 0xd83d, 0xdc8e, 0x3a, 0x67, 0x65, 0x6d, 0x3a, 0x67, 0x65, - 0x6d, 0x2696, 0xfe0f, 0x3a, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x73, 0x3a, 0x73, - 0x63, 0x61, 0x6c, 0x65, 0x73, 0xd83d, 0xdd27, 0x3a, 0x77, 0x72, 0x65, 0x6e, - 0x63, 0x68, 0x3a, 0x77, 0x72, 0x65, 0x6e, 0x63, 0x68, 0xd83d, 0xdd28, 0x3a, - 0x68, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x3a, 0x68, 0x61, 0x6d, 0x6d, 0x65, - 0x72, 0x2692, 0x3a, 0x68, 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x5f, 0x61, 0x6e, - 0x64, 0x5f, 0x70, 0x69, 0x63, 0x6b, 0x3a, 0x61, 0x6e, 0x64, 0x68, 0x61, - 0x6d, 0x6d, 0x65, 0x72, 0x70, 0x69, 0x63, 0x6b, 0x2692, 0x3a, 0x68, 0x61, - 0x6d, 0x6d, 0x65, 0x72, 0x5f, 0x70, 0x69, 0x63, 0x6b, 0x3a, 0x68, 0x61, - 0x6d, 0x6d, 0x65, 0x72, 0x70, 0x69, 0x63, 0x6b, 0xd83d, 0xdee0, 0x3a, 0x68, - 0x61, 0x6d, 0x6d, 0x65, 0x72, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x77, 0x72, - 0x65, 0x6e, 0x63, 0x68, 0x3a, 0x61, 0x6e, 0x64, 0x68, 0x61, 0x6d, 0x6d, - 0x65, 0x72, 0x77, 0x72, 0x65, 0x6e, 0x63, 0x68, 0xd83d, 0xdee0, 0x3a, 0x74, - 0x6f, 0x6f, 0x6c, 0x73, 0x3a, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x26cf, 0x3a, - 0x70, 0x69, 0x63, 0x6b, 0x3a, 0x70, 0x69, 0x63, 0x6b, 0xd83d, 0xdd29, 0x3a, - 0x6e, 0x75, 0x74, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x62, 0x6f, 0x6c, 0x74, - 0x3a, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x6c, 0x74, 0x6e, 0x75, 0x74, 0x2699, - 0xfe0f, 0x3a, 0x67, 0x65, 0x61, 0x72, 0x3a, 0x67, 0x65, 0x61, 0x72, 0x26d3, - 0x3a, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x3a, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x73, 0xd83d, 0xdd2b, 0x3a, 0x67, 0x75, 0x6e, 0x3a, 0x67, 0x75, 0x6e, - 0xd83d, 0xdca3, 0x3a, 0x62, 0x6f, 0x6d, 0x62, 0x3a, 0x62, 0x6f, 0x6d, 0x62, - 0xd83d, 0xdd2a, 0x3a, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x3a, 0x6b, 0x6e, 0x69, - 0x66, 0x65, 0xd83d, 0xdde1, 0x3a, 0x64, 0x61, 0x67, 0x67, 0x65, 0x72, 0x5f, - 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x3a, 0x64, 0x61, 0x67, 0x67, 0x65, 0x72, - 0x6b, 0x6e, 0x69, 0x66, 0x65, 0xd83d, 0xdde1, 0x3a, 0x64, 0x61, 0x67, 0x67, - 0x65, 0x72, 0x3a, 0x64, 0x61, 0x67, 0x67, 0x65, 0x72, 0x2694, 0xfe0f, 0x3a, - 0x63, 0x72, 0x6f, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x73, 0x77, 0x6f, 0x72, - 0x64, 0x73, 0x3a, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x65, 0x64, 0x73, 0x77, - 0x6f, 0x72, 0x64, 0x73, 0xd83d, 0xdee1, 0x3a, 0x73, 0x68, 0x69, 0x65, 0x6c, - 0x64, 0x3a, 0x73, 0x68, 0x69, 0x65, 0x6c, 0x64, 0xd83d, 0xdeac, 0x3a, 0x73, - 0x6d, 0x6f, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x73, 0x6d, 0x6f, 0x6b, 0x69, - 0x6e, 0x67, 0x26b0, 0xfe0f, 0x3a, 0x63, 0x6f, 0x66, 0x66, 0x69, 0x6e, 0x3a, - 0x63, 0x6f, 0x66, 0x66, 0x69, 0x6e, 0x26b1, 0xfe0f, 0x3a, 0x66, 0x75, 0x6e, - 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x75, 0x72, 0x6e, 0x3a, 0x66, 0x75, 0x6e, - 0x65, 0x72, 0x61, 0x6c, 0x75, 0x72, 0x6e, 0x26b1, 0xfe0f, 0x3a, 0x75, 0x72, - 0x6e, 0x3a, 0x75, 0x72, 0x6e, 0xd83c, 0xdffa, 0x3a, 0x61, 0x6d, 0x70, 0x68, - 0x6f, 0x72, 0x61, 0x3a, 0x61, 0x6d, 0x70, 0x68, 0x6f, 0x72, 0x61, 0xd83d, - 0xdd2e, 0x3a, 0x63, 0x72, 0x79, 0x73, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x61, - 0x6c, 0x6c, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x63, 0x72, 0x79, 0x73, 0x74, - 0x61, 0x6c, 0xd83d, 0xdcff, 0x3a, 0x70, 0x72, 0x61, 0x79, 0x65, 0x72, 0x5f, - 0x62, 0x65, 0x61, 0x64, 0x73, 0x3a, 0x62, 0x65, 0x61, 0x64, 0x73, 0x70, - 0x72, 0x61, 0x79, 0x65, 0x72, 0xd83d, 0xdc88, 0x3a, 0x62, 0x61, 0x72, 0x62, - 0x65, 0x72, 0x3a, 0x62, 0x61, 0x72, 0x62, 0x65, 0x72, 0x2697, 0xfe0f, 0x3a, - 0x61, 0x6c, 0x65, 0x6d, 0x62, 0x69, 0x63, 0x3a, 0x61, 0x6c, 0x65, 0x6d, - 0x62, 0x69, 0x63, 0xd83d, 0xdd2d, 0x3a, 0x74, 0x65, 0x6c, 0x65, 0x73, 0x63, - 0x6f, 0x70, 0x65, 0x3a, 0x74, 0x65, 0x6c, 0x65, 0x73, 0x63, 0x6f, 0x70, - 0x65, 0xd83d, 0xdd2c, 0x3a, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x63, 0x6f, - 0x70, 0x65, 0x3a, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x63, 0x6f, 0x70, - 0x65, 0xd83d, 0xdd73, 0x3a, 0x68, 0x6f, 0x6c, 0x65, 0x3a, 0x68, 0x6f, 0x6c, - 0x65, 0xd83d, 0xdc8a, 0x3a, 0x70, 0x69, 0x6c, 0x6c, 0x3a, 0x70, 0x69, 0x6c, - 0x6c, 0xd83d, 0xdc89, 0x3a, 0x73, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x65, 0x3a, - 0x73, 0x79, 0x72, 0x69, 0x6e, 0x67, 0x65, 0xd83c, 0xdf21, 0x3a, 0x74, 0x68, - 0x65, 0x72, 0x6d, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x3a, 0x74, 0x68, - 0x65, 0x72, 0x6d, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0xd83d, 0xdebd, 0x3a, - 0x74, 0x6f, 0x69, 0x6c, 0x65, 0x74, 0x3a, 0x74, 0x6f, 0x69, 0x6c, 0x65, - 0x74, 0xd83d, 0xdeb0, 0x3a, 0x70, 0x6f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, - 0x77, 0x61, 0x74, 0x65, 0x72, 0x3a, 0x70, 0x6f, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x77, 0x61, 0x74, 0x65, 0x72, 0xd83d, 0xdebf, 0x3a, 0x73, 0x68, 0x6f, - 0x77, 0x65, 0x72, 0x3a, 0x73, 0x68, 0x6f, 0x77, 0x65, 0x72, 0xd83d, 0xdec1, - 0x3a, 0x62, 0x61, 0x74, 0x68, 0x74, 0x75, 0x62, 0x3a, 0x62, 0x61, 0x74, - 0x68, 0x74, 0x75, 0x62, 0xd83d, 0xdec0, 0x3a, 0x62, 0x61, 0x74, 0x68, 0x3a, - 0x62, 0x61, 0x74, 0x68, 0xd83d, 0xdece, 0x3a, 0x62, 0x65, 0x6c, 0x6c, 0x68, - 0x6f, 0x70, 0x5f, 0x62, 0x65, 0x6c, 0x6c, 0x3a, 0x62, 0x65, 0x6c, 0x6c, - 0x62, 0x65, 0x6c, 0x6c, 0x68, 0x6f, 0x70, 0xd83d, 0xdece, 0x3a, 0x62, 0x65, - 0x6c, 0x6c, 0x68, 0x6f, 0x70, 0x3a, 0x62, 0x65, 0x6c, 0x6c, 0x68, 0x6f, - 0x70, 0xd83d, 0xdd11, 0x3a, 0x6b, 0x65, 0x79, 0x3a, 0x6b, 0x65, 0x79, 0xd83d, - 0xdddd, 0x3a, 0x6f, 0x6c, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x3a, 0x6b, 0x65, - 0x79, 0x6f, 0x6c, 0x64, 0xd83d, 0xdddd, 0x3a, 0x6b, 0x65, 0x79, 0x32, 0x3a, - 0x6b, 0x65, 0x79, 0x32, 0xd83d, 0xdeaa, 0x3a, 0x64, 0x6f, 0x6f, 0x72, 0x3a, - 0x64, 0x6f, 0x6f, 0x72, 0xd83d, 0xdecb, 0x3a, 0x63, 0x6f, 0x75, 0x63, 0x68, - 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x6c, 0x61, 0x6d, 0x70, 0x3a, 0x61, 0x6e, - 0x64, 0x63, 0x6f, 0x75, 0x63, 0x68, 0x6c, 0x61, 0x6d, 0x70, 0xd83d, 0xdecb, - 0x3a, 0x63, 0x6f, 0x75, 0x63, 0x68, 0x3a, 0x63, 0x6f, 0x75, 0x63, 0x68, - 0xd83d, 0xdecf, 0x3a, 0x62, 0x65, 0x64, 0x3a, 0x62, 0x65, 0x64, 0xd83d, 0xdecc, - 0x3a, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x63, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, - 0x61, 0x63, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x64, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0xd83d, 0xddbc, 0x3a, - 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x70, - 0x69, 0x63, 0x74, 0x75, 0x72, 0x65, 0x3a, 0x66, 0x72, 0x61, 0x6d, 0x65, - 0x70, 0x69, 0x63, 0x74, 0x75, 0x72, 0x65, 0x77, 0x69, 0x74, 0x68, 0xd83d, - 0xddbc, 0x3a, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x68, 0x6f, 0x74, - 0x6f, 0x3a, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x70, 0x68, 0x6f, 0x74, 0x6f, - 0xd83d, 0xdecd, 0x3a, 0x73, 0x68, 0x6f, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x5f, - 0x62, 0x61, 0x67, 0x73, 0x3a, 0x62, 0x61, 0x67, 0x73, 0x73, 0x68, 0x6f, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0xd83d, 0xded2, 0x3a, 0x73, 0x68, 0x6f, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x79, - 0x3a, 0x73, 0x68, 0x6f, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x74, 0x72, 0x6f, - 0x6c, 0x6c, 0x65, 0x79, 0xd83d, 0xded2, 0x3a, 0x73, 0x68, 0x6f, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x61, 0x72, 0x74, 0x3a, 0x63, 0x61, 0x72, - 0x74, 0x73, 0x68, 0x6f, 0x70, 0x70, 0x69, 0x6e, 0x67, 0xd83c, 0xdf81, 0x3a, - 0x67, 0x69, 0x66, 0x74, 0x3a, 0x67, 0x69, 0x66, 0x74, 0xd83c, 0xdf88, 0x3a, - 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x6f, 0x6e, 0x3a, 0x62, 0x61, 0x6c, 0x6c, - 0x6f, 0x6f, 0x6e, 0xd83c, 0xdf8f, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x73, 0xd83c, 0xdf80, 0x3a, 0x72, 0x69, 0x62, 0x62, - 0x6f, 0x6e, 0x3a, 0x72, 0x69, 0x62, 0x62, 0x6f, 0x6e, 0xd83c, 0xdf8a, 0x3a, - 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x74, 0x74, 0x69, 0x5f, 0x62, 0x61, 0x6c, - 0x6c, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x74, - 0x74, 0x69, 0xd83c, 0xdf89, 0x3a, 0x74, 0x61, 0x64, 0x61, 0x3a, 0x74, 0x61, - 0x64, 0x61, 0xd83c, 0xdf8e, 0x3a, 0x64, 0x6f, 0x6c, 0x6c, 0x73, 0x3a, 0x64, - 0x6f, 0x6c, 0x6c, 0x73, 0xd83c, 0xdfee, 0x3a, 0x69, 0x7a, 0x61, 0x6b, 0x61, - 0x79, 0x61, 0x5f, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x3a, 0x69, - 0x7a, 0x61, 0x6b, 0x61, 0x79, 0x61, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0xd83c, 0xdf90, 0x3a, 0x77, 0x69, 0x6e, 0x64, 0x5f, 0x63, 0x68, 0x69, - 0x6d, 0x65, 0x3a, 0x63, 0x68, 0x69, 0x6d, 0x65, 0x77, 0x69, 0x6e, 0x64, - 0x2709, 0xfe0f, 0x3a, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x3a, - 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0xd83d, 0xdce9, 0x3a, 0x65, - 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, - 0x5f, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, - 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x77, 0x69, 0x74, 0x68, - 0xd83d, 0xdce8, 0x3a, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x5f, - 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x3a, 0x65, 0x6e, 0x76, - 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, - 0x67, 0xd83d, 0xdce7, 0x3a, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x3a, 0x65, 0x6d, - 0x61, 0x69, 0x6c, 0xd83d, 0xdce7, 0x3a, 0x65, 0x2d, 0x6d, 0x61, 0x69, 0x6c, - 0x3a, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0xd83d, 0xdc8c, 0x3a, 0x6c, 0x6f, 0x76, - 0x65, 0x5f, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x3a, 0x6c, 0x65, 0x74, - 0x74, 0x65, 0x72, 0x6c, 0x6f, 0x76, 0x65, 0xd83d, 0xdce5, 0x3a, 0x69, 0x6e, - 0x62, 0x6f, 0x78, 0x5f, 0x74, 0x72, 0x61, 0x79, 0x3a, 0x69, 0x6e, 0x62, - 0x6f, 0x78, 0x74, 0x72, 0x61, 0x79, 0xd83d, 0xdce4, 0x3a, 0x6f, 0x75, 0x74, - 0x62, 0x6f, 0x78, 0x5f, 0x74, 0x72, 0x61, 0x79, 0x3a, 0x6f, 0x75, 0x74, - 0x62, 0x6f, 0x78, 0x74, 0x72, 0x61, 0x79, 0xd83d, 0xdce6, 0x3a, 0x70, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x3a, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0xd83c, 0xdff7, 0x3a, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x3a, 0x6c, 0x61, - 0x62, 0x65, 0x6c, 0xd83d, 0xdcea, 0x3a, 0x6d, 0x61, 0x69, 0x6c, 0x62, 0x6f, - 0x78, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x3a, 0x63, 0x6c, 0x6f, - 0x73, 0x65, 0x64, 0x6d, 0x61, 0x69, 0x6c, 0x62, 0x6f, 0x78, 0xd83d, 0xdceb, - 0x3a, 0x6d, 0x61, 0x69, 0x6c, 0x62, 0x6f, 0x78, 0x3a, 0x6d, 0x61, 0x69, - 0x6c, 0x62, 0x6f, 0x78, 0xd83d, 0xdcec, 0x3a, 0x6d, 0x61, 0x69, 0x6c, 0x62, - 0x6f, 0x78, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x6d, 0x61, 0x69, 0x6c, - 0x3a, 0x6d, 0x61, 0x69, 0x6c, 0x6d, 0x61, 0x69, 0x6c, 0x62, 0x6f, 0x78, - 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdced, 0x3a, 0x6d, 0x61, 0x69, 0x6c, 0x62, - 0x6f, 0x78, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x6e, 0x6f, 0x5f, 0x6d, - 0x61, 0x69, 0x6c, 0x3a, 0x6d, 0x61, 0x69, 0x6c, 0x6d, 0x61, 0x69, 0x6c, - 0x62, 0x6f, 0x78, 0x6e, 0x6f, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdcee, 0x3a, - 0x70, 0x6f, 0x73, 0x74, 0x62, 0x6f, 0x78, 0x3a, 0x70, 0x6f, 0x73, 0x74, - 0x62, 0x6f, 0x78, 0xd83d, 0xdcef, 0x3a, 0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, - 0x5f, 0x68, 0x6f, 0x72, 0x6e, 0x3a, 0x68, 0x6f, 0x72, 0x6e, 0x70, 0x6f, - 0x73, 0x74, 0x61, 0x6c, 0xd83d, 0xdcdc, 0x3a, 0x73, 0x63, 0x72, 0x6f, 0x6c, - 0x6c, 0x3a, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0xd83d, 0xdcc3, 0x3a, 0x70, - 0x61, 0x67, 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x63, 0x75, 0x72, - 0x6c, 0x3a, 0x63, 0x75, 0x72, 0x6c, 0x70, 0x61, 0x67, 0x65, 0x77, 0x69, - 0x74, 0x68, 0xd83d, 0xdcc4, 0x3a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, - 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x70, 0x3a, 0x66, 0x61, 0x63, 0x69, - 0x6e, 0x67, 0x70, 0x61, 0x67, 0x65, 0x75, 0x70, 0xd83d, 0xdcd1, 0x3a, 0x62, - 0x6f, 0x6f, 0x6b, 0x6d, 0x61, 0x72, 0x6b, 0x5f, 0x74, 0x61, 0x62, 0x73, - 0x3a, 0x62, 0x6f, 0x6f, 0x6b, 0x6d, 0x61, 0x72, 0x6b, 0x74, 0x61, 0x62, - 0x73, 0xd83d, 0xdcca, 0x3a, 0x62, 0x61, 0x72, 0x5f, 0x63, 0x68, 0x61, 0x72, - 0x74, 0x3a, 0x62, 0x61, 0x72, 0x63, 0x68, 0x61, 0x72, 0x74, 0xd83d, 0xdcc8, - 0x3a, 0x63, 0x68, 0x61, 0x72, 0x74, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, - 0x75, 0x70, 0x77, 0x61, 0x72, 0x64, 0x73, 0x5f, 0x74, 0x72, 0x65, 0x6e, - 0x64, 0x3a, 0x63, 0x68, 0x61, 0x72, 0x74, 0x74, 0x72, 0x65, 0x6e, 0x64, - 0x75, 0x70, 0x77, 0x61, 0x72, 0x64, 0x73, 0x77, 0x69, 0x74, 0x68, 0xd83d, - 0xdcc9, 0x3a, 0x63, 0x68, 0x61, 0x72, 0x74, 0x5f, 0x77, 0x69, 0x74, 0x68, - 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x77, 0x61, 0x72, 0x64, 0x73, 0x5f, 0x74, - 0x72, 0x65, 0x6e, 0x64, 0x3a, 0x63, 0x68, 0x61, 0x72, 0x74, 0x64, 0x6f, - 0x77, 0x6e, 0x77, 0x61, 0x72, 0x64, 0x73, 0x74, 0x72, 0x65, 0x6e, 0x64, - 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xddd2, 0x3a, 0x73, 0x70, 0x69, 0x72, 0x61, - 0x6c, 0x5f, 0x6e, 0x6f, 0x74, 0x65, 0x5f, 0x70, 0x61, 0x64, 0x3a, 0x6e, - 0x6f, 0x74, 0x65, 0x70, 0x61, 0x64, 0x73, 0x70, 0x69, 0x72, 0x61, 0x6c, - 0xd83d, 0xddd2, 0x3a, 0x6e, 0x6f, 0x74, 0x65, 0x70, 0x61, 0x64, 0x5f, 0x73, - 0x70, 0x69, 0x72, 0x61, 0x6c, 0x3a, 0x6e, 0x6f, 0x74, 0x65, 0x70, 0x61, - 0x64, 0x73, 0x70, 0x69, 0x72, 0x61, 0x6c, 0xd83d, 0xddd3, 0x3a, 0x73, 0x70, - 0x69, 0x72, 0x61, 0x6c, 0x5f, 0x63, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, - 0x72, 0x5f, 0x70, 0x61, 0x64, 0x3a, 0x63, 0x61, 0x6c, 0x65, 0x6e, 0x64, - 0x61, 0x72, 0x70, 0x61, 0x64, 0x73, 0x70, 0x69, 0x72, 0x61, 0x6c, 0xd83d, - 0xddd3, 0x3a, 0x63, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x5f, 0x73, - 0x70, 0x69, 0x72, 0x61, 0x6c, 0x3a, 0x63, 0x61, 0x6c, 0x65, 0x6e, 0x64, - 0x61, 0x72, 0x73, 0x70, 0x69, 0x72, 0x61, 0x6c, 0xd83d, 0xdcc6, 0x3a, 0x63, - 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x3a, 0x63, 0x61, 0x6c, 0x65, - 0x6e, 0x64, 0x61, 0x72, 0xd83d, 0xdcc5, 0x3a, 0x64, 0x61, 0x74, 0x65, 0x3a, - 0x64, 0x61, 0x74, 0x65, 0xd83d, 0xddd1, 0x3a, 0x77, 0x61, 0x73, 0x74, 0x65, - 0x62, 0x61, 0x73, 0x6b, 0x65, 0x74, 0x3a, 0x77, 0x61, 0x73, 0x74, 0x65, - 0x62, 0x61, 0x73, 0x6b, 0x65, 0x74, 0xd83d, 0xdcc7, 0x3a, 0x63, 0x61, 0x72, - 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x63, 0x61, 0x72, 0x64, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0xd83d, 0xddc3, 0x3a, 0x63, 0x61, 0x72, 0x64, - 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x62, 0x6f, 0x78, 0x3a, 0x62, 0x6f, - 0x78, 0x63, 0x61, 0x72, 0x64, 0x66, 0x69, 0x6c, 0x65, 0xd83d, 0xddc3, 0x3a, - 0x63, 0x61, 0x72, 0x64, 0x5f, 0x62, 0x6f, 0x78, 0x3a, 0x62, 0x6f, 0x78, - 0x63, 0x61, 0x72, 0x64, 0xd83d, 0xddf3, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x6f, - 0x74, 0x5f, 0x62, 0x6f, 0x78, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x62, - 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x74, - 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x62, 0x6f, 0x78, 0x77, 0x69, 0x74, - 0x68, 0xd83d, 0xddf3, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x5f, 0x62, - 0x6f, 0x78, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x62, 0x6f, 0x78, - 0xd83d, 0xddc4, 0x3a, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x62, 0x69, - 0x6e, 0x65, 0x74, 0x3a, 0x63, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x66, - 0x69, 0x6c, 0x65, 0xd83d, 0xdccb, 0x3a, 0x63, 0x6c, 0x69, 0x70, 0x62, 0x6f, - 0x61, 0x72, 0x64, 0x3a, 0x63, 0x6c, 0x69, 0x70, 0x62, 0x6f, 0x61, 0x72, - 0x64, 0xd83d, 0xdcc1, 0x3a, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x66, 0x6f, 0x6c, - 0x64, 0x65, 0x72, 0x3a, 0x66, 0x69, 0x6c, 0x65, 0x66, 0x6f, 0x6c, 0x64, - 0x65, 0x72, 0xd83d, 0xdcc2, 0x3a, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x66, 0x69, - 0x6c, 0x65, 0x5f, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x3a, 0x66, 0x69, - 0x6c, 0x65, 0x66, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x6f, 0x70, 0x65, 0x6e, - 0xd83d, 0xddc2, 0x3a, 0x63, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x5f, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x3a, 0x63, - 0x61, 0x72, 0x64, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0xd83d, 0xddc2, 0x3a, 0x64, 0x69, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x73, 0x3a, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, - 0xd83d, 0xddde, 0x3a, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x64, 0x5f, 0x75, 0x70, - 0x5f, 0x6e, 0x65, 0x77, 0x73, 0x70, 0x61, 0x70, 0x65, 0x72, 0x3a, 0x6e, - 0x65, 0x77, 0x73, 0x70, 0x61, 0x70, 0x65, 0x72, 0x72, 0x6f, 0x6c, 0x6c, - 0x65, 0x64, 0x75, 0x70, 0xd83d, 0xddde, 0x3a, 0x6e, 0x65, 0x77, 0x73, 0x70, - 0x61, 0x70, 0x65, 0x72, 0x32, 0x3a, 0x6e, 0x65, 0x77, 0x73, 0x70, 0x61, - 0x70, 0x65, 0x72, 0x32, 0xd83d, 0xdcf0, 0x3a, 0x6e, 0x65, 0x77, 0x73, 0x70, - 0x61, 0x70, 0x65, 0x72, 0x3a, 0x6e, 0x65, 0x77, 0x73, 0x70, 0x61, 0x70, - 0x65, 0x72, 0xd83d, 0xdcd3, 0x3a, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, - 0x6b, 0x3a, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0xd83d, 0xdcd4, - 0x3a, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x77, 0x69, - 0x74, 0x68, 0x5f, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x76, - 0x65, 0x5f, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x63, 0x6f, 0x76, 0x65, - 0x72, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x6e, - 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x77, 0x69, 0x74, 0x68, 0xd83d, - 0xdcd2, 0x3a, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x72, 0x3a, 0x6c, 0x65, 0x64, - 0x67, 0x65, 0x72, 0xd83d, 0xdcd5, 0x3a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, - 0x5f, 0x62, 0x6f, 0x6f, 0x6b, 0x3a, 0x62, 0x6f, 0x6f, 0x6b, 0x63, 0x6c, - 0x6f, 0x73, 0x65, 0x64, 0xd83d, 0xdcd7, 0x3a, 0x67, 0x72, 0x65, 0x65, 0x6e, - 0x5f, 0x62, 0x6f, 0x6f, 0x6b, 0x3a, 0x62, 0x6f, 0x6f, 0x6b, 0x67, 0x72, - 0x65, 0x65, 0x6e, 0xd83d, 0xdcd8, 0x3a, 0x62, 0x6c, 0x75, 0x65, 0x5f, 0x62, - 0x6f, 0x6f, 0x6b, 0x3a, 0x62, 0x6c, 0x75, 0x65, 0x62, 0x6f, 0x6f, 0x6b, - 0xd83d, 0xdcd9, 0x3a, 0x6f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x62, 0x6f, - 0x6f, 0x6b, 0x3a, 0x62, 0x6f, 0x6f, 0x6b, 0x6f, 0x72, 0x61, 0x6e, 0x67, - 0x65, 0xd83d, 0xdcda, 0x3a, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x3a, 0x62, 0x6f, - 0x6f, 0x6b, 0x73, 0xd83d, 0xdcd6, 0x3a, 0x62, 0x6f, 0x6f, 0x6b, 0x3a, 0x62, - 0x6f, 0x6f, 0x6b, 0xd83d, 0xdd16, 0x3a, 0x62, 0x6f, 0x6f, 0x6b, 0x6d, 0x61, - 0x72, 0x6b, 0x3a, 0x62, 0x6f, 0x6f, 0x6b, 0x6d, 0x61, 0x72, 0x6b, 0xd83d, - 0xdd17, 0x3a, 0x6c, 0x69, 0x6e, 0x6b, 0x3a, 0x6c, 0x69, 0x6e, 0x6b, 0xd83d, - 0xdcce, 0x3a, 0x70, 0x61, 0x70, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x70, 0x3a, - 0x70, 0x61, 0x70, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x70, 0xd83d, 0xdd87, 0x3a, - 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x70, 0x65, 0x72, - 0x63, 0x6c, 0x69, 0x70, 0x73, 0x3a, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x64, - 0x70, 0x61, 0x70, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x70, 0x73, 0xd83d, 0xdd87, - 0x3a, 0x70, 0x61, 0x70, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x70, 0x73, 0x3a, - 0x70, 0x61, 0x70, 0x65, 0x72, 0x63, 0x6c, 0x69, 0x70, 0x73, 0xd83d, 0xdcd0, - 0x3a, 0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x5f, - 0x72, 0x75, 0x6c, 0x65, 0x72, 0x3a, 0x72, 0x75, 0x6c, 0x65, 0x72, 0x74, - 0x72, 0x69, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x72, 0xd83d, 0xdccf, 0x3a, - 0x73, 0x74, 0x72, 0x61, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x72, 0x75, 0x6c, - 0x65, 0x72, 0x3a, 0x72, 0x75, 0x6c, 0x65, 0x72, 0x73, 0x74, 0x72, 0x61, - 0x69, 0x67, 0x68, 0x74, 0xd83d, 0xdccc, 0x3a, 0x70, 0x75, 0x73, 0x68, 0x70, - 0x69, 0x6e, 0x3a, 0x70, 0x75, 0x73, 0x68, 0x70, 0x69, 0x6e, 0xd83d, 0xdccd, - 0x3a, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x70, 0x75, 0x73, 0x68, 0x70, - 0x69, 0x6e, 0x3a, 0x70, 0x75, 0x73, 0x68, 0x70, 0x69, 0x6e, 0x72, 0x6f, - 0x75, 0x6e, 0x64, 0x2702, 0xfe0f, 0x3a, 0x73, 0x63, 0x69, 0x73, 0x73, 0x6f, - 0x72, 0x73, 0x3a, 0x73, 0x63, 0x69, 0x73, 0x73, 0x6f, 0x72, 0x73, 0xd83d, - 0xdd8a, 0x3a, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x66, 0x74, - 0x5f, 0x62, 0x61, 0x6c, 0x6c, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x70, - 0x65, 0x6e, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x6c, 0x65, 0x66, 0x74, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x70, 0x65, 0x6e, - 0xd83d, 0xdd8a, 0x3a, 0x70, 0x65, 0x6e, 0x5f, 0x62, 0x61, 0x6c, 0x6c, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x70, 0x65, 0x6e, 0xd83d, 0xdd8b, 0x3a, 0x6c, 0x6f, 0x77, 0x65, - 0x72, 0x5f, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x66, 0x6f, 0x75, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x5f, 0x70, 0x65, 0x6e, 0x3a, 0x66, 0x6f, 0x75, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x6c, 0x65, 0x66, 0x74, 0x6c, 0x6f, 0x77, 0x65, - 0x72, 0x70, 0x65, 0x6e, 0xd83d, 0xdd8b, 0x3a, 0x70, 0x65, 0x6e, 0x5f, 0x66, - 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x3a, 0x66, 0x6f, 0x75, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x70, 0x65, 0x6e, 0x2712, 0xfe0f, 0x3a, 0x62, 0x6c, - 0x61, 0x63, 0x6b, 0x5f, 0x6e, 0x69, 0x62, 0x3a, 0x62, 0x6c, 0x61, 0x63, - 0x6b, 0x6e, 0x69, 0x62, 0xd83d, 0xdd8c, 0x3a, 0x6c, 0x6f, 0x77, 0x65, 0x72, - 0x5f, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x70, 0x61, 0x69, 0x6e, 0x74, 0x62, - 0x72, 0x75, 0x73, 0x68, 0x3a, 0x6c, 0x65, 0x66, 0x74, 0x6c, 0x6f, 0x77, - 0x65, 0x72, 0x70, 0x61, 0x69, 0x6e, 0x74, 0x62, 0x72, 0x75, 0x73, 0x68, - 0xd83d, 0xdd8c, 0x3a, 0x70, 0x61, 0x69, 0x6e, 0x74, 0x62, 0x72, 0x75, 0x73, - 0x68, 0x3a, 0x70, 0x61, 0x69, 0x6e, 0x74, 0x62, 0x72, 0x75, 0x73, 0x68, - 0xd83d, 0xdd8d, 0x3a, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x66, - 0x74, 0x5f, 0x63, 0x72, 0x61, 0x79, 0x6f, 0x6e, 0x3a, 0x63, 0x72, 0x61, - 0x79, 0x6f, 0x6e, 0x6c, 0x65, 0x66, 0x74, 0x6c, 0x6f, 0x77, 0x65, 0x72, - 0xd83d, 0xdd8d, 0x3a, 0x63, 0x72, 0x61, 0x79, 0x6f, 0x6e, 0x3a, 0x63, 0x72, - 0x61, 0x79, 0x6f, 0x6e, 0xd83d, 0xdcdd, 0x3a, 0x6d, 0x65, 0x6d, 0x6f, 0x3a, - 0x6d, 0x65, 0x6d, 0x6f, 0xd83d, 0xdcdd, 0x3a, 0x70, 0x65, 0x6e, 0x63, 0x69, - 0x6c, 0x3a, 0x70, 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x270f, 0xfe0f, 0x3a, 0x70, - 0x65, 0x6e, 0x63, 0x69, 0x6c, 0x32, 0x3a, 0x70, 0x65, 0x6e, 0x63, 0x69, - 0x6c, 0x32, 0xd83d, 0xdd0d, 0x3a, 0x6d, 0x61, 0x67, 0x3a, 0x6d, 0x61, 0x67, - 0xd83d, 0xdd0e, 0x3a, 0x6d, 0x61, 0x67, 0x5f, 0x72, 0x69, 0x67, 0x68, 0x74, - 0x3a, 0x6d, 0x61, 0x67, 0x72, 0x69, 0x67, 0x68, 0x74, 0xd83d, 0xdd0f, 0x3a, - 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x69, 0x6e, - 0x6b, 0x5f, 0x70, 0x65, 0x6e, 0x3a, 0x69, 0x6e, 0x6b, 0x6c, 0x6f, 0x63, - 0x6b, 0x70, 0x65, 0x6e, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdd10, 0x3a, 0x63, - 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x5f, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x77, - 0x69, 0x74, 0x68, 0x5f, 0x6b, 0x65, 0x79, 0x3a, 0x63, 0x6c, 0x6f, 0x73, - 0x65, 0x64, 0x6b, 0x65, 0x79, 0x6c, 0x6f, 0x63, 0x6b, 0x77, 0x69, 0x74, - 0x68, 0xd83d, 0xdd12, 0x3a, 0x6c, 0x6f, 0x63, 0x6b, 0x3a, 0x6c, 0x6f, 0x63, - 0x6b, 0xd83d, 0xdd13, 0x3a, 0x75, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x3a, 0x75, - 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x2764, 0xfe0f, 0x3a, 0x68, 0x65, 0x61, 0x72, - 0x74, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0xd83e, 0xdde1, 0x3a, 0x6f, 0x72, - 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x3a, 0x68, - 0x65, 0x61, 0x72, 0x74, 0x6f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0xd83d, 0xdc9b, - 0x3a, 0x79, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x68, 0x65, 0x61, 0x72, - 0x74, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x79, 0x65, 0x6c, 0x6c, 0x6f, - 0x77, 0xd83d, 0xdc9a, 0x3a, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x5f, 0x68, 0x65, - 0x61, 0x72, 0x74, 0x3a, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x68, 0x65, 0x61, - 0x72, 0x74, 0xd83d, 0xdc99, 0x3a, 0x62, 0x6c, 0x75, 0x65, 0x5f, 0x68, 0x65, - 0x61, 0x72, 0x74, 0x3a, 0x62, 0x6c, 0x75, 0x65, 0x68, 0x65, 0x61, 0x72, - 0x74, 0xd83d, 0xdc9c, 0x3a, 0x70, 0x75, 0x72, 0x70, 0x6c, 0x65, 0x5f, 0x68, - 0x65, 0x61, 0x72, 0x74, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x70, 0x75, - 0x72, 0x70, 0x6c, 0x65, 0xd83d, 0xdda4, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, - 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, - 0x68, 0x65, 0x61, 0x72, 0x74, 0xd83d, 0xdc94, 0x3a, 0x62, 0x72, 0x6f, 0x6b, - 0x65, 0x6e, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x3a, 0x62, 0x72, 0x6f, - 0x6b, 0x65, 0x6e, 0x68, 0x65, 0x61, 0x72, 0x74, 0x2763, 0xfe0f, 0x3a, 0x68, - 0x65, 0x61, 0x76, 0x79, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x5f, 0x65, - 0x78, 0x63, 0x6c, 0x61, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, - 0x61, 0x72, 0x6b, 0x5f, 0x6f, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x6e, 0x74, - 0x3a, 0x65, 0x78, 0x63, 0x6c, 0x61, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x65, 0x61, 0x76, 0x79, 0x6d, 0x61, - 0x72, 0x6b, 0x6f, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x2763, 0xfe0f, - 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x5f, 0x65, 0x78, 0x63, 0x6c, 0x61, - 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x65, 0x78, 0x63, 0x6c, 0x61, - 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x68, 0x65, 0x61, 0x72, 0x74, 0xd83d, - 0xdc95, 0x3a, 0x74, 0x77, 0x6f, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x73, - 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x73, 0x74, 0x77, 0x6f, 0xd83d, 0xdc9e, - 0x3a, 0x72, 0x65, 0x76, 0x6f, 0x6c, 0x76, 0x69, 0x6e, 0x67, 0x5f, 0x68, - 0x65, 0x61, 0x72, 0x74, 0x73, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x73, - 0x72, 0x65, 0x76, 0x6f, 0x6c, 0x76, 0x69, 0x6e, 0x67, 0xd83d, 0xdc93, 0x3a, - 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x3a, 0x68, 0x65, - 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0xd83d, 0xdc97, 0x3a, 0x68, 0x65, - 0x61, 0x72, 0x74, 0x70, 0x75, 0x6c, 0x73, 0x65, 0x3a, 0x68, 0x65, 0x61, - 0x72, 0x74, 0x70, 0x75, 0x6c, 0x73, 0x65, 0xd83d, 0xdc96, 0x3a, 0x73, 0x70, - 0x61, 0x72, 0x6b, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x65, 0x61, 0x72, - 0x74, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x73, 0x70, 0x61, 0x72, 0x6b, - 0x6c, 0x69, 0x6e, 0x67, 0xd83d, 0xdc98, 0x3a, 0x63, 0x75, 0x70, 0x69, 0x64, - 0x3a, 0x63, 0x75, 0x70, 0x69, 0x64, 0xd83d, 0xdc9d, 0x3a, 0x67, 0x69, 0x66, - 0x74, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x3a, 0x67, 0x69, 0x66, 0x74, - 0x68, 0x65, 0x61, 0x72, 0x74, 0xd83d, 0xdc9f, 0x3a, 0x68, 0x65, 0x61, 0x72, - 0x74, 0x5f, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x3a, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x68, - 0x65, 0x61, 0x72, 0x74, 0x262e, 0xfe0f, 0x3a, 0x70, 0x65, 0x61, 0x63, 0x65, - 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x3a, 0x70, 0x65, 0x61, 0x63, - 0x65, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x262e, 0xfe0f, 0x3a, 0x70, 0x65, - 0x61, 0x63, 0x65, 0x3a, 0x70, 0x65, 0x61, 0x63, 0x65, 0x271d, 0xfe0f, 0x3a, - 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x3a, - 0x63, 0x72, 0x6f, 0x73, 0x73, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x271d, 0xfe0f, - 0x3a, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x3a, 0x63, 0x72, 0x6f, 0x73, 0x73, - 0x262a, 0xfe0f, 0x3a, 0x73, 0x74, 0x61, 0x72, 0x5f, 0x61, 0x6e, 0x64, 0x5f, - 0x63, 0x72, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x3a, 0x61, 0x6e, 0x64, - 0x63, 0x72, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x74, 0x73, 0x74, 0x61, 0x72, - 0xd83d, 0xdd49, 0x3a, 0x6f, 0x6d, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, - 0x3a, 0x6f, 0x6d, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x2638, 0xfe0f, 0x3a, - 0x77, 0x68, 0x65, 0x65, 0x6c, 0x5f, 0x6f, 0x66, 0x5f, 0x64, 0x68, 0x61, - 0x72, 0x6d, 0x61, 0x3a, 0x64, 0x68, 0x61, 0x72, 0x6d, 0x61, 0x6f, 0x66, - 0x77, 0x68, 0x65, 0x65, 0x6c, 0x2721, 0xfe0f, 0x3a, 0x73, 0x74, 0x61, 0x72, - 0x5f, 0x6f, 0x66, 0x5f, 0x64, 0x61, 0x76, 0x69, 0x64, 0x3a, 0x64, 0x61, - 0x76, 0x69, 0x64, 0x6f, 0x66, 0x73, 0x74, 0x61, 0x72, 0xd83d, 0xdd2f, 0x3a, - 0x73, 0x69, 0x78, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x5f, - 0x73, 0x74, 0x61, 0x72, 0x3a, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, - 0x73, 0x69, 0x78, 0x73, 0x74, 0x61, 0x72, 0xd83d, 0xdd4e, 0x3a, 0x6d, 0x65, - 0x6e, 0x6f, 0x72, 0x61, 0x68, 0x3a, 0x6d, 0x65, 0x6e, 0x6f, 0x72, 0x61, - 0x68, 0x262f, 0xfe0f, 0x3a, 0x79, 0x69, 0x6e, 0x5f, 0x79, 0x61, 0x6e, 0x67, - 0x3a, 0x79, 0x61, 0x6e, 0x67, 0x79, 0x69, 0x6e, 0x2626, 0xfe0f, 0x3a, 0x6f, - 0x72, 0x74, 0x68, 0x6f, 0x64, 0x6f, 0x78, 0x5f, 0x63, 0x72, 0x6f, 0x73, - 0x73, 0x3a, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x6f, 0x72, 0x74, 0x68, 0x6f, - 0x64, 0x6f, 0x78, 0xd83d, 0xded0, 0x3a, 0x77, 0x6f, 0x72, 0x73, 0x68, 0x69, - 0x70, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x3a, 0x73, 0x79, 0x6d, - 0x62, 0x6f, 0x6c, 0x77, 0x6f, 0x72, 0x73, 0x68, 0x69, 0x70, 0xd83d, 0xded0, - 0x3a, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x77, 0x6f, - 0x72, 0x73, 0x68, 0x69, 0x70, 0x3a, 0x6f, 0x66, 0x70, 0x6c, 0x61, 0x63, - 0x65, 0x77, 0x6f, 0x72, 0x73, 0x68, 0x69, 0x70, 0x26ce, 0x3a, 0x6f, 0x70, - 0x68, 0x69, 0x75, 0x63, 0x68, 0x75, 0x73, 0x3a, 0x6f, 0x70, 0x68, 0x69, - 0x75, 0x63, 0x68, 0x75, 0x73, 0x2648, 0xfe0f, 0x3a, 0x61, 0x72, 0x69, 0x65, - 0x73, 0x3a, 0x61, 0x72, 0x69, 0x65, 0x73, 0x2649, 0xfe0f, 0x3a, 0x74, 0x61, - 0x75, 0x72, 0x75, 0x73, 0x3a, 0x74, 0x61, 0x75, 0x72, 0x75, 0x73, 0x264a, - 0xfe0f, 0x3a, 0x67, 0x65, 0x6d, 0x69, 0x6e, 0x69, 0x3a, 0x67, 0x65, 0x6d, - 0x69, 0x6e, 0x69, 0x264b, 0xfe0f, 0x3a, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x72, - 0x3a, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x264c, 0xfe0f, 0x3a, 0x6c, 0x65, - 0x6f, 0x3a, 0x6c, 0x65, 0x6f, 0x264d, 0xfe0f, 0x3a, 0x76, 0x69, 0x72, 0x67, - 0x6f, 0x3a, 0x76, 0x69, 0x72, 0x67, 0x6f, 0x264e, 0xfe0f, 0x3a, 0x6c, 0x69, - 0x62, 0x72, 0x61, 0x3a, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x264f, 0xfe0f, 0x3a, - 0x73, 0x63, 0x6f, 0x72, 0x70, 0x69, 0x75, 0x73, 0x3a, 0x73, 0x63, 0x6f, - 0x72, 0x70, 0x69, 0x75, 0x73, 0x2650, 0xfe0f, 0x3a, 0x73, 0x61, 0x67, 0x69, - 0x74, 0x74, 0x61, 0x72, 0x69, 0x75, 0x73, 0x3a, 0x73, 0x61, 0x67, 0x69, - 0x74, 0x74, 0x61, 0x72, 0x69, 0x75, 0x73, 0x2651, 0xfe0f, 0x3a, 0x63, 0x61, - 0x70, 0x72, 0x69, 0x63, 0x6f, 0x72, 0x6e, 0x3a, 0x63, 0x61, 0x70, 0x72, - 0x69, 0x63, 0x6f, 0x72, 0x6e, 0x2652, 0xfe0f, 0x3a, 0x61, 0x71, 0x75, 0x61, - 0x72, 0x69, 0x75, 0x73, 0x3a, 0x61, 0x71, 0x75, 0x61, 0x72, 0x69, 0x75, - 0x73, 0x2653, 0xfe0f, 0x3a, 0x70, 0x69, 0x73, 0x63, 0x65, 0x73, 0x3a, 0x70, - 0x69, 0x73, 0x63, 0x65, 0x73, 0xd83c, 0xdd94, 0x3a, 0x69, 0x64, 0x3a, 0x69, - 0x64, 0x269b, 0xfe0f, 0x3a, 0x61, 0x74, 0x6f, 0x6d, 0x5f, 0x73, 0x79, 0x6d, - 0x62, 0x6f, 0x6c, 0x3a, 0x61, 0x74, 0x6f, 0x6d, 0x73, 0x79, 0x6d, 0x62, - 0x6f, 0x6c, 0x269b, 0xfe0f, 0x3a, 0x61, 0x74, 0x6f, 0x6d, 0x3a, 0x61, 0x74, - 0x6f, 0x6d, 0xd83c, 0xde51, 0x3a, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, - 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2622, 0xfe0f, 0x3a, 0x72, 0x61, 0x64, - 0x69, 0x6f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x73, 0x69, 0x67, - 0x6e, 0x3a, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x61, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x73, 0x69, 0x67, 0x6e, 0x2622, 0xfe0f, 0x3a, 0x72, 0x61, 0x64, 0x69, - 0x6f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x3a, 0x72, 0x61, 0x64, 0x69, - 0x6f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2623, 0xfe0f, 0x3a, 0x62, 0x69, - 0x6f, 0x68, 0x61, 0x7a, 0x61, 0x72, 0x64, 0x5f, 0x73, 0x69, 0x67, 0x6e, - 0x3a, 0x62, 0x69, 0x6f, 0x68, 0x61, 0x7a, 0x61, 0x72, 0x64, 0x73, 0x69, - 0x67, 0x6e, 0x2623, 0xfe0f, 0x3a, 0x62, 0x69, 0x6f, 0x68, 0x61, 0x7a, 0x61, - 0x72, 0x64, 0x3a, 0x62, 0x69, 0x6f, 0x68, 0x61, 0x7a, 0x61, 0x72, 0x64, - 0xd83d, 0xdcf4, 0x3a, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x68, - 0x6f, 0x6e, 0x65, 0x5f, 0x6f, 0x66, 0x66, 0x3a, 0x6d, 0x6f, 0x62, 0x69, - 0x6c, 0x65, 0x6f, 0x66, 0x66, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0xd83d, 0xdcf3, - 0x3a, 0x76, 0x69, 0x62, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, - 0x6f, 0x64, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x65, 0x76, 0x69, 0x62, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xd83c, 0xde36, 0x3a, 0x75, 0x36, 0x37, 0x30, - 0x39, 0x3a, 0x75, 0x36, 0x37, 0x30, 0x39, 0xd83c, 0xde1a, 0xfe0f, 0x3a, 0x75, - 0x37, 0x31, 0x32, 0x31, 0x3a, 0x75, 0x37, 0x31, 0x32, 0x31, 0xd83c, 0xde38, - 0x3a, 0x75, 0x37, 0x35, 0x33, 0x33, 0x3a, 0x75, 0x37, 0x35, 0x33, 0x33, - 0xd83c, 0xde3a, 0x3a, 0x75, 0x35, 0x35, 0x62, 0x36, 0x3a, 0x75, 0x35, 0x35, - 0x62, 0x36, 0xd83c, 0xde37, 0xfe0f, 0x3a, 0x75, 0x36, 0x37, 0x30, 0x38, 0x3a, - 0x75, 0x36, 0x37, 0x30, 0x38, 0x2734, 0xfe0f, 0x3a, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x6c, - 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x3a, 0x62, 0x6c, 0x61, - 0x63, 0x6b, 0x65, 0x69, 0x67, 0x68, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x65, 0x64, 0x73, 0x74, 0x61, 0x72, 0xd83c, 0xdd9a, 0x3a, 0x76, 0x73, 0x3a, - 0x76, 0x73, 0xd83d, 0xdcae, 0x3a, 0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, 0x66, - 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x3a, 0x66, 0x6c, 0x6f, 0x77, 0x65, 0x72, - 0x77, 0x68, 0x69, 0x74, 0x65, 0xd83c, 0xde50, 0x3a, 0x69, 0x64, 0x65, 0x6f, - 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x61, 0x64, 0x76, 0x61, 0x6e, 0x74, - 0x61, 0x67, 0x65, 0x3a, 0x61, 0x64, 0x76, 0x61, 0x6e, 0x74, 0x61, 0x67, - 0x65, 0x69, 0x64, 0x65, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x3299, 0xfe0f, - 0x3a, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x3a, 0x73, 0x65, 0x63, 0x72, - 0x65, 0x74, 0x3297, 0xfe0f, 0x3a, 0x63, 0x6f, 0x6e, 0x67, 0x72, 0x61, 0x74, - 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x63, 0x6f, 0x6e, - 0x67, 0x72, 0x61, 0x74, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0xd83c, 0xde34, 0x3a, 0x75, 0x35, 0x34, 0x30, 0x38, 0x3a, 0x75, 0x35, 0x34, - 0x30, 0x38, 0xd83c, 0xde35, 0x3a, 0x75, 0x36, 0x65, 0x38, 0x30, 0x3a, 0x75, - 0x36, 0x65, 0x38, 0x30, 0xd83c, 0xde39, 0x3a, 0x75, 0x35, 0x32, 0x37, 0x32, - 0x3a, 0x75, 0x35, 0x32, 0x37, 0x32, 0xd83c, 0xde32, 0x3a, 0x75, 0x37, 0x39, - 0x38, 0x31, 0x3a, 0x75, 0x37, 0x39, 0x38, 0x31, 0xd83c, 0xdd70, 0xfe0f, 0x3a, - 0x61, 0x3a, 0x61, 0xd83c, 0xdd71, 0xfe0f, 0x3a, 0x62, 0x3a, 0x62, 0xd83c, 0xdd8e, - 0x3a, 0x61, 0x62, 0x3a, 0x61, 0x62, 0xd83c, 0xdd91, 0x3a, 0x63, 0x6c, 0x3a, - 0x63, 0x6c, 0xd83c, 0xdd7e, 0xfe0f, 0x3a, 0x6f, 0x32, 0x3a, 0x6f, 0x32, 0xd83c, - 0xdd98, 0x3a, 0x73, 0x6f, 0x73, 0x3a, 0x73, 0x6f, 0x73, 0x274c, 0x3a, 0x78, - 0x3a, 0x78, 0x2b55, 0xfe0f, 0x3a, 0x6f, 0x3a, 0x6f, 0xd83d, 0xded1, 0x3a, 0x73, - 0x74, 0x6f, 0x70, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x3a, 0x73, 0x69, 0x67, - 0x6e, 0x73, 0x74, 0x6f, 0x70, 0xd83d, 0xded1, 0x3a, 0x6f, 0x63, 0x74, 0x61, - 0x67, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x3a, 0x6f, - 0x63, 0x74, 0x61, 0x67, 0x6f, 0x6e, 0x61, 0x6c, 0x73, 0x69, 0x67, 0x6e, - 0x26d4, 0xfe0f, 0x3a, 0x6e, 0x6f, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x3a, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x6e, 0x6f, 0xd83d, 0xdcdb, 0x3a, 0x6e, 0x61, - 0x6d, 0x65, 0x5f, 0x62, 0x61, 0x64, 0x67, 0x65, 0x3a, 0x62, 0x61, 0x64, - 0x67, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0xd83d, 0xdeab, 0x3a, 0x6e, 0x6f, 0x5f, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x3a, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x6e, 0x6f, 0x73, 0x69, 0x67, 0x6e, 0xd83d, 0xdcaf, - 0x3a, 0x31, 0x30, 0x30, 0x3a, 0x31, 0x30, 0x30, 0xd83d, 0xdca2, 0x3a, 0x61, - 0x6e, 0x67, 0x65, 0x72, 0x3a, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x2668, 0xfe0f, - 0x3a, 0x68, 0x6f, 0x74, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x3a, - 0x68, 0x6f, 0x74, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x73, 0xd83d, 0xdeb7, - 0x3a, 0x6e, 0x6f, 0x5f, 0x70, 0x65, 0x64, 0x65, 0x73, 0x74, 0x72, 0x69, - 0x61, 0x6e, 0x73, 0x3a, 0x6e, 0x6f, 0x70, 0x65, 0x64, 0x65, 0x73, 0x74, - 0x72, 0x69, 0x61, 0x6e, 0x73, 0xd83d, 0xdeaf, 0x3a, 0x64, 0x6f, 0x5f, 0x6e, - 0x6f, 0x74, 0x5f, 0x6c, 0x69, 0x74, 0x74, 0x65, 0x72, 0x3a, 0x64, 0x6f, - 0x6c, 0x69, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x6f, 0x74, 0xd83d, 0xdeb3, 0x3a, - 0x6e, 0x6f, 0x5f, 0x62, 0x69, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x3a, - 0x62, 0x69, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x6e, 0x6f, 0xd83d, 0xdeb1, - 0x3a, 0x6e, 0x6f, 0x6e, 0x2d, 0x70, 0x6f, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x5f, 0x77, 0x61, 0x74, 0x65, 0x72, 0x3a, 0x6e, 0x6f, 0x6e, 0x70, 0x6f, - 0x74, 0x61, 0x62, 0x6c, 0x65, 0x77, 0x61, 0x74, 0x65, 0x72, 0xd83d, 0xdd1e, - 0x3a, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x67, 0x65, 0x3a, 0x75, 0x6e, - 0x64, 0x65, 0x72, 0x61, 0x67, 0x65, 0xd83d, 0xdcf5, 0x3a, 0x6e, 0x6f, 0x5f, - 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x68, 0x6f, 0x6e, 0x65, - 0x73, 0x3a, 0x6d, 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x70, 0x68, - 0x6f, 0x6e, 0x65, 0x73, 0xd83d, 0xdead, 0x3a, 0x6e, 0x6f, 0x5f, 0x73, 0x6d, - 0x6f, 0x6b, 0x69, 0x6e, 0x67, 0x3a, 0x6e, 0x6f, 0x73, 0x6d, 0x6f, 0x6b, - 0x69, 0x6e, 0x67, 0x2757, 0xfe0f, 0x3a, 0x65, 0x78, 0x63, 0x6c, 0x61, 0x6d, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x65, 0x78, 0x63, 0x6c, 0x61, 0x6d, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2755, 0x3a, 0x67, 0x72, 0x65, 0x79, 0x5f, - 0x65, 0x78, 0x63, 0x6c, 0x61, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, - 0x65, 0x78, 0x63, 0x6c, 0x61, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x67, - 0x72, 0x65, 0x79, 0x2753, 0x3a, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, - 0x6e, 0x3a, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x2754, 0x3a, - 0x67, 0x72, 0x65, 0x79, 0x5f, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, - 0x6e, 0x3a, 0x67, 0x72, 0x65, 0x79, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, - 0x6f, 0x6e, 0x203c, 0xfe0f, 0x3a, 0x62, 0x61, 0x6e, 0x67, 0x62, 0x61, 0x6e, - 0x67, 0x3a, 0x62, 0x61, 0x6e, 0x67, 0x62, 0x61, 0x6e, 0x67, 0x2049, 0xfe0f, - 0x3a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x6f, 0x62, 0x61, 0x6e, 0x67, - 0x3a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x6f, 0x62, 0x61, 0x6e, 0x67, - 0xd83d, 0xdd05, 0x3a, 0x6c, 0x6f, 0x77, 0x5f, 0x62, 0x72, 0x69, 0x67, 0x68, - 0x74, 0x6e, 0x65, 0x73, 0x73, 0x3a, 0x62, 0x72, 0x69, 0x67, 0x68, 0x74, - 0x6e, 0x65, 0x73, 0x73, 0x6c, 0x6f, 0x77, 0xd83d, 0xdd06, 0x3a, 0x68, 0x69, - 0x67, 0x68, 0x5f, 0x62, 0x72, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x65, 0x73, - 0x73, 0x3a, 0x62, 0x72, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x65, 0x73, 0x73, - 0x68, 0x69, 0x67, 0x68, 0x303d, 0xfe0f, 0x3a, 0x70, 0x61, 0x72, 0x74, 0x5f, - 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x6d, 0x61, 0x72, 0x6b, 0x3a, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x70, 0x61, 0x72, 0x74, - 0x26a0, 0xfe0f, 0x3a, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x3a, 0x77, - 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0xd83d, 0xdeb8, 0x3a, 0x63, 0x68, 0x69, - 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x69, - 0x6e, 0x67, 0x3a, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x63, - 0x72, 0x6f, 0x73, 0x73, 0x69, 0x6e, 0x67, 0xd83d, 0xdd31, 0x3a, 0x74, 0x72, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x3a, 0x74, 0x72, 0x69, 0x64, 0x65, 0x6e, - 0x74, 0x269c, 0xfe0f, 0x3a, 0x66, 0x6c, 0x65, 0x75, 0x72, 0x2d, 0x64, 0x65, - 0x2d, 0x6c, 0x69, 0x73, 0x3a, 0x64, 0x65, 0x66, 0x6c, 0x65, 0x75, 0x72, - 0x6c, 0x69, 0x73, 0xd83d, 0xdd30, 0x3a, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x6e, - 0x65, 0x72, 0x3a, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x267b, - 0xfe0f, 0x3a, 0x72, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x3a, 0x72, 0x65, - 0x63, 0x79, 0x63, 0x6c, 0x65, 0x2705, 0x3a, 0x77, 0x68, 0x69, 0x74, 0x65, - 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x3a, - 0x63, 0x68, 0x65, 0x63, 0x6b, 0x6d, 0x61, 0x72, 0x6b, 0x77, 0x68, 0x69, - 0x74, 0x65, 0xd83c, 0xde2f, 0xfe0f, 0x3a, 0x75, 0x36, 0x33, 0x30, 0x37, 0x3a, - 0x75, 0x36, 0x33, 0x30, 0x37, 0xd83d, 0xdcb9, 0x3a, 0x63, 0x68, 0x61, 0x72, - 0x74, 0x3a, 0x63, 0x68, 0x61, 0x72, 0x74, 0x2747, 0xfe0f, 0x3a, 0x73, 0x70, - 0x61, 0x72, 0x6b, 0x6c, 0x65, 0x3a, 0x73, 0x70, 0x61, 0x72, 0x6b, 0x6c, - 0x65, 0x2733, 0xfe0f, 0x3a, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x73, 0x70, - 0x6f, 0x6b, 0x65, 0x64, 0x5f, 0x61, 0x73, 0x74, 0x65, 0x72, 0x69, 0x73, - 0x6b, 0x3a, 0x61, 0x73, 0x74, 0x65, 0x72, 0x69, 0x73, 0x6b, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x73, 0x70, 0x6f, 0x6b, 0x65, 0x64, 0x274e, 0x3a, 0x6e, - 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x73, 0x71, 0x75, 0x61, - 0x72, 0x65, 0x64, 0x5f, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x5f, 0x6d, 0x61, - 0x72, 0x6b, 0x3a, 0x63, 0x72, 0x6f, 0x73, 0x73, 0x6d, 0x61, 0x72, 0x6b, - 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x73, 0x71, 0x75, 0x61, - 0x72, 0x65, 0x64, 0xd83c, 0xdf10, 0x3a, 0x67, 0x6c, 0x6f, 0x62, 0x65, 0x5f, - 0x77, 0x69, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x72, 0x69, 0x64, 0x69, 0x61, - 0x6e, 0x73, 0x3a, 0x67, 0x6c, 0x6f, 0x62, 0x65, 0x6d, 0x65, 0x72, 0x69, - 0x64, 0x69, 0x61, 0x6e, 0x73, 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdca0, 0x3a, - 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x5f, 0x73, 0x68, 0x61, 0x70, - 0x65, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x61, 0x5f, 0x64, 0x6f, 0x74, - 0x5f, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x3a, 0x61, 0x64, 0x69, 0x61, - 0x6d, 0x6f, 0x6e, 0x64, 0x64, 0x6f, 0x74, 0x69, 0x6e, 0x73, 0x69, 0x64, - 0x65, 0x73, 0x68, 0x61, 0x70, 0x65, 0x77, 0x69, 0x74, 0x68, 0x24c2, 0xfe0f, - 0x3a, 0x6d, 0x3a, 0x6d, 0xd83c, 0xdf00, 0x3a, 0x63, 0x79, 0x63, 0x6c, 0x6f, - 0x6e, 0x65, 0x3a, 0x63, 0x79, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0xd83d, 0xdca4, - 0x3a, 0x7a, 0x7a, 0x7a, 0x3a, 0x7a, 0x7a, 0x7a, 0xd83c, 0xdfe7, 0x3a, 0x61, - 0x74, 0x6d, 0x3a, 0x61, 0x74, 0x6d, 0xd83d, 0xdebe, 0x3a, 0x77, 0x63, 0x3a, - 0x77, 0x63, 0x267f, 0xfe0f, 0x3a, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x63, 0x68, - 0x61, 0x69, 0x72, 0x3a, 0x77, 0x68, 0x65, 0x65, 0x6c, 0x63, 0x68, 0x61, - 0x69, 0x72, 0xd83c, 0xdd7f, 0xfe0f, 0x3a, 0x70, 0x61, 0x72, 0x6b, 0x69, 0x6e, - 0x67, 0x3a, 0x70, 0x61, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0xd83c, 0xde33, 0x3a, - 0x75, 0x37, 0x61, 0x37, 0x61, 0x3a, 0x75, 0x37, 0x61, 0x37, 0x61, 0xd83c, - 0xde02, 0xfe0f, 0x3a, 0x73, 0x61, 0x3a, 0x73, 0x61, 0xd83d, 0xdec2, 0x3a, 0x70, - 0x61, 0x73, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x3a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, - 0x61, 0x73, 0x73, 0x70, 0x6f, 0x72, 0x74, 0xd83d, 0xdec3, 0x3a, 0x63, 0x75, - 0x73, 0x74, 0x6f, 0x6d, 0x73, 0x3a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, - 0x73, 0xd83d, 0xdec4, 0x3a, 0x62, 0x61, 0x67, 0x67, 0x61, 0x67, 0x65, 0x5f, - 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x3a, 0x62, 0x61, 0x67, 0x67, 0x61, 0x67, - 0x65, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0xd83d, 0xdec5, 0x3a, 0x6c, 0x65, 0x66, - 0x74, 0x5f, 0x6c, 0x75, 0x67, 0x67, 0x61, 0x67, 0x65, 0x3a, 0x6c, 0x65, - 0x66, 0x74, 0x6c, 0x75, 0x67, 0x67, 0x61, 0x67, 0x65, 0xd83d, 0xdeb9, 0x3a, - 0x6d, 0x65, 0x6e, 0x73, 0x3a, 0x6d, 0x65, 0x6e, 0x73, 0xd83d, 0xdeba, 0x3a, - 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x73, 0x3a, 0x77, 0x6f, 0x6d, 0x65, 0x6e, - 0x73, 0xd83d, 0xdebc, 0x3a, 0x62, 0x61, 0x62, 0x79, 0x5f, 0x73, 0x79, 0x6d, - 0x62, 0x6f, 0x6c, 0x3a, 0x62, 0x61, 0x62, 0x79, 0x73, 0x79, 0x6d, 0x62, - 0x6f, 0x6c, 0xd83d, 0xdebb, 0x3a, 0x72, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x6f, - 0x6d, 0x3a, 0x72, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x6f, 0x6d, 0xd83d, 0xdeae, - 0x3a, 0x70, 0x75, 0x74, 0x5f, 0x6c, 0x69, 0x74, 0x74, 0x65, 0x72, 0x5f, - 0x69, 0x6e, 0x5f, 0x69, 0x74, 0x73, 0x5f, 0x70, 0x6c, 0x61, 0x63, 0x65, - 0x3a, 0x69, 0x6e, 0x69, 0x74, 0x73, 0x6c, 0x69, 0x74, 0x74, 0x65, 0x72, - 0x70, 0x6c, 0x61, 0x63, 0x65, 0x70, 0x75, 0x74, 0xd83c, 0xdfa6, 0x3a, 0x63, - 0x69, 0x6e, 0x65, 0x6d, 0x61, 0x3a, 0x63, 0x69, 0x6e, 0x65, 0x6d, 0x61, - 0xd83d, 0xdcf6, 0x3a, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x74, - 0x72, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x6c, 0x73, 0x74, 0x72, 0x65, 0x6e, 0x67, 0x74, 0x68, 0xd83c, 0xde01, 0x3a, - 0x6b, 0x6f, 0x6b, 0x6f, 0x3a, 0x6b, 0x6f, 0x6b, 0x6f, 0xd83d, 0xdd23, 0x3a, - 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x3a, 0x73, 0x79, 0x6d, 0x62, - 0x6f, 0x6c, 0x73, 0x2139, 0xfe0f, 0x3a, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x3a, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0xd83d, 0xdd24, 0x3a, 0x61, 0x62, 0x63, - 0x3a, 0x61, 0x62, 0x63, 0xd83d, 0xdd21, 0x3a, 0x61, 0x62, 0x63, 0x64, 0x3a, - 0x61, 0x62, 0x63, 0x64, 0xd83d, 0xdd20, 0x3a, 0x63, 0x61, 0x70, 0x69, 0x74, - 0x61, 0x6c, 0x5f, 0x61, 0x62, 0x63, 0x64, 0x3a, 0x61, 0x62, 0x63, 0x64, - 0x63, 0x61, 0x70, 0x69, 0x74, 0x61, 0x6c, 0xd83c, 0xdd96, 0x3a, 0x6e, 0x67, - 0x3a, 0x6e, 0x67, 0xd83c, 0xdd97, 0x3a, 0x6f, 0x6b, 0x3a, 0x6f, 0x6b, 0xd83c, - 0xdd99, 0x3a, 0x75, 0x70, 0x3a, 0x75, 0x70, 0xd83c, 0xdd92, 0x3a, 0x63, 0x6f, - 0x6f, 0x6c, 0x3a, 0x63, 0x6f, 0x6f, 0x6c, 0xd83c, 0xdd95, 0x3a, 0x6e, 0x65, - 0x77, 0x3a, 0x6e, 0x65, 0x77, 0xd83c, 0xdd93, 0x3a, 0x66, 0x72, 0x65, 0x65, - 0x3a, 0x66, 0x72, 0x65, 0x65, 0x30, 0xfe0f, 0x20e3, 0x3a, 0x7a, 0x65, 0x72, - 0x6f, 0x3a, 0x7a, 0x65, 0x72, 0x6f, 0x31, 0xfe0f, 0x20e3, 0x3a, 0x6f, 0x6e, - 0x65, 0x3a, 0x6f, 0x6e, 0x65, 0x32, 0xfe0f, 0x20e3, 0x3a, 0x74, 0x77, 0x6f, - 0x3a, 0x74, 0x77, 0x6f, 0x33, 0xfe0f, 0x20e3, 0x3a, 0x74, 0x68, 0x72, 0x65, - 0x65, 0x3a, 0x74, 0x68, 0x72, 0x65, 0x65, 0x34, 0xfe0f, 0x20e3, 0x3a, 0x66, - 0x6f, 0x75, 0x72, 0x3a, 0x66, 0x6f, 0x75, 0x72, 0x35, 0xfe0f, 0x20e3, 0x3a, - 0x66, 0x69, 0x76, 0x65, 0x3a, 0x66, 0x69, 0x76, 0x65, 0x36, 0xfe0f, 0x20e3, - 0x3a, 0x73, 0x69, 0x78, 0x3a, 0x73, 0x69, 0x78, 0x37, 0xfe0f, 0x20e3, 0x3a, - 0x73, 0x65, 0x76, 0x65, 0x6e, 0x3a, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x38, - 0xfe0f, 0x20e3, 0x3a, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x39, 0xfe0f, 0x20e3, 0x3a, 0x6e, 0x69, 0x6e, 0x65, 0x3a, 0x6e, - 0x69, 0x6e, 0x65, 0xd83d, 0xdd1f, 0x3a, 0x6b, 0x65, 0x79, 0x63, 0x61, 0x70, - 0x5f, 0x74, 0x65, 0x6e, 0x3a, 0x6b, 0x65, 0x79, 0x63, 0x61, 0x70, 0x74, - 0x65, 0x6e, 0xd83d, 0xdd22, 0x3a, 0x31, 0x32, 0x33, 0x34, 0x3a, 0x31, 0x32, - 0x33, 0x34, 0x23, 0xfe0f, 0x20e3, 0x3a, 0x68, 0x61, 0x73, 0x68, 0x3a, 0x68, - 0x61, 0x73, 0x68, 0x2a, 0xfe0f, 0x20e3, 0x3a, 0x6b, 0x65, 0x79, 0x63, 0x61, - 0x70, 0x5f, 0x61, 0x73, 0x74, 0x65, 0x72, 0x69, 0x73, 0x6b, 0x3a, 0x61, - 0x73, 0x74, 0x65, 0x72, 0x69, 0x73, 0x6b, 0x6b, 0x65, 0x79, 0x63, 0x61, - 0x70, 0x2a, 0xfe0f, 0x20e3, 0x3a, 0x61, 0x73, 0x74, 0x65, 0x72, 0x69, 0x73, - 0x6b, 0x3a, 0x61, 0x73, 0x74, 0x65, 0x72, 0x69, 0x73, 0x6b, 0x23cf, 0xfe0f, - 0x3a, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, - 0x6c, 0x3a, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x79, 0x6d, 0x62, 0x6f, - 0x6c, 0x23cf, 0xfe0f, 0x3a, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x3a, 0x65, 0x6a, - 0x65, 0x63, 0x74, 0x25b6, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, - 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x3a, 0x61, 0x72, 0x72, 0x6f, - 0x77, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x23f8, 0x3a, 0x64, 0x6f, - 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, - 0x6c, 0x5f, 0x62, 0x61, 0x72, 0x3a, 0x62, 0x61, 0x72, 0x64, 0x6f, 0x75, - 0x62, 0x6c, 0x65, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x23f8, - 0x3a, 0x70, 0x61, 0x75, 0x73, 0x65, 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, - 0x6e, 0x3a, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x70, 0x61, 0x75, 0x73, - 0x65, 0x23ef, 0x3a, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x70, 0x61, 0x75, 0x73, - 0x65, 0x3a, 0x70, 0x61, 0x75, 0x73, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x23f9, - 0x3a, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, - 0x3a, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x73, 0x74, 0x6f, 0x70, 0x23fa, - 0x3a, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f, 0x62, 0x75, 0x74, 0x74, - 0x6f, 0x6e, 0x3a, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x72, 0x65, 0x63, - 0x6f, 0x72, 0x64, 0x23ed, 0x3a, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x74, 0x72, - 0x61, 0x63, 0x6b, 0x3a, 0x6e, 0x65, 0x78, 0x74, 0x74, 0x72, 0x61, 0x63, - 0x6b, 0x23ed, 0x3a, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x6e, 0x65, 0x78, - 0x74, 0x3a, 0x6e, 0x65, 0x78, 0x74, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x23ee, - 0x3a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x74, 0x72, - 0x61, 0x63, 0x6b, 0x3a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, - 0x74, 0x72, 0x61, 0x63, 0x6b, 0x23ee, 0x3a, 0x74, 0x72, 0x61, 0x63, 0x6b, - 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x3a, 0x70, 0x72, - 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x23e9, - 0x3a, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, - 0x64, 0x3a, 0x66, 0x61, 0x73, 0x74, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, - 0x64, 0x23ea, 0x3a, 0x72, 0x65, 0x77, 0x69, 0x6e, 0x64, 0x3a, 0x72, 0x65, - 0x77, 0x69, 0x6e, 0x64, 0x23eb, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, - 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x75, 0x70, 0x3a, 0x61, 0x72, - 0x72, 0x6f, 0x77, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x75, 0x70, 0x23ec, - 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x64, 0x6f, 0x75, 0x62, 0x6c, - 0x65, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, - 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x64, 0x6f, 0x77, 0x6e, 0x25c0, 0xfe0f, - 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x77, - 0x61, 0x72, 0x64, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x62, 0x61, 0x63, - 0x6b, 0x77, 0x61, 0x72, 0x64, 0xd83d, 0xdd3c, 0x3a, 0x61, 0x72, 0x72, 0x6f, - 0x77, 0x5f, 0x75, 0x70, 0x5f, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x3a, 0x61, - 0x72, 0x72, 0x6f, 0x77, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x75, 0x70, 0xd83d, - 0xdd3d, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x64, 0x6f, 0x77, 0x6e, - 0x5f, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, - 0x64, 0x6f, 0x77, 0x6e, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x27a1, 0xfe0f, 0x3a, - 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, - 0x61, 0x72, 0x72, 0x6f, 0x77, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2b05, 0xfe0f, - 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x6c, 0x65, 0x66, 0x74, 0x3a, - 0x61, 0x72, 0x72, 0x6f, 0x77, 0x6c, 0x65, 0x66, 0x74, 0x2b06, 0xfe0f, 0x3a, - 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x75, 0x70, 0x3a, 0x61, 0x72, 0x72, - 0x6f, 0x77, 0x75, 0x70, 0x2b07, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, - 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x64, - 0x6f, 0x77, 0x6e, 0x2197, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, - 0x75, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, - 0x61, 0x72, 0x72, 0x6f, 0x77, 0x72, 0x69, 0x67, 0x68, 0x74, 0x75, 0x70, - 0x70, 0x65, 0x72, 0x2198, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, - 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, - 0x61, 0x72, 0x72, 0x6f, 0x77, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x72, 0x69, - 0x67, 0x68, 0x74, 0x2199, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, - 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x61, - 0x72, 0x72, 0x6f, 0x77, 0x6c, 0x65, 0x66, 0x74, 0x6c, 0x6f, 0x77, 0x65, - 0x72, 0x2196, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x75, 0x70, - 0x70, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x61, 0x72, 0x72, - 0x6f, 0x77, 0x6c, 0x65, 0x66, 0x74, 0x75, 0x70, 0x70, 0x65, 0x72, 0x2195, - 0xfe0f, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x75, 0x70, 0x5f, 0x64, - 0x6f, 0x77, 0x6e, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x64, 0x6f, 0x77, - 0x6e, 0x75, 0x70, 0x2194, 0xfe0f, 0x3a, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x72, - 0x69, 0x67, 0x68, 0x74, 0x5f, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x3a, 0x61, - 0x72, 0x72, 0x6f, 0x77, 0x6c, 0x65, 0x66, 0x74, 0x72, 0x69, 0x67, 0x68, - 0x74, 0x21aa, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x72, 0x69, - 0x67, 0x68, 0x74, 0x5f, 0x68, 0x6f, 0x6f, 0x6b, 0x3a, 0x61, 0x72, 0x72, - 0x6f, 0x77, 0x68, 0x6f, 0x6f, 0x6b, 0x72, 0x69, 0x67, 0x68, 0x74, 0x21a9, - 0xfe0f, 0x3a, 0x6c, 0x65, 0x66, 0x74, 0x77, 0x61, 0x72, 0x64, 0x73, 0x5f, - 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x68, - 0x6f, 0x6f, 0x6b, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x68, 0x6f, 0x6f, - 0x6b, 0x6c, 0x65, 0x66, 0x74, 0x77, 0x61, 0x72, 0x64, 0x73, 0x77, 0x69, - 0x74, 0x68, 0x2934, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x68, - 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x70, 0x3a, 0x61, 0x72, - 0x72, 0x6f, 0x77, 0x68, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x75, 0x70, - 0x2935, 0xfe0f, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x5f, 0x68, 0x65, 0x61, - 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x3a, 0x61, 0x72, - 0x72, 0x6f, 0x77, 0x64, 0x6f, 0x77, 0x6e, 0x68, 0x65, 0x61, 0x64, 0x69, - 0x6e, 0x67, 0xd83d, 0xdd00, 0x3a, 0x74, 0x77, 0x69, 0x73, 0x74, 0x65, 0x64, - 0x5f, 0x72, 0x69, 0x67, 0x68, 0x74, 0x77, 0x61, 0x72, 0x64, 0x73, 0x5f, - 0x61, 0x72, 0x72, 0x6f, 0x77, 0x73, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, - 0x73, 0x72, 0x69, 0x67, 0x68, 0x74, 0x77, 0x61, 0x72, 0x64, 0x73, 0x74, - 0x77, 0x69, 0x73, 0x74, 0x65, 0x64, 0xd83d, 0xdd01, 0x3a, 0x72, 0x65, 0x70, - 0x65, 0x61, 0x74, 0x3a, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0xd83d, 0xdd02, - 0x3a, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x5f, 0x6f, 0x6e, 0x65, 0x3a, - 0x6f, 0x6e, 0x65, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0xd83d, 0xdd04, 0x3a, - 0x61, 0x72, 0x72, 0x6f, 0x77, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x65, 0x72, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x77, 0x69, 0x73, 0x65, 0x3a, - 0x61, 0x72, 0x72, 0x6f, 0x77, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, - 0x72, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x77, 0x69, 0x73, 0x65, 0xd83d, 0xdd03, - 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x73, 0x5f, 0x63, 0x6c, 0x6f, 0x63, - 0x6b, 0x77, 0x69, 0x73, 0x65, 0x3a, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x73, - 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x77, 0x69, 0x73, 0x65, 0xd83c, 0xdfb5, 0x3a, - 0x6d, 0x75, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x6e, 0x6f, 0x74, 0x65, - 0x3a, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x6e, 0x6f, 0x74, 0x65, - 0xd83c, 0xdfb6, 0x3a, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x3a, 0x6e, 0x6f, 0x74, - 0x65, 0x73, 0x2795, 0x3a, 0x68, 0x65, 0x61, 0x76, 0x79, 0x5f, 0x70, 0x6c, - 0x75, 0x73, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x3a, 0x68, 0x65, 0x61, 0x76, - 0x79, 0x70, 0x6c, 0x75, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x2796, 0x3a, 0x68, - 0x65, 0x61, 0x76, 0x79, 0x5f, 0x6d, 0x69, 0x6e, 0x75, 0x73, 0x5f, 0x73, - 0x69, 0x67, 0x6e, 0x3a, 0x68, 0x65, 0x61, 0x76, 0x79, 0x6d, 0x69, 0x6e, - 0x75, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x2797, 0x3a, 0x68, 0x65, 0x61, 0x76, - 0x79, 0x5f, 0x64, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, - 0x69, 0x67, 0x6e, 0x3a, 0x64, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x68, 0x65, 0x61, 0x76, 0x79, 0x73, 0x69, 0x67, 0x6e, 0x2716, 0xfe0f, 0x3a, - 0x68, 0x65, 0x61, 0x76, 0x79, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x78, 0x3a, 0x68, - 0x65, 0x61, 0x76, 0x79, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x78, 0xd83d, 0xdcb2, 0x3a, 0x68, 0x65, - 0x61, 0x76, 0x79, 0x5f, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x5f, 0x73, - 0x69, 0x67, 0x6e, 0x3a, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x68, 0x65, - 0x61, 0x76, 0x79, 0x73, 0x69, 0x67, 0x6e, 0xd83d, 0xdcb1, 0x3a, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x65, 0x78, 0x63, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x3a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, - 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2122, 0xfe0f, 0x3a, 0x74, - 0x6d, 0x3a, 0x74, 0x6d, 0xa9, 0xfe0f, 0x3a, 0x63, 0x6f, 0x70, 0x79, 0x72, - 0x69, 0x67, 0x68, 0x74, 0x3a, 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, - 0x68, 0x74, 0xae, 0xfe0f, 0x3a, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x65, 0x64, 0x3a, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, - 0x65, 0x64, 0xd83d, 0xdde8, 0x3a, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x73, 0x70, - 0x65, 0x65, 0x63, 0x68, 0x5f, 0x62, 0x75, 0x62, 0x62, 0x6c, 0x65, 0x3a, - 0x62, 0x75, 0x62, 0x62, 0x6c, 0x65, 0x6c, 0x65, 0x66, 0x74, 0x73, 0x70, - 0x65, 0x65, 0x63, 0x68, 0xd83d, 0xdde8, 0x3a, 0x73, 0x70, 0x65, 0x65, 0x63, - 0x68, 0x5f, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x6c, 0x65, 0x66, 0x74, 0x73, - 0x70, 0x65, 0x65, 0x63, 0x68, 0xd83d, 0xdc41, 0x200d, 0xd83d, 0xdde8, 0x3a, 0x65, - 0x79, 0x65, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x65, 0x63, 0x68, - 0x5f, 0x62, 0x75, 0x62, 0x62, 0x6c, 0x65, 0x3a, 0x62, 0x75, 0x62, 0x62, - 0x6c, 0x65, 0x65, 0x79, 0x65, 0x69, 0x6e, 0x73, 0x70, 0x65, 0x65, 0x63, - 0x68, 0xd83d, 0xdd1a, 0x3a, 0x65, 0x6e, 0x64, 0x3a, 0x65, 0x6e, 0x64, 0xd83d, - 0xdd19, 0x3a, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x62, 0x61, 0x63, 0x6b, 0xd83d, - 0xdd1b, 0x3a, 0x6f, 0x6e, 0x3a, 0x6f, 0x6e, 0xd83d, 0xdd1d, 0x3a, 0x74, 0x6f, - 0x70, 0x3a, 0x74, 0x6f, 0x70, 0xd83d, 0xdd1c, 0x3a, 0x73, 0x6f, 0x6f, 0x6e, - 0x3a, 0x73, 0x6f, 0x6f, 0x6e, 0x3030, 0xfe0f, 0x3a, 0x77, 0x61, 0x76, 0x79, - 0x5f, 0x64, 0x61, 0x73, 0x68, 0x3a, 0x64, 0x61, 0x73, 0x68, 0x77, 0x61, - 0x76, 0x79, 0x27b0, 0x3a, 0x63, 0x75, 0x72, 0x6c, 0x79, 0x5f, 0x6c, 0x6f, - 0x6f, 0x70, 0x3a, 0x63, 0x75, 0x72, 0x6c, 0x79, 0x6c, 0x6f, 0x6f, 0x70, - 0x27bf, 0x3a, 0x6c, 0x6f, 0x6f, 0x70, 0x3a, 0x6c, 0x6f, 0x6f, 0x70, 0x2714, - 0xfe0f, 0x3a, 0x68, 0x65, 0x61, 0x76, 0x79, 0x5f, 0x63, 0x68, 0x65, 0x63, - 0x6b, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x3a, 0x63, 0x68, 0x65, 0x63, 0x6b, - 0x68, 0x65, 0x61, 0x76, 0x79, 0x6d, 0x61, 0x72, 0x6b, 0x2611, 0xfe0f, 0x3a, - 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x74, 0x5f, 0x62, 0x6f, 0x78, 0x5f, 0x77, - 0x69, 0x74, 0x68, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x3a, 0x62, 0x61, - 0x6c, 0x6c, 0x6f, 0x74, 0x62, 0x6f, 0x78, 0x63, 0x68, 0x65, 0x63, 0x6b, - 0x77, 0x69, 0x74, 0x68, 0xd83d, 0xdd18, 0x3a, 0x72, 0x61, 0x64, 0x69, 0x6f, - 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x62, 0x75, 0x74, 0x74, - 0x6f, 0x6e, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x26aa, 0xfe0f, 0x3a, 0x77, 0x68, - 0x69, 0x74, 0x65, 0x5f, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x3a, 0x63, - 0x69, 0x72, 0x63, 0x6c, 0x65, 0x77, 0x68, 0x69, 0x74, 0x65, 0x26ab, 0xfe0f, - 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x69, 0x72, 0x63, 0x6c, - 0x65, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x63, 0x69, 0x72, 0x63, 0x6c, - 0x65, 0xd83d, 0xdd34, 0x3a, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x69, 0x72, 0x63, - 0x6c, 0x65, 0x3a, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x72, 0x65, 0x64, - 0xd83d, 0xdd35, 0x3a, 0x62, 0x6c, 0x75, 0x65, 0x5f, 0x63, 0x69, 0x72, 0x63, - 0x6c, 0x65, 0x3a, 0x62, 0x6c, 0x75, 0x65, 0x63, 0x69, 0x72, 0x63, 0x6c, - 0x65, 0xd83d, 0xdd3a, 0x3a, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, 0x72, 0x65, - 0x64, 0x5f, 0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, 0x6c, 0x65, 0x3a, 0x72, - 0x65, 0x64, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x74, 0x72, 0x69, 0x61, 0x6e, - 0x67, 0x6c, 0x65, 0xd83d, 0xdd3b, 0x3a, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, - 0x72, 0x65, 0x64, 0x5f, 0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, 0x6c, 0x65, - 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x3a, 0x64, 0x6f, 0x77, 0x6e, 0x72, 0x65, - 0x64, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, - 0x6c, 0x65, 0xd83d, 0xdd38, 0x3a, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, 0x6f, - 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, - 0x64, 0x3a, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x6f, 0x72, 0x61, - 0x6e, 0x67, 0x65, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0xd83d, 0xdd39, 0x3a, 0x73, - 0x6d, 0x61, 0x6c, 0x6c, 0x5f, 0x62, 0x6c, 0x75, 0x65, 0x5f, 0x64, 0x69, - 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x3a, 0x62, 0x6c, 0x75, 0x65, 0x64, 0x69, - 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0xd83d, 0xdd36, - 0x3a, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x6f, 0x72, 0x61, 0x6e, 0x67, - 0x65, 0x5f, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x3a, 0x64, 0x69, - 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x6f, 0x72, - 0x61, 0x6e, 0x67, 0x65, 0xd83d, 0xdd37, 0x3a, 0x6c, 0x61, 0x72, 0x67, 0x65, - 0x5f, 0x62, 0x6c, 0x75, 0x65, 0x5f, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, - 0x64, 0x3a, 0x62, 0x6c, 0x75, 0x65, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, - 0x64, 0x6c, 0x61, 0x72, 0x67, 0x65, 0xd83d, 0xdd33, 0x3a, 0x77, 0x68, 0x69, - 0x74, 0x65, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x5f, 0x62, 0x75, - 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x73, - 0x71, 0x75, 0x61, 0x72, 0x65, 0x77, 0x68, 0x69, 0x74, 0x65, 0xd83d, 0xdd32, - 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, - 0x65, 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x62, 0x6c, 0x61, - 0x63, 0x6b, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x73, 0x71, 0x75, 0x61, - 0x72, 0x65, 0x25aa, 0xfe0f, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x5f, 0x73, - 0x6d, 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x3a, - 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x73, 0x71, - 0x75, 0x61, 0x72, 0x65, 0x25ab, 0xfe0f, 0x3a, 0x77, 0x68, 0x69, 0x74, 0x65, - 0x5f, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, - 0x65, 0x3a, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x73, 0x71, 0x75, 0x61, 0x72, - 0x65, 0x77, 0x68, 0x69, 0x74, 0x65, 0x25fe, 0xfe0f, 0x3a, 0x62, 0x6c, 0x61, - 0x63, 0x6b, 0x5f, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x5f, 0x73, 0x6d, - 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x3a, 0x62, - 0x6c, 0x61, 0x63, 0x6b, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x73, 0x6d, - 0x61, 0x6c, 0x6c, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x25fd, 0xfe0f, 0x3a, - 0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, - 0x5f, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, - 0x65, 0x3a, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x73, 0x6d, 0x61, 0x6c, - 0x6c, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x77, 0x68, 0x69, 0x74, 0x65, - 0x25fc, 0xfe0f, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x5f, 0x6d, 0x65, 0x64, - 0x69, 0x75, 0x6d, 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x3a, 0x62, - 0x6c, 0x61, 0x63, 0x6b, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x73, 0x71, - 0x75, 0x61, 0x72, 0x65, 0x25fb, 0xfe0f, 0x3a, 0x77, 0x68, 0x69, 0x74, 0x65, - 0x5f, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x5f, 0x73, 0x71, 0x75, 0x61, - 0x72, 0x65, 0x3a, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x73, 0x71, 0x75, - 0x61, 0x72, 0x65, 0x77, 0x68, 0x69, 0x74, 0x65, 0x2b1b, 0xfe0f, 0x3a, 0x62, - 0x6c, 0x61, 0x63, 0x6b, 0x5f, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x73, - 0x71, 0x75, 0x61, 0x72, 0x65, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x6c, - 0x61, 0x72, 0x67, 0x65, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x2b1c, 0xfe0f, - 0x3a, 0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, 0x6c, 0x61, 0x72, 0x67, 0x65, - 0x5f, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x3a, 0x6c, 0x61, 0x72, 0x67, - 0x65, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x77, 0x68, 0x69, 0x74, 0x65, - 0xd83d, 0xdd08, 0x3a, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x3a, 0x73, - 0x70, 0x65, 0x61, 0x6b, 0x65, 0x72, 0xd83d, 0xdd07, 0x3a, 0x6d, 0x75, 0x74, - 0x65, 0x3a, 0x6d, 0x75, 0x74, 0x65, 0xd83d, 0xdd09, 0x3a, 0x73, 0x6f, 0x75, - 0x6e, 0x64, 0x3a, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0xd83d, 0xdd0a, 0x3a, 0x6c, - 0x6f, 0x75, 0x64, 0x5f, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x6c, 0x6f, - 0x75, 0x64, 0x73, 0x6f, 0x75, 0x6e, 0x64, 0xd83d, 0xdd14, 0x3a, 0x62, 0x65, - 0x6c, 0x6c, 0x3a, 0x62, 0x65, 0x6c, 0x6c, 0xd83d, 0xdd15, 0x3a, 0x6e, 0x6f, - 0x5f, 0x62, 0x65, 0x6c, 0x6c, 0x3a, 0x62, 0x65, 0x6c, 0x6c, 0x6e, 0x6f, - 0xd83d, 0xdce3, 0x3a, 0x6d, 0x65, 0x67, 0x61, 0x3a, 0x6d, 0x65, 0x67, 0x61, - 0xd83d, 0xdce2, 0x3a, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x70, 0x65, 0x61, 0x6b, - 0x65, 0x72, 0x3a, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x70, 0x65, 0x61, 0x6b, - 0x65, 0x72, 0xd83d, 0xdcac, 0x3a, 0x73, 0x70, 0x65, 0x65, 0x63, 0x68, 0x5f, - 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x6f, 0x6e, 0x3a, 0x62, 0x61, 0x6c, 0x6c, - 0x6f, 0x6f, 0x6e, 0x73, 0x70, 0x65, 0x65, 0x63, 0x68, 0xd83d, 0xdcad, 0x3a, - 0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x5f, 0x62, 0x61, 0x6c, 0x6c, - 0x6f, 0x6f, 0x6e, 0x3a, 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x6f, 0x6e, 0x74, - 0x68, 0x6f, 0x75, 0x67, 0x68, 0x74, 0xd83d, 0xddef, 0x3a, 0x72, 0x69, 0x67, - 0x68, 0x74, 0x5f, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x62, 0x75, 0x62, - 0x62, 0x6c, 0x65, 0x3a, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x62, 0x75, 0x62, - 0x62, 0x6c, 0x65, 0x72, 0x69, 0x67, 0x68, 0x74, 0xd83d, 0xddef, 0x3a, 0x61, - 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x61, - 0x6e, 0x67, 0x65, 0x72, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2660, 0xfe0f, 0x3a, - 0x73, 0x70, 0x61, 0x64, 0x65, 0x73, 0x3a, 0x73, 0x70, 0x61, 0x64, 0x65, - 0x73, 0x2663, 0xfe0f, 0x3a, 0x63, 0x6c, 0x75, 0x62, 0x73, 0x3a, 0x63, 0x6c, - 0x75, 0x62, 0x73, 0x2665, 0xfe0f, 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x73, - 0x3a, 0x68, 0x65, 0x61, 0x72, 0x74, 0x73, 0x2666, 0xfe0f, 0x3a, 0x64, 0x69, - 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x73, 0x3a, 0x64, 0x69, 0x61, 0x6d, 0x6f, - 0x6e, 0x64, 0x73, 0xd83c, 0xdccf, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x5f, - 0x6a, 0x6f, 0x6b, 0x65, 0x72, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x6a, - 0x6f, 0x6b, 0x65, 0x72, 0xd83c, 0xdfb4, 0x3a, 0x66, 0x6c, 0x6f, 0x77, 0x65, - 0x72, 0x5f, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x61, - 0x72, 0x64, 0x73, 0x3a, 0x63, 0x61, 0x72, 0x64, 0x73, 0x66, 0x6c, 0x6f, - 0x77, 0x65, 0x72, 0x70, 0x6c, 0x61, 0x79, 0x69, 0x6e, 0x67, 0xd83c, 0xdc04, - 0xfe0f, 0x3a, 0x6d, 0x61, 0x68, 0x6a, 0x6f, 0x6e, 0x67, 0x3a, 0x6d, 0x61, - 0x68, 0x6a, 0x6f, 0x6e, 0x67, 0xd83d, 0xdd50, 0x3a, 0x63, 0x6c, 0x6f, 0x63, - 0x6b, 0x31, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0xd83d, 0xdd51, 0x3a, - 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x32, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, - 0x32, 0xd83d, 0xdd52, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x33, 0x3a, 0x63, - 0x6c, 0x6f, 0x63, 0x6b, 0x33, 0xd83d, 0xdd53, 0x3a, 0x63, 0x6c, 0x6f, 0x63, - 0x6b, 0x34, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x34, 0xd83d, 0xdd54, 0x3a, - 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x35, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, - 0x35, 0xd83d, 0xdd55, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x36, 0x3a, 0x63, - 0x6c, 0x6f, 0x63, 0x6b, 0x36, 0xd83d, 0xdd56, 0x3a, 0x63, 0x6c, 0x6f, 0x63, - 0x6b, 0x37, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x37, 0xd83d, 0xdd57, 0x3a, - 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x38, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, - 0x38, 0xd83d, 0xdd58, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x39, 0x3a, 0x63, - 0x6c, 0x6f, 0x63, 0x6b, 0x39, 0xd83d, 0xdd59, 0x3a, 0x63, 0x6c, 0x6f, 0x63, - 0x6b, 0x31, 0x30, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x30, 0xd83d, - 0xdd5a, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x31, 0x3a, 0x63, 0x6c, - 0x6f, 0x63, 0x6b, 0x31, 0x31, 0xd83d, 0xdd5b, 0x3a, 0x63, 0x6c, 0x6f, 0x63, - 0x6b, 0x31, 0x32, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x32, 0xd83d, - 0xdd5c, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x33, 0x30, 0x3a, 0x63, - 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x33, 0x30, 0xd83d, 0xdd5d, 0x3a, 0x63, 0x6c, - 0x6f, 0x63, 0x6b, 0x32, 0x33, 0x30, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, - 0x32, 0x33, 0x30, 0xd83d, 0xdd5e, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x33, - 0x33, 0x30, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x33, 0x33, 0x30, 0xd83d, - 0xdd5f, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x34, 0x33, 0x30, 0x3a, 0x63, - 0x6c, 0x6f, 0x63, 0x6b, 0x34, 0x33, 0x30, 0xd83d, 0xdd60, 0x3a, 0x63, 0x6c, - 0x6f, 0x63, 0x6b, 0x35, 0x33, 0x30, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, - 0x35, 0x33, 0x30, 0xd83d, 0xdd61, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x36, - 0x33, 0x30, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x36, 0x33, 0x30, 0xd83d, - 0xdd62, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x37, 0x33, 0x30, 0x3a, 0x63, - 0x6c, 0x6f, 0x63, 0x6b, 0x37, 0x33, 0x30, 0xd83d, 0xdd63, 0x3a, 0x63, 0x6c, - 0x6f, 0x63, 0x6b, 0x38, 0x33, 0x30, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, - 0x38, 0x33, 0x30, 0xd83d, 0xdd64, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x39, - 0x33, 0x30, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x39, 0x33, 0x30, 0xd83d, - 0xdd65, 0x3a, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x30, 0x33, 0x30, 0x3a, - 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x30, 0x33, 0x30, 0xd83d, 0xdd66, 0x3a, - 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x31, 0x31, 0x33, 0x30, 0x3a, 0x63, 0x6c, - 0x6f, 0x63, 0x6b, 0x31, 0x31, 0x33, 0x30, 0xd83d, 0xdd67, 0x3a, 0x63, 0x6c, - 0x6f, 0x63, 0x6b, 0x31, 0x32, 0x33, 0x30, 0x3a, 0x63, 0x6c, 0x6f, 0x63, - 0x6b, 0x31, 0x32, 0x33, 0x30, 0xd83c, 0xdff3, 0xfe0f, 0x3a, 0x77, 0x61, 0x76, - 0x69, 0x6e, 0x67, 0x5f, 0x77, 0x68, 0x69, 0x74, 0x65, 0x5f, 0x66, 0x6c, - 0x61, 0x67, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x77, 0x61, 0x76, 0x69, 0x6e, - 0x67, 0x77, 0x68, 0x69, 0x74, 0x65, 0xd83c, 0xdff3, 0xfe0f, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x77, 0x68, 0x69, 0x74, 0x65, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x77, 0x68, 0x69, 0x74, 0x65, 0xd83c, 0xdff4, 0x3a, 0x77, 0x61, 0x76, - 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x5f, 0x66, 0x6c, - 0x61, 0x67, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x66, 0x6c, 0x61, 0x67, - 0x77, 0x61, 0x76, 0x69, 0x6e, 0x67, 0xd83c, 0xdff4, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x3a, 0x62, 0x6c, 0x61, 0x63, - 0x6b, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdfc1, 0x3a, 0x63, 0x68, 0x65, 0x63, - 0x6b, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x3a, 0x63, - 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x65, 0x64, 0x66, 0x6c, 0x61, 0x67, - 0xd83d, 0xdea9, 0x3a, 0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, - 0x72, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, - 0x73, 0x74, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6f, 0x6e, 0x70, 0x6f, 0x73, - 0x74, 0x74, 0x72, 0x69, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x72, 0xd83c, - 0xdff3, 0xfe0f, 0x200d, 0xd83c, 0xdf08, 0x3a, 0x67, 0x61, 0x79, 0x5f, 0x70, 0x72, - 0x69, 0x64, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x67, 0x61, 0x79, 0x70, 0x72, 0x69, 0x64, 0x65, 0xd83c, 0xdff3, 0xfe0f, - 0x200d, 0xd83c, 0xdf08, 0x3a, 0x72, 0x61, 0x69, 0x6e, 0x62, 0x6f, 0x77, 0x5f, - 0x66, 0x6c, 0x61, 0x67, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x72, 0x61, 0x69, - 0x6e, 0x62, 0x6f, 0x77, 0xd83c, 0xddfa, 0xd83c, 0xddf3, 0x3a, 0x75, 0x6e, 0x69, - 0x74, 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, - 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x75, 0x6e, 0x69, 0x74, 0x65, - 0x64, 0xd83c, 0xdde6, 0xd83c, 0xddeb, 0x3a, 0x61, 0x66, 0x3a, 0x61, 0x66, 0xd83c, - 0xdde6, 0xd83c, 0xddeb, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x66, 0x3a, - 0x61, 0x66, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xddfd, 0x3a, 0x61, - 0x78, 0x3a, 0x61, 0x78, 0xd83c, 0xdde6, 0xd83c, 0xddfd, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x61, 0x78, 0x3a, 0x61, 0x78, 0x66, 0x6c, 0x61, 0x67, 0xd83c, - 0xdde6, 0xd83c, 0xddf1, 0x3a, 0x61, 0x6c, 0x3a, 0x61, 0x6c, 0xd83c, 0xdde6, 0xd83c, - 0xddf1, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x6c, 0x3a, 0x61, 0x6c, - 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde9, 0xd83c, 0xddff, 0x3a, 0x64, 0x7a, 0x3a, - 0x64, 0x7a, 0xd83c, 0xdde9, 0xd83c, 0xddff, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x64, 0x7a, 0x3a, 0x64, 0x7a, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, - 0xddf8, 0x3a, 0x61, 0x73, 0x3a, 0x61, 0x73, 0xd83c, 0xdde6, 0xd83c, 0xddf8, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x73, 0x3a, 0x61, 0x73, 0x66, 0x6c, - 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xdde9, 0x3a, 0x61, 0x64, 0x3a, 0x61, 0x64, - 0xd83c, 0xdde6, 0xd83c, 0xdde9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x64, - 0x3a, 0x61, 0x64, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xddf4, 0x3a, - 0x61, 0x6f, 0x3a, 0x61, 0x6f, 0xd83c, 0xdde6, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x61, 0x6f, 0x3a, 0x61, 0x6f, 0x66, 0x6c, 0x61, 0x67, - 0xd83c, 0xdde6, 0xd83c, 0xddee, 0x3a, 0x61, 0x69, 0x3a, 0x61, 0x69, 0xd83c, 0xdde6, - 0xd83c, 0xddee, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x69, 0x3a, 0x61, - 0x69, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xddf6, 0x3a, 0x61, 0x71, - 0x3a, 0x61, 0x71, 0xd83c, 0xdde6, 0xd83c, 0xddf6, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x61, 0x71, 0x3a, 0x61, 0x71, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, - 0xd83c, 0xddec, 0x3a, 0x61, 0x67, 0x3a, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xddec, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x67, 0x3a, 0x61, 0x67, 0x66, - 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xddf7, 0x3a, 0x61, 0x72, 0x3a, 0x61, - 0x72, 0xd83c, 0xdde6, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, - 0x72, 0x3a, 0x61, 0x72, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xddf2, - 0x3a, 0x61, 0x6d, 0x3a, 0x61, 0x6d, 0xd83c, 0xdde6, 0xd83c, 0xddf2, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x6d, 0x3a, 0x61, 0x6d, 0x66, 0x6c, 0x61, - 0x67, 0xd83c, 0xdde6, 0xd83c, 0xddfc, 0x3a, 0x61, 0x77, 0x3a, 0x61, 0x77, 0xd83c, - 0xdde6, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x77, 0x3a, - 0x61, 0x77, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xddfa, 0x3a, 0x68, - 0x6d, 0x3a, 0x68, 0x6d, 0xd83c, 0xdde6, 0xd83c, 0xddfa, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x68, 0x6d, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x68, 0x6d, 0xd83c, - 0xdde6, 0xd83c, 0xddfa, 0x3a, 0x61, 0x75, 0x3a, 0x61, 0x75, 0xd83c, 0xdde6, 0xd83c, - 0xddfa, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x75, 0x3a, 0x61, 0x75, - 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, 0xddf9, 0x3a, 0x61, 0x74, 0x3a, - 0x61, 0x74, 0xd83c, 0xdde6, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x61, 0x74, 0x3a, 0x61, 0x74, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde6, 0xd83c, - 0xddff, 0x3a, 0x61, 0x7a, 0x3a, 0x61, 0x7a, 0xd83c, 0xdde6, 0xd83c, 0xddff, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x7a, 0x3a, 0x61, 0x7a, 0x66, 0x6c, - 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddf8, 0x3a, 0x62, 0x73, 0x3a, 0x62, 0x73, - 0xd83c, 0xdde7, 0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x73, - 0x3a, 0x62, 0x73, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xdded, 0x3a, - 0x62, 0x68, 0x3a, 0x62, 0x68, 0xd83c, 0xdde7, 0xd83c, 0xdded, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x62, 0x68, 0x3a, 0x62, 0x68, 0x66, 0x6c, 0x61, 0x67, - 0xd83c, 0xdde7, 0xd83c, 0xdde9, 0x3a, 0x62, 0x64, 0x3a, 0x62, 0x64, 0xd83c, 0xdde7, - 0xd83c, 0xdde9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x64, 0x3a, 0x62, - 0x64, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xdde7, 0x3a, 0x62, 0x62, - 0x3a, 0x62, 0x62, 0xd83c, 0xdde7, 0xd83c, 0xdde7, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x62, 0x62, 0x3a, 0x62, 0x62, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, - 0xd83c, 0xddfe, 0x3a, 0x62, 0x79, 0x3a, 0x62, 0x79, 0xd83c, 0xdde7, 0xd83c, 0xddfe, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x79, 0x3a, 0x62, 0x79, 0x66, - 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddea, 0x3a, 0x62, 0x65, 0x3a, 0x62, - 0x65, 0xd83c, 0xdde7, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, - 0x65, 0x3a, 0x62, 0x65, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddff, - 0x3a, 0x62, 0x7a, 0x3a, 0x62, 0x7a, 0xd83c, 0xdde7, 0xd83c, 0xddff, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x7a, 0x3a, 0x62, 0x7a, 0x66, 0x6c, 0x61, - 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddef, 0x3a, 0x62, 0x6a, 0x3a, 0x62, 0x6a, 0xd83c, - 0xdde7, 0xd83c, 0xddef, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x6a, 0x3a, - 0x62, 0x6a, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddf2, 0x3a, 0x62, - 0x6d, 0x3a, 0x62, 0x6d, 0xd83c, 0xdde7, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x62, 0x6d, 0x3a, 0x62, 0x6d, 0x66, 0x6c, 0x61, 0x67, 0xd83c, - 0xdde7, 0xd83c, 0xddf9, 0x3a, 0x62, 0x74, 0x3a, 0x62, 0x74, 0xd83c, 0xdde7, 0xd83c, - 0xddf9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x74, 0x3a, 0x62, 0x74, - 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddf4, 0x3a, 0x62, 0x6f, 0x3a, - 0x62, 0x6f, 0xd83c, 0xdde7, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x62, 0x6f, 0x3a, 0x62, 0x6f, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, - 0xdde6, 0x3a, 0x62, 0x61, 0x3a, 0x62, 0x61, 0xd83c, 0xdde7, 0xd83c, 0xdde6, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x61, 0x3a, 0x62, 0x61, 0x66, 0x6c, - 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddfc, 0x3a, 0x62, 0x77, 0x3a, 0x62, 0x77, - 0xd83c, 0xdde7, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x77, - 0x3a, 0x62, 0x77, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddf7, 0x3a, - 0x62, 0x72, 0x3a, 0x62, 0x72, 0xd83c, 0xdde7, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x62, 0x72, 0x3a, 0x62, 0x72, 0x66, 0x6c, 0x61, 0x67, - 0xd83c, 0xddee, 0xd83c, 0xddf4, 0x3a, 0x69, 0x6f, 0x3a, 0x69, 0x6f, 0xd83c, 0xddee, - 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x69, 0x6f, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x69, 0x6f, 0xd83c, 0xddee, 0xd83c, 0xddf4, 0x3a, 0x64, 0x67, - 0x3a, 0x64, 0x67, 0xd83c, 0xddee, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x64, 0x67, 0x3a, 0x64, 0x67, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddfb, - 0xd83c, 0xddec, 0x3a, 0x76, 0x67, 0x3a, 0x76, 0x67, 0xd83c, 0xddfb, 0xd83c, 0xddec, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x76, 0x67, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x76, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddf3, 0x3a, 0x62, 0x6e, 0x3a, 0x62, - 0x6e, 0xd83c, 0xdde7, 0xd83c, 0xddf3, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, - 0x6e, 0x3a, 0x62, 0x6e, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddec, - 0x3a, 0x62, 0x67, 0x3a, 0x62, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddec, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x67, 0x3a, 0x62, 0x67, 0x66, 0x6c, 0x61, - 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddeb, 0x3a, 0x62, 0x66, 0x3a, 0x62, 0x66, 0xd83c, - 0xdde7, 0xd83c, 0xddeb, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x66, 0x3a, - 0x62, 0x66, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde7, 0xd83c, 0xddee, 0x3a, 0x62, - 0x69, 0x3a, 0x62, 0x69, 0xd83c, 0xdde7, 0xd83c, 0xddee, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x62, 0x69, 0x3a, 0x62, 0x69, 0x66, 0x6c, 0x61, 0x67, 0xd83c, - 0xddf0, 0xd83c, 0xdded, 0x3a, 0x6b, 0x68, 0x3a, 0x6b, 0x68, 0xd83c, 0xddf0, 0xd83c, - 0xdded, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6b, 0x68, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x6b, 0x68, 0xd83c, 0xdde8, 0xd83c, 0xddf2, 0x3a, 0x63, 0x6d, 0x3a, - 0x63, 0x6d, 0xd83c, 0xdde8, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x63, 0x6d, 0x3a, 0x63, 0x6d, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde8, 0xd83c, - 0xdde6, 0x3a, 0x63, 0x61, 0x3a, 0x63, 0x61, 0xd83c, 0xdde8, 0xd83c, 0xdde6, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x61, 0x3a, 0x63, 0x61, 0x66, 0x6c, - 0x61, 0x67, 0xd83c, 0xddee, 0xd83c, 0xdde8, 0x3a, 0x69, 0x63, 0x3a, 0x69, 0x63, - 0xd83c, 0xddee, 0xd83c, 0xdde8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x69, 0x63, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x69, 0x63, 0xd83c, 0xdde8, 0xd83c, 0xddfb, 0x3a, - 0x63, 0x76, 0x3a, 0x63, 0x76, 0xd83c, 0xdde8, 0xd83c, 0xddfb, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x63, 0x76, 0x3a, 0x63, 0x76, 0x66, 0x6c, 0x61, 0x67, - 0xd83c, 0xdde7, 0xd83c, 0xddf6, 0x3a, 0x62, 0x71, 0x3a, 0x62, 0x71, 0xd83c, 0xdde7, - 0xd83c, 0xddf6, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x71, 0x3a, 0x62, - 0x71, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddf0, 0xd83c, 0xddfe, 0x3a, 0x6b, 0x79, - 0x3a, 0x6b, 0x79, 0xd83c, 0xddf0, 0xd83c, 0xddfe, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x6b, 0x79, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6b, 0x79, 0xd83c, 0xdde8, - 0xd83c, 0xddeb, 0x3a, 0x63, 0x66, 0x3a, 0x63, 0x66, 0xd83c, 0xdde8, 0xd83c, 0xddeb, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x66, 0x3a, 0x63, 0x66, 0x66, - 0x6c, 0x61, 0x67, 0xd83c, 0xddf9, 0xd83c, 0xdde9, 0x3a, 0x74, 0x64, 0x3a, 0x74, - 0x64, 0xd83c, 0xddf9, 0xd83c, 0xdde9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, - 0x64, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x64, 0xd83c, 0xdde8, 0xd83c, 0xddf1, - 0x3a, 0x63, 0x68, 0x69, 0x6c, 0x65, 0x3a, 0x63, 0x68, 0x69, 0x6c, 0x65, - 0xd83c, 0xdde8, 0xd83c, 0xddf1, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x6c, - 0x3a, 0x63, 0x6c, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde8, 0xd83c, 0xddf3, 0x3a, - 0x63, 0x6e, 0x3a, 0x63, 0x6e, 0xd83c, 0xdde8, 0xd83c, 0xddf3, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x63, 0x6e, 0x3a, 0x63, 0x6e, 0x66, 0x6c, 0x61, 0x67, - 0xd83c, 0xdde8, 0xd83c, 0xddfd, 0x3a, 0x63, 0x78, 0x3a, 0x63, 0x78, 0xd83c, 0xdde8, - 0xd83c, 0xddfd, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x78, 0x3a, 0x63, - 0x78, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde8, 0xd83c, 0xdde8, 0x3a, 0x63, 0x63, - 0x3a, 0x63, 0x63, 0xd83c, 0xdde8, 0xd83c, 0xdde8, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x63, 0x63, 0x3a, 0x63, 0x63, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde8, - 0xd83c, 0xddf4, 0x3a, 0x63, 0x6f, 0x3a, 0x63, 0x6f, 0xd83c, 0xdde8, 0xd83c, 0xddf4, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x6f, 0x3a, 0x63, 0x6f, 0x66, - 0x6c, 0x61, 0x67, 0xd83c, 0xddf0, 0xd83c, 0xddf2, 0x3a, 0x6b, 0x6d, 0x3a, 0x6b, - 0x6d, 0xd83c, 0xddf0, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6b, - 0x6d, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6b, 0x6d, 0xd83c, 0xdde8, 0xd83c, 0xddec, - 0x3a, 0x63, 0x67, 0x3a, 0x63, 0x67, 0xd83c, 0xdde8, 0xd83c, 0xddec, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x67, 0x3a, 0x63, 0x67, 0x66, 0x6c, 0x61, - 0x67, 0xd83c, 0xdde8, 0xd83c, 0xdde9, 0x3a, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0x3a, - 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0xd83c, 0xdde8, 0xd83c, 0xdde9, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x63, 0x64, 0x3a, 0x63, 0x64, 0x66, 0x6c, 0x61, 0x67, - 0xd83c, 0xdde8, 0xd83c, 0xddf0, 0x3a, 0x63, 0x6b, 0x3a, 0x63, 0x6b, 0xd83c, 0xdde8, - 0xd83c, 0xddf0, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x6b, 0x3a, 0x63, - 0x6b, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde8, 0xd83c, 0xddf7, 0x3a, 0x63, 0x72, - 0x3a, 0x63, 0x72, 0xd83c, 0xdde8, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x63, 0x72, 0x3a, 0x63, 0x72, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde8, - 0xd83c, 0xddee, 0x3a, 0x63, 0x69, 0x3a, 0x63, 0x69, 0xd83c, 0xdde8, 0xd83c, 0xddee, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x69, 0x3a, 0x63, 0x69, 0x66, - 0x6c, 0x61, 0x67, 0xd83c, 0xdded, 0xd83c, 0xddf7, 0x3a, 0x68, 0x72, 0x3a, 0x68, - 0x72, 0xd83c, 0xdded, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x68, - 0x72, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x68, 0x72, 0xd83c, 0xdde8, 0xd83c, 0xddfa, - 0x3a, 0x63, 0x75, 0x3a, 0x63, 0x75, 0xd83c, 0xdde8, 0xd83c, 0xddfa, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x75, 0x3a, 0x63, 0x75, 0x66, 0x6c, 0x61, - 0x67, 0xd83c, 0xdde8, 0xd83c, 0xddfc, 0x3a, 0x63, 0x77, 0x3a, 0x63, 0x77, 0xd83c, - 0xdde8, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x77, 0x3a, - 0x63, 0x77, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde8, 0xd83c, 0xddfe, 0x3a, 0x63, - 0x79, 0x3a, 0x63, 0x79, 0xd83c, 0xdde8, 0xd83c, 0xddfe, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x63, 0x79, 0x3a, 0x63, 0x79, 0x66, 0x6c, 0x61, 0x67, 0xd83c, - 0xdde8, 0xd83c, 0xddff, 0x3a, 0x63, 0x7a, 0x3a, 0x63, 0x7a, 0xd83c, 0xdde8, 0xd83c, - 0xddff, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x7a, 0x3a, 0x63, 0x7a, - 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde9, 0xd83c, 0xddf0, 0x3a, 0x64, 0x6b, 0x3a, - 0x64, 0x6b, 0xd83c, 0xdde9, 0xd83c, 0xddf0, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x64, 0x6b, 0x3a, 0x64, 0x6b, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde9, 0xd83c, - 0xddef, 0x3a, 0x64, 0x6a, 0x3a, 0x64, 0x6a, 0xd83c, 0xdde9, 0xd83c, 0xddef, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x64, 0x6a, 0x3a, 0x64, 0x6a, 0x66, 0x6c, - 0x61, 0x67, 0xd83c, 0xdde9, 0xd83c, 0xddf2, 0x3a, 0x64, 0x6d, 0x3a, 0x64, 0x6d, - 0xd83c, 0xdde9, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x64, 0x6d, - 0x3a, 0x64, 0x6d, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xdde9, 0xd83c, 0xddf4, 0x3a, - 0x64, 0x6f, 0x3a, 0x64, 0x6f, 0xd83c, 0xdde9, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x64, 0x6f, 0x3a, 0x64, 0x6f, 0x66, 0x6c, 0x61, 0x67, - 0xd83c, 0xddea, 0xd83c, 0xdde8, 0x3a, 0x65, 0x63, 0x3a, 0x65, 0x63, 0xd83c, 0xddea, - 0xd83c, 0xdde8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x65, 0x63, 0x3a, 0x65, - 0x63, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddea, 0xd83c, 0xddec, 0x3a, 0x65, 0x67, - 0x3a, 0x65, 0x67, 0xd83c, 0xddea, 0xd83c, 0xddec, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x65, 0x67, 0x3a, 0x65, 0x67, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddf8, - 0xd83c, 0xddfb, 0x3a, 0x73, 0x76, 0x3a, 0x73, 0x76, 0xd83c, 0xddf8, 0xd83c, 0xddfb, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x76, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x73, 0x76, 0xd83c, 0xddec, 0xd83c, 0xddf6, 0x3a, 0x67, 0x71, 0x3a, 0x67, - 0x71, 0xd83c, 0xddec, 0xd83c, 0xddf6, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, - 0x71, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x71, 0xd83c, 0xddea, 0xd83c, 0xddf7, - 0x3a, 0x65, 0x72, 0x3a, 0x65, 0x72, 0xd83c, 0xddea, 0xd83c, 0xddf7, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x65, 0x72, 0x3a, 0x65, 0x72, 0x66, 0x6c, 0x61, - 0x67, 0xd83c, 0xddea, 0xd83c, 0xddea, 0x3a, 0x65, 0x65, 0x3a, 0x65, 0x65, 0xd83c, - 0xddea, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x65, 0x65, 0x3a, - 0x65, 0x65, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddea, 0xd83c, 0xddf9, 0x3a, 0x65, - 0x74, 0x3a, 0x65, 0x74, 0xd83c, 0xddea, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x65, 0x74, 0x3a, 0x65, 0x74, 0x66, 0x6c, 0x61, 0x67, 0xd83c, - 0xddea, 0xd83c, 0xddfa, 0x3a, 0x65, 0x75, 0x3a, 0x65, 0x75, 0xd83c, 0xddea, 0xd83c, - 0xddfa, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x65, 0x75, 0x3a, 0x65, 0x75, - 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddeb, 0xd83c, 0xddf0, 0x3a, 0x66, 0x6b, 0x3a, - 0x66, 0x6b, 0xd83c, 0xddeb, 0xd83c, 0xddf0, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x66, 0x6b, 0x3a, 0x66, 0x6b, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddeb, 0xd83c, - 0xddf4, 0x3a, 0x66, 0x6f, 0x3a, 0x66, 0x6f, 0xd83c, 0xddeb, 0xd83c, 0xddf4, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x66, 0x6f, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x66, 0x6f, 0xd83c, 0xddeb, 0xd83c, 0xddef, 0x3a, 0x66, 0x6a, 0x3a, 0x66, 0x6a, - 0xd83c, 0xddeb, 0xd83c, 0xddef, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x66, 0x6a, - 0x3a, 0x66, 0x6a, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddeb, 0xd83c, 0xddee, 0x3a, - 0x66, 0x69, 0x3a, 0x66, 0x69, 0xd83c, 0xddeb, 0xd83c, 0xddee, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x66, 0x69, 0x3a, 0x66, 0x69, 0x66, 0x6c, 0x61, 0x67, - 0xd83c, 0xddeb, 0xd83c, 0xddf7, 0x3a, 0x6d, 0x66, 0x3a, 0x6d, 0x66, 0xd83c, 0xddeb, - 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x66, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x6d, 0x66, 0xd83c, 0xddeb, 0xd83c, 0xddf7, 0x3a, 0x66, 0x72, - 0x3a, 0x66, 0x72, 0xd83c, 0xddeb, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x66, 0x72, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x66, 0x72, 0xd83c, 0xddeb, - 0xd83c, 0xddf7, 0x3a, 0x63, 0x70, 0x3a, 0x63, 0x70, 0xd83c, 0xddeb, 0xd83c, 0xddf7, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, 0x70, 0x3a, 0x63, 0x70, 0x66, - 0x6c, 0x61, 0x67, 0xd83c, 0xddec, 0xd83c, 0xddeb, 0x3a, 0x67, 0x66, 0x3a, 0x67, - 0x66, 0xd83c, 0xddec, 0xd83c, 0xddeb, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, - 0x66, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x66, 0xd83c, 0xddf5, 0xd83c, 0xddeb, - 0x3a, 0x70, 0x66, 0x3a, 0x70, 0x66, 0xd83c, 0xddf5, 0xd83c, 0xddeb, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x66, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x70, - 0x66, 0xd83c, 0xddf9, 0xd83c, 0xddeb, 0x3a, 0x74, 0x66, 0x3a, 0x74, 0x66, 0xd83c, - 0xddf9, 0xd83c, 0xddeb, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x66, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x74, 0x66, 0xd83c, 0xddec, 0xd83c, 0xdde6, 0x3a, 0x67, - 0x61, 0x3a, 0x67, 0x61, 0xd83c, 0xddec, 0xd83c, 0xdde6, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x67, 0x61, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x61, 0xd83c, - 0xddec, 0xd83c, 0xddf2, 0x3a, 0x67, 0x6d, 0x3a, 0x67, 0x6d, 0xd83c, 0xddec, 0xd83c, - 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x6d, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x67, 0x6d, 0xd83c, 0xddec, 0xd83c, 0xddea, 0x3a, 0x67, 0x65, 0x3a, - 0x67, 0x65, 0xd83c, 0xddec, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x67, 0x65, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x65, 0xd83c, 0xdde9, 0xd83c, - 0xddea, 0x3a, 0x64, 0x65, 0x3a, 0x64, 0x65, 0xd83c, 0xdde9, 0xd83c, 0xddea, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x64, 0x65, 0x3a, 0x64, 0x65, 0x66, 0x6c, - 0x61, 0x67, 0xd83c, 0xddec, 0xd83c, 0xdded, 0x3a, 0x67, 0x68, 0x3a, 0x67, 0x68, - 0xd83c, 0xddec, 0xd83c, 0xdded, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x68, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x68, 0xd83c, 0xddec, 0xd83c, 0xddee, 0x3a, - 0x67, 0x69, 0x3a, 0x67, 0x69, 0xd83c, 0xddec, 0xd83c, 0xddee, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x67, 0x69, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x69, - 0xd83c, 0xddec, 0xd83c, 0xddf7, 0x3a, 0x67, 0x72, 0x3a, 0x67, 0x72, 0xd83c, 0xddec, - 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x72, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x67, 0x72, 0xd83c, 0xddec, 0xd83c, 0xddf1, 0x3a, 0x67, 0x6c, - 0x3a, 0x67, 0x6c, 0xd83c, 0xddec, 0xd83c, 0xddf1, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x67, 0x6c, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x6c, 0xd83c, 0xddec, - 0xd83c, 0xdde9, 0x3a, 0x67, 0x64, 0x3a, 0x67, 0x64, 0xd83c, 0xddec, 0xd83c, 0xdde9, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x64, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x67, 0x64, 0xd83c, 0xddec, 0xd83c, 0xddf5, 0x3a, 0x67, 0x70, 0x3a, 0x67, - 0x70, 0xd83c, 0xddec, 0xd83c, 0xddf5, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, - 0x70, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x70, 0xd83c, 0xddec, 0xd83c, 0xddfa, - 0x3a, 0x67, 0x75, 0x3a, 0x67, 0x75, 0xd83c, 0xddec, 0xd83c, 0xddfa, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x75, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, - 0x75, 0xd83c, 0xddec, 0xd83c, 0xddf9, 0x3a, 0x67, 0x74, 0x3a, 0x67, 0x74, 0xd83c, - 0xddec, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x74, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x67, 0x74, 0xd83c, 0xddec, 0xd83c, 0xddec, 0x3a, 0x67, - 0x67, 0x3a, 0x67, 0x67, 0xd83c, 0xddec, 0xd83c, 0xddec, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x67, 0x67, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x67, 0xd83c, - 0xddec, 0xd83c, 0xddf3, 0x3a, 0x67, 0x6e, 0x3a, 0x67, 0x6e, 0xd83c, 0xddec, 0xd83c, - 0xddf3, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x6e, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x67, 0x6e, 0xd83c, 0xddec, 0xd83c, 0xddfc, 0x3a, 0x67, 0x77, 0x3a, - 0x67, 0x77, 0xd83c, 0xddec, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x67, 0x77, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x77, 0xd83c, 0xddec, 0xd83c, - 0xddfe, 0x3a, 0x67, 0x79, 0x3a, 0x67, 0x79, 0xd83c, 0xddec, 0xd83c, 0xddfe, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x79, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x67, 0x79, 0xd83c, 0xdded, 0xd83c, 0xddf9, 0x3a, 0x68, 0x74, 0x3a, 0x68, 0x74, - 0xd83c, 0xdded, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x68, 0x74, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x68, 0x74, 0xd83c, 0xdded, 0xd83c, 0xddf3, 0x3a, - 0x68, 0x6e, 0x3a, 0x68, 0x6e, 0xd83c, 0xdded, 0xd83c, 0xddf3, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x68, 0x6e, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x68, 0x6e, - 0xd83c, 0xdded, 0xd83c, 0xddf0, 0x3a, 0x68, 0x6b, 0x3a, 0x68, 0x6b, 0xd83c, 0xdded, - 0xd83c, 0xddf0, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x68, 0x6b, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x68, 0x6b, 0xd83c, 0xdded, 0xd83c, 0xddfa, 0x3a, 0x68, 0x75, - 0x3a, 0x68, 0x75, 0xd83c, 0xdded, 0xd83c, 0xddfa, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x68, 0x75, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x68, 0x75, 0xd83c, 0xddee, - 0xd83c, 0xddf8, 0x3a, 0x69, 0x73, 0x3a, 0x69, 0x73, 0xd83c, 0xddee, 0xd83c, 0xddf8, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x69, 0x73, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x69, 0x73, 0xd83c, 0xddee, 0xd83c, 0xddf3, 0x3a, 0x69, 0x6e, 0x3a, 0x69, - 0x6e, 0xd83c, 0xddee, 0xd83c, 0xddf3, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x69, - 0x6e, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x69, 0x6e, 0xd83c, 0xddee, 0xd83c, 0xdde9, - 0x3a, 0x69, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x3a, 0x69, - 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0xd83c, 0xddee, 0xd83c, 0xdde9, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x69, 0x64, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x69, 0x64, 0xd83c, 0xddee, 0xd83c, 0xddf7, 0x3a, 0x69, 0x72, 0x3a, 0x69, - 0x72, 0xd83c, 0xddee, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x69, - 0x72, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x69, 0x72, 0xd83c, 0xddee, 0xd83c, 0xddf6, - 0x3a, 0x69, 0x71, 0x3a, 0x69, 0x71, 0xd83c, 0xddee, 0xd83c, 0xddf6, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x69, 0x71, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x69, - 0x71, 0xd83c, 0xddee, 0xd83c, 0xddea, 0x3a, 0x69, 0x65, 0x3a, 0x69, 0x65, 0xd83c, - 0xddee, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x69, 0x65, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x69, 0x65, 0xd83c, 0xddee, 0xd83c, 0xddf2, 0x3a, 0x69, - 0x6d, 0x3a, 0x69, 0x6d, 0xd83c, 0xddee, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x69, 0x6d, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x69, 0x6d, 0xd83c, - 0xddee, 0xd83c, 0xddf1, 0x3a, 0x69, 0x6c, 0x3a, 0x69, 0x6c, 0xd83c, 0xddee, 0xd83c, - 0xddf1, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x69, 0x6c, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x69, 0x6c, 0xd83c, 0xddee, 0xd83c, 0xddf9, 0x3a, 0x69, 0x74, 0x3a, - 0x69, 0x74, 0xd83c, 0xddee, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x69, 0x74, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x69, 0x74, 0xd83c, 0xddef, 0xd83c, - 0xddf2, 0x3a, 0x6a, 0x6d, 0x3a, 0x6a, 0x6d, 0xd83c, 0xddef, 0xd83c, 0xddf2, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6a, 0x6d, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x6a, 0x6d, 0xd83c, 0xddef, 0xd83c, 0xddf5, 0x3a, 0x6a, 0x70, 0x3a, 0x6a, 0x70, - 0xd83c, 0xddef, 0xd83c, 0xddf5, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6a, 0x70, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6a, 0x70, 0xd83c, 0xdf8c, 0x3a, 0x63, 0x72, - 0x6f, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x3a, - 0x63, 0x72, 0x6f, 0x73, 0x73, 0x65, 0x64, 0x66, 0x6c, 0x61, 0x67, 0x73, - 0xd83c, 0xddef, 0xd83c, 0xddea, 0x3a, 0x6a, 0x65, 0x3a, 0x6a, 0x65, 0xd83c, 0xddef, - 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6a, 0x65, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x6a, 0x65, 0xd83c, 0xddef, 0xd83c, 0xddf4, 0x3a, 0x6a, 0x6f, - 0x3a, 0x6a, 0x6f, 0xd83c, 0xddef, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x6a, 0x6f, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6a, 0x6f, 0xd83c, 0xddf0, - 0xd83c, 0xddff, 0x3a, 0x6b, 0x7a, 0x3a, 0x6b, 0x7a, 0xd83c, 0xddf0, 0xd83c, 0xddff, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6b, 0x7a, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x6b, 0x7a, 0xd83c, 0xddf0, 0xd83c, 0xddea, 0x3a, 0x6b, 0x65, 0x3a, 0x6b, - 0x65, 0xd83c, 0xddf0, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6b, - 0x65, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6b, 0x65, 0xd83c, 0xddf0, 0xd83c, 0xddee, - 0x3a, 0x6b, 0x69, 0x3a, 0x6b, 0x69, 0xd83c, 0xddf0, 0xd83c, 0xddee, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x6b, 0x69, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6b, - 0x69, 0xd83c, 0xddfd, 0xd83c, 0xddf0, 0x3a, 0x78, 0x6b, 0x3a, 0x78, 0x6b, 0xd83c, - 0xddfd, 0xd83c, 0xddf0, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x78, 0x6b, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x78, 0x6b, 0xd83c, 0xddf0, 0xd83c, 0xddfc, 0x3a, 0x6b, - 0x77, 0x3a, 0x6b, 0x77, 0xd83c, 0xddf0, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x6b, 0x77, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6b, 0x77, 0xd83c, - 0xddf0, 0xd83c, 0xddec, 0x3a, 0x6b, 0x67, 0x3a, 0x6b, 0x67, 0xd83c, 0xddf0, 0xd83c, - 0xddec, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6b, 0x67, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x6b, 0x67, 0xd83c, 0xddf1, 0xd83c, 0xdde6, 0x3a, 0x6c, 0x61, 0x3a, - 0x6c, 0x61, 0xd83c, 0xddf1, 0xd83c, 0xdde6, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x6c, 0x61, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6c, 0x61, 0xd83c, 0xddf1, 0xd83c, - 0xddfb, 0x3a, 0x6c, 0x76, 0x3a, 0x6c, 0x76, 0xd83c, 0xddf1, 0xd83c, 0xddfb, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6c, 0x76, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x6c, 0x76, 0xd83c, 0xddf1, 0xd83c, 0xdde7, 0x3a, 0x6c, 0x62, 0x3a, 0x6c, 0x62, - 0xd83c, 0xddf1, 0xd83c, 0xdde7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6c, 0x62, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6c, 0x62, 0xd83c, 0xddf1, 0xd83c, 0xddf8, 0x3a, - 0x6c, 0x73, 0x3a, 0x6c, 0x73, 0xd83c, 0xddf1, 0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x6c, 0x73, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6c, 0x73, - 0xd83c, 0xddf1, 0xd83c, 0xddf7, 0x3a, 0x6c, 0x72, 0x3a, 0x6c, 0x72, 0xd83c, 0xddf1, - 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6c, 0x72, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x6c, 0x72, 0xd83c, 0xddf1, 0xd83c, 0xddfe, 0x3a, 0x6c, 0x79, - 0x3a, 0x6c, 0x79, 0xd83c, 0xddf1, 0xd83c, 0xddfe, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x6c, 0x79, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6c, 0x79, 0xd83c, 0xddf1, - 0xd83c, 0xddee, 0x3a, 0x6c, 0x69, 0x3a, 0x6c, 0x69, 0xd83c, 0xddf1, 0xd83c, 0xddee, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6c, 0x69, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x6c, 0x69, 0xd83c, 0xddf1, 0xd83c, 0xddf9, 0x3a, 0x6c, 0x74, 0x3a, 0x6c, - 0x74, 0xd83c, 0xddf1, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6c, - 0x74, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6c, 0x74, 0xd83c, 0xddf1, 0xd83c, 0xddfa, - 0x3a, 0x6c, 0x75, 0x3a, 0x6c, 0x75, 0xd83c, 0xddf1, 0xd83c, 0xddfa, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x6c, 0x75, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6c, - 0x75, 0xd83c, 0xddf2, 0xd83c, 0xddf4, 0x3a, 0x6d, 0x6f, 0x3a, 0x6d, 0x6f, 0xd83c, - 0xddf2, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x6f, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x6f, 0xd83c, 0xddf2, 0xd83c, 0xddf0, 0x3a, 0x6d, - 0x6b, 0x3a, 0x6d, 0x6b, 0xd83c, 0xddf2, 0xd83c, 0xddf0, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x6d, 0x6b, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x6b, 0xd83c, - 0xddf2, 0xd83c, 0xddec, 0x3a, 0x6d, 0x67, 0x3a, 0x6d, 0x67, 0xd83c, 0xddf2, 0xd83c, - 0xddec, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x67, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x6d, 0x67, 0xd83c, 0xddf2, 0xd83c, 0xddfc, 0x3a, 0x6d, 0x77, 0x3a, - 0x6d, 0x77, 0xd83c, 0xddf2, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x6d, 0x77, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x77, 0xd83c, 0xddf2, 0xd83c, - 0xddfe, 0x3a, 0x6d, 0x79, 0x3a, 0x6d, 0x79, 0xd83c, 0xddf2, 0xd83c, 0xddfe, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x79, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x6d, 0x79, 0xd83c, 0xddf2, 0xd83c, 0xddfb, 0x3a, 0x6d, 0x76, 0x3a, 0x6d, 0x76, - 0xd83c, 0xddf2, 0xd83c, 0xddfb, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x76, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x76, 0xd83c, 0xddf2, 0xd83c, 0xddf1, 0x3a, - 0x6d, 0x6c, 0x3a, 0x6d, 0x6c, 0xd83c, 0xddf2, 0xd83c, 0xddf1, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x6d, 0x6c, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x6c, - 0xd83c, 0xddf2, 0xd83c, 0xddf9, 0x3a, 0x6d, 0x74, 0x3a, 0x6d, 0x74, 0xd83c, 0xddf2, - 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x74, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x6d, 0x74, 0xd83c, 0xddf2, 0xd83c, 0xdded, 0x3a, 0x6d, 0x68, - 0x3a, 0x6d, 0x68, 0xd83c, 0xddf2, 0xd83c, 0xdded, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x6d, 0x68, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x68, 0xd83c, 0xddf2, - 0xd83c, 0xddf6, 0x3a, 0x6d, 0x71, 0x3a, 0x6d, 0x71, 0xd83c, 0xddf2, 0xd83c, 0xddf6, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x71, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x6d, 0x71, 0xd83c, 0xddf2, 0xd83c, 0xddf7, 0x3a, 0x6d, 0x72, 0x3a, 0x6d, - 0x72, 0xd83c, 0xddf2, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, - 0x72, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x72, 0xd83c, 0xddf2, 0xd83c, 0xddfa, - 0x3a, 0x6d, 0x75, 0x3a, 0x6d, 0x75, 0xd83c, 0xddf2, 0xd83c, 0xddfa, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x75, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, - 0x75, 0xd83c, 0xddfe, 0xd83c, 0xddf9, 0x3a, 0x79, 0x74, 0x3a, 0x79, 0x74, 0xd83c, - 0xddfe, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x79, 0x74, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x79, 0x74, 0xd83c, 0xddf2, 0xd83c, 0xddfd, 0x3a, 0x6d, - 0x78, 0x3a, 0x6d, 0x78, 0xd83c, 0xddf2, 0xd83c, 0xddfd, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x6d, 0x78, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x78, 0xd83c, - 0xddeb, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6d, 0x3a, 0x66, 0x6d, 0xd83c, 0xddeb, 0xd83c, - 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x66, 0x6d, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x66, 0x6d, 0xd83c, 0xddf2, 0xd83c, 0xdde9, 0x3a, 0x6d, 0x64, 0x3a, - 0x6d, 0x64, 0xd83c, 0xddf2, 0xd83c, 0xdde9, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x6d, 0x64, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x64, 0xd83c, 0xddf2, 0xd83c, - 0xdde8, 0x3a, 0x6d, 0x63, 0x3a, 0x6d, 0x63, 0xd83c, 0xddf2, 0xd83c, 0xdde8, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x63, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x6d, 0x63, 0xd83c, 0xddf2, 0xd83c, 0xddf3, 0x3a, 0x6d, 0x6e, 0x3a, 0x6d, 0x6e, - 0xd83c, 0xddf2, 0xd83c, 0xddf3, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x6e, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x6e, 0xd83c, 0xddf2, 0xd83c, 0xddea, 0x3a, - 0x6d, 0x65, 0x3a, 0x6d, 0x65, 0xd83c, 0xddf2, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x6d, 0x65, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x65, - 0xd83c, 0xddf2, 0xd83c, 0xddf8, 0x3a, 0x6d, 0x73, 0x3a, 0x6d, 0x73, 0xd83c, 0xddf2, - 0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x73, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x6d, 0x73, 0xd83c, 0xddf2, 0xd83c, 0xdde6, 0x3a, 0x6d, 0x61, - 0x3a, 0x6d, 0x61, 0xd83c, 0xddf2, 0xd83c, 0xdde6, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x6d, 0x61, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x61, 0xd83c, 0xddf2, - 0xd83c, 0xddff, 0x3a, 0x6d, 0x7a, 0x3a, 0x6d, 0x7a, 0xd83c, 0xddf2, 0xd83c, 0xddff, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, 0x7a, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x6d, 0x7a, 0xd83c, 0xddf2, 0xd83c, 0xddf2, 0x3a, 0x6d, 0x6d, 0x3a, 0x6d, - 0x6d, 0xd83c, 0xddf2, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6d, - 0x6d, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x6d, 0xd83c, 0xddf3, 0xd83c, 0xdde6, - 0x3a, 0x6e, 0x61, 0x3a, 0x6e, 0x61, 0xd83c, 0xddf3, 0xd83c, 0xdde6, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x6e, 0x61, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6e, - 0x61, 0xd83c, 0xddf3, 0xd83c, 0xddf7, 0x3a, 0x6e, 0x72, 0x3a, 0x6e, 0x72, 0xd83c, - 0xddf3, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6e, 0x72, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x6e, 0x72, 0xd83c, 0xddf3, 0xd83c, 0xddf5, 0x3a, 0x6e, - 0x70, 0x3a, 0x6e, 0x70, 0xd83c, 0xddf3, 0xd83c, 0xddf5, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x6e, 0x70, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6e, 0x70, 0xd83c, - 0xddf3, 0xd83c, 0xddf1, 0x3a, 0x6e, 0x6c, 0x3a, 0x6e, 0x6c, 0xd83c, 0xddf3, 0xd83c, - 0xddf1, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6e, 0x6c, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x6e, 0x6c, 0xd83c, 0xddf3, 0xd83c, 0xdde8, 0x3a, 0x6e, 0x63, 0x3a, - 0x6e, 0x63, 0xd83c, 0xddf3, 0xd83c, 0xdde8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x6e, 0x63, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6e, 0x63, 0xd83c, 0xddf3, 0xd83c, - 0xddff, 0x3a, 0x6e, 0x7a, 0x3a, 0x6e, 0x7a, 0xd83c, 0xddf3, 0xd83c, 0xddff, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6e, 0x7a, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x6e, 0x7a, 0xd83c, 0xddf3, 0xd83c, 0xddee, 0x3a, 0x6e, 0x69, 0x3a, 0x6e, 0x69, - 0xd83c, 0xddf3, 0xd83c, 0xddee, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6e, 0x69, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6e, 0x69, 0xd83c, 0xddf3, 0xd83c, 0xddea, 0x3a, - 0x6e, 0x65, 0x3a, 0x6e, 0x65, 0xd83c, 0xddf3, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x6e, 0x65, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6e, 0x65, - 0xd83c, 0xddf3, 0xd83c, 0xddec, 0x3a, 0x6e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, - 0x3a, 0x6e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0xd83c, 0xddf3, 0xd83c, 0xddec, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6e, 0x67, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x6e, 0x67, 0xd83c, 0xddf3, 0xd83c, 0xddfa, 0x3a, 0x6e, 0x75, 0x3a, 0x6e, - 0x75, 0xd83c, 0xddf3, 0xd83c, 0xddfa, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6e, - 0x75, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6e, 0x75, 0xd83c, 0xddf3, 0xd83c, 0xddeb, - 0x3a, 0x6e, 0x66, 0x3a, 0x6e, 0x66, 0xd83c, 0xddf3, 0xd83c, 0xddeb, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x6e, 0x66, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6e, - 0x66, 0xd83c, 0xddf0, 0xd83c, 0xddf5, 0x3a, 0x6b, 0x70, 0x3a, 0x6b, 0x70, 0xd83c, - 0xddf0, 0xd83c, 0xddf5, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6b, 0x70, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x6b, 0x70, 0xd83c, 0xddf2, 0xd83c, 0xddf5, 0x3a, 0x6d, - 0x70, 0x3a, 0x6d, 0x70, 0xd83c, 0xddf2, 0xd83c, 0xddf5, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x6d, 0x70, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6d, 0x70, 0xd83c, - 0xddf3, 0xd83c, 0xddf4, 0x3a, 0x73, 0x6a, 0x3a, 0x73, 0x6a, 0xd83c, 0xddf3, 0xd83c, - 0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x6a, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x73, 0x6a, 0xd83c, 0xddf3, 0xd83c, 0xddf4, 0x3a, 0x6e, 0x6f, 0x3a, - 0x6e, 0x6f, 0xd83c, 0xddf3, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x6e, 0x6f, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6e, 0x6f, 0xd83c, 0xddf3, 0xd83c, - 0xddf4, 0x3a, 0x62, 0x76, 0x3a, 0x62, 0x76, 0xd83c, 0xddf3, 0xd83c, 0xddf4, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, 0x76, 0x3a, 0x62, 0x76, 0x66, 0x6c, - 0x61, 0x67, 0xd83c, 0xddf4, 0xd83c, 0xddf2, 0x3a, 0x6f, 0x6d, 0x3a, 0x6f, 0x6d, - 0xd83c, 0xddf4, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6f, 0x6d, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6f, 0x6d, 0xd83c, 0xddf5, 0xd83c, 0xddf0, 0x3a, - 0x70, 0x6b, 0x3a, 0x70, 0x6b, 0xd83c, 0xddf5, 0xd83c, 0xddf0, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x70, 0x6b, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x70, 0x6b, - 0xd83c, 0xddf5, 0xd83c, 0xddfc, 0x3a, 0x70, 0x77, 0x3a, 0x70, 0x77, 0xd83c, 0xddf5, - 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x77, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x70, 0x77, 0xd83c, 0xddf5, 0xd83c, 0xddf8, 0x3a, 0x70, 0x73, - 0x3a, 0x70, 0x73, 0xd83c, 0xddf5, 0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x70, 0x73, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x70, 0x73, 0xd83c, 0xddf5, - 0xd83c, 0xdde6, 0x3a, 0x70, 0x61, 0x3a, 0x70, 0x61, 0xd83c, 0xddf5, 0xd83c, 0xdde6, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x61, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x70, 0x61, 0xd83c, 0xddf5, 0xd83c, 0xddec, 0x3a, 0x70, 0x67, 0x3a, 0x70, - 0x67, 0xd83c, 0xddf5, 0xd83c, 0xddec, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, - 0x67, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x70, 0x67, 0xd83c, 0xddf5, 0xd83c, 0xddfe, - 0x3a, 0x70, 0x79, 0x3a, 0x70, 0x79, 0xd83c, 0xddf5, 0xd83c, 0xddfe, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x79, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x70, - 0x79, 0xd83c, 0xddf5, 0xd83c, 0xddea, 0x3a, 0x70, 0x65, 0x3a, 0x70, 0x65, 0xd83c, - 0xddf5, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x65, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x70, 0x65, 0xd83c, 0xddf5, 0xd83c, 0xdded, 0x3a, 0x70, - 0x68, 0x3a, 0x70, 0x68, 0xd83c, 0xddf5, 0xd83c, 0xdded, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x70, 0x68, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x70, 0x68, 0xd83c, - 0xddf5, 0xd83c, 0xddf3, 0x3a, 0x70, 0x6e, 0x3a, 0x70, 0x6e, 0xd83c, 0xddf5, 0xd83c, - 0xddf3, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x6e, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x70, 0x6e, 0xd83c, 0xddf5, 0xd83c, 0xddf1, 0x3a, 0x70, 0x6c, 0x3a, - 0x70, 0x6c, 0xd83c, 0xddf5, 0xd83c, 0xddf1, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x70, 0x6c, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x70, 0x6c, 0xd83c, 0xddf5, 0xd83c, - 0xddf9, 0x3a, 0x70, 0x74, 0x3a, 0x70, 0x74, 0xd83c, 0xddf5, 0xd83c, 0xddf9, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x74, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x70, 0x74, 0xd83c, 0xddf5, 0xd83c, 0xddf7, 0x3a, 0x70, 0x72, 0x3a, 0x70, 0x72, - 0xd83c, 0xddf5, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x72, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x70, 0x72, 0xd83c, 0xddf6, 0xd83c, 0xdde6, 0x3a, - 0x71, 0x61, 0x3a, 0x71, 0x61, 0xd83c, 0xddf6, 0xd83c, 0xdde6, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x71, 0x61, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x71, 0x61, - 0xd83c, 0xddf7, 0xd83c, 0xddea, 0x3a, 0x72, 0x65, 0x3a, 0x72, 0x65, 0xd83c, 0xddf7, - 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x72, 0x65, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x72, 0x65, 0xd83c, 0xddf7, 0xd83c, 0xddf4, 0x3a, 0x72, 0x6f, - 0x3a, 0x72, 0x6f, 0xd83c, 0xddf7, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x72, 0x6f, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x72, 0x6f, 0xd83c, 0xddf7, - 0xd83c, 0xddfa, 0x3a, 0x72, 0x75, 0x3a, 0x72, 0x75, 0xd83c, 0xddf7, 0xd83c, 0xddfa, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x72, 0x75, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x72, 0x75, 0xd83c, 0xddf7, 0xd83c, 0xddfc, 0x3a, 0x72, 0x77, 0x3a, 0x72, - 0x77, 0xd83c, 0xddf7, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x72, - 0x77, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x72, 0x77, 0xd83c, 0xddfc, 0xd83c, 0xddf8, - 0x3a, 0x77, 0x73, 0x3a, 0x77, 0x73, 0xd83c, 0xddfc, 0xd83c, 0xddf8, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x77, 0x73, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x77, - 0x73, 0xd83c, 0xddf8, 0xd83c, 0xddf2, 0x3a, 0x73, 0x6d, 0x3a, 0x73, 0x6d, 0xd83c, - 0xddf8, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x6d, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x73, 0x6d, 0xd83c, 0xddf8, 0xd83c, 0xddf9, 0x3a, 0x73, - 0x74, 0x3a, 0x73, 0x74, 0xd83c, 0xddf8, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x73, 0x74, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x74, 0xd83c, - 0xddf8, 0xd83c, 0xdde6, 0x3a, 0x73, 0x61, 0x75, 0x64, 0x69, 0x3a, 0x73, 0x61, - 0x75, 0x64, 0x69, 0xd83c, 0xddf8, 0xd83c, 0xdde6, 0x3a, 0x73, 0x61, 0x75, 0x64, - 0x69, 0x61, 0x72, 0x61, 0x62, 0x69, 0x61, 0x3a, 0x73, 0x61, 0x75, 0x64, - 0x69, 0x61, 0x72, 0x61, 0x62, 0x69, 0x61, 0xd83c, 0xddf8, 0xd83c, 0xdde6, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x61, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x73, 0x61, 0xd83c, 0xddf8, 0xd83c, 0xddf3, 0x3a, 0x73, 0x6e, 0x3a, 0x73, 0x6e, - 0xd83c, 0xddf8, 0xd83c, 0xddf3, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x6e, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x6e, 0xd83c, 0xddf7, 0xd83c, 0xddf8, 0x3a, - 0x72, 0x73, 0x3a, 0x72, 0x73, 0xd83c, 0xddf7, 0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x72, 0x73, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x72, 0x73, - 0xd83c, 0xddf8, 0xd83c, 0xdde8, 0x3a, 0x73, 0x63, 0x3a, 0x73, 0x63, 0xd83c, 0xddf8, - 0xd83c, 0xdde8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x63, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x73, 0x63, 0xd83c, 0xddf8, 0xd83c, 0xddf1, 0x3a, 0x73, 0x6c, - 0x3a, 0x73, 0x6c, 0xd83c, 0xddf8, 0xd83c, 0xddf1, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x73, 0x6c, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x6c, 0xd83c, 0xddf8, - 0xd83c, 0xddec, 0x3a, 0x73, 0x67, 0x3a, 0x73, 0x67, 0xd83c, 0xddf8, 0xd83c, 0xddec, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x67, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x73, 0x67, 0xd83c, 0xddf8, 0xd83c, 0xddfd, 0x3a, 0x73, 0x78, 0x3a, 0x73, - 0x78, 0xd83c, 0xddf8, 0xd83c, 0xddfd, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, - 0x78, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x78, 0xd83c, 0xddf8, 0xd83c, 0xddf0, - 0x3a, 0x73, 0x6b, 0x3a, 0x73, 0x6b, 0xd83c, 0xddf8, 0xd83c, 0xddf0, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x6b, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, - 0x6b, 0xd83c, 0xddf8, 0xd83c, 0xddee, 0x3a, 0x73, 0x69, 0x3a, 0x73, 0x69, 0xd83c, - 0xddf8, 0xd83c, 0xddee, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x69, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x73, 0x69, 0xd83c, 0xddec, 0xd83c, 0xddf8, 0x3a, 0x67, - 0x73, 0x3a, 0x67, 0x73, 0xd83c, 0xddec, 0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x67, 0x73, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x67, 0x73, 0xd83c, - 0xddf8, 0xd83c, 0xdde7, 0x3a, 0x73, 0x62, 0x3a, 0x73, 0x62, 0xd83c, 0xddf8, 0xd83c, - 0xdde7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x62, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x73, 0x62, 0xd83c, 0xddf8, 0xd83c, 0xddf4, 0x3a, 0x73, 0x6f, 0x3a, - 0x73, 0x6f, 0xd83c, 0xddf8, 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x73, 0x6f, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x6f, 0xd83c, 0xddff, 0xd83c, - 0xdde6, 0x3a, 0x7a, 0x61, 0x3a, 0x7a, 0x61, 0xd83c, 0xddff, 0xd83c, 0xdde6, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x7a, 0x61, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x7a, 0x61, 0xd83c, 0xddf0, 0xd83c, 0xddf7, 0x3a, 0x6b, 0x72, 0x3a, 0x6b, 0x72, - 0xd83c, 0xddf0, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6b, 0x72, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6b, 0x72, 0xd83c, 0xddf8, 0xd83c, 0xddf8, 0x3a, - 0x73, 0x73, 0x3a, 0x73, 0x73, 0xd83c, 0xddf8, 0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x73, 0x73, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x73, - 0xd83c, 0xddea, 0xd83c, 0xddf8, 0x3a, 0x65, 0x73, 0x3a, 0x65, 0x73, 0xd83c, 0xddea, - 0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x65, 0x73, 0x3a, 0x65, - 0x73, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddea, 0xd83c, 0xddf8, 0x3a, 0x65, 0x61, - 0x3a, 0x65, 0x61, 0xd83c, 0xddea, 0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x65, 0x61, 0x3a, 0x65, 0x61, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddf1, - 0xd83c, 0xddf0, 0x3a, 0x6c, 0x6b, 0x3a, 0x6c, 0x6b, 0xd83c, 0xddf1, 0xd83c, 0xddf0, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6c, 0x6b, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x6c, 0x6b, 0xd83c, 0xdde7, 0xd83c, 0xddf1, 0x3a, 0x62, 0x6c, 0x3a, 0x62, - 0x6c, 0xd83c, 0xdde7, 0xd83c, 0xddf1, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x62, - 0x6c, 0x3a, 0x62, 0x6c, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddf8, 0xd83c, 0xdded, - 0x3a, 0x74, 0x61, 0x3a, 0x74, 0x61, 0xd83c, 0xddf8, 0xd83c, 0xdded, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x61, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, - 0x61, 0xd83c, 0xddf8, 0xd83c, 0xdded, 0x3a, 0x73, 0x68, 0x3a, 0x73, 0x68, 0xd83c, - 0xddf8, 0xd83c, 0xdded, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x68, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x73, 0x68, 0xd83c, 0xddf8, 0xd83c, 0xdded, 0x3a, 0x61, - 0x63, 0x3a, 0x61, 0x63, 0xd83c, 0xddf8, 0xd83c, 0xdded, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x61, 0x63, 0x3a, 0x61, 0x63, 0x66, 0x6c, 0x61, 0x67, 0xd83c, - 0xddf0, 0xd83c, 0xddf3, 0x3a, 0x6b, 0x6e, 0x3a, 0x6b, 0x6e, 0xd83c, 0xddf0, 0xd83c, - 0xddf3, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x6b, 0x6e, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x6b, 0x6e, 0xd83c, 0xddf1, 0xd83c, 0xdde8, 0x3a, 0x6c, 0x63, 0x3a, - 0x6c, 0x63, 0xd83c, 0xddf1, 0xd83c, 0xdde8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x6c, 0x63, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x6c, 0x63, 0xd83c, 0xddf5, 0xd83c, - 0xddf2, 0x3a, 0x70, 0x6d, 0x3a, 0x70, 0x6d, 0xd83c, 0xddf5, 0xd83c, 0xddf2, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x70, 0x6d, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x70, 0x6d, 0xd83c, 0xddfb, 0xd83c, 0xdde8, 0x3a, 0x76, 0x63, 0x3a, 0x76, 0x63, - 0xd83c, 0xddfb, 0xd83c, 0xdde8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x76, 0x63, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x76, 0x63, 0xd83c, 0xddf8, 0xd83c, 0xdde9, 0x3a, - 0x73, 0x64, 0x3a, 0x73, 0x64, 0xd83c, 0xddf8, 0xd83c, 0xdde9, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x73, 0x64, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x64, - 0xd83c, 0xddf8, 0xd83c, 0xddf7, 0x3a, 0x73, 0x72, 0x3a, 0x73, 0x72, 0xd83c, 0xddf8, - 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x72, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x73, 0x72, 0xd83c, 0xddf8, 0xd83c, 0xddff, 0x3a, 0x73, 0x7a, - 0x3a, 0x73, 0x7a, 0xd83c, 0xddf8, 0xd83c, 0xddff, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x73, 0x7a, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x7a, 0xd83c, 0xddf8, - 0xd83c, 0xddea, 0x3a, 0x73, 0x65, 0x3a, 0x73, 0x65, 0xd83c, 0xddf8, 0xd83c, 0xddea, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x65, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x73, 0x65, 0xd83c, 0xdde8, 0xd83c, 0xdded, 0x3a, 0x63, 0x68, 0x3a, 0x63, - 0x68, 0xd83c, 0xdde8, 0xd83c, 0xdded, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x63, - 0x68, 0x3a, 0x63, 0x68, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddf8, 0xd83c, 0xddfe, - 0x3a, 0x73, 0x79, 0x3a, 0x73, 0x79, 0xd83c, 0xddf8, 0xd83c, 0xddfe, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x73, 0x79, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x73, - 0x79, 0xd83c, 0xddf9, 0xd83c, 0xddfc, 0x3a, 0x74, 0x77, 0x3a, 0x74, 0x77, 0xd83c, - 0xddf9, 0xd83c, 0xddfc, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x77, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x74, 0x77, 0xd83c, 0xddf9, 0xd83c, 0xddef, 0x3a, 0x74, - 0x6a, 0x3a, 0x74, 0x6a, 0xd83c, 0xddf9, 0xd83c, 0xddef, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x74, 0x6a, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x6a, 0xd83c, - 0xddf9, 0xd83c, 0xddff, 0x3a, 0x74, 0x7a, 0x3a, 0x74, 0x7a, 0xd83c, 0xddf9, 0xd83c, - 0xddff, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x7a, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x74, 0x7a, 0xd83c, 0xddf9, 0xd83c, 0xdded, 0x3a, 0x74, 0x68, 0x3a, - 0x74, 0x68, 0xd83c, 0xddf9, 0xd83c, 0xdded, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x74, 0x68, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x68, 0xd83c, 0xddf9, 0xd83c, - 0xddf1, 0x3a, 0x74, 0x6c, 0x3a, 0x74, 0x6c, 0xd83c, 0xddf9, 0xd83c, 0xddf1, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x6c, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x74, 0x6c, 0xd83c, 0xddf9, 0xd83c, 0xddec, 0x3a, 0x74, 0x67, 0x3a, 0x74, 0x67, - 0xd83c, 0xddf9, 0xd83c, 0xddec, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x67, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x67, 0xd83c, 0xddf9, 0xd83c, 0xddf0, 0x3a, - 0x74, 0x6b, 0x3a, 0x74, 0x6b, 0xd83c, 0xddf9, 0xd83c, 0xddf0, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x74, 0x6b, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x6b, - 0xd83c, 0xddf9, 0xd83c, 0xddf4, 0x3a, 0x74, 0x6f, 0x3a, 0x74, 0x6f, 0xd83c, 0xddf9, - 0xd83c, 0xddf4, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x6f, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x74, 0x6f, 0xd83c, 0xddf9, 0xd83c, 0xddf9, 0x3a, 0x74, 0x74, - 0x3a, 0x74, 0x74, 0xd83c, 0xddf9, 0xd83c, 0xddf9, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x74, 0x74, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x74, 0xd83c, 0xddf9, - 0xd83c, 0xddf3, 0x3a, 0x74, 0x6e, 0x3a, 0x74, 0x6e, 0xd83c, 0xddf9, 0xd83c, 0xddf3, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x6e, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x74, 0x6e, 0xd83c, 0xddf9, 0xd83c, 0xddf7, 0x3a, 0x74, 0x72, 0x3a, 0x74, - 0x72, 0xd83c, 0xddf9, 0xd83c, 0xddf7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, - 0x72, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x72, 0xd83c, 0xddf9, 0xd83c, 0xddf2, - 0x3a, 0x74, 0x75, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x69, 0x73, 0x74, 0x61, - 0x6e, 0x3a, 0x74, 0x75, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x69, 0x73, 0x74, - 0x61, 0x6e, 0xd83c, 0xddf9, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x74, 0x6d, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x74, 0x6d, 0xd83c, 0xddf9, 0xd83c, - 0xdde8, 0x3a, 0x74, 0x63, 0x3a, 0x74, 0x63, 0xd83c, 0xddf9, 0xd83c, 0xdde8, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x63, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x74, 0x63, 0xd83c, 0xddf9, 0xd83c, 0xddfb, 0x3a, 0x74, 0x75, 0x76, 0x61, 0x6c, - 0x75, 0x3a, 0x74, 0x75, 0x76, 0x61, 0x6c, 0x75, 0xd83c, 0xddf9, 0xd83c, 0xddfb, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x74, 0x76, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x74, 0x76, 0xd83c, 0xddfb, 0xd83c, 0xddee, 0x3a, 0x76, 0x69, 0x3a, 0x76, - 0x69, 0xd83c, 0xddfb, 0xd83c, 0xddee, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x76, - 0x69, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x76, 0x69, 0xd83c, 0xddfa, 0xd83c, 0xddec, - 0x3a, 0x75, 0x67, 0x3a, 0x75, 0x67, 0xd83c, 0xddfa, 0xd83c, 0xddec, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x75, 0x67, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x75, - 0x67, 0xd83c, 0xddfa, 0xd83c, 0xdde6, 0x3a, 0x75, 0x61, 0x3a, 0x75, 0x61, 0xd83c, - 0xddfa, 0xd83c, 0xdde6, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x75, 0x61, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x75, 0x61, 0xd83c, 0xdde6, 0xd83c, 0xddea, 0x3a, 0x61, - 0x65, 0x3a, 0x61, 0x65, 0xd83c, 0xdde6, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x61, 0x65, 0x3a, 0x61, 0x65, 0x66, 0x6c, 0x61, 0x67, 0xd83c, - 0xddec, 0xd83c, 0xdde7, 0x3a, 0x67, 0x62, 0x3a, 0x67, 0x62, 0xd83c, 0xddec, 0xd83c, - 0xdde7, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x67, 0x62, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x67, 0x62, 0xd83c, 0xdff4, 0xdb40, 0xdc67, 0xdb40, 0xdc62, 0xdb40, 0xdc65, - 0xdb40, 0xdc6e, 0xdb40, 0xdc67, 0xdb40, 0xdc7f, 0x3a, 0x65, 0x6e, 0x67, 0x6c, 0x61, - 0x6e, 0x64, 0x3a, 0x65, 0x6e, 0x67, 0x6c, 0x61, 0x6e, 0x64, 0xd83c, 0xdff4, - 0xdb40, 0xdc67, 0xdb40, 0xdc62, 0xdb40, 0xdc73, 0xdb40, 0xdc63, 0xdb40, 0xdc74, 0xdb40, 0xdc7f, - 0x3a, 0x73, 0x63, 0x6f, 0x74, 0x6c, 0x61, 0x6e, 0x64, 0x3a, 0x73, 0x63, - 0x6f, 0x74, 0x6c, 0x61, 0x6e, 0x64, 0xd83c, 0xdff4, 0xdb40, 0xdc67, 0xdb40, 0xdc62, - 0xdb40, 0xdc77, 0xdb40, 0xdc6c, 0xdb40, 0xdc73, 0xdb40, 0xdc7f, 0x3a, 0x77, 0x61, 0x6c, - 0x65, 0x73, 0x3a, 0x77, 0x61, 0x6c, 0x65, 0x73, 0xd83c, 0xddfa, 0xd83c, 0xddf8, - 0x3a, 0x75, 0x73, 0x3a, 0x75, 0x73, 0xd83c, 0xddfa, 0xd83c, 0xddf8, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x75, 0x73, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x75, - 0x73, 0xd83c, 0xddfa, 0xd83c, 0xddf8, 0x3a, 0x75, 0x6d, 0x3a, 0x75, 0x6d, 0xd83c, - 0xddfa, 0xd83c, 0xddf8, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x75, 0x6d, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x75, 0x6d, 0xd83c, 0xddfa, 0xd83c, 0xddfe, 0x3a, 0x75, - 0x79, 0x3a, 0x75, 0x79, 0xd83c, 0xddfa, 0xd83c, 0xddfe, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x75, 0x79, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x75, 0x79, 0xd83c, - 0xddfa, 0xd83c, 0xddff, 0x3a, 0x75, 0x7a, 0x3a, 0x75, 0x7a, 0xd83c, 0xddfa, 0xd83c, - 0xddff, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x75, 0x7a, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x75, 0x7a, 0xd83c, 0xddfb, 0xd83c, 0xddfa, 0x3a, 0x76, 0x75, 0x3a, - 0x76, 0x75, 0xd83c, 0xddfb, 0xd83c, 0xddfa, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, - 0x76, 0x75, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x76, 0x75, 0xd83c, 0xddfb, 0xd83c, - 0xdde6, 0x3a, 0x76, 0x61, 0x3a, 0x76, 0x61, 0xd83c, 0xddfb, 0xd83c, 0xdde6, 0x3a, - 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x76, 0x61, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x76, 0x61, 0xd83c, 0xddfb, 0xd83c, 0xddea, 0x3a, 0x76, 0x65, 0x3a, 0x76, 0x65, - 0xd83c, 0xddfb, 0xd83c, 0xddea, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x76, 0x65, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x76, 0x65, 0xd83c, 0xddfb, 0xd83c, 0xddf3, 0x3a, - 0x76, 0x6e, 0x3a, 0x76, 0x6e, 0xd83c, 0xddfb, 0xd83c, 0xddf3, 0x3a, 0x66, 0x6c, - 0x61, 0x67, 0x5f, 0x76, 0x6e, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x76, 0x6e, - 0xd83c, 0xddfc, 0xd83c, 0xddeb, 0x3a, 0x77, 0x66, 0x3a, 0x77, 0x66, 0xd83c, 0xddfc, - 0xd83c, 0xddeb, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x77, 0x66, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x77, 0x66, 0xd83c, 0xddea, 0xd83c, 0xdded, 0x3a, 0x65, 0x68, - 0x3a, 0x65, 0x68, 0xd83c, 0xddea, 0xd83c, 0xdded, 0x3a, 0x66, 0x6c, 0x61, 0x67, - 0x5f, 0x65, 0x68, 0x3a, 0x65, 0x68, 0x66, 0x6c, 0x61, 0x67, 0xd83c, 0xddfe, - 0xd83c, 0xddea, 0x3a, 0x79, 0x65, 0x3a, 0x79, 0x65, 0xd83c, 0xddfe, 0xd83c, 0xddea, - 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x79, 0x65, 0x3a, 0x66, 0x6c, 0x61, - 0x67, 0x79, 0x65, 0xd83c, 0xddff, 0xd83c, 0xddf2, 0x3a, 0x7a, 0x6d, 0x3a, 0x7a, - 0x6d, 0xd83c, 0xddff, 0xd83c, 0xddf2, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x7a, - 0x6d, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x7a, 0x6d, 0xd83c, 0xddff, 0xd83c, 0xddfc, - 0x3a, 0x7a, 0x77, 0x3a, 0x7a, 0x77, 0xd83c, 0xddff, 0xd83c, 0xddfc, 0x3a, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x7a, 0x77, 0x3a, 0x66, 0x6c, 0x61, 0x67, 0x7a, - 0x77 }; - -const small ReplacementWordLengths[] = { - 8, 6, 5, 4, 9, 8, 5, 5, 3, 5, 8, 2, - 7, 3, 4, 7, 5, 8, 4, 8, 7, 6, 5, 4, - 4, 6, 4, 6, 4, 8, 4, 5, 5, 7, 7, 4, - 7, 7, 6, 4, 7, 3, 3, 5, 6, 6, 4, 3, - 5, 6, 3, 3, 5, 6, 7, 5, 4, 7, 4, 6, - 4, 4, 7, 4, 4, 4, 4, 10, 4, 6, 5, 8, - 12, 7, 7, 8, 4, 8, 8, 5, 6, 4, 8, 5, - 9, 9, 10, 4, 5, 5, 3, 3, 7, 5, 4, 4, - 5, 4, 7, 4, 9, 4, 7, 6, 7, 4, 5, 12, - 8, 5, 4, 7, 7, 3, 4, 8, 8, 4, 4, 5, - 4, 4, 4, 8, 4, 4, 5, 5, 2, 4, 7, 14, - 9, 4, 4, 7, 4, 4, 7, 6, 8, 9, 5, 4, - 10, 8, 5, 8, 4, 6, 5, 4, 4, 5, 6, 5, - 6, 4, 4, 9, 4, 8, 6, 4, 8, 4, 4, 11, - 4, 4, 11, 7, 4, 4, 4, 7, 4, 4, 5, 5, - 5, 5, 6, 4, 3, 4, 6, 3, 7, 3, 8, 4, - 6, 8, 5, 4, 5, 3, 6, 4, 4, 5, 8, 5, - 3, 10, 5, 10, 5, 5, 7, 5, 4, 5, 5, 4, - 7, 1, 3, 6, 3, 5, 3, 3, 3, 4, 5, 3, - 5, 3, 7, 3, 6, 3, 6, 4, 3, 7, 5, 8, - 2, 5, 4, 5, 6, 4, 5, 7, 9, 4, 7, 2, - 8, 7, 9, 2, 10, 5, 4, 4, 4, 6, 4, 4, - 4, 5, 6, 4, 5, 3, 7, 6, 4, 5, 6, 4, - 7, 7, 1, 7, 4, 3, 5, 2, 4, 3, 5, 4, - 2, 4, 5, 5, 5, 1, 5, 2, 4, 5, 5, 2, - 4, 6, 4, 4, 2, 4, 4, 2, 6, 7, 4, 6, - 7, 4, 4, 7, 3, 7, 7, 4, 6, 4, 6, 4, - 4, 6, 4, 4, 4, 2, 4, 2, 6, 8, 6, 4, - 6, 8, 4, 6, 6, 4, 7, 4, 8, 4, 4, 6, - 3, 4, 10, 3, 4, 5, 4, 2, 10, 8, 4, 8, - 4, 2, 10, 5, 2, 10, 4, 4, 5, 3, 5, 5, - 3, 5, 6, 5, 5, 6, 3, 5, 4, 6, 4, 5, - 6, 6, 7, 6, 7, 5, 5, 5, 5, 3, 5, 3, - 3, 3, 2, 4, 3, 7, 3, 4, 6, 7, 5, 3, - 6, 7, 3, 6, 4, 6, 6, 7, 9, 4, 5, 7, - 6, 5, 3, 7, 6, 3, 7, 6, 12, 5, 6, 12, - 3, 6, 12, 6, 5, 5, 5, 3, 9, 5, 9, 5, - 9, 3, 2, 6, 3, 3, 9, 6, 5, 6, 6, 3, - 6, 6, 5, 6, 3, 4, 5, 4, 3, 7, 5, 3, - 7, 6, 5, 3, 6, 7, 5, 3, 7, 7, 5, 6, - 7, 3, 6, 12, 5, 3, 12, 6, 5, 6, 3, 6, - 6, 8, 5, 3, 8, 9, 5, 3, 9, 6, 5, 6, - 3, 11, 5, 11, 3, 5, 5, 3, 5, 9, 5, 9, - 3, 5, 5, 5, 3, 5, 4, 4, 2, 3, 6, 8, - 6, 9, 6, 5, 3, 5, 4, 5, 4, 4, 3, 3, - 5, 3, 3, 3, 7, 5, 7, 3, 7, 5, 6, 6, - 3, 6, 5, 5, 5, 5, 3, 7, 9, 6, 5, 5, - 5, 5, 3, 5, 9, 5, 8, 5, 6, 7, 6, 5, - 6, 3, 3, 6, 6, 4, 7, 5, 4, 11, 6, 4, - 6, 7, 4, 3, 7, 9, 2, 5, 4, 2, 9, 2, - 6, 9, 3, 2, 9, 2, 5, 2, 5, 9, 2, 6, - 9, 3, 2, 4, 7, 5, 4, 7, 4, 6, 7, 4, - 3, 7, 11, 5, 11, 3, 8, 4, 4, 11, 6, 9, - 5, 6, 9, 3, 9, 7, 5, 4, 6, 7, 4, 6, - 7, 3, 7, 8, 5, 8, 6, 8, 3, 7, 7, 5, - 7, 7, 7, 6, 7, 7, 3, 4, 7, 7, 5, 7, - 7, 7, 6, 4, 7, 3, 7, 2, 4, 6, 5, 2, - 6, 4, 6, 2, 3, 4, 6, 4, 4, 6, 6, 6, - 4, 7, 3, 5, 4, 8, 4, 5, 7, 5, 4, 8, - 6, 4, 5, 4, 3, 8, 4, 8, 2, 10, 3, 4, - 7, 5, 3, 7, 7, 6, 7, 7, 5, 3, 7, 6, - 6, 7, 6, 5, 7, 3, 5, 5, 7, 3, 3, 6, - 5, 4, 6, 5, 3, 4, 5, 6, 5, 4, 2, 6, - 2, 6, 5, 2, 4, 6, 2, 10, 4, 3, 5, 10, - 2, 4, 2, 10, 2, 4, 2, 6, 3, 6, 3, 5, - 6, 3, 6, 4, 6, 4, 6, 4, 6, 3, 6, 3, - 6, 4, 6, 4, 6, 4, 6, 3, 6, 3, 6, 4, - 6, 4, 6, 4, 3, 6, 5, 6, 4, 5, 3, 6, - 4, 5, 3, 3, 6, 5, 6, 4, 4, 5, 3, 6, - 3, 6, 4, 3, 3, 6, 4, 3, 3, 3, 6, 3, - 6, 4, 4, 3, 4, 7, 6, 5, 5, 7, 5, 6, - 6, 4, 4, 6, 4, 4, 4, 8, 4, 5, 6, 5, - 6, 6, 3, 3, 6, 5, 6, 5, 6, 5, 4, 5, - 6, 4, 5, 4, 5, 5, 7, 9, 7, 6, 10, 4, - 10, 6, 8, 3, 3, 5, 7, 6, 4, 3, 3, 4, - 4, 5, 5, 5, 4, 4, 4, 3, 3, 4, 3, 4, - 4, 6, 4, 2, 3, 4, 4, 2, 4, 2, 5, 6, - 7, 7, 4, 4, 5, 5, 8, 5, 7, 4, 5, 3, - 3, 4, 4, 5, 4, 7, 7, 3, 3, 9, 5, 6, - 3, 7, 6, 6, 3, 8, 6, 5, 6, 3, 1, 8, - 7, 5, 6, 4, 8, 4, 8, 4, 7, 5, 6, 5, - 9, 6, 7, 5, 7, 8, 10, 5, 5, 9, 5, 7, - 7, 5, 2, 4, 9, 4, 3, 5, 4, 4, 4, 6, - 4, 7, 6, 4, 2, 5, 4, 7, 6, 3, 8, 8, - 3, 6, 4, 6, 6, 4, 6, 9, 4, 9, 4, 9, - 4, 4, 4, 8, 4, 8, 6, 4, 4, 6, 8, 4, - 6, 6, 4, 4, 5, 8, 5, 3, 2, 4, 7, 5, - 4, 6, 6, 4, 6, 8, 7, 6, 7, 9, 4, 3, - 4, 4, 4, 4, 4, 4, 5, 4, 7, 4, 4, 4, - 4, 7, 4, 4, 4, 3, 4, 4, 4, 7, 4, 6, - 4, 4, 7, 8, 4, 6, 4, 3, 8, 4, 6, 5, - 4, 7, 7, 4, 6, 8, 4, 8, 5, 6, 5, 4, - 5, 5, 4, 5, 8, 3, 5, 4, 5, 4, 5, 7, - 4, 5, 7, 7, 5, 5, 5, 3, 5, 4, 5, 5, - 3, 5, 6, 5, 6, 5, 3, 5, 5, 3, 5, 5, - 6, 5, 4, 3, 5, 4, 5, 4, 3, 5, 5, 4, - 4, 5, 4, 3, 5, 4, 7, 5, 4, 7, 5, 9, - 4, 5, 9, 5, 4, 4, 5, 4, 9, 8, 7, 7, - 4, 4, 4, 7, 5, 5, 8, 9, 5, 3, 5, 5, - 5, 4, 9, 5, 6, 10, 6, 10, 5, 8, 5, 9, - 7, 9, 4, 6, 8, 7, 8, 8, 3, 6, 4, 6, - 6, 6, 5, 9, 5, 8, 5, 5, 6, 7, 6, 5, - 6, 3, 7, 8, 5, 3, 4, 2, 3, 7, 4, 4, - 2, 3, 3, 6, 9, 5, 5, 8, 4, 7, 9, 7, - 4, 7, 5, 5, 5, 6, 4, 2, 3, 7, 6, 4, - 9, 5, 4, 5, 5, 5, 8, 5, 6, 4, 4, 4, - 7, 4, 4, 4, 6, 7, 4, 5, 3, 6, 5, 3, - 8, 3, 4, 8, 4, 7, 7, 8, 5, 3, 9, 7, - 8, 6, 8, 6, 7, 7, 5, 3, 5, 4, 2, 4, - 4, 6, 6, 3, 3, 5, 4, 4, 4, 5, 8, 5, - 9, 5, 5, 4, 6, 5, 7, 8, 5, 8, 6, 4, - 7, 4, 9, 5, 3, 4, 5, 3, 4, 5, 5, 4, - 4, 5, 5, 4, 5, 4, 3, 7, 10, 6, 10, 8, - 8, 6, 10, 8, 5, 5, 5, 6, 4, 4, 9, 6, - 5, 6, 4, 3, 7, 7, 4, 4, 3, 4, 4, 7, - 3, 5, 3, 3, 4, 7, 4, 6, 6, 6, 5, 6, - 7, 4, 7, 7, 7, 4, 5, 4, 4, 3, 5, 7, - 5, 3, 5, 11, 7, 7, 5, 7, 3, 7, 6, 6, - 6, 7, 6, 7, 5, 9, 3, 9, 9, 9, 6, 9, - 12, 5, 12, 3, 9, 9, 5, 6, 4, 8, 5, 4, - 8, 3, 4, 6, 4, 10, 6, 4, 8, 6, 7, 6, - 7, 6, 8, 7, 5, 8, 8, 6, 7, 8, 3, 7, - 7, 5, 7, 3, 6, 7, 6, 5, 6, 2, 5, 8, - 5, 2, 5, 6, 8, 2, 5, 3, 8, 7, 5, 3, - 7, 6, 6, 7, 8, 5, 3, 8, 7, 6, 8, 7, - 4, 5, 5, 3, 7, 4, 5, 4, 5, 6, 7, 4, - 5, 4, 6, 5, 4, 3, 6, 7, 4, 6, 6, 8, - 5, 8, 6, 8, 3, 6, 8, 5, 6, 3, 8, 9, - 8, 6, 8, 6, 6, 5, 6, 3, 9, 6, 6, 6, - 5, 5, 5, 5, 5, 5, 5, 6, 5, 6, 5, 5, - 5, 5, 5, 5, 6, 5, 5, 8, 7, 8, 6, 6, - 9, 7, 7, 6, 4, 8, 5, 8, 3, 7, 8, 8, - 6, 4, 10, 3, 7, 10, 10, 7, 5, 8, 7, 4, - 10, 4, 4, 9, 7, 6, 6, 3, 4, 4, 7, 4, - 5, 7, 4, 3, 3, 4, 4, 3, 3, 10, 3, 6, - 3, 4, 3, 6, 9, 6, 4, 7, 5, 11, 5, 7, - 7, 4, 9, 5, 7, 10, 6, 10, 5, 8, 3, 8, - 6, 3, 8, 10, 8, 8, 4, 6, 7, 8, 8, 7, - 10, 3, 7, 5, 8, 7, 8, 11, 4, 11, 5, 5, - 4, 10, 5, 6, 5, 4, 7, 8, 8, 9, 8, 8, - 8, 5, 8, 5, 4, 7, 9, 6, 6, 6, 10, 5, - 5, 8, 9, 9, 9, 4, 6, 4, 5, 4, 6, 8, - 12, 5, 7, 8, 5, 7, 7, 3, 5, 3, 5, 7, - 2, 6, 5, 5, 6, 8, 6, 8, 7, 6, 5, 7, - 6, 8, 5, 8, 6, 2, 8, 5, 8, 5, 8, 4, - 5, 6, 6, 6, 6, 7, 8, 6, 8, 4, 8, 4, - 4, 5, 7, 4, 5, 6, 5, 4, 9, 5, 5, 8, - 8, 5, 9, 5, 8, 12, 12, 4, 7, 6, 10, 5, - 6, 4, 8, 6, 4, 8, 4, 5, 11, 5, 6, 5, - 4, 7, 8, 9, 6, 6, 9, 5, 6, 6, 8, 5, - 7, 5, 8, 5, 4, 5, 8, 4, 4, 7, 9, 4, - 7, 5, 8, 9, 4, 7, 4, 6, 4, 4, 9, 5, - 5, 4, 5, 3, 2, 6, 5, 5, 5, 6, 7, 8, - 8, 8, 7, 7, 7, 6, 5, 5, 6, 5, 5, 9, - 8, 11, 8, 4, 6, 2, 3, 3, 6, 6, 5, 4, - 6, 5, 6, 5, 4, 9, 9, 4, 6, 8, 9, 9, - 5, 3, 2, 5, 10, 6, 11, 5, 6, 7, 5, 9, - 5, 5, 5, 5, 5, 5, 11, 5, 9, 7, 9, 4, - 9, 7, 8, 4, 4, 10, 6, 4, 3, 3, 5, 5, - 4, 6, 3, 4, 5, 8, 4, 6, 3, 6, 6, 6, - 3, 6, 4, 6, 4, 3, 6, 6, 5, 4, 3, 4, - 3, 4, 6, 3, 4, 5, 6, 5, 6, 7, 6, 6, - 7, 6, 7, 3, 3, 7, 4, 7, 5, 6, 6, 7, - 9, 10, 4, 4, 7, 11, 6, 7, 5, 6, 7, 4, - 4, 7, 7, 3, 3, 3, 4, 4, 3, 5, 4, 5, - 3, 13, 8, 5, 7, 4, 5, 5, 4, 8, 8, 7, - 4, 8, 4, 7, 5, 6, 4, 8, 4, 5, 7, 7, - 5, 4, 8, 5, 8, 4, 8, 8, 5, 1, 4, 6, - 4, 5, 4, 6, 4, 7, 5, 6, 7, 7, 4, 7, - 4, 4, 7, 2, 4, 7, 4, 6, 6, 4, 4, 4, - 6, 4, 2, 8, 4, 3, 5, 5, 5, 7, 4, 5, - 9, 5, 4, 4, 3, 6, 7, 6, 8, 3, 6, 8, - 6, 8, 4, 11, 4, 5, 3, 4, 4, 3, 4, 6, - 6, 3, 4, 6, 3, 7, 4, 9, 4, 6, 4, 6, - 4, 4, 8, 5, 8, 9, 6, 2, 10, 9, 8, 5, - 10, 8, 4, 6, 4, 6, 4, 5, 4, 4, 4, 6, - 5, 4, 8, 4, 9, 6, 10, 10, 5, 10, 5, 8, - 7, 7, 5, 8, 9, 4, 5, 3, 9, 3, 8, 4, - 5, 3, 8, 3, 5, 3, 4, 5, 10, 10, 6, 4, - 5, 6, 4, 6, 7, 3, 3, 5, 3, 4, 3, 4, - 6, 3, 4, 4, 4, 6, 5, 5, 6, 5, 6, 5, - 5, 4, 5, 5, 6, 5, 5, 6, 5, 11, 5, 5, - 4, 8, 11, 5, 6, 3, 6, 9, 9, 10, 5, 9, - 5, 4, 5, 10, 5, 5, 6, 5, 5, 5, 5, 3, - 8, 4, 2, 6, 6, 2, 5, 5, 2, 4, 7, 3, - 4, 7, 4, 3, 5, 8, 6, 7, 2, 5, 7, 9, - 5, 6, 6, 6, 3, 5, 5, 8, 11, 9, 8, 6, - 2, 4, 6, 4, 6, 11, 4, 11, 9, 4, 9, 6, - 3, 5, 4, 9, 5, 5, 5, 5, 5, 5, 5, 7, - 4, 2, 6, 5, 9, 9, 6, 15, 5, 5, 5, 5, - 1, 1, 2, 2, 2, 3, 1, 1, 4, 4, 9, 4, - 5, 2, 5, 4, 5, 2, 4, 3, 5, 10, 2, 11, - 2, 6, 3, 8, 2, 3, 7, 5, 8, 6, 2, 6, - 2, 7, 11, 11, 4, 8, 4, 8, 8, 11, 10, 3, - 10, 4, 11, 4, 4, 7, 8, 8, 7, 2, 5, 3, - 8, 7, 5, 4, 5, 5, 5, 7, 8, 5, 6, 5, - 4, 8, 7, 5, 9, 4, 1, 7, 3, 6, 5, 4, - 1, 7, 3, 3, 2, 10, 7, 5, 2, 7, 8, 7, - 7, 5, 4, 7, 4, 6, 4, 6, 8, 2, 3, 6, - 5, 3, 6, 6, 8, 4, 7, 11, 6, 3, 4, 4, - 7, 2, 2, 2, 4, 3, 4, 4, 3, 3, 5, 4, - 4, 3, 5, 5, 4, 6, 3, 4, 4, 8, 6, 8, - 5, 6, 5, 5, 7, 3, 6, 8, 6, 5, 5, 4, - 6, 4, 6, 6, 4, 5, 4, 5, 8, 5, 8, 5, - 4, 7, 6, 5, 6, 2, 5, 6, 4, 5, 8, 5, - 5, 2, 5, 4, 5, 5, 5, 5, 4, 5, 2, 5, - 4, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 4, - 5, 5, 4, 2, 5, 4, 5, 5, 4, 5, 5, 4, - 9, 4, 5, 7, 2, 5, 4, 7, 6, 10, 7, 6, - 3, 6, 6, 16, 6, 9, 7, 4, 5, 5, 4, 4, - 5, 5, 4, 8, 5, 4, 5, 14, 1, 6, 5, 4, - 8, 8, 2, 9, 10, 6, 4, 6, 4, 6, 6, 3, - 2, 6, 3, 4, 2, 3, 4, 4, 4, 5, 4, 4, - 5, 5, 4, 6, 3, 5, 4, 6, 5, 6, 5, 5, - 6, 6, 3, 4, 6, 3, 5, 8, 4, 3, 5, 8, - 7, 6, 5, 4, 7, 5, 7, 5, 6, 4, 7, 5, - 6, 6, 5, 5, 6, 6, 5, 5, 6, 5, 6, 5, - 5, 6, 5, 6, 6, 5, 6, 5, 5, 6, 6, 6, - 6, 5, 5, 5, 6, 5, 6, 5, 7, 4, 5, 4, - 5, 4, 4, 2, 4, 11, 7, 6, 7, 7, 5, 6, - 5, 5, 5, 6, 5, 6, 8, 5, 5, 5, 6, 7, - 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, - 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, - 9, 4, 6, 5, 4, 5, 5, 4, 6, 5, 4, 9, - 4, 4, 2, 4, 10, 4, 3, 5, 4, 7, 7, 6, - 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, - 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, - 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, - 2, 2, 4, 2, 4, 2, 2, 2, 4, 2, 2, 4, - 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, - 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, - 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, - 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 4, 2, - 2, 2, 4, 2, 4, 2, 2, 2, 4, 2, 2, 4, - 2, 2, 4, 2, 2, 4, 2, 4, 2, 2, 2, 4, - 2, 2, 4, 2, 4, 2, 2, 2, 4, 2, 2, 4, - 2, 4, 2, 2, 2, 4, 2, 4, 2, 5, 2, 4, - 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, - 2, 4, 2, 2, 2, 4, 5, 2, 4, 2, 2, 4, - 2, 2, 4, 2, 2, 4, 2, 4, 2, 2, 2, 4, - 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, - 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, - 2, 2, 4, 2, 4, 2, 2, 4, 2, 2, 2, 4, - 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, - 2, 4, 2, 2, 2, 4, 2, 2, 4, 2, 4, 2, - 2, 4, 2, 2, 2, 4, 2, 4, 2, 2, 4, 2, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, - 2, 2, 4, 2, 4, 2, 2, 4, 2, 2, 4, 2, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 9, 4, 2, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, - 7, 5, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 7, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 2, 4, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, - 4, 2, 2, 4, 2, 5, 11, 4, 2, 2, 4, 2, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, - 2, 4, 2, 2, 2, 4, 2, 2, 4, 2, 4, 2, - 2, 2, 4, 2, 4, 2, 2, 4, 2, 2, 2, 4, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, - 2, 2, 4, 2, 4, 2, 2, 4, 2, 2, 4, 2, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, - 2, 4, 2, 12, 4, 2, 2, 4, 2, 6, 4, 2, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 4, - 2, 4, 2, 7, 8, 5, 2, 4, 2, 2, 4, 2, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 2, - 2, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 4, - 2, 4, 2, 2, 4, 2, 2, 4, 2 }; - -const ReplacementStruct ReplacementInitData[] = { - { small(2), small(10), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(5), small(1) }, - { small(2), small(31), small(5) }, - { small(2), small(6), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(23), small(3) }, - { small(2), small(14), small(2) }, - { small(2), small(18), small(3) }, - { small(2), small(13), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(15), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(22), small(3) }, - { small(2), small(21), small(3) }, - { small(2), small(5), small(1) }, - { small(2), small(18), small(3) }, - { small(2), small(30), small(5) }, - { small(2), small(30), small(5) }, - { small(2), small(12), small(2) }, - { small(2), small(26), small(4) }, - { small(2), small(19), small(3) }, - { small(2), small(11), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(14), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(24), small(3) }, - { small(2), small(14), small(2) }, - { small(2), small(21), small(3) }, - { small(2), small(11), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(30), small(5) }, - { small(2), small(16), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(23), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(10), small(1) }, - { small(2), small(27), small(5) }, - { small(2), small(15), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(10), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(16), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(24), small(4) }, - { small(2), small(14), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(12), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(19), small(3) }, - { small(2), small(14), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(15), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(23), small(3) }, - { small(2), small(18), small(2) }, - { small(2), small(24), small(4) }, - { small(2), small(14), small(2) }, - { small(2), small(18), small(3) }, - { small(2), small(13), small(2) }, - { small(2), small(22), small(4) }, - { small(2), small(8), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(5), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(17), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(22), small(3) }, - { small(2), small(18), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(16), small(3) }, - { small(2), small(12), small(2) }, - { small(2), small(11), small(2) }, - { small(2), small(9), small(2) }, - { small(2), small(16), small(3) }, - { small(2), small(11), small(2) }, - { small(2), small(13), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(17), small(3) }, - { small(2), small(13), small(2) }, - { small(2), small(19), small(3) }, - { small(2), small(12), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(11), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(4), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(4), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(7), small(1) }, - { small(1), small(6), small(1) }, - { small(2), small(11), small(2) }, - { small(2), small(18), small(3) }, - { small(2), small(12), small(2) }, - { small(2), small(19), small(3) }, - { small(2), small(43), small(7) }, - { small(2), small(17), small(2) }, - { small(2), small(3), small(1) }, - { small(2), small(18), small(3) }, - { small(2), small(19), small(4) }, - { small(2), small(7), small(1) }, - { small(2), small(9), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(13), small(2) }, - { small(2), small(12), small(3) }, - { small(2), small(12), small(2) }, - { small(2), small(10), small(2) }, - { small(1), small(13), small(2) }, - { small(2), small(14), small(3) }, - { small(2), small(21), small(4) }, - { small(2), small(34), small(5) }, - { small(2), small(14), small(2) }, - { small(2), small(55), small(9) }, - { small(2), small(8), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(14), small(3) }, - { small(2), small(9), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(43), small(6) }, - { small(2), small(15), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(29), small(4) }, - { small(2), small(15), small(2) }, - { small(2), small(20), small(3) }, - { small(2), small(21), small(3) }, - { small(2), small(6), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(5), small(1) }, - { small(5), small(20), small(3) }, - { small(5), small(18), small(3) }, - { small(5), small(24), small(4) }, - { small(5), small(21), small(3) }, - { small(2), small(16), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(13), small(2) }, - { small(2), small(11), small(2) }, - { small(2), small(21), small(5) }, - { small(2), small(22), small(4) }, - { small(5), small(22), small(3) }, - { small(5), small(20), small(3) }, - { small(5), small(17), small(3) }, - { small(5), small(23), small(3) }, - { small(2), small(22), small(3) }, - { small(5), small(22), small(3) }, - { small(5), small(20), small(3) }, - { small(5), small(5), small(1) }, - { small(5), small(16), small(2) }, - { small(5), small(27), small(3) }, - { small(5), small(25), small(3) }, - { small(5), small(21), small(2) }, - { small(5), small(13), small(2) }, - { small(5), small(11), small(2) }, - { small(5), small(11), small(1) }, - { small(5), small(7), small(1) }, - { small(6), small(17), small(2) }, - { small(6), small(15), small(2) }, - { small(6), small(15), small(3) }, - { small(6), small(5), small(1) }, - { small(6), small(11), small(1) }, - { small(5), small(21), small(3) }, - { small(5), small(19), small(3) }, - { small(5), small(14), small(2) }, - { small(5), small(12), small(2) }, - { small(5), small(12), small(2) }, - { small(5), small(10), small(2) }, - { small(5), small(15), small(2) }, - { small(5), small(13), small(2) }, - { small(5), small(14), small(2) }, - { small(5), small(12), small(2) }, - { small(5), small(15), small(2) }, - { small(5), small(13), small(2) }, - { small(5), small(22), small(3) }, - { small(5), small(20), small(3) }, - { small(5), small(20), small(2) }, - { small(5), small(18), small(2) }, - { small(5), small(21), small(3) }, - { small(5), small(19), small(3) }, - { small(5), small(16), small(2) }, - { small(5), small(14), small(2) }, - { small(5), small(17), small(2) }, - { small(5), small(15), small(2) }, - { small(5), small(14), small(2) }, - { small(5), small(12), small(2) }, - { small(5), small(19), small(2) }, - { small(5), small(17), small(2) }, - { small(5), small(13), small(2) }, - { small(5), small(11), small(2) }, - { small(5), small(17), small(2) }, - { small(5), small(15), small(2) }, - { small(5), small(13), small(2) }, - { small(5), small(11), small(2) }, - { small(2), small(17), small(3) }, - { small(2), small(15), small(3) }, - { small(2), small(10), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(18), small(2) }, - { small(2), small(11), small(2) }, - { small(2), small(7), small(1) }, - { small(5), small(12), small(2) }, - { small(5), small(6), small(1) }, - { small(5), small(10), small(2) }, - { small(5), small(11), small(2) }, - { small(5), small(5), small(1) }, - { small(5), small(9), small(2) }, - { small(5), small(15), small(2) }, - { small(5), small(9), small(1) }, - { small(5), small(13), small(2) }, - { small(5), small(14), small(2) }, - { small(5), small(8), small(1) }, - { small(5), small(12), small(2) }, - { small(5), small(13), small(2) }, - { small(5), small(7), small(1) }, - { small(5), small(11), small(2) }, - { small(5), small(9), small(1) }, - { small(5), small(11), small(1) }, - { small(5), small(8), small(1) }, - { small(5), small(13), small(2) }, - { small(5), small(7), small(1) }, - { small(5), small(11), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(17), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(16), small(2) }, - { small(5), small(14), small(2) }, - { small(5), small(12), small(2) }, - { small(5), small(5), small(1) }, - { small(5), small(15), small(2) }, - { small(5), small(20), small(3) }, - { small(5), small(25), small(3) }, - { small(5), small(21), small(3) }, - { small(5), small(18), small(3) }, - { small(5), small(20), small(3) }, - { small(5), small(9), small(2) }, - { small(5), small(21), small(3) }, - { small(5), small(18), small(3) }, - { small(5), small(20), small(3) }, - { small(5), small(10), small(2) }, - { small(5), small(21), small(3) }, - { small(5), small(18), small(3) }, - { small(5), small(20), small(3) }, - { small(5), small(14), small(2) }, - { small(5), small(21), small(3) }, - { small(5), small(18), small(3) }, - { small(5), small(19), small(2) }, - { small(5), small(17), small(2) }, - { small(5), small(10), small(1) }, - { small(5), small(11), small(2) }, - { small(5), small(20), small(2) }, - { small(5), small(17), small(2) }, - { small(5), small(18), small(2) }, - { small(5), small(15), small(2) }, - { small(5), small(15), small(2) }, - { small(5), small(26), small(4) }, - { small(5), small(16), small(2) }, - { small(5), small(13), small(2) }, - { small(5), small(16), small(2) }, - { small(5), small(17), small(2) }, - { small(5), small(14), small(2) }, - { small(5), small(23), small(3) }, - { small(5), small(9), small(1) }, - { small(5), small(24), small(3) }, - { small(5), small(21), small(3) }, - { small(5), small(28), small(4) }, - { small(5), small(9), small(1) }, - { small(5), small(24), small(3) }, - { small(5), small(26), small(4) }, - { small(5), small(22), small(4) }, - { small(5), small(23), small(4) }, - { small(5), small(20), small(4) }, - { small(2), small(11), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(13), small(2) }, - { small(5), small(32), small(5) }, - { small(5), small(9), small(1) }, - { small(5), small(33), small(5) }, - { small(5), small(30), small(5) }, - { small(2), small(33), small(5) }, - { small(5), small(15), small(2) }, - { small(5), small(13), small(2) }, - { small(5), small(9), small(1) }, - { small(5), small(16), small(2) }, - { small(5), small(15), small(2) }, - { small(5), small(13), small(2) }, - { small(5), small(8), small(1) }, - { small(5), small(16), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(25), small(4) }, - { small(2), small(23), small(4) }, - { small(2), small(19), small(3) }, - { small(2), small(29), small(5) }, - { small(8), small(22), small(4) }, - { small(8), small(11), small(2) }, - { small(8), small(22), small(4) }, - { small(8), small(11), small(2) }, - { small(2), small(12), small(1) }, - { small(2), small(16), small(3) }, - { small(11), small(15), small(2) }, - { small(11), small(9), small(2) }, - { small(11), small(15), small(2) }, - { small(11), small(9), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(22), small(4) }, - { small(8), small(12), small(2) }, - { small(11), small(13), small(2) }, - { small(11), small(13), small(2) }, - { small(11), small(13), small(2) }, - { small(8), small(12), small(2) }, - { small(8), small(12), small(2) }, - { small(11), small(13), small(2) }, - { small(11), small(13), small(2) }, - { small(11), small(13), small(2) }, - { small(8), small(12), small(2) }, - { small(8), small(12), small(2) }, - { small(11), small(13), small(2) }, - { small(11), small(13), small(2) }, - { small(11), small(13), small(2) }, - { small(5), small(18), small(3) }, - { small(5), small(19), small(3) }, - { small(8), small(23), small(4) }, - { small(8), small(22), small(4) }, - { small(8), small(24), small(4) }, - { small(5), small(16), small(3) }, - { small(5), small(17), small(3) }, - { small(8), small(21), small(4) }, - { small(8), small(20), small(4) }, - { small(8), small(22), small(4) }, - { small(2), small(6), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(11), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(11), small(2) }, - { small(2), small(15), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(14), small(2) }, - { small(1), small(25), small(4) }, - { small(1), small(19), small(3) }, - { small(2), small(7), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(12), small(1) }, - { small(2), small(17), small(2) }, - { small(2), small(17), small(2) }, - { small(2), small(5), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(10), small(2) }, - { small(2), small(5), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(11), small(2) }, - { small(2), small(5), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(10), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(13), small(3) }, - { small(2), small(14), small(3) }, - { small(2), small(15), small(3) }, - { small(2), small(8), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(15), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(10), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(7), small(2) }, - { small(2), small(10), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(17), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(4), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(15), small(3) }, - { small(2), small(6), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(11), small(2) }, - { small(2), small(10), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(18), small(3) }, - { small(2), small(8), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(10), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(13), small(3) }, - { small(2), small(9), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(13), small(2) }, - { small(2), small(10), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(15), small(3) }, - { small(2), small(21), small(4) }, - { small(2), small(30), small(5) }, - { small(2), small(29), small(5) }, - { small(2), small(20), small(4) }, - { small(2), small(11), small(2) }, - { small(2), small(21), small(3) }, - { small(2), small(19), small(3) }, - { small(2), small(22), small(3) }, - { small(2), small(10), small(2) }, - { small(2), small(22), small(3) }, - { small(2), small(20), small(3) }, - { small(2), small(21), small(3) }, - { small(2), small(15), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(1), small(10), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(20), small(3) }, - { small(2), small(15), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(28), small(5) }, - { small(2), small(23), small(4) }, - { small(2), small(14), small(2) }, - { small(2), small(24), small(4) }, - { small(2), small(17), small(3) }, - { small(2), small(7), small(1) }, - { small(2), small(34), small(6) }, - { small(2), small(22), small(4) }, - { small(2), small(17), small(3) }, - { small(2), small(12), small(2) }, - { small(1), small(24), small(4) }, - { small(1), small(20), small(3) }, - { small(2), small(22), small(3) }, - { small(2), small(17), small(2) }, - { small(2), small(17), small(3) }, - { small(2), small(12), small(2) }, - { small(2), small(11), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(19), small(3) }, - { small(2), small(6), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(10), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(11), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(13), small(3) }, - { small(2), small(13), small(2) }, - { small(2), small(14), small(3) }, - { small(2), small(9), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(19), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(21), small(4) }, - { small(2), small(13), small(2) }, - { small(2), small(11), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(11), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(11), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(11), small(2) }, - { small(2), small(10), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(11), small(2) }, - { small(2), small(15), small(3) }, - { small(2), small(6), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(16), small(3) }, - { small(2), small(6), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(17), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(10), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(26), small(4) }, - { small(2), small(11), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(16), small(3) }, - { small(2), small(27), small(5) }, - { small(2), small(18), small(3) }, - { small(2), small(17), small(3) }, - { small(2), small(13), small(2) }, - { small(2), small(12), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(11), small(2) }, - { small(2), small(11), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(18), small(3) }, - { small(2), small(14), small(2) }, - { small(2), small(10), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(15), small(3) }, - { small(2), small(23), small(4) }, - { small(2), small(15), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(22), small(3) }, - { small(2), small(25), small(4) }, - { small(2), small(6), small(1) }, - { small(1), small(11), small(2) }, - { small(2), small(15), small(2) }, - { small(2), small(5), small(1) }, - { small(1), small(7), small(1) }, - { small(2), small(13), small(1) }, - { small(6), small(23), small(3) }, - { small(6), small(21), small(3) }, - { small(6), small(15), small(2) }, - { small(6), small(8), small(1) }, - { small(6), small(24), small(3) }, - { small(5), small(17), small(2) }, - { small(5), small(15), small(2) }, - { small(5), small(11), small(1) }, - { small(5), small(11), small(1) }, - { small(5), small(18), small(2) }, - { small(5), small(20), small(2) }, - { small(5), small(18), small(2) }, - { small(5), small(11), small(1) }, - { small(5), small(24), small(3) }, - { small(5), small(21), small(3) }, - { small(5), small(19), small(3) }, - { small(5), small(18), small(3) }, - { small(5), small(19), small(2) }, - { small(5), small(22), small(3) }, - { small(2), small(9), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(16), small(2) }, - { small(5), small(24), small(3) }, - { small(5), small(10), small(1) }, - { small(5), small(25), small(3) }, - { small(5), small(22), small(3) }, - { small(6), small(15), small(2) }, - { small(6), small(13), small(2) }, - { small(6), small(8), small(1) }, - { small(6), small(16), small(2) }, - { small(2), small(14), small(2) }, - { small(5), small(25), small(4) }, - { small(5), small(26), small(4) }, - { small(5), small(23), small(4) }, - { small(5), small(15), small(2) }, - { small(5), small(13), small(2) }, - { small(5), small(8), small(1) }, - { small(5), small(16), small(2) }, - { small(5), small(16), small(2) }, - { small(5), small(14), small(2) }, - { small(5), small(9), small(1) }, - { small(5), small(17), small(2) }, - { small(5), small(26), small(4) }, - { small(5), small(24), small(4) }, - { small(5), small(12), small(2) }, - { small(5), small(27), small(4) }, - { small(5), small(19), small(3) }, - { small(5), small(17), small(3) }, - { small(5), small(9), small(1) }, - { small(5), small(20), small(3) }, - { small(5), small(16), small(2) }, - { small(5), small(17), small(2) }, - { small(5), small(14), small(2) }, - { small(5), small(23), small(3) }, - { small(5), small(21), small(3) }, - { small(5), small(20), small(2) }, - { small(5), small(24), small(3) }, - { small(5), small(14), small(2) }, - { small(5), small(12), small(2) }, - { small(5), small(11), small(1) }, - { small(5), small(15), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(19), small(3) }, - { small(2), small(13), small(2) }, - { small(2), small(20), small(3) }, - { small(2), small(14), small(2) }, - { small(2), small(19), small(3) }, - { small(2), small(13), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(17), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(19), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(13), small(2) }, - { small(5), small(16), small(2) }, - { small(5), small(14), small(2) }, - { small(5), small(9), small(1) }, - { small(5), small(10), small(1) }, - { small(5), small(17), small(2) }, - { small(2), small(17), small(2) }, - { small(2), small(5), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(18), small(2) }, - { small(2), small(22), small(3) }, - { small(2), small(6), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(10), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(9), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(10), small(2) }, - { small(2), small(5), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(10), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(11), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(19), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(19), small(2) }, - { small(2), small(12), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(21), small(3) }, - { small(2), small(14), small(2) }, - { small(2), small(21), small(2) }, - { small(2), small(15), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(19), small(2) }, - { small(2), small(20), small(2) }, - { small(2), small(13), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(18), small(2) }, - { small(2), small(10), small(1) }, - { small(2), small(18), small(2) }, - { small(2), small(19), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(18), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(20), small(2) }, - { small(2), small(19), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(19), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(12), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(13), small(2) }, - { small(1), small(7), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(14), small(1) }, - { small(2), small(24), small(3) }, - { small(2), small(15), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(11), small(2) }, - { small(2), small(5), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(19), small(3) }, - { small(2), small(13), small(2) }, - { small(2), small(17), small(2) }, - { small(2), small(17), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(10), small(1) }, - { small(1), small(20), small(3) }, - { small(1), small(16), small(2) }, - { small(2), small(21), small(3) }, - { small(2), small(7), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(9), small(1) }, - { small(1), small(10), small(1) }, - { small(2), small(22), small(3) }, - { small(2), small(15), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(19), small(3) }, - { small(2), small(17), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(25), small(3) }, - { small(2), small(17), small(2) }, - { small(2), small(23), small(2) }, - { small(2), small(19), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(18), small(2) }, - { small(2), small(13), small(2) }, - { small(2), small(22), small(3) }, - { small(2), small(10), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(19), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(20), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(7), small(1) }, - { small(1), small(15), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(15), small(2) }, - { small(2), small(10), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(15), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(24), small(3) }, - { small(2), small(7), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(13), small(2) }, - { small(2), small(11), small(2) }, - { small(2), small(11), small(1) }, - { small(2), small(18), small(3) }, - { small(2), small(11), small(2) }, - { small(2), small(17), small(3) }, - { small(2), small(7), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(18), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(20), small(3) }, - { small(2), small(20), small(3) }, - { small(2), small(11), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(13), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(4), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(19), small(3) }, - { small(2), small(14), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(11), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(20), small(2) }, - { small(2), small(11), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(4), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(19), small(2) }, - { small(2), small(13), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(15), small(2) }, - { small(1), small(11), small(1) }, - { small(1), small(13), small(2) }, - { small(1), small(7), small(1) }, - { small(1), small(13), small(2) }, - { small(2), small(19), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(11), small(1) }, - { small(1), small(24), small(3) }, - { small(2), small(11), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(10), small(2) }, - { small(2), small(5), small(1) }, - { small(2), small(18), small(3) }, - { small(2), small(8), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(5), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(1), small(17), small(3) }, - { small(1), small(13), small(2) }, - { small(2), small(19), small(3) }, - { small(2), small(7), small(1) }, - { small(1), small(6), small(1) }, - { small(2), small(14), small(3) }, - { small(2), small(6), small(1) }, - { small(1), small(8), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(5), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(13), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(9), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(16), small(3) }, - { small(2), small(7), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(24), small(2) }, - { small(2), small(20), small(3) }, - { small(2), small(13), small(2) }, - { small(2), small(15), small(2) }, - { small(2), small(18), small(2) }, - { small(2), small(15), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(17), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(10), small(1) }, - { small(2), small(21), small(3) }, - { small(2), small(19), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(8), small(2) }, - { small(2), small(13), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(13), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(19), small(3) }, - { small(2), small(22), small(4) }, - { small(2), small(9), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(16), small(3) }, - { small(2), small(16), small(3) }, - { small(2), small(15), small(2) }, - { small(2), small(11), small(2) }, - { small(2), small(26), small(4) }, - { small(2), small(28), small(4) }, - { small(2), small(17), small(3) }, - { small(2), small(16), small(2) }, - { small(2), small(21), small(3) }, - { small(2), small(17), small(2) }, - { small(2), small(10), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(13), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(15), small(3) }, - { small(2), small(10), small(2) }, - { small(2), small(24), small(4) }, - { small(2), small(12), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(11), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(18), small(3) }, - { small(2), small(21), small(3) }, - { small(2), small(10), small(1) }, - { small(2), small(21), small(3) }, - { small(2), small(12), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(32), small(4) }, - { small(2), small(8), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(11), small(2) }, - { small(2), small(13), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(19), small(2) }, - { small(2), small(12), small(1) }, - { small(2), small(18), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(10), small(1) }, - { small(2), small(26), small(4) }, - { small(2), small(15), small(2) }, - { small(2), small(25), small(4) }, - { small(2), small(14), small(2) }, - { small(2), small(11), small(2) }, - { small(2), small(23), small(3) }, - { small(2), small(12), small(1) }, - { small(2), small(19), small(3) }, - { small(2), small(8), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(11), small(2) }, - { small(2), small(19), small(4) }, - { small(2), small(22), small(4) }, - { small(2), small(6), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(13), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(13), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(39), small(5) }, - { small(2), small(19), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(18), small(2) }, - { small(2), small(11), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(17), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(18), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(19), small(3) }, - { small(2), small(11), small(2) }, - { small(2), small(17), small(3) }, - { small(2), small(15), small(3) }, - { small(2), small(18), small(3) }, - { small(2), small(9), small(1) }, - { small(2), small(10), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(18), small(3) }, - { small(1), small(11), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(13), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(4), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(18), small(2) }, - { small(2), small(13), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(11), small(1) }, - { small(2), small(18), small(3) }, - { small(2), small(16), small(2) }, - { small(2), small(7), small(1) }, - { small(3), small(7), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(7), small(1) }, - { small(3), small(7), small(1) }, - { small(2), small(26), small(4) }, - { small(2), small(4), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(21), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(17), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(7), small(1) }, - { small(3), small(3), small(1) }, - { small(3), small(3), small(1) }, - { small(2), small(4), small(1) }, - { small(2), small(4), small(1) }, - { small(3), small(4), small(1) }, - { small(2), small(5), small(1) }, - { small(1), small(3), small(1) }, - { small(2), small(3), small(1) }, - { small(2), small(11), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(10), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(15), small(3) }, - { small(2), small(5), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(15), small(3) }, - { small(2), small(13), small(2) }, - { small(2), small(19), small(3) }, - { small(2), small(10), small(1) }, - { small(2), small(18), small(3) }, - { small(2), small(12), small(2) }, - { small(2), small(13), small(1) }, - { small(1), small(18), small(2) }, - { small(1), small(10), small(1) }, - { small(1), small(15), small(2) }, - { small(2), small(10), small(1) }, - { small(2), small(13), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(17), small(2) }, - { small(2), small(23), small(3) }, - { small(2), small(9), small(1) }, - { small(2), small(19), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(14), small(3) }, - { small(2), small(10), small(1) }, - { small(2), small(9), small(1) }, - { small(1), small(18), small(3) }, - { small(3), small(7), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(23), small(3) }, - { small(1), small(29), small(4) }, - { small(2), small(22), small(3) }, - { small(2), small(33), small(6) }, - { small(2), small(3), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(4), small(1) }, - { small(2), small(12), small(1) }, - { small(3), small(9), small(1) }, - { small(2), small(7), small(1) }, - { small(3), small(4), small(1) }, - { small(2), small(18), small(2) }, - { small(2), small(9), small(1) }, - { small(2), small(15), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(10), small(1) }, - { small(2), small(25), small(5) }, - { small(2), small(8), small(1) }, - { small(2), small(17), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(20), small(2) }, - { small(2), small(5), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(4), small(1) }, - { small(2), small(4), small(1) }, - { small(2), small(4), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(6), small(1) }, - { small(3), small(6), small(1) }, - { small(3), small(5), small(1) }, - { small(3), small(5), small(1) }, - { small(3), small(7), small(1) }, - { small(3), small(6), small(1) }, - { small(3), small(6), small(1) }, - { small(3), small(5), small(1) }, - { small(3), small(7), small(1) }, - { small(3), small(7), small(1) }, - { small(3), small(6), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(6), small(1) }, - { small(3), small(6), small(1) }, - { small(3), small(17), small(2) }, - { small(3), small(10), small(1) }, - { small(2), small(14), small(2) }, - { small(2), small(7), small(1) }, - { small(2), small(15), small(2) }, - { small(1), small(21), small(3) }, - { small(1), small(14), small(2) }, - { small(1), small(12), small(2) }, - { small(1), small(13), small(2) }, - { small(1), small(15), small(2) }, - { small(1), small(12), small(2) }, - { small(1), small(12), small(2) }, - { small(1), small(16), small(2) }, - { small(1), small(16), small(2) }, - { small(1), small(14), small(2) }, - { small(1), small(8), small(1) }, - { small(1), small(17), small(3) }, - { small(1), small(19), small(3) }, - { small(2), small(16), small(2) }, - { small(2), small(16), small(3) }, - { small(2), small(18), small(3) }, - { small(2), small(13), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(10), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(19), small(3) }, - { small(2), small(19), small(3) }, - { small(2), small(18), small(3) }, - { small(2), small(18), small(3) }, - { small(2), small(15), small(3) }, - { small(2), small(18), small(3) }, - { small(2), small(18), small(3) }, - { small(2), small(27), small(4) }, - { small(2), small(18), small(3) }, - { small(2), small(20), small(3) }, - { small(2), small(27), small(3) }, - { small(2), small(8), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(25), small(2) }, - { small(2), small(18), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(7), small(1) }, - { small(1), small(17), small(3) }, - { small(1), small(18), small(3) }, - { small(1), small(21), small(3) }, - { small(2), small(24), small(3) }, - { small(2), small(19), small(3) }, - { small(2), small(19), small(2) }, - { small(2), small(4), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(12), small(1) }, - { small(2), small(20), small(3) }, - { small(2), small(13), small(2) }, - { small(5), small(22), small(4) }, - { small(2), small(5), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(4), small(1) }, - { small(2), small(5), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(11), small(2) }, - { small(1), small(12), small(2) }, - { small(1), small(6), small(1) }, - { small(2), small(18), small(3) }, - { small(2), small(23), small(4) }, - { small(2), small(14), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(14), small(2) }, - { small(2), small(12), small(2) }, - { small(2), small(13), small(2) }, - { small(2), small(20), small(3) }, - { small(2), small(25), small(4) }, - { small(2), small(22), small(3) }, - { small(2), small(20), small(3) }, - { small(2), small(22), small(3) }, - { small(2), small(20), small(3) }, - { small(2), small(21), small(3) }, - { small(2), small(21), small(3) }, - { small(2), small(20), small(3) }, - { small(2), small(20), small(3) }, - { small(2), small(27), small(4) }, - { small(2), small(27), small(4) }, - { small(2), small(21), small(3) }, - { small(2), small(21), small(3) }, - { small(2), small(20), small(3) }, - { small(2), small(20), small(3) }, - { small(2), small(9), small(1) }, - { small(2), small(6), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(12), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(9), small(2) }, - { small(2), small(6), small(1) }, - { small(2), small(13), small(1) }, - { small(2), small(16), small(2) }, - { small(2), small(17), small(2) }, - { small(2), small(20), small(3) }, - { small(2), small(13), small(2) }, - { small(2), small(8), small(1) }, - { small(2), small(7), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(13), small(2) }, - { small(2), small(22), small(3) }, - { small(3), small(9), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(8), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(9), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(10), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(11), small(1) }, - { small(2), small(11), small(1) }, - { small(3), small(19), small(3) }, - { small(3), small(12), small(2) }, - { small(2), small(19), small(3) }, - { small(2), small(12), small(2) }, - { small(2), small(16), small(2) }, - { small(2), small(25), small(4) }, - { small(6), small(16), small(3) }, - { small(6), small(14), small(2) }, - { small(4), small(16), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(7), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(7), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(11), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(2), small(15), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(9), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(7), small(1) }, - { small(4), small(13), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(14), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(8), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(14), small(9), small(1) }, - { small(14), small(10), small(1) }, - { small(14), small(7), small(1) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, - { small(4), small(4), small(1) }, - { small(4), small(9), small(2) }, -}; - -const medium ReplacementIndices[] = { - 140, 144, 1283, 1359, 161, 736, 52, 79, 81, 116, 118, 152, - 169, 198, 207, 254, 255, 260, 261, 292, 413, 475, 572, 573, - 574, 598, 615, 616, 633, 723, 724, 747, 748, 749, 753, 835, - 843, 844, 869, 873, 884, 886, 901, 902, 903, 904, 905, 920, - 957, 996, 1036, 1060, 1062, 1065, 1079, 1083, 1101, 1104, 1120, 1222, - 1233, 1243, 1246, 1247, 1248, 1263, 1270, 1272, 1284, 1301, 1312, 1315, - 1319, 1339, 1340, 1341, 1361, 1362, 1365, 1377, 1378, 1379, 1380, 1381, - 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, - 1394, 1395, 1396, 1399, 1400, 1456, 1457, 1498, 1499, 1500, 1501, 1502, - 1503, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, - 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1526, 1527, 1528, 1529, 1530, - 1531, 1928, 1929, 1984, 1985, 11, 97, 98, 165, 166, 169, 188, - 191, 192, 193, 196, 200, 201, 202, 203, 204, 264, 295, 296, - 297, 298, 299, 347, 349, 350, 351, 376, 391, 393, 394, 396, - 398, 399, 407, 411, 418, 420, 428, 440, 457, 458, 464, 466, - 470, 471, 472, 474, 489, 507, 541, 549, 555, 556, 581, 591, - 594, 607, 620, 634, 642, 643, 644, 651, 654, 664, 675, 678, - 690, 696, 706, 711, 712, 720, 726, 727, 730, 732, 739, 742, - 748, 750, 751, 775, 776, 777, 778, 779, 807, 808, 810, 814, - 815, 816, 817, 818, 819, 820, 821, 858, 863, 864, 876, 883, - 893, 894, 925, 939, 940, 941, 954, 956, 958, 966, 972, 996, - 1006, 1007, 1042, 1044, 1065, 1069, 1080, 1081, 1082, 1093, 1094, 1095, - 1096, 1103, 1107, 1111, 1114, 1138, 1139, 1150, 1151, 1152, 1153, 1166, - 1167, 1168, 1169, 1170, 1171, 1172, 1182, 1183, 1186, 1204, 1206, 1207, - 1251, 1252, 1260, 1271, 1281, 1288, 1297, 1299, 1300, 1306, 1327, 1331, - 1366, 1367, 1369, 1370, 1379, 1412, 1414, 1416, 1424, 1425, 1427, 1429, - 1433, 1435, 1436, 1437, 1438, 1440, 1442, 1444, 1450, 1451, 1454, 1455, - 1456, 1462, 1491, 1492, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, - 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, - 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1566, 1567, 1568, 1569, - 1570, 1571, 1572, 1573, 1584, 1585, 1841, 1842, 1922, 1923, 23, 26, - 28, 40, 46, 49, 59, 101, 102, 107, 108, 116, 117, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 135, 152, 153, 172, - 173, 195, 210, 218, 220, 221, 222, 236, 237, 268, 269, 342, - 360, 363, 364, 365, 366, 367, 368, 369, 371, 373, 401, 402, - 418, 421, 422, 423, 432, 434, 446, 455, 458, 459, 460, 476, - 488, 496, 504, 505, 509, 518, 526, 532, 533, 540, 555, 566, - 568, 571, 580, 584, 585, 588, 589, 591, 592, 593, 594, 595, - 596, 597, 598, 599, 600, 601, 602, 603, 625, 628, 635, 637, - 638, 641, 646, 647, 649, 652, 669, 673, 680, 681, 682, 686, - 689, 693, 695, 696, 699, 700, 707, 709, 713, 714, 718, 720, - 721, 728, 742, 743, 757, 771, 772, 773, 774, 811, 812, 813, - 837, 845, 861, 863, 866, 867, 868, 882, 887, 889, 912, 917, - 922, 931, 932, 935, 936, 947, 950, 958, 959, 968, 972, 973, - 990, 991, 992, 993, 1000, 1001, 1003, 1010, 1013, 1016, 1017, 1018, - 1019, 1032, 1034, 1036, 1037, 1038, 1046, 1055, 1067, 1073, 1076, 1080, - 1101, 1102, 1109, 1114, 1118, 1129, 1136, 1139, 1140, 1141, 1144, 1145, - 1146, 1149, 1150, 1151, 1154, 1155, 1158, 1164, 1166, 1189, 1190, 1197, - 1215, 1220, 1221, 1222, 1229, 1236, 1242, 1265, 1273, 1303, 1308, 1310, - 1313, 1317, 1325, 1326, 1327, 1334, 1341, 1345, 1399, 1400, 1408, 1410, - 1421, 1423, 1424, 1426, 1427, 1428, 1429, 1459, 1463, 1465, 1466, 1467, - 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, - 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, 1488, 1493, 1576, 1577, - 1578, 1579, 1582, 1583, 1588, 1589, 1592, 1593, 1594, 1595, 1596, 1597, - 1598, 1599, 1600, 1601, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, - 1612, 1613, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1660, 1661, - 1730, 1946, 1947, 15, 16, 37, 60, 83, 84, 86, 142, 162, - 227, 228, 231, 301, 344, 345, 346, 348, 406, 431, 433, 461, - 492, 504, 515, 516, 521, 522, 530, 531, 535, 575, 608, 609, - 610, 655, 676, 684, 698, 719, 774, 850, 851, 856, 857, 902, - 942, 944, 956, 962, 992, 1003, 1004, 1012, 1014, 1047, 1050, 1071, - 1072, 1100, 1116, 1141, 1147, 1158, 1159, 1164, 1217, 1224, 1225, 1287, - 1305, 1315, 1366, 1377, 1378, 1381, 1385, 1390, 1395, 1405, 1407, 1420, - 1431, 1432, 1433, 1434, 1435, 1461, 1504, 1505, 1562, 1563, 1624, 1625, - 1626, 1627, 1628, 1629, 1630, 1631, 1674, 1675, 19, 22, 23, 26, - 27, 29, 55, 73, 75, 76, 126, 175, 183, 186, 187, 274, - 275, 276, 293, 347, 349, 350, 430, 451, 452, 453, 462, 501, - 534, 548, 572, 573, 574, 632, 648, 870, 931, 964, 1043, 1052, - 1119, 1120, 1121, 1122, 1123, 1208, 1209, 1260, 1280, 1282, 1293, 1294, - 1312, 1356, 1363, 1364, 1408, 1414, 1415, 1632, 1633, 1634, 1635, 1640, - 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1916, 1917, 1918, 1919, 1988, - 2009, 2010, 8, 13, 15, 28, 29, 30, 31, 41, 42, 43, - 44, 47, 54, 56, 58, 62, 65, 67, 68, 70, 72, 75, - 78, 84, 86, 87, 90, 91, 93, 95, 96, 97, 99, 101, - 107, 120, 130, 147, 148, 149, 150, 151, 152, 153, 167, 169, - 175, 176, 185, 234, 235, 244, 245, 256, 257, 289, 290, 291, - 295, 316, 317, 318, 319, 320, 325, 328, 329, 330, 335, 338, - 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, - 399, 400, 438, 439, 441, 445, 449, 450, 468, 490, 491, 529, - 531, 540, 544, 552, 558, 559, 560, 561, 562, 563, 569, 582, - 583, 607, 614, 644, 658, 662, 668, 669, 677, 681, 682, 691, - 723, 724, 725, 731, 735, 741, 749, 780, 781, 782, 823, 824, - 870, 894, 909, 918, 921, 934, 937, 949, 960, 989, 997, 1012, - 1017, 1020, 1022, 1026, 1040, 1045, 1077, 1105, 1106, 1112, 1137, 1150, - 1154, 1156, 1157, 1184, 1185, 1262, 1305, 1347, 1352, 1353, 1365, 1375, - 1463, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1499, 1501, 1503, - 1505, 1507, 1509, 1511, 1513, 1515, 1517, 1519, 1521, 1523, 1525, 1527, - 1529, 1531, 1533, 1535, 1537, 1539, 1541, 1543, 1545, 1547, 1549, 1551, - 1553, 1555, 1557, 1559, 1561, 1563, 1565, 1567, 1569, 1571, 1573, 1575, - 1577, 1579, 1581, 1583, 1585, 1587, 1589, 1591, 1593, 1595, 1597, 1599, - 1601, 1603, 1605, 1607, 1609, 1611, 1613, 1615, 1617, 1619, 1621, 1623, - 1625, 1627, 1629, 1631, 1633, 1635, 1637, 1639, 1641, 1643, 1645, 1647, - 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1657, 1658, 1659, 1661, - 1663, 1665, 1667, 1669, 1671, 1673, 1675, 1677, 1679, 1681, 1683, 1685, - 1687, 1689, 1691, 1693, 1695, 1697, 1699, 1701, 1703, 1705, 1707, 1709, - 1711, 1713, 1715, 1717, 1719, 1721, 1723, 1725, 1727, 1729, 1730, 1732, - 1734, 1736, 1738, 1740, 1742, 1744, 1746, 1748, 1750, 1752, 1754, 1756, - 1758, 1760, 1762, 1764, 1766, 1768, 1770, 1772, 1774, 1776, 1778, 1780, - 1782, 1784, 1786, 1788, 1790, 1792, 1793, 1794, 1796, 1798, 1800, 1802, - 1804, 1806, 1808, 1810, 1812, 1814, 1816, 1818, 1820, 1822, 1824, 1826, - 1828, 1830, 1832, 1834, 1836, 1838, 1840, 1842, 1844, 1846, 1848, 1850, - 1852, 1854, 1856, 1858, 1860, 1862, 1864, 1866, 1868, 1870, 1872, 1874, - 1876, 1878, 1880, 1882, 1884, 1887, 1889, 1891, 1893, 1895, 1897, 1899, - 1901, 1903, 1905, 1907, 1909, 1911, 1913, 1915, 1917, 1919, 1921, 1923, - 1925, 1927, 1929, 1931, 1933, 1935, 1937, 1939, 1941, 1943, 1945, 1947, - 1949, 1951, 1953, 1955, 1957, 1959, 1961, 1963, 1965, 1967, 1969, 1971, - 1973, 1975, 1977, 1979, 1981, 1983, 1985, 1987, 1992, 1994, 1996, 1998, - 2000, 2002, 2004, 2006, 2008, 2010, 2012, 2014, 2016, 0, 3, 74, - 106, 113, 155, 194, 205, 209, 223, 224, 225, 226, 283, 284, - 285, 304, 305, 306, 307, 308, 310, 311, 331, 333, 334, 335, - 337, 338, 392, 393, 395, 397, 398, 400, 415, 500, 506, 514, - 564, 570, 615, 622, 665, 704, 713, 714, 715, 717, 743, 744, - 745, 746, 750, 751, 787, 788, 789, 790, 854, 856, 859, 938, - 953, 1056, 1066, 1068, 1110, 1167, 1203, 1216, 1235, 1294, 1296, 1314, - 1495, 1638, 1639, 1662, 1663, 1668, 1669, 1670, 1671, 1672, 1673, 1676, - 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, - 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1904, - 1905, 1986, 1987, 19, 20, 55, 62, 63, 64, 67, 77, 97, - 98, 101, 110, 126, 133, 134, 136, 137, 152, 156, 158, 164, - 165, 166, 167, 168, 169, 172, 175, 177, 189, 190, 200, 201, - 202, 203, 215, 232, 233, 300, 302, 303, 312, 313, 314, 315, - 331, 332, 333, 334, 361, 362, 363, 364, 365, 367, 409, 419, - 421, 422, 427, 436, 452, 459, 460, 467, 527, 538, 554, 636, - 655, 656, 657, 703, 740, 741, 783, 784, 785, 786, 791, 847, - 910, 936, 952, 953, 954, 955, 956, 957, 965, 967, 970, 1039, - 1040, 1059, 1060, 1061, 1062, 1086, 1134, 1200, 1201, 1202, 1203, 1204, - 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1216, 1217, - 1285, 1300, 1360, 1392, 1393, 1394, 1395, 1403, 1404, 1405, 1406, 1407, - 1423, 1460, 1524, 1525, 1614, 1615, 1700, 1701, 1702, 1703, 1704, 1705, - 1706, 1707, 12, 103, 104, 119, 152, 189, 191, 192, 265, 301, - 339, 340, 341, 351, 685, 686, 687, 756, 792, 793, 794, 942, - 943, 999, 1117, 1121, 1125, 1149, 1158, 1196, 1245, 1263, 1298, 1315, - 1333, 1338, 1414, 1560, 1561, 1580, 1581, 1708, 1709, 1710, 1711, 1712, - 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, - 1725, 7, 105, 106, 122, 125, 262, 263, 404, 838, 839, 840, - 841, 842, 932, 981, 1009, 1462, 1726, 1727, 1728, 1729, 1731, 1732, - 1733, 1734, 20, 21, 22, 23, 128, 180, 370, 372, 374, 408, - 442, 629, 630, 723, 724, 725, 752, 849, 911, 976, 1002, 1032, - 1070, 1071, 1097, 1098, 1099, 1197, 1336, 1358, 1361, 1574, 1575, 1586, - 1587, 1602, 1603, 1735, 1736, 1737, 1738, 1739, 1740, 1743, 1744, 1745, - 1746, 1833, 1834, 1912, 1913, 1930, 1931, 5, 8, 69, 70, 122, - 138, 148, 149, 155, 159, 179, 181, 351, 444, 445, 482, 498, - 540, 543, 544, 545, 561, 565, 600, 601, 619, 653, 694, 761, - 762, 763, 764, 765, 792, 793, 794, 873, 881, 895, 896, 923, - 924, 929, 970, 1031, 1101, 1117, 1124, 1128, 1165, 1173, 1175, 1182, - 1184, 1187, 1189, 1196, 1197, 1198, 1220, 1237, 1239, 1287, 1299, 1305, - 1328, 1333, 1383, 1387, 1388, 1389, 1391, 1393, 1412, 1413, 1421, 1422, - 1434, 1435, 1444, 1445, 1449, 1453, 1747, 1748, 1749, 1750, 1751, 1752, - 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, - 1920, 1921, 1932, 1933, 30, 54, 67, 71, 80, 87, 88, 94, - 99, 100, 152, 157, 169, 172, 173, 174, 175, 176, 199, 201, - 208, 209, 210, 212, 213, 217, 221, 224, 228, 233, 235, 237, - 239, 241, 243, 245, 247, 249, 250, 251, 253, 255, 257, 259, - 261, 263, 265, 268, 269, 271, 272, 273, 276, 279, 282, 285, - 286, 287, 288, 291, 297, 303, 307, 311, 315, 317, 323, 327, - 330, 334, 335, 336, 337, 338, 341, 345, 346, 350, 351, 353, - 357, 362, 364, 367, 368, 370, 373, 374, 376, 377, 378, 379, - 380, 386, 387, 388, 389, 390, 396, 397, 398, 399, 400, 412, - 420, 435, 450, 454, 524, 545, 546, 559, 560, 561, 562, 563, - 564, 565, 566, 567, 568, 569, 570, 571, 624, 652, 654, 704, - 705, 753, 762, 767, 772, 776, 786, 788, 794, 796, 800, 804, - 808, 813, 814, 815, 816, 817, 819, 823, 825, 827, 829, 830, - 831, 839, 846, 848, 849, 860, 871, 877, 878, 879, 880, 887, - 891, 892, 898, 915, 926, 927, 928, 946, 947, 948, 949, 974, - 980, 986, 995, 1006, 1007, 1011, 1019, 1029, 1030, 1037, 1049, 1054, - 1085, 1123, 1129, 1130, 1131, 1132, 1191, 1194, 1195, 1208, 1227, 1253, - 1254, 1291, 1301, 1308, 1313, 1314, 1316, 1329, 1401, 1404, 1406, 1423, - 1440, 1441, 1442, 1443, 1447, 1452, 1464, 1656, 1657, 1765, 1766, 1767, - 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, - 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1791, 1792, 1795, - 1796, 1797, 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, - 1808, 1809, 1810, 1835, 1836, 31, 32, 71, 72, 90, 184, 304, - 305, 306, 307, 342, 405, 448, 451, 452, 453, 562, 567, 744, - 983, 994, 996, 1065, 1132, 1142, 1143, 1160, 1161, 1162, 1163, 1164, - 1186, 1280, 1281, 1282, 1286, 1287, 1288, 1289, 1291, 1292, 1313, 1342, - 1346, 1357, 1371, 1372, 1401, 1402, 1451, 1497, 1811, 1812, 1813, 1814, - 1815, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1826, - 1827, 1828, 1829, 1830, 1831, 1832, 1839, 1840, 8, 25, 26, 27, - 54, 67, 80, 105, 122, 133, 156, 158, 165, 166, 206, 207, - 208, 216, 217, 219, 229, 248, 249, 308, 309, 310, 311, 463, - 485, 508, 521, 548, 613, 652, 654, 668, 683, 704, 882, 883, - 884, 885, 907, 929, 938, 961, 963, 964, 986, 1047, 1048, 1098, - 1126, 1157, 1169, 1201, 1208, 1223, 1224, 1225, 1229, 1231, 1232, 1253, - 1274, 1277, 1279, 1343, 1349, 1398, 1417, 1432, 1434, 1494, 1843, 1844, - 38, 45, 109, 112, 131, 132, 146, 159, 160, 161, 162, 163, - 169, 178, 202, 203, 204, 209, 214, 216, 217, 219, 258, 259, - 266, 267, 294, 299, 301, 302, 306, 310, 314, 319, 320, 322, - 324, 325, 326, 327, 329, 333, 337, 340, 347, 349, 350, 355, - 359, 425, 426, 441, 447, 448, 456, 511, 517, 521, 528, 536, - 590, 617, 626, 627, 636, 639, 640, 645, 650, 653, 659, 661, - 667, 668, 688, 692, 697, 701, 702, 703, 720, 724, 725, 738, - 749, 765, 770, 774, 777, 778, 779, 782, 783, 785, 786, 790, - 792, 793, 794, 798, 802, 803, 804, 805, 806, 810, 812, 817, - 821, 823, 824, 825, 826, 827, 828, 842, 843, 868, 882, 916, - 963, 964, 983, 984, 1005, 1020, 1021, 1025, 1043, 1053, 1060, 1061, - 1064, 1081, 1087, 1091, 1105, 1106, 1127, 1133, 1134, 1136, 1137, 1142, - 1144, 1174, 1175, 1176, 1179, 1180, 1182, 1183, 1184, 1185, 1187, 1188, - 1192, 1193, 1196, 1205, 1218, 1219, 1226, 1231, 1244, 1253, 1260, 1286, - 1289, 1291, 1301, 1322, 1325, 1333, 1367, 1368, 1373, 1374, 1403, 1463, - 1494, 1495, 1664, 1665, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, - 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, - 1865, 1866, 1867, 1868, 1934, 1935, 560, 561, 565, 569, 1295, 1296, - 1869, 1870, 8, 9, 10, 18, 29, 53, 60, 75, 76, 120, - 121, 134, 150, 151, 160, 164, 166, 167, 169, 175, 312, 313, - 314, 315, 339, 340, 341, 356, 357, 358, 359, 424, 437, 483, - 502, 503, 510, 512, 519, 523, 525, 548, 551, 553, 586, 594, - 595, 596, 597, 598, 599, 671, 678, 679, 680, 735, 754, 791, - 807, 808, 809, 810, 832, 833, 861, 866, 867, 879, 881, 888, - 889, 891, 895, 908, 935, 978, 979, 982, 1023, 1028, 1113, 1160, - 1177, 1178, 1180, 1195, 1211, 1249, 1250, 1307, 1332, 1370, 1376, 1382, - 1386, 1387, 1391, 1392, 1396, 1397, 1398, 1411, 1425, 1428, 1430, 1431, - 1456, 1457, 1496, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1890, - 1891, 1, 2, 4, 6, 13, 14, 22, 25, 26, 27, 33, - 34, 35, 41, 42, 50, 54, 57, 59, 61, 68, 82, 85, - 89, 92, 93, 103, 111, 114, 115, 116, 117, 119, 123, 124, - 127, 129, 136, 156, 167, 168, 189, 190, 191, 192, 229, 230, - 238, 239, 240, 241, 252, 253, 270, 321, 322, 323, 339, 340, - 341, 343, 351, 403, 410, 412, 413, 414, 416, 429, 431, 451, - 453, 473, 477, 478, 479, 481, 484, 486, 487, 495, 513, 537, - 539, 547, 557, 558, 576, 577, 578, 587, 588, 589, 590, 591, - 592, 594, 595, 602, 603, 604, 605, 606, 610, 623, 640, 660, - 661, 662, 665, 666, 668, 670, 672, 674, 677, 685, 701, 709, - 710, 722, 726, 729, 754, 755, 756, 757, 758, 759, 760, 795, - 796, 797, 798, 799, 800, 801, 802, 825, 826, 829, 848, 852, - 860, 875, 878, 888, 893, 896, 900, 904, 905, 906, 907, 909, - 913, 914, 916, 917, 919, 929, 933, 947, 948, 959, 962, 968, - 969, 975, 977, 982, 985, 986, 987, 988, 990, 991, 994, 1029, - 1031, 1033, 1040, 1041, 1057, 1073, 1074, 1075, 1088, 1092, 1104, 1107, - 1108, 1109, 1135, 1142, 1143, 1144, 1145, 1178, 1181, 1214, 1218, 1222, - 1223, 1225, 1226, 1230, 1240, 1241, 1246, 1249, 1251, 1260, 1264, 1275, - 1278, 1279, 1282, 1292, 1311, 1312, 1313, 1315, 1324, 1331, 1335, 1337, - 1338, 1354, 1355, 1363, 1369, 1380, 1381, 1403, 1404, 1405, 1407, 1412, - 1413, 1414, 1419, 1430, 1431, 1432, 1433, 1436, 1437, 1438, 1439, 1440, - 1441, 1442, 1443, 1444, 1445, 1446, 1448, 1449, 1454, 1458, 1636, 1637, - 1837, 1838, 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1892, - 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1906, - 1907, 1908, 1909, 1914, 1915, 1926, 1927, 1938, 1939, 1940, 1941, 1942, - 1943, 1944, 1945, 1948, 1949, 1989, 8, 25, 26, 27, 47, 51, - 65, 66, 95, 96, 132, 139, 141, 143, 145, 156, 182, 211, - 212, 213, 214, 242, 243, 246, 247, 265, 300, 302, 303, 361, - 362, 417, 443, 480, 483, 490, 497, 520, 533, 534, 535, 536, - 542, 550, 584, 585, 598, 599, 618, 631, 663, 708, 717, 719, - 727, 733, 737, 822, 827, 828, 834, 835, 836, 837, 853, 862, - 865, 872, 874, 885, 886, 890, 897, 899, 923, 924, 930, 951, - 978, 979, 1006, 1007, 1008, 1023, 1024, 1027, 1034, 1035, 1063, 1084, - 1089, 1090, 1108, 1115, 1125, 1126, 1138, 1140, 1141, 1177, 1210, 1234, - 1304, 1350, 1351, 1358, 1371, 1372, 1373, 1374, 1396, 1409, 1418, 1430, - 1431, 1455, 1494, 1590, 1591, 1666, 1667, 1924, 1925, 1950, 1951, 1952, - 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, - 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, - 1977, 15, 16, 36, 132, 161, 163, 432, 468, 469, 611, 612, - 752, 753, 938, 939, 940, 1077, 1078, 1137, 1140, 1160, 1199, 1255, - 1256, 1257, 1258, 1259, 1266, 1267, 1268, 1269, 1290, 1309, 1323, 1344, - 1377, 1380, 1384, 1386, 1389, 1390, 1394, 1497, 1980, 1981, 1982, 1983, - 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 91, 154, 170, 264, - 277, 278, 279, 734, 855, 859, 923, 945, 1015, 1018, 1238, 1254, - 1261, 1366, 1564, 1565, 1936, 1937, 1978, 1979, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 17, 27, 29, 30, 39, 43, 48, 54, - 67, 75, 95, 97, 101, 152, 167, 169, 171, 175, 177, 197, - 200, 202, 206, 209, 210, 211, 212, 213, 214, 215, 216, 220, - 221, 222, 223, 227, 232, 233, 234, 236, 238, 240, 242, 244, - 245, 246, 248, 249, 250, 252, 254, 256, 258, 260, 262, 264, - 271, 274, 277, 280, 283, 289, 293, 294, 296, 300, 304, 308, - 309, 312, 316, 321, 324, 325, 328, 331, 335, 339, 347, 349, - 350, 352, 353, 354, 355, 356, 361, 363, 364, 365, 366, 367, - 370, 371, 372, 376, 381, 382, 383, 384, 385, 391, 392, 393, - 394, 395, 402, 419, 421, 422, 465, 478, 493, 494, 507, 552, - 553, 558, 559, 560, 561, 562, 564, 566, 568, 570, 584, 588, - 589, 591, 592, 594, 595, 596, 600, 602, 607, 621, 646, 709, - 715, 716, 720, 724, 726, 754, 761, 762, 763, 765, 766, 767, - 768, 769, 770, 771, 775, 777, 783, 787, 792, 795, 799, 803, - 804, 805, 806, 807, 811, 814, 818, 838, 850, 926, 934, 940, - 953, 971, 994, 995, 998, 1017, 1049, 1058, 1062, 1091, 1105, 1118, - 1120, 1131, 1132, 1136, 1140, 1141, 1148, 1152, 1164, 1196, 1197, 1224, - 1230, 1231, 1262, 1289, 1302, 1308, 1314, 1315, 1320, 1321, 1330, 1393, - 1420, 1424, 1426, 1436, 1439, 1441, 1443, 1445, 1489, 1490, 1491, 1879, - 1880, 1990, 2007, 2008, 1276, 1406, 1741, 1742, 24, 155, 1051, 1202, - 1228, 1789, 1790, 2011, 2012, 87, 88, 280, 281, 282, 499, 579, - 1318, 1348, 1910, 1911, 2013, 2014, 2015, 2016 }; - -struct ReplacementIndexStruct { - utf16char ch; - medium count; -}; - -const checksum ReplacementChecksums[] = { - - 0xAE1DAB16U, 0x8F27A2AU, 0x465496D5U, 0x892E9135U, 0xD621DD31U, 0x40D5B583U, 0x23598B8CU, 0x174C4A14U, 0x9739B1DAU, 0xF448853DU, 0xF3DF7DF2U, 0x15D5108FU, - 0xE8A0D4E8U, 0x8FBCAF62U, 0x95F9E2A9U, 0x47CEA738U, 0x839E1EBCU, 0xA58AFD2AU, 0xAAA850BDU, 0xBBEE1755U, 0x4F9A8CDDU, 0x77C2915FU, 0x42B9AA72U, 0xABB65511U, - 0x984E9DE9U, 0xDEA4DF8BU, 0x11744AD7U, 0x229620B8U, 0x19FC0474U, 0x498A1E2EU, 0xEB73F061U, 0xCF4EB7B4U, 0x5E990F1U, 0xB6610B6U, 0xA23C27B2U, 0x9F57820DU, - 0xCAEFB5CCU, 0x868C5775U, 0x36F0B13EU, 0xC2104FC3U, 0x635ED438U, 0xFE76A6BFU, 0xAF98DEFEU, 0xC4A1CE0BU, 0x24A144DU, 0xA07F4113U, 0xA1B56E69U, 0x7AC6D4C1U, - 0xA6737D27U, 0xB74B407AU, 0xF3A0B08AU, 0x3841C7E7U, 0x7BD9C74BU, 0x57960B20U, 0xC9542F16U, 0x488EB822U, 0xA1CE4738U, 0x65284ADEU, 0x3CAC3D83U, 0xBBB37EE8U, - 0xBB721077U, 0x754CB19FU, 0xDD058F8EU, 0x33167FFDU, 0xC7DA2CAAU, 0x50A359D4U, 0x9E85659AU, 0x448DCA70U, 0x645EA110U, 0xA6832DF5U, 0x7F7A32B5U, 0xA3016C3FU, - 0x47DE3B8DU, 0x347522B4U, 0x349608E1U, 0x8A111CA0U, 0x16625752U, 0x3DD97630U, 0x283C812CU, 0x62FCCC72U, 0x2A8707F7U, 0x4CAAF872U, 0x2FB36C45U, 0xD5827C60U, - 0xE79C25ACU, 0xC53F5EC8U, 0x7DE5251FU, 0x3CA5EFD1U, 0xBEEDA352U, 0x10FF4E8EU, 0x5A37598EU, 0x7CC72338U, 0x92500B16U, 0xD5E5CEF4U, 0xF9ABE6FBU, 0xEF0313FDU, - 0x5D682C8AU, 0xD1D48498U, 0x4DA7CF6AU, 0x3DDDF327U, 0xC9016AA9U, 0x26FBBFD8U, 0xF0D58D6U, 0x2B17F5C6U, 0xA903A376U, 0xCA823961U, 0x829E9619U, 0xF3DA224AU, - 0xDDF16CC9U, 0x8F456FB4U, 0xCC6B224AU, 0x75B42ABFU, 0xCD7DECEFU, 0x73290221U, 0xDF8E5CD8U, 0x1D568D7CU, 0x7F2FCD63U, 0x539DB28DU, 0xB9BB5841U, 0x88EB5D8DU, - 0x30B6C9CCU, 0xEA5F5485U, 0xF282B417U, 0x46508060U, 0x8C9D5E3EU, 0xBC04162BU, 0xFA329E5DU, 0xC885E4CCU, 0xDCBF9DCAU, 0x4715B337U, 0x2FDC1366U, 0x3E3BBA50U, - 0xC99E60F3U, 0x9F2BF2CU, 0x73F18BAU, 0xB561B097U, 0x9000A7E8U, 0xEE613496U, 0xCAD661B5U, 0xADEFBC1EU, 0x717A2494U, 0x10ED817CU, 0xD5497538U, 0xC264618U, - 0xA723C789U, 0x365CA2E0U, 0xC4AE628U, 0xDAD44170U, 0x69B2A699U, 0xFA94A82BU, 0x9500E45FU, 0x641EDBEU, 0xBBC0F4D2U, 0xE21AA1F5U, 0x7FDEA451U, 0xF6B2D68U, - 0x5F8E4A17U, 0x9682906DU, 0x41B84148U, 0x6659DDC9U, 0xBA4A5BADU, 0x14B31920U, 0x1360E730U, 0x590C5708U, 0xF019A4AAU, 0x5089CA96U, 0xF0B0E775U, 0xFDD90E49U, - 0x1BF1824BU, 0xE13025FCU, 0xEF137B9DU, 0x7935115AU, 0x718BD26AU, 0xF09E5811U, 0x7BA332A6U, 0xA7615393U, 0x73FAF11U, 0x55936B7CU, 0x6DC1E6EFU, 0x73A15F22U, - 0xB2FDF279U, 0xD6B59BAEU, 0x27ABA3E6U, 0x2367BEC9U, 0xE7C938F9U, 0x560FEC09U, 0x12C5119U, 0x5001267U, 0x5365E024U, 0x85080CCDU, 0xA3B79EC5U, 0x960F8445U, - 0xF895CC46U, 0x3A3AF35CU, 0x6BE7869BU, 0x14D9D708U, 0xC4A951A1U, 0xAE72E7B2U, 0x99D3DAE2U, 0xEA4D4D5BU, 0x4282D2C1U, 0x33ECB6EBU, 0x4415ADC3U, 0xC78A4A6EU, - 0xD72386B8U, 0xF3E3048EU, 0x1B8D6392U, 0x2C2C5EC2U, 0xA58D62B2U, 0x147A0701U, 0xE63DAAF0U, 0x8DDD9273U, 0xF5A4B231U, 0x9FF25F7FU, 0xDDEA0DB3U, 0x194D812DU, - 0x5CEB285U, 0x7DB792C7U, 0x750B1EB5U, 0x57AE509CU, 0xC8F777C2U, 0xBCD1360BU, 0x632D2CA8U, 0xBC462336U, 0x602E733DU, 0x2194100DU, 0x2FB69E71U, 0x58D9C98U, - 0xD3907616U, 0x40B025B8U, 0x8638D05AU, 0xE4433DD5U, 0xB399E080U, 0xEB05158DU, 0x21E41D29U, 0xA97B497EU, 0x7DF9E406U, 0x2B2DDA74U, 0xBA0D8072U, 0x23F15693U, - 0x69AB4478U, 0xE134102FU, 0x8522D229U, 0x1CDE04C8U, 0x1021B3B1U, 0x685893F3U, 0x548FAB48U, 0x3926C75EU, 0xCD7FFCC1U, 0x95E309CCU, 0x70DCC40DU, 0x5809E8BDU, - 0xC3D9F1CBU, 0x15C41B45U, 0x461F4802U, 0xCE801C55U, 0x39156F0DU, 0x3AE08EU, 0x8D001528U, 0x51684523U, 0x85F53FF7U, 0x53E8D579U, 0x81AED8F1U, 0x5DC688FAU, - 0x752D5FFCU, 0xA15A7026U, 0xA3F2B218U, 0x84AC213BU, 0x88B16330U, 0x43104043U, 0x364A68E3U, 0x7A3633D9U, 0x8133D145U, 0x2CE20DABU, 0x551CC37BU, 0x40826DDFU, - 0x72073AE0U, 0xCD0A52A0U, 0x7BF57C24U, 0x54F68441U, 0x311B04E2U, 0x3BF381E1U, 0xB98450B5U, 0x9365254FU, 0x959808U, 0x4F0D7544U, 0x70311041U, 0x51FFC7D2U, - 0xE66C3289U, 0x7830DA3CU, 0xEBC0677BU, 0xA4588A37U, 0x2CD52C5U, 0x8C136450U, 0x1A32A58U, 0xBDC4CE8BU, 0xBE1AD3FCU, 0x368587ABU, 0x24762692U, 0xDB6866FU, - 0xDBFE03C1U, 0x32805E0BU, 0xBDB344CU, 0xB6576FD7U, 0xCE602BD5U, 0xD9A1C5D8U, 0x1E451C58U, 0xA3C947C3U, 0x8A5E6F27U, 0xA76375AEU, 0x5A7B58AAU, 0xE7F70331U, - 0x9E18A785U, 0x5E2B2BB3U, 0x4E3D9008U, 0xF3B1CB93U, 0xFE1D8CFCU, 0xC732037FU, 0xE5F2028FU, 0x922F93ECU, 0x3B1CD1U, 0x489442A4U, 0xE3308006U, 0x9E89A82AU, - 0x88E25FD7U, 0xBA9183F8U, 0xC98F90D9U, 0x111E8936U, 0xAB056753U, 0x3E5DD491U, 0x83D04BE3U, 0x7419BEF7U, 0xDEC343D9U, 0xDF53B75BU, 0x8D38CBC1U, 0x9E65B31DU, - 0x49E9647BU, 0x487990F9U, 0x8586DA3AU, 0x6AEC2F1DU, 0x3ADBB0DDU, 0x12950F5FU, 0x65E071DDU, 0x141AF304U, 0xE27A2FD3U, 0xCF0F75B3U, 0x506B7DCCU, 0x7729EE20U, - 0x83A892CEU, 0x1724B686U, 0x1D5443E6U, 0x8D4BA4A5U, 0xF994FF2AU, 0x606829CBU, 0x4F6BD1AEU, 0xB8F93024U, 0xF6C1C490U, 0x6F3D1271U, 0xE8119B5BU, 0xB7AC0B9EU, - 0xA93D2434U, 0x9CBC7723U, 0x5384167CU, 0x6CC02C32U, 0xE3AEFA3BU, 0x96ACCCB8U, 0x93EDFEB5U, 0xB455ABEU, 0xE0468B3U, 0xD2638E77U, 0x85F33C85U, 0x53C0FE60U, - 0x40A0CF69U, 0xCE296866U, 0xDD49596FU, 0x89ED9A7CU, 0xB2168218U, 0x2A16FE9FU, 0xC6158813U, 0x96D819A0U, 0xF1CB7821U, 0xF0B3234EU, 0xC76DD37CU, 0xF6999932U, - 0xA6540881U, 0xC1476900U, 0xBF852F50U, 0x885BDF62U, 0x2B6EA5F0U, 0x7BA33443U, 0x1CB055C2U, 0x406B945CU, 0x21FBAB96U, 0x25A9EEF7U, 0x29D0280DU, 0xDCD83354U, - 0x95D847CAU, 0x193AD0D7U, 0x65149603U, 0x875F1D51U, 0xF2D6AE5EU, 0xB48C2023U, 0x9E89C614U, 0x71040E80U, 0x2F6DB3B1U, 0x4FBD2D4DU, 0x382CE581U, 0x8682E54AU, - 0xC6CE3C16U, 0xD0CDB310U, 0xC097D2DCU, 0x61442A6DU, 0x803FC77EU, 0xBFABF3D6U, 0xBB1662DBU, 0x639138F2U, 0xA01171D6U, 0xB70E7066U, 0x4F4D5F1AU, 0x2AB83F69U, - 0x1BED886U, 0x125067C1U, 0xF2BDF6E8U, 0xE496DD92U, 0x97589D6U, 0x1D17DA74U, 0xD6E2180AU, 0x96AAE39BU, 0x9E79ED3CU, 0xA1E56DA4U, 0xFE814EF2U, 0x55E387B6U, - 0x38A8B47FU, 0xB200788AU, 0xC063E892U, 0x7E1CEC20U, 0x62C476EDU, 0xF83527BEU, 0xCB64655U, 0xF85F383EU, 0xEFE50809U, 0xA32D4B9DU, 0x14325108U, 0xC46CF3FCU, - 0x8646A4A2U, 0x24231E6EU, 0xE8DC260CU, 0x9CA8A446U, 0x4A5517EBU, 0xCDBD569CU, 0xB4C0F066U, 0xF1C615D9U, 0x14C9784FU, 0xC35ACFA4U, 0xA1F99F39U, 0xDB5D327U, - 0x16208387U, 0x487A6530U, 0x8B83FB15U, 0x47AA297BU, 0xA6838556U, 0xFE99F07BU, 0xAAC72C75U, 0xD7EE632BU, 0xCC9E80CU, 0xDC478D7BU, 0x7E2514C1U, 0xEC7A9229U, - 0x7EFF1AE2U, 0xDA58F332U, 0x7FFD9AE0U, 0xD62250F0U, 0x36FF2FD3U, 0x5343E85AU, 0x7DE1A231U, 0x73105D3AU, 0x8694822BU, 0x9EA10A8CU, 0x454632DU, 0xBDBA49B8U, - 0x2AFBA286U, 0x638306DBU, 0xD0EE5B94U, 0xFA67DEA8U, 0x54739A2DU, 0xED50973AU, 0xB8A32501U, 0x96A4B4A6U, 0x26400C9AU, 0x11CDDFF8U, 0x532A2EC9U, 0xC01BA957U, - 0x38F60BF1U, 0x709E7D5BU, 0xD63F1DE9U, 0xAA9B52FCU, 0xE5D7E3BU, 0x3D792D12U, 0xF7AF95C2U, 0x23FE045AU, 0xA348A4DCU, 0x3EE734ECU, 0xA157B457U, 0x19AD5091U, - 0x2A0F1115U, 0x8E3D8B1FU, 0xF7640767U, 0x77418D32U, 0x3AF7B59U, 0xDF7CC644U, 0x4F107817U, 0xD65CF7B3U, 0x5D63C132U, 0xB71ABEBBU, 0xBD678059U, 0x796A3A58U, - 0x3E76DFA6U, 0x7B931373U, 0x4C62A6D8U, 0x57F03940U, 0xB2A038EEU, 0x5FDF9A23U, 0xA0263983U, 0x7E882A01U, 0x9DFC1084U, 0x7072D927U, 0xD8FDE69FU, 0x96F9AB93U, - 0xE0E7157BU, 0x58F4B5B9U, 0x57E98EE9U, 0x2B7F17D5U, 0xBF5D536FU, 0x19B4B8DDU, 0x670EE546U, 0x759F5B56U, 0x521D3385U, 0x54FF4F92U, 0x2D9CBF6AU, 0xD0F0ACFBU, - 0x41F4137CU, 0x3ECD73DCU, 0xD98F534U, 0xAFC9093DU, 0x11EB63E2U, 0x69341E0FU, 0x45C58EDBU, 0x8ADA0754U, 0xDFF71D29U, 0xBACC8D3CU, 0x795F863CU, 0xDA5B599FU, - 0x756A6CFCU, 0x492FD69AU, 0x2AC4EC3FU, 0xE8B85ECU, 0x6E924FB3U, 0x29F01476U, 0x16F0C1B5U, 0xFBB8B0D5U, 0x6F47CA15U, 0xE7DF0A66U, 0x752BEE8CU, 0xC46345A2U, - 0xA8C65A6U, 0x1A0CBBA0U, 0xC6B953FBU, 0xF469483CU, 0xE8DBA058U, 0x55E1E9EDU, 0x220DF006U, 0x93AA672CU, 0xF77C2327U, 0x4D7BA0B7U, 0xC9C38BCEU, 0xA4B0DB5U, - 0x9798D36AU, 0x210C73B2U, 0x2D884E0BU, 0x2CF555C5U, 0x559C4DCU, 0x4C553278U, 0x2594AF17U, 0xF92DA22FU, 0x46D9B7D7U, 0x3BAA86EEU, 0x8D972880U, 0x2FEF17FCU, - 0xF479A777U, 0x13EC6D08U, 0x507AFB0FU, 0x3DBD6B73U, 0xD3DAA910U, 0xFF842DA6U, 0x56D07CCDU, 0x76F544DDU, 0xAB51C2E8U, 0xFE925847U, 0x1266FB35U, 0x9951A06U, - 0xD3FF1DF6U, 0x51D302CEU, 0x66FB4072U, 0x3338DADDU, 0xE3411213U, 0x67610EA3U, 0x8FD669ECU, 0xA28A9DA9U, 0x170B62DFU, 0x520CEC4CU, 0x4A7596BEU, 0x732E55FDU, - 0x1BD7ADCCU, 0x6DBF878BU, 0xF0257FF7U, 0x36069DA1U, 0x17D3C5EEU, 0xCCBE59DCU, 0xF17154B8U, 0xFED05FF9U, 0x70F66BAAU, 0x668A255FU, 0x5E1E3F24U, 0xC6AA9101U, - 0xA9DF1308U, 0x1CE8989FU, 0xF2C4756CU, 0x606CB509U, 0xECE1CA0CU, 0x2394B2A6U, 0x16C80794U, 0xAE1222A3U, 0x8CB97B86U, 0x2A219240U, 0xB20CD4A6U, 0x4CACE737U, - 0xB911D42CU, 0xE6AE7EDU, 0x8EC4A97AU, 0x6C05079AU, 0x2A97030AU, 0x66821408U, 0x54C18CD7U, 0x66B85367U, 0x5C604485U, 0xACBF9192U, 0x3A9FAE2U, 0x3CD0C352U, - 0x92F9FA79U, 0xC17824C7U, 0x538FB0D3U, 0xB803EAFU, 0x3AD85536U, 0x41D70FEBU, 0x8F21EB7FU, 0xD768A2BEU, 0xDDABF113U, 0xD17178C2U, 0x56378FD7U, 0x90F8A446U, - 0xF445416FU, 0xBED2C72U, 0x93D47BEAU, 0xAEA4D915U, 0xF5601C83U, 0x317F54CBU, 0x10AA0C84U, 0xD907DC46U, 0xE342A78AU, 0xF2047AF4U, 0xBD65E28U, 0xB389E207U, - 0x3BD7614EU, 0x7CF71C84U, 0x4E118784U, 0x48C31E39U, 0x4112EFC5U, 0x948FC967U, 0xB0B24B2CU, 0x1FE25283U, 0x629F7C2DU, 0xC08B5199U, 0x2F114A8EU, 0x57EF2916U, - 0x2B576B96U, 0xCE051BEAU, 0xEC16C919U, 0xBFF3A0CBU, 0x36A16CCDU, 0xE838218DU, 0xEE352A21U, 0xE38E5B7FU, 0x3A8BB7DFU, 0x1F0ECE93U, 0x5385D9B7U, 0xAC29F8F4U, - 0x575DB2ADU, 0xACBF183FU, 0x567EEE14U, 0xE8AD89DBU, 0x1E97978CU, 0xA9209129U, 0x859AA93BU, 0xC97EF510U, 0xE3E9CEBBU, 0xD8CE4D00U, 0xBA789F5AU, 0xF87F77BBU, - 0x4A4B351BU, 0xB62AC6D9U, 0xCF96A065U, 0x74744A1FU, 0xD93F0955U, 0x4F6722B3U, 0xFDCD24EEU, 0xE6A9F921U, 0x166CC0D6U, 0xB92186A0U, 0x29211071U, 0xD978BCDDU, - 0xB14992FCU, 0x19854E77U, 0x3FE60A5U, 0x58FC1E58U, 0x10475664U, 0xDAFCA3E6U, 0x5BFB6CDBU, 0x19ABDD0BU, 0xD22AD479U, 0xFDCAE1D1U, 0x82D2915DU, 0xE3DFF22AU, - 0x130FDF55U, 0xD3B59A0FU, 0xD5F60290U, 0x6CCD0385U, 0x58438A99U, 0xDE26F199U, 0x3E40DEB9U, 0x706B5E46U, 0xD0A47AE4U, 0x3AA9B57AU, 0x8504AFF7U, 0x5E28BCA3U, - 0x3B8DBFD5U, 0x28CAFF29U, 0xFBE90C93U, 0xEAD04C12U, 0xCB24B726U, 0xF6C65A18U, 0x2A34D380U, 0x62E270A6U, 0x6E546C36U, 0x31006A54U, 0x20B4D99EU, 0xD625B3A1U, - 0x29503BFAU, 0x5F4FF005U, 0xBF30759DU, 0xA18BD87CU, 0xA2D5259U, 0x34D4508EU, 0xCDF525B8U, 0xD28710F0U, 0xB2863FDDU, 0x9F9E5922U, 0x70B1EF12U, 0xA6AC059CU, - 0xBBEBD881U, 0x472BCFE6U, 0xE62890CU, 0xA80B1464U, 0xC5A27872U, 0x3BEA65ABU, 0xA8392847U, 0x279F356AU, 0x7F03C067U, 0x7D764E6CU, 0xA208B04BU, 0x110FA646U, - 0xE1642FD1U, 0x12D001U, 0x16F6CE5BU, 0xFC591AA1U, 0x4B671A82U, 0x8737FAAAU, 0x552AF746U, 0x21D61F84U, 0xB82AC965U, 0x3B3F074FU, 0x60BBD08AU, 0x9AD6EC38U, - 0x3A123F0CU, 0x79EC7FD1U, 0xF5966D91U, 0x426CB588U, 0xDB906369U, 0x9B6900FEU, 0x3017A86U, 0xEEDF7292U, 0xC60A5E22U, 0x19DDB430U, 0x7B87C150U, 0x49FFE8C2U, - 0x875E3C9U, 0xEFB8D540U, 0xBB551FEU, 0x485E57B1U, 0x7171D832U, 0xAA37823U, 0xB678C79CU, 0x8D8B6024U, 0x18D3D3E6U, 0xA55E4C94U, 0x92D028AU, 0xF00C77BCU, - 0x7049BC1CU, 0xA2670B26U, 0x6CB5177AU, 0xE42A432DU, 0xA711D2F5U, 0xDF1942E9U, 0x8927E59AU, 0x3A72453FU, 0x464E138BU, 0xC1B90DE8U, 0x9EAD10B7U, 0x1E4CB9E4U, - 0x2CF77C5BU, 0x8BEAF43BU, 0xEA39A146U, 0x14F38D7U, 0x7116D68AU, 0xBB545FEBU, 0x81B4AA98U, 0xD01859CAU, 0xDF71061U, 0x479A64C4U, 0x71B1C5DBU, 0x5964E96BU, - 0xF1560394U, 0xF28823A4U, 0xE4E97619U, 0x1295A088U, 0x7049FDAU, 0xE592D573U, 0x3535BE69U, 0x1619B844U, 0xD727F3DEU, 0x13232E2BU, 0x51338796U, 0x4B84738U, - 0xF482392DU, 0xAB40F973U, 0x9E36BDD6U, 0x3845F022U, 0xA2F40E8BU, 0xC698595DU, 0x87D8352DU, 0xEEB9CC7FU, 0xC644164DU, 0x4CDBDEAFU, 0xE2DE7491U, 0x31F7EB3DU, - 0x9599038U, 0x9D918DA1U, 0x65E89B01U, 0x886E82A6U, 0xFFFE534AU, 0xE151673CU, 0x2026F087U, 0x6D682B4EU, 0xDEF444BDU, 0xF1416D33U, 0xBA2D6D03U, 0xEEFF589AU, - 0xD41F5106U, 0xDE088E4CU, 0x999A79F6U, 0xE8AEA3D0U, 0xE93324AEU, 0xAD49F7U, 0x5FE7A23DU, 0xC1728CACU, 0x60B9C80EU, 0xE3F2AFEBU, 0x95F0722U, 0xA039D72EU, - 0xD6262CCFU, 0x76C373F8U, 0xB040A838U, 0xCF9DD85FU, 0x89EE399BU, 0x4280BC28U, 0xFC69FC63U, 0x3D05B634U, 0x49B5C357U, 0x6E56C308U, 0x1754FB6U, 0xBB51865DU, - 0x8715888CU, 0xAD2738D0U, 0xAE6891D3U, 0x3D480692U, 0xB7351D91U, 0x4537E08EU, 0x2E2BD03U, 0x7F89BA71U, 0x964B44CEU, 0x24B54B9U, 0x1D1552DU, 0x7686B89FU, - 0xDC21E010U, 0xC76B9756U, 0x9E6B1EDU, 0x51599457U, 0x9A6FBFC1U, 0xBBC871A0U, 0xC3FAEA7CU, 0xFAD6BDE8U, 0x1D426A4FU, 0x23516287U, 0x54E93201U, 0x3D14944U, - 0x20F91670U, 0x7D2AAB9U, 0x7A1502CDU, 0x5A8B6DF7U, 0x2D7BE547U, 0xC7686672U, 0x6D9E58AFU, 0xEB0B3F26U, 0x92FD1CE6U, 0x10438777U, 0xB9A6DF98U, 0x8F21D6D6U, - 0xA5DC42D9U, 0x6101B9D7U, 0xAA8A7A11U, 0x97ABDF97U, 0xF820B371U, 0x12E7060FU, 0x7898B7E6U, 0xECC6032BU, 0xCEFB7A8CU, 0x2F1E6611U, 0x9CD6CAB9U, 0x3BC2405BU, - 0x16974E59U, 0xB1168D81U, 0x399695C7U, 0x116814AFU, 0xE6BF9B30U, 0xDAAEEB22U, 0x9AE019F0U, 0xE91C586BU, 0x2C799952U, 0xE5A1E7CEU, 0x264CB5CEU, 0x9C43107EU, - 0xA1A8D07EU, 0x405A2DB6U, 0x804346D2U, 0xBE708250U, 0x67B107D0U, 0xC596A1FBU, 0xB7E8AC33U, 0x829235A2U, 0xA0D9823DU, 0x46D24122U, 0x2B9EA93U, 0xA1C073C6U, - 0xC4EAFBEU, 0x9CBCA0CEU, 0x87CB523EU, 0x93F53F24U, 0x30F100CBU, 0xC76E5C71U, 0x588FA645U, 0xC9B298CDU, 0xC2BC200U, 0xC5B21FE9U, 0xEEEE5BF8U, 0xBB647D0EU, - 0xE0A73F06U, 0xC685C32DU, 0x1C5C9B9BU, 0x2A44CEAU, 0x9534296EU, 0x5A5EC350U, 0xB3780B29U, 0xE8A4B00U, 0xF8327784U, 0x996FC0C8U, 0xD67C8539U, 0x621659DDU, - 0x1FD6996U, 0xB398D6D2U, 0xBBEC03D6U, 0x3F8504F6U, 0x9FA1B8CEU, 0x83ADB8A5U, 0x9004789FU, 0x99ED15F4U, 0x6883E2DU, 0x3C75FFACU, 0xD2391F74U, 0x66EE73F1U, - 0x8FA89A21U, 0x801A7503U, 0x522E1784U, 0x36392E2EU, 0x19DF8128U, 0x6EA25305U, 0x846C8437U, 0x4EE0BEACU, 0xF690FDC5U, 0xF6832E1EU, 0xA48C9379U, 0x5F8921B0U, - 0xFE3D1F9CU, 0x4B6BADFEU, 0x2DDBBD52U, 0xFA227036U, 0xFE4FE03AU, 0xD4BD8877U, 0xC255594EU, 0x8A61FE32U, 0x63B85E32U, 0xC24637DFU, 0x39229F39U, 0xF9B405A4U, - 0x3EBF9329U, 0xF28B6E98U, 0x81DAA8C9U, 0x55ACEF34U, 0x296DE97FU, 0x5953C3AU, 0x7268DC76U, 0x49C2BAAAU, 0x1FD82E79U, 0xE54C1803U, 0x9CD98442U, 0x4C57DE89U, - 0x7FD97D63U, 0x5B3CB6F5U, 0x67B3B2E4U, 0x3EC0ABB7U, 0xEE3200C0U, 0x3FA3D082U, 0x4D0F7C4AU, 0x892D309CU, 0x56B3DD2CU, 0xEB5F7612U, 0x2EE42882U, 0xCF07E495U, - 0xF2A9BC6BU, 0x9DA909A4U, 0x937B3A8U, 0x363217CFU, 0x9AED0006U, 0x60362015U, 0x5226B280U, 0x8524AEA3U, 0xFBC8F58DU, 0x7B172312U, 0x9CCC34DU, 0xA8AE6F61U, - 0xE3CA111EU, 0x59FE8325U, 0x6EC95B2U, 0xF676DCD9U, 0x9A250AE3U, 0x99E585E7U, 0xA62C89BU, 0xC631DEF4U, 0x58BC30C1U, 0x470412E1U, 0xC05117F0U, 0xA51D983CU, - 0x1E629C01U, 0x541C0E33U, 0xEB80059DU, 0x129D07E0U, 0x48EDAAD6U, 0x8397F485U, 0x1857F8F0U, 0x97497FE1U, 0xA8AEC1F6U, 0xC8027F76U, 0x736E96A8U, 0x1A578E1AU, - 0x6B9FD701U, 0x8B4734B7U, 0x7102220U, 0x13FE645BU, 0xE25D1A59U, 0x7A7D69ECU, 0x9295838AU, 0x6761FB08U, 0x493105F6U, 0x13BF90E3U, 0x6691E578U, 0xC741FD85U, - 0x62E01643U, 0xE782CAB0U, 0x3223B5F4U, 0xB36E1464U, 0x2C04AA45U, 0x9260D4CBU, 0x660DB966U, 0x41F2BCF7U, 0xF17D8432U, 0x17C405A6U, 0x87274585U, 0x537E9E9EU, - 0x7B344BCU, 0x1E023531U, 0xDD6783A8U, 0xFA37738DU, 0xD7D7F72CU, 0xEAADB26BU, 0x5B511B45U, 0x240A687DU, 0x44E66B55U, 0xD0808C97U, 0xF31BFF35U, 0x9EE5345CU, - 0x258906C2U, 0x9860CC4AU, 0xB9CCB14FU, 0x5580726EU, 0x26B182EU, 0x4F6C5C89U, 0x5D26775DU, 0xF0CA22ADU, 0x2DD7CAC5U, 0xD0EDAF27U, 0x8C09D6DU, 0xDCFB88F2U, - 0x71C63BCFU, 0xAEC8C854U, 0xC3ADC8F6U, 0xE93C7B65U, 0xC698C893U, 0x8E574092U, 0x92FF3CB6U, 0xF8648ABAU, 0x3F4D318AU, 0xB5BC2991U, 0x5E05BD9DU, 0xB09A78A0U, - 0x15AB67C0U, 0x3FADF7CEU, 0x2927A3FDU, 0x445BA5DBU, 0xFA3008B2U, 0x2891DB6BU, 0xDBB845FU, 0x573B85ECU, 0x18F54327U, 0x74F4356BU, 0x95971E70U, 0x4470A211U, - 0xB905173DU, 0x414D94A9U, 0xE929B3ADU, 0xAE3B8A7AU, 0xFF18EB1U, 0xEE383B0CU, 0x7B04D607U, 0x693E6DA4U, 0xC3FB577EU, 0x7AC48735U, 0x1A99C4ADU, 0x45B0C657U, - 0x5CC05A5U, 0xE24AE587U, 0x884FA08EU, 0x5BCE0610U, 0xCCBADA00U, 0xEEBE62E2U, 0x1BED96D4U, 0xFF9731C4U, 0x5644B2A0U, 0x9119ABCAU, 0x28FC1FE4U, 0x983CF251U, - 0xF92F5A3BU, 0xDC9DC061U, 0x5B150730U, 0xCB5F1CBDU, 0x5966470CU, 0xE5C92630U, 0x974502D1U, 0x2047F98CU, 0x444D6B88U, 0xFB8235EU, 0x359D6CU, 0xC34153C2U, - 0x2A95D777U, 0xCE439251U, 0x5B6E4E6FU, 0xB408F38U, 0x2423E46EU, 0x4C85DCE9U, 0xBBEEC84BU, 0xE9D46305U, 0x30187C97U, 0x181599U, 0xF4F90026U, 0x952F111CU, - 0x5B9D9750U, 0x624304BEU, 0xCE566F2EU, 0xF5B066E3U, 0xC84AEDC4U, 0x26984E70U, 0xD637245CU, 0xAEADB1U, 0x7F65D377U, 0xDD7410C6U, 0xE156A6E8U, 0x2BDB808BU, - 0x3107D6E5U, 0xA654151FU, 0x5DBD1349U, 0x29676B1CU, 0xD9B9A12BU, 0x559571C7U, 0x17D9B1EFU, 0x8EBB69EAU, 0x6E834FD7U, 0x22AF6658U, 0x50FD3DEBU, 0xA35B6E1U, - 0x87B78513U, 0x5CA68B6U, 0xF3B77C65U, 0xDAE7ACC8U, 0xBD84E707U, 0xC0B1F2EEU, 0x7C5B280BU, 0x3C82C2A7U, 0xF1848767U, 0xCF397063U, 0x11293CECU, 0x86B3A406U, - 0xCF0391E2U, 0xCAE6F488U, 0xA2130914U, 0x80443800U, 0x75A52C98U, 0x255D3BC5U, 0x70B8141FU, 0x52A6D7E8U, 0xF3773CB5U, 0x16682961U, 0xE291D23CU, 0xEA1AB08DU, - 0x3AF6AC29U, 0xF077AF0BU, 0xDB42975FU, 0xE4B5A5C3U, 0x828767D9U, 0xCE511DFDU, 0x8FA20C6DU, 0xD4FEEEB4U, 0x3B75D536U, 0x81090466U, 0xB210CB77U, 0xA0A56499U, - 0x601ADD2U, 0xAB167BEAU, 0xF706C300U, 0x1B058070U, 0x9F01D362U, 0x52CFBC44U, 0x96A9AB7BU, 0x966588D6U, 0xB899A286U, 0x5EE0407AU, 0x681CEAFFU, 0x4C40811U, - 0xB20B7269U, 0x367237BFU, 0x428A0B94U, 0xD691C645U, 0xB12CFF27U, 0x9E6383BEU, 0x6176461EU, 0xFDB47228U, 0x51A94E60U, 0xFBD6A3E0U, 0xF187D05EU, 0x4DA143CFU, - 0x49C7CCE6U, 0xB4B52BF7U, 0x3BA3A346U, 0xA803AAFEU, 0x9FC8C67BU, 0xA639766CU, 0x4C6B2408U, 0xED09AD3DU, 0xDBBD48U, 0xE0E2196DU, 0xE9FFEE62U, 0xB50384FU, - 0xDFE188A2U, 0x3633AE21U, 0xAEF9F8C9U, 0x80178502U, 0xED42BC9CU, 0x85653DDDU, 0x394C79C4U, 0x71477B3DU, 0xF8C674CFU, 0xD4B8C4E9U, 0x2A5947F9U, 0xFC4C64D2U, - 0x6B322B31U, 0xB9B20DFBU, 0x57BB1739U, 0x3D915162U, 0x5AAAA1ACU, 0x91EB2A66U, 0x35CA03C9U, 0xDE6D0202U, 0xCB2E089FU, 0x57048634U, 0xEEBBC058U, 0x3813A5F6U, - 0x722CE848U, 0x8479A8A6U, 0xE92B8076U, 0x1B1F3F83U, 0x81D8932FU, 0xFDDDB092U, 0x30D5B4C9U, 0xC91CF267U, 0x36AD135BU, 0x71F52515U, 0xC089EF35U, 0x41038328U, - 0x6456724BU, 0x1B2B3E23U, 0xD24210BBU, 0xC62FBD71U, 0xFCAD3662U, 0x8E3F7FF2U, 0xE48AE1B8U, 0xD23BC8ABU, 0xEF89F436U, 0x62BCE039U, 0x1A5DE46CU, 0x16236FU, - 0xCA241E6DU, 0x9EEE203BU, 0x3D3879E4U, 0x1D1C6180U, 0xD378251U, 0xE2BA4A87U, 0x66DFA1A0U, 0xCFA93D5DU, 0x9F152D0U, 0x7418FB2CU, 0x6CB7295CU, 0x9F7002F9U, - 0x1F7DE611U, 0x5FA0D6B3U, 0xA466F742U, 0x8E097065U, 0x7F7B3458U, 0x25360EB8U, 0xE8ADA4B0U, 0x18B1FE00U, 0x2AC22D1CU, 0x4186B027U, 0x959C76EAU, 0x8872FA1EU, - 0x486317D3U, 0xED35E29BU, 0xB17E878U, 0x8F6CC5FCU, 0x2E8831DBU, 0xFA55FF05U, 0x6FEFF36U, 0xBE942D00U, 0x36B6480EU, 0x4C5D91EFU, 0xEB2C7AC2U, 0xEA33683AU, - 0xB8A51C5EU, 0x8BF2227BU, 0xF37E24F6U, 0x864012FU, 0x5DE7786U, 0x3EFEC660U, 0xE2761ACU, 0x54A6C4ABU, 0x4047D505U, 0x37FBD45CU, 0x65D5D78BU, 0xBE3CF030U, - 0x4A150EFBU, 0x2F283083U, 0xCB47C04DU, 0x973EDABU, 0xD6BC301FU, 0xD792EACU, 0xEEA55E7U, 0xAB40BD74U, 0x1C5A009AU, 0x7485B1C1U, 0xCA86F28AU, 0xA743045FU, - 0xB76BFEDU, 0x76DD731AU, 0x3752687U, 0x968C7740U, 0x2CAC2CA8U, 0x9B8691CAU, 0xF0EF8D89U, 0x770D8687U, 0xF6DE8D96U, 0x91B3A983U, 0x7228545U, 0xA8134914U, - 0xFD9A01E6U, 0x72386ADDU, 0x845A80A6U, 0x10675D75U, 0x31032835U, 0xB6510D2AU, 0x67E9C2D9U, 0x8C073B5FU, 0x348F2BA5U, 0xE4DF38ECU, 0x535EDE00U, 0xE31FD2EFU, - 0xAA5BD7DCU, 0x9D963F06U, 0x8D26D2E9U, 0x5D76C1A0U, 0x95131597U, 0x25521978U, 0xA549BA78U, 0xFC809EA1U, 0x9CC1A4E2U, 0x58043720U, 0xE3BD3B7BU, 0xED684815U, - 0x8A1B48E8U, 0x9C5BFCA1U, 0x32FA853AU, 0xB3626483U, 0x972DA82DU, 0xE492749AU, 0x35CA2D1DU, 0xC1E25D40U, 0xFAA559E2U, 0x27472E18U, 0xEA8FB72AU, 0x5D846824U, - 0x77540CDAU, 0x45717960U, 0x57C4D68EU, 0xEF78B1EBU, 0x72AF8952U, 0xCA13EE37U, 0xD8A641D9U, 0x601A26BCU, 0x387936EAU, 0x80C5518FU, 0x47E9CBACU, 0xFF55ACC9U, - 0xEDE00327U, 0x835DF178U, 0xDD2F69BU, 0xC178F605U, 0xCBBDFF1CU, 0x717FF82U, 0x8998F861U, 0x4532F8FFU, 0x9C12EA53U, 0x50B8EACDU, 0x2E8AEB86U, 0xE220EB18U, - 0x6CAFECFBU, 0x6D9D258CU, 0xBC42E87CU, 0x61A4E33U, 0xCFB8C4FU, 0x81664E1AU, 0x13BBA529U, 0x5BFB8755U, 0x5B9E60F1U, 0xAAF0E106U, 0x89633A85U, 0x3E0560D0U, - 0x39A51A29U, 0x8EC3407CU, 0xE6DEDAE1U, 0x51B880B4U, 0xC3614311U, 0x74071944U, 0xEEA49D28U, 0x59C2C77DU, 0x236AF20EU, 0x940CA85BU, 0xF46B750FU, 0x430D2F5AU, - 0xD1002AD3U, 0x66667086U, 0x44AD55A3U, 0xF3CB0FF6U, 0x31DF5DE0U, 0x86B907B5U, 0x5618FA4DU, 0xE17EA018U, 0x5E62BD84U, 0xE904E7D1U, 0x61C60A7FU, 0xD6A0502AU, - 0x796DEC4CU, 0xCE0BB619U, 0xCBCFC2F4U, 0x7CA998A1U, 0x7373A591U, 0xC415FFC4U, 0x93ACD2A2U, 0x24CA88F7U, 0x6830EF86U, 0xDF56B5D3U, 0xEF283F18U, 0x584E654DU, - 0xA5FE80A0U, 0x1298DAF5U, 0x8095DF7CU, 0x37F38529U, 0x78D0FE2U, 0xB0EB55B7U, 0x1D42E7C5U, 0xAA24BD90U, 0x1538A00CU, 0xA25EFA59U, 0x4521F793U, 0xF247ADC6U, - 0xD8F6CF2AU, 0x6F90957FU, 0xF5E7D73FU, 0x42818D6AU, 0x72FF07A1U, 0xC5995DF4U, 0x92207092U, 0x25462AC7U, 0xE75278D1U, 0x50342284U, 0xD08C88E3U, 0x67EAD2B6U, - 0x1838F762U, 0xAF5EAD37U, 0x6112CC53U, 0xD6749606U, 0x2F0C6FC3U, 0x986A3596U, 0xCA4360C4U, 0x7D253A91U, 0xB74B2F4EU, 0x2D751BU, 0xFF7482BU, 0xB891127EU, - 0x5794587DU, 0xE0F20228U, 0xC8276ED0U, 0x7F413485U, 0x13AA1C8FU, 0xA4CC46DAU, 0x597CA337U, 0xEE1AF962U, 0x52EE48DAU, 0xE588128FU, 0x94B2CC11U, 0x23D49644U, - 0xC239270DU, 0x755F7D58U, 0x20825E2AU, 0x97E4047FU, 0xC4AB9B8EU, 0x73CDC1DBU, 0x70716126U, 0xC7173B73U, 0xAC65B06DU, 0x1C7021BFU, 0x11FB361U, 0xB679E934U, - 0x746DBB22U, 0xC30BE177U, 0xF3756BBCU, 0x441331E9U, 0xB9A3D404U, 0xEC58E51U, 0xFFF99EE2U, 0x489FC4B7U, 0x7C17FCEBU, 0xCB71A6BEU, 0x4106B2AAU, 0xD9C40950U, - 0x36C14353U, 0x81A71906U, 0x1BD05B46U, 0xACB60113U, 0x9CC88BD8U, 0x2BAED18DU, 0x7117AB85U, 0xC671F1D0U, 0x860763FFU, 0x316139AAU, 0x2C0EAB74U, 0x9B68F121U, - 0xCCD1DC47U, 0x7BB78612U, 0xDE6473A9U, 0x690229FCU, 0x2BC473EBU, 0x9CA229BEU, 0x9378148EU, 0x241E4EDBU, 0xEAF2C37U, 0xB9C97662U, 0xA4A6E4BCU, 0x13C0BEE9U, - 0x252C88A1U, 0x924AD2F4U, 0xAA4E1FF6U, 0x1D2845A3U, 0x9764CE8AU, 0x200294DFU, 0x92F4B6BEU, 0x2592ECEBU, 0xCD89B85BU, 0x7AEFE20EU, 0x47D77DU, 0xB7218D28U, - 0xE8E2E787U, 0x5F84BDD2U, 0x505E80E2U, 0xE738DAB7U, 0x660CD2E0U, 0xD16A88B5U, 0xE96E45B7U, 0x5E081FE2U, 0xDEB0B585U, 0x69D6EFD0U, 0xCC051A6BU, 0x7B63403EU, - 0xFEA1FAFEU, 0x49C7A0ABU, 0x4B1DCAF5U, 0xFC7B90A0U, 0xB1D993CDU, 0x6BFC998U, 0x5F3AD998U, 0xE85C83CDU, 0x41E9EBBBU, 0xF68FB1EEU, 0xDA78A9ADU, 0x6D1EF3F8U, - 0xC2EDE121U, 0x758BBB74U, 0x883B5E99U, 0x3F5D04CCU, 0x4D8F7676U, 0xFAE92C23U, 0xCB1B04D8U, 0x7C7D5E8DU, 0xBFE5AEABU, 0x883F4FEU, 0x759C9CEU, 0xB03F939BU, - 0x80411950U, 0x37274305U, 0x308739FCU, 0x87E163A9U, 0xF5331113U, 0x42554B46U, 0x2A48D1DBU, 0x9D2E8B8EU, 0x1D9621E9U, 0xAAF07BBCU, 0xA52A468CU, 0x124C1CD9U, - 0xE786BEFDU, 0x50E0E4A8U, 0x9A8EF177U, 0x2DE8AB22U, 0xB79FE962U, 0xF9B337U, 0x57409E51U, 0xE026C404U, 0x547CF459U, 0xE31AAE0CU, 0x6BD843A2U, 0xDCBE19F7U, - 0x5C06B390U, 0xEB60E9C5U, 0xECC0933CU, 0x5BA6C969U, 0x2F71F45U, 0xB5914510U, 0xA0849007U, 0x17E2CA52U, 0x5D8F4DD1U, 0x785F2A36U, 0xBA4B7820U, 0xD2D2275U, - 0xA8FED7CEU, 0x1F988D9BU, 0x77851706U, 0xC0E34D53U, 0xB2313FE9U, 0x55765BCU, 0xA8D588CU, 0xBDEB02D9U, 0x9F2027FCU, 0x28467DA9U, 0x34A54D47U, 0x83C31712U, - 0x96D6C205U, 0x21B09850U, 0x335DBD17U, 0xF11165A8U, 0x46773FFDU, 0x9EAC85CCU, 0x29CADF99U, 0x3237F1C4U, 0x8551AB91U, 0x3A4DB60DU, 0x8D2BEC58U, 0x709B09B5U, - 0xC7FD53E0U, 0x5FD0B10BU, 0xE8B6EB5EU, 0xC05D2919U, 0x773B734CU, 0x90447E86U, 0x272224D3U, 0xA82A11E2U, 0x1F4C4BB7U, 0x65E47EC4U, 0xD2822491U, 0xBA9FBE0CU, - 0xDF9E459U, 0x523A8EF6U, 0xE55CD4A3U, 0xEA86E993U, 0x5DE0B3C6U, 0x3D876E92U, 0x8AE134C7U, 0x6D9E390DU, 0xDAF86358U, 0xCFEDB64FU, 0x788BEC1AU, 0x7751D12AU, - 0xC0378B7FU, 0x83A9B574U, 0x34CFEF21U, 0xCCB2223U, 0xBBAD7876U, 0x461D9D9BU, 0xF17BC7CEU, 0x1604CA04U, 0xA1629051U, 0xF6DBBD37U, 0x41BDE762U, 0xAEB8AD61U, - 0x19DEF734U, 0x911C1A9AU, 0x267A40CFU, 0x4B165EAU, 0xB3D73FBFU, 0x1E7E8DCDU, 0xA918D798U, 0x336F95D8U, 0x8409CF8DU, 0x21DA3A36U, 0x96BC6063U, 0xBC0D028FU, - 0xB6B58DAU, 0x9CF62567U, 0x2B907F32U, 0x4E67DA52U, 0xF9018007U, 0x43678D3CU, 0xF401D769U, 0x54A83275U, 0xE3CE6820U, 0xC97F0ACCU, 0x7E195099U, 0x3B15D211U, - 0x8C738844U, 0xEC145510U, 0x5B720F45U, 0x99665D53U, 0x2E000706U, 0x6376C247U, 0xD4109812U, 0xE46E12D9U, 0x5308488CU, 0x29A07DFFU, 0x9EC627AAU, 0xE5E2B0E9U, - 0x5284EABCU, 0xA74E4898U, 0x102812CDU, 0xD478013U, 0xBA21DA46U, 0x17886834U, 0xA0EE3261U, 0x4FEB7862U, 0xF88D2237U, 0x62FA6077U, 0xD59C3A22U, 0x20569806U, - 0x9730C253U, 0x6A8027BEU, 0xDDE67DEBU, 0x318A297CU, 0x77EFB560U, 0x3A997021U, 0x8DFF2A74U, 0x78358850U, 0xCF53D205U, 0x5D8A11A0U, 0xEAEC4BF5U, 0x8BD3F2BDU, - 0x3CB5A8E8U, 0x8DAB26ADU, 0x3ACD7CF8U, 0x53DC7DAU, 0xB25B9D8FU, 0x5FEE1FB4U, 0xE88845E1U, 0x6468DCF4U, 0xD30E86A1U, 0xB3833366U, 0x4E56933U, 0xA94CDB41U, - 0x1E2A8114U, 0x262E4C16U, 0x91481643U, 0xDC3ED302U, 0x6B588957U, 0xF9558CDEU, 0x4E33D68BU, 0x4993AC72U, 0xFEF5F627U, 0x535C4455U, 0xE43A1E00U, 0xA1369C88U, - 0x1650C6DDU, 0x845DC354U, 0x333B9901U, 0x2E540BDFU, 0x9932518AU, 0xBBF974AFU, 0xC9F2EFAU, 0x9E922B73U, 0x29F47126U, 0x176200A7U, 0xA0045AF2U, 0x1E94E55EU, - 0xA9F2BF0BU, 0x7129053AU, 0xC64F5F6FU, 0x4E8DB2C1U, 0xF9EBE894U, 0xE4847A4AU, 0x53E2201FU, 0x3B2B7CAEU, 0x8C4D26FBU, 0x107C1E14U, 0xA71A4441U, 0x3D6D0601U, - 0x8A0B5C54U, 0xD1F96FEAU, 0x701F8A2FU, 0xEDCCFBF9U, 0x2C9B1FAU, 0xB5AFEBAFU, 0x6BE6ED1DU, 0xDC80B748U, 0xF0A36927U, 0x47C53372U, 0xA8C07971U, 0x1FA62324U, - 0x7FC1FE70U, 0xC8A7A425U, 0x77BBB9B9U, 0xC0DDE3ECU, 0x351741C8U, 0x82711B9DU, 0x9F1E8943U, 0x2878D316U, 0x38FD7E35U, 0x8F9B2460U, 0x481F0E42U, 0xFF795417U, - 0xBA75D69FU, 0xD138CCAU, 0x7DA5F064U, 0xCAC3AA31U, 0xF783D92BU, 0x40E5837EU, 0xA0BA3EB8U, 0x17DC64EDU, 0x7535DF3EU, 0xC253856BU, 0x8F25402AU, 0x38431A7FU, - 0xC797F186U, 0x70F1ABD3U, 0x604AA84FU, 0xD72CF21AU, 0x47AF9114U, 0xF0C9CB41U, 0x27A2EE26U, 0x90C4B473U, 0xBEBDCAB7U, 0x9DB90E2U, 0xED4C310CU, 0x5A2A6B59U, - 0x223D969U, 0xB545833CU, 0x96E86CBAU, 0x218E36EFU, 0xA06EF894U, 0x1708A2C1U, 0x6D74519EU, 0xDA120BCBU, 0x180659DDU, 0xAF600388U, 0xDDB27132U, 0x6AD42B67U, - 0xD5C836FBU, 0x62AE6CAEU, 0x2474ECBDU, 0x9312B6E8U, 0xCF07DEDCU, 0x78618489U, 0x32DD9957U, 0x85BBC302U, 0x90AE1615U, 0x27C84C40U, 0xC0B7418AU, 0x77D11BDFU, - 0x3AA7DE9EU, 0x8DC184CBU, 0xB5C549C9U, 0x2A3139CU, 0x62C4CEC8U, 0xD5A2949DU, 0x28127170U, 0x9F742B25U, 0xA770E627U, 0x1016BC72U, 0x206836B9U, 0x970E6CECU, - 0x1FCC8142U, 0xA8AADB17U, 0x5036965U, 0xB2653330U, 0x52862C08U, 0xBA1F74F9U, 0xEDA6599FU, 0x5AC003CAU, 0x47526A2CU, 0x3D07A467U, 0xCFD318F0U, 0x78B542A5U, - 0xA9981D6DU, 0x1EFE4738U, 0x8CF342B1U, 0x3B9518E4U, 0x9BD6956BU, 0x2CB0CF3EU, 0xD0584ECFU, 0x673E149AU, 0x2A667589U, 0x1811A54AU, 0x45F31ACBU, 0x76E3DDA5U, - 0xC18587F0U, 0xC625FD09U, 0x7143A75CU, 0x195E3DC1U, 0xAE386794U, 0xBEB922FU, 0xBC8DC87AU, 0xD51CF0D7U, 0x627AAA82U, 0xA67301FU, 0xBD016A4AU, 0x8505A748U, - 0x3263FD1DU, 0x52042049U, 0xE5627A1CU, 0x5CECDB03U, 0xEB8A8156U, 0xF22D0FA0U, 0x454B55F5U, 0x7453159DU, 0xC3354FC8U, 0x37734FDCU, 0x80151589U, 0x8D7F827U, - 0xBFB1A272U }; - -const ReplacementIndexStruct ReplacementIndexData[] = { - { utf16char(43), medium(1) }, - { utf16char(45), medium(1) }, - { utf16char(49), medium(2) }, - { utf16char(50), medium(1) }, - { utf16char(56), medium(1) }, - { utf16char(97), medium(131) }, - { utf16char(98), medium(233) }, - { utf16char(99), medium(305) }, - { utf16char(100), medium(101) }, - { utf16char(101), medium(78) }, - { utf16char(102), medium(451) }, - { utf16char(103), medium(114) }, - { utf16char(104), medium(143) }, - { utf16char(105), medium(59) }, - { utf16char(106), medium(25) }, - { utf16char(107), medium(53) }, - { utf16char(108), medium(105) }, - { utf16char(109), medium(265) }, - { utf16char(110), medium(75) }, - { utf16char(111), medium(76) }, - { utf16char(112), medium(210) }, - { utf16char(113), medium(8) }, - { utf16char(114), medium(119) }, - { utf16char(115), medium(305) }, - { utf16char(116), medium(151) }, - { utf16char(117), medium(55) }, - { utf16char(118), medium(32) }, - { utf16char(119), medium(228) }, - { utf16char(120), medium(4) }, - { utf16char(121), medium(9) }, - { utf16char(122), medium(15) }, -}; - -std::vector Replacements; -std::map> ReplacementsMap; -std::map ReplacementsHash; - -void InitReplacements() { - if (!Replacements.empty()) { - return; - } - auto data = ReplacementData; - auto takeString = [&data](int size) { - auto result = utf16string(data, size); - data += size; - return result; - }; - auto wordSize = ReplacementWordLengths; - - Replacements.reserve(1936); - for (auto item : ReplacementInitData) { - auto emoji = takeString(item.emojiSize); - auto replacement = takeString(item.replacementSize); - auto words = std::vector(); - words.reserve(item.wordsCount); - for (auto i = 0; i != item.wordsCount; ++i) { - words.push_back(takeString(*wordSize++)); - } - Replacements.push_back({ std::move(emoji), std::move(replacement), std::move(words) }); - } - - auto indices = ReplacementIndices; - auto items = &Replacements[0]; - for (auto item : ReplacementIndexData) { - auto index = std::vector(); - index.reserve(item.count); - for (auto i = 0; i != item.count; ++i) { - index.push_back(items + (*indices++)); - } - ReplacementsMap.emplace(item.ch, std::move(index)); - } - - for (auto checksum : ReplacementChecksums) { - ReplacementsHash.emplace(checksum, items++); - } -} - -const std::vector *GetReplacements(utf16char first) { - if (ReplacementsMap.empty()) { - InitReplacements(); - } - auto it = ReplacementsMap.find(first); - return (it == ReplacementsMap.cend()) ? nullptr : &it->second; -} - -utf16string GetReplacementEmoji(utf16string replacement) { - auto code = countChecksum(replacement.data(), replacement.size() * sizeof(utf16char)); - auto it = ReplacementsHash.find(code); - return (it == ReplacementsHash.cend()) ? utf16string() : it->second->emoji; -} diff --git a/TMessagesProj/jni/emoji/emoji_suggestions_data.h b/TMessagesProj/jni/emoji/emoji_suggestions_data.h deleted file mode 100755 index 68d9692e2..000000000 --- a/TMessagesProj/jni/emoji/emoji_suggestions_data.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -WARNING! All changes made in this file will be lost! -Created from 'empty' by 'codegen_emoji' - -This file is part of Telegram Desktop, -the official desktop version of Telegram messaging app, see https://telegram.org - -Telegram Desktop is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -It is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -In addition, as a special exception, the copyright holders give permission -to link the code of portions of this program with the OpenSSL library. - -Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE -Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org -*/ -#pragma once - -#include "emoji_suggestions.h" - -struct Replacement { - utf16string emoji; - utf16string replacement; - std::vector words; -}; - -constexpr auto kReplacementMaxLength = 55; - -void InitReplacements(); -const std::vector *GetReplacements(utf16char first); -utf16string GetReplacementEmoji(utf16string replacement); diff --git a/TMessagesProj/jni/ffmpeg/include/libavformat/dv.h b/TMessagesProj/jni/ffmpeg/include/libavformat/dv.h new file mode 100644 index 000000000..160c6ab87 --- /dev/null +++ b/TMessagesProj/jni/ffmpeg/include/libavformat/dv.h @@ -0,0 +1,41 @@ +/* + * General DV muxer/demuxer + * Copyright (c) 2003 Roman Shaposhnik + * + * Many thanks to Dan Dennedy for providing wealth + * of DV technical info. + * + * Raw DV format + * Copyright (c) 2002 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_DV_H +#define AVFORMAT_DV_H + +#include "avformat.h" + +typedef struct DVDemuxContext DVDemuxContext; +DVDemuxContext* avpriv_dv_init_demux(AVFormatContext* s); +int avpriv_dv_get_packet(DVDemuxContext*, AVPacket *); +int avpriv_dv_produce_packet(DVDemuxContext*, AVPacket*, uint8_t*, int, int64_t); +void ff_dv_offset_reset(DVDemuxContext *c, int64_t frame_offset); + +typedef struct DVMuxContext DVMuxContext; + +#endif /* AVFORMAT_DV_H */ diff --git a/TMessagesProj/jni/ffmpeg/include/libavformat/isom.h b/TMessagesProj/jni/ffmpeg/include/libavformat/isom.h new file mode 100644 index 000000000..73b4504e5 --- /dev/null +++ b/TMessagesProj/jni/ffmpeg/include/libavformat/isom.h @@ -0,0 +1,367 @@ +/* + * ISO Media common code + * copyright (c) 2001 Fabrice Bellard + * copyright (c) 2002 Francois Revol + * copyright (c) 2006 Baptiste Coudurier + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_ISOM_H +#define AVFORMAT_ISOM_H + +#include +#include + +#include "libavutil/encryption_info.h" +#include "libavutil/mastering_display_metadata.h" +#include "libavutil/spherical.h" +#include "libavutil/stereo3d.h" + +#include "avio.h" +#include "internal.h" +#include "dv.h" + +/* isom.c */ +extern const AVCodecTag ff_mp4_obj_type[]; +extern const AVCodecTag ff_codec_movvideo_tags[]; +extern const AVCodecTag ff_codec_movaudio_tags[]; +extern const AVCodecTag ff_codec_movsubtitle_tags[]; +extern const AVCodecTag ff_codec_movdata_tags[]; + +int ff_mov_iso639_to_lang(const char lang[4], int mp4); +int ff_mov_lang_to_iso639(unsigned code, char to[4]); + +struct AVAESCTR; + +/* the QuickTime file format is quite convoluted... + * it has lots of index tables, each indexing something in another one... + * Here we just use what is needed to read the chunks + */ + +typedef struct MOVStts { + unsigned int count; + int duration; +} MOVStts; + +typedef struct MOVStsc { + int first; + int count; + int id; +} MOVStsc; + +typedef struct MOVElst { + int64_t duration; + int64_t time; + float rate; +} MOVElst; + +typedef struct MOVDref { + uint32_t type; + char *path; + char *dir; + char volume[28]; + char filename[64]; + int16_t nlvl_to, nlvl_from; +} MOVDref; + +typedef struct MOVAtom { + uint32_t type; + int64_t size; /* total size (excluding the size and type fields) */ +} MOVAtom; + +struct MOVParseTableEntry; + +typedef struct MOVFragment { + int found_tfhd; + unsigned track_id; + uint64_t base_data_offset; + uint64_t moof_offset; + uint64_t implicit_offset; + unsigned stsd_id; + unsigned duration; + unsigned size; + unsigned flags; +} MOVFragment; + +typedef struct MOVTrackExt { + unsigned track_id; + unsigned stsd_id; + unsigned duration; + unsigned size; + unsigned flags; +} MOVTrackExt; + +typedef struct MOVSbgp { + unsigned int count; + unsigned int index; +} MOVSbgp; + +typedef struct MOVEncryptionIndex { + // Individual encrypted samples. If there are no elements, then the default + // settings will be used. + unsigned int nb_encrypted_samples; + AVEncryptionInfo **encrypted_samples; + + uint8_t* auxiliary_info_sizes; + size_t auxiliary_info_sample_count; + uint8_t auxiliary_info_default_size; + uint64_t* auxiliary_offsets; ///< Absolute seek position + size_t auxiliary_offsets_count; +} MOVEncryptionIndex; + +typedef struct MOVFragmentStreamInfo { + int id; + int64_t sidx_pts; + int64_t first_tfra_pts; + int64_t tfdt_dts; + int index_entry; + MOVEncryptionIndex *encryption_index; +} MOVFragmentStreamInfo; + +typedef struct MOVFragmentIndexItem { + int64_t moof_offset; + int headers_read; + int current; + int nb_stream_info; + MOVFragmentStreamInfo * stream_info; +} MOVFragmentIndexItem; + +typedef struct MOVFragmentIndex { + int allocated_size; + int complete; + int current; + int nb_items; + MOVFragmentIndexItem * item; +} MOVFragmentIndex; + +typedef struct MOVIndexRange { + int64_t start; + int64_t end; +} MOVIndexRange; + +typedef struct MOVStreamContext { + AVIOContext *pb; + int pb_is_copied; + int ffindex; ///< AVStream index + int next_chunk; + unsigned int chunk_count; + int64_t *chunk_offsets; + unsigned int stts_count; + MOVStts *stts_data; + unsigned int ctts_count; + unsigned int ctts_allocated_size; + MOVStts *ctts_data; + unsigned int stsc_count; + MOVStsc *stsc_data; + unsigned int stsc_index; + int stsc_sample; + unsigned int stps_count; + unsigned *stps_data; ///< partial sync sample for mpeg-2 open gop + MOVElst *elst_data; + unsigned int elst_count; + int ctts_index; + int ctts_sample; + unsigned int sample_size; ///< may contain value calculated from stsd or value from stsz atom + unsigned int stsz_sample_size; ///< always contains sample size from stsz atom + unsigned int sample_count; + int *sample_sizes; + int keyframe_absent; + unsigned int keyframe_count; + int *keyframes; + int time_scale; + int64_t time_offset; ///< time offset of the edit list entries + int64_t min_corrected_pts; ///< minimum Composition time shown by the edits excluding empty edits. + int current_sample; + int64_t current_index; + MOVIndexRange* index_ranges; + MOVIndexRange* current_index_range; + unsigned int bytes_per_frame; + unsigned int samples_per_frame; + int dv_audio_container; + int pseudo_stream_id; ///< -1 means demux all ids + int16_t audio_cid; ///< stsd audio compression id + unsigned drefs_count; + MOVDref *drefs; + int dref_id; + int timecode_track; + int width; ///< tkhd width + int height; ///< tkhd height + int dts_shift; ///< dts shift when ctts is negative + uint32_t palette[256]; + int has_palette; + int64_t data_size; + uint32_t tmcd_flags; ///< tmcd track flags + int64_t track_end; ///< used for dts generation in fragmented movie files + int start_pad; ///< amount of samples to skip due to enc-dec delay + unsigned int rap_group_count; + MOVSbgp *rap_group; + + int nb_frames_for_fps; + int64_t duration_for_fps; + + /** extradata array (and size) for multiple stsd */ + uint8_t **extradata; + int *extradata_size; + int last_stsd_index; + int stsd_count; + int stsd_version; + + int32_t *display_matrix; + AVStereo3D *stereo3d; + AVSphericalMapping *spherical; + size_t spherical_size; + AVMasteringDisplayMetadata *mastering; + AVContentLightMetadata *coll; + size_t coll_size; + + uint32_t format; + + int has_sidx; // If there is an sidx entry for this stream. + struct { + struct AVAESCTR* aes_ctr; + unsigned int per_sample_iv_size; // Either 0, 8, or 16. + AVEncryptionInfo *default_encrypted_sample; + MOVEncryptionIndex *encryption_index; + } cenc; +} MOVStreamContext; + +typedef struct MOVContext { + const AVClass *clazz; ///< class for private options + AVFormatContext *fc; + int time_scale; + int64_t duration; ///< duration of the longest track + int found_moov; ///< 'moov' atom has been found + int found_mdat; ///< 'mdat' atom has been found + int found_hdlr_mdta; ///< 'hdlr' atom with type 'mdta' has been found + int trak_index; ///< Index of the current 'trak' + char **meta_keys; + unsigned meta_keys_count; + DVDemuxContext *dv_demux; + AVFormatContext *dv_fctx; + int isom; ///< 1 if file is ISO Media (mp4/3gp) + MOVFragment fragment; ///< current fragment in moof atom + MOVTrackExt *trex_data; + unsigned trex_count; + int itunes_metadata; ///< metadata are itunes style + int handbrake_version; + int *chapter_tracks; + unsigned int nb_chapter_tracks; + int use_absolute_path; + int ignore_editlist; + int advanced_editlist; + int ignore_chapters; + int seek_individually; + int64_t next_root_atom; ///< offset of the next root atom + int export_all; + int export_xmp; + int *bitrates; ///< bitrates read before streams creation + int bitrates_count; + int moov_retry; + int use_mfra_for; + int has_looked_for_mfra; + MOVFragmentIndex frag_index; + int atom_depth; + unsigned int aax_mode; ///< 'aax' file has been detected + uint8_t file_key[20]; + uint8_t file_iv[20]; + void *activation_bytes; + int activation_bytes_size; + void *audible_fixed_key; + int audible_fixed_key_size; + struct AVAES *aes_decrypt; + uint8_t *decryption_key; + int decryption_key_len; + int enable_drefs; + int32_t movie_display_matrix[3][3]; ///< display matrix from mvhd +} MOVContext; + +int ff_mp4_read_descr_len(AVIOContext *pb); +int ff_mp4_read_descr(AVFormatContext *fc, AVIOContext *pb, int *tag); +int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext *pb); +void ff_mp4_parse_es_descr(AVIOContext *pb, int *es_id); + +#define MP4ODescrTag 0x01 +#define MP4IODescrTag 0x02 +#define MP4ESDescrTag 0x03 +#define MP4DecConfigDescrTag 0x04 +#define MP4DecSpecificDescrTag 0x05 +#define MP4SLDescrTag 0x06 + +#define MOV_TFHD_BASE_DATA_OFFSET 0x01 +#define MOV_TFHD_STSD_ID 0x02 +#define MOV_TFHD_DEFAULT_DURATION 0x08 +#define MOV_TFHD_DEFAULT_SIZE 0x10 +#define MOV_TFHD_DEFAULT_FLAGS 0x20 +#define MOV_TFHD_DURATION_IS_EMPTY 0x010000 +#define MOV_TFHD_DEFAULT_BASE_IS_MOOF 0x020000 + +#define MOV_TRUN_DATA_OFFSET 0x01 +#define MOV_TRUN_FIRST_SAMPLE_FLAGS 0x04 +#define MOV_TRUN_SAMPLE_DURATION 0x100 +#define MOV_TRUN_SAMPLE_SIZE 0x200 +#define MOV_TRUN_SAMPLE_FLAGS 0x400 +#define MOV_TRUN_SAMPLE_CTS 0x800 + +#define MOV_FRAG_SAMPLE_FLAG_DEGRADATION_PRIORITY_MASK 0x0000ffff +#define MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC 0x00010000 +#define MOV_FRAG_SAMPLE_FLAG_PADDING_MASK 0x000e0000 +#define MOV_FRAG_SAMPLE_FLAG_REDUNDANCY_MASK 0x00300000 +#define MOV_FRAG_SAMPLE_FLAG_DEPENDED_MASK 0x00c00000 +#define MOV_FRAG_SAMPLE_FLAG_DEPENDS_MASK 0x03000000 + +#define MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO 0x02000000 +#define MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES 0x01000000 + +#define MOV_TKHD_FLAG_ENABLED 0x0001 +#define MOV_TKHD_FLAG_IN_MOVIE 0x0002 +#define MOV_TKHD_FLAG_IN_PREVIEW 0x0004 +#define MOV_TKHD_FLAG_IN_POSTER 0x0008 + +#define MOV_SAMPLE_DEPENDENCY_UNKNOWN 0x0 +#define MOV_SAMPLE_DEPENDENCY_YES 0x1 +#define MOV_SAMPLE_DEPENDENCY_NO 0x2 + + +#define TAG_IS_AVCI(tag) \ + ((tag) == MKTAG('a', 'i', '5', 'p') || \ + (tag) == MKTAG('a', 'i', '5', 'q') || \ + (tag) == MKTAG('a', 'i', '5', '2') || \ + (tag) == MKTAG('a', 'i', '5', '3') || \ + (tag) == MKTAG('a', 'i', '5', '5') || \ + (tag) == MKTAG('a', 'i', '5', '6') || \ + (tag) == MKTAG('a', 'i', '1', 'p') || \ + (tag) == MKTAG('a', 'i', '1', 'q') || \ + (tag) == MKTAG('a', 'i', '1', '2') || \ + (tag) == MKTAG('a', 'i', '1', '3') || \ + (tag) == MKTAG('a', 'i', '1', '5') || \ + (tag) == MKTAG('a', 'i', '1', '6') || \ + (tag) == MKTAG('a', 'i', 'v', 'x') || \ + (tag) == MKTAG('A', 'V', 'i', 'n')) + + +int ff_mov_read_esds(AVFormatContext *fc, AVIOContext *pb); + +int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries); +void ff_mov_write_chan(AVIOContext *pb, int64_t channel_layout); + +#define FF_MOV_FLAG_MFRA_AUTO -1 +#define FF_MOV_FLAG_MFRA_DTS 1 +#define FF_MOV_FLAG_MFRA_PTS 2 + + +#endif /* AVFORMAT_ISOM_H */ diff --git a/TMessagesProj/jni/gifvideo.cpp b/TMessagesProj/jni/gifvideo.cpp index cae9401d4..376bdec09 100644 --- a/TMessagesProj/jni/gifvideo.cpp +++ b/TMessagesProj/jni/gifvideo.cpp @@ -13,6 +13,7 @@ extern "C" { #include +#include #include #include @@ -67,11 +68,10 @@ typedef struct VideoInfo { } stream = nullptr; } - /*if (ioBuffer) { TODO memleak? - av_free(ioBuffer); - ioBuffer = nullptr; - }*/ if (ioContext != nullptr) { + if (ioContext->buffer) { + av_freep(&ioContext->buffer); + } avio_context_free(&ioContext); ioContext = nullptr; } @@ -88,12 +88,14 @@ typedef struct VideoInfo { video_stream_idx = -1; video_stream = nullptr; + audio_stream = nullptr; } AVFormatContext *fmt_ctx = nullptr; char *src = nullptr; int video_stream_idx = -1; AVStream *video_stream = nullptr; + AVStream *audio_stream = nullptr; AVCodecContext *video_dec_ctx = nullptr; AVFrame *frame = nullptr; bool has_decoded_frames = false; @@ -248,6 +250,94 @@ int64_t seekCallback(void *opaque, int64_t offset, int whence) { return 0; } +enum PARAM_NUM { + PARAM_NUM_IS_AVC = 0, + PARAM_NUM_WIDTH = 1, + PARAM_NUM_HEIGHT = 2, + PARAM_NUM_BITRATE = 3, + PARAM_NUM_DURATION = 4, + PARAM_NUM_AUDIO_FRAME_SIZE = 5, + PARAM_NUM_VIDEO_FRAME_SIZE = 6, + PARAM_NUM_FRAMERATE = 7, + PARAM_NUM_ROTATION = 8, + PARAM_NUM_COUNT = 9 +}; + +void Java_org_telegram_ui_Components_AnimatedFileDrawable_getVideoInfo(JNIEnv *env, jclass clazz, jstring src, jintArray data) { + VideoInfo *info = new VideoInfo(); + + char const *srcString = env->GetStringUTFChars(src, 0); + size_t len = strlen(srcString); + info->src = new char[len + 1]; + memcpy(info->src, srcString, len); + info->src[len] = '\0'; + if (srcString != 0) { + env->ReleaseStringUTFChars(src, srcString); + } + + int ret; + if ((ret = avformat_open_input(&info->fmt_ctx, info->src, NULL, NULL)) < 0) { + LOGE("can't open source file %s, %s", info->src, av_err2str(ret)); + delete info; + return; + } + + if ((ret = avformat_find_stream_info(info->fmt_ctx, NULL)) < 0) { + LOGE("can't find stream information %s, %s", info->src, av_err2str(ret)); + delete info; + return; + } + + if ((ret = av_find_best_stream(info->fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0)) >= 0) { + info->video_stream = info->fmt_ctx->streams[ret]; + } + + if ((ret = av_find_best_stream(info->fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0)) >= 0) { + info->audio_stream = info->fmt_ctx->streams[ret]; + } + + if (info->video_stream == nullptr) { + LOGE("can't find video stream in the input, aborting %s", info->src); + delete info; + return; + } + + jint *dataArr = env->GetIntArrayElements(data, 0); + if (dataArr != nullptr) { + dataArr[PARAM_NUM_IS_AVC] = info->video_stream->codecpar->codec_id == AV_CODEC_ID_H264; + if (strstr(info->fmt_ctx->iformat->name, "mov") != 0 && dataArr[PARAM_NUM_IS_AVC]) { + MOVStreamContext *mov = (MOVStreamContext *) info->video_stream->priv_data; + dataArr[PARAM_NUM_VIDEO_FRAME_SIZE] = (jint) mov->data_size; + + if (info->audio_stream != nullptr) { + mov = (MOVStreamContext *) info->audio_stream->priv_data; + dataArr[PARAM_NUM_AUDIO_FRAME_SIZE] = (jint) mov->data_size; + } + } + dataArr[PARAM_NUM_BITRATE] = (jint) info->video_stream->codecpar->bit_rate; + dataArr[PARAM_NUM_WIDTH] = info->video_stream->codecpar->width; + dataArr[PARAM_NUM_HEIGHT] = info->video_stream->codecpar->height; + AVDictionaryEntry *rotate_tag = av_dict_get(info->video_stream->metadata, "rotate", NULL, 0); + if (rotate_tag && *rotate_tag->value && strcmp(rotate_tag->value, "0")) { + char *tail; + dataArr[PARAM_NUM_ROTATION] = (jint) av_strtod(rotate_tag->value, &tail); + if (*tail) { + dataArr[PARAM_NUM_ROTATION] = 0; + } + } else { + dataArr[PARAM_NUM_ROTATION] = 0; + } + if (info->video_stream->codecpar->codec_id == AV_CODEC_ID_H264) { + dataArr[PARAM_NUM_FRAMERATE] = (jint) av_q2d(info->video_stream->avg_frame_rate); + } else { + dataArr[PARAM_NUM_FRAMERATE] = (jint) av_q2d(info->video_stream->r_frame_rate); + } + dataArr[PARAM_NUM_DURATION] = (int32_t) (info->fmt_ctx->duration * 1000 / AV_TIME_BASE); + env->ReleaseIntArrayElements(data, dataArr, 0); + delete info; + } +} + jlong Java_org_telegram_ui_Components_AnimatedFileDrawable_createDecoder(JNIEnv *env, jclass clazz, jstring src, jintArray data, jint account, jlong streamFileSize, jobject stream) { VideoInfo *info = new VideoInfo(); @@ -305,7 +395,7 @@ jlong Java_org_telegram_ui_Components_AnimatedFileDrawable_createDecoder(JNIEnv info->video_stream = info->fmt_ctx->streams[info->video_stream_idx]; } - if (info->video_stream <= 0) { + if (info->video_stream == nullptr) { LOGE("can't find video stream in the input, aborting %s", info->src); delete info; return 0; @@ -442,12 +532,7 @@ void Java_org_telegram_ui_Components_AnimatedFileDrawable_seekToMs(JNIEnv *env, } if (got_frame) { if (info->frame->format == AV_PIX_FMT_YUV420P || info->frame->format == AV_PIX_FMT_BGRA || info->frame->format == AV_PIX_FMT_YUVJ420P) { - int64_t pkt_pts; - if (info->frame->pts != AV_NOPTS_VALUE) { - pkt_pts = info->frame->pts; - } else { - pkt_pts = info->frame->pkt_dts; - } + int64_t pkt_pts = info->frame->best_effort_timestamp; if (pkt_pts >= pts) { return; } @@ -524,11 +609,7 @@ jint Java_org_telegram_ui_Components_AnimatedFileDrawable_getVideoFrame(JNIEnv * if (dataArr != nullptr) { wantedWidth = dataArr[0]; wantedHeight = dataArr[1]; - if (info->frame->pts != AV_NOPTS_VALUE) { - dataArr[3] = (jint) (1000 * info->frame->pts * av_q2d(info->video_stream->time_base)); - } else { - dataArr[3] = (jint) (1000 * info->frame->pkt_dts * av_q2d(info->video_stream->time_base)); - } + dataArr[3] = (jint) (1000 * info->frame->best_effort_timestamp * av_q2d(info->video_stream->time_base)); env->ReleaseIntArrayElements(data, dataArr, 0); } else { AndroidBitmapInfo bitmapInfo; diff --git a/TMessagesProj/jni/libtgvoip b/TMessagesProj/jni/libtgvoip index ce74c9216..78decc81b 160000 --- a/TMessagesProj/jni/libtgvoip +++ b/TMessagesProj/jni/libtgvoip @@ -1 +1 @@ -Subproject commit ce74c9216f599874571061f39c2dc31632b3004b +Subproject commit 78decc81bf25cf36ad1b4a9398aa11cb195db9c5 diff --git a/TMessagesProj/jni/sqlite/sqlite3.c b/TMessagesProj/jni/sqlite/sqlite3.c index 0ceb49a45..a39e56902 100644 --- a/TMessagesProj/jni/sqlite/sqlite3.c +++ b/TMessagesProj/jni/sqlite/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.27.2. By combining all the individual C code files into this +** version 3.28.0. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -1162,9 +1162,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.27.2" -#define SQLITE_VERSION_NUMBER 3027002 -#define SQLITE_SOURCE_ID "2019-02-25 16:06:06 bd49a8271d650fa89e446b42e513b595a717b9212c91dd384aab871fc1d0f6d7" +#define SQLITE_VERSION "3.28.0" +#define SQLITE_VERSION_NUMBER 3028000 +#define SQLITE_SOURCE_ID "2019-04-16 19:49:53 884b4b7e502b4e991677b53971277adfaf0a04a284f8e483e2553d0f83156b50" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -1228,6 +1228,9 @@ SQLITE_API int sqlite3_libversion_number(void); #ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS SQLITE_API int sqlite3_compileoption_used(const char *zOptName); SQLITE_API const char *sqlite3_compileoption_get(int N); +#else +# define sqlite3_compileoption_used(X) 0 +# define sqlite3_compileoption_get(X) ((void*)0) #endif /* @@ -3125,8 +3128,8 @@ struct sqlite3_mem_methods { ** ** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] **
SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
-**
^This option is used to enable or disable the two-argument -** version of the [fts3_tokenizer()] function which is part of the +**
^This option is used to enable or disable the +** [fts3_tokenizer()] function which is part of the ** [FTS3] full-text search engine extension. ** There should be two additional arguments. ** The first argument is an integer which is 0 to disable fts3_tokenizer() or @@ -3238,6 +3241,17 @@ struct sqlite3_mem_methods { **
  • Direct writes to [shadow tables]. ** **
  • +** +** [[SQLITE_DBCONFIG_WRITABLE_SCHEMA]]
    SQLITE_DBCONFIG_WRITABLE_SCHEMA
    +**
    The SQLITE_DBCONFIG_WRITABLE_SCHEMA option activates or deactivates the +** "writable_schema" flag. This has the same effect and is logically equivalent +** to setting [PRAGMA writable_schema=ON] or [PRAGMA writable_schema=OFF]. +** The first argument to this setting is an integer which is 0 to disable +** the writable_schema, positive to enable writable_schema, or negative to +** leave the setting unchanged. The second parameter is a pointer to an +** integer into which is written 0 or 1 to indicate whether the writable_schema +** is enabled or disabled following this call. +**
    ** */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ @@ -3251,7 +3265,8 @@ struct sqlite3_mem_methods { #define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */ #define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ #define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */ -#define SQLITE_DBCONFIG_MAX 1010 /* Largest DBCONFIG */ +#define SQLITE_DBCONFIG_WRITABLE_SCHEMA 1011 /* int int* */ +#define SQLITE_DBCONFIG_MAX 1011 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes @@ -4933,6 +4948,18 @@ SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); */ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); +/* +** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement +** METHOD: sqlite3_stmt +** +** ^The sqlite3_stmt_isexplain(S) interface returns 1 if the +** prepared statement S is an EXPLAIN statement, or 2 if the +** statement S is an EXPLAIN QUERY PLAN. +** ^The sqlite3_stmt_isexplain(S) interface returns 0 if S is +** an ordinary statement or a NULL pointer. +*/ +SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt); + /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset ** METHOD: sqlite3_stmt @@ -5072,7 +5099,9 @@ typedef struct sqlite3_context sqlite3_context; ** ^The fifth argument to the BLOB and string binding interfaces ** is a destructor used to dispose of the BLOB or ** string after SQLite has finished with it. ^The destructor is called -** to dispose of the BLOB or string even if the call to bind API fails. +** to dispose of the BLOB or string even if the call to the bind API fails, +** except the destructor is not called if the third parameter is a NULL +** pointer or the fourth parameter is negative. ** ^If the fifth argument is ** the special value [SQLITE_STATIC], then SQLite assumes that the ** information is in static, unmanaged space and does not need to be freed. @@ -5989,6 +6018,8 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** sqlite3_value_nochange   ** →  True if the column is unchanged in an UPDATE ** against a virtual table. +** sqlite3_value_frombind   +** →  True if value originated from a [bound parameter] ** ** ** Details: @@ -6050,6 +6081,11 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** than within an [xUpdate] method call for an UPDATE statement, then ** the return value is arbitrary and meaningless. ** +** ^The sqlite3_value_frombind(X) interface returns non-zero if the +** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()] +** interfaces. ^If X comes from an SQL literal value, or a table column, +** and expression, then sqlite3_value_frombind(X) returns zero. +** ** Please pay particular attention to the fact that the pointer returned ** from [sqlite3_value_blob()], [sqlite3_value_text()], or ** [sqlite3_value_text16()] can be invalidated by a subsequent call to @@ -6095,6 +6131,7 @@ SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); SQLITE_API int sqlite3_value_type(sqlite3_value*); SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); SQLITE_API int sqlite3_value_nochange(sqlite3_value*); +SQLITE_API int sqlite3_value_frombind(sqlite3_value*); /* ** CAPI3REF: Finding The Subtype Of SQL Values @@ -6830,7 +6867,7 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); ** associated with database N of connection D. ^The main database file ** has the name "main". If there is no attached database N on the database ** connection D, or if database N is a temporary or in-memory database, then -** a NULL pointer is returned. +** this function will return either a NULL pointer or an empty string. ** ** ^The filename returned by this function is the output of the ** xFullPathname method of the [VFS]. ^In other words, the filename @@ -11931,7 +11968,7 @@ SQLITE_API int sqlite3rebaser_configure( ** in size. This function allocates and populates a buffer with a copy ** of the changeset rebased rebased according to the configuration of the ** rebaser object passed as the first argument. If successful, (*ppOut) -** is set to point to the new buffer containing the rebased changset and +** is set to point to the new buffer containing the rebased changeset and ** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the ** responsibility of the caller to eventually free the new buffer using ** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut) @@ -12340,7 +12377,7 @@ struct Fts5PhraseIter { ** Save the pointer passed as the second argument as the extension functions ** "auxiliary data". The pointer may then be retrieved by the current or any ** future invocation of the same fts5 extension function made as part of -** of the same MATCH query using the xGetAuxdata() API. +** the same MATCH query using the xGetAuxdata() API. ** ** Each extension function is allocated a single auxiliary data slot for ** each FTS query (MATCH expression). If the extension function is invoked @@ -12355,7 +12392,7 @@ struct Fts5PhraseIter { ** The xDelete callback, if one is specified, is also invoked on the ** auxiliary data pointer after the FTS5 query has finished. ** -** If an error (e.g. an OOM condition) occurs within this function, an +** If an error (e.g. an OOM condition) occurs within this function, ** the auxiliary data is set to NULL and an error code returned. If the ** xDelete parameter was not NULL, it is invoked on the auxiliary data ** pointer before returning. @@ -13381,7 +13418,7 @@ struct Hash { unsigned int count; /* Number of entries in this table */ HashElem *first; /* The first element of the array */ struct _ht { /* the hash table */ - int count; /* Number of entries with this hash */ + unsigned int count; /* Number of entries with this hash */ HashElem *chain; /* Pointer to first entry with this hash */ } *ht; }; @@ -13522,99 +13559,94 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define TK_PRECEDING 85 #define TK_RANGE 86 #define TK_UNBOUNDED 87 -#define TK_REINDEX 88 -#define TK_RENAME 89 -#define TK_CTIME_KW 90 -#define TK_ANY 91 -#define TK_BITAND 92 -#define TK_BITOR 93 -#define TK_LSHIFT 94 -#define TK_RSHIFT 95 -#define TK_PLUS 96 -#define TK_MINUS 97 -#define TK_STAR 98 -#define TK_SLASH 99 -#define TK_REM 100 -#define TK_CONCAT 101 -#define TK_COLLATE 102 -#define TK_BITNOT 103 -#define TK_ON 104 -#define TK_INDEXED 105 -#define TK_STRING 106 -#define TK_JOIN_KW 107 -#define TK_CONSTRAINT 108 -#define TK_DEFAULT 109 -#define TK_NULL 110 -#define TK_PRIMARY 111 -#define TK_UNIQUE 112 -#define TK_CHECK 113 -#define TK_REFERENCES 114 -#define TK_AUTOINCR 115 -#define TK_INSERT 116 -#define TK_DELETE 117 -#define TK_UPDATE 118 -#define TK_SET 119 -#define TK_DEFERRABLE 120 -#define TK_FOREIGN 121 -#define TK_DROP 122 -#define TK_UNION 123 -#define TK_ALL 124 -#define TK_EXCEPT 125 -#define TK_INTERSECT 126 -#define TK_SELECT 127 -#define TK_VALUES 128 -#define TK_DISTINCT 129 -#define TK_DOT 130 -#define TK_FROM 131 -#define TK_JOIN 132 -#define TK_USING 133 -#define TK_ORDER 134 -#define TK_GROUP 135 -#define TK_HAVING 136 -#define TK_LIMIT 137 -#define TK_WHERE 138 -#define TK_INTO 139 -#define TK_NOTHING 140 -#define TK_FLOAT 141 -#define TK_BLOB 142 -#define TK_INTEGER 143 -#define TK_VARIABLE 144 -#define TK_CASE 145 -#define TK_WHEN 146 -#define TK_THEN 147 -#define TK_ELSE 148 -#define TK_INDEX 149 -#define TK_ALTER 150 -#define TK_ADD 151 -#define TK_WINDOW 152 -#define TK_OVER 153 -#define TK_FILTER 154 -#define TK_TRUEFALSE 155 -#define TK_ISNOT 156 -#define TK_FUNCTION 157 -#define TK_COLUMN 158 -#define TK_AGG_FUNCTION 159 -#define TK_AGG_COLUMN 160 -#define TK_UMINUS 161 -#define TK_UPLUS 162 -#define TK_TRUTH 163 -#define TK_REGISTER 164 -#define TK_VECTOR 165 -#define TK_SELECT_COLUMN 166 -#define TK_IF_NULL_ROW 167 -#define TK_ASTERISK 168 -#define TK_SPAN 169 -#define TK_END_OF_FILE 170 -#define TK_UNCLOSED_STRING 171 -#define TK_SPACE 172 -#define TK_ILLEGAL 173 - -/* The token codes above must all fit in 8 bits */ -#define TKFLG_MASK 0xff - -/* Flags that can be added to a token code when it is not -** being stored in a u8: */ -#define TKFLG_DONTFOLD 0x100 /* Omit constant folding optimizations */ +#define TK_EXCLUDE 88 +#define TK_GROUPS 89 +#define TK_OTHERS 90 +#define TK_TIES 91 +#define TK_REINDEX 92 +#define TK_RENAME 93 +#define TK_CTIME_KW 94 +#define TK_ANY 95 +#define TK_BITAND 96 +#define TK_BITOR 97 +#define TK_LSHIFT 98 +#define TK_RSHIFT 99 +#define TK_PLUS 100 +#define TK_MINUS 101 +#define TK_STAR 102 +#define TK_SLASH 103 +#define TK_REM 104 +#define TK_CONCAT 105 +#define TK_COLLATE 106 +#define TK_BITNOT 107 +#define TK_ON 108 +#define TK_INDEXED 109 +#define TK_STRING 110 +#define TK_JOIN_KW 111 +#define TK_CONSTRAINT 112 +#define TK_DEFAULT 113 +#define TK_NULL 114 +#define TK_PRIMARY 115 +#define TK_UNIQUE 116 +#define TK_CHECK 117 +#define TK_REFERENCES 118 +#define TK_AUTOINCR 119 +#define TK_INSERT 120 +#define TK_DELETE 121 +#define TK_UPDATE 122 +#define TK_SET 123 +#define TK_DEFERRABLE 124 +#define TK_FOREIGN 125 +#define TK_DROP 126 +#define TK_UNION 127 +#define TK_ALL 128 +#define TK_EXCEPT 129 +#define TK_INTERSECT 130 +#define TK_SELECT 131 +#define TK_VALUES 132 +#define TK_DISTINCT 133 +#define TK_DOT 134 +#define TK_FROM 135 +#define TK_JOIN 136 +#define TK_USING 137 +#define TK_ORDER 138 +#define TK_GROUP 139 +#define TK_HAVING 140 +#define TK_LIMIT 141 +#define TK_WHERE 142 +#define TK_INTO 143 +#define TK_NOTHING 144 +#define TK_FLOAT 145 +#define TK_BLOB 146 +#define TK_INTEGER 147 +#define TK_VARIABLE 148 +#define TK_CASE 149 +#define TK_WHEN 150 +#define TK_THEN 151 +#define TK_ELSE 152 +#define TK_INDEX 153 +#define TK_ALTER 154 +#define TK_ADD 155 +#define TK_WINDOW 156 +#define TK_OVER 157 +#define TK_FILTER 158 +#define TK_TRUEFALSE 159 +#define TK_ISNOT 160 +#define TK_FUNCTION 161 +#define TK_COLUMN 162 +#define TK_AGG_FUNCTION 163 +#define TK_AGG_COLUMN 164 +#define TK_UMINUS 165 +#define TK_UPLUS 166 +#define TK_TRUTH 167 +#define TK_REGISTER 168 +#define TK_VECTOR 169 +#define TK_SELECT_COLUMN 170 +#define TK_IF_NULL_ROW 171 +#define TK_ASTERISK 172 +#define TK_SPAN 173 +#define TK_SPACE 174 +#define TK_ILLEGAL 175 /************** End of parse.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -14546,9 +14578,6 @@ struct BtreePayload { SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload, int flags, int seekResult); SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); -#ifndef SQLITE_OMIT_WINDOWFUNC -SQLITE_PRIVATE void sqlite3BtreeSkipNext(BtCursor*); -#endif SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int flags); SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); @@ -14906,25 +14935,25 @@ typedef struct VdbeOpList VdbeOpList; #define OP_Offset 89 /* synopsis: r[P3] = sqlite_offset(P1) */ #define OP_Column 90 /* synopsis: r[P3]=PX */ #define OP_Affinity 91 /* synopsis: affinity(r[P1@P2]) */ -#define OP_BitAnd 92 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ -#define OP_BitOr 93 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ -#define OP_ShiftLeft 94 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */ -#define OP_Add 96 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ -#define OP_Subtract 97 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ -#define OP_Multiply 98 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ -#define OP_Divide 99 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ -#define OP_Remainder 100 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ -#define OP_Concat 101 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ -#define OP_MakeRecord 102 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ -#define OP_BitNot 103 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */ -#define OP_Count 104 /* synopsis: r[P2]=count() */ -#define OP_ReadCookie 105 -#define OP_String8 106 /* same as TK_STRING, synopsis: r[P2]='P4' */ -#define OP_SetCookie 107 -#define OP_ReopenIdx 108 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenRead 109 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenWrite 110 /* synopsis: root=P2 iDb=P3 */ +#define OP_MakeRecord 92 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ +#define OP_Count 93 /* synopsis: r[P2]=count() */ +#define OP_ReadCookie 94 +#define OP_SetCookie 95 +#define OP_BitAnd 96 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ +#define OP_BitOr 97 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ +#define OP_ShiftLeft 98 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */ +#define OP_Add 100 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */ +#define OP_Subtract 101 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */ +#define OP_Multiply 102 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */ +#define OP_Divide 103 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */ +#define OP_Remainder 104 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */ +#define OP_Concat 105 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ +#define OP_ReopenIdx 106 /* synopsis: root=P2 iDb=P3 */ +#define OP_BitNot 107 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */ +#define OP_OpenRead 108 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenWrite 109 /* synopsis: root=P2 iDb=P3 */ +#define OP_String8 110 /* same as TK_STRING, synopsis: r[P2]='P4' */ #define OP_OpenDup 111 #define OP_OpenAutoindex 112 /* synopsis: nColumn=P2 */ #define OP_OpenEphemeral 113 /* synopsis: nColumn=P2 */ @@ -14955,11 +14984,11 @@ typedef struct VdbeOpList VdbeOpList; #define OP_ResetSorter 138 #define OP_CreateBtree 139 /* synopsis: r[P2]=root iDb=P1 flags=P3 */ #define OP_SqlExec 140 -#define OP_Real 141 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ -#define OP_ParseSchema 142 -#define OP_LoadAnalysis 143 -#define OP_DropTable 144 -#define OP_DropIndex 145 +#define OP_ParseSchema 141 +#define OP_LoadAnalysis 142 +#define OP_DropTable 143 +#define OP_DropIndex 144 +#define OP_Real 145 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ #define OP_DropTrigger 146 #define OP_IntegrityCk 147 #define OP_RowSetAdd 148 /* synopsis: rowset(P1)=r[P2] */ @@ -15010,14 +15039,14 @@ typedef struct VdbeOpList VdbeOpList; /* 64 */ 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10,\ /* 72 */ 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,\ /* 80 */ 0x10, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\ -/* 88 */ 0x12, 0x20, 0x00, 0x00, 0x26, 0x26, 0x26, 0x26,\ -/* 96 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\ -/* 104 */ 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 88 */ 0x12, 0x20, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,\ +/* 96 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\ +/* 104 */ 0x26, 0x26, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00,\ /* 112 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 128 */ 0x10, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10,\ -/* 136 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00,\ -/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\ +/* 136 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\ +/* 144 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\ /* 152 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ /* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\ /* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00,} @@ -16325,6 +16354,7 @@ struct sqlite3 { void (*xRollbackCallback)(void*); /* Invoked at every commit. */ void *pUpdateArg; void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); + Parse *pParse; /* Current parse */ #ifdef SQLITE_ENABLE_PREUPDATE_HOOK void *pPreUpdateArg; /* First argument to xPreUpdateCallback */ void (*xPreUpdateCallback)( /* Registered using sqlite3_preupdate_hook() */ @@ -16458,7 +16488,8 @@ struct sqlite3 { #define DBFLAG_SchemaChange 0x0001 /* Uncommitted Hash table changes */ #define DBFLAG_PreferBuiltin 0x0002 /* Preference to built-in funcs */ #define DBFLAG_Vacuum 0x0004 /* Currently in a VACUUM */ -#define DBFLAG_SchemaKnownOk 0x0008 /* Schema is known to be valid */ +#define DBFLAG_VacuumInto 0x0008 /* Currently running VACUUM INTO */ +#define DBFLAG_SchemaKnownOk 0x0010 /* Schema is known to be valid */ /* ** Bits of the sqlite3.dbOptFlags field that are used by the @@ -16466,7 +16497,7 @@ struct sqlite3 { ** selectively disable various optimizations. */ #define SQLITE_QueryFlattener 0x0001 /* Query flattening */ - /* 0x0002 available for reuse */ +#define SQLITE_WindowFunc 0x0002 /* Use xInverse for window functions */ #define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ #define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ #define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */ @@ -16584,7 +16615,6 @@ struct FuncDestructor { #define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ #define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ #define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ -#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */ #define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ /* @@ -17390,12 +17420,16 @@ struct Expr { /* ** The following are the meanings of bits in the Expr.flags field. +** Value restrictions: +** +** EP_Agg == NC_HasAgg == SF_HasAgg +** EP_Win == NC_HasWin */ #define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ -#define EP_Agg 0x000002 /* Contains one or more aggregate functions */ +#define EP_Distinct 0x000002 /* Aggregate function with DISTINCT keyword */ #define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */ #define EP_FixedCol 0x000008 /* TK_Column with a known fixed value */ -#define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */ +#define EP_Agg 0x000010 /* Contains one or more aggregate functions */ #define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */ #define EP_DblQuoted 0x000040 /* token.z was originally in "..." */ #define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */ @@ -17406,7 +17440,7 @@ struct Expr { #define EP_Skip 0x001000 /* COLLATE, AS, or UNLIKELY */ #define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */ #define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ -#define EP_Static 0x008000 /* Held in memory not obtained from malloc() */ +#define EP_Win 0x008000 /* Contains window functions */ #define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ #define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ @@ -17418,6 +17452,7 @@ struct Expr { #define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */ #define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */ #define EP_Quoted 0x4000000 /* TK_ID was originally quoted */ +#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */ /* ** The EP_Propagate mask is a set of properties that automatically propagate @@ -17657,8 +17692,9 @@ struct NameContext { ** Allowed values for the NameContext, ncFlags field. ** ** Value constraints (all checked via assert()): -** NC_HasAgg == SF_HasAgg +** NC_HasAgg == SF_HasAgg == EP_Agg ** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX +** NC_HasWin == EP_Win ** */ #define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */ @@ -17674,6 +17710,7 @@ struct NameContext { #define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */ #define NC_Complex 0x2000 /* True if a function or subquery seen */ #define NC_AllowWin 0x4000 /* Window functions are allowed here */ +#define NC_HasWin 0x8000 /* One or more window functions seen */ /* ** An instance of the following object describes a single ON CONFLICT @@ -17988,6 +18025,7 @@ struct Parse { AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ Parse *pToplevel; /* Parse structure for main program (or NULL) */ Table *pTriggerTab; /* Table triggers are being coded for */ + Parse *pParentParse; /* Parent parser if this parser is nested */ int addrCrTab; /* Address of OP_CreateBtree opcode on CREATE TABLE */ u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ u32 oldmask; /* Mask of old.* columns referenced */ @@ -18428,7 +18466,7 @@ struct TreeView { #endif /* SQLITE_DEBUG */ /* -** This object is used in varioius ways, all related to window functions +** This object is used in various ways, all related to window functions ** ** (1) A single instance of this structure is attached to the ** the Expr.pWin field for each window function in an expression tree. @@ -18443,15 +18481,18 @@ struct TreeView { ** object on a linked list attached to Select.pWinDefn. ** ** The uses (1) and (2) are really the same Window object that just happens -** to be accessible in two different ways. Use (3) is are separate objects. +** to be accessible in two different ways. Use case (3) are separate objects. */ struct Window { char *zName; /* Name of window (may be NULL) */ + char *zBase; /* Name of base window for chaining (may be NULL) */ ExprList *pPartition; /* PARTITION BY clause */ ExprList *pOrderBy; /* ORDER BY clause */ - u8 eType; /* TK_RANGE or TK_ROWS */ + u8 eFrmType; /* TK_RANGE, TK_GROUPS, TK_ROWS, or 0 */ u8 eStart; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */ u8 eEnd; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */ + u8 bImplicitFrame; /* True if frame was implicitly specified */ + u8 eExclude; /* TK_NO, TK_CURRENT, TK_TIES, TK_GROUP, or 0 */ Expr *pStart; /* Expression for " PRECEDING" */ Expr *pEnd; /* Expression for " FOLLOWING" */ Window *pNextWin; /* Next window function belonging to this SELECT */ @@ -18462,17 +18503,19 @@ struct Window { int regResult; int csrApp; /* Function cursor (used by min/max) */ int regApp; /* Function register (also used by min/max) */ - int regPart; /* First in a set of registers holding PARTITION BY - ** and ORDER BY values for the window */ + int regPart; /* Array of registers for PARTITION BY values */ Expr *pOwner; /* Expression object this window is attached to */ int nBufferCol; /* Number of columns in buffer table */ int iArgCol; /* Offset of first argument for this function */ + int regOne; /* Register containing constant value 1 */ + int regStartRowid; + int regEndRowid; }; #ifndef SQLITE_OMIT_WINDOWFUNC SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3*, Window*); SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p); -SQLITE_PRIVATE Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*); +SQLITE_PRIVATE Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8); SQLITE_PRIVATE void sqlite3WindowAttach(Parse*, Expr*, Window*); SQLITE_PRIVATE int sqlite3WindowCompare(Parse*, Window*, Window*); SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse*, Window*); @@ -18483,6 +18526,8 @@ SQLITE_PRIVATE void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*); SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p); SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p); SQLITE_PRIVATE void sqlite3WindowFunctions(void); +SQLITE_PRIVATE void sqlite3WindowChain(Parse*, Window*, Window*); +SQLITE_PRIVATE Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprList*, Token*); #else # define sqlite3WindowDelete(a,b) # define sqlite3WindowFunctions() @@ -18712,6 +18757,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView*, const Window*, u8); SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*); SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); +SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3*,int); SQLITE_PRIVATE void sqlite3Dequote(char*); SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*); SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*); @@ -20135,11 +20181,11 @@ struct sqlite3_value { #define MEM_Real 0x0008 /* Value is a real number */ #define MEM_Blob 0x0010 /* Value is a BLOB */ #define MEM_AffMask 0x001f /* Mask of affinity bits */ -/* Available 0x0020 */ +#define MEM_FromBind 0x0020 /* Value originates from sqlite3_bind() */ /* Available 0x0040 */ #define MEM_Undefined 0x0080 /* Value is undefined */ #define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */ -#define MEM_TypeMask 0xc1ff /* Mask of type bits */ +#define MEM_TypeMask 0xc1df /* Mask of type bits */ /* Whenever Mem contains a valid string or blob representation, one of @@ -20171,6 +20217,12 @@ struct sqlite3_value { #define MemSetTypeFlag(p, f) \ ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f) +/* +** True if Mem X is a NULL-nochng type. +*/ +#define MemNullNochng(X) \ + ((X)->flags==(MEM_Null|MEM_Zero) && (X)->n==0 && (X)->u.nZero==0) + /* ** Return true if a memory cell is not marked as invalid. This macro ** is for use inside assert() statements only. @@ -27120,6 +27172,9 @@ SQLITE_PRIVATE void sqlite3OomFault(sqlite3 *db){ db->u1.isInterrupted = 1; } db->lookaside.bDisable++; + if( db->pParse ){ + db->pParse->rc = SQLITE_NOMEM_BKPT; + } } } @@ -27313,7 +27368,8 @@ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ static void setStrAccumError(StrAccum *p, u8 eError){ assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG ); p->accError = eError; - p->nAlloc = 0; + if( p->mxAlloc ) sqlite3_str_reset(p); + if( eError==SQLITE_TOOBIG ) sqlite3ErrorToParser(p->db, eError); } /* @@ -27343,6 +27399,7 @@ static char *getTextArg(PrintfArguments *p){ */ static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){ char *z; + if( pAccum->accError ) return 0; if( n>pAccum->nAlloc && n>pAccum->mxAlloc ){ setStrAccumError(pAccum, SQLITE_TOOBIG); return 0; @@ -28062,9 +28119,8 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ return 0; } if( p->mxAlloc==0 ){ - N = p->nAlloc - p->nChar - 1; setStrAccumError(p, SQLITE_TOOBIG); - return N; + return p->nAlloc - p->nChar - 1; }else{ char *zOld = isMalloced(p) ? p->zText : 0; i64 szNew = p->nChar; @@ -28136,7 +28192,7 @@ SQLITE_API void sqlite3_str_append(sqlite3_str *p, const char *z, int N){ assert( z!=0 || N==0 ); assert( p->zText!=0 || p->nChar==0 || p->accError ); assert( N>=0 ); - assert( p->accError==0 || p->nAlloc==0 ); + assert( p->accError==0 || p->nAlloc==0 || p->mxAlloc==0 ); if( p->nChar+N >= p->nAlloc ){ enlargeAndAppend(p,z,N); }else if( N ){ @@ -28769,24 +28825,62 @@ SQLITE_PRIVATE void sqlite3TreeViewBound( ** Generate a human-readable explanation for a Window object */ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){ + int nElement = 0; + if( pWin->pFilter ){ + sqlite3TreeViewItem(pView, "FILTER", 1); + sqlite3TreeViewExpr(pView, pWin->pFilter, 0); + sqlite3TreeViewPop(pView); + } pView = sqlite3TreeViewPush(pView, more); if( pWin->zName ){ - sqlite3TreeViewLine(pView, "OVER %s", pWin->zName); + sqlite3TreeViewLine(pView, "OVER %s (%p)", pWin->zName, pWin); }else{ - sqlite3TreeViewLine(pView, "OVER"); + sqlite3TreeViewLine(pView, "OVER (%p)", pWin); + } + if( pWin->zBase ) nElement++; + if( pWin->pOrderBy ) nElement++; + if( pWin->eFrmType ) nElement++; + if( pWin->eExclude ) nElement++; + if( pWin->zBase ){ + sqlite3TreeViewPush(pView, (--nElement)>0); + sqlite3TreeViewLine(pView, "window: %s", pWin->zBase); + sqlite3TreeViewPop(pView); } if( pWin->pPartition ){ - sqlite3TreeViewExprList(pView, pWin->pPartition, 1, "PARTITION-BY"); + sqlite3TreeViewExprList(pView, pWin->pPartition, nElement>0,"PARTITION-BY"); } if( pWin->pOrderBy ){ - sqlite3TreeViewExprList(pView, pWin->pOrderBy, 1, "ORDER-BY"); + sqlite3TreeViewExprList(pView, pWin->pOrderBy, (--nElement)>0, "ORDER-BY"); } - if( pWin->eType ){ - sqlite3TreeViewItem(pView, pWin->eType==TK_RANGE ? "RANGE" : "ROWS", 0); + if( pWin->eFrmType ){ + char zBuf[30]; + const char *zFrmType = "ROWS"; + if( pWin->eFrmType==TK_RANGE ) zFrmType = "RANGE"; + if( pWin->eFrmType==TK_GROUPS ) zFrmType = "GROUPS"; + sqlite3_snprintf(sizeof(zBuf),zBuf,"%s%s",zFrmType, + pWin->bImplicitFrame ? " (implied)" : ""); + sqlite3TreeViewItem(pView, zBuf, (--nElement)>0); sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1); sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0); sqlite3TreeViewPop(pView); } + if( pWin->eExclude ){ + char zBuf[30]; + const char *zExclude; + switch( pWin->eExclude ){ + case TK_NO: zExclude = "NO OTHERS"; break; + case TK_CURRENT: zExclude = "CURRENT ROW"; break; + case TK_GROUP: zExclude = "GROUP"; break; + case TK_TIES: zExclude = "TIES"; break; + default: + sqlite3_snprintf(sizeof(zBuf),zBuf,"invalid(%d)", pWin->eExclude); + zExclude = zBuf; + break; + } + sqlite3TreeViewPush(pView, 0); + sqlite3TreeViewLine(pView, "EXCLUDE %s", zExclude); + sqlite3TreeViewPop(pView); + } sqlite3TreeViewPop(pView); } #endif /* SQLITE_OMIT_WINDOWFUNC */ @@ -29766,11 +29860,11 @@ SQLITE_PRIVATE u32 sqlite3Utf8Read( ** encoding, or if *pMem does not contain a string value. */ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ - int len; /* Maximum length of output string in bytes */ - unsigned char *zOut; /* Output buffer */ - unsigned char *zIn; /* Input iterator */ - unsigned char *zTerm; /* End of input */ - unsigned char *z; /* Output iterator */ + sqlite3_int64 len; /* Maximum length of output string in bytes */ + unsigned char *zOut; /* Output buffer */ + unsigned char *zIn; /* Input iterator */ + unsigned char *zTerm; /* End of input */ + unsigned char *z; /* Output iterator */ unsigned int c; assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); @@ -29819,14 +29913,14 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desired ** nul-terminator. */ pMem->n &= ~1; - len = pMem->n * 2 + 1; + len = 2 * (sqlite3_int64)pMem->n + 1; }else{ /* When converting from UTF-8 to UTF-16 the maximum growth is caused ** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16 ** character. Two bytes are required in the output buffer for the ** nul-terminator. */ - len = pMem->n * 2 + 2; + len = 2 * (sqlite3_int64)pMem->n + 2; } /* Set zIn to point at the start of the input buffer and zTerm to point 1 @@ -30133,15 +30227,23 @@ SQLITE_PRIVATE void sqlite3Coverage(int x){ #endif /* -** Give a callback to the test harness that can be used to simulate faults -** in places where it is difficult or expensive to do so purely by means -** of inputs. +** Calls to sqlite3FaultSim() are used to simulate a failure during testing, +** or to bypass normal error detection during testing in order to let +** execute proceed futher downstream. ** -** The intent of the integer argument is to let the fault simulator know -** which of multiple sqlite3FaultSim() calls has been hit. +** In deployment, sqlite3FaultSim() *always* return SQLITE_OK (0). The +** sqlite3FaultSim() function only returns non-zero during testing. ** -** Return whatever integer value the test callback returns, or return -** SQLITE_OK if no test callback is installed. +** During testing, if the test harness has set a fault-sim callback using +** a call to sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL), then +** each call to sqlite3FaultSim() is relayed to that application-supplied +** callback and the integer return value form the application-supplied +** callback is returned by sqlite3FaultSim(). +** +** The integer argument to sqlite3FaultSim() is a code to identify which +** sqlite3FaultSim() instance is being invoked. Each call to sqlite3FaultSim() +** should have a unique code. To prevent legacy testing applications from +** breaking, the codes should not be changed or reused. */ #ifndef SQLITE_UNTESTABLE SQLITE_PRIVATE int sqlite3FaultSim(int iTest){ @@ -30326,6 +30428,19 @@ SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ } } +/* +** If database connection db is currently parsing SQL, then transfer +** error code errCode to that parser if the parser has not already +** encountered some other kind of error. +*/ +SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3 *db, int errCode){ + Parse *pParse; + if( db==0 || (pParse = db->pParse)==0 ) return errCode; + pParse->rc = errCode; + pParse->nErr++; + return errCode; +} + /* ** Convert an SQL-style quoted string into a normal string by removing ** the quote characters. The conversion is done in-place. If the @@ -31677,7 +31792,7 @@ SQLITE_PRIVATE VList *sqlite3VListAdd( assert( pIn==0 || pIn[0]>=3 ); /* Verify ok to add new elements */ if( pIn==0 || pIn[1]+nInt > pIn[0] ){ /* Enlarge the allocation */ - int nAlloc = (pIn ? pIn[0]*2 : 10) + nInt; + sqlite3_int64 nAlloc = (pIn ? 2*(sqlite3_int64)pIn[0] : 10) + nInt; VList *pOut = sqlite3DbRealloc(db, pIn, nAlloc*sizeof(int)); if( pOut==0 ) return pIn; if( pIn==0 ) pOut[1] = 2; @@ -31883,7 +31998,7 @@ static HashElem *findElementWithHash( unsigned int *pHash /* Write the hash value here */ ){ HashElem *elem; /* Used to loop thru the element list */ - int count; /* Number of elements left to test */ + unsigned int count; /* Number of elements left to test */ unsigned int h; /* The computed hash */ static HashElem nullElement = { 0, 0, 0, 0 }; @@ -31931,8 +32046,8 @@ static void removeElementGivenHash( if( pEntry->chain==elem ){ pEntry->chain = elem->next; } + assert( pEntry->count>0 ); pEntry->count--; - assert( pEntry->count>=0 ); } sqlite3_free( elem ); pH->count--; @@ -32107,25 +32222,25 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 89 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"), /* 90 */ "Column" OpHelp("r[P3]=PX"), /* 91 */ "Affinity" OpHelp("affinity(r[P1@P2])"), - /* 92 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), - /* 93 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), - /* 94 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"), - /* 96 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), - /* 97 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), - /* 98 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), - /* 99 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), - /* 100 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), - /* 101 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), - /* 102 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), - /* 103 */ "BitNot" OpHelp("r[P2]= ~r[P1]"), - /* 104 */ "Count" OpHelp("r[P2]=count()"), - /* 105 */ "ReadCookie" OpHelp(""), - /* 106 */ "String8" OpHelp("r[P2]='P4'"), - /* 107 */ "SetCookie" OpHelp(""), - /* 108 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), - /* 109 */ "OpenRead" OpHelp("root=P2 iDb=P3"), - /* 110 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), + /* 92 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), + /* 93 */ "Count" OpHelp("r[P2]=count()"), + /* 94 */ "ReadCookie" OpHelp(""), + /* 95 */ "SetCookie" OpHelp(""), + /* 96 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), + /* 97 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), + /* 98 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"), + /* 100 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"), + /* 101 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"), + /* 102 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"), + /* 103 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"), + /* 104 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"), + /* 105 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), + /* 106 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), + /* 107 */ "BitNot" OpHelp("r[P2]= ~r[P1]"), + /* 108 */ "OpenRead" OpHelp("root=P2 iDb=P3"), + /* 109 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), + /* 110 */ "String8" OpHelp("r[P2]='P4'"), /* 111 */ "OpenDup" OpHelp(""), /* 112 */ "OpenAutoindex" OpHelp("nColumn=P2"), /* 113 */ "OpenEphemeral" OpHelp("nColumn=P2"), @@ -32156,11 +32271,11 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 138 */ "ResetSorter" OpHelp(""), /* 139 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"), /* 140 */ "SqlExec" OpHelp(""), - /* 141 */ "Real" OpHelp("r[P2]=P4"), - /* 142 */ "ParseSchema" OpHelp(""), - /* 143 */ "LoadAnalysis" OpHelp(""), - /* 144 */ "DropTable" OpHelp(""), - /* 145 */ "DropIndex" OpHelp(""), + /* 141 */ "ParseSchema" OpHelp(""), + /* 142 */ "LoadAnalysis" OpHelp(""), + /* 143 */ "DropTable" OpHelp(""), + /* 144 */ "DropIndex" OpHelp(""), + /* 145 */ "Real" OpHelp("r[P2]=P4"), /* 146 */ "DropTrigger" OpHelp(""), /* 147 */ "IntegrityCk" OpHelp(""), /* 148 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), @@ -49016,9 +49131,7 @@ static void pcache1FreePage(PgHdr1 *p){ ** exists, this function falls back to sqlite3Malloc(). */ SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){ - /* During rebalance operations on a corrupt database file, it is sometimes - ** (rarely) possible to overread the temporary page buffer by a few bytes. - ** Enlarge the allocation slightly so that this does not cause problems. */ + assert( sz<=65536+8 ); /* These allocations are never very large */ return pcache1Alloc(sz); } @@ -51302,6 +51415,9 @@ static const unsigned char aJournalMagic[] = { SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){ if( pPager->fd->pMethods==0 ) return 0; if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; +#ifdef SQLITE_HAS_CODEC + if( pPager->xCodec!=0 ) return 0; +#endif #ifndef SQLITE_OMIT_WAL if( pPager->pWal ){ u32 iRead = 0; @@ -54251,8 +54367,14 @@ SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nR rc = sqlite3OsFileSize(pPager->fd, &nByte); } if( rc==SQLITE_OK ){ - pNew = (char *)sqlite3PageMalloc(pageSize); - if( !pNew ) rc = SQLITE_NOMEM_BKPT; + /* 8 bytes of zeroed overrun space is sufficient so that the b-tree + * cell header parser will never run off the end of the allocation */ + pNew = (char *)sqlite3PageMalloc(pageSize+8); + if( !pNew ){ + rc = SQLITE_NOMEM_BKPT; + }else{ + memset(pNew+pageSize, 0, 8); + } } if( rc==SQLITE_OK ){ @@ -57633,8 +57755,12 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i */ pPg->flags &= ~PGHDR_NEED_SYNC; pPgOld = sqlite3PagerLookup(pPager, pgno); - assert( !pPgOld || pPgOld->nRef==1 ); + assert( !pPgOld || pPgOld->nRef==1 || CORRUPT_DB ); if( pPgOld ){ + if( pPgOld->nRef>1 ){ + sqlite3PagerUnrefNotNull(pPgOld); + return SQLITE_CORRUPT_BKPT; + } pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC); if( pPager->tempFile ){ /* Do not discard pages from an in-memory database since we might @@ -58162,7 +58288,7 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pS */ SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager){ assert( pPager->pWal ); - return sqlite3WalSnapshotUnlock(pPager->pWal); + sqlite3WalSnapshotUnlock(pPager->pWal); } #endif /* SQLITE_ENABLE_SNAPSHOT */ @@ -58763,7 +58889,7 @@ static SQLITE_NOINLINE int walIndexPageRealloc( /* Enlarge the pWal->apWiData[] array if required */ if( pWal->nWiData<=iPage ){ - int nByte = sizeof(u32*)*(iPage+1); + sqlite3_int64 nByte = sizeof(u32*)*(iPage+1); volatile u32 **apNew; apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte); if( !apNew ){ @@ -58867,6 +58993,7 @@ static void walChecksumBytes( assert( nByte>=8 ); assert( (nByte&0x00000007)==0 ); + assert( nByte<=65536 ); if( nativeCksum ){ do { @@ -59174,6 +59301,7 @@ static void walCleanupHash(Wal *pWal){ int iLimit = 0; /* Zero values greater than this */ int nByte; /* Number of bytes to zero in aPgno[] */ int i; /* Used to iterate through aHash[] */ + int rc; /* Return code form walHashGet() */ assert( pWal->writeLock ); testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE-1 ); @@ -59184,11 +59312,12 @@ static void walCleanupHash(Wal *pWal){ /* Obtain pointers to the hash-table and page-number array containing ** the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed - ** that the page said hash-table and array reside on is already mapped. + ** that the page said hash-table and array reside on is already mapped.(1) */ assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) ); assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] ); - walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc); + rc = walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc); + if( NEVER(rc) ) return; /* Defense-in-depth, in case (1) above is wrong */ /* Zero all hash-table entries that correspond to frame numbers greater ** than pWal->hdr.mxFrame. @@ -59802,7 +59931,7 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ WalIterator *p; /* Return value */ int nSegment; /* Number of segments to merge */ u32 iLast; /* Last frame in log */ - int nByte; /* Number of bytes to allocate */ + sqlite3_int64 nByte; /* Number of bytes to allocate */ int i; /* Iterator variable */ ht_slot *aTmp; /* Temp space used by merge-sort */ int rc = SQLITE_OK; /* Return Code */ @@ -62338,7 +62467,7 @@ struct MemPage { u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */ u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */ u16 cellOffset; /* Index in aData of first cell pointer */ - u16 nFree; /* Number of free bytes on the page */ + int nFree; /* Number of free bytes on the page. -1 for unknown */ u16 nCell; /* Number of cells on this page, local and ovfl */ u16 maskPage; /* Mask for page offset */ u16 aiOvfl[4]; /* Insert the i-th overflow cell before the aiOvfl-th @@ -63892,14 +64021,18 @@ moveto_done: */ static int btreeRestoreCursorPosition(BtCursor *pCur){ int rc; - int skipNext; + int skipNext = 0; assert( cursorOwnsBtShared(pCur) ); assert( pCur->eState>=CURSOR_REQUIRESEEK ); if( pCur->eState==CURSOR_FAULT ){ return pCur->skipNext; } pCur->eState = CURSOR_INVALID; - rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext); + if( sqlite3FaultSim(410) ){ + rc = SQLITE_IOERR; + }else{ + rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext); + } if( rc==SQLITE_OK ){ sqlite3_free(pCur->pKey); pCur->pKey = 0; @@ -64480,7 +64613,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ hdr = pPage->hdrOffset; cellOffset = pPage->cellOffset; nCell = pPage->nCell; - assert( nCell==get2byte(&data[hdr+3]) ); + assert( nCell==get2byte(&data[hdr+3]) || CORRUPT_DB ); iCellFirst = cellOffset + 2*nCell; usableSize = pPage->pBt->usableSize; @@ -64491,11 +64624,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ ** reconstruct the entire page. */ if( (int)data[hdr+7]<=nMaxFrag ){ int iFree = get2byte(&data[hdr+1]); - - /* If the initial freeblock offset were out of bounds, that would - ** have been detected by btreeInitPage() when it was computing the - ** number of free bytes on the page. */ - assert( iFree<=usableSize-4 ); + if( iFree>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage); if( iFree ){ int iFree2 = get2byte(&data[iFree]); if( iFree2>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage); @@ -64514,7 +64643,10 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage); memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz)); sz += sz2; + }else if( iFree+sz>usableSize ){ + return SQLITE_CORRUPT_PAGE(pPage); } + cbrk = top+sz; assert( cbrk+(iFree-top) <= usableSize ); memmove(&data[cbrk], &data[top], iFree-top); @@ -64565,6 +64697,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ data[hdr+7] = 0; defragment_out: + assert( pPage->nFree>=0 ); if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){ return SQLITE_CORRUPT_PAGE(pPage); } @@ -64592,16 +64725,16 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ ** causes the fragmentation count to exceed 60. */ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ - const int hdr = pPg->hdrOffset; - u8 * const aData = pPg->aData; - int iAddr = hdr + 1; - int pc = get2byte(&aData[iAddr]); - int x; - int usableSize = pPg->pBt->usableSize; - int size; /* Size of the free slot */ + const int hdr = pPg->hdrOffset; /* Offset to page header */ + u8 * const aData = pPg->aData; /* Page data */ + int iAddr = hdr + 1; /* Address of ptr to pc */ + int pc = get2byte(&aData[iAddr]); /* Address of a free slot */ + int x; /* Excess size of the slot */ + int maxPC = pPg->pBt->usableSize - nByte; /* Max address for a usable slot */ + int size; /* Size of the free slot */ assert( pc>0 ); - while( pc<=usableSize-4 ){ + while( pc<=maxPC ){ /* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each ** freeblock form a big-endian integer which is the size of the freeblock ** in bytes, including the 4-byte header. */ @@ -64609,10 +64742,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ if( (x = size - nByte)>=0 ){ testcase( x==4 ); testcase( x==3 ); - if( size+pc > usableSize ){ - *pRc = SQLITE_CORRUPT_PAGE(pPg); - return 0; - }else if( x<4 ){ + if( x<4 ){ /* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total ** number of bytes in fragments may not exceed 60. */ if( aData[hdr+7]>57 ) return 0; @@ -64621,21 +64751,31 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ ** fragmented bytes within the page. */ memcpy(&aData[iAddr], &aData[pc], 2); aData[hdr+7] += (u8)x; + }else if( x+pc > maxPC ){ + /* This slot extends off the end of the usable part of the page */ + *pRc = SQLITE_CORRUPT_PAGE(pPg); + return 0; }else{ /* The slot remains on the free-list. Reduce its size to account - ** for the portion used by the new allocation. */ + ** for the portion used by the new allocation. */ put2byte(&aData[pc+2], x); } return &aData[pc + x]; } iAddr = pc; pc = get2byte(&aData[pc]); - if( pcmaxPC+nByte-4 ){ + /* The free slot chain extends off the end of the page */ *pRc = SQLITE_CORRUPT_PAGE(pPg); } - return 0; } @@ -64685,9 +64825,9 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ } } - /* If there is enough space between gap and top for one more cell pointer - ** array entry offset, and if the freelist is not empty, then search the - ** freelist looking for a free slot big enough to satisfy the request. + /* If there is enough space between gap and top for one more cell pointer, + ** and if the freelist is not empty, then search the + ** freelist looking for a slot big enough to satisfy the request. */ testcase( gap+2==top ); testcase( gap+1==top ); @@ -64709,6 +64849,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ testcase( gap+2+nByte==top ); if( gap+2+nByte>top ){ assert( pPage->nCell>0 || CORRUPT_DB ); + assert( pPage->nFree>=0 ); rc = defragmentPage(pPage, MIN(4, pPage->nFree - (2+nByte))); if( rc ) return rc; top = get2byteNotZero(&data[hdr+5]); @@ -64717,7 +64858,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ /* Allocate memory from the gap in between the cell pointer array - ** and the cell content area. The btreeInitPage() call has already + ** and the cell content area. The btreeComputeFreeSpace() call has already ** validated the freelist. Given that the freelist is valid, there ** is no way that the allocation can extend off the end of the page. ** The assert() below verifies the previous sentence. @@ -64736,7 +64877,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ ** ** Adjacent freeblocks are coalesced. ** -** Note that even though the freeblock list was checked by btreeInitPage(), +** Even though the freeblock list was checked by btreeComputeFreeSpace(), ** that routine will not detect overlap between cells or freeblocks. Nor ** does it detect cells or freeblocks that encrouch into the reserved bytes ** at the end of the page. So do additional corruption checks inside this @@ -64898,21 +65039,14 @@ static int decodeFlags(MemPage *pPage, int flagByte){ } /* -** Initialize the auxiliary information for a disk block. -** -** Return SQLITE_OK on success. If we see that the page does -** not contain a well-formed database page, then return -** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not -** guarantee that the page is well-formed. It only shows that -** we failed to detect any corruption. +** Compute the amount of freespace on the page. In other words, fill +** in the pPage->nFree field. */ -static int btreeInitPage(MemPage *pPage){ +static int btreeComputeFreeSpace(MemPage *pPage){ int pc; /* Address of a freeblock within pPage->aData[] */ u8 hdr; /* Offset to beginning of page header */ u8 *data; /* Equal to pPage->aData */ - BtShared *pBt; /* The main btree structure */ int usableSize; /* Amount of usable space on each page */ - u16 cellOffset; /* Offset from start of page to first cell pointer */ int nFree; /* Number of unused bytes on the page */ int top; /* First byte of the cell content area */ int iCellFirst; /* First allowable cell or freeblock offset */ @@ -64924,71 +65058,18 @@ static int btreeInitPage(MemPage *pPage){ assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) ); assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) ); - assert( pPage->isInit==0 ); + assert( pPage->isInit==1 ); + assert( pPage->nFree<0 ); - pBt = pPage->pBt; + usableSize = pPage->pBt->usableSize; hdr = pPage->hdrOffset; data = pPage->aData; - /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating - ** the b-tree page type. */ - if( decodeFlags(pPage, data[hdr]) ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); - pPage->maskPage = (u16)(pBt->pageSize - 1); - pPage->nOverflow = 0; - usableSize = pBt->usableSize; - pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize; - pPage->aDataEnd = &data[usableSize]; - pPage->aCellIdx = &data[cellOffset]; - pPage->aDataOfst = &data[pPage->childPtrSize]; /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates ** the start of the cell content area. A zero value for this integer is ** interpreted as 65536. */ top = get2byteNotZero(&data[hdr+5]); - /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the - ** number of cells on the page. */ - pPage->nCell = get2byte(&data[hdr+3]); - if( pPage->nCell>MX_CELL(pBt) ){ - /* To many cells for a single page. The page must be corrupt */ - return SQLITE_CORRUPT_PAGE(pPage); - } - testcase( pPage->nCell==MX_CELL(pBt) ); - /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only - ** possible for a root page of a table that contains no rows) then the - ** offset to the cell content area will equal the page size minus the - ** bytes of reserved space. */ - assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB ); - - /* A malformed database page might cause us to read past the end - ** of page when parsing a cell. - ** - ** The following block of code checks early to see if a cell extends - ** past the end of a page boundary and causes SQLITE_CORRUPT to be - ** returned if it does. - */ - iCellFirst = cellOffset + 2*pPage->nCell; + iCellFirst = hdr + 8 + pPage->childPtrSize + 2*pPage->nCell; iCellLast = usableSize - 4; - if( pBt->db->flags & SQLITE_CellSizeCk ){ - int i; /* Index into the cell pointer array */ - int sz; /* Size of a cell */ - - if( !pPage->leaf ) iCellLast--; - for(i=0; inCell; i++){ - pc = get2byteAligned(&data[cellOffset+i*2]); - testcase( pc==iCellFirst ); - testcase( pc==iCellLast ); - if( pciCellLast ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - sz = pPage->xCellSize(pPage, &data[pc]); - testcase( pc+sz==usableSize ); - if( pc+sz>usableSize ){ - return SQLITE_CORRUPT_PAGE(pPage); - } - } - if( !pPage->leaf ) iCellLast++; - } /* Compute the total free space on the page ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the @@ -65036,7 +65117,100 @@ static int btreeInitPage(MemPage *pPage){ return SQLITE_CORRUPT_PAGE(pPage); } pPage->nFree = (u16)(nFree - iCellFirst); + return SQLITE_OK; +} + +/* +** Do additional sanity check after btreeInitPage() if +** PRAGMA cell_size_check=ON +*/ +static SQLITE_NOINLINE int btreeCellSizeCheck(MemPage *pPage){ + int iCellFirst; /* First allowable cell or freeblock offset */ + int iCellLast; /* Last possible cell or freeblock offset */ + int i; /* Index into the cell pointer array */ + int sz; /* Size of a cell */ + int pc; /* Address of a freeblock within pPage->aData[] */ + u8 *data; /* Equal to pPage->aData */ + int usableSize; /* Maximum usable space on the page */ + int cellOffset; /* Start of cell content area */ + + iCellFirst = pPage->cellOffset + 2*pPage->nCell; + usableSize = pPage->pBt->usableSize; + iCellLast = usableSize - 4; + data = pPage->aData; + cellOffset = pPage->cellOffset; + if( !pPage->leaf ) iCellLast--; + for(i=0; inCell; i++){ + pc = get2byteAligned(&data[cellOffset+i*2]); + testcase( pc==iCellFirst ); + testcase( pc==iCellLast ); + if( pciCellLast ){ + return SQLITE_CORRUPT_PAGE(pPage); + } + sz = pPage->xCellSize(pPage, &data[pc]); + testcase( pc+sz==usableSize ); + if( pc+sz>usableSize ){ + return SQLITE_CORRUPT_PAGE(pPage); + } + } + return SQLITE_OK; +} + +/* +** Initialize the auxiliary information for a disk block. +** +** Return SQLITE_OK on success. If we see that the page does +** not contain a well-formed database page, then return +** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not +** guarantee that the page is well-formed. It only shows that +** we failed to detect any corruption. +*/ +static int btreeInitPage(MemPage *pPage){ + u8 *data; /* Equal to pPage->aData */ + BtShared *pBt; /* The main btree structure */ + + assert( pPage->pBt!=0 ); + assert( pPage->pBt->db!=0 ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); + assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) ); + assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) ); + assert( pPage->isInit==0 ); + + pBt = pPage->pBt; + data = pPage->aData + pPage->hdrOffset; + /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating + ** the b-tree page type. */ + if( decodeFlags(pPage, data[0]) ){ + return SQLITE_CORRUPT_PAGE(pPage); + } + assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); + pPage->maskPage = (u16)(pBt->pageSize - 1); + pPage->nOverflow = 0; + pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize; + pPage->aCellIdx = data + pPage->childPtrSize + 8; + pPage->aDataEnd = pPage->aData + pBt->usableSize; + pPage->aDataOfst = pPage->aData + pPage->childPtrSize; + /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the + ** number of cells on the page. */ + pPage->nCell = get2byte(&data[3]); + if( pPage->nCell>MX_CELL(pBt) ){ + /* To many cells for a single page. The page must be corrupt */ + return SQLITE_CORRUPT_PAGE(pPage); + } + testcase( pPage->nCell==MX_CELL(pBt) ); + /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only + ** possible for a root page of a table that contains no rows) then the + ** offset to the cell content area will equal the page size minus the + ** bytes of reserved space. */ + assert( pPage->nCell>0 + || get2byteNotZero(&data[5])==(int)pBt->usableSize + || CORRUPT_DB ); + pPage->nFree = -1; /* Indicate that this value is yet uncomputed */ pPage->isInit = 1; + if( pBt->db->flags & SQLITE_CellSizeCk ){ + return btreeCellSizeCheck(pPage); + } return SQLITE_OK; } @@ -65179,19 +65353,18 @@ static int getAndInitPage( if( pgno>btreePagecount(pBt) ){ rc = SQLITE_CORRUPT_BKPT; - goto getAndInitPage_error; + goto getAndInitPage_error1; } rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly); if( rc ){ - goto getAndInitPage_error; + goto getAndInitPage_error1; } *ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage); if( (*ppPage)->isInit==0 ){ btreePageFromDbPage(pDbPage, pgno, pBt); rc = btreeInitPage(*ppPage); if( rc!=SQLITE_OK ){ - releasePage(*ppPage); - goto getAndInitPage_error; + goto getAndInitPage_error2; } } assert( (*ppPage)->pgno==pgno ); @@ -65201,12 +65374,13 @@ static int getAndInitPage( ** compatible with the root page. */ if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){ rc = SQLITE_CORRUPT_PGNO(pgno); - releasePage(*ppPage); - goto getAndInitPage_error; + goto getAndInitPage_error2; } return SQLITE_OK; -getAndInitPage_error: +getAndInitPage_error2: + releasePage(*ppPage); +getAndInitPage_error1: if( pCur ){ pCur->iPage--; pCur->pPage = pCur->apPage[pCur->iPage]; @@ -68287,23 +68461,6 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ return rc; } -/* -** This function is a no-op if cursor pCur does not point to a valid row. -** Otherwise, if pCur is valid, configure it so that the next call to -** sqlite3BtreeNext() is a no-op. -*/ -#ifndef SQLITE_OMIT_WINDOWFUNC -SQLITE_PRIVATE void sqlite3BtreeSkipNext(BtCursor *pCur){ - /* We believe that the cursor must always be in the valid state when - ** this routine is called, but the proof is difficult, so we add an - ** ALWaYS() test just in case we are wrong. */ - if( ALWAYS(pCur->eState==CURSOR_VALID) ){ - pCur->eState = CURSOR_SKIPNEXT; - pCur->skipNext = 1; - } -} -#endif /* SQLITE_OMIT_WINDOWFUNC */ - /* Move the cursor to the last entry in the table. Return SQLITE_OK ** on success. Set *pRes to 0 if the cursor actually points to something ** or set *pRes to 1 if the table is empty. @@ -68569,7 +68726,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( sqlite3_free(pCellKey); goto moveto_finish; } - c = xRecordCompare(nCell, pCellKey, pIdxKey); + c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey); sqlite3_free(pCellKey); } assert( @@ -69201,13 +69358,15 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ MemPage *pPage1 = pBt->pPage1; /* Local reference to page 1 */ MemPage *pPage; /* Page being freed. May be NULL. */ int rc; /* Return Code */ - int nFree; /* Initial number of pages on free-list */ + u32 nFree; /* Initial number of pages on free-list */ assert( sqlite3_mutex_held(pBt->mutex) ); assert( CORRUPT_DB || iPage>1 ); assert( !pMemPage || pMemPage->pgno==iPage ); - if( iPage<2 ) return SQLITE_CORRUPT_BKPT; + if( iPage<2 || iPage>pBt->nPage ){ + return SQLITE_CORRUPT_BKPT; + } if( pMemPage ){ pPage = pMemPage; sqlite3PagerRef(pPage->pDbPage); @@ -69618,6 +69777,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ assert( CORRUPT_DB || sz==cellSize(pPage, idx) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( pPage->nFree>=0 ); data = pPage->aData; ptr = &pPage->aCellIdx[2*idx]; pc = get2byte(ptr); @@ -69688,6 +69848,7 @@ static void insertCell( ** might be less than 8 (leaf-size + pointer) on the interior node. Hence ** the term after the || in the following assert(). */ assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) ); + assert( pPage->nFree>=0 ); if( pPage->nOverflow || sz+2>pPage->nFree ){ if( pTemp ){ memcpy(pTemp, pCell, sz); @@ -69745,7 +69906,7 @@ static void insertCell( pPage->nCell++; /* increment the cell count */ if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++; - assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell ); + assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell || CORRUPT_DB ); #ifndef SQLITE_OMIT_AUTOVACUUM if( pPage->pBt->autoVacuum ){ /* The cell may contain a pointer to an overflow page. If so, write @@ -69832,8 +69993,13 @@ static void insertCell( ** are used and they point to the leaf pages only, and the ixNx value are: ** ** ixNx[0] = Number of cells in Child-1. -** ixNx[1] = Number of cells in Child-1 and Child-2 + 1 for 1st divider. -** ixNx[2] = Number of cells in Child-1 and Child-2 + both divider cells +** ixNx[1] = Number of cells in Child-1 and Child-2. +** ixNx[2] = Total number of cells. +** +** Sometimes when deleting, a child page can have zero cells. In those +** cases, ixNx[] entries with higher indexes, and the corresponding apEnd[] +** entries, shift down. The end result is that each ixNx[] entry should +** be larger than the previous */ typedef struct CellArray CellArray; struct CellArray { @@ -70162,8 +70328,9 @@ static int editPage( int iCell = (iOld + pPg->aiOvfl[i]) - iNew; if( iCell>=0 && iCellaCellIdx[iCell * 2]; - assert( nCell>=iCell ); - memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2); + if( nCell>iCell ){ + memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2); + } nCell++; if( pageInsertArray( pPg, pBegin, &pData, pCellptr, @@ -70239,8 +70406,10 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( sqlite3PagerIswriteable(pParent->pDbPage) ); assert( pPage->nOverflow==1 ); - + if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT; /* dbfuzz001.test */ + assert( pPage->nFree>=0 ); + assert( pParent->nFree>=0 ); /* Allocate a new page. This page will become the right-sibling of ** pPage. Make the parent page writable, so that the new divider cell @@ -70410,6 +70579,7 @@ static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){ */ pTo->isInit = 0; rc = btreeInitPage(pTo); + if( rc==SQLITE_OK ) rc = btreeComputeFreeSpace(pTo); if( rc!=SQLITE_OK ){ *pRC = rc; return; @@ -70518,6 +70688,7 @@ static int balance_nonroot( if( !aOvflSpace ){ return SQLITE_NOMEM_BKPT; } + assert( pParent->nFree>=0 ); /* Find the sibling pages to balance. Also locate the cells in pParent ** that divide the siblings. An attempt is made to find NN siblings on @@ -70557,7 +70728,13 @@ static int balance_nonroot( memset(apOld, 0, (i+1)*sizeof(MemPage*)); goto balance_cleanup; } - nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow; + if( apOld[i]->nFree<0 ){ + rc = btreeComputeFreeSpace(apOld[i]); + if( rc ){ + memset(apOld, 0, (i)*sizeof(MemPage*)); + goto balance_cleanup; + } + } if( (i--)==0 ) break; if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){ @@ -70601,6 +70778,7 @@ static int balance_nonroot( /* Make nMaxCells a multiple of 4 in order to preserve 8-byte ** alignment */ + nMaxCells = nOld*(MX_CELL(pBt) + ArraySize(pParent->apOvfl)); nMaxCells = (nMaxCells + 3)&~3; /* @@ -70611,7 +70789,7 @@ static int balance_nonroot( + nMaxCells*sizeof(u16) /* b.szCell */ + pBt->pageSize; /* aSpace1 */ - assert( szScratch<=6*(int)pBt->pageSize ); + assert( szScratch<=7*(int)pBt->pageSize ); b.apCell = sqlite3StackAllocRaw(0, szScratch ); if( b.apCell==0 ){ rc = SQLITE_NOMEM_BKPT; @@ -70751,11 +70929,15 @@ static int balance_nonroot( MemPage *p = apOld[i]; b.apEnd[k] = p->aDataEnd; b.ixNx[k] = cntOld[i]; + if( k && b.ixNx[k]==b.ixNx[k-1] ){ + k--; /* Omit b.ixNx[] entry for child pages with no cells */ + } if( !leafData ){ k++; b.apEnd[k] = pParent->aDataEnd; b.ixNx[k] = cntOld[i]+1; } + assert( p->nFree>=0 ); szNew[i] = usableSpace - p->nFree; for(j=0; jnOverflow; j++){ szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]); @@ -70981,18 +71163,17 @@ static int balance_nonroot( if( ISAUTOVACUUM ){ MemPage *pOld; MemPage *pNew = pOld = apNew[0]; - u8 *aOld = pNew->aData; int cntOldNext = pNew->nCell + pNew->nOverflow; - int usableSize = pBt->usableSize; int iNew = 0; int iOld = 0; for(i=0; inCell + pOld->nOverflow + !leafData; - aOld = pOld->aData; } if( i==cntNew[iNew] ){ pNew = apNew[++iNew]; @@ -71007,7 +71188,7 @@ static int balance_nonroot( ** overflow cell), we can skip updating the pointer map entries. */ if( iOld>=nNew || pNew->pgno!=aPgno[iOld] - || !SQLITE_WITHIN(pCell,aOld,&aOld[usableSize]) + || !SQLITE_WITHIN(pCell,pOld->aData,pOld->aDataEnd) ){ if( !leafCorrection ){ ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno, &rc); @@ -71158,7 +71339,8 @@ static int balance_nonroot( rc = defragmentPage(apNew[0], -1); testcase( rc!=SQLITE_OK ); assert( apNew[0]->nFree == - (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2) + (get2byteNotZero(&apNew[0]->aData[5]) - apNew[0]->cellOffset + - apNew[0]->nCell*2) || rc!=SQLITE_OK ); copyNodeContent(apNew[0], pParent, &rc); @@ -71257,7 +71439,7 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){ } assert( sqlite3PagerIswriteable(pChild->pDbPage) ); assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); - assert( pChild->nCell==pRoot->nCell ); + assert( pChild->nCell==pRoot->nCell || CORRUPT_DB ); TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno)); @@ -71299,6 +71481,7 @@ static int balance(BtCursor *pCur){ int iPage = pCur->iPage; MemPage *pPage = pCur->pPage; + if( NEVER(pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break; if( iPage==0 ){ if( pPage->nOverflow ){ /* The root page of the b-tree is overfull. In this case call the @@ -71327,6 +71510,9 @@ static int balance(BtCursor *pCur){ int const iIdx = pCur->aiIdx[iPage-1]; rc = sqlite3PagerWrite(pParent->pDbPage); + if( rc==SQLITE_OK && pParent->nFree<0 ){ + rc = btreeComputeFreeSpace(pParent); + } if( rc==SQLITE_OK ){ #ifndef SQLITE_OMIT_QUICKBALANCE if( pPage->intKeyLeaf @@ -71673,6 +71859,10 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( pPage = pCur->pPage; assert( pPage->intKey || pX->nKey>=0 ); assert( pPage->leaf || !pPage->intKey ); + if( pPage->nFree<0 ){ + rc = btreeComputeFreeSpace(pPage); + if( rc ) return rc; + } TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n", pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno, @@ -71815,14 +72005,18 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ assert( pCur->curFlags & BTCF_WriteFlag ); assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); assert( !hasReadConflicts(p, pCur->pgnoRoot) ); - assert( pCur->ixpPage->nCell ); - assert( pCur->eState==CURSOR_VALID ); assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 ); + if( pCur->eState==CURSOR_REQUIRESEEK ){ + rc = btreeRestoreCursorPosition(pCur); + if( rc ) return rc; + } + assert( pCur->eState==CURSOR_VALID ); iCellDepth = pCur->iPage; iCellIdx = pCur->ix; pPage = pCur->pPage; pCell = findCell(pPage, iCellIdx); + if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ) return SQLITE_CORRUPT; /* If the bPreserve flag is set to true, then the cursor position must ** be preserved following this delete operation. If the current delete @@ -71893,6 +72087,10 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ Pgno n; unsigned char *pTmp; + if( pLeaf->nFree<0 ){ + rc = btreeComputeFreeSpace(pLeaf); + if( rc ) return rc; + } if( iCellDepthiPage-1 ){ n = pCur->apPage[iCellDepth+1]->pgno; }else{ @@ -72251,6 +72449,9 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){ assert( sqlite3BtreeHoldsMutex(p) ); assert( p->inTrans==TRANS_WRITE ); assert( iTable>=2 ); + if( iTable>btreePagecount(pBt) ){ + return SQLITE_CORRUPT_BKPT; + } rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0); if( rc ) return rc; @@ -72599,10 +72800,10 @@ static void checkList( IntegrityCk *pCheck, /* Integrity checking context */ int isFreeList, /* True for a freelist. False for overflow page list */ int iPage, /* Page number for first page in the list */ - int N /* Expected number of pages in the list */ + u32 N /* Expected number of pages in the list */ ){ int i; - int expected = N; + u32 expected = N; int nErrAtStart = pCheck->nErr; while( iPage!=0 && pCheck->mxErr ){ DbPage *pOvflPage; @@ -72784,6 +72985,11 @@ static int checkTreePage( "btreeInitPage() returns error code %d", rc); goto end_of_check; } + if( (rc = btreeComputeFreeSpace(pPage))!=0 ){ + assert( rc==SQLITE_CORRUPT ); + checkAppendMsg(pCheck, "free space corruption", rc); + goto end_of_check; + } data = pPage->aData; hdr = pPage->hdrOffset; @@ -72856,7 +73062,7 @@ static int checkTreePage( /* Check the content overflow list */ if( info.nPayload>info.nLocal ){ - int nPage; /* Number of pages on the overflow chain */ + u32 nPage; /* Number of pages on the overflow chain */ Pgno pgnoOvfl; /* First page of the overflow chain */ assert( pc + info.nSize - 4 <= usableSize ); nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4); @@ -72916,9 +73122,9 @@ static int checkTreePage( i = get2byte(&data[hdr+1]); while( i>0 ){ int size, j; - assert( (u32)i<=usableSize-4 ); /* Enforced by btreeInitPage() */ + assert( (u32)i<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */ size = get2byte(&data[i+2]); - assert( (u32)(i+size)<=usableSize ); /* Enforced by btreeInitPage() */ + assert( (u32)(i+size)<=usableSize ); /* due to btreeComputeFreeSpace() */ btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1)); /* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a ** big-endian integer which is the offset in the b-tree page of the next @@ -72927,8 +73133,8 @@ static int checkTreePage( j = get2byte(&data[i]); /* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of ** increasing offset. */ - assert( j==0 || j>i+size ); /* Enforced by btreeInitPage() */ - assert( (u32)j<=usableSize-4 ); /* Enforced by btreeInitPage() */ + assert( j==0 || j>i+size ); /* Enforced by btreeComputeFreeSpace() */ + assert( (u32)j<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */ i = j; } /* Analyze the min-heap looking for overlap between cells and/or @@ -74272,7 +74478,7 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){ ((p->flags&MEM_Static)!=0 ? 1 : 0) <= 1 ); /* No other bits set */ - assert( (p->flags & ~(MEM_Null|MEM_Term|MEM_Subtype + assert( (p->flags & ~(MEM_Null|MEM_Term|MEM_Subtype|MEM_FromBind |MEM_Dyn|MEM_Ephem|MEM_Static))==0 ); }else{ /* A pure NULL might have other flags, such as MEM_Static, MEM_Dyn, @@ -74393,8 +74599,7 @@ SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ } /* -** Make sure pMem->z points to a writable allocation of at least -** min(n,32) bytes. +** Make sure pMem->z points to a writable allocation of at least n bytes. ** ** If the bPreserve argument is true, then copy of the content of ** pMem->z into the new allocation. pMem must be either a string or @@ -74413,7 +74618,6 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPre assert( pMem->szMalloc==0 || pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) ); - if( n<32 ) n = 32; if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){ pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n); bPreserve = 0; @@ -74515,13 +74719,15 @@ SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){ SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){ int nByte; assert( pMem->flags & MEM_Zero ); - assert( pMem->flags&MEM_Blob ); + assert( (pMem->flags&MEM_Blob)!=0 || MemNullNochng(pMem) ); + testcase( sqlite3_value_nochange(pMem) ); assert( !sqlite3VdbeMemIsRowSet(pMem) ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); /* Set nByte to the number of bytes required to store the expanded blob. */ nByte = pMem->n + pMem->u.nZero; if( nByte<=0 ){ + if( (pMem->flags & MEM_Blob)==0 ) return SQLITE_OK; nByte = 1; } if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){ @@ -75262,7 +75468,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( assert( enc!=0 ); if( enc==SQLITE_UTF8 ){ nByte = 0x7fffffff & (int)strlen(z); - if( nByte>iLimit ) nByte = iLimit+1; }else{ for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){} } @@ -75274,29 +75479,30 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( ** management (one of MEM_Dyn or MEM_Static). */ if( xDel==SQLITE_TRANSIENT ){ - int nAlloc = nByte; + u32 nAlloc = nByte; if( flags&MEM_Term ){ nAlloc += (enc==SQLITE_UTF8?1:2); } if( nByte>iLimit ){ - return SQLITE_TOOBIG; + return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG); } testcase( nAlloc==0 ); testcase( nAlloc==31 ); testcase( nAlloc==32 ); - if( sqlite3VdbeMemClearAndResize(pMem, MAX(nAlloc,32)) ){ + if( sqlite3VdbeMemClearAndResize(pMem, (int)MAX(nAlloc,32)) ){ return SQLITE_NOMEM_BKPT; } memcpy(pMem->z, z, nAlloc); - }else if( xDel==SQLITE_DYNAMIC ){ - sqlite3VdbeMemRelease(pMem); - pMem->zMalloc = pMem->z = (char *)z; - pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); }else{ sqlite3VdbeMemRelease(pMem); pMem->z = (char *)z; - pMem->xDel = xDel; - flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn); + if( xDel==SQLITE_DYNAMIC ){ + pMem->zMalloc = pMem->z; + pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc); + }else{ + pMem->xDel = xDel; + flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn); + } } pMem->n = nByte; @@ -76264,9 +76470,11 @@ static int growOpArray(Vdbe *v, int nOp){ ** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current ** size of the op array or add 1KB of space, whichever is smaller. */ #ifdef SQLITE_TEST_REALLOC_STRESS - int nNew = (v->nOpAlloc>=512 ? v->nOpAlloc*2 : v->nOpAlloc+nOp); + sqlite3_int64 nNew = (v->nOpAlloc>=512 ? 2*(sqlite3_int64)v->nOpAlloc + : (sqlite3_int64)v->nOpAlloc+nOp); #else - int nNew = (v->nOpAlloc ? v->nOpAlloc*2 : (int)(1024/sizeof(Op))); + sqlite3_int64 nNew = (v->nOpAlloc ? 2*(sqlite3_int64)v->nOpAlloc + : (sqlite3_int64)(1024/sizeof(Op))); UNUSED_PARAMETER(nOp); #endif @@ -76746,6 +76954,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ int opcode = pOp->opcode; if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename || opcode==OP_VDestroy + || (opcode==OP_Function0 && pOp->p4.pFunc->funcFlags&SQLITE_FUNC_INTERNAL) || ((opcode==OP_Halt || opcode==OP_HaltIfNull) && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort)) ){ @@ -77053,7 +77262,7 @@ SQLITE_PRIVATE void sqlite3VdbeScanStatus( LogEst nEst, /* Estimated number of output rows */ const char *zName /* Name of table or index being scanned */ ){ - int nByte = (p->nScan+1) * sizeof(ScanStatus); + sqlite3_int64 nByte = (p->nScan+1) * sizeof(ScanStatus); ScanStatus *aNew; aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte); if( aNew ){ @@ -78174,9 +78383,9 @@ SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe *p){ ** of a ReusableSpace object by the allocSpace() routine below. */ struct ReusableSpace { - u8 *pSpace; /* Available memory */ - int nFree; /* Bytes of available memory */ - int nNeeded; /* Total bytes that could not be allocated */ + u8 *pSpace; /* Available memory */ + sqlite3_int64 nFree; /* Bytes of available memory */ + sqlite3_int64 nNeeded; /* Total bytes that could not be allocated */ }; /* Try to allocate nByte bytes of 8-byte aligned bulk memory for pBuf @@ -78196,7 +78405,7 @@ struct ReusableSpace { static void *allocSpace( struct ReusableSpace *p, /* Bulk memory available for allocation */ void *pBuf, /* Pointer to a prior allocation */ - int nByte /* Bytes of memory needed */ + sqlite3_int64 nByte /* Bytes of memory needed */ ){ assert( EIGHT_BYTE_ALIGNMENT(p->pSpace) ); if( pBuf==0 ){ @@ -81153,7 +81362,7 @@ static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){ assert( p->zSql!=0 ); sqlite3OsCurrentTimeInt64(db->pVfs, &iNow); iElapse = (iNow - p->startTime)*1000000; -#ifndef SQLITE_OMIT_DEPRECATED +#ifndef SQLITE_OMIT_DEPRECATED if( db->xProfile ){ db->xProfile(db->pProfileArg, p->zSql, iElapse); } @@ -81361,6 +81570,11 @@ SQLITE_API int sqlite3_value_nochange(sqlite3_value *pVal){ return (pVal->flags&(MEM_Null|MEM_Zero))==(MEM_Null|MEM_Zero); } +/* Return true if a parameter value originated from an sqlite3_bind() */ +SQLITE_API int sqlite3_value_frombind(sqlite3_value *pVal){ + return (pVal->flags&MEM_FromBind)!=0; +} + /* Make a copy of an sqlite3_value object */ SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){ @@ -82206,10 +82420,10 @@ SQLITE_API int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ ** or a constant) then useTypes 2, 3, and 4 return NULL. */ static const void *columnName( - sqlite3_stmt *pStmt, - int N, - const void *(*xFunc)(Mem*), - int useType + sqlite3_stmt *pStmt, /* The statement */ + int N, /* Which column to get the name for */ + int useUtf16, /* True to return the name as UTF16 */ + int useType /* What type of name */ ){ const void *ret; Vdbe *p; @@ -82230,8 +82444,15 @@ static const void *columnName( N += useType*n; sqlite3_mutex_enter(db->mutex); assert( db->mallocFailed==0 ); - ret = xFunc(&p->aColName[N]); - /* A malloc may have failed inside of the xFunc() call. If this +#ifndef SQLITE_OMIT_UTF16 + if( useUtf16 ){ + ret = sqlite3_value_text16((sqlite3_value*)&p->aColName[N]); + }else +#endif + { + ret = sqlite3_value_text((sqlite3_value*)&p->aColName[N]); + } + /* A malloc may have failed inside of the _text() call. If this ** is the case, clear the mallocFailed flag and return NULL. */ if( db->mallocFailed ){ @@ -82248,13 +82469,11 @@ static const void *columnName( ** statement pStmt. */ SQLITE_API const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME); + return columnName(pStmt, N, 0, COLNAME_NAME); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME); + return columnName(pStmt, N, 1, COLNAME_NAME); } #endif @@ -82273,13 +82492,11 @@ SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ ** of the result set of SQL statement pStmt. */ SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE); + return columnName(pStmt, N, 0, COLNAME_DECLTYPE); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE); + return columnName(pStmt, N, 1, COLNAME_DECLTYPE); } #endif /* SQLITE_OMIT_UTF16 */ #endif /* SQLITE_OMIT_DECLTYPE */ @@ -82291,13 +82508,11 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ ** anything else which is not an unambiguous reference to a database column. */ SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE); + return columnName(pStmt, N, 0, COLNAME_DATABASE); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE); + return columnName(pStmt, N, 1, COLNAME_DATABASE); } #endif /* SQLITE_OMIT_UTF16 */ @@ -82307,13 +82522,11 @@ SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N ** anything else which is not an unambiguous reference to a database column. */ SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE); + return columnName(pStmt, N, 0, COLNAME_TABLE); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE); + return columnName(pStmt, N, 1, COLNAME_TABLE); } #endif /* SQLITE_OMIT_UTF16 */ @@ -82323,13 +82536,11 @@ SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){ ** anything else which is not an unambiguous reference to a database column. */ SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN); + return columnName(pStmt, N, 0, COLNAME_COLUMN); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){ - return columnName( - pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN); + return columnName(pStmt, N, 1, COLNAME_COLUMN); } #endif /* SQLITE_OMIT_UTF16 */ #endif /* SQLITE_ENABLE_COLUMN_METADATA */ @@ -82697,6 +82908,14 @@ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){ return pStmt ? ((Vdbe*)pStmt)->readOnly : 1; } +/* +** Return 1 if the statement is an EXPLAIN and return 2 if the +** statement is an EXPLAIN QUERY PLAN +*/ +SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt){ + return pStmt ? ((Vdbe*)pStmt)->explain : 0; +} + /* ** Return true if the prepared statement is in need of being reset. */ @@ -83386,12 +83605,20 @@ SQLITE_API int sqlite3_found_count = 0; ** feature is used for test suite validation only and does not appear an ** production builds. ** -** M is an integer between 2 and 4. 2 indicates a ordinary two-way -** branch (I=0 means fall through and I=1 means taken). 3 indicates -** a 3-way branch where the third way is when one of the operands is -** NULL. 4 indicates the OP_Jump instruction which has three destinations -** depending on whether the first operand is less than, equal to, or greater -** than the second. +** M is the type of branch. I is the direction taken for this instance of +** the branch. +** +** M: 2 - two-way branch (I=0: fall-thru 1: jump ) +** 3 - two-way + NULL (I=0: fall-thru 1: jump 2: NULL ) +** 4 - OP_Jump (I=0: jump p1 1: jump p2 2: jump p3) +** +** In other words, if M is 2, then I is either 0 (for fall-through) or +** 1 (for when the branch is taken). If M is 3, the I is 0 for an +** ordinary fall-through, I is 1 if the branch was taken, and I is 2 +** if the result of comparison is NULL. For M=3, I=2 the jump may or +** may not be taken, depending on the SQLITE_JUMPIFNULL flags in p5. +** When M is 4, that means that an OP_Jump is being run. I is 0, 1, or 2 +** depending on if the operands are less than, equal, or greater than. ** ** iSrcLine is the source code line (from the __LINE__ macro) that ** generated the VDBE instruction combined with flag bits. The source @@ -83402,9 +83629,9 @@ SQLITE_API int sqlite3_found_count = 0; ** alternate branch are never taken. If a branch is never taken then ** flags should be 0x06 since only the fall-through approach is allowed. ** -** Bit 0x04 of the flags indicates an OP_Jump opcode that is only +** Bit 0x08 of the flags indicates an OP_Jump opcode that is only ** interested in equal or not-equal. In other words, I==0 and I==2 -** should be treated the same. +** should be treated as equivalent ** ** Since only a line number is retained, not the filename, this macro ** only works for amalgamation builds. But that is ok, since these macros @@ -83428,6 +83655,18 @@ SQLITE_API int sqlite3_found_count = 0; mNever = iSrcLine >> 24; assert( (I & mNever)==0 ); if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/ + /* Invoke the branch coverage callback with three arguments: + ** iSrcLine - the line number of the VdbeCoverage() macro, with + ** flags removed. + ** I - Mask of bits 0x07 indicating which cases are are + ** fulfilled by this instance of the jump. 0x01 means + ** fall-thru, 0x02 means taken, 0x04 means NULL. Any + ** impossible cases (ex: if the comparison is never NULL) + ** are filled in automatically so that the coverage + ** measurement logic does not flag those impossible cases + ** as missed coverage. + ** M - Type of jump. Same as M argument above + */ I |= mNever; if( M==2 ) I |= 0x04; if( M==4 ){ @@ -83975,6 +84214,15 @@ SQLITE_PRIVATE int sqlite3VdbeExec( assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ sqlite3VdbeEnter(p); +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + if( db->xProgress ){ + u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP]; + assert( 0 < db->nProgressOps ); + nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps); + }else{ + nProgressLimit = 0xffffffff; + } +#endif if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ @@ -83988,15 +84236,6 @@ SQLITE_PRIVATE int sqlite3VdbeExec( db->busyHandler.nBusy = 0; if( db->u1.isInterrupted ) goto abort_due_to_interrupt; sqlite3VdbeIOTraceSql(p); -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - if( db->xProgress ){ - u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP]; - assert( 0 < db->nProgressOps ); - nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps); - }else{ - nProgressLimit = 0xffffffff; - } -#endif #ifdef SQLITE_DEBUG sqlite3BeginBenignMalloc(); if( p->pc==0 @@ -84172,10 +84411,11 @@ check_for_interrupt: ** If the progress callback returns non-zero, exit the virtual machine with ** a return code SQLITE_ABORT. */ - if( nVmStep>=nProgressLimit && db->xProgress!=0 ){ + while( nVmStep>=nProgressLimit && db->xProgress!=0 ){ assert( db->nProgressOps!=0 ); - nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps); + nProgressLimit += db->nProgressOps; if( db->xProgress(db->pProgressArg) ){ + nProgressLimit = 0xffffffff; rc = SQLITE_INTERRUPT; goto abort_due_to_error; } @@ -84454,6 +84694,7 @@ case OP_String8: { /* same as TK_STRING, out2 */ if( encoding!=SQLITE_UTF8 ){ rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC); assert( rc==SQLITE_OK || rc==SQLITE_TOOBIG ); + if( rc ) goto too_big; if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem; assert( pOut->szMalloc>0 && pOut->zMalloc==pOut->z ); assert( VdbeMemDynamic(pOut)==0 ); @@ -84466,7 +84707,6 @@ case OP_String8: { /* same as TK_STRING, out2 */ pOp->p4.z = pOut->z; pOp->p1 = pOut->n; } - testcase( rc==SQLITE_TOOBIG ); #endif if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; @@ -84588,7 +84828,10 @@ case OP_Variable: { /* out2 */ goto too_big; } pOut = &aMem[pOp->p2]; - sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static); + if( VdbeMemDynamic(pOut) ) sqlite3VdbeMemSetNull(pOut); + memcpy(pOut, pVar, MEMCELLSIZE); + pOut->flags &= ~(MEM_Dyn|MEM_Ephem); + pOut->flags |= MEM_Static|MEM_FromBind; UPDATE_MAX_BLOBSIZE(pOut); break; } @@ -84721,18 +84964,6 @@ case OP_ResultRow: { assert( pOp->p1>0 ); assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 ); -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - /* Run the progress counter just before returning. - */ - if( db->xProgress!=0 - && nVmStep>=nProgressLimit - && db->xProgress(db->pProgressArg)!=0 - ){ - rc = SQLITE_INTERRUPT; - goto abort_due_to_error; - } -#endif - /* If this statement has violated immediate foreign key constraints, do ** not return the number of rows modified. And do not RELEASE the statement ** transaction. It needs to be rolled back. */ @@ -85098,8 +85329,8 @@ case OP_MustBeInt: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; if( (pIn1->flags & MEM_Int)==0 ){ applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding); - VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2); if( (pIn1->flags & MEM_Int)==0 ){ + VdbeBranchTaken(1, 2); if( pOp->p2==0 ){ rc = SQLITE_MISMATCH; goto abort_due_to_error; @@ -85108,6 +85339,7 @@ case OP_MustBeInt: { /* jump, in1 */ } } } + VdbeBranchTaken(0, 2); MemSetTypeFlag(pIn1, MEM_Int); break; } @@ -85282,7 +85514,6 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ ** OP_Eq or OP_Ne) then take the jump or not depending on whether ** or not both operands are null. */ - assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne ); assert( (flags1 & MEM_Cleared)==0 ); assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 || CORRUPT_DB ); testcase( (pOp->p5 & SQLITE_JUMPIFNULL)!=0 ); @@ -85291,7 +85522,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ ){ res = 0; /* Operands are equal */ }else{ - res = 1; /* Operands are not equal */ + res = ((flags3 & MEM_Null) ? -1 : +1); /* Operands are not equal */ } }else{ /* SQLITE_NULLEQ is clear and at least one operand is NULL, @@ -85409,7 +85640,7 @@ compare_op: pOut->u.i = res2; REGISTER_TRACE(pOp->p2, pOut); }else{ - VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3); + VdbeBranchTaken(res2!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3); if( res2 ){ goto jump_to_p2; } @@ -85959,15 +86190,15 @@ case OP_Column: { zEndHdr = zData + aOffset[0]; testcase( zHdr>=zEndHdr ); do{ - if( (t = zHdr[0])<0x80 ){ + if( (pC->aType[i] = t = zHdr[0])<0x80 ){ zHdr++; offset64 += sqlite3VdbeOneByteSerialTypeLen(t); }else{ zHdr += sqlite3GetVarint32(zHdr, &t); + pC->aType[i] = t; offset64 += sqlite3VdbeSerialTypeLen(t); } - pC->aType[i++] = t; - aOffset[i] = (u32)(offset64 & 0xffffffff); + aOffset[++i] = (u32)(offset64 & 0xffffffff); }while( i<=p2 && zHdrpKeyInfo = pOrig->pKeyInfo; pCx->isTable = pOrig->isTable; pCx->pgnoRoot = pOrig->pgnoRoot; + pCx->isOrdered = pOrig->isOrdered; rc = sqlite3BtreeCursor(pOrig->pBtx, pCx->pgnoRoot, BTREE_WRCSR, pCx->pKeyInfo, pCx->uc.pCursor); /* The sqlite3BtreeCursor() routine can only fail for the first cursor @@ -88478,7 +88710,7 @@ case OP_Sort: { /* jump */ p->aCounter[SQLITE_STMTSTATUS_SORT]++; /* Fall through into OP_Rewind */ } -/* Opcode: Rewind P1 P2 * * P5 +/* Opcode: Rewind P1 P2 * * * ** ** The next use of the Rowid or Column or Next instruction for P1 ** will refer to the first entry in the database table or index. @@ -88486,10 +88718,6 @@ case OP_Sort: { /* jump */ ** If the table or index is not empty, fall through to the following ** instruction. ** -** If P5 is non-zero and the table is not empty, then the "skip-next" -** flag is set on the cursor so that the next OP_Next instruction -** executed on it is a no-op. -** ** This opcode leaves the cursor configured to move in forward order, ** from the beginning toward the end. In other words, the cursor is ** configured to use Next, not Prev. @@ -88500,6 +88728,7 @@ case OP_Rewind: { /* jump */ int res; assert( pOp->p1>=0 && pOp->p1nCursor ); + assert( pOp->p5==0 ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) ); @@ -88514,9 +88743,6 @@ case OP_Rewind: { /* jump */ pCrsr = pC->uc.pCursor; assert( pCrsr ); rc = sqlite3BtreeFirst(pCrsr, &res); -#ifndef SQLITE_OMIT_WINDOWFUNC - if( pOp->p5 ) sqlite3BtreeSkipNext(pCrsr); -#endif pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; } @@ -89526,8 +89752,7 @@ case OP_Program: { /* jump */ } #endif pOp = &aOp[-1]; - - break; + goto check_for_interrupt; } /* Opcode: Param P1 P2 * * * @@ -89899,6 +90124,7 @@ case OP_AggFinal: { assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); #ifndef SQLITE_OMIT_WINDOWFUNC if( pOp->p3 ){ + memAboutToChange(p, &aMem[pOp->p3]); rc = sqlite3VdbeMemAggValue(pMem, &aMem[pOp->p3], pOp->p4.pFunc); pMem = &aMem[pOp->p3]; }else @@ -90936,7 +91162,16 @@ abort_due_to_error: ** release the mutexes on btrees that were acquired at the ** top. */ vdbe_return: - testcase( nVmStep>0 ); +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + while( nVmStep>=nProgressLimit && db->xProgress!=0 ){ + nProgressLimit += db->nProgressOps; + if( db->xProgress(db->pProgressArg) ){ + nProgressLimit = 0xffffffff; + rc = SQLITE_INTERRUPT; + goto abort_due_to_error; + } + } +#endif p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep; sqlite3VdbeLeave(p); assert( rc!=SQLITE_OK || nExtraDelete==0 @@ -92023,7 +92258,7 @@ static int vdbePmaReadBlob( /* Extend the p->aAlloc[] allocation if required. */ if( p->nAllocnAlloc*2); + sqlite3_int64 nNew = MAX(128, 2*(sqlite3_int64)p->nAlloc); while( nByte>nNew ) nNew = nNew*2; aNew = sqlite3Realloc(p->aAlloc, nNew); if( !aNew ) return SQLITE_NOMEM_BKPT; @@ -93314,15 +93549,19 @@ SQLITE_PRIVATE int sqlite3VdbeSorterWrite( if( nMin>pSorter->nMemory ){ u8 *aNew; - int iListOff = (u8*)pSorter->list.pList - pSorter->list.aMemory; - int nNew = pSorter->nMemory * 2; + sqlite3_int64 nNew = 2 * (sqlite3_int64)pSorter->nMemory; + int iListOff = -1; + if( pSorter->list.pList ){ + iListOff = (u8*)pSorter->list.pList - pSorter->list.aMemory; + } while( nNew < nMin ) nNew = nNew*2; if( nNew > pSorter->mxPmaSize ) nNew = pSorter->mxPmaSize; if( nNew < nMin ) nNew = nMin; - aNew = sqlite3Realloc(pSorter->list.aMemory, nNew); if( !aNew ) return SQLITE_NOMEM_BKPT; - pSorter->list.pList = (SorterRecord*)&aNew[iListOff]; + if( iListOff>=0 ){ + pSorter->list.pList = (SorterRecord*)&aNew[iListOff]; + } pSorter->list.aMemory = aNew; pSorter->nMemory = nNew; } @@ -95309,6 +95548,10 @@ static int lookupName( sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); return WRC_Abort; } + if( (pNC->ncFlags&NC_AllowWin)==0 && ExprHasProperty(pOrig, EP_Win) ){ + sqlite3ErrorMsg(pParse, "misuse of aliased window function %s",zAs); + return WRC_Abort; + } if( sqlite3ExprVectorSize(pOrig)!=1 ){ sqlite3ErrorMsg(pParse, "row value misused"); return WRC_Abort; @@ -95599,6 +95842,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ const char *zId; /* The function name. */ FuncDef *pDef; /* Information about the function */ u8 enc = ENC(pParse->db); /* The database encoding */ + int savedAllowFlags = (pNC->ncFlags & (NC_AllowAgg | NC_AllowWin)); assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); zId = pExpr->u.zToken; @@ -95720,8 +95964,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pNC->nErr++; } if( is_agg ){ + /* Window functions may not be arguments of aggregate functions. + ** Or arguments of other window functions. But aggregate functions + ** may be arguments for window functions. */ #ifndef SQLITE_OMIT_WINDOWFUNC - pNC->ncFlags &= ~(pExpr->y.pWin ? NC_AllowWin : NC_AllowAgg); + pNC->ncFlags &= ~(NC_AllowWin | (!pExpr->y.pWin ? NC_AllowAgg : 0)); #else pNC->ncFlags &= ~NC_AllowAgg; #endif @@ -95742,7 +95989,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pExpr->y.pWin->pNextWin = pSel->pWin; pSel->pWin = pExpr->y.pWin; } - pNC->ncFlags |= NC_AllowWin; + pNC->ncFlags |= NC_HasWin; }else #endif /* SQLITE_OMIT_WINDOWFUNC */ { @@ -95760,8 +96007,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX); } - pNC->ncFlags |= NC_AllowAgg; } + pNC->ncFlags |= savedAllowFlags; } /* FIX ME: Compute pExpr->affinity based on the expected return ** type of the function @@ -96298,7 +96545,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ */ for(i=0; ipSrc->nSrc; i++){ struct SrcList_item *pItem = &p->pSrc->a[i]; - if( pItem->pSelect ){ + if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){ NameContext *pNC; /* Used to iterate name contexts */ int nRef = 0; /* Refcount for pOuterNC and outer contexts */ const char *zSavedContext = pParse->zAuthContext; @@ -96430,6 +96677,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ } } +#ifndef SQLITE_OMIT_WINDOWFUNC if( IN_RENAME_OBJECT ){ Window *pWin; for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){ @@ -96440,6 +96688,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ } } } +#endif /* If this is part of a compound SELECT, check that it has the right ** number of expressions in the select list. */ @@ -96520,8 +96769,8 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames( Walker w; if( pExpr==0 ) return SQLITE_OK; - savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg); - pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg); + savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin); + pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin); w.pParse = pNC->pParse; w.xExprCallback = resolveExprStep; w.xSelectCallback = resolveSelectStep; @@ -96537,9 +96786,11 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames( #if SQLITE_MAX_EXPR_DEPTH>0 w.pParse->nHeight -= pExpr->nHeight; #endif - if( pNC->ncFlags & NC_HasAgg ){ - ExprSetProperty(pExpr, EP_Agg); - } + assert( EP_Agg==NC_HasAgg ); + assert( EP_Win==NC_HasWin ); + testcase( pNC->ncFlags & NC_HasAgg ); + testcase( pNC->ncFlags & NC_HasWin ); + ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) ); pNC->ncFlags |= savedHasAgg; return pNC->nErr>0 || w.pParse->nErr>0; } @@ -97495,7 +97746,7 @@ SQLITE_PRIVATE Expr *sqlite3PExpr( p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)); if( p ){ memset(p, 0, sizeof(Expr)); - p->op = op & TKFLG_MASK; + p->op = op & 0xff; p->iAgg = -1; } sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight); @@ -97960,7 +98211,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ static With *withDup(sqlite3 *db, With *p){ With *pRet = 0; if( p ){ - int nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1); + sqlite3_int64 nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1); pRet = sqlite3DbMallocZero(db, nByte); if( pRet ){ int i; @@ -98225,7 +98476,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend( }else if( (pList->nExpr & (pList->nExpr-1))==0 ){ ExprList *pNew; pNew = sqlite3DbRealloc(db, pList, - sizeof(*pList)+(2*pList->nExpr - 1)*sizeof(pList->a[0])); + sizeof(*pList)+(2*(sqlite3_int64)pList->nExpr-1)*sizeof(pList->a[0])); if( pNew==0 ){ goto no_mem; } @@ -101670,6 +101921,17 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ */ SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){ Walker w; + p = sqlite3ExprSkipCollate(p); + while( p ){ + if( p->op==TK_NOTNULL ){ + p = p->pLeft; + }else if( p->op==TK_AND ){ + if( sqlite3ExprImpliesNonNullRow(p->pLeft, iTab) ) return 1; + p = p->pRight; + }else{ + break; + } + } w.xExprCallback = impliesNotNullRow; w.xSelectCallback = 0; w.xSelectCallback2 = 0; @@ -102251,15 +102513,15 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable( } #endif - /* Begin a transaction for database iDb. - ** Then modify the schema cookie (since the ALTER TABLE modifies the - ** schema). Open a statement transaction if the table is a virtual - ** table. - */ + /* Begin a transaction for database iDb. Then modify the schema cookie + ** (since the ALTER TABLE modifies the schema). Call sqlite3MayAbort(), + ** as the scalar functions (e.g. sqlite_rename_table()) invoked by the + ** nested SQL may raise an exception. */ v = sqlite3GetVdbe(pParse); if( v==0 ){ goto exit_rename_table; } + sqlite3MayAbort(pParse); /* figure out how many UTF-8 characters are in zName */ zTabName = pTab->zName; @@ -102328,7 +102590,6 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable( int i = ++pParse->nMem; sqlite3VdbeLoadString(v, i, zName); sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB); - sqlite3MayAbort(pParse); } #endif @@ -102649,6 +102910,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameColumn( ** uses the sqlite_rename_column() SQL function to compute the new ** CREATE statement text for the sqlite_master table. */ + sqlite3MayAbort(pParse); zNew = sqlite3NameFromToken(db, pNew); if( !zNew ) goto exit_rename_column; assert( pNew->n>0 ); @@ -105903,12 +106165,14 @@ static void attachFunc( sqlite3BtreeEnterAll(db); db->init.iDb = 0; db->mDbFlags &= ~(DBFLAG_SchemaKnownOk); - rc = sqlite3Init(db, &zErrDyn); + if( !REOPEN_AS_MEMDB(db) ){ + rc = sqlite3Init(db, &zErrDyn); + } sqlite3BtreeLeaveAll(db); assert( zErrDyn==0 || rc!=SQLITE_OK ); } #ifdef SQLITE_USER_AUTHENTICATION - if( rc==SQLITE_OK ){ + if( rc==SQLITE_OK && !REOPEN_AS_MEMDB(db) ){ u8 newAuth = 0; rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth); if( newAuthauth.authLevel ){ @@ -106837,7 +107101,12 @@ SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ zSql = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); if( zSql==0 ){ - return; /* A malloc must have failed */ + /* This can result either from an OOM or because the formatted string + ** exceeds SQLITE_LIMIT_LENGTH. In the latter case, we need to set + ** an error */ + if( !db->mallocFailed ) pParse->rc = SQLITE_TOOBIG; + pParse->nErr++; + return; } pParse->nested++; memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ); @@ -107977,7 +108246,8 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey( && sortOrder!=SQLITE_SO_DESC ){ if( IN_RENAME_OBJECT && pList ){ - sqlite3RenameTokenRemap(pParse, &pTab->iPKey, pList->a[0].pExpr); + Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[0].pExpr); + sqlite3RenameTokenRemap(pParse, &pTab->iPKey, pCExpr); } pTab->iPKey = iCol; pTab->keyConf = (u8)onError; @@ -108398,6 +108668,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ pTab->iPKey = -1; }else{ pPk = sqlite3PrimaryKeyIndex(pTab); + assert( pPk!=0 ); /* ** Remove all redundant columns from the PRIMARY KEY. For example, change @@ -108567,6 +108838,11 @@ SQLITE_PRIVATE void sqlite3EndTable( if( p->tnum==1 ) p->tabFlags |= TF_Readonly; } + assert( (p->tabFlags & TF_HasPrimaryKey)==0 + || p->iPKey>=0 || sqlite3PrimaryKeyIndex(p)!=0 ); + assert( (p->tabFlags & TF_HasPrimaryKey)!=0 + || (p->iPKey<0 && sqlite3PrimaryKeyIndex(p)==0) ); + /* Special processing for WITHOUT ROWID Tables */ if( tabOpts & TF_WithoutRowid ){ if( (p->tabFlags & TF_Autoincrement) ){ @@ -109720,13 +109996,13 @@ SQLITE_PRIVATE void sqlite3CreateIndex( assert( pParse->nErr==0 ); if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 && db->init.busy==0 + && pTblName!=0 #if SQLITE_USER_AUTHENTICATION && sqlite3UserAuthTable(pTab->zName)==0 #endif #ifdef SQLITE_ALLOW_SQLITE_MASTER_INDEX && sqlite3StrICmp(&pTab->zName[7],"master")!=0 #endif - && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){ sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); goto exit_create_index; @@ -109830,6 +110106,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex( sqlite3ExprListSetSortOrder(pList, sortOrder); }else{ sqlite3ExprListCheckLength(pParse, pList, "index"); + if( pParse->nErr ) goto exit_create_index; } /* Figure out how many bytes of space are required to store explicitly @@ -109848,6 +110125,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex( */ nName = sqlite3Strlen30(zName); nExtraCol = pPk ? pPk->nKeyCol : 1; + assert( pList->nExpr + nExtraCol <= 32767 /* Fits in i16 */ ); pIndex = sqlite3AllocateIndexObject(db, pList->nExpr + nExtraCol, nName + nExtra + 1, &zExtra); if( db->mallocFailed ){ @@ -110331,9 +110609,9 @@ SQLITE_PRIVATE void *sqlite3ArrayAllocate( int *pIdx /* Write the index of a new slot here */ ){ char *z; - int n = *pnEntry; + sqlite3_int64 n = *pIdx = *pnEntry; if( (n & (n-1))==0 ){ - int sz = (n==0) ? 1 : 2*n; + sqlite3_int64 sz = (n==0) ? 1 : 2*n; void *pNew = sqlite3DbRealloc(db, pArray, sz*szEntry); if( pNew==0 ){ *pIdx = -1; @@ -110343,7 +110621,6 @@ SQLITE_PRIVATE void *sqlite3ArrayAllocate( } z = (char*)pArray; memset(&z[n * szEntry], 0, szEntry); - *pIdx = n; ++*pnEntry; return pArray; } @@ -110454,7 +110731,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge( /* Allocate additional space if needed */ if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){ SrcList *pNew; - int nAlloc = pSrc->nSrc*2+nExtra; + sqlite3_int64 nAlloc = 2*(sqlite3_int64)pSrc->nSrc+nExtra; sqlite3 *db = pParse->db; if( pSrc->nSrc+nExtra>=SQLITE_MAX_SRCLIST ){ @@ -110961,7 +111238,8 @@ SQLITE_PRIVATE void sqlite3UniqueConstraint( StrAccum errMsg; Table *pTab = pIdx->pTable; - sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200); + sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, + pParse->db->aLimit[SQLITE_LIMIT_LENGTH]); if( pIdx->aColExpr ){ sqlite3_str_appendf(&errMsg, "index '%q'", pIdx->zName); }else{ @@ -111210,7 +111488,7 @@ SQLITE_PRIVATE With *sqlite3WithAdd( } if( pWith ){ - int nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte); + sqlite3_int64 nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte); pNew = sqlite3DbRealloc(db, pWith, nByte); }else{ pNew = sqlite3DbMallocZero(db, sizeof(*pWith)); @@ -114518,6 +114796,10 @@ static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){ if( ALWAYS(pDef) ){ pDef->funcFlags |= flagVal; } + pDef = sqlite3FindFunction(db, zName, 3, SQLITE_UTF8, 0); + if( pDef ){ + pDef->funcFlags |= flagVal; + } } /* @@ -117840,7 +118122,9 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]); VdbeComment((v, "for %s", pIdx->zName)); #ifdef SQLITE_ENABLE_NULL_TRIM - if( pIdx->idxType==2 ) sqlite3SetMakeRecordP5(v, pIdx->pTable); + if( pIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){ + sqlite3SetMakeRecordP5(v, pIdx->pTable); + } #endif /* In an UPDATE operation, if this index is the PRIMARY KEY index @@ -118444,6 +118728,13 @@ static int xferOptimization( if( pSrcIdx==0 ){ return 0; /* pDestIdx has no corresponding index in pSrc */ } + if( pSrcIdx->tnum==pDestIdx->tnum && pSrc->pSchema==pDest->pSchema + && sqlite3FaultSim(411)==SQLITE_OK ){ + /* The sqlite3FaultSim() call allows this corruption test to be + ** bypassed during testing, in order to exercise other corruption tests + ** further downstream. */ + return 0; /* Corrupt schema - two indexes on the same btree */ + } } #ifndef SQLITE_OMIT_CHECK if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){ @@ -118521,7 +118812,7 @@ static int xferOptimization( sqlite3RowidConstraint(pParse, onError, pDest); sqlite3VdbeJumpHere(v, addr2); autoIncStep(pParse, regAutoinc, regRowid); - }else if( pDest->pIndex==0 ){ + }else if( pDest->pIndex==0 && !(db->mDbFlags & DBFLAG_VacuumInto) ){ addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid); }else{ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); @@ -118584,7 +118875,7 @@ static int xferOptimization( sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest); } } - if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){ + if( !HasRowid(pSrc) && pDestIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){ idxInsFlags |= OPFLAG_NCHANGE; } sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData); @@ -119096,6 +119387,9 @@ struct sqlite3_api_routines { void(*xDestroy)(void*)); /* Version 3.26.0 and later */ const char *(*normalized_sql)(sqlite3_stmt*); + /* Version 3.28.0 and later */ + int (*stmt_isexplain)(sqlite3_stmt*); + int (*value_frombind)(sqlite3_value*); }; /* @@ -119385,6 +119679,9 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_create_window_function sqlite3_api->create_window_function /* Version 3.26.0 and later */ #define sqlite3_normalized_sql sqlite3_api->normalized_sql +/* Version 3.28.0 and later */ +#define sqlite3_stmt_isexplain sqlite3_api->isexplain +#define sqlite3_value_frombind sqlite3_api->frombind #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) @@ -119844,10 +120141,13 @@ static const sqlite3_api_routines sqlite3Apis = { sqlite3_create_window_function, /* Version 3.26.0 and later */ #ifdef SQLITE_ENABLE_NORMALIZE - sqlite3_normalized_sql + sqlite3_normalized_sql, #else - 0 + 0, #endif + /* Version 3.28.0 and later */ + sqlite3_stmt_isexplain, + sqlite3_value_frombind }; /* @@ -129627,7 +129927,7 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){ ** ** If regAcc is non-zero and there are no min() or max() aggregates ** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator -** registers i register regAcc contains 0. The caller will take care +** registers if register regAcc contains 0. The caller will take care ** of setting and clearing regAcc. */ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){ @@ -133719,11 +134019,11 @@ build_vacuum_end: /* ** This routine implements the OP_Vacuum opcode of the VDBE. */ -SQLITE_PRIVATE int sqlite3RunVacuum( +SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum( char **pzErrMsg, /* Write error message here */ sqlite3 *db, /* Database connection */ int iDb, /* Which attached DB to vacuum */ - sqlite3_value *pOut /* Write results here, if not NULL */ + sqlite3_value *pOut /* Write results here, if not NULL. VACUUM INTO */ ){ int rc = SQLITE_OK; /* Return code from service routines */ Btree *pMain; /* The database being vacuumed */ @@ -133732,6 +134032,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum( u64 saved_flags; /* Saved value of db->flags */ int saved_nChange; /* Saved value of db->nChange */ int saved_nTotalChange; /* Saved value of db->nTotalChange */ + u32 saved_openFlags; /* Saved value of db->openFlags */ u8 saved_mTrace; /* Saved trace settings */ Db *pDb = 0; /* Database to detach at end of vacuum */ int isMemDb; /* True if vacuuming a :memory: database */ @@ -133742,18 +134043,21 @@ SQLITE_PRIVATE int sqlite3RunVacuum( if( !db->autoCommit ){ sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction"); - return SQLITE_ERROR; + return SQLITE_ERROR; /* IMP: R-12218-18073 */ } if( db->nVdbeActive>1 ){ sqlite3SetString(pzErrMsg, db,"cannot VACUUM - SQL statements in progress"); - return SQLITE_ERROR; + return SQLITE_ERROR; /* IMP: R-15610-35227 */ } + saved_openFlags = db->openFlags; if( pOut ){ if( sqlite3_value_type(pOut)!=SQLITE_TEXT ){ sqlite3SetString(pzErrMsg, db, "non-text filename"); return SQLITE_ERROR; } zOut = (const char*)sqlite3_value_text(pOut); + db->openFlags &= ~SQLITE_OPEN_READONLY; + db->openFlags |= SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE; }else{ zOut = ""; } @@ -133792,6 +134096,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum( */ nDb = db->nDb; rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS vacuum_db", zOut); + db->openFlags = saved_openFlags; if( rc!=SQLITE_OK ) goto end_of_vacuum; assert( (db->nDb-1)==nDb ); pDb = &db->aDb[nDb]; @@ -133805,6 +134110,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum( sqlite3SetString(pzErrMsg, db, "output file already exists"); goto end_of_vacuum; } + db->mDbFlags |= DBFLAG_VacuumInto; } nRes = sqlite3BtreeGetOptimalReserve(pMain); @@ -134293,9 +134599,13 @@ SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){ ** string will be freed automatically when the table is ** deleted. */ -static void addModuleArgument(sqlite3 *db, Table *pTable, char *zArg){ - int nBytes = sizeof(char *)*(2+pTable->nModuleArg); +static void addModuleArgument(Parse *pParse, Table *pTable, char *zArg){ + sqlite3_int64 nBytes = sizeof(char *)*(2+pTable->nModuleArg); char **azModuleArg; + sqlite3 *db = pParse->db; + if( pTable->nModuleArg+3>=db->aLimit[SQLITE_LIMIT_COLUMN] ){ + sqlite3ErrorMsg(pParse, "too many columns on %s", pTable->zName); + } azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes); if( azModuleArg==0 ){ sqlite3DbFree(db, zArg); @@ -134330,9 +134640,9 @@ SQLITE_PRIVATE void sqlite3VtabBeginParse( db = pParse->db; assert( pTable->nModuleArg==0 ); - addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); - addModuleArgument(db, pTable, 0); - addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName)); + addModuleArgument(pParse, pTable, sqlite3NameFromToken(db, pModuleName)); + addModuleArgument(pParse, pTable, 0); + addModuleArgument(pParse, pTable, sqlite3DbStrDup(db, pTable->zName)); assert( (pParse->sNameToken.z==pName2->z && pName2->z!=0) || (pParse->sNameToken.z==pName1->z && pName2->z==0) ); @@ -134365,7 +134675,7 @@ static void addArgumentToVtab(Parse *pParse){ const char *z = (const char*)pParse->sArg.z; int n = pParse->sArg.n; sqlite3 *db = pParse->db; - addModuleArgument(db, pParse->pNewTable, sqlite3DbStrNDup(db, z, n)); + addModuleArgument(pParse, pParse->pNewTable, sqlite3DbStrNDup(db, z, n)); } } @@ -134654,7 +134964,8 @@ static int growVTrans(sqlite3 *db){ /* Grow the sqlite3.aVTrans array if required */ if( (db->nVTrans%ARRAY_INCR)==0 ){ VTable **aVTrans; - int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR); + sqlite3_int64 nBytes = sizeof(sqlite3_vtab*)* + ((sqlite3_int64)db->nVTrans + ARRAY_INCR); aVTrans = sqlite3DbRealloc(db, (void *)db->aVTrans, nBytes); if( !aVTrans ){ return SQLITE_NOMEM_BKPT; @@ -135150,9 +135461,9 @@ SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){ pTab->pSchema = db->aDb[0].pSchema; assert( pTab->nModuleArg==0 ); pTab->iPKey = -1; - addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); - addModuleArgument(db, pTab, 0); - addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); + addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName)); + addModuleArgument(pParse, pTab, 0); + addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName)); rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr); if( rc ){ sqlite3ErrorMsg(pParse, "%s", zErr); @@ -136990,6 +137301,34 @@ static void whereIndexExprTrans( } } +/* +** The pTruth expression is always true because it is the WHERE clause +** a partial index that is driving a query loop. Look through all of the +** WHERE clause terms on the query, and if any of those terms must be +** true because pTruth is true, then mark those WHERE clause terms as +** coded. +*/ +static void whereApplyPartialIndexConstraints( + Expr *pTruth, + int iTabCur, + WhereClause *pWC +){ + int i; + WhereTerm *pTerm; + while( pTruth->op==TK_AND ){ + whereApplyPartialIndexConstraints(pTruth->pLeft, iTabCur, pWC); + pTruth = pTruth->pRight; + } + for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){ + Expr *pExpr; + if( pTerm->wtFlags & TERM_CODED ) continue; + pExpr = pTerm->pExpr; + if( sqlite3ExprCompare(0, pExpr, pTruth, iTabCur)==0 ){ + pTerm->wtFlags |= TERM_CODED; + } + } +} + /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. @@ -137599,6 +137938,14 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo); } + /* If a partial index is driving the loop, try to eliminate WHERE clause + ** terms from the query that must be true due to the WHERE clause of + ** the partial index + */ + if( pIdx->pPartIdxWhere ){ + whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC); + } + /* Record the instruction used to terminate the loop. */ if( pLoop->wsFlags & WHERE_ONEROW ){ pLevel->op = OP_Noop; @@ -137762,7 +138109,12 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); } if( pAndExpr ){ - pAndExpr = sqlite3PExpr(pParse, TK_AND|TKFLG_DONTFOLD, 0, pAndExpr); + /* The extra 0x10000 bit on the opcode is masked off and does not + ** become part of the new Expr.op. However, it does make the + ** op==TK_AND comparison inside of sqlite3PExpr() false, and this + ** prevents sqlite3PExpr() from implementing AND short-circuit + ** optimization, which we do not want here. */ + pAndExpr = sqlite3PExpr(pParse, TK_AND|0x10000, 0, pAndExpr); } } @@ -137992,8 +138344,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( u32 x = pLevel->iLikeRepCntr; if( x>0 ){ skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If,(int)(x>>1)); + VdbeCoverageIf(v, (x&1)==1); + VdbeCoverageIf(v, (x&1)==0); } - VdbeCoverage(v); #endif } #ifdef WHERETRACE_ENABLED /* 0xffff */ @@ -139595,6 +139948,12 @@ SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){ }else if( p->x.pList ){ mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList); } +#ifndef SQLITE_OMIT_WINDOWFUNC + if( p->op==TK_FUNCTION && p->y.pWin ){ + mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pPartition); + mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pOrderBy); + } +#endif return mask; } SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ @@ -143011,11 +143370,11 @@ static int whereLoopAddVirtual( rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn); /* If the call to xBestIndex() with all terms enabled produced a plan - ** that does not require any source tables (IOW: a plan with mBest==0), - ** then there is no point in making any further calls to xBestIndex() - ** since they will all return the same result (if the xBestIndex() - ** implementation is sane). */ - if( rc==SQLITE_OK && (mBest = (pNew->prereq & ~mPrereq))!=0 ){ + ** that does not require any source tables (IOW: a plan with mBest==0) + ** and does not use an IN(...) operator, then there is no point in making + ** any further calls to xBestIndex() since they will all return the same + ** result (if the xBestIndex() implementation is sane). */ + if( rc==SQLITE_OK && ((mBest = (pNew->prereq & ~mPrereq))!=0 || bIn) ){ int seenZero = 0; /* True if a plan with no prereqs seen */ int seenZeroNoIN = 0; /* Plan with no prereqs and no IN(...) seen */ Bitmask mPrev = 0; @@ -145248,6 +145607,96 @@ static void dense_rankValueFunc(sqlite3_context *pCtx){ } } +/* +** Implementation of built-in window function nth_value(). This +** implementation is used in "slow mode" only - when the EXCLUDE clause +** is not set to the default value "NO OTHERS". +*/ +struct NthValueCtx { + i64 nStep; + sqlite3_value *pValue; +}; +static void nth_valueStepFunc( + sqlite3_context *pCtx, + int nArg, + sqlite3_value **apArg +){ + struct NthValueCtx *p; + p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); + if( p ){ + i64 iVal; + switch( sqlite3_value_numeric_type(apArg[1]) ){ + case SQLITE_INTEGER: + iVal = sqlite3_value_int64(apArg[1]); + break; + case SQLITE_FLOAT: { + double fVal = sqlite3_value_double(apArg[1]); + if( ((i64)fVal)!=fVal ) goto error_out; + iVal = (i64)fVal; + break; + } + default: + goto error_out; + } + if( iVal<=0 ) goto error_out; + + p->nStep++; + if( iVal==p->nStep ){ + p->pValue = sqlite3_value_dup(apArg[0]); + if( !p->pValue ){ + sqlite3_result_error_nomem(pCtx); + } + } + } + UNUSED_PARAMETER(nArg); + UNUSED_PARAMETER(apArg); + return; + + error_out: + sqlite3_result_error( + pCtx, "second argument to nth_value must be a positive integer", -1 + ); +} +static void nth_valueFinalizeFunc(sqlite3_context *pCtx){ + struct NthValueCtx *p; + p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, 0); + if( p && p->pValue ){ + sqlite3_result_value(pCtx, p->pValue); + sqlite3_value_free(p->pValue); + p->pValue = 0; + } +} +#define nth_valueInvFunc noopStepFunc +#define nth_valueValueFunc noopValueFunc + +static void first_valueStepFunc( + sqlite3_context *pCtx, + int nArg, + sqlite3_value **apArg +){ + struct NthValueCtx *p; + p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); + if( p && p->pValue==0 ){ + p->pValue = sqlite3_value_dup(apArg[0]); + if( !p->pValue ){ + sqlite3_result_error_nomem(pCtx); + } + } + UNUSED_PARAMETER(nArg); + UNUSED_PARAMETER(apArg); +} +static void first_valueFinalizeFunc(sqlite3_context *pCtx){ + struct NthValueCtx *p; + p = (struct NthValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); + if( p && p->pValue ){ + sqlite3_result_value(pCtx, p->pValue); + sqlite3_value_free(p->pValue); + p->pValue = 0; + } +} +#define first_valueInvFunc noopStepFunc +#define first_valueValueFunc noopValueFunc + /* ** Implementation of built-in window function rank(). Assumes that ** the window frame has been set to: @@ -145283,7 +145732,7 @@ static void rankValueFunc(sqlite3_context *pCtx){ ** Implementation of built-in window function percent_rank(). Assumes that ** the window frame has been set to: ** -** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW +** GROUPS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING */ static void percent_rankStepFunc( sqlite3_context *pCtx, @@ -145291,38 +145740,44 @@ static void percent_rankStepFunc( sqlite3_value **apArg ){ struct CallCount *p; - UNUSED_PARAMETER(nArg); assert( nArg==1 ); - + UNUSED_PARAMETER(nArg); assert( nArg==0 ); + UNUSED_PARAMETER(apArg); p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p ){ - if( p->nTotal==0 ){ - p->nTotal = sqlite3_value_int64(apArg[0]); - } - p->nStep++; - if( p->nValue==0 ){ - p->nValue = p->nStep; - } + p->nTotal++; } } +static void percent_rankInvFunc( + sqlite3_context *pCtx, + int nArg, + sqlite3_value **apArg +){ + struct CallCount *p; + UNUSED_PARAMETER(nArg); assert( nArg==0 ); + UNUSED_PARAMETER(apArg); + p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); + p->nStep++; +} static void percent_rankValueFunc(sqlite3_context *pCtx){ struct CallCount *p; p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p ){ + p->nValue = p->nStep; if( p->nTotal>1 ){ - double r = (double)(p->nValue-1) / (double)(p->nTotal-1); + double r = (double)p->nValue / (double)(p->nTotal-1); sqlite3_result_double(pCtx, r); }else{ sqlite3_result_double(pCtx, 0.0); } - p->nValue = 0; } } +#define percent_rankFinalizeFunc percent_rankValueFunc /* ** Implementation of built-in window function cume_dist(). Assumes that ** the window frame has been set to: ** -** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW +** GROUPS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING */ static void cume_distStepFunc( sqlite3_context *pCtx, @@ -145330,24 +145785,33 @@ static void cume_distStepFunc( sqlite3_value **apArg ){ struct CallCount *p; - assert( nArg==1 ); UNUSED_PARAMETER(nArg); - + UNUSED_PARAMETER(nArg); assert( nArg==0 ); + UNUSED_PARAMETER(apArg); p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p ){ - if( p->nTotal==0 ){ - p->nTotal = sqlite3_value_int64(apArg[0]); - } - p->nStep++; + p->nTotal++; } } +static void cume_distInvFunc( + sqlite3_context *pCtx, + int nArg, + sqlite3_value **apArg +){ + struct CallCount *p; + UNUSED_PARAMETER(nArg); assert( nArg==0 ); + UNUSED_PARAMETER(apArg); + p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); + p->nStep++; +} static void cume_distValueFunc(sqlite3_context *pCtx){ struct CallCount *p; - p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p)); - if( p && p->nTotal ){ + p = (struct CallCount*)sqlite3_aggregate_context(pCtx, 0); + if( p ){ double r = (double)(p->nStep) / (double)(p->nTotal); sqlite3_result_double(pCtx, r); } } +#define cume_distFinalizeFunc cume_distValueFunc /* ** Context object for ntile() window function. @@ -145362,7 +145826,7 @@ struct NtileCtx { ** Implementation of ntile(). This assumes that the window frame has ** been coerced to: ** -** ROWS UNBOUNDED PRECEDING AND CURRENT ROW +** ROWS CURRENT ROW AND UNBOUNDED FOLLOWING */ static void ntileStepFunc( sqlite3_context *pCtx, @@ -145370,32 +145834,42 @@ static void ntileStepFunc( sqlite3_value **apArg ){ struct NtileCtx *p; - assert( nArg==2 ); UNUSED_PARAMETER(nArg); + assert( nArg==1 ); UNUSED_PARAMETER(nArg); p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p ){ if( p->nTotal==0 ){ p->nParam = sqlite3_value_int64(apArg[0]); - p->nTotal = sqlite3_value_int64(apArg[1]); if( p->nParam<=0 ){ sqlite3_result_error( pCtx, "argument of ntile must be a positive integer", -1 ); } } - p->iRow++; + p->nTotal++; } } +static void ntileInvFunc( + sqlite3_context *pCtx, + int nArg, + sqlite3_value **apArg +){ + struct NtileCtx *p; + assert( nArg==1 ); UNUSED_PARAMETER(nArg); + UNUSED_PARAMETER(apArg); + p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); + p->iRow++; +} static void ntileValueFunc(sqlite3_context *pCtx){ struct NtileCtx *p; p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); if( p && p->nParam>0 ){ int nSize = (p->nTotal / p->nParam); if( nSize==0 ){ - sqlite3_result_int64(pCtx, p->iRow); + sqlite3_result_int64(pCtx, p->iRow+1); }else{ i64 nLarge = p->nTotal - p->nParam*nSize; i64 iSmall = nLarge*(nSize+1); - i64 iRow = p->iRow-1; + i64 iRow = p->iRow; assert( (nLarge*(nSize+1) + (p->nParam-nLarge)*nSize)==p->nTotal ); @@ -145407,6 +145881,7 @@ static void ntileValueFunc(sqlite3_context *pCtx){ } } } +#define ntileFinalizeFunc ntileValueFunc /* ** Context object for last_value() window function. @@ -145456,7 +145931,7 @@ static void last_valueInvFunc( } static void last_valueValueFunc(sqlite3_context *pCtx){ struct LastValueCtx *p; - p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p)); + p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, 0); if( p && p->pVal ){ sqlite3_result_value(pCtx, p->pVal); } @@ -145546,12 +146021,12 @@ SQLITE_PRIVATE void sqlite3WindowFunctions(void){ WINDOWFUNCX(row_number, 0, 0), WINDOWFUNCX(dense_rank, 0, 0), WINDOWFUNCX(rank, 0, 0), - WINDOWFUNCX(percent_rank, 0, SQLITE_FUNC_WINDOW_SIZE), - WINDOWFUNCX(cume_dist, 0, SQLITE_FUNC_WINDOW_SIZE), - WINDOWFUNCX(ntile, 1, SQLITE_FUNC_WINDOW_SIZE), + WINDOWFUNCALL(percent_rank, 0, 0), + WINDOWFUNCALL(cume_dist, 0, 0), + WINDOWFUNCALL(ntile, 1, 0), WINDOWFUNCALL(last_value, 1, 0), - WINDOWFUNCNOOP(nth_value, 2, 0), - WINDOWFUNCNOOP(first_value, 1, 0), + WINDOWFUNCALL(nth_value, 2, 0), + WINDOWFUNCALL(first_value, 1, 0), WINDOWFUNCNOOP(lead, 1, 0), WINDOWFUNCNOOP(lead, 2, 0), WINDOWFUNCNOOP(lead, 3, 0), @@ -145562,6 +146037,17 @@ SQLITE_PRIVATE void sqlite3WindowFunctions(void){ sqlite3InsertBuiltinFuncs(aWindowFuncs, ArraySize(aWindowFuncs)); } +static Window *windowFind(Parse *pParse, Window *pList, const char *zName){ + Window *p; + for(p=pList; p; p=p->pNextWin){ + if( sqlite3StrICmp(p->zName, zName)==0 ) break; + } + if( p==0 ){ + sqlite3ErrorMsg(pParse, "no such window: %s", zName); + } + return p; +} + /* ** This function is called immediately after resolving the function name ** for a window function within a SELECT statement. Argument pList is a @@ -145585,48 +146071,66 @@ SQLITE_PRIVATE void sqlite3WindowUpdate( Window *pWin, /* Window frame to update */ FuncDef *pFunc /* Window function definition */ ){ - if( pWin->zName && pWin->eType==0 ){ - Window *p; - for(p=pList; p; p=p->pNextWin){ - if( sqlite3StrICmp(p->zName, pWin->zName)==0 ) break; - } - if( p==0 ){ - sqlite3ErrorMsg(pParse, "no such window: %s", pWin->zName); - return; - } + if( pWin->zName && pWin->eFrmType==0 ){ + Window *p = windowFind(pParse, pList, pWin->zName); + if( p==0 ) return; pWin->pPartition = sqlite3ExprListDup(pParse->db, p->pPartition, 0); pWin->pOrderBy = sqlite3ExprListDup(pParse->db, p->pOrderBy, 0); pWin->pStart = sqlite3ExprDup(pParse->db, p->pStart, 0); pWin->pEnd = sqlite3ExprDup(pParse->db, p->pEnd, 0); pWin->eStart = p->eStart; pWin->eEnd = p->eEnd; - pWin->eType = p->eType; + pWin->eFrmType = p->eFrmType; + pWin->eExclude = p->eExclude; + }else{ + sqlite3WindowChain(pParse, pWin, pList); } + if( (pWin->eFrmType==TK_RANGE) + && (pWin->pStart || pWin->pEnd) + && (pWin->pOrderBy==0 || pWin->pOrderBy->nExpr!=1) + ){ + sqlite3ErrorMsg(pParse, + "RANGE with offset PRECEDING/FOLLOWING requires one ORDER BY expression" + ); + }else if( pFunc->funcFlags & SQLITE_FUNC_WINDOW ){ sqlite3 *db = pParse->db; if( pWin->pFilter ){ sqlite3ErrorMsg(pParse, "FILTER clause may only be used with aggregate window functions" ); - }else - if( pFunc->zName==row_numberName || pFunc->zName==ntileName ){ - sqlite3ExprDelete(db, pWin->pStart); - sqlite3ExprDelete(db, pWin->pEnd); - pWin->pStart = pWin->pEnd = 0; - pWin->eType = TK_ROWS; - pWin->eStart = TK_UNBOUNDED; - pWin->eEnd = TK_CURRENT; - }else - - if( pFunc->zName==dense_rankName || pFunc->zName==rankName - || pFunc->zName==percent_rankName || pFunc->zName==cume_distName - ){ - sqlite3ExprDelete(db, pWin->pStart); - sqlite3ExprDelete(db, pWin->pEnd); - pWin->pStart = pWin->pEnd = 0; - pWin->eType = TK_RANGE; - pWin->eStart = TK_UNBOUNDED; - pWin->eEnd = TK_CURRENT; + }else{ + struct WindowUpdate { + const char *zFunc; + int eFrmType; + int eStart; + int eEnd; + } aUp[] = { + { row_numberName, TK_ROWS, TK_UNBOUNDED, TK_CURRENT }, + { dense_rankName, TK_RANGE, TK_UNBOUNDED, TK_CURRENT }, + { rankName, TK_RANGE, TK_UNBOUNDED, TK_CURRENT }, + { percent_rankName, TK_GROUPS, TK_CURRENT, TK_UNBOUNDED }, + { cume_distName, TK_GROUPS, TK_FOLLOWING, TK_UNBOUNDED }, + { ntileName, TK_ROWS, TK_CURRENT, TK_UNBOUNDED }, + { leadName, TK_ROWS, TK_UNBOUNDED, TK_UNBOUNDED }, + { lagName, TK_ROWS, TK_UNBOUNDED, TK_CURRENT }, + }; + int i; + for(i=0; izName==aUp[i].zFunc ){ + sqlite3ExprDelete(db, pWin->pStart); + sqlite3ExprDelete(db, pWin->pEnd); + pWin->pEnd = pWin->pStart = 0; + pWin->eFrmType = aUp[i].eFrmType; + pWin->eStart = aUp[i].eStart; + pWin->eEnd = aUp[i].eEnd; + pWin->eExclude = 0; + if( pWin->eStart==TK_FOLLOWING ){ + pWin->pStart = sqlite3Expr(db, TK_INTEGER, "1"); + } + break; + } + } } } pWin->pFunc = pFunc; @@ -145831,6 +146335,7 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){ ** The OpenEphemeral instruction is coded later, after it is known how ** many columns the table will have. */ pMWin->iEphCsr = pParse->nTab++; + pParse->nTab += 3; selectWindowRewriteEList(pParse, pMWin, pSrc, p->pEList, &pSublist); selectWindowRewriteEList(pParse, pMWin, pSrc, p->pOrderBy, &pSublist); @@ -145886,6 +146391,9 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){ } sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, pSublist->nExpr); + sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+1, pMWin->iEphCsr); + sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+2, pMWin->iEphCsr); + sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+3, pMWin->iEphCsr); }else{ sqlite3SelectDelete(db, pSub); } @@ -145906,6 +146414,7 @@ SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3 *db, Window *p){ sqlite3ExprDelete(db, p->pEnd); sqlite3ExprDelete(db, p->pStart); sqlite3DbFree(db, p->zName); + sqlite3DbFree(db, p->zBase); sqlite3DbFree(db, p); } } @@ -145942,16 +146451,18 @@ static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){ */ SQLITE_PRIVATE Window *sqlite3WindowAlloc( Parse *pParse, /* Parsing context */ - int eType, /* Frame type. TK_RANGE or TK_ROWS */ + int eType, /* Frame type. TK_RANGE, TK_ROWS, TK_GROUPS, or 0 */ int eStart, /* Start type: CURRENT, PRECEDING, FOLLOWING, UNBOUNDED */ Expr *pStart, /* Start window size if TK_PRECEDING or FOLLOWING */ int eEnd, /* End type: CURRENT, FOLLOWING, TK_UNBOUNDED, PRECEDING */ - Expr *pEnd /* End window size if TK_FOLLOWING or PRECEDING */ + Expr *pEnd, /* End window size if TK_FOLLOWING or PRECEDING */ + u8 eExclude /* EXCLUDE clause */ ){ Window *pWin = 0; + int bImplicitFrame = 0; /* Parser assures the following: */ - assert( eType==TK_RANGE || eType==TK_ROWS ); + assert( eType==0 || eType==TK_RANGE || eType==TK_ROWS || eType==TK_GROUPS ); assert( eStart==TK_CURRENT || eStart==TK_PRECEDING || eStart==TK_UNBOUNDED || eStart==TK_FOLLOWING ); assert( eEnd==TK_CURRENT || eEnd==TK_FOLLOWING @@ -145959,13 +146470,9 @@ SQLITE_PRIVATE Window *sqlite3WindowAlloc( assert( (eStart==TK_PRECEDING || eStart==TK_FOLLOWING)==(pStart!=0) ); assert( (eEnd==TK_FOLLOWING || eEnd==TK_PRECEDING)==(pEnd!=0) ); - - /* If a frame is declared "RANGE" (not "ROWS"), then it may not use - ** either " PRECEDING" or " FOLLOWING". - */ - if( eType==TK_RANGE && (pStart!=0 || pEnd!=0) ){ - sqlite3ErrorMsg(pParse, "RANGE must use only UNBOUNDED or CURRENT ROW"); - goto windowAllocErr; + if( eType==0 ){ + bImplicitFrame = 1; + eType = TK_RANGE; } /* Additionally, the @@ -145985,15 +146492,20 @@ SQLITE_PRIVATE Window *sqlite3WindowAlloc( if( (eStart==TK_CURRENT && eEnd==TK_PRECEDING) || (eStart==TK_FOLLOWING && (eEnd==TK_PRECEDING || eEnd==TK_CURRENT)) ){ - sqlite3ErrorMsg(pParse, "unsupported frame delimiter for ROWS"); + sqlite3ErrorMsg(pParse, "unsupported frame specification"); goto windowAllocErr; } pWin = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); if( pWin==0 ) goto windowAllocErr; - pWin->eType = eType; + pWin->eFrmType = eType; pWin->eStart = eStart; pWin->eEnd = eEnd; + if( eExclude==0 && OptimizationDisabled(pParse->db, SQLITE_WindowFunc) ){ + eExclude = TK_NO; + } + pWin->eExclude = eExclude; + pWin->bImplicitFrame = bImplicitFrame; pWin->pEnd = sqlite3WindowOffsetExpr(pParse, pEnd); pWin->pStart = sqlite3WindowOffsetExpr(pParse, pStart); return pWin; @@ -146004,6 +146516,69 @@ windowAllocErr: return 0; } +/* +** Attach PARTITION and ORDER BY clauses pPartition and pOrderBy to window +** pWin. Also, if parameter pBase is not NULL, set pWin->zBase to the +** equivalent nul-terminated string. +*/ +SQLITE_PRIVATE Window *sqlite3WindowAssemble( + Parse *pParse, + Window *pWin, + ExprList *pPartition, + ExprList *pOrderBy, + Token *pBase +){ + if( pWin ){ + pWin->pPartition = pPartition; + pWin->pOrderBy = pOrderBy; + if( pBase ){ + pWin->zBase = sqlite3DbStrNDup(pParse->db, pBase->z, pBase->n); + } + }else{ + sqlite3ExprListDelete(pParse->db, pPartition); + sqlite3ExprListDelete(pParse->db, pOrderBy); + } + return pWin; +} + +/* +** Window *pWin has just been created from a WINDOW clause. Tokne pBase +** is the base window. Earlier windows from the same WINDOW clause are +** stored in the linked list starting at pWin->pNextWin. This function +** either updates *pWin according to the base specification, or else +** leaves an error in pParse. +*/ +SQLITE_PRIVATE void sqlite3WindowChain(Parse *pParse, Window *pWin, Window *pList){ + if( pWin->zBase ){ + sqlite3 *db = pParse->db; + Window *pExist = windowFind(pParse, pList, pWin->zBase); + if( pExist ){ + const char *zErr = 0; + /* Check for errors */ + if( pWin->pPartition ){ + zErr = "PARTITION clause"; + }else if( pExist->pOrderBy && pWin->pOrderBy ){ + zErr = "ORDER BY clause"; + }else if( pExist->bImplicitFrame==0 ){ + zErr = "frame specification"; + } + if( zErr ){ + sqlite3ErrorMsg(pParse, + "cannot override %s of window: %s", zErr, pWin->zBase + ); + }else{ + pWin->pPartition = sqlite3ExprListDup(db, pExist->pPartition, 0); + if( pExist->pOrderBy ){ + assert( pWin->pOrderBy==0 ); + pWin->pOrderBy = sqlite3ExprListDup(db, pExist->pOrderBy, 0); + } + sqlite3DbFree(db, pWin->zBase); + pWin->zBase = 0; + } + } + } +} + /* ** Attach window object pWin to expression p. */ @@ -146032,9 +146607,10 @@ SQLITE_PRIVATE void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){ ** Identical window objects can be processed in a single scan. */ SQLITE_PRIVATE int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2){ - if( p1->eType!=p2->eType ) return 1; + if( p1->eFrmType!=p2->eFrmType ) return 1; if( p1->eStart!=p2->eStart ) return 1; if( p1->eEnd!=p2->eEnd ) return 1; + if( p1->eExclude!=p2->eExclude ) return 1; if( sqlite3ExprCompare(pParse, p1->pStart, p2->pStart, -1) ) return 1; if( sqlite3ExprCompare(pParse, p1->pEnd, p2->pEnd, -1) ) return 1; if( sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1) ) return 1; @@ -146051,12 +146627,27 @@ SQLITE_PRIVATE int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2){ SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){ Window *pWin; Vdbe *v = sqlite3GetVdbe(pParse); - int nPart = (pMWin->pPartition ? pMWin->pPartition->nExpr : 0); - nPart += (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0); - if( nPart ){ + + /* Allocate registers to use for PARTITION BY values, if any. Initialize + ** said registers to NULL. */ + if( pMWin->pPartition ){ + int nExpr = pMWin->pPartition->nExpr; pMWin->regPart = pParse->nMem+1; - pParse->nMem += nPart; - sqlite3VdbeAddOp3(v, OP_Null, 0, pMWin->regPart, pMWin->regPart+nPart-1); + pParse->nMem += nExpr; + sqlite3VdbeAddOp3(v, OP_Null, 0, pMWin->regPart, pMWin->regPart+nExpr-1); + } + + pMWin->regOne = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regOne); + + if( pMWin->eExclude ){ + pMWin->regStartRowid = ++pParse->nMem; + pMWin->regEndRowid = ++pParse->nMem; + pMWin->csrApp = pParse->nTab++; + sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regStartRowid); + sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regEndRowid); + sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->csrApp, pMWin->iEphCsr); + return; } for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ @@ -146085,20 +146676,24 @@ SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){ else if( p->zName==nth_valueName || p->zName==first_valueName ){ /* Allocate two registers at pWin->regApp. These will be used to ** store the start and end index of the current frame. */ - assert( pMWin->iEphCsr ); pWin->regApp = pParse->nMem+1; pWin->csrApp = pParse->nTab++; pParse->nMem += 2; sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr); } else if( p->zName==leadName || p->zName==lagName ){ - assert( pMWin->iEphCsr ); pWin->csrApp = pParse->nTab++; sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr); } } } +#define WINDOW_STARTING_INT 0 +#define WINDOW_ENDING_INT 1 +#define WINDOW_NTH_VALUE_INT 2 +#define WINDOW_STARTING_NUM 3 +#define WINDOW_ENDING_NUM 4 + /* ** A "PRECEDING " (eCond==0) or "FOLLOWING " (eCond==1) or the ** value of the second argument to nth_value() (eCond==2) has just been @@ -146106,25 +146701,42 @@ SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){ ** code to check that the value is a non-negative integer and throws an ** exception if it is not. */ -static void windowCheckIntValue(Parse *pParse, int reg, int eCond){ +static void windowCheckValue(Parse *pParse, int reg, int eCond){ static const char *azErr[] = { "frame starting offset must be a non-negative integer", "frame ending offset must be a non-negative integer", - "second argument to nth_value must be a positive integer" + "second argument to nth_value must be a positive integer", + "frame starting offset must be a non-negative number", + "frame ending offset must be a non-negative number", }; - static int aOp[] = { OP_Ge, OP_Ge, OP_Gt }; + static int aOp[] = { OP_Ge, OP_Ge, OP_Gt, OP_Ge, OP_Ge }; Vdbe *v = sqlite3GetVdbe(pParse); int regZero = sqlite3GetTempReg(pParse); - assert( eCond==0 || eCond==1 || eCond==2 ); + assert( eCond>=0 && eCond=WINDOW_STARTING_NUM ){ + int regString = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC); + sqlite3VdbeAddOp3(v, OP_Ge, regString, sqlite3VdbeCurrentAddr(v)+2, reg); + sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC|SQLITE_JUMPIFNULL); + VdbeCoverage(v); + assert( eCond==3 || eCond==4 ); + VdbeCoverageIf(v, eCond==3); + VdbeCoverageIf(v, eCond==4); + }else{ + sqlite3VdbeAddOp2(v, OP_MustBeInt, reg, sqlite3VdbeCurrentAddr(v)+2); + VdbeCoverage(v); + assert( eCond==0 || eCond==1 || eCond==2 ); + VdbeCoverageIf(v, eCond==0); + VdbeCoverageIf(v, eCond==1); + VdbeCoverageIf(v, eCond==2); + } sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg); - VdbeCoverageNeverNullIf(v, eCond==0); - VdbeCoverageNeverNullIf(v, eCond==1); + VdbeCoverageNeverNullIf(v, eCond==0); /* NULL case captured by */ + VdbeCoverageNeverNullIf(v, eCond==1); /* the OP_MustBeInt */ VdbeCoverageNeverNullIf(v, eCond==2); + VdbeCoverageNeverNullIf(v, eCond==3); /* NULL case caught by */ + VdbeCoverageNeverNullIf(v, eCond==4); /* the OP_Ge */ sqlite3MayAbort(pParse); sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort); sqlite3VdbeAppendP4(v, (void*)azErr[eCond], P4_STATIC); @@ -146164,37 +146776,28 @@ static void windowAggStep( Window *pMWin, /* Linked list of window functions */ int csr, /* Read arguments from this cursor */ int bInverse, /* True to invoke xInverse instead of xStep */ - int reg, /* Array of registers */ - int regPartSize /* Register containing size of partition */ + int reg /* Array of registers */ ){ Vdbe *v = sqlite3GetVdbe(pParse); Window *pWin; for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - int flags = pWin->pFunc->funcFlags; + FuncDef *pFunc = pWin->pFunc; int regArg; int nArg = windowArgCount(pWin); + int i; - if( csr>=0 ){ - int i; - for(i=0; izName!=nth_valueName ){ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i); + }else{ + sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+i, reg+i); } - regArg = reg; - if( flags & SQLITE_FUNC_WINDOW_SIZE ){ - if( nArg==0 ){ - regArg = regPartSize; - }else{ - sqlite3VdbeAddOp2(v, OP_SCopy, regPartSize, reg+nArg); - } - nArg++; - } - }else{ - assert( !(flags & SQLITE_FUNC_WINDOW_SIZE) ); - regArg = reg + pWin->iArgCol; } + regArg = reg; - if( (pWin->pFunc->funcFlags & SQLITE_FUNC_MINMAX) - && pWin->eStart!=TK_UNBOUNDED + if( pMWin->regStartRowid==0 + && (pFunc->funcFlags & SQLITE_FUNC_MINMAX) + && (pWin->eStart!=TK_UNBOUNDED) ){ int addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regArg); VdbeCoverage(v); @@ -146211,34 +146814,24 @@ static void windowAggStep( } sqlite3VdbeJumpHere(v, addrIsNull); }else if( pWin->regApp ){ - assert( pWin->pFunc->zName==nth_valueName - || pWin->pFunc->zName==first_valueName + assert( pFunc->zName==nth_valueName + || pFunc->zName==first_valueName ); assert( bInverse==0 || bInverse==1 ); sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1-bInverse, 1); - }else if( pWin->pFunc->zName==leadName - || pWin->pFunc->zName==lagName - ){ - /* no-op */ - }else{ + }else if( pFunc->xSFunc!=noopStepFunc ){ int addrIf = 0; if( pWin->pFilter ){ int regTmp; assert( nArg==0 || nArg==pWin->pOwner->x.pList->nExpr ); assert( nArg || pWin->pOwner->x.pList==0 ); - if( csr>0 ){ - regTmp = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp); - }else{ - regTmp = regArg + nArg; - } + regTmp = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp); addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1); VdbeCoverage(v); - if( csr>0 ){ - sqlite3ReleaseTempReg(pParse, regTmp); - } + sqlite3ReleaseTempReg(pParse, regTmp); } - if( pWin->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ + if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ CollSeq *pColl; assert( nArg>0 ); pColl = sqlite3ExprNNCollSeq(pParse, pWin->pOwner->x.pList->a[0].pExpr); @@ -146246,45 +146839,96 @@ static void windowAggStep( } sqlite3VdbeAddOp3(v, bInverse? OP_AggInverse : OP_AggStep, bInverse, regArg, pWin->regAccum); - sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF); + sqlite3VdbeAppendP4(v, pFunc, P4_FUNCDEF); sqlite3VdbeChangeP5(v, (u8)nArg); if( addrIf ) sqlite3VdbeJumpHere(v, addrIf); } } } +typedef struct WindowCodeArg WindowCodeArg; +typedef struct WindowCsrAndReg WindowCsrAndReg; +struct WindowCsrAndReg { + int csr; + int reg; +}; + +struct WindowCodeArg { + Parse *pParse; + Window *pMWin; + Vdbe *pVdbe; + int regGosub; + int addrGosub; + int regArg; + int eDelete; + + WindowCsrAndReg start; + WindowCsrAndReg current; + WindowCsrAndReg end; +}; + /* -** Generate VM code to invoke either xValue() (bFinal==0) or xFinalize() -** (bFinal==1) for each window function in the linked list starting at +** Values that may be passed as the second argument to windowCodeOp(). +*/ +#define WINDOW_RETURN_ROW 1 +#define WINDOW_AGGINVERSE 2 +#define WINDOW_AGGSTEP 3 + +/* +** Generate VM code to read the window frames peer values from cursor csr into +** an array of registers starting at reg. +*/ +static void windowReadPeerValues( + WindowCodeArg *p, + int csr, + int reg +){ + Window *pMWin = p->pMWin; + ExprList *pOrderBy = pMWin->pOrderBy; + if( pOrderBy ){ + Vdbe *v = sqlite3GetVdbe(p->pParse); + ExprList *pPart = pMWin->pPartition; + int iColOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0); + int i; + for(i=0; inExpr; i++){ + sqlite3VdbeAddOp3(v, OP_Column, csr, iColOff+i, reg+i); + } + } +} + +/* +** Generate VM code to invoke either xValue() (bFin==0) or xFinalize() +** (bFin==1) for each window function in the linked list starting at ** pMWin. Or, for built-in window-functions that do not use the standard ** API, generate the equivalent VM code. */ -static void windowAggFinal(Parse *pParse, Window *pMWin, int bFinal){ +static void windowAggFinal(WindowCodeArg *p, int bFin){ + Parse *pParse = p->pParse; + Window *pMWin = p->pMWin; Vdbe *v = sqlite3GetVdbe(pParse); Window *pWin; for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - if( (pWin->pFunc->funcFlags & SQLITE_FUNC_MINMAX) - && pWin->eStart!=TK_UNBOUNDED + if( pMWin->regStartRowid==0 + && (pWin->pFunc->funcFlags & SQLITE_FUNC_MINMAX) + && (pWin->eStart!=TK_UNBOUNDED) ){ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); sqlite3VdbeAddOp1(v, OP_Last, pWin->csrApp); VdbeCoverage(v); sqlite3VdbeAddOp3(v, OP_Column, pWin->csrApp, 0, pWin->regResult); sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2); - if( bFinal ){ - sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp); - } }else if( pWin->regApp ){ + assert( pMWin->regStartRowid==0 ); }else{ - if( bFinal ){ - sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, windowArgCount(pWin)); + int nArg = windowArgCount(pWin); + if( bFin ){ + sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, nArg); sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF); sqlite3VdbeAddOp2(v, OP_Copy, pWin->regAccum, pWin->regResult); sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); }else{ - sqlite3VdbeAddOp3(v, OP_AggValue, pWin->regAccum, windowArgCount(pWin), - pWin->regResult); + sqlite3VdbeAddOp3(v, OP_AggValue,pWin->regAccum,nArg,pWin->regResult); sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF); } } @@ -146292,66 +146936,97 @@ static void windowAggFinal(Parse *pParse, Window *pMWin, int bFinal){ } /* -** This function generates VM code to invoke the sub-routine at address -** lblFlushPart once for each partition with the entire partition cached in -** the Window.iEphCsr temp table. +** Generate code to calculate the current values of all window functions in the +** p->pMWin list by doing a full scan of the current window frame. Store the +** results in the Window.regResult registers, ready to return the upper +** layer. */ -static void windowPartitionCache( - Parse *pParse, - Select *p, /* The rewritten SELECT statement */ - WhereInfo *pWInfo, /* WhereInfo to call WhereEnd() on */ - int regFlushPart, /* Register to use with Gosub lblFlushPart */ - int lblFlushPart, /* Subroutine to Gosub to */ - int *pRegSize /* OUT: Register containing partition size */ -){ - Window *pMWin = p->pWin; - Vdbe *v = sqlite3GetVdbe(pParse); - int iSubCsr = p->pSrc->a[0].iCursor; - int nSub = p->pSrc->a[0].pTab->nCol; - int k; +static void windowFullScan(WindowCodeArg *p){ + Window *pWin; + Parse *pParse = p->pParse; + Window *pMWin = p->pMWin; + Vdbe *v = p->pVdbe; - int reg = pParse->nMem+1; - int regRecord = reg+nSub; - int regRowid = regRecord+1; + int regCRowid = 0; /* Current rowid value */ + int regCPeer = 0; /* Current peer values */ + int regRowid = 0; /* AggStep rowid value */ + int regPeer = 0; /* AggStep peer values */ - *pRegSize = regRowid; - pParse->nMem += nSub + 2; + int nPeer; + int lblNext; + int lblBrk; + int addrNext; + int csr = pMWin->csrApp; - /* Load the column values for the row returned by the sub-select - ** into an array of registers starting at reg. */ - for(k=0; kpOrderBy ? pMWin->pOrderBy->nExpr : 0); + + lblNext = sqlite3VdbeMakeLabel(pParse); + lblBrk = sqlite3VdbeMakeLabel(pParse); + + regCRowid = sqlite3GetTempReg(pParse); + regRowid = sqlite3GetTempReg(pParse); + if( nPeer ){ + regCPeer = sqlite3GetTempRange(pParse, nPeer); + regPeer = sqlite3GetTempRange(pParse, nPeer); } - sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, nSub, regRecord); - /* Check if this is the start of a new partition. If so, call the - ** flush_partition sub-routine. */ - if( pMWin->pPartition ){ + sqlite3VdbeAddOp2(v, OP_Rowid, pMWin->iEphCsr, regCRowid); + windowReadPeerValues(p, pMWin->iEphCsr, regCPeer); + + for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ + sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); + } + + sqlite3VdbeAddOp3(v, OP_SeekGE, csr, lblBrk, pMWin->regStartRowid); + VdbeCoverage(v); + addrNext = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp2(v, OP_Rowid, csr, regRowid); + sqlite3VdbeAddOp3(v, OP_Gt, pMWin->regEndRowid, lblBrk, regRowid); + VdbeCoverageNeverNull(v); + + if( pMWin->eExclude==TK_CURRENT ){ + sqlite3VdbeAddOp3(v, OP_Eq, regCRowid, lblNext, regRowid); + VdbeCoverageNeverNull(v); + }else if( pMWin->eExclude!=TK_NO ){ int addr; - ExprList *pPart = pMWin->pPartition; - int nPart = pPart->nExpr; - int regNewPart = reg + pMWin->nBufferCol; - KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0); + int addrEq = 0; + KeyInfo *pKeyInfo = 0; - addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart,nPart); - sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); - sqlite3VdbeAddOp3(v, OP_Jump, addr+2, addr+4, addr+2); - VdbeCoverageEqNe(v); - sqlite3VdbeAddOp3(v, OP_Copy, regNewPart, pMWin->regPart, nPart-1); - sqlite3VdbeAddOp2(v, OP_Gosub, regFlushPart, lblFlushPart); - VdbeComment((v, "call flush_partition")); + if( pMWin->pOrderBy ){ + pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pMWin->pOrderBy, 0, 0); + } + if( pMWin->eExclude==TK_TIES ){ + addrEq = sqlite3VdbeAddOp3(v, OP_Eq, regCRowid, 0, regRowid); + VdbeCoverageNeverNull(v); + } + if( pKeyInfo ){ + windowReadPeerValues(p, csr, regPeer); + sqlite3VdbeAddOp3(v, OP_Compare, regPeer, regCPeer, nPeer); + sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); + addr = sqlite3VdbeCurrentAddr(v)+1; + sqlite3VdbeAddOp3(v, OP_Jump, addr, lblNext, addr); + VdbeCoverageEqNe(v); + }else{ + sqlite3VdbeAddOp2(v, OP_Goto, 0, lblNext); + } + if( addrEq ) sqlite3VdbeJumpHere(v, addrEq); } - /* Buffer the current row in the ephemeral table. */ - sqlite3VdbeAddOp2(v, OP_NewRowid, pMWin->iEphCsr, regRowid); - sqlite3VdbeAddOp3(v, OP_Insert, pMWin->iEphCsr, regRecord, regRowid); + windowAggStep(pParse, pMWin, csr, 0, p->regArg); - /* End of the input loop */ - sqlite3WhereEnd(pWInfo); + sqlite3VdbeResolveLabel(v, lblNext); + sqlite3VdbeAddOp2(v, OP_Next, csr, addrNext); + VdbeCoverage(v); + sqlite3VdbeJumpHere(v, addrNext-1); + sqlite3VdbeJumpHere(v, addrNext+1); + sqlite3ReleaseTempReg(pParse, regRowid); + sqlite3ReleaseTempReg(pParse, regCRowid); + if( nPeer ){ + sqlite3ReleaseTempRange(pParse, regPeer, nPeer); + sqlite3ReleaseTempRange(pParse, regCPeer, nPeer); + } - /* Invoke "flush_partition" to deal with the final (or only) partition */ - sqlite3VdbeAddOp2(v, OP_Gosub, regFlushPart, lblFlushPart); - VdbeComment((v, "call flush_partition")); + windowAggFinal(p, 1); } /* @@ -146367,110 +147042,74 @@ static void windowPartitionCache( ** lag() ** lead() */ -static void windowReturnOneRow( - Parse *pParse, - Window *pMWin, - int regGosub, - int addrGosub -){ - Vdbe *v = sqlite3GetVdbe(pParse); - Window *pWin; - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - FuncDef *pFunc = pWin->pFunc; - if( pFunc->zName==nth_valueName - || pFunc->zName==first_valueName - ){ - int csr = pWin->csrApp; - int lbl = sqlite3VdbeMakeLabel(pParse); - int tmpReg = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); +static void windowReturnOneRow(WindowCodeArg *p){ + Window *pMWin = p->pMWin; + Vdbe *v = p->pVdbe; - if( pFunc->zName==nth_valueName ){ - sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+1,tmpReg); - windowCheckIntValue(pParse, tmpReg, 2); - }else{ - sqlite3VdbeAddOp2(v, OP_Integer, 1, tmpReg); - } - sqlite3VdbeAddOp3(v, OP_Add, tmpReg, pWin->regApp, tmpReg); - sqlite3VdbeAddOp3(v, OP_Gt, pWin->regApp+1, lbl, tmpReg); - VdbeCoverageNeverNull(v); - sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, 0, tmpReg); - VdbeCoverageNeverTaken(v); - sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult); - sqlite3VdbeResolveLabel(v, lbl); - sqlite3ReleaseTempReg(pParse, tmpReg); - } - else if( pFunc->zName==leadName || pFunc->zName==lagName ){ - int nArg = pWin->pOwner->x.pList->nExpr; - int iEph = pMWin->iEphCsr; - int csr = pWin->csrApp; - int lbl = sqlite3VdbeMakeLabel(pParse); - int tmpReg = sqlite3GetTempReg(pParse); + if( pMWin->regStartRowid ){ + windowFullScan(p); + }else{ + Parse *pParse = p->pParse; + Window *pWin; - if( nArg<3 ){ + for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ + FuncDef *pFunc = pWin->pFunc; + if( pFunc->zName==nth_valueName + || pFunc->zName==first_valueName + ){ + int csr = pWin->csrApp; + int lbl = sqlite3VdbeMakeLabel(pParse); + int tmpReg = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); - }else{ - sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+2, pWin->regResult); + + if( pFunc->zName==nth_valueName ){ + sqlite3VdbeAddOp3(v, OP_Column,pMWin->iEphCsr,pWin->iArgCol+1,tmpReg); + windowCheckValue(pParse, tmpReg, 2); + }else{ + sqlite3VdbeAddOp2(v, OP_Integer, 1, tmpReg); + } + sqlite3VdbeAddOp3(v, OP_Add, tmpReg, pWin->regApp, tmpReg); + sqlite3VdbeAddOp3(v, OP_Gt, pWin->regApp+1, lbl, tmpReg); + VdbeCoverageNeverNull(v); + sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, 0, tmpReg); + VdbeCoverageNeverTaken(v); + sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult); + sqlite3VdbeResolveLabel(v, lbl); + sqlite3ReleaseTempReg(pParse, tmpReg); } - sqlite3VdbeAddOp2(v, OP_Rowid, iEph, tmpReg); - if( nArg<2 ){ - int val = (pFunc->zName==leadName ? 1 : -1); - sqlite3VdbeAddOp2(v, OP_AddImm, tmpReg, val); - }else{ - int op = (pFunc->zName==leadName ? OP_Add : OP_Subtract); - int tmpReg2 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+1, tmpReg2); - sqlite3VdbeAddOp3(v, op, tmpReg2, tmpReg, tmpReg); - sqlite3ReleaseTempReg(pParse, tmpReg2); + else if( pFunc->zName==leadName || pFunc->zName==lagName ){ + int nArg = pWin->pOwner->x.pList->nExpr; + int csr = pWin->csrApp; + int lbl = sqlite3VdbeMakeLabel(pParse); + int tmpReg = sqlite3GetTempReg(pParse); + int iEph = pMWin->iEphCsr; + + if( nArg<3 ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); + }else{ + sqlite3VdbeAddOp3(v, OP_Column, iEph,pWin->iArgCol+2,pWin->regResult); + } + sqlite3VdbeAddOp2(v, OP_Rowid, iEph, tmpReg); + if( nArg<2 ){ + int val = (pFunc->zName==leadName ? 1 : -1); + sqlite3VdbeAddOp2(v, OP_AddImm, tmpReg, val); + }else{ + int op = (pFunc->zName==leadName ? OP_Add : OP_Subtract); + int tmpReg2 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+1, tmpReg2); + sqlite3VdbeAddOp3(v, op, tmpReg2, tmpReg, tmpReg); + sqlite3ReleaseTempReg(pParse, tmpReg2); + } + + sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, lbl, tmpReg); + VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult); + sqlite3VdbeResolveLabel(v, lbl); + sqlite3ReleaseTempReg(pParse, tmpReg); } - - sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, lbl, tmpReg); - VdbeCoverage(v); - sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult); - sqlite3VdbeResolveLabel(v, lbl); - sqlite3ReleaseTempReg(pParse, tmpReg); } } - sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub); -} - -/* -** Invoke the code generated by windowReturnOneRow() and, optionally, the -** xInverse() function for each window function, for one or more rows -** from the Window.iEphCsr temp table. This routine generates VM code -** similar to: -** -** while( regCtr>0 ){ -** regCtr--; -** windowReturnOneRow() -** if( bInverse ){ -** AggInverse -** } -** Next (Window.iEphCsr) -** } -*/ -static void windowReturnRows( - Parse *pParse, - Window *pMWin, /* List of window functions */ - int regCtr, /* Register containing number of rows */ - int regGosub, /* Register for Gosub addrGosub */ - int addrGosub, /* Address of sub-routine for ReturnOneRow */ - int regInvArg, /* Array of registers for xInverse args */ - int regInvSize /* Register containing size of partition */ -){ - int addr; - Vdbe *v = sqlite3GetVdbe(pParse); - windowAggFinal(pParse, pMWin, 0); - addr = sqlite3VdbeAddOp3(v, OP_IfPos, regCtr, sqlite3VdbeCurrentAddr(v)+2 ,1); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); - windowReturnOneRow(pParse, pMWin, regGosub, addrGosub); - if( regInvArg ){ - windowAggStep(pParse, pMWin, pMWin->iEphCsr, 1, regInvArg, regInvSize); - } - sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, addr); - VdbeCoverage(v); - sqlite3VdbeJumpHere(v, addr+1); /* The OP_Goto */ + sqlite3VdbeAddOp2(v, OP_Gosub, p->regGosub, p->addrGosub); } /* @@ -146488,17 +147127,17 @@ static int windowInitAccum(Parse *pParse, Window *pMWin){ FuncDef *pFunc = pWin->pFunc; sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); nArg = MAX(nArg, windowArgCount(pWin)); - if( pFunc->zName==nth_valueName - || pFunc->zName==first_valueName - ){ - sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp); - sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); - } + if( pMWin->regStartRowid==0 ){ + if( pFunc->zName==nth_valueName || pFunc->zName==first_valueName ){ + sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp); + sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); + } - if( (pFunc->funcFlags & SQLITE_FUNC_MINMAX) && pWin->csrApp ){ - assert( pWin->eStart!=TK_UNBOUNDED ); - sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp); - sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); + if( (pFunc->funcFlags & SQLITE_FUNC_MINMAX) && pWin->csrApp ){ + assert( pWin->eStart!=TK_UNBOUNDED ); + sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp); + sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1); + } } } regArg = pParse->nMem+1; @@ -146506,672 +147145,248 @@ static int windowInitAccum(Parse *pParse, Window *pMWin){ return regArg; } - -/* -** This function does the work of sqlite3WindowCodeStep() for all "ROWS" -** window frame types except for "BETWEEN UNBOUNDED PRECEDING AND CURRENT -** ROW". Pseudo-code for each follows. -** -** ROWS BETWEEN PRECEDING AND FOLLOWING -** -** ... -** if( new partition ){ -** Gosub flush_partition -** } -** Insert (record in eph-table) -** sqlite3WhereEnd() -** Gosub flush_partition -** -** flush_partition: -** Once { -** OpenDup (iEphCsr -> csrStart) -** OpenDup (iEphCsr -> csrEnd) -** } -** regStart = // PRECEDING expression -** regEnd = // FOLLOWING expression -** if( regStart<0 || regEnd<0 ){ error! } -** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done -** Next(csrEnd) // if EOF skip Aggstep -** Aggstep (csrEnd) -** if( (regEnd--)<=0 ){ -** AggFinal (xValue) -** Gosub addrGosub -** Next(csr) // if EOF goto flush_partition_done -** if( (regStart--)<=0 ){ -** AggInverse (csrStart) -** Next(csrStart) -** } -** } -** flush_partition_done: -** ResetSorter (csr) -** Return -** -** ROWS BETWEEN PRECEDING AND CURRENT ROW -** ROWS BETWEEN CURRENT ROW AND FOLLOWING -** ROWS BETWEEN UNBOUNDED PRECEDING AND FOLLOWING -** -** These are similar to the above. For "CURRENT ROW", intialize the -** register to 0. For "UNBOUNDED PRECEDING" to infinity. -** -** ROWS BETWEEN PRECEDING AND UNBOUNDED FOLLOWING -** ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING -** -** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done -** while( 1 ){ -** Next(csrEnd) // Exit while(1) at EOF -** Aggstep (csrEnd) -** } -** while( 1 ){ -** AggFinal (xValue) -** Gosub addrGosub -** Next(csr) // if EOF goto flush_partition_done -** if( (regStart--)<=0 ){ -** AggInverse (csrStart) -** Next(csrStart) -** } -** } -** -** For the "CURRENT ROW AND UNBOUNDED FOLLOWING" case, the final if() -** condition is always true (as if regStart were initialized to 0). -** -** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING -** -** This is the only RANGE case handled by this routine. It modifies the -** second while( 1 ) loop in "ROWS BETWEEN CURRENT ... UNBOUNDED..." to -** be: -** -** while( 1 ){ -** AggFinal (xValue) -** while( 1 ){ -** regPeer++ -** Gosub addrGosub -** Next(csr) // if EOF goto flush_partition_done -** if( new peer ) break; -** } -** while( (regPeer--)>0 ){ -** AggInverse (csrStart) -** Next(csrStart) -** } -** } -** -** ROWS BETWEEN FOLLOWING AND FOLLOWING -** -** regEnd = regEnd - regStart -** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done -** Aggstep (csrEnd) -** Next(csrEnd) // if EOF fall-through -** if( (regEnd--)<=0 ){ -** if( (regStart--)<=0 ){ -** AggFinal (xValue) -** Gosub addrGosub -** Next(csr) // if EOF goto flush_partition_done -** } -** AggInverse (csrStart) -** Next (csrStart) -** } -** -** ROWS BETWEEN PRECEDING AND PRECEDING -** -** Replace the bit after "Rewind" in the above with: -** -** if( (regEnd--)<=0 ){ -** AggStep (csrEnd) -** Next (csrEnd) -** } -** AggFinal (xValue) -** Gosub addrGosub -** Next(csr) // if EOF goto flush_partition_done -** if( (regStart--)<=0 ){ -** AggInverse (csr2) -** Next (csr2) -** } -** +/* +** Return true if the current frame should be cached in the ephemeral table, +** even if there are no xInverse() calls required. */ -static void windowCodeRowExprStep( - Parse *pParse, - Select *p, - WhereInfo *pWInfo, - int regGosub, - int addrGosub -){ - Window *pMWin = p->pWin; - Vdbe *v = sqlite3GetVdbe(pParse); - int regFlushPart; /* Register for "Gosub flush_partition" */ - int lblFlushPart; /* Label for "Gosub flush_partition" */ - int lblFlushDone; /* Label for "Gosub flush_partition_done" */ - - int regArg; - int addr; - int csrStart = pParse->nTab++; - int csrEnd = pParse->nTab++; - int regStart; /* Value of PRECEDING */ - int regEnd; /* Value of FOLLOWING */ - int addrGoto; - int addrTop; - int addrIfPos1 = 0; - int addrIfPos2 = 0; - int regSize = 0; - - assert( pMWin->eStart==TK_PRECEDING - || pMWin->eStart==TK_CURRENT - || pMWin->eStart==TK_FOLLOWING - || pMWin->eStart==TK_UNBOUNDED - ); - assert( pMWin->eEnd==TK_FOLLOWING - || pMWin->eEnd==TK_CURRENT - || pMWin->eEnd==TK_UNBOUNDED - || pMWin->eEnd==TK_PRECEDING - ); - - /* Allocate register and label for the "flush_partition" sub-routine. */ - regFlushPart = ++pParse->nMem; - lblFlushPart = sqlite3VdbeMakeLabel(pParse); - lblFlushDone = sqlite3VdbeMakeLabel(pParse); - - regStart = ++pParse->nMem; - regEnd = ++pParse->nMem; - - windowPartitionCache(pParse, p, pWInfo, regFlushPart, lblFlushPart, ®Size); - - addrGoto = sqlite3VdbeAddOp0(v, OP_Goto); - - /* Start of "flush_partition" */ - sqlite3VdbeResolveLabel(v, lblFlushPart); - sqlite3VdbeAddOp2(v, OP_Once, 0, sqlite3VdbeCurrentAddr(v)+3); - VdbeCoverage(v); - VdbeComment((v, "Flush_partition subroutine")); - sqlite3VdbeAddOp2(v, OP_OpenDup, csrStart, pMWin->iEphCsr); - sqlite3VdbeAddOp2(v, OP_OpenDup, csrEnd, pMWin->iEphCsr); - - /* If either regStart or regEnd are not non-negative integers, throw - ** an exception. */ - if( pMWin->pStart ){ - sqlite3ExprCode(pParse, pMWin->pStart, regStart); - windowCheckIntValue(pParse, regStart, 0); - } - if( pMWin->pEnd ){ - sqlite3ExprCode(pParse, pMWin->pEnd, regEnd); - windowCheckIntValue(pParse, regEnd, 1); - } - - /* If this is "ROWS FOLLOWING AND ROWS FOLLOWING", do: - ** - ** if( regEndpEnd && pMWin->eStart==TK_FOLLOWING ){ - assert( pMWin->pStart!=0 ); - assert( pMWin->eEnd==TK_FOLLOWING ); - sqlite3VdbeAddOp3(v, OP_Ge, regStart, sqlite3VdbeCurrentAddr(v)+2, regEnd); - VdbeCoverageNeverNull(v); - sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart); - sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regEnd); - } - - if( pMWin->pStart && pMWin->eEnd==TK_PRECEDING ){ - assert( pMWin->pEnd!=0 ); - assert( pMWin->eStart==TK_PRECEDING ); - sqlite3VdbeAddOp3(v, OP_Le, regStart, sqlite3VdbeCurrentAddr(v)+3, regEnd); - VdbeCoverageNeverNull(v); - sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart); - sqlite3VdbeAddOp2(v, OP_Copy, regSize, regEnd); - } - - /* Initialize the accumulator register for each window function to NULL */ - regArg = windowInitAccum(pParse, pMWin); - - sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr, lblFlushDone); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Rewind, csrStart, lblFlushDone); - VdbeCoverageNeverTaken(v); - sqlite3VdbeChangeP5(v, 1); - sqlite3VdbeAddOp2(v, OP_Rewind, csrEnd, lblFlushDone); - VdbeCoverageNeverTaken(v); - sqlite3VdbeChangeP5(v, 1); - - /* Invoke AggStep function for each window function using the row that - ** csrEnd currently points to. Or, if csrEnd is already at EOF, - ** do nothing. */ - addrTop = sqlite3VdbeCurrentAddr(v); - if( pMWin->eEnd==TK_PRECEDING ){ - addrIfPos1 = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0 , 1); - VdbeCoverage(v); - } - sqlite3VdbeAddOp2(v, OP_Next, csrEnd, sqlite3VdbeCurrentAddr(v)+2); - VdbeCoverage(v); - addr = sqlite3VdbeAddOp0(v, OP_Goto); - windowAggStep(pParse, pMWin, csrEnd, 0, regArg, regSize); - if( pMWin->eEnd==TK_UNBOUNDED ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); - sqlite3VdbeJumpHere(v, addr); - addrTop = sqlite3VdbeCurrentAddr(v); - }else{ - sqlite3VdbeJumpHere(v, addr); - if( pMWin->eEnd==TK_PRECEDING ){ - sqlite3VdbeJumpHere(v, addrIfPos1); +static int windowCacheFrame(Window *pMWin){ + Window *pWin; + if( pMWin->regStartRowid ) return 1; + for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ + FuncDef *pFunc = pWin->pFunc; + if( (pFunc->zName==nth_valueName) + || (pFunc->zName==first_valueName) + || (pFunc->zName==leadName) + || (pFunc->zName==lagName) + ){ + return 1; } } - - if( pMWin->eEnd==TK_FOLLOWING ){ - addrIfPos1 = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0 , 1); - VdbeCoverage(v); - } - if( pMWin->eStart==TK_FOLLOWING ){ - addrIfPos2 = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0 , 1); - VdbeCoverage(v); - } - windowAggFinal(pParse, pMWin, 0); - windowReturnOneRow(pParse, pMWin, regGosub, addrGosub); - sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)+2); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Goto, 0, lblFlushDone); - if( pMWin->eStart==TK_FOLLOWING ){ - sqlite3VdbeJumpHere(v, addrIfPos2); - } - - if( pMWin->eStart==TK_CURRENT - || pMWin->eStart==TK_PRECEDING - || pMWin->eStart==TK_FOLLOWING - ){ - int lblSkipInverse = sqlite3VdbeMakeLabel(pParse);; - if( pMWin->eStart==TK_PRECEDING ){ - sqlite3VdbeAddOp3(v, OP_IfPos, regStart, lblSkipInverse, 1); - VdbeCoverage(v); - } - if( pMWin->eStart==TK_FOLLOWING ){ - sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+2); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Goto, 0, lblSkipInverse); - }else{ - sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+1); - VdbeCoverageAlwaysTaken(v); - } - windowAggStep(pParse, pMWin, csrStart, 1, regArg, regSize); - sqlite3VdbeResolveLabel(v, lblSkipInverse); - } - if( pMWin->eEnd==TK_FOLLOWING ){ - sqlite3VdbeJumpHere(v, addrIfPos1); - } - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); - - /* flush_partition_done: */ - sqlite3VdbeResolveLabel(v, lblFlushDone); - sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr); - sqlite3VdbeAddOp1(v, OP_Return, regFlushPart); - VdbeComment((v, "end flush_partition subroutine")); - - /* Jump to here to skip over flush_partition */ - sqlite3VdbeJumpHere(v, addrGoto); + return 0; } /* -** This function does the work of sqlite3WindowCodeStep() for cases that -** would normally be handled by windowCodeDefaultStep() when there are -** one or more built-in window-functions that require the entire partition -** to be cached in a temp table before any rows can be returned. Additionally. -** "RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING" is always handled by -** this function. +** regOld and regNew are each the first register in an array of size +** pOrderBy->nExpr. This function generates code to compare the two +** arrays of registers using the collation sequences and other comparison +** parameters specified by pOrderBy. ** -** Pseudo-code corresponding to the VM code generated by this function -** for each type of window follows. -** -** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW -** -** flush_partition: -** Once { -** OpenDup (iEphCsr -> csrLead) -** } -** Integer ctr 0 -** foreach row (csrLead){ -** if( new peer ){ -** AggFinal (xValue) -** for(i=0; i csrLead) -** } -** foreach row (csrLead) { -** AggStep (csrLead) -** } -** foreach row (iEphCsr) { -** Gosub addrGosub -** } -** -** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING -** -** flush_partition: -** Once { -** OpenDup (iEphCsr -> csrLead) -** } -** foreach row (csrLead){ -** AggStep (csrLead) -** } -** Rewind (csrLead) -** Integer ctr 0 -** foreach row (csrLead){ -** if( new peer ){ -** AggFinal (xValue) -** for(i=0; ipWin; Vdbe *v = sqlite3GetVdbe(pParse); - int k; - int addr; - ExprList *pPart = pMWin->pPartition; - ExprList *pOrderBy = pMWin->pOrderBy; - int nPeer = pOrderBy ? pOrderBy->nExpr : 0; - int regNewPeer; - - int addrGoto; /* Address of Goto used to jump flush_par.. */ - int addrNext; /* Jump here for next iteration of loop */ - int regFlushPart; - int lblFlushPart; - int csrLead; - int regCtr; - int regArg; /* Register array to martial function args */ - int regSize; - int lblEmpty; - int bReverse = pMWin->pOrderBy && pMWin->eStart==TK_CURRENT - && pMWin->eEnd==TK_UNBOUNDED; - - assert( (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT) - || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_UNBOUNDED) - || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_CURRENT) - || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED) - ); - - lblEmpty = sqlite3VdbeMakeLabel(pParse); - regNewPeer = pParse->nMem+1; - pParse->nMem += nPeer; - - /* Allocate register and label for the "flush_partition" sub-routine. */ - regFlushPart = ++pParse->nMem; - lblFlushPart = sqlite3VdbeMakeLabel(pParse); - - csrLead = pParse->nTab++; - regCtr = ++pParse->nMem; - - windowPartitionCache(pParse, p, pWInfo, regFlushPart, lblFlushPart, ®Size); - addrGoto = sqlite3VdbeAddOp0(v, OP_Goto); - - /* Start of "flush_partition" */ - sqlite3VdbeResolveLabel(v, lblFlushPart); - sqlite3VdbeAddOp2(v, OP_Once, 0, sqlite3VdbeCurrentAddr(v)+2); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_OpenDup, csrLead, pMWin->iEphCsr); - - /* Initialize the accumulator register for each window function to NULL */ - regArg = windowInitAccum(pParse, pMWin); - - sqlite3VdbeAddOp2(v, OP_Integer, 0, regCtr); - sqlite3VdbeAddOp2(v, OP_Rewind, csrLead, lblEmpty); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr, lblEmpty); - VdbeCoverageNeverTaken(v); - - if( bReverse ){ - int addr2 = sqlite3VdbeCurrentAddr(v); - windowAggStep(pParse, pMWin, csrLead, 0, regArg, regSize); - sqlite3VdbeAddOp2(v, OP_Next, csrLead, addr2); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Rewind, csrLead, lblEmpty); - VdbeCoverageNeverTaken(v); - } - addrNext = sqlite3VdbeCurrentAddr(v); - - if( pOrderBy && (pMWin->eEnd==TK_CURRENT || pMWin->eStart==TK_CURRENT) ){ - int bCurrent = (pMWin->eStart==TK_CURRENT); - int addrJump = 0; /* Address of OP_Jump below */ - if( pMWin->eType==TK_RANGE ){ - int iOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0); - int regPeer = pMWin->regPart + (pPart ? pPart->nExpr : 0); - KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0); - for(k=0; knExpr; + KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0); + sqlite3VdbeAddOp3(v, OP_Compare, regOld, regNew, nVal); + sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); + sqlite3VdbeAddOp3(v, OP_Jump, + sqlite3VdbeCurrentAddr(v)+1, addr, sqlite3VdbeCurrentAddr(v)+1 ); - if( addrJump ) sqlite3VdbeJumpHere(v, addrJump); + VdbeCoverageEqNe(v); + sqlite3VdbeAddOp3(v, OP_Copy, regNew, regOld, nVal-1); + }else{ + sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); } - - if( bReverse==0 ){ - windowAggStep(pParse, pMWin, csrLead, 0, regArg, regSize); - } - sqlite3VdbeAddOp2(v, OP_AddImm, regCtr, 1); - sqlite3VdbeAddOp2(v, OP_Next, csrLead, addrNext); - VdbeCoverage(v); - - windowReturnRows(pParse, pMWin, regCtr, regGosub, addrGosub, 0, 0); - - sqlite3VdbeResolveLabel(v, lblEmpty); - sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr); - sqlite3VdbeAddOp1(v, OP_Return, regFlushPart); - - /* Jump to here to skip over flush_partition */ - sqlite3VdbeJumpHere(v, addrGoto); } +/* +** This function is called as part of generating VM programs for RANGE +** offset PRECEDING/FOLLOWING frame boundaries. Assuming "ASC" order for +** the ORDER BY term in the window, it generates code equivalent to: +** +** if( csr1.peerVal + regVal >= csr2.peerVal ) goto lbl; +** +** A special type of arithmetic is used such that if csr.peerVal is not +** a numeric type (real or integer), then the result of the addition is +** a copy of csr1.peerVal. +*/ +static void windowCodeRangeTest( + WindowCodeArg *p, + int op, /* OP_Ge or OP_Gt */ + int csr1, + int regVal, + int csr2, + int lbl +){ + Parse *pParse = p->pParse; + Vdbe *v = sqlite3GetVdbe(pParse); + int reg1 = sqlite3GetTempReg(pParse); + int reg2 = sqlite3GetTempReg(pParse); + int arith = OP_Add; + int addrGe; + + int regString = ++pParse->nMem; + + assert( op==OP_Ge || op==OP_Gt || op==OP_Le ); + assert( p->pMWin->pOrderBy && p->pMWin->pOrderBy->nExpr==1 ); + if( p->pMWin->pOrderBy->a[0].sortOrder ){ + switch( op ){ + case OP_Ge: op = OP_Le; break; + case OP_Gt: op = OP_Lt; break; + default: assert( op==OP_Le ); op = OP_Ge; break; + } + arith = OP_Subtract; + } + + windowReadPeerValues(p, csr1, reg1); + windowReadPeerValues(p, csr2, reg2); + + /* Check if the peer value for csr1 value is a text or blob by comparing + ** it to the smallest possible string - ''. If it is, jump over the + ** OP_Add or OP_Subtract operation and proceed directly to the comparison. */ + sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC); + addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1); + VdbeCoverage(v); + sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1); + sqlite3VdbeJumpHere(v, addrGe); + sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v); + sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); + assert( op==OP_Ge || op==OP_Gt || op==OP_Lt || op==OP_Le ); + testcase(op==OP_Ge); VdbeCoverageIf(v, op==OP_Ge); + testcase(op==OP_Lt); VdbeCoverageIf(v, op==OP_Lt); + testcase(op==OP_Le); VdbeCoverageIf(v, op==OP_Le); + testcase(op==OP_Gt); VdbeCoverageIf(v, op==OP_Gt); + + sqlite3ReleaseTempReg(pParse, reg1); + sqlite3ReleaseTempReg(pParse, reg2); +} /* -** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW -** -** ... -** if( new partition ){ -** AggFinal (xFinalize) -** Gosub addrGosub -** ResetSorter eph-table -** } -** else if( new peer ){ -** AggFinal (xValue) -** Gosub addrGosub -** ResetSorter eph-table -** } -** AggStep -** Insert (record into eph-table) -** sqlite3WhereEnd() -** AggFinal (xFinalize) -** Gosub addrGosub -** -** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING -** -** As above, except take no action for a "new peer". Invoke -** the sub-routine once only for each partition. -** -** RANGE BETWEEN CURRENT ROW AND CURRENT ROW -** -** As above, except that the "new peer" condition is handled in the -** same way as "new partition" (so there is no "else if" block). -** -** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW -** -** As above, except assume every row is a "new peer". +** Helper function for sqlite3WindowCodeStep(). Each call to this function +** generates VM code for a single RETURN_ROW, AGGSTEP or AGGINVERSE +** operation. Refer to the header comment for sqlite3WindowCodeStep() for +** details. */ -static void windowCodeDefaultStep( - Parse *pParse, - Select *p, - WhereInfo *pWInfo, - int regGosub, - int addrGosub +static int windowCodeOp( + WindowCodeArg *p, /* Context object */ + int op, /* WINDOW_RETURN_ROW, AGGSTEP or AGGINVERSE */ + int regCountdown, /* Register for OP_IfPos countdown */ + int jumpOnEof /* Jump here if stepped cursor reaches EOF */ ){ - Window *pMWin = p->pWin; - Vdbe *v = sqlite3GetVdbe(pParse); - int k; - int iSubCsr = p->pSrc->a[0].iCursor; - int nSub = p->pSrc->a[0].pTab->nCol; - int reg = pParse->nMem+1; - int regRecord = reg+nSub; - int regRowid = regRecord+1; - int addr; - ExprList *pPart = pMWin->pPartition; - ExprList *pOrderBy = pMWin->pOrderBy; + int csr, reg; + Parse *pParse = p->pParse; + Window *pMWin = p->pMWin; + int ret = 0; + Vdbe *v = p->pVdbe; + int addrIf = 0; + int addrContinue = 0; + int addrGoto = 0; + int bPeer = (pMWin->eFrmType!=TK_ROWS); - assert( pMWin->eType==TK_RANGE - || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT) - ); + int lblDone = sqlite3VdbeMakeLabel(pParse); + int addrNextRange = 0; - assert( (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT) - || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_UNBOUNDED) - || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_CURRENT) - || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED && !pOrderBy) - ); - - if( pMWin->eEnd==TK_UNBOUNDED ){ - pOrderBy = 0; + /* Special case - WINDOW_AGGINVERSE is always a no-op if the frame + ** starts with UNBOUNDED PRECEDING. */ + if( op==WINDOW_AGGINVERSE && pMWin->eStart==TK_UNBOUNDED ){ + assert( regCountdown==0 && jumpOnEof==0 ); + return 0; } - pParse->nMem += nSub + 2; - - /* Load the individual column values of the row returned by - ** the sub-select into an array of registers. */ - for(k=0; knExpr : 0); - int addrGoto = 0; - int addrJump = 0; - int nPeer = (pOrderBy ? pOrderBy->nExpr : 0); - - if( pPart ){ - int regNewPart = reg + pMWin->nBufferCol; - KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0); - addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart,nPart); - sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); - addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2); - VdbeCoverageEqNe(v); - windowAggFinal(pParse, pMWin, 1); - if( pOrderBy ){ - addrGoto = sqlite3VdbeAddOp0(v, OP_Goto); - } - } - - if( pOrderBy ){ - int regNewPeer = reg + pMWin->nBufferCol + nPart; - int regPeer = pMWin->regPart + nPart; - - if( addrJump ) sqlite3VdbeJumpHere(v, addrJump); - if( pMWin->eType==TK_RANGE ){ - KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0); - addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPeer, regPeer, nPeer); - sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); - addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2); - VdbeCoverage(v); + if( regCountdown>0 ){ + if( pMWin->eFrmType==TK_RANGE ){ + addrNextRange = sqlite3VdbeCurrentAddr(v); + assert( op==WINDOW_AGGINVERSE || op==WINDOW_AGGSTEP ); + if( op==WINDOW_AGGINVERSE ){ + if( pMWin->eStart==TK_FOLLOWING ){ + windowCodeRangeTest( + p, OP_Le, p->current.csr, regCountdown, p->start.csr, lblDone + ); + }else{ + windowCodeRangeTest( + p, OP_Ge, p->start.csr, regCountdown, p->current.csr, lblDone + ); + } }else{ - addrJump = 0; + windowCodeRangeTest( + p, OP_Gt, p->end.csr, regCountdown, p->current.csr, lblDone + ); } - windowAggFinal(pParse, pMWin, pMWin->eStart==TK_CURRENT); - if( addrGoto ) sqlite3VdbeJumpHere(v, addrGoto); + }else{ + addrIf = sqlite3VdbeAddOp3(v, OP_IfPos, regCountdown, 0, 1); + VdbeCoverage(v); } - - sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr,sqlite3VdbeCurrentAddr(v)+3); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub); - sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1); - VdbeCoverage(v); - - sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr); - sqlite3VdbeAddOp3( - v, OP_Copy, reg+pMWin->nBufferCol, pMWin->regPart, nPart+nPeer-1 - ); - - if( addrJump ) sqlite3VdbeJumpHere(v, addrJump); } - /* Invoke step function for window functions */ - windowAggStep(pParse, pMWin, -1, 0, reg, 0); + if( op==WINDOW_RETURN_ROW && pMWin->regStartRowid==0 ){ + windowAggFinal(p, 0); + } + addrContinue = sqlite3VdbeCurrentAddr(v); + switch( op ){ + case WINDOW_RETURN_ROW: + csr = p->current.csr; + reg = p->current.reg; + windowReturnOneRow(p); + break; - /* Buffer the current row in the ephemeral table. */ - if( pMWin->nBufferCol>0 ){ - sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, pMWin->nBufferCol, regRecord); + case WINDOW_AGGINVERSE: + csr = p->start.csr; + reg = p->start.reg; + if( pMWin->regStartRowid ){ + assert( pMWin->regEndRowid ); + sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regStartRowid, 1); + }else{ + windowAggStep(pParse, pMWin, csr, 1, p->regArg); + } + break; + + default: + assert( op==WINDOW_AGGSTEP ); + csr = p->end.csr; + reg = p->end.reg; + if( pMWin->regStartRowid ){ + assert( pMWin->regEndRowid ); + sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regEndRowid, 1); + }else{ + windowAggStep(pParse, pMWin, csr, 0, p->regArg); + } + break; + } + + if( op==p->eDelete ){ + sqlite3VdbeAddOp1(v, OP_Delete, csr); + sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION); + } + + if( jumpOnEof ){ + sqlite3VdbeAddOp2(v, OP_Next, csr, sqlite3VdbeCurrentAddr(v)+2); + VdbeCoverage(v); + ret = sqlite3VdbeAddOp0(v, OP_Goto); }else{ - sqlite3VdbeAddOp2(v, OP_Blob, 0, regRecord); - sqlite3VdbeAppendP4(v, (void*)"", 0); + sqlite3VdbeAddOp2(v, OP_Next, csr, sqlite3VdbeCurrentAddr(v)+1+bPeer); + VdbeCoverage(v); + if( bPeer ){ + addrGoto = sqlite3VdbeAddOp0(v, OP_Goto); + } } - sqlite3VdbeAddOp2(v, OP_NewRowid, pMWin->iEphCsr, regRowid); - sqlite3VdbeAddOp3(v, OP_Insert, pMWin->iEphCsr, regRecord, regRowid); - /* End the database scan loop. */ - sqlite3WhereEnd(pWInfo); + if( bPeer ){ + int nReg = (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0); + int regTmp = (nReg ? sqlite3GetTempRange(pParse, nReg) : 0); + windowReadPeerValues(p, csr, regTmp); + windowIfNewPeer(pParse, pMWin->pOrderBy, regTmp, reg, addrContinue); + sqlite3ReleaseTempRange(pParse, regTmp, nReg); + } - windowAggFinal(pParse, pMWin, 1); - sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr,sqlite3VdbeCurrentAddr(v)+3); - VdbeCoverage(v); - sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub); - sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1); - VdbeCoverage(v); + if( addrNextRange ){ + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNextRange); + } + sqlite3VdbeResolveLabel(v, lblDone); + if( addrGoto ) sqlite3VdbeJumpHere(v, addrGoto); + if( addrIf ) sqlite3VdbeJumpHere(v, addrIf); + return ret; } + /* ** Allocate and return a duplicate of the Window object indicated by the ** third argument. Set the Window.pOwner field of the new object to @@ -147187,9 +147402,10 @@ SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){ pNew->pFunc = p->pFunc; pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0); pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0); - pNew->eType = p->eType; + pNew->eFrmType = p->eFrmType; pNew->eEnd = p->eEnd; pNew->eStart = p->eStart; + pNew->eExclude = p->eExclude; pNew->pStart = sqlite3ExprDup(db, p->pStart, 0); pNew->pEnd = sqlite3ExprDup(db, p->pEnd, 0); pNew->pOwner = pOwner; @@ -147216,12 +147432,360 @@ SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p){ return pRet; } +/* +** Return true if it can be determined at compile time that expression +** pExpr evaluates to a value that, when cast to an integer, is greater +** than zero. False otherwise. +** +** If an OOM error occurs, this function sets the Parse.db.mallocFailed +** flag and returns zero. +*/ +static int windowExprGtZero(Parse *pParse, Expr *pExpr){ + int ret = 0; + sqlite3 *db = pParse->db; + sqlite3_value *pVal = 0; + sqlite3ValueFromExpr(db, pExpr, db->enc, SQLITE_AFF_NUMERIC, &pVal); + if( pVal && sqlite3_value_int(pVal)>0 ){ + ret = 1; + } + sqlite3ValueFree(pVal); + return ret; +} + /* ** sqlite3WhereBegin() has already been called for the SELECT statement ** passed as the second argument when this function is invoked. It generates -** code to populate the Window.regResult register for each window function and -** invoke the sub-routine at instruction addrGosub once for each row. -** This function calls sqlite3WhereEnd() before returning. +** code to populate the Window.regResult register for each window function +** and invoke the sub-routine at instruction addrGosub once for each row. +** sqlite3WhereEnd() is always called before returning. +** +** This function handles several different types of window frames, which +** require slightly different processing. The following pseudo code is +** used to implement window frames of the form: +** +** ROWS BETWEEN PRECEDING AND FOLLOWING +** +** Other window frame types use variants of the following: +** +** ... loop started by sqlite3WhereBegin() ... +** if( new partition ){ +** Gosub flush +** } +** Insert new row into eph table. +** +** if( first row of partition ){ +** // Rewind three cursors, all open on the eph table. +** Rewind(csrEnd); +** Rewind(csrStart); +** Rewind(csrCurrent); +** +** regEnd = // FOLLOWING expression +** regStart = // PRECEDING expression +** }else{ +** // First time this branch is taken, the eph table contains two +** // rows. The first row in the partition, which all three cursors +** // currently point to, and the following row. +** AGGSTEP +** if( (regEnd--)<=0 ){ +** RETURN_ROW +** if( (regStart--)<=0 ){ +** AGGINVERSE +** } +** } +** } +** } +** flush: +** AGGSTEP +** while( 1 ){ +** RETURN ROW +** if( csrCurrent is EOF ) break; +** if( (regStart--)<=0 ){ +** AggInverse(csrStart) +** Next(csrStart) +** } +** } +** +** The pseudo-code above uses the following shorthand: +** +** AGGSTEP: invoke the aggregate xStep() function for each window function +** with arguments read from the current row of cursor csrEnd, then +** step cursor csrEnd forward one row (i.e. sqlite3BtreeNext()). +** +** RETURN_ROW: return a row to the caller based on the contents of the +** current row of csrCurrent and the current state of all +** aggregates. Then step cursor csrCurrent forward one row. +** +** AGGINVERSE: invoke the aggregate xInverse() function for each window +** functions with arguments read from the current row of cursor +** csrStart. Then step csrStart forward one row. +** +** There are two other ROWS window frames that are handled significantly +** differently from the above - "BETWEEN PRECEDING AND PRECEDING" +** and "BETWEEN FOLLOWING AND FOLLOWING". These are special +** cases because they change the order in which the three cursors (csrStart, +** csrCurrent and csrEnd) iterate through the ephemeral table. Cases that +** use UNBOUNDED or CURRENT ROW are much simpler variations on one of these +** three. +** +** ROWS BETWEEN PRECEDING AND PRECEDING +** +** ... loop started by sqlite3WhereBegin() ... +** if( new partition ){ +** Gosub flush +** } +** Insert new row into eph table. +** if( first row of partition ){ +** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) +** regEnd = +** regStart = +** }else{ +** if( (regEnd--)<=0 ){ +** AGGSTEP +** } +** RETURN_ROW +** if( (regStart--)<=0 ){ +** AGGINVERSE +** } +** } +** } +** flush: +** if( (regEnd--)<=0 ){ +** AGGSTEP +** } +** RETURN_ROW +** +** +** ROWS BETWEEN FOLLOWING AND FOLLOWING +** +** ... loop started by sqlite3WhereBegin() ... +** if( new partition ){ +** Gosub flush +** } +** Insert new row into eph table. +** if( first row of partition ){ +** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) +** regEnd = +** regStart = regEnd - +** }else{ +** AGGSTEP +** if( (regEnd--)<=0 ){ +** RETURN_ROW +** } +** if( (regStart--)<=0 ){ +** AGGINVERSE +** } +** } +** } +** flush: +** AGGSTEP +** while( 1 ){ +** if( (regEnd--)<=0 ){ +** RETURN_ROW +** if( eof ) break; +** } +** if( (regStart--)<=0 ){ +** AGGINVERSE +** if( eof ) break +** } +** } +** while( !eof csrCurrent ){ +** RETURN_ROW +** } +** +** For the most part, the patterns above are adapted to support UNBOUNDED by +** assuming that it is equivalent to "infinity PRECEDING/FOLLOWING" and +** CURRENT ROW by assuming that it is equivilent to "0 PRECEDING/FOLLOWING". +** This is optimized of course - branches that will never be taken and +** conditions that are always true are omitted from the VM code. The only +** exceptional case is: +** +** ROWS BETWEEN FOLLOWING AND UNBOUNDED FOLLOWING +** +** ... loop started by sqlite3WhereBegin() ... +** if( new partition ){ +** Gosub flush +** } +** Insert new row into eph table. +** if( first row of partition ){ +** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) +** regStart = +** }else{ +** AGGSTEP +** } +** } +** flush: +** AGGSTEP +** while( 1 ){ +** if( (regStart--)<=0 ){ +** AGGINVERSE +** if( eof ) break +** } +** RETURN_ROW +** } +** while( !eof csrCurrent ){ +** RETURN_ROW +** } +** +** Also requiring special handling are the cases: +** +** ROWS BETWEEN PRECEDING AND PRECEDING +** ROWS BETWEEN FOLLOWING AND FOLLOWING +** +** when (expr1 < expr2). This is detected at runtime, not by this function. +** To handle this case, the pseudo-code programs depicted above are modified +** slightly to be: +** +** ... loop started by sqlite3WhereBegin() ... +** if( new partition ){ +** Gosub flush +** } +** Insert new row into eph table. +** if( first row of partition ){ +** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) +** regEnd = +** regStart = +** if( regEnd < regStart ){ +** RETURN_ROW +** delete eph table contents +** continue +** } +** ... +** +** The new "continue" statement in the above jumps to the next iteration +** of the outer loop - the one started by sqlite3WhereBegin(). +** +** The various GROUPS cases are implemented using the same patterns as +** ROWS. The VM code is modified slightly so that: +** +** 1. The else branch in the main loop is only taken if the row just +** added to the ephemeral table is the start of a new group. In +** other words, it becomes: +** +** ... loop started by sqlite3WhereBegin() ... +** if( new partition ){ +** Gosub flush +** } +** Insert new row into eph table. +** if( first row of partition ){ +** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) +** regEnd = +** regStart = +** }else if( new group ){ +** ... +** } +** } +** +** 2. Instead of processing a single row, each RETURN_ROW, AGGSTEP or +** AGGINVERSE step processes the current row of the relevant cursor and +** all subsequent rows belonging to the same group. +** +** RANGE window frames are a little different again. As for GROUPS, the +** main loop runs once per group only. And RETURN_ROW, AGGSTEP and AGGINVERSE +** deal in groups instead of rows. As for ROWS and GROUPS, there are three +** basic cases: +** +** RANGE BETWEEN PRECEDING AND FOLLOWING +** +** ... loop started by sqlite3WhereBegin() ... +** if( new partition ){ +** Gosub flush +** } +** Insert new row into eph table. +** if( first row of partition ){ +** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) +** regEnd = +** regStart = +** }else{ +** AGGSTEP +** while( (csrCurrent.key + regEnd) < csrEnd.key ){ +** RETURN_ROW +** while( csrStart.key + regStart) < csrCurrent.key ){ +** AGGINVERSE +** } +** } +** } +** } +** flush: +** AGGSTEP +** while( 1 ){ +** RETURN ROW +** if( csrCurrent is EOF ) break; +** while( csrStart.key + regStart) < csrCurrent.key ){ +** AGGINVERSE +** } +** } +** } +** +** In the above notation, "csr.key" means the current value of the ORDER BY +** expression (there is only ever 1 for a RANGE that uses an FOLLOWING +** or PRECEDING AND PRECEDING +** +** ... loop started by sqlite3WhereBegin() ... +** if( new partition ){ +** Gosub flush +** } +** Insert new row into eph table. +** if( first row of partition ){ +** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) +** regEnd = +** regStart = +** }else{ +** if( (csrEnd.key + regEnd) <= csrCurrent.key ){ +** AGGSTEP +** } +** while( (csrStart.key + regStart) < csrCurrent.key ){ +** AGGINVERSE +** } +** RETURN_ROW +** } +** } +** flush: +** while( (csrEnd.key + regEnd) <= csrCurrent.key ){ +** AGGSTEP +** } +** while( (csrStart.key + regStart) < csrCurrent.key ){ +** AGGINVERSE +** } +** RETURN_ROW +** +** RANGE BETWEEN FOLLOWING AND FOLLOWING +** +** ... loop started by sqlite3WhereBegin() ... +** if( new partition ){ +** Gosub flush +** } +** Insert new row into eph table. +** if( first row of partition ){ +** Rewind(csrEnd) ; Rewind(csrStart) ; Rewind(csrCurrent) +** regEnd = +** regStart = +** }else{ +** AGGSTEP +** while( (csrCurrent.key + regEnd) < csrEnd.key ){ +** while( (csrCurrent.key + regStart) > csrStart.key ){ +** AGGINVERSE +** } +** RETURN_ROW +** } +** } +** } +** flush: +** AGGSTEP +** while( 1 ){ +** while( (csrCurrent.key + regStart) > csrStart.key ){ +** AGGINVERSE +** if( eof ) break "while( 1 )" loop. +** } +** RETURN_ROW +** } +** while( !eof csrCurrent ){ +** RETURN_ROW +** } +** +** The text above leaves out many details. Refer to the code and comments +** below for a more complete picture. */ SQLITE_PRIVATE void sqlite3WindowCodeStep( Parse *pParse, /* Parse context */ @@ -147231,75 +147795,321 @@ SQLITE_PRIVATE void sqlite3WindowCodeStep( int addrGosub /* OP_Gosub here to return each row */ ){ Window *pMWin = p->pWin; + ExprList *pOrderBy = pMWin->pOrderBy; + Vdbe *v = sqlite3GetVdbe(pParse); + int csrWrite; /* Cursor used to write to eph. table */ + int csrInput = p->pSrc->a[0].iCursor; /* Cursor of sub-select */ + int nInput = p->pSrc->a[0].pTab->nCol; /* Number of cols returned by sub */ + int iInput; /* To iterate through sub cols */ + int addrNe; /* Address of OP_Ne */ + int addrGosubFlush = 0; /* Address of OP_Gosub to flush: */ + int addrInteger = 0; /* Address of OP_Integer */ + int addrEmpty; /* Address of OP_Rewind in flush: */ + int regStart = 0; /* Value of PRECEDING */ + int regEnd = 0; /* Value of FOLLOWING */ + int regNew; /* Array of registers holding new input row */ + int regRecord; /* regNew array in record form */ + int regRowid; /* Rowid for regRecord in eph table */ + int regNewPeer = 0; /* Peer values for new row (part of regNew) */ + int regPeer = 0; /* Peer values for current row */ + int regFlushPart = 0; /* Register for "Gosub flush_partition" */ + WindowCodeArg s; /* Context object for sub-routines */ + int lblWhereEnd; /* Label just before sqlite3WhereEnd() code */ - /* There are three different functions that may be used to do the work - ** of this one, depending on the window frame and the specific built-in - ** window functions used (if any). - ** - ** windowCodeRowExprStep() handles all "ROWS" window frames, except for: - ** - ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW - ** - ** The exception is because windowCodeRowExprStep() implements all window - ** frame types by caching the entire partition in a temp table, and - ** "ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW" is easy enough to - ** implement without such a cache. - ** - ** windowCodeCacheStep() is used for: - ** - ** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING - ** - ** It is also used for anything not handled by windowCodeRowExprStep() - ** that invokes a built-in window function that requires the entire - ** partition to be cached in a temp table before any rows are returned - ** (e.g. nth_value() or percent_rank()). - ** - ** Finally, assuming there is no built-in window function that requires - ** the partition to be cached, windowCodeDefaultStep() is used for: - ** - ** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW - ** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING - ** RANGE BETWEEN CURRENT ROW AND CURRENT ROW - ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW - ** - ** windowCodeDefaultStep() is the only one of the three functions that - ** does not cache each partition in a temp table before beginning to - ** return rows. - */ - if( pMWin->eType==TK_ROWS - && (pMWin->eStart!=TK_UNBOUNDED||pMWin->eEnd!=TK_CURRENT||!pMWin->pOrderBy) - ){ - VdbeModuleComment((pParse->pVdbe, "Begin RowExprStep()")); - windowCodeRowExprStep(pParse, p, pWInfo, regGosub, addrGosub); - }else{ - Window *pWin; - int bCache = 0; /* True to use CacheStep() */ + assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_CURRENT + || pMWin->eStart==TK_FOLLOWING || pMWin->eStart==TK_UNBOUNDED + ); + assert( pMWin->eEnd==TK_FOLLOWING || pMWin->eEnd==TK_CURRENT + || pMWin->eEnd==TK_UNBOUNDED || pMWin->eEnd==TK_PRECEDING + ); + assert( pMWin->eExclude==0 || pMWin->eExclude==TK_CURRENT + || pMWin->eExclude==TK_GROUP || pMWin->eExclude==TK_TIES + || pMWin->eExclude==TK_NO + ); - if( pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED ){ - bCache = 1; - }else{ - for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - FuncDef *pFunc = pWin->pFunc; - if( (pFunc->funcFlags & SQLITE_FUNC_WINDOW_SIZE) - || (pFunc->zName==nth_valueName) - || (pFunc->zName==first_valueName) - || (pFunc->zName==leadName) - || (pFunc->zName==lagName) - ){ - bCache = 1; - break; + lblWhereEnd = sqlite3VdbeMakeLabel(pParse); + + /* Fill in the context object */ + memset(&s, 0, sizeof(WindowCodeArg)); + s.pParse = pParse; + s.pMWin = pMWin; + s.pVdbe = v; + s.regGosub = regGosub; + s.addrGosub = addrGosub; + s.current.csr = pMWin->iEphCsr; + csrWrite = s.current.csr+1; + s.start.csr = s.current.csr+2; + s.end.csr = s.current.csr+3; + + /* Figure out when rows may be deleted from the ephemeral table. There + ** are four options - they may never be deleted (eDelete==0), they may + ** be deleted as soon as they are no longer part of the window frame + ** (eDelete==WINDOW_AGGINVERSE), they may be deleted as after the row + ** has been returned to the caller (WINDOW_RETURN_ROW), or they may + ** be deleted after they enter the frame (WINDOW_AGGSTEP). */ + switch( pMWin->eStart ){ + case TK_FOLLOWING: + if( pMWin->eFrmType!=TK_RANGE + && windowExprGtZero(pParse, pMWin->pStart) + ){ + s.eDelete = WINDOW_RETURN_ROW; + } + break; + case TK_UNBOUNDED: + if( windowCacheFrame(pMWin)==0 ){ + if( pMWin->eEnd==TK_PRECEDING ){ + if( pMWin->eFrmType!=TK_RANGE + && windowExprGtZero(pParse, pMWin->pEnd) + ){ + s.eDelete = WINDOW_AGGSTEP; + } + }else{ + s.eDelete = WINDOW_RETURN_ROW; } } - } + break; + default: + s.eDelete = WINDOW_AGGINVERSE; + break; + } - /* Otherwise, call windowCodeDefaultStep(). */ - if( bCache ){ - VdbeModuleComment((pParse->pVdbe, "Begin CacheStep()")); - windowCodeCacheStep(pParse, p, pWInfo, regGosub, addrGosub); - }else{ - VdbeModuleComment((pParse->pVdbe, "Begin DefaultStep()")); - windowCodeDefaultStep(pParse, p, pWInfo, regGosub, addrGosub); + /* Allocate registers for the array of values from the sub-query, the + ** samve values in record form, and the rowid used to insert said record + ** into the ephemeral table. */ + regNew = pParse->nMem+1; + pParse->nMem += nInput; + regRecord = ++pParse->nMem; + regRowid = ++pParse->nMem; + + /* If the window frame contains an " PRECEDING" or " FOLLOWING" + ** clause, allocate registers to store the results of evaluating each + ** . */ + if( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING ){ + regStart = ++pParse->nMem; + } + if( pMWin->eEnd==TK_PRECEDING || pMWin->eEnd==TK_FOLLOWING ){ + regEnd = ++pParse->nMem; + } + + /* If this is not a "ROWS BETWEEN ..." frame, then allocate arrays of + ** registers to store copies of the ORDER BY expressions (peer values) + ** for the main loop, and for each cursor (start, current and end). */ + if( pMWin->eFrmType!=TK_ROWS ){ + int nPeer = (pOrderBy ? pOrderBy->nExpr : 0); + regNewPeer = regNew + pMWin->nBufferCol; + if( pMWin->pPartition ) regNewPeer += pMWin->pPartition->nExpr; + regPeer = pParse->nMem+1; pParse->nMem += nPeer; + s.start.reg = pParse->nMem+1; pParse->nMem += nPeer; + s.current.reg = pParse->nMem+1; pParse->nMem += nPeer; + s.end.reg = pParse->nMem+1; pParse->nMem += nPeer; + } + + /* Load the column values for the row returned by the sub-select + ** into an array of registers starting at regNew. Assemble them into + ** a record in register regRecord. */ + for(iInput=0; iInputpPartition ){ + int addr; + ExprList *pPart = pMWin->pPartition; + int nPart = pPart->nExpr; + int regNewPart = regNew + pMWin->nBufferCol; + KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0); + + regFlushPart = ++pParse->nMem; + addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart, nPart); + sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO); + sqlite3VdbeAddOp3(v, OP_Jump, addr+2, addr+4, addr+2); + VdbeCoverageEqNe(v); + addrGosubFlush = sqlite3VdbeAddOp1(v, OP_Gosub, regFlushPart); + VdbeComment((v, "call flush_partition")); + sqlite3VdbeAddOp3(v, OP_Copy, regNewPart, pMWin->regPart, nPart-1); + } + + /* Insert the new row into the ephemeral table */ + sqlite3VdbeAddOp2(v, OP_NewRowid, csrWrite, regRowid); + sqlite3VdbeAddOp3(v, OP_Insert, csrWrite, regRecord, regRowid); + addrNe = sqlite3VdbeAddOp3(v, OP_Ne, pMWin->regOne, 0, regRowid); + VdbeCoverageNeverNull(v); + + /* This block is run for the first row of each partition */ + s.regArg = windowInitAccum(pParse, pMWin); + + if( regStart ){ + sqlite3ExprCode(pParse, pMWin->pStart, regStart); + windowCheckValue(pParse, regStart, 0 + (pMWin->eFrmType==TK_RANGE ? 3 : 0)); + } + if( regEnd ){ + sqlite3ExprCode(pParse, pMWin->pEnd, regEnd); + windowCheckValue(pParse, regEnd, 1 + (pMWin->eFrmType==TK_RANGE ? 3 : 0)); + } + + if( pMWin->eStart==pMWin->eEnd && regStart ){ + int op = ((pMWin->eStart==TK_FOLLOWING) ? OP_Ge : OP_Le); + int addrGe = sqlite3VdbeAddOp3(v, op, regStart, 0, regEnd); + VdbeCoverageNeverNullIf(v, op==OP_Ge); /* NeverNull because bound */ + VdbeCoverageNeverNullIf(v, op==OP_Le); /* values previously checked */ + windowAggFinal(&s, 0); + sqlite3VdbeAddOp2(v, OP_Rewind, s.current.csr, 1); + VdbeCoverageNeverTaken(v); + windowReturnOneRow(&s); + sqlite3VdbeAddOp1(v, OP_ResetSorter, s.current.csr); + sqlite3VdbeAddOp2(v, OP_Goto, 0, lblWhereEnd); + sqlite3VdbeJumpHere(v, addrGe); + } + if( pMWin->eStart==TK_FOLLOWING && pMWin->eFrmType!=TK_RANGE && regEnd ){ + assert( pMWin->eEnd==TK_FOLLOWING ); + sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regStart); + } + + if( pMWin->eStart!=TK_UNBOUNDED ){ + sqlite3VdbeAddOp2(v, OP_Rewind, s.start.csr, 1); + VdbeCoverageNeverTaken(v); + } + sqlite3VdbeAddOp2(v, OP_Rewind, s.current.csr, 1); + VdbeCoverageNeverTaken(v); + sqlite3VdbeAddOp2(v, OP_Rewind, s.end.csr, 1); + VdbeCoverageNeverTaken(v); + if( regPeer && pOrderBy ){ + sqlite3VdbeAddOp3(v, OP_Copy, regNewPeer, regPeer, pOrderBy->nExpr-1); + sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.start.reg, pOrderBy->nExpr-1); + sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.current.reg, pOrderBy->nExpr-1); + sqlite3VdbeAddOp3(v, OP_Copy, regPeer, s.end.reg, pOrderBy->nExpr-1); + } + + sqlite3VdbeAddOp2(v, OP_Goto, 0, lblWhereEnd); + + sqlite3VdbeJumpHere(v, addrNe); + + /* Beginning of the block executed for the second and subsequent rows. */ + if( regPeer ){ + windowIfNewPeer(pParse, pOrderBy, regNewPeer, regPeer, lblWhereEnd); + } + if( pMWin->eStart==TK_FOLLOWING ){ + windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0); + if( pMWin->eEnd!=TK_UNBOUNDED ){ + if( pMWin->eFrmType==TK_RANGE ){ + int lbl = sqlite3VdbeMakeLabel(pParse); + int addrNext = sqlite3VdbeCurrentAddr(v); + windowCodeRangeTest(&s, OP_Ge, s.current.csr, regEnd, s.end.csr, lbl); + windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); + windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext); + sqlite3VdbeResolveLabel(v, lbl); + }else{ + windowCodeOp(&s, WINDOW_RETURN_ROW, regEnd, 0); + windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); + } } + }else + if( pMWin->eEnd==TK_PRECEDING ){ + int bRPS = (pMWin->eStart==TK_PRECEDING && pMWin->eFrmType==TK_RANGE); + windowCodeOp(&s, WINDOW_AGGSTEP, regEnd, 0); + if( bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); + windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0); + if( !bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); + }else{ + int addr = 0; + windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0); + if( pMWin->eEnd!=TK_UNBOUNDED ){ + if( pMWin->eFrmType==TK_RANGE ){ + int lbl = 0; + addr = sqlite3VdbeCurrentAddr(v); + if( regEnd ){ + lbl = sqlite3VdbeMakeLabel(pParse); + windowCodeRangeTest(&s, OP_Ge, s.current.csr, regEnd, s.end.csr, lbl); + } + windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0); + windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); + if( regEnd ){ + sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); + sqlite3VdbeResolveLabel(v, lbl); + } + }else{ + if( regEnd ){ + addr = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0, 1); + VdbeCoverage(v); + } + windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0); + windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); + if( regEnd ) sqlite3VdbeJumpHere(v, addr); + } + } + } + + /* End of the main input loop */ + sqlite3VdbeResolveLabel(v, lblWhereEnd); + sqlite3WhereEnd(pWInfo); + + /* Fall through */ + if( pMWin->pPartition ){ + addrInteger = sqlite3VdbeAddOp2(v, OP_Integer, 0, regFlushPart); + sqlite3VdbeJumpHere(v, addrGosubFlush); + } + + addrEmpty = sqlite3VdbeAddOp1(v, OP_Rewind, csrWrite); + VdbeCoverage(v); + if( pMWin->eEnd==TK_PRECEDING ){ + int bRPS = (pMWin->eStart==TK_PRECEDING && pMWin->eFrmType==TK_RANGE); + windowCodeOp(&s, WINDOW_AGGSTEP, regEnd, 0); + if( bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); + windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0); + }else if( pMWin->eStart==TK_FOLLOWING ){ + int addrStart; + int addrBreak1; + int addrBreak2; + int addrBreak3; + windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0); + if( pMWin->eFrmType==TK_RANGE ){ + addrStart = sqlite3VdbeCurrentAddr(v); + addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 1); + addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 1); + }else + if( pMWin->eEnd==TK_UNBOUNDED ){ + addrStart = sqlite3VdbeCurrentAddr(v); + addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regStart, 1); + addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, 0, 1); + }else{ + assert( pMWin->eEnd==TK_FOLLOWING ); + addrStart = sqlite3VdbeCurrentAddr(v); + addrBreak1 = windowCodeOp(&s, WINDOW_RETURN_ROW, regEnd, 1); + addrBreak2 = windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 1); + } + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart); + sqlite3VdbeJumpHere(v, addrBreak2); + addrStart = sqlite3VdbeCurrentAddr(v); + addrBreak3 = windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 1); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart); + sqlite3VdbeJumpHere(v, addrBreak1); + sqlite3VdbeJumpHere(v, addrBreak3); + }else{ + int addrBreak; + int addrStart; + windowCodeOp(&s, WINDOW_AGGSTEP, 0, 0); + addrStart = sqlite3VdbeCurrentAddr(v); + addrBreak = windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 1); + windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrStart); + sqlite3VdbeJumpHere(v, addrBreak); + } + sqlite3VdbeJumpHere(v, addrEmpty); + + sqlite3VdbeAddOp1(v, OP_ResetSorter, s.current.csr); + if( pMWin->pPartition ){ + if( pMWin->regStartRowid ){ + sqlite3VdbeAddOp2(v, OP_Integer, 1, pMWin->regStartRowid); + sqlite3VdbeAddOp2(v, OP_Integer, 0, pMWin->regEndRowid); + } + sqlite3VdbeChangeP1(v, addrInteger, sqlite3VdbeCurrentAddr(v)); + sqlite3VdbeAddOp1(v, OP_Return, regFlushPart); } } @@ -147488,6 +148298,10 @@ static void disableLookaside(Parse *pParse){ sqlite3ExprListSetName(pParse, p, pIdToken, 1); return p; } + +#if TK_SPAN>255 +# error too many tokens in the grammar +#endif /**************** End of %include directives **********************************/ /* These constants specify the various numeric values for terminal symbols ** in a format understandable to "makeheaders". This section is blank unless @@ -147551,27 +148365,28 @@ static void disableLookaside(Parse *pParse){ #endif /************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned short int -#define YYNOCODE 278 +#define YYNOCODE 301 #define YYACTIONTYPE unsigned short int -#define YYWILDCARD 91 +#define YYWILDCARD 95 #define sqlite3ParserTOKENTYPE Token typedef union { int yyinit; sqlite3ParserTOKENTYPE yy0; - ExprList* yy42; - int yy96; - TriggerStep* yy119; - Window* yy147; - SrcList* yy167; - Upsert* yy266; - struct FrameBound yy317; - IdList* yy336; - struct TrigEvent yy350; - struct {int value; int mask;} yy367; - Select* yy423; - const char* yy464; - Expr* yy490; - With* yy499; + With* yy59; + IdList* yy62; + struct TrigEvent yy90; + Upsert* yy136; + struct FrameBound yy201; + u8 yy238; + const char* yy294; + Window* yy295; + struct {int value; int mask;} yy355; + ExprList* yy434; + TriggerStep* yy455; + Select* yy457; + SrcList* yy483; + int yy494; + Expr* yy524; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 @@ -147587,17 +148402,17 @@ typedef union { #define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse; #define sqlite3ParserCTX_STORE yypParser->pParse=pParse; #define YYFALLBACK 1 -#define YYNSTATE 524 -#define YYNRULE 369 -#define YYNTOKEN 155 -#define YY_MAX_SHIFT 523 -#define YY_MIN_SHIFTREDUCE 760 -#define YY_MAX_SHIFTREDUCE 1128 -#define YY_ERROR_ACTION 1129 -#define YY_ACCEPT_ACTION 1130 -#define YY_NO_ACTION 1131 -#define YY_MIN_REDUCE 1132 -#define YY_MAX_REDUCE 1500 +#define YYNSTATE 541 +#define YYNRULE 375 +#define YYNTOKEN 176 +#define YY_MAX_SHIFT 540 +#define YY_MIN_SHIFTREDUCE 784 +#define YY_MAX_SHIFTREDUCE 1158 +#define YY_ERROR_ACTION 1159 +#define YY_ACCEPT_ACTION 1160 +#define YY_NO_ACTION 1161 +#define YY_MIN_REDUCE 1162 +#define YY_MAX_REDUCE 1536 /************* End control #defines *******************************************/ #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) @@ -147664,569 +148479,603 @@ typedef union { ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (2009) +#define YY_ACTTAB_COUNT (2142) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 377, 518, 371, 107, 104, 200, 1293, 518, 1130, 1, - /* 10 */ 1, 523, 2, 1134, 518, 1203, 1203, 1262, 277, 373, - /* 20 */ 129, 495, 37, 37, 1397, 1201, 1201, 1211, 65, 65, - /* 30 */ 480, 891, 107, 104, 200, 37, 37, 1043, 1494, 892, - /* 40 */ 346, 1494, 342, 114, 115, 105, 1106, 1106, 957, 960, - /* 50 */ 950, 950, 112, 112, 113, 113, 113, 113, 285, 254, - /* 60 */ 254, 518, 254, 254, 500, 518, 495, 518, 107, 104, - /* 70 */ 200, 1085, 515, 481, 386, 515, 1464, 442, 501, 230, - /* 80 */ 197, 439, 37, 37, 1172, 210, 65, 65, 65, 65, - /* 90 */ 254, 254, 111, 111, 111, 111, 110, 110, 109, 109, - /* 100 */ 109, 108, 404, 515, 404, 155, 1041, 431, 401, 400, - /* 110 */ 254, 254, 373, 1431, 1427, 408, 1110, 1085, 1086, 1087, - /* 120 */ 284, 1112, 500, 515, 500, 368, 1433, 1421, 1428, 1111, - /* 130 */ 1261, 499, 373, 502, 108, 404, 114, 115, 105, 1106, - /* 140 */ 1106, 957, 960, 950, 950, 112, 112, 113, 113, 113, - /* 150 */ 113, 276, 509, 1113, 369, 1113, 114, 115, 105, 1106, - /* 160 */ 1106, 957, 960, 950, 950, 112, 112, 113, 113, 113, - /* 170 */ 113, 496, 1420, 1431, 493, 1468, 1065, 260, 1063, 433, - /* 180 */ 74, 107, 104, 200, 498, 111, 111, 111, 111, 110, - /* 190 */ 110, 109, 109, 109, 108, 404, 373, 113, 113, 113, - /* 200 */ 113, 106, 131, 91, 1361, 111, 111, 111, 111, 110, - /* 210 */ 110, 109, 109, 109, 108, 404, 113, 113, 113, 113, - /* 220 */ 114, 115, 105, 1106, 1106, 957, 960, 950, 950, 112, - /* 230 */ 112, 113, 113, 113, 113, 111, 111, 111, 111, 110, - /* 240 */ 110, 109, 109, 109, 108, 404, 116, 110, 110, 109, - /* 250 */ 109, 109, 108, 404, 111, 111, 111, 111, 110, 110, - /* 260 */ 109, 109, 109, 108, 404, 917, 512, 512, 512, 111, - /* 270 */ 111, 111, 111, 110, 110, 109, 109, 109, 108, 404, - /* 280 */ 517, 1198, 1177, 181, 109, 109, 109, 108, 404, 373, - /* 290 */ 1198, 402, 402, 402, 75, 360, 111, 111, 111, 111, - /* 300 */ 110, 110, 109, 109, 109, 108, 404, 382, 299, 419, - /* 310 */ 287, 170, 518, 114, 115, 105, 1106, 1106, 957, 960, - /* 320 */ 950, 950, 112, 112, 113, 113, 113, 113, 1444, 523, - /* 330 */ 2, 1134, 518, 13, 13, 337, 277, 1085, 129, 226, - /* 340 */ 937, 1058, 1000, 471, 917, 1211, 453, 384, 1085, 395, - /* 350 */ 162, 1057, 155, 45, 45, 416, 928, 401, 400, 479, - /* 360 */ 927, 12, 111, 111, 111, 111, 110, 110, 109, 109, - /* 370 */ 109, 108, 404, 226, 286, 254, 254, 254, 254, 518, - /* 380 */ 16, 16, 373, 1085, 1086, 1087, 314, 299, 515, 472, - /* 390 */ 515, 927, 927, 929, 1085, 1086, 1087, 378, 276, 509, - /* 400 */ 65, 65, 1113, 210, 1113, 1085, 114, 115, 105, 1106, - /* 410 */ 1106, 957, 960, 950, 950, 112, 112, 113, 113, 113, - /* 420 */ 113, 1448, 222, 1134, 1089, 461, 458, 457, 277, 180, - /* 430 */ 129, 378, 392, 408, 423, 456, 500, 1211, 240, 257, - /* 440 */ 324, 464, 319, 463, 227, 470, 12, 317, 424, 300, - /* 450 */ 317, 1085, 1086, 1087, 485, 111, 111, 111, 111, 110, - /* 460 */ 110, 109, 109, 109, 108, 404, 181, 118, 1085, 254, - /* 470 */ 254, 1089, 518, 90, 351, 373, 518, 1181, 365, 798, - /* 480 */ 1440, 339, 515, 248, 248, 77, 325, 133, 1085, 249, - /* 490 */ 424, 300, 794, 49, 49, 210, 515, 65, 65, 114, - /* 500 */ 115, 105, 1106, 1106, 957, 960, 950, 950, 112, 112, - /* 510 */ 113, 113, 113, 113, 1085, 1086, 1087, 222, 1085, 438, - /* 520 */ 461, 458, 457, 937, 787, 408, 171, 857, 362, 1021, - /* 530 */ 456, 136, 198, 486, 1085, 1086, 1087, 448, 794, 928, - /* 540 */ 5, 193, 192, 927, 1022, 107, 104, 200, 111, 111, - /* 550 */ 111, 111, 110, 110, 109, 109, 109, 108, 404, 1023, - /* 560 */ 254, 254, 803, 1085, 1085, 1086, 1087, 437, 373, 1085, - /* 570 */ 344, 787, 791, 515, 927, 927, 929, 1085, 1408, 1396, - /* 580 */ 832, 1085, 176, 3, 852, 1085, 518, 1439, 429, 851, - /* 590 */ 833, 518, 114, 115, 105, 1106, 1106, 957, 960, 950, - /* 600 */ 950, 112, 112, 113, 113, 113, 113, 13, 13, 1085, - /* 610 */ 1086, 1087, 13, 13, 518, 1085, 1086, 1087, 1496, 358, - /* 620 */ 1085, 389, 1234, 1085, 1086, 1087, 391, 1085, 1086, 1087, - /* 630 */ 448, 1085, 1086, 1087, 518, 65, 65, 947, 947, 958, - /* 640 */ 961, 111, 111, 111, 111, 110, 110, 109, 109, 109, - /* 650 */ 108, 404, 518, 382, 878, 13, 13, 518, 877, 518, - /* 660 */ 263, 373, 518, 431, 448, 1070, 1085, 1086, 1087, 267, - /* 670 */ 448, 488, 1360, 64, 64, 431, 812, 155, 50, 50, - /* 680 */ 65, 65, 518, 65, 65, 114, 115, 105, 1106, 1106, - /* 690 */ 957, 960, 950, 950, 112, 112, 113, 113, 113, 113, - /* 700 */ 518, 951, 382, 13, 13, 415, 411, 462, 414, 1085, - /* 710 */ 1366, 777, 1210, 292, 297, 813, 399, 497, 181, 403, - /* 720 */ 261, 15, 15, 276, 509, 414, 413, 1366, 1368, 410, - /* 730 */ 372, 345, 1209, 264, 111, 111, 111, 111, 110, 110, - /* 740 */ 109, 109, 109, 108, 404, 265, 254, 254, 229, 1405, - /* 750 */ 268, 1215, 268, 1103, 373, 1085, 1086, 1087, 938, 515, - /* 760 */ 393, 409, 876, 515, 254, 254, 1152, 482, 473, 262, - /* 770 */ 422, 476, 325, 503, 289, 518, 291, 515, 114, 115, - /* 780 */ 105, 1106, 1106, 957, 960, 950, 950, 112, 112, 113, - /* 790 */ 113, 113, 113, 414, 1021, 1366, 39, 39, 254, 254, - /* 800 */ 254, 254, 980, 254, 254, 254, 254, 255, 255, 1022, - /* 810 */ 279, 515, 516, 515, 846, 846, 515, 138, 515, 518, - /* 820 */ 515, 1043, 1495, 251, 1023, 1495, 876, 111, 111, 111, - /* 830 */ 111, 110, 110, 109, 109, 109, 108, 404, 518, 1353, - /* 840 */ 51, 51, 518, 199, 518, 506, 290, 373, 518, 276, - /* 850 */ 509, 922, 9, 483, 233, 1005, 1005, 445, 189, 52, - /* 860 */ 52, 325, 280, 53, 53, 54, 54, 373, 876, 55, - /* 870 */ 55, 114, 115, 105, 1106, 1106, 957, 960, 950, 950, - /* 880 */ 112, 112, 113, 113, 113, 113, 97, 518, 95, 1104, - /* 890 */ 1041, 114, 115, 105, 1106, 1106, 957, 960, 950, 950, - /* 900 */ 112, 112, 113, 113, 113, 113, 135, 199, 56, 56, - /* 910 */ 765, 766, 767, 225, 224, 223, 518, 283, 437, 233, - /* 920 */ 111, 111, 111, 111, 110, 110, 109, 109, 109, 108, - /* 930 */ 404, 1002, 876, 326, 518, 1002, 1104, 40, 40, 518, - /* 940 */ 111, 111, 111, 111, 110, 110, 109, 109, 109, 108, - /* 950 */ 404, 518, 448, 518, 1104, 41, 41, 518, 17, 518, - /* 960 */ 43, 43, 1155, 379, 518, 448, 518, 443, 518, 390, - /* 970 */ 518, 194, 44, 44, 57, 57, 1247, 518, 58, 58, - /* 980 */ 59, 59, 518, 466, 326, 14, 14, 60, 60, 120, - /* 990 */ 120, 61, 61, 449, 1206, 93, 518, 425, 46, 46, - /* 1000 */ 518, 1104, 518, 62, 62, 518, 437, 305, 518, 852, - /* 1010 */ 518, 298, 518, 1246, 851, 373, 518, 63, 63, 1293, - /* 1020 */ 397, 47, 47, 142, 142, 1467, 143, 143, 821, 70, - /* 1030 */ 70, 48, 48, 66, 66, 373, 518, 121, 121, 114, - /* 1040 */ 115, 105, 1106, 1106, 957, 960, 950, 950, 112, 112, - /* 1050 */ 113, 113, 113, 113, 518, 418, 518, 67, 67, 114, - /* 1060 */ 115, 105, 1106, 1106, 957, 960, 950, 950, 112, 112, - /* 1070 */ 113, 113, 113, 113, 312, 122, 122, 123, 123, 1293, - /* 1080 */ 518, 357, 1126, 88, 518, 435, 325, 387, 111, 111, - /* 1090 */ 111, 111, 110, 110, 109, 109, 109, 108, 404, 266, - /* 1100 */ 518, 119, 119, 518, 1293, 141, 141, 518, 111, 111, - /* 1110 */ 111, 111, 110, 110, 109, 109, 109, 108, 404, 518, - /* 1120 */ 801, 140, 140, 518, 127, 127, 511, 379, 126, 126, - /* 1130 */ 518, 137, 518, 1308, 518, 307, 518, 310, 518, 203, - /* 1140 */ 124, 124, 1307, 96, 125, 125, 207, 388, 1441, 468, - /* 1150 */ 1127, 69, 69, 71, 71, 68, 68, 38, 38, 42, - /* 1160 */ 42, 357, 1042, 373, 1293, 276, 509, 801, 185, 469, - /* 1170 */ 494, 436, 444, 6, 380, 156, 253, 197, 469, 134, - /* 1180 */ 426, 33, 1038, 373, 1121, 359, 1411, 114, 115, 105, - /* 1190 */ 1106, 1106, 957, 960, 950, 950, 112, 112, 113, 113, - /* 1200 */ 113, 113, 914, 296, 27, 293, 90, 114, 103, 105, - /* 1210 */ 1106, 1106, 957, 960, 950, 950, 112, 112, 113, 113, - /* 1220 */ 113, 113, 919, 275, 430, 232, 891, 232, 432, 256, - /* 1230 */ 1127, 232, 398, 370, 892, 28, 111, 111, 111, 111, - /* 1240 */ 110, 110, 109, 109, 109, 108, 404, 301, 454, 1385, - /* 1250 */ 90, 228, 209, 987, 811, 810, 111, 111, 111, 111, - /* 1260 */ 110, 110, 109, 109, 109, 108, 404, 315, 818, 819, - /* 1270 */ 90, 323, 983, 931, 885, 228, 373, 232, 999, 849, - /* 1280 */ 999, 322, 102, 998, 1384, 998, 785, 850, 440, 132, - /* 1290 */ 102, 302, 1243, 306, 309, 311, 373, 313, 1194, 1180, - /* 1300 */ 987, 115, 105, 1106, 1106, 957, 960, 950, 950, 112, - /* 1310 */ 112, 113, 113, 113, 113, 1178, 1179, 318, 327, 328, - /* 1320 */ 931, 1255, 105, 1106, 1106, 957, 960, 950, 950, 112, - /* 1330 */ 112, 113, 113, 113, 113, 1292, 1230, 1457, 273, 1241, - /* 1340 */ 504, 505, 1298, 100, 510, 246, 4, 1161, 1154, 111, - /* 1350 */ 111, 111, 111, 110, 110, 109, 109, 109, 108, 404, - /* 1360 */ 513, 1143, 187, 1142, 202, 1144, 1451, 356, 1227, 111, - /* 1370 */ 111, 111, 111, 110, 110, 109, 109, 109, 108, 404, - /* 1380 */ 11, 1277, 330, 405, 332, 334, 191, 1285, 364, 195, - /* 1390 */ 295, 417, 288, 100, 510, 507, 4, 434, 459, 321, - /* 1400 */ 1177, 349, 1357, 1356, 336, 155, 190, 1454, 1121, 158, - /* 1410 */ 513, 508, 235, 1404, 937, 1402, 1118, 381, 77, 428, - /* 1420 */ 98, 98, 8, 1282, 168, 30, 152, 99, 160, 405, - /* 1430 */ 520, 519, 88, 405, 927, 1362, 1274, 420, 163, 73, - /* 1440 */ 164, 76, 165, 166, 421, 507, 452, 212, 361, 363, - /* 1450 */ 427, 276, 509, 31, 1288, 172, 491, 441, 216, 1351, - /* 1460 */ 82, 490, 447, 1373, 937, 927, 927, 929, 930, 24, - /* 1470 */ 98, 98, 304, 247, 218, 177, 308, 99, 219, 405, - /* 1480 */ 520, 519, 450, 1145, 927, 220, 366, 1197, 100, 510, - /* 1490 */ 465, 4, 1188, 1196, 1195, 394, 803, 1169, 1187, 367, - /* 1500 */ 1168, 396, 484, 320, 1167, 513, 1466, 87, 475, 100, - /* 1510 */ 510, 271, 4, 272, 478, 927, 927, 929, 930, 24, - /* 1520 */ 1443, 1074, 407, 1238, 1239, 258, 513, 329, 405, 331, - /* 1530 */ 355, 355, 354, 243, 352, 234, 489, 774, 498, 184, - /* 1540 */ 507, 338, 1422, 339, 117, 1220, 10, 341, 333, 405, - /* 1550 */ 204, 491, 282, 1219, 1237, 1236, 492, 335, 343, 937, - /* 1560 */ 281, 507, 94, 1337, 186, 98, 98, 347, 89, 487, - /* 1570 */ 348, 241, 99, 29, 405, 520, 519, 274, 1151, 927, - /* 1580 */ 937, 521, 1080, 245, 242, 244, 98, 98, 856, 522, - /* 1590 */ 206, 1140, 1135, 99, 144, 405, 520, 519, 147, 375, - /* 1600 */ 927, 149, 376, 157, 1389, 1390, 1388, 1387, 205, 145, - /* 1610 */ 927, 927, 929, 930, 24, 146, 130, 761, 1165, 1164, - /* 1620 */ 72, 100, 510, 1162, 4, 269, 406, 188, 278, 201, - /* 1630 */ 259, 927, 927, 929, 930, 24, 128, 911, 513, 997, - /* 1640 */ 995, 159, 374, 208, 148, 161, 835, 276, 509, 211, - /* 1650 */ 294, 1011, 915, 167, 150, 383, 169, 78, 385, 79, - /* 1660 */ 80, 405, 81, 151, 1014, 213, 214, 1010, 139, 18, - /* 1670 */ 412, 215, 303, 507, 232, 1115, 1003, 446, 173, 217, - /* 1680 */ 174, 32, 776, 451, 491, 322, 221, 175, 814, 490, - /* 1690 */ 83, 455, 937, 19, 460, 316, 20, 84, 98, 98, - /* 1700 */ 270, 182, 85, 467, 153, 99, 154, 405, 520, 519, - /* 1710 */ 1074, 407, 927, 183, 258, 963, 1046, 86, 34, 355, - /* 1720 */ 355, 354, 243, 352, 474, 1047, 774, 35, 477, 196, - /* 1730 */ 250, 100, 510, 252, 4, 884, 178, 231, 1060, 204, - /* 1740 */ 21, 282, 102, 927, 927, 929, 930, 24, 513, 281, - /* 1750 */ 879, 22, 1064, 1062, 1051, 7, 340, 23, 978, 179, - /* 1760 */ 90, 92, 510, 964, 4, 236, 962, 966, 1020, 1019, - /* 1770 */ 237, 405, 967, 25, 36, 514, 932, 786, 513, 206, - /* 1780 */ 101, 26, 845, 507, 238, 239, 1459, 147, 350, 1458, - /* 1790 */ 149, 353, 1075, 1131, 1131, 1131, 1131, 205, 1131, 1131, - /* 1800 */ 1131, 405, 937, 1131, 1131, 1131, 1131, 1131, 98, 98, - /* 1810 */ 1131, 1131, 1131, 507, 1131, 99, 1131, 405, 520, 519, - /* 1820 */ 1131, 1131, 927, 1131, 1131, 1131, 1131, 1131, 1131, 1131, - /* 1830 */ 1131, 374, 937, 1131, 1131, 1131, 276, 509, 98, 98, - /* 1840 */ 1131, 1131, 1131, 1131, 1131, 99, 1131, 405, 520, 519, - /* 1850 */ 1131, 1131, 927, 927, 927, 929, 930, 24, 1131, 412, - /* 1860 */ 1131, 1131, 1131, 258, 1131, 1131, 1131, 1131, 355, 355, - /* 1870 */ 354, 243, 352, 1131, 1131, 774, 1131, 1131, 1131, 1131, - /* 1880 */ 1131, 1131, 1131, 927, 927, 929, 930, 24, 204, 1131, - /* 1890 */ 282, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 281, 1131, - /* 1900 */ 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, - /* 1910 */ 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, - /* 1920 */ 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 206, 1131, - /* 1930 */ 1131, 1131, 1131, 1131, 1131, 1131, 147, 1131, 1131, 149, - /* 1940 */ 1131, 1131, 1131, 1131, 1131, 1131, 205, 1131, 1131, 1131, - /* 1950 */ 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, - /* 1960 */ 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, - /* 1970 */ 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, - /* 1980 */ 374, 1131, 1131, 1131, 1131, 276, 509, 1131, 1131, 1131, - /* 1990 */ 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, - /* 2000 */ 1131, 1131, 1131, 1131, 1131, 1131, 1131, 1131, 412, + /* 0 */ 535, 1323, 112, 109, 209, 112, 109, 209, 1160, 1, + /* 10 */ 1, 540, 2, 1164, 535, 1292, 1228, 1207, 289, 384, + /* 20 */ 134, 42, 42, 1427, 382, 1228, 9, 1241, 242, 492, + /* 30 */ 1291, 915, 373, 379, 1026, 70, 70, 427, 1026, 916, + /* 40 */ 529, 529, 529, 119, 120, 110, 1136, 1136, 981, 984, + /* 50 */ 974, 974, 117, 117, 118, 118, 118, 118, 380, 264, + /* 60 */ 264, 264, 264, 1134, 264, 264, 112, 109, 209, 397, + /* 70 */ 454, 517, 532, 491, 532, 1233, 1233, 532, 239, 206, + /* 80 */ 493, 112, 109, 209, 464, 219, 118, 118, 118, 118, + /* 90 */ 111, 393, 440, 444, 16, 16, 116, 116, 116, 116, + /* 100 */ 115, 115, 114, 114, 114, 113, 415, 971, 971, 982, + /* 110 */ 985, 235, 1463, 351, 1134, 419, 384, 116, 116, 116, + /* 120 */ 116, 115, 115, 114, 114, 114, 113, 415, 116, 116, + /* 130 */ 116, 116, 115, 115, 114, 114, 114, 113, 415, 961, + /* 140 */ 119, 120, 110, 1136, 1136, 981, 984, 974, 974, 117, + /* 150 */ 117, 118, 118, 118, 118, 952, 415, 941, 298, 951, + /* 160 */ 941, 1480, 540, 2, 1164, 1115, 535, 1458, 160, 289, + /* 170 */ 6, 134, 1504, 389, 406, 975, 338, 1024, 1241, 337, + /* 180 */ 1089, 1476, 1089, 118, 118, 118, 118, 42, 42, 329, + /* 190 */ 951, 951, 953, 116, 116, 116, 116, 115, 115, 114, + /* 200 */ 114, 114, 113, 415, 311, 430, 299, 311, 881, 160, + /* 210 */ 264, 264, 401, 384, 324, 1115, 1116, 1117, 288, 526, + /* 220 */ 96, 159, 1441, 532, 141, 116, 116, 116, 116, 115, + /* 230 */ 115, 114, 114, 114, 113, 415, 219, 119, 120, 110, + /* 240 */ 1136, 1136, 981, 984, 974, 974, 117, 117, 118, 118, + /* 250 */ 118, 118, 115, 115, 114, 114, 114, 113, 415, 288, + /* 260 */ 526, 403, 533, 121, 870, 870, 419, 250, 267, 336, + /* 270 */ 475, 331, 474, 236, 160, 319, 1084, 322, 1465, 329, + /* 280 */ 350, 12, 535, 384, 502, 1115, 1084, 435, 312, 1084, + /* 290 */ 116, 116, 116, 116, 115, 115, 114, 114, 114, 113, + /* 300 */ 415, 535, 836, 42, 42, 138, 426, 119, 120, 110, + /* 310 */ 1136, 1136, 981, 984, 974, 974, 117, 117, 118, 118, + /* 320 */ 118, 118, 70, 70, 288, 526, 412, 411, 480, 1457, + /* 330 */ 335, 79, 6, 473, 1140, 1115, 1116, 1117, 501, 1142, + /* 340 */ 334, 837, 811, 1484, 512, 1164, 534, 1141, 123, 187, + /* 350 */ 289, 384, 134, 448, 434, 1115, 80, 349, 498, 1241, + /* 360 */ 116, 116, 116, 116, 115, 115, 114, 114, 114, 113, + /* 370 */ 415, 1143, 1115, 1143, 459, 119, 120, 110, 1136, 1136, + /* 380 */ 981, 984, 974, 974, 117, 117, 118, 118, 118, 118, + /* 390 */ 404, 264, 264, 811, 1463, 506, 368, 1156, 535, 114, + /* 400 */ 114, 114, 113, 415, 532, 1115, 1116, 1117, 231, 518, + /* 410 */ 1500, 472, 469, 468, 175, 497, 422, 219, 1202, 70, + /* 420 */ 70, 467, 1115, 1116, 1117, 176, 201, 200, 116, 116, + /* 430 */ 116, 116, 115, 115, 114, 114, 114, 113, 415, 535, + /* 440 */ 1115, 264, 264, 435, 312, 1115, 273, 419, 384, 513, + /* 450 */ 1450, 1115, 326, 1084, 532, 517, 82, 1084, 167, 388, + /* 460 */ 69, 69, 1115, 1084, 519, 509, 1084, 1084, 12, 1157, + /* 470 */ 1084, 420, 119, 120, 110, 1136, 1136, 981, 984, 974, + /* 480 */ 974, 117, 117, 118, 118, 118, 118, 258, 258, 535, + /* 490 */ 1115, 1116, 1117, 1045, 535, 1115, 1116, 1117, 1323, 535, + /* 500 */ 532, 1115, 1116, 1117, 296, 483, 1211, 818, 1046, 448, + /* 510 */ 70, 70, 1115, 1116, 1117, 50, 50, 448, 356, 500, + /* 520 */ 70, 70, 207, 1047, 32, 116, 116, 116, 116, 115, + /* 530 */ 115, 114, 114, 114, 113, 415, 453, 264, 264, 1115, + /* 540 */ 450, 449, 961, 508, 856, 384, 517, 5, 900, 822, + /* 550 */ 532, 484, 181, 1115, 857, 516, 517, 818, 952, 507, + /* 560 */ 3, 1115, 951, 1231, 1231, 482, 398, 1115, 1095, 119, + /* 570 */ 120, 110, 1136, 1136, 981, 984, 974, 974, 117, 117, + /* 580 */ 118, 118, 118, 118, 1115, 535, 238, 1115, 1391, 1115, + /* 590 */ 1116, 1117, 159, 951, 951, 953, 231, 1115, 259, 472, + /* 600 */ 469, 468, 310, 1115, 1116, 1117, 13, 13, 297, 467, + /* 610 */ 276, 1115, 1116, 1117, 412, 411, 1095, 1115, 1116, 1117, + /* 620 */ 395, 355, 116, 116, 116, 116, 115, 115, 114, 114, + /* 630 */ 114, 113, 415, 208, 1115, 1116, 1117, 1115, 1116, 1117, + /* 640 */ 264, 264, 384, 337, 902, 393, 815, 1115, 1116, 1117, + /* 650 */ 413, 413, 413, 532, 112, 109, 209, 309, 900, 1143, + /* 660 */ 535, 1143, 535, 393, 901, 1210, 119, 120, 110, 1136, + /* 670 */ 1136, 981, 984, 974, 974, 117, 117, 118, 118, 118, + /* 680 */ 118, 13, 13, 13, 13, 265, 265, 535, 143, 264, + /* 690 */ 264, 288, 526, 535, 1119, 400, 535, 402, 532, 510, + /* 700 */ 1457, 512, 532, 6, 113, 415, 1067, 1530, 70, 70, + /* 710 */ 1530, 535, 271, 535, 70, 70, 535, 13, 13, 116, + /* 720 */ 116, 116, 116, 115, 115, 114, 114, 114, 113, 415, + /* 730 */ 272, 277, 13, 13, 13, 13, 535, 13, 13, 384, + /* 740 */ 535, 304, 425, 1100, 284, 1119, 184, 801, 185, 338, + /* 750 */ 285, 514, 1532, 369, 1239, 1438, 1182, 70, 70, 425, + /* 760 */ 424, 70, 70, 119, 120, 110, 1136, 1136, 981, 984, + /* 770 */ 974, 974, 117, 117, 118, 118, 118, 118, 190, 1065, + /* 780 */ 1067, 1531, 442, 107, 1531, 408, 264, 264, 264, 264, + /* 790 */ 383, 1396, 261, 410, 95, 900, 485, 414, 421, 532, + /* 800 */ 1045, 532, 301, 1133, 303, 488, 433, 1451, 1396, 1398, + /* 810 */ 278, 535, 278, 520, 1435, 1046, 116, 116, 116, 116, + /* 820 */ 115, 115, 114, 114, 114, 113, 415, 425, 264, 264, + /* 830 */ 1047, 190, 54, 54, 535, 291, 384, 264, 264, 362, + /* 840 */ 962, 532, 1004, 376, 1084, 264, 264, 1029, 1029, 456, + /* 850 */ 532, 523, 270, 1065, 1084, 55, 55, 1084, 532, 442, + /* 860 */ 119, 120, 110, 1136, 1136, 981, 984, 974, 974, 117, + /* 870 */ 117, 118, 118, 118, 118, 535, 1396, 190, 302, 1383, + /* 880 */ 208, 535, 789, 790, 791, 535, 515, 535, 1323, 371, + /* 890 */ 337, 234, 233, 232, 459, 515, 15, 15, 459, 477, + /* 900 */ 459, 459, 44, 44, 136, 900, 56, 56, 57, 57, + /* 910 */ 1185, 390, 197, 116, 116, 116, 116, 115, 115, 114, + /* 920 */ 114, 114, 113, 415, 535, 876, 535, 442, 535, 274, + /* 930 */ 875, 1323, 357, 384, 353, 140, 1426, 946, 1455, 1323, + /* 940 */ 1390, 6, 1240, 1236, 292, 58, 58, 59, 59, 60, + /* 950 */ 60, 535, 1456, 384, 535, 6, 399, 119, 120, 110, + /* 960 */ 1136, 1136, 981, 984, 974, 974, 117, 117, 118, 118, + /* 970 */ 118, 118, 61, 61, 535, 45, 45, 119, 120, 110, + /* 980 */ 1136, 1136, 981, 984, 974, 974, 117, 117, 118, 118, + /* 990 */ 118, 118, 1477, 479, 202, 46, 46, 275, 95, 455, + /* 1000 */ 535, 212, 535, 337, 535, 1454, 535, 409, 6, 242, + /* 1010 */ 116, 116, 116, 116, 115, 115, 114, 114, 114, 113, + /* 1020 */ 415, 48, 48, 49, 49, 62, 62, 63, 63, 535, + /* 1030 */ 116, 116, 116, 116, 115, 115, 114, 114, 114, 113, + /* 1040 */ 415, 535, 459, 535, 1134, 535, 1151, 535, 142, 535, + /* 1050 */ 64, 64, 535, 1338, 535, 494, 535, 446, 535, 1264, + /* 1060 */ 535, 1337, 14, 14, 65, 65, 125, 125, 66, 66, + /* 1070 */ 51, 51, 535, 67, 67, 68, 68, 52, 52, 147, + /* 1080 */ 147, 148, 148, 1453, 317, 98, 6, 535, 1245, 481, + /* 1090 */ 535, 827, 535, 75, 75, 1134, 102, 481, 100, 535, + /* 1100 */ 532, 535, 368, 1066, 1503, 384, 535, 845, 53, 53, + /* 1110 */ 93, 71, 71, 126, 126, 295, 528, 390, 288, 526, + /* 1120 */ 72, 72, 127, 127, 139, 384, 38, 128, 128, 119, + /* 1130 */ 120, 110, 1136, 1136, 981, 984, 974, 974, 117, 117, + /* 1140 */ 118, 118, 118, 118, 535, 495, 535, 447, 535, 119, + /* 1150 */ 120, 110, 1136, 1136, 981, 984, 974, 974, 117, 117, + /* 1160 */ 118, 118, 118, 118, 235, 124, 124, 146, 146, 145, + /* 1170 */ 145, 287, 535, 1277, 535, 1157, 535, 391, 161, 263, + /* 1180 */ 206, 381, 116, 116, 116, 116, 115, 115, 114, 114, + /* 1190 */ 114, 113, 415, 132, 132, 131, 131, 129, 129, 535, + /* 1200 */ 30, 535, 116, 116, 116, 116, 115, 115, 114, 114, + /* 1210 */ 114, 113, 415, 535, 216, 1062, 1276, 535, 370, 535, + /* 1220 */ 130, 130, 74, 74, 535, 915, 389, 876, 17, 437, + /* 1230 */ 429, 31, 875, 916, 76, 76, 266, 101, 73, 73, + /* 1240 */ 43, 43, 835, 834, 308, 47, 47, 95, 825, 943, + /* 1250 */ 441, 938, 241, 241, 305, 443, 313, 384, 241, 95, + /* 1260 */ 842, 843, 193, 465, 1209, 327, 237, 436, 95, 1011, + /* 1270 */ 1007, 909, 873, 237, 241, 107, 1023, 384, 1023, 955, + /* 1280 */ 1415, 119, 120, 110, 1136, 1136, 981, 984, 974, 974, + /* 1290 */ 117, 117, 118, 118, 118, 118, 1022, 809, 1022, 825, + /* 1300 */ 137, 119, 108, 110, 1136, 1136, 981, 984, 974, 974, + /* 1310 */ 117, 117, 118, 118, 118, 118, 874, 1414, 451, 107, + /* 1320 */ 1011, 314, 1273, 318, 218, 321, 323, 325, 1224, 1208, + /* 1330 */ 955, 330, 339, 340, 116, 116, 116, 116, 115, 115, + /* 1340 */ 114, 114, 114, 113, 415, 1285, 1322, 1260, 1493, 1470, + /* 1350 */ 1271, 283, 521, 1328, 116, 116, 116, 116, 115, 115, + /* 1360 */ 114, 114, 114, 113, 415, 1191, 1184, 1173, 1172, 1174, + /* 1370 */ 522, 1487, 211, 460, 384, 256, 199, 367, 1257, 342, + /* 1380 */ 195, 470, 307, 344, 11, 333, 525, 445, 1307, 1315, + /* 1390 */ 375, 203, 1207, 1151, 384, 346, 1387, 188, 360, 120, + /* 1400 */ 110, 1136, 1136, 981, 984, 974, 974, 117, 117, 118, + /* 1410 */ 118, 118, 118, 1386, 428, 1490, 245, 300, 348, 1148, + /* 1420 */ 110, 1136, 1136, 981, 984, 974, 974, 117, 117, 118, + /* 1430 */ 118, 118, 118, 189, 198, 1434, 1432, 78, 81, 163, + /* 1440 */ 82, 392, 439, 1392, 173, 105, 527, 35, 4, 157, + /* 1450 */ 1312, 116, 116, 116, 116, 115, 115, 114, 114, 114, + /* 1460 */ 113, 415, 530, 165, 93, 1304, 431, 432, 168, 463, + /* 1470 */ 221, 116, 116, 116, 116, 115, 115, 114, 114, 114, + /* 1480 */ 113, 415, 169, 452, 170, 416, 171, 374, 372, 438, + /* 1490 */ 36, 1318, 177, 225, 1381, 87, 458, 524, 1403, 316, + /* 1500 */ 257, 105, 527, 227, 4, 182, 461, 160, 320, 228, + /* 1510 */ 377, 1175, 476, 229, 1227, 1226, 405, 1225, 530, 1218, + /* 1520 */ 961, 378, 1199, 1198, 827, 332, 103, 103, 1197, 407, + /* 1530 */ 8, 1217, 1502, 104, 487, 416, 537, 536, 281, 282, + /* 1540 */ 951, 416, 490, 1268, 496, 92, 341, 243, 1269, 343, + /* 1550 */ 244, 1267, 122, 524, 345, 1461, 515, 288, 526, 10, + /* 1560 */ 354, 1266, 1460, 352, 504, 1250, 99, 1367, 94, 503, + /* 1570 */ 499, 951, 951, 953, 954, 27, 961, 347, 1249, 194, + /* 1580 */ 251, 358, 103, 103, 359, 1181, 34, 538, 1110, 104, + /* 1590 */ 255, 416, 537, 536, 286, 252, 951, 254, 539, 149, + /* 1600 */ 1170, 1419, 1165, 1420, 1418, 150, 1417, 135, 279, 785, + /* 1610 */ 151, 417, 1195, 196, 290, 210, 386, 1194, 269, 387, + /* 1620 */ 162, 1021, 133, 77, 1192, 1019, 935, 951, 951, 953, + /* 1630 */ 954, 27, 1479, 1104, 418, 164, 153, 268, 217, 166, + /* 1640 */ 859, 306, 366, 366, 365, 253, 363, 220, 1035, 798, + /* 1650 */ 172, 939, 105, 527, 155, 4, 394, 174, 396, 156, + /* 1660 */ 83, 1038, 213, 84, 294, 85, 86, 223, 222, 530, + /* 1670 */ 1034, 144, 293, 18, 224, 315, 241, 1027, 1145, 178, + /* 1680 */ 457, 226, 179, 37, 800, 334, 462, 230, 328, 466, + /* 1690 */ 180, 471, 416, 88, 19, 20, 89, 280, 838, 158, + /* 1700 */ 191, 90, 215, 478, 524, 1097, 204, 192, 987, 91, + /* 1710 */ 152, 1070, 39, 154, 1071, 504, 486, 40, 489, 205, + /* 1720 */ 505, 260, 105, 527, 214, 4, 908, 961, 262, 183, + /* 1730 */ 240, 21, 903, 103, 103, 107, 22, 1086, 23, 530, + /* 1740 */ 104, 1088, 416, 537, 536, 24, 1093, 951, 25, 1074, + /* 1750 */ 1090, 1094, 7, 33, 511, 186, 26, 1002, 385, 95, + /* 1760 */ 988, 986, 416, 288, 526, 990, 1044, 246, 1043, 247, + /* 1770 */ 991, 28, 41, 106, 524, 956, 810, 29, 951, 951, + /* 1780 */ 953, 954, 27, 531, 361, 504, 423, 248, 869, 249, + /* 1790 */ 503, 1495, 364, 1105, 1161, 1494, 1161, 961, 1161, 1161, + /* 1800 */ 1161, 1161, 1161, 103, 103, 1161, 1161, 1161, 1161, 1161, + /* 1810 */ 104, 1161, 416, 537, 536, 1104, 418, 951, 1161, 268, + /* 1820 */ 1161, 1161, 1161, 1161, 366, 366, 365, 253, 363, 1161, + /* 1830 */ 1161, 798, 1161, 1161, 1161, 1161, 105, 527, 1161, 4, + /* 1840 */ 1161, 1161, 1161, 1161, 213, 1161, 294, 1161, 951, 951, + /* 1850 */ 953, 954, 27, 530, 293, 1161, 1161, 1161, 1161, 1161, + /* 1860 */ 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, + /* 1870 */ 1161, 1161, 1161, 1161, 1161, 1161, 416, 1161, 1161, 1161, + /* 1880 */ 1161, 1161, 1161, 1161, 215, 1161, 1161, 1161, 524, 1161, + /* 1890 */ 1161, 1161, 152, 1161, 1161, 154, 105, 527, 1161, 4, + /* 1900 */ 1161, 1161, 1161, 1161, 1161, 1161, 214, 1161, 1161, 1161, + /* 1910 */ 1161, 961, 1161, 530, 1161, 1161, 1161, 103, 103, 880, + /* 1920 */ 1161, 1161, 1161, 1161, 104, 1161, 416, 537, 536, 1161, + /* 1930 */ 1161, 951, 1161, 1161, 1161, 1161, 416, 1161, 1161, 1161, + /* 1940 */ 385, 1161, 1161, 1161, 1161, 288, 526, 1161, 524, 1161, + /* 1950 */ 1161, 1161, 1161, 1161, 1161, 1161, 97, 527, 1161, 4, + /* 1960 */ 1161, 1161, 951, 951, 953, 954, 27, 1161, 423, 1161, + /* 1970 */ 1161, 961, 1161, 530, 1161, 1161, 1161, 103, 103, 1161, + /* 1980 */ 1161, 1161, 1161, 1161, 104, 1161, 416, 537, 536, 1161, + /* 1990 */ 1161, 951, 268, 1161, 1161, 1161, 416, 366, 366, 365, + /* 2000 */ 253, 363, 1161, 1161, 798, 1161, 1161, 1161, 524, 1161, + /* 2010 */ 1161, 1161, 1161, 1161, 1161, 1161, 1161, 213, 1161, 294, + /* 2020 */ 1161, 1161, 951, 951, 953, 954, 27, 293, 1161, 1161, + /* 2030 */ 1161, 961, 1161, 1161, 1161, 1161, 1161, 103, 103, 1161, + /* 2040 */ 1161, 1161, 1161, 1161, 104, 1161, 416, 537, 536, 1161, + /* 2050 */ 1161, 951, 1161, 1161, 1161, 1161, 1161, 215, 1161, 1161, + /* 2060 */ 1161, 1161, 1161, 1161, 1161, 152, 1161, 1161, 154, 1161, + /* 2070 */ 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 214, + /* 2080 */ 1161, 1161, 951, 951, 953, 954, 27, 1161, 1161, 1161, + /* 2090 */ 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, + /* 2100 */ 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, + /* 2110 */ 1161, 1161, 1161, 385, 1161, 1161, 1161, 1161, 288, 526, + /* 2120 */ 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, + /* 2130 */ 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, + /* 2140 */ 1161, 423, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 168, 163, 184, 238, 239, 240, 163, 163, 155, 156, - /* 10 */ 157, 158, 159, 160, 163, 202, 203, 187, 165, 19, - /* 20 */ 167, 163, 184, 185, 259, 202, 203, 174, 184, 185, - /* 30 */ 174, 31, 238, 239, 240, 184, 185, 22, 23, 39, - /* 40 */ 216, 26, 218, 43, 44, 45, 46, 47, 48, 49, - /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 174, 206, - /* 60 */ 207, 163, 206, 207, 220, 163, 163, 163, 238, 239, - /* 70 */ 240, 59, 219, 229, 231, 219, 183, 245, 174, 223, - /* 80 */ 224, 249, 184, 185, 191, 232, 184, 185, 184, 185, - /* 90 */ 206, 207, 92, 93, 94, 95, 96, 97, 98, 99, - /* 100 */ 100, 101, 102, 219, 102, 81, 91, 163, 96, 97, - /* 110 */ 206, 207, 19, 275, 276, 262, 104, 105, 106, 107, - /* 120 */ 163, 109, 220, 219, 220, 184, 275, 269, 277, 117, - /* 130 */ 187, 229, 19, 229, 101, 102, 43, 44, 45, 46, - /* 140 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 150 */ 57, 127, 128, 141, 184, 143, 43, 44, 45, 46, - /* 160 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 170 */ 57, 268, 269, 275, 276, 197, 83, 233, 85, 163, - /* 180 */ 67, 238, 239, 240, 134, 92, 93, 94, 95, 96, - /* 190 */ 97, 98, 99, 100, 101, 102, 19, 54, 55, 56, - /* 200 */ 57, 58, 152, 26, 247, 92, 93, 94, 95, 96, - /* 210 */ 97, 98, 99, 100, 101, 102, 54, 55, 56, 57, - /* 220 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - /* 230 */ 53, 54, 55, 56, 57, 92, 93, 94, 95, 96, - /* 240 */ 97, 98, 99, 100, 101, 102, 69, 96, 97, 98, - /* 250 */ 99, 100, 101, 102, 92, 93, 94, 95, 96, 97, - /* 260 */ 98, 99, 100, 101, 102, 73, 179, 180, 181, 92, - /* 270 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - /* 280 */ 163, 191, 192, 163, 98, 99, 100, 101, 102, 19, - /* 290 */ 200, 179, 180, 181, 24, 175, 92, 93, 94, 95, - /* 300 */ 96, 97, 98, 99, 100, 101, 102, 163, 116, 117, - /* 310 */ 118, 22, 163, 43, 44, 45, 46, 47, 48, 49, - /* 320 */ 50, 51, 52, 53, 54, 55, 56, 57, 157, 158, - /* 330 */ 159, 160, 163, 184, 185, 163, 165, 59, 167, 46, - /* 340 */ 90, 76, 11, 174, 73, 174, 19, 198, 59, 19, - /* 350 */ 72, 86, 81, 184, 185, 234, 106, 96, 97, 163, - /* 360 */ 110, 182, 92, 93, 94, 95, 96, 97, 98, 99, - /* 370 */ 100, 101, 102, 46, 230, 206, 207, 206, 207, 163, - /* 380 */ 184, 185, 19, 105, 106, 107, 23, 116, 219, 220, - /* 390 */ 219, 141, 142, 143, 105, 106, 107, 104, 127, 128, - /* 400 */ 184, 185, 141, 232, 143, 59, 43, 44, 45, 46, - /* 410 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 420 */ 57, 158, 108, 160, 59, 111, 112, 113, 165, 250, - /* 430 */ 167, 104, 102, 262, 255, 121, 220, 174, 108, 109, - /* 440 */ 110, 111, 112, 113, 114, 229, 182, 120, 117, 118, - /* 450 */ 120, 105, 106, 107, 163, 92, 93, 94, 95, 96, - /* 460 */ 97, 98, 99, 100, 101, 102, 163, 22, 59, 206, - /* 470 */ 207, 106, 163, 26, 171, 19, 163, 193, 175, 23, - /* 480 */ 163, 22, 219, 206, 207, 139, 163, 22, 59, 182, - /* 490 */ 117, 118, 59, 184, 185, 232, 219, 184, 185, 43, - /* 500 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - /* 510 */ 54, 55, 56, 57, 105, 106, 107, 108, 59, 255, - /* 520 */ 111, 112, 113, 90, 59, 262, 22, 98, 174, 12, - /* 530 */ 121, 208, 163, 220, 105, 106, 107, 163, 105, 106, - /* 540 */ 22, 96, 97, 110, 27, 238, 239, 240, 92, 93, - /* 550 */ 94, 95, 96, 97, 98, 99, 100, 101, 102, 42, - /* 560 */ 206, 207, 115, 59, 105, 106, 107, 163, 19, 59, - /* 570 */ 163, 106, 23, 219, 141, 142, 143, 59, 163, 205, - /* 580 */ 63, 59, 72, 22, 124, 59, 163, 270, 234, 129, - /* 590 */ 73, 163, 43, 44, 45, 46, 47, 48, 49, 50, - /* 600 */ 51, 52, 53, 54, 55, 56, 57, 184, 185, 105, - /* 610 */ 106, 107, 184, 185, 163, 105, 106, 107, 265, 266, - /* 620 */ 59, 198, 225, 105, 106, 107, 198, 105, 106, 107, - /* 630 */ 163, 105, 106, 107, 163, 184, 185, 46, 47, 48, - /* 640 */ 49, 92, 93, 94, 95, 96, 97, 98, 99, 100, - /* 650 */ 101, 102, 163, 163, 132, 184, 185, 163, 132, 163, - /* 660 */ 256, 19, 163, 163, 163, 23, 105, 106, 107, 198, - /* 670 */ 163, 220, 205, 184, 185, 163, 35, 81, 184, 185, - /* 680 */ 184, 185, 163, 184, 185, 43, 44, 45, 46, 47, - /* 690 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 700 */ 163, 110, 163, 184, 185, 109, 205, 66, 163, 59, - /* 710 */ 163, 21, 205, 16, 174, 74, 220, 198, 163, 220, - /* 720 */ 230, 184, 185, 127, 128, 180, 181, 180, 181, 163, - /* 730 */ 175, 242, 174, 233, 92, 93, 94, 95, 96, 97, - /* 740 */ 98, 99, 100, 101, 102, 233, 206, 207, 26, 163, - /* 750 */ 195, 207, 197, 26, 19, 105, 106, 107, 23, 219, - /* 760 */ 119, 260, 26, 219, 206, 207, 174, 19, 174, 230, - /* 770 */ 80, 174, 163, 174, 77, 163, 79, 219, 43, 44, - /* 780 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - /* 790 */ 55, 56, 57, 248, 12, 248, 184, 185, 206, 207, - /* 800 */ 206, 207, 112, 206, 207, 206, 207, 206, 207, 27, - /* 810 */ 163, 219, 123, 219, 125, 126, 219, 208, 219, 163, - /* 820 */ 219, 22, 23, 23, 42, 26, 26, 92, 93, 94, - /* 830 */ 95, 96, 97, 98, 99, 100, 101, 102, 163, 149, - /* 840 */ 184, 185, 163, 107, 163, 63, 149, 19, 163, 127, - /* 850 */ 128, 23, 22, 105, 24, 116, 117, 118, 131, 184, - /* 860 */ 185, 163, 163, 184, 185, 184, 185, 19, 132, 184, - /* 870 */ 185, 43, 44, 45, 46, 47, 48, 49, 50, 51, - /* 880 */ 52, 53, 54, 55, 56, 57, 146, 163, 148, 59, - /* 890 */ 91, 43, 44, 45, 46, 47, 48, 49, 50, 51, - /* 900 */ 52, 53, 54, 55, 56, 57, 208, 107, 184, 185, - /* 910 */ 7, 8, 9, 116, 117, 118, 163, 163, 163, 24, - /* 920 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - /* 930 */ 102, 29, 132, 163, 163, 33, 106, 184, 185, 163, - /* 940 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - /* 950 */ 102, 163, 163, 163, 59, 184, 185, 163, 22, 163, - /* 960 */ 184, 185, 177, 178, 163, 163, 163, 65, 163, 199, - /* 970 */ 163, 26, 184, 185, 184, 185, 163, 163, 184, 185, - /* 980 */ 184, 185, 163, 98, 163, 184, 185, 184, 185, 184, - /* 990 */ 185, 184, 185, 252, 205, 147, 163, 61, 184, 185, - /* 1000 */ 163, 106, 163, 184, 185, 163, 163, 205, 163, 124, - /* 1010 */ 163, 256, 163, 163, 129, 19, 163, 184, 185, 163, - /* 1020 */ 199, 184, 185, 184, 185, 23, 184, 185, 26, 184, - /* 1030 */ 185, 184, 185, 184, 185, 19, 163, 184, 185, 43, - /* 1040 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - /* 1050 */ 54, 55, 56, 57, 163, 163, 163, 184, 185, 43, - /* 1060 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - /* 1070 */ 54, 55, 56, 57, 16, 184, 185, 184, 185, 163, - /* 1080 */ 163, 22, 23, 138, 163, 19, 163, 231, 92, 93, - /* 1090 */ 94, 95, 96, 97, 98, 99, 100, 101, 102, 256, - /* 1100 */ 163, 184, 185, 163, 163, 184, 185, 163, 92, 93, - /* 1110 */ 94, 95, 96, 97, 98, 99, 100, 101, 102, 163, - /* 1120 */ 59, 184, 185, 163, 184, 185, 177, 178, 184, 185, - /* 1130 */ 163, 208, 163, 237, 163, 77, 163, 79, 163, 15, - /* 1140 */ 184, 185, 237, 147, 184, 185, 24, 231, 153, 154, - /* 1150 */ 91, 184, 185, 184, 185, 184, 185, 184, 185, 184, - /* 1160 */ 185, 22, 23, 19, 163, 127, 128, 106, 24, 273, - /* 1170 */ 271, 105, 231, 274, 263, 264, 223, 224, 273, 22, - /* 1180 */ 118, 24, 23, 19, 60, 26, 163, 43, 44, 45, - /* 1190 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - /* 1200 */ 56, 57, 140, 23, 22, 163, 26, 43, 44, 45, - /* 1210 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - /* 1220 */ 56, 57, 23, 211, 23, 26, 31, 26, 23, 22, - /* 1230 */ 91, 26, 231, 221, 39, 53, 92, 93, 94, 95, - /* 1240 */ 96, 97, 98, 99, 100, 101, 102, 23, 23, 163, - /* 1250 */ 26, 26, 130, 59, 109, 110, 92, 93, 94, 95, - /* 1260 */ 96, 97, 98, 99, 100, 101, 102, 23, 7, 8, - /* 1270 */ 26, 110, 23, 59, 23, 26, 19, 26, 141, 23, - /* 1280 */ 143, 120, 26, 141, 163, 143, 23, 23, 163, 26, - /* 1290 */ 26, 163, 163, 163, 163, 163, 19, 163, 163, 193, - /* 1300 */ 106, 44, 45, 46, 47, 48, 49, 50, 51, 52, - /* 1310 */ 53, 54, 55, 56, 57, 163, 193, 163, 163, 163, - /* 1320 */ 106, 163, 45, 46, 47, 48, 49, 50, 51, 52, - /* 1330 */ 53, 54, 55, 56, 57, 163, 163, 130, 222, 163, - /* 1340 */ 163, 203, 163, 19, 20, 251, 22, 163, 163, 92, - /* 1350 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - /* 1360 */ 36, 163, 209, 163, 261, 163, 163, 161, 222, 92, - /* 1370 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - /* 1380 */ 210, 213, 222, 59, 222, 222, 182, 213, 213, 196, - /* 1390 */ 257, 226, 226, 19, 20, 71, 22, 257, 188, 187, - /* 1400 */ 192, 212, 187, 187, 226, 81, 210, 166, 60, 261, - /* 1410 */ 36, 244, 130, 170, 90, 170, 38, 170, 139, 104, - /* 1420 */ 96, 97, 48, 236, 22, 235, 43, 103, 201, 105, - /* 1430 */ 106, 107, 138, 59, 110, 247, 213, 18, 204, 258, - /* 1440 */ 204, 258, 204, 204, 170, 71, 18, 169, 213, 236, - /* 1450 */ 213, 127, 128, 235, 201, 201, 82, 170, 169, 213, - /* 1460 */ 146, 87, 62, 254, 90, 141, 142, 143, 144, 145, - /* 1470 */ 96, 97, 253, 170, 169, 22, 170, 103, 169, 105, - /* 1480 */ 106, 107, 189, 170, 110, 169, 189, 186, 19, 20, - /* 1490 */ 104, 22, 194, 186, 186, 64, 115, 186, 194, 189, - /* 1500 */ 188, 102, 133, 186, 186, 36, 186, 104, 189, 19, - /* 1510 */ 20, 246, 22, 246, 189, 141, 142, 143, 144, 145, - /* 1520 */ 0, 1, 2, 228, 228, 5, 36, 227, 59, 227, - /* 1530 */ 10, 11, 12, 13, 14, 170, 84, 17, 134, 216, - /* 1540 */ 71, 272, 270, 22, 137, 217, 22, 216, 227, 59, - /* 1550 */ 30, 82, 32, 217, 228, 228, 87, 227, 170, 90, - /* 1560 */ 40, 71, 146, 241, 215, 96, 97, 214, 136, 135, - /* 1570 */ 213, 25, 103, 26, 105, 106, 107, 243, 173, 110, - /* 1580 */ 90, 172, 13, 6, 164, 164, 96, 97, 98, 162, - /* 1590 */ 70, 162, 162, 103, 176, 105, 106, 107, 78, 267, - /* 1600 */ 110, 81, 267, 264, 182, 182, 182, 182, 88, 176, - /* 1610 */ 141, 142, 143, 144, 145, 176, 190, 4, 182, 182, - /* 1620 */ 182, 19, 20, 182, 22, 190, 3, 22, 151, 15, - /* 1630 */ 89, 141, 142, 143, 144, 145, 16, 128, 36, 23, - /* 1640 */ 23, 139, 122, 24, 119, 131, 20, 127, 128, 133, - /* 1650 */ 16, 1, 140, 131, 119, 61, 139, 53, 37, 53, - /* 1660 */ 53, 59, 53, 119, 105, 34, 130, 1, 5, 22, - /* 1670 */ 150, 104, 149, 71, 26, 75, 68, 41, 68, 130, - /* 1680 */ 104, 24, 20, 19, 82, 120, 114, 22, 28, 87, - /* 1690 */ 22, 67, 90, 22, 67, 23, 22, 22, 96, 97, - /* 1700 */ 67, 23, 138, 22, 37, 103, 153, 105, 106, 107, - /* 1710 */ 1, 2, 110, 23, 5, 23, 23, 26, 22, 10, - /* 1720 */ 11, 12, 13, 14, 24, 23, 17, 22, 24, 130, - /* 1730 */ 23, 19, 20, 23, 22, 105, 22, 34, 85, 30, - /* 1740 */ 34, 32, 26, 141, 142, 143, 144, 145, 36, 40, - /* 1750 */ 132, 34, 75, 83, 23, 44, 24, 34, 23, 26, - /* 1760 */ 26, 19, 20, 23, 22, 26, 23, 23, 23, 23, - /* 1770 */ 22, 59, 11, 22, 22, 26, 23, 23, 36, 70, - /* 1780 */ 22, 22, 124, 71, 130, 130, 130, 78, 23, 130, - /* 1790 */ 81, 15, 1, 278, 278, 278, 278, 88, 278, 278, - /* 1800 */ 278, 59, 90, 278, 278, 278, 278, 278, 96, 97, - /* 1810 */ 278, 278, 278, 71, 278, 103, 278, 105, 106, 107, - /* 1820 */ 278, 278, 110, 278, 278, 278, 278, 278, 278, 278, - /* 1830 */ 278, 122, 90, 278, 278, 278, 127, 128, 96, 97, - /* 1840 */ 278, 278, 278, 278, 278, 103, 278, 105, 106, 107, - /* 1850 */ 278, 278, 110, 141, 142, 143, 144, 145, 278, 150, - /* 1860 */ 278, 278, 278, 5, 278, 278, 278, 278, 10, 11, - /* 1870 */ 12, 13, 14, 278, 278, 17, 278, 278, 278, 278, - /* 1880 */ 278, 278, 278, 141, 142, 143, 144, 145, 30, 278, - /* 1890 */ 32, 278, 278, 278, 278, 278, 278, 278, 40, 278, - /* 1900 */ 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - /* 1910 */ 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - /* 1920 */ 278, 278, 278, 278, 278, 278, 278, 278, 70, 278, - /* 1930 */ 278, 278, 278, 278, 278, 278, 78, 278, 278, 81, - /* 1940 */ 278, 278, 278, 278, 278, 278, 88, 278, 278, 278, - /* 1950 */ 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - /* 1960 */ 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - /* 1970 */ 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - /* 1980 */ 122, 278, 278, 278, 278, 127, 128, 278, 278, 278, - /* 1990 */ 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, - /* 2000 */ 278, 278, 278, 278, 278, 278, 278, 278, 150, 278, - /* 2010 */ 278, 278, 278, 278, 278, 278, 278, 278, 278, + /* 0 */ 184, 184, 259, 260, 261, 259, 260, 261, 176, 177, + /* 10 */ 178, 179, 180, 181, 184, 208, 212, 213, 186, 19, + /* 20 */ 188, 205, 206, 280, 205, 221, 22, 195, 24, 195, + /* 30 */ 208, 31, 195, 205, 29, 205, 206, 255, 33, 39, + /* 40 */ 200, 201, 202, 43, 44, 45, 46, 47, 48, 49, + /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 205, 227, + /* 60 */ 228, 227, 228, 59, 227, 228, 259, 260, 261, 252, + /* 70 */ 65, 241, 240, 184, 240, 223, 224, 240, 244, 245, + /* 80 */ 250, 259, 260, 261, 19, 253, 54, 55, 56, 57, + /* 90 */ 58, 184, 255, 184, 205, 206, 96, 97, 98, 99, + /* 100 */ 100, 101, 102, 103, 104, 105, 106, 46, 47, 48, + /* 110 */ 49, 46, 296, 297, 110, 283, 19, 96, 97, 98, + /* 120 */ 99, 100, 101, 102, 103, 104, 105, 106, 96, 97, + /* 130 */ 98, 99, 100, 101, 102, 103, 104, 105, 106, 94, + /* 140 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + /* 150 */ 53, 54, 55, 56, 57, 110, 106, 73, 251, 114, + /* 160 */ 73, 178, 179, 180, 181, 59, 184, 292, 81, 186, + /* 170 */ 295, 188, 218, 108, 19, 114, 184, 11, 195, 184, + /* 180 */ 83, 184, 85, 54, 55, 56, 57, 205, 206, 124, + /* 190 */ 145, 146, 147, 96, 97, 98, 99, 100, 101, 102, + /* 200 */ 103, 104, 105, 106, 120, 121, 122, 120, 102, 81, + /* 210 */ 227, 228, 220, 19, 16, 109, 110, 111, 131, 132, + /* 220 */ 26, 184, 184, 240, 229, 96, 97, 98, 99, 100, + /* 230 */ 101, 102, 103, 104, 105, 106, 253, 43, 44, 45, + /* 240 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + /* 250 */ 56, 57, 100, 101, 102, 103, 104, 105, 106, 131, + /* 260 */ 132, 106, 127, 69, 129, 130, 283, 112, 113, 114, + /* 270 */ 115, 116, 117, 118, 81, 77, 76, 79, 296, 124, + /* 280 */ 298, 203, 184, 19, 84, 59, 86, 121, 122, 89, + /* 290 */ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + /* 300 */ 106, 184, 35, 205, 206, 22, 113, 43, 44, 45, + /* 310 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + /* 320 */ 56, 57, 205, 206, 131, 132, 100, 101, 291, 292, + /* 330 */ 114, 67, 295, 66, 108, 109, 110, 111, 138, 113, + /* 340 */ 124, 74, 59, 179, 184, 181, 184, 121, 22, 271, + /* 350 */ 186, 19, 188, 184, 276, 59, 24, 184, 241, 195, + /* 360 */ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + /* 370 */ 106, 145, 59, 147, 184, 43, 44, 45, 46, 47, + /* 380 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + /* 390 */ 123, 227, 228, 110, 296, 297, 22, 23, 184, 102, + /* 400 */ 103, 104, 105, 106, 240, 109, 110, 111, 112, 195, + /* 410 */ 204, 115, 116, 117, 22, 184, 226, 253, 212, 205, + /* 420 */ 206, 125, 109, 110, 111, 22, 100, 101, 96, 97, + /* 430 */ 98, 99, 100, 101, 102, 103, 104, 105, 106, 184, + /* 440 */ 59, 227, 228, 121, 122, 59, 277, 283, 19, 289, + /* 450 */ 290, 59, 23, 76, 240, 241, 143, 76, 72, 189, + /* 460 */ 205, 206, 59, 86, 250, 84, 89, 86, 203, 95, + /* 470 */ 89, 281, 43, 44, 45, 46, 47, 48, 49, 50, + /* 480 */ 51, 52, 53, 54, 55, 56, 57, 227, 228, 184, + /* 490 */ 109, 110, 111, 12, 184, 109, 110, 111, 184, 184, + /* 500 */ 240, 109, 110, 111, 184, 195, 214, 59, 27, 184, + /* 510 */ 205, 206, 109, 110, 111, 205, 206, 184, 263, 138, + /* 520 */ 205, 206, 184, 42, 22, 96, 97, 98, 99, 100, + /* 530 */ 101, 102, 103, 104, 105, 106, 266, 227, 228, 59, + /* 540 */ 270, 276, 94, 66, 63, 19, 241, 22, 26, 23, + /* 550 */ 240, 241, 72, 59, 73, 250, 241, 109, 110, 82, + /* 560 */ 22, 59, 114, 223, 224, 250, 252, 59, 91, 43, + /* 570 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + /* 580 */ 54, 55, 56, 57, 59, 184, 26, 59, 268, 109, + /* 590 */ 110, 111, 184, 145, 146, 147, 112, 59, 203, 115, + /* 600 */ 116, 117, 277, 109, 110, 111, 205, 206, 195, 125, + /* 610 */ 277, 109, 110, 111, 100, 101, 139, 109, 110, 111, + /* 620 */ 219, 184, 96, 97, 98, 99, 100, 101, 102, 103, + /* 630 */ 104, 105, 106, 111, 109, 110, 111, 109, 110, 111, + /* 640 */ 227, 228, 19, 184, 136, 184, 23, 109, 110, 111, + /* 650 */ 200, 201, 202, 240, 259, 260, 261, 195, 136, 145, + /* 660 */ 184, 147, 184, 184, 136, 214, 43, 44, 45, 46, + /* 670 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 680 */ 57, 205, 206, 205, 206, 227, 228, 184, 229, 227, + /* 690 */ 228, 131, 132, 184, 59, 219, 184, 219, 240, 291, + /* 700 */ 292, 184, 240, 295, 105, 106, 22, 23, 205, 206, + /* 710 */ 26, 184, 251, 184, 205, 206, 184, 205, 206, 96, + /* 720 */ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + /* 730 */ 251, 219, 205, 206, 205, 206, 184, 205, 206, 19, + /* 740 */ 184, 16, 184, 23, 241, 110, 219, 21, 219, 184, + /* 750 */ 241, 219, 286, 287, 195, 184, 195, 205, 206, 201, + /* 760 */ 202, 205, 206, 43, 44, 45, 46, 47, 48, 49, + /* 770 */ 50, 51, 52, 53, 54, 55, 56, 57, 184, 95, + /* 780 */ 22, 23, 184, 26, 26, 220, 227, 228, 227, 228, + /* 790 */ 196, 184, 23, 241, 26, 26, 195, 241, 184, 240, + /* 800 */ 12, 240, 77, 26, 79, 195, 80, 290, 201, 202, + /* 810 */ 216, 184, 218, 195, 184, 27, 96, 97, 98, 99, + /* 820 */ 100, 101, 102, 103, 104, 105, 106, 269, 227, 228, + /* 830 */ 42, 184, 205, 206, 184, 184, 19, 227, 228, 192, + /* 840 */ 23, 240, 116, 196, 76, 227, 228, 120, 121, 122, + /* 850 */ 240, 63, 254, 95, 86, 205, 206, 89, 240, 184, + /* 860 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + /* 870 */ 53, 54, 55, 56, 57, 184, 269, 184, 153, 153, + /* 880 */ 111, 184, 7, 8, 9, 184, 138, 184, 184, 196, + /* 890 */ 184, 120, 121, 122, 184, 138, 205, 206, 184, 102, + /* 900 */ 184, 184, 205, 206, 156, 136, 205, 206, 205, 206, + /* 910 */ 198, 199, 135, 96, 97, 98, 99, 100, 101, 102, + /* 920 */ 103, 104, 105, 106, 184, 128, 184, 184, 184, 254, + /* 930 */ 133, 184, 237, 19, 239, 229, 226, 23, 292, 184, + /* 940 */ 226, 295, 226, 226, 184, 205, 206, 205, 206, 205, + /* 950 */ 206, 184, 292, 19, 184, 295, 252, 43, 44, 45, + /* 960 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + /* 970 */ 56, 57, 205, 206, 184, 205, 206, 43, 44, 45, + /* 980 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + /* 990 */ 56, 57, 157, 158, 26, 205, 206, 254, 26, 252, + /* 1000 */ 184, 15, 184, 184, 184, 292, 184, 252, 295, 24, + /* 1010 */ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + /* 1020 */ 106, 205, 206, 205, 206, 205, 206, 205, 206, 184, + /* 1030 */ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + /* 1040 */ 106, 184, 184, 184, 59, 184, 60, 184, 229, 184, + /* 1050 */ 205, 206, 184, 258, 184, 19, 184, 19, 184, 246, + /* 1060 */ 184, 258, 205, 206, 205, 206, 205, 206, 205, 206, + /* 1070 */ 205, 206, 184, 205, 206, 205, 206, 205, 206, 205, + /* 1080 */ 206, 205, 206, 292, 226, 151, 295, 184, 228, 294, + /* 1090 */ 184, 119, 184, 205, 206, 110, 150, 294, 152, 184, + /* 1100 */ 240, 184, 22, 23, 23, 19, 184, 26, 205, 206, + /* 1110 */ 142, 205, 206, 205, 206, 184, 198, 199, 131, 132, + /* 1120 */ 205, 206, 205, 206, 22, 19, 24, 205, 206, 43, + /* 1130 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + /* 1140 */ 54, 55, 56, 57, 184, 109, 184, 109, 184, 43, + /* 1150 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + /* 1160 */ 54, 55, 56, 57, 46, 205, 206, 205, 206, 205, + /* 1170 */ 206, 232, 184, 184, 184, 95, 184, 284, 285, 244, + /* 1180 */ 245, 242, 96, 97, 98, 99, 100, 101, 102, 103, + /* 1190 */ 104, 105, 106, 205, 206, 205, 206, 205, 206, 184, + /* 1200 */ 22, 184, 96, 97, 98, 99, 100, 101, 102, 103, + /* 1210 */ 104, 105, 106, 184, 24, 23, 184, 184, 26, 184, + /* 1220 */ 205, 206, 205, 206, 184, 31, 108, 128, 22, 122, + /* 1230 */ 184, 53, 133, 39, 205, 206, 22, 151, 205, 206, + /* 1240 */ 205, 206, 113, 114, 23, 205, 206, 26, 59, 23, + /* 1250 */ 23, 144, 26, 26, 184, 23, 23, 19, 26, 26, + /* 1260 */ 7, 8, 24, 23, 214, 23, 26, 61, 26, 59, + /* 1270 */ 23, 23, 23, 26, 26, 26, 145, 19, 147, 59, + /* 1280 */ 184, 43, 44, 45, 46, 47, 48, 49, 50, 51, + /* 1290 */ 52, 53, 54, 55, 56, 57, 145, 23, 147, 110, + /* 1300 */ 26, 43, 44, 45, 46, 47, 48, 49, 50, 51, + /* 1310 */ 52, 53, 54, 55, 56, 57, 23, 184, 184, 26, + /* 1320 */ 110, 184, 184, 184, 134, 184, 184, 184, 184, 184, + /* 1330 */ 110, 184, 184, 184, 96, 97, 98, 99, 100, 101, + /* 1340 */ 102, 103, 104, 105, 106, 184, 184, 184, 134, 300, + /* 1350 */ 184, 243, 184, 184, 96, 97, 98, 99, 100, 101, + /* 1360 */ 102, 103, 104, 105, 106, 184, 184, 184, 184, 184, + /* 1370 */ 224, 184, 282, 273, 19, 272, 203, 182, 243, 243, + /* 1380 */ 230, 209, 278, 243, 231, 208, 265, 278, 234, 234, + /* 1390 */ 234, 217, 213, 60, 19, 243, 208, 237, 233, 44, + /* 1400 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + /* 1410 */ 55, 56, 57, 208, 247, 187, 134, 247, 247, 38, + /* 1420 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + /* 1430 */ 55, 56, 57, 237, 231, 191, 191, 279, 279, 282, + /* 1440 */ 143, 191, 108, 268, 22, 19, 20, 256, 22, 43, + /* 1450 */ 257, 96, 97, 98, 99, 100, 101, 102, 103, 104, + /* 1460 */ 105, 106, 36, 222, 142, 234, 18, 191, 225, 18, + /* 1470 */ 190, 96, 97, 98, 99, 100, 101, 102, 103, 104, + /* 1480 */ 105, 106, 225, 191, 225, 59, 225, 257, 234, 234, + /* 1490 */ 256, 222, 222, 190, 234, 150, 62, 71, 275, 274, + /* 1500 */ 191, 19, 20, 190, 22, 22, 210, 81, 191, 190, + /* 1510 */ 210, 191, 108, 190, 207, 207, 64, 207, 36, 215, + /* 1520 */ 94, 210, 207, 209, 119, 207, 100, 101, 207, 106, + /* 1530 */ 48, 215, 207, 107, 210, 109, 110, 111, 267, 267, + /* 1540 */ 114, 59, 210, 249, 137, 108, 248, 191, 249, 248, + /* 1550 */ 88, 249, 141, 71, 248, 299, 138, 131, 132, 22, + /* 1560 */ 191, 249, 299, 237, 82, 238, 150, 262, 140, 87, + /* 1570 */ 139, 145, 146, 147, 148, 149, 94, 248, 238, 236, + /* 1580 */ 25, 235, 100, 101, 234, 194, 26, 193, 13, 107, + /* 1590 */ 6, 109, 110, 111, 264, 185, 114, 185, 183, 197, + /* 1600 */ 183, 203, 183, 203, 203, 197, 203, 211, 211, 4, + /* 1610 */ 197, 3, 203, 22, 155, 15, 288, 203, 93, 288, + /* 1620 */ 285, 23, 16, 203, 203, 23, 132, 145, 146, 147, + /* 1630 */ 148, 149, 0, 1, 2, 143, 123, 5, 24, 135, + /* 1640 */ 20, 16, 10, 11, 12, 13, 14, 137, 1, 17, + /* 1650 */ 135, 144, 19, 20, 123, 22, 61, 143, 37, 123, + /* 1660 */ 53, 109, 30, 53, 32, 53, 53, 134, 34, 36, + /* 1670 */ 1, 5, 40, 22, 108, 153, 26, 68, 75, 68, + /* 1680 */ 41, 134, 108, 24, 20, 124, 19, 118, 23, 67, + /* 1690 */ 22, 67, 59, 22, 22, 22, 22, 67, 28, 37, + /* 1700 */ 23, 142, 70, 22, 71, 23, 157, 23, 23, 26, + /* 1710 */ 78, 23, 22, 81, 23, 82, 24, 22, 24, 134, + /* 1720 */ 87, 23, 19, 20, 92, 22, 109, 94, 23, 22, + /* 1730 */ 34, 34, 136, 100, 101, 26, 34, 85, 34, 36, + /* 1740 */ 107, 83, 109, 110, 111, 34, 90, 114, 34, 23, + /* 1750 */ 75, 75, 44, 22, 24, 26, 34, 23, 126, 26, + /* 1760 */ 23, 23, 59, 131, 132, 23, 23, 26, 23, 22, + /* 1770 */ 11, 22, 22, 22, 71, 23, 23, 22, 145, 146, + /* 1780 */ 147, 148, 149, 26, 23, 82, 154, 134, 128, 134, + /* 1790 */ 87, 134, 15, 1, 301, 134, 301, 94, 301, 301, + /* 1800 */ 301, 301, 301, 100, 101, 301, 301, 301, 301, 301, + /* 1810 */ 107, 301, 109, 110, 111, 1, 2, 114, 301, 5, + /* 1820 */ 301, 301, 301, 301, 10, 11, 12, 13, 14, 301, + /* 1830 */ 301, 17, 301, 301, 301, 301, 19, 20, 301, 22, + /* 1840 */ 301, 301, 301, 301, 30, 301, 32, 301, 145, 146, + /* 1850 */ 147, 148, 149, 36, 40, 301, 301, 301, 301, 301, + /* 1860 */ 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, + /* 1870 */ 301, 301, 301, 301, 301, 301, 59, 301, 301, 301, + /* 1880 */ 301, 301, 301, 301, 70, 301, 301, 301, 71, 301, + /* 1890 */ 301, 301, 78, 301, 301, 81, 19, 20, 301, 22, + /* 1900 */ 301, 301, 301, 301, 301, 301, 92, 301, 301, 301, + /* 1910 */ 301, 94, 301, 36, 301, 301, 301, 100, 101, 102, + /* 1920 */ 301, 301, 301, 301, 107, 301, 109, 110, 111, 301, + /* 1930 */ 301, 114, 301, 301, 301, 301, 59, 301, 301, 301, + /* 1940 */ 126, 301, 301, 301, 301, 131, 132, 301, 71, 301, + /* 1950 */ 301, 301, 301, 301, 301, 301, 19, 20, 301, 22, + /* 1960 */ 301, 301, 145, 146, 147, 148, 149, 301, 154, 301, + /* 1970 */ 301, 94, 301, 36, 301, 301, 301, 100, 101, 301, + /* 1980 */ 301, 301, 301, 301, 107, 301, 109, 110, 111, 301, + /* 1990 */ 301, 114, 5, 301, 301, 301, 59, 10, 11, 12, + /* 2000 */ 13, 14, 301, 301, 17, 301, 301, 301, 71, 301, + /* 2010 */ 301, 301, 301, 301, 301, 301, 301, 30, 301, 32, + /* 2020 */ 301, 301, 145, 146, 147, 148, 149, 40, 301, 301, + /* 2030 */ 301, 94, 301, 301, 301, 301, 301, 100, 101, 301, + /* 2040 */ 301, 301, 301, 301, 107, 301, 109, 110, 111, 301, + /* 2050 */ 301, 114, 301, 301, 301, 301, 301, 70, 301, 301, + /* 2060 */ 301, 301, 301, 301, 301, 78, 301, 301, 81, 301, + /* 2070 */ 301, 301, 301, 301, 301, 301, 301, 301, 301, 92, + /* 2080 */ 301, 301, 145, 146, 147, 148, 149, 301, 301, 301, + /* 2090 */ 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, + /* 2100 */ 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, + /* 2110 */ 301, 301, 301, 126, 301, 301, 301, 301, 131, 132, + /* 2120 */ 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, + /* 2130 */ 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, + /* 2140 */ 301, 154, 301, 301, 301, 301, 301, 301, 301, 301, + /* 2150 */ 301, 301, 301, 301, 301, 301, 301, 301, 301, 301, + /* 2160 */ 301, 301, 301, 301, 301, 301, 301, 301, 301, }; -#define YY_SHIFT_COUNT (523) +#define YY_SHIFT_COUNT (540) #define YY_SHIFT_MIN (0) -#define YY_SHIFT_MAX (1858) +#define YY_SHIFT_MAX (1987) static const unsigned short int yy_shift_ofst[] = { - /* 0 */ 1709, 1520, 1858, 1324, 1324, 24, 1374, 1469, 1602, 1712, - /* 10 */ 1712, 1712, 271, 0, 0, 113, 1016, 1712, 1712, 1712, - /* 20 */ 1712, 1712, 1712, 1712, 1712, 1712, 1712, 12, 12, 409, - /* 30 */ 596, 24, 24, 24, 24, 24, 24, 93, 177, 270, - /* 40 */ 363, 456, 549, 642, 735, 828, 848, 996, 1144, 1016, - /* 50 */ 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, - /* 60 */ 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1164, 1016, 1257, - /* 70 */ 1277, 1277, 1490, 1712, 1712, 1712, 1712, 1712, 1712, 1712, - /* 80 */ 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, - /* 90 */ 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, - /* 100 */ 1712, 1712, 1712, 1712, 1712, 1742, 1712, 1712, 1712, 1712, - /* 110 */ 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 143, - /* 120 */ 162, 162, 162, 162, 162, 204, 151, 186, 650, 690, - /* 130 */ 327, 650, 261, 261, 650, 722, 722, 722, 722, 373, - /* 140 */ 33, 2, 2009, 2009, 330, 330, 330, 346, 289, 278, - /* 150 */ 289, 289, 517, 517, 459, 510, 15, 799, 650, 650, - /* 160 */ 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, - /* 170 */ 650, 650, 650, 650, 650, 650, 650, 650, 650, 650, - /* 180 */ 331, 365, 995, 995, 265, 365, 50, 1038, 2009, 2009, - /* 190 */ 2009, 433, 250, 250, 504, 314, 429, 518, 522, 526, - /* 200 */ 561, 650, 650, 650, 650, 650, 650, 650, 650, 650, - /* 210 */ 192, 650, 650, 650, 650, 650, 650, 650, 650, 650, - /* 220 */ 650, 650, 650, 641, 641, 641, 650, 650, 650, 650, - /* 230 */ 800, 650, 650, 650, 830, 650, 650, 782, 650, 650, - /* 240 */ 650, 650, 650, 650, 650, 650, 739, 902, 689, 895, - /* 250 */ 895, 895, 895, 736, 689, 689, 885, 445, 903, 1124, - /* 260 */ 945, 748, 748, 1066, 945, 945, 1066, 447, 1002, 293, - /* 270 */ 1195, 1195, 1195, 748, 740, 727, 460, 1157, 1348, 1282, - /* 280 */ 1282, 1378, 1378, 1282, 1279, 1315, 1402, 1383, 1294, 1419, - /* 290 */ 1419, 1419, 1419, 1282, 1428, 1294, 1294, 1315, 1402, 1383, - /* 300 */ 1383, 1294, 1282, 1428, 1314, 1400, 1282, 1428, 1453, 1282, - /* 310 */ 1428, 1282, 1428, 1453, 1386, 1386, 1386, 1431, 1453, 1386, - /* 320 */ 1381, 1386, 1431, 1386, 1386, 1453, 1399, 1399, 1453, 1369, - /* 330 */ 1403, 1369, 1403, 1369, 1403, 1369, 1403, 1282, 1404, 1452, - /* 340 */ 1521, 1407, 1404, 1524, 1282, 1416, 1407, 1432, 1434, 1294, - /* 350 */ 1546, 1547, 1569, 1569, 1577, 1577, 1577, 2009, 2009, 2009, - /* 360 */ 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, - /* 370 */ 2009, 2009, 2009, 591, 697, 1059, 1139, 1058, 797, 465, - /* 380 */ 1159, 1182, 1122, 1062, 1180, 936, 1199, 1201, 1205, 1224, - /* 390 */ 1225, 1244, 1061, 1145, 1261, 1161, 1194, 1249, 1251, 1256, - /* 400 */ 1137, 1142, 1263, 1264, 1214, 1207, 1613, 1623, 1605, 1477, - /* 410 */ 1614, 1541, 1620, 1616, 1617, 1509, 1502, 1525, 1619, 1514, - /* 420 */ 1626, 1516, 1634, 1650, 1522, 1512, 1535, 1594, 1621, 1517, - /* 430 */ 1604, 1606, 1607, 1609, 1544, 1559, 1631, 1536, 1666, 1663, - /* 440 */ 1647, 1567, 1523, 1608, 1648, 1610, 1600, 1636, 1549, 1576, - /* 450 */ 1657, 1662, 1664, 1565, 1572, 1665, 1624, 1668, 1671, 1672, - /* 460 */ 1674, 1627, 1660, 1675, 1633, 1667, 1678, 1564, 1681, 1553, - /* 470 */ 1690, 1692, 1691, 1693, 1696, 1700, 1702, 1705, 1704, 1599, - /* 480 */ 1707, 1710, 1630, 1703, 1714, 1618, 1716, 1706, 1716, 1717, - /* 490 */ 1653, 1677, 1670, 1711, 1731, 1732, 1733, 1734, 1723, 1735, - /* 500 */ 1716, 1740, 1743, 1744, 1745, 1739, 1746, 1748, 1761, 1751, - /* 510 */ 1752, 1753, 1754, 1758, 1759, 1749, 1658, 1654, 1655, 1656, - /* 520 */ 1659, 1765, 1776, 1791, + /* 0 */ 1814, 1632, 1987, 1426, 1426, 128, 1482, 1633, 1703, 1877, + /* 10 */ 1877, 1877, 87, 0, 0, 264, 1106, 1877, 1877, 1877, + /* 20 */ 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, + /* 30 */ 226, 226, 381, 381, 296, 193, 128, 128, 128, 128, + /* 40 */ 128, 128, 97, 194, 332, 429, 526, 623, 720, 817, + /* 50 */ 914, 934, 1086, 1238, 1106, 1106, 1106, 1106, 1106, 1106, + /* 60 */ 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + /* 70 */ 1106, 1106, 1258, 1106, 1355, 1375, 1375, 1817, 1877, 1877, + /* 80 */ 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, + /* 90 */ 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, + /* 100 */ 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, + /* 110 */ 1937, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, + /* 120 */ 1877, 1877, 1877, 1877, 32, 129, 129, 129, 129, 129, + /* 130 */ 21, 152, 297, 494, 726, 65, 494, 514, 514, 494, + /* 140 */ 560, 560, 560, 560, 322, 599, 50, 2142, 2142, 155, + /* 150 */ 155, 155, 313, 392, 386, 392, 392, 481, 481, 200, + /* 160 */ 480, 684, 758, 494, 494, 494, 494, 494, 494, 494, + /* 170 */ 494, 494, 494, 494, 494, 494, 494, 494, 494, 494, + /* 180 */ 494, 494, 494, 494, 768, 768, 494, 166, 377, 377, + /* 190 */ 635, 835, 835, 635, 748, 987, 2142, 2142, 2142, 448, + /* 200 */ 45, 45, 403, 484, 502, 106, 525, 508, 528, 538, + /* 210 */ 494, 494, 494, 494, 494, 494, 494, 494, 494, 84, + /* 220 */ 494, 494, 494, 494, 494, 494, 494, 494, 494, 494, + /* 230 */ 494, 494, 267, 267, 267, 494, 494, 494, 494, 769, + /* 240 */ 494, 494, 494, 4, 477, 494, 494, 788, 494, 494, + /* 250 */ 494, 494, 494, 494, 494, 494, 727, 5, 135, 985, + /* 260 */ 985, 985, 985, 522, 135, 135, 797, 326, 875, 986, + /* 270 */ 968, 1036, 1036, 1038, 968, 968, 1038, 972, 1081, 1118, + /* 280 */ 1194, 1194, 1194, 1036, 757, 757, 946, 777, 1099, 1102, + /* 290 */ 1333, 1282, 1282, 1381, 1381, 1282, 1297, 1334, 1422, 1406, + /* 300 */ 1322, 1448, 1448, 1448, 1448, 1282, 1451, 1322, 1322, 1334, + /* 310 */ 1422, 1406, 1406, 1322, 1282, 1451, 1345, 1434, 1282, 1451, + /* 320 */ 1483, 1282, 1451, 1282, 1451, 1483, 1404, 1404, 1404, 1452, + /* 330 */ 1483, 1404, 1405, 1404, 1452, 1404, 1404, 1483, 1423, 1423, + /* 340 */ 1483, 1407, 1437, 1407, 1437, 1407, 1437, 1407, 1437, 1282, + /* 350 */ 1462, 1462, 1411, 1418, 1537, 1282, 1416, 1411, 1428, 1431, + /* 360 */ 1322, 1555, 1560, 1575, 1575, 1584, 1584, 1584, 2142, 2142, + /* 370 */ 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, + /* 380 */ 2142, 2142, 2142, 2142, 61, 725, 374, 1080, 198, 771, + /* 390 */ 283, 1192, 1178, 1190, 1107, 1221, 1206, 1226, 1227, 1232, + /* 400 */ 1233, 1240, 1242, 1189, 1129, 1253, 216, 1210, 1247, 1248, + /* 410 */ 1249, 1131, 1151, 1274, 1293, 1220, 1214, 1605, 1608, 1591, + /* 420 */ 1459, 1600, 1525, 1606, 1598, 1602, 1494, 1492, 1513, 1614, + /* 430 */ 1504, 1620, 1510, 1625, 1647, 1515, 1507, 1531, 1595, 1621, + /* 440 */ 1514, 1607, 1610, 1612, 1613, 1536, 1552, 1634, 1533, 1669, + /* 450 */ 1666, 1651, 1566, 1522, 1609, 1650, 1611, 1603, 1639, 1547, + /* 460 */ 1574, 1659, 1664, 1667, 1561, 1569, 1668, 1622, 1671, 1672, + /* 470 */ 1665, 1673, 1624, 1670, 1674, 1630, 1662, 1677, 1559, 1681, + /* 480 */ 1682, 1549, 1684, 1685, 1683, 1688, 1690, 1692, 1691, 1695, + /* 490 */ 1694, 1585, 1698, 1705, 1617, 1696, 1707, 1596, 1709, 1697, + /* 500 */ 1702, 1704, 1711, 1652, 1675, 1658, 1708, 1676, 1656, 1714, + /* 510 */ 1726, 1731, 1730, 1729, 1733, 1722, 1734, 1709, 1737, 1738, + /* 520 */ 1742, 1743, 1741, 1745, 1747, 1759, 1749, 1750, 1752, 1753, + /* 530 */ 1751, 1755, 1757, 1660, 1653, 1655, 1657, 1661, 1761, 1777, + /* 540 */ 1792, }; -#define YY_REDUCE_COUNT (372) -#define YY_REDUCE_MIN (-235) -#define YY_REDUCE_MAX (1441) +#define YY_REDUCE_COUNT (383) +#define YY_REDUCE_MIN (-257) +#define YY_REDUCE_MAX (1421) static const short yy_reduce_ofst[] = { - /* 0 */ -147, 171, 263, -96, 169, -144, -162, -149, -102, -156, - /* 10 */ -98, 216, 354, -170, -57, -235, 307, 149, 423, 428, - /* 20 */ 471, 313, 451, 519, 489, 496, 499, 545, 547, 555, - /* 30 */ -116, 540, 558, 592, 594, 597, 599, -206, -206, -206, - /* 40 */ -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, - /* 50 */ -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, - /* 60 */ -206, -206, -206, -206, -206, -206, -206, -206, -206, -206, - /* 70 */ -206, -206, 196, 309, 494, 537, 612, 656, 675, 679, - /* 80 */ 681, 685, 724, 753, 771, 776, 788, 790, 794, 796, - /* 90 */ 801, 803, 805, 807, 814, 819, 833, 837, 839, 842, - /* 100 */ 845, 847, 849, 853, 873, 891, 893, 917, 921, 937, - /* 110 */ 940, 944, 956, 960, 967, 969, 971, 973, 975, -206, - /* 120 */ -206, -206, -206, -206, -206, -206, -206, -206, 501, -168, - /* 130 */ 90, -97, 87, 112, 303, 277, 601, 277, 601, 179, - /* 140 */ -206, -206, -206, -206, -107, -107, -107, -43, -56, 323, - /* 150 */ 500, 512, -187, -177, 317, 609, 353, 353, 120, 144, - /* 160 */ 490, 539, 698, 374, 467, 507, 789, 404, -157, 755, - /* 170 */ 856, 916, 843, 941, 802, 770, 923, 821, 1001, -142, - /* 180 */ 264, 785, 896, 905, 899, 949, -176, 544, 911, 953, - /* 190 */ 1012, -182, -59, -30, 16, -22, 117, 172, 291, 369, - /* 200 */ 407, 415, 566, 586, 647, 699, 754, 813, 850, 892, - /* 210 */ 121, 1023, 1042, 1086, 1121, 1125, 1128, 1129, 1130, 1131, - /* 220 */ 1132, 1134, 1135, 284, 1106, 1123, 1152, 1154, 1155, 1156, - /* 230 */ 397, 1158, 1172, 1173, 1116, 1176, 1177, 1138, 1179, 117, - /* 240 */ 1184, 1185, 1198, 1200, 1202, 1203, 741, 1094, 1153, 1146, - /* 250 */ 1160, 1162, 1163, 397, 1153, 1153, 1170, 1204, 1206, 1103, - /* 260 */ 1168, 1165, 1166, 1133, 1174, 1175, 1140, 1210, 1193, 1208, - /* 270 */ 1212, 1215, 1216, 1178, 1167, 1189, 1196, 1241, 1148, 1243, - /* 280 */ 1245, 1181, 1183, 1247, 1188, 1187, 1190, 1227, 1223, 1234, - /* 290 */ 1236, 1238, 1239, 1274, 1278, 1235, 1237, 1213, 1218, 1253, - /* 300 */ 1254, 1246, 1287, 1289, 1209, 1219, 1303, 1305, 1293, 1306, - /* 310 */ 1309, 1313, 1316, 1297, 1301, 1307, 1308, 1298, 1310, 1311, - /* 320 */ 1312, 1317, 1304, 1318, 1320, 1319, 1265, 1267, 1325, 1295, - /* 330 */ 1300, 1296, 1302, 1326, 1321, 1327, 1330, 1365, 1323, 1269, - /* 340 */ 1272, 1328, 1331, 1322, 1388, 1334, 1336, 1349, 1353, 1357, - /* 350 */ 1405, 1409, 1420, 1421, 1427, 1429, 1430, 1332, 1335, 1339, - /* 360 */ 1418, 1422, 1423, 1424, 1425, 1433, 1426, 1435, 1436, 1437, - /* 370 */ 1438, 1441, 1439, + /* 0 */ -168, -17, 164, 214, 310, -166, -184, -18, 98, -170, + /* 10 */ 305, 315, -163, -193, -178, -257, 395, 401, 476, 478, + /* 20 */ 512, 117, 527, 529, 503, 509, 532, 255, 552, 556, + /* 30 */ 558, 607, 37, 408, 594, 413, 462, 559, 561, 601, + /* 40 */ 610, 618, -254, -254, -254, -254, -254, -254, -254, -254, + /* 50 */ -254, -254, -254, -254, -254, -254, -254, -254, -254, -254, + /* 60 */ -254, -254, -254, -254, -254, -254, -254, -254, -254, -254, + /* 70 */ -254, -254, -254, -254, -254, -254, -254, -111, 627, 650, + /* 80 */ 691, 697, 701, 703, 740, 742, 744, 767, 770, 790, + /* 90 */ 816, 818, 820, 822, 845, 857, 859, 861, 863, 865, + /* 100 */ 868, 870, 872, 874, 876, 888, 903, 906, 908, 915, + /* 110 */ 917, 922, 960, 962, 964, 988, 990, 992, 1015, 1017, + /* 120 */ 1029, 1033, 1035, 1040, -254, -254, -254, -254, -254, -254, + /* 130 */ -254, -254, -254, 190, 270, -196, 160, -160, 450, 647, + /* 140 */ 260, 458, 260, 458, 78, -254, -254, -254, -254, 206, + /* 150 */ 206, 206, 320, 598, -5, 675, 743, -148, 340, -125, + /* 160 */ 459, 466, 466, 693, -93, 461, 479, 706, 710, 714, + /* 170 */ 716, 717, 169, -183, 325, 314, 704, 333, 747, 858, + /* 180 */ -8, 819, 565, 755, 646, 660, 517, 265, 713, 791, + /* 190 */ 712, 795, 803, 918, 695, 860, 893, 935, 939, -181, + /* 200 */ -172, -147, -91, -46, -3, 162, 173, 231, 338, 437, + /* 210 */ 571, 614, 630, 651, 760, 931, 989, 1032, 1046, -218, + /* 220 */ 38, 1070, 1096, 1133, 1134, 1137, 1138, 1139, 1141, 1142, + /* 230 */ 1143, 1144, 292, 451, 1050, 1145, 1147, 1148, 1149, 813, + /* 240 */ 1161, 1162, 1163, 1108, 1049, 1166, 1168, 1146, 1169, 162, + /* 250 */ 1181, 1182, 1183, 1184, 1185, 1187, 1100, 1103, 1150, 1135, + /* 260 */ 1136, 1140, 1152, 813, 1150, 1150, 1153, 1173, 1195, 1090, + /* 270 */ 1154, 1167, 1170, 1104, 1155, 1156, 1109, 1172, 1174, 1179, + /* 280 */ 1177, 1188, 1205, 1171, 1160, 1196, 1121, 1165, 1203, 1228, + /* 290 */ 1157, 1244, 1245, 1158, 1159, 1250, 1175, 1193, 1191, 1241, + /* 300 */ 1231, 1243, 1257, 1259, 1261, 1276, 1280, 1254, 1255, 1230, + /* 310 */ 1234, 1269, 1270, 1260, 1292, 1303, 1223, 1225, 1309, 1313, + /* 320 */ 1296, 1317, 1319, 1320, 1323, 1300, 1307, 1308, 1310, 1304, + /* 330 */ 1311, 1315, 1314, 1318, 1316, 1321, 1325, 1324, 1271, 1272, + /* 340 */ 1332, 1294, 1298, 1299, 1301, 1302, 1306, 1312, 1329, 1356, + /* 350 */ 1256, 1263, 1327, 1326, 1305, 1369, 1330, 1340, 1343, 1346, + /* 360 */ 1350, 1391, 1394, 1410, 1412, 1415, 1417, 1419, 1328, 1331, + /* 370 */ 1335, 1402, 1398, 1400, 1401, 1403, 1408, 1396, 1397, 1409, + /* 380 */ 1414, 1420, 1421, 1413, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1500, 1500, 1500, 1346, 1129, 1235, 1129, 1129, 1129, 1346, - /* 10 */ 1346, 1346, 1129, 1265, 1265, 1399, 1160, 1129, 1129, 1129, - /* 20 */ 1129, 1129, 1129, 1129, 1345, 1129, 1129, 1129, 1129, 1129, - /* 30 */ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1271, 1129, - /* 40 */ 1129, 1129, 1129, 1129, 1347, 1348, 1129, 1129, 1129, 1398, - /* 50 */ 1400, 1363, 1281, 1280, 1279, 1278, 1381, 1252, 1276, 1269, - /* 60 */ 1273, 1341, 1342, 1340, 1344, 1348, 1347, 1129, 1272, 1312, - /* 70 */ 1326, 1311, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 80 */ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 90 */ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 100 */ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 110 */ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1320, - /* 120 */ 1325, 1331, 1324, 1321, 1314, 1313, 1315, 1316, 1129, 1150, - /* 130 */ 1199, 1129, 1129, 1129, 1129, 1417, 1416, 1129, 1129, 1160, - /* 140 */ 1317, 1318, 1328, 1327, 1406, 1456, 1455, 1364, 1129, 1129, - /* 150 */ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 160 */ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 170 */ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 180 */ 1160, 1156, 1306, 1305, 1426, 1156, 1259, 1129, 1412, 1235, - /* 190 */ 1226, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 200 */ 1129, 1129, 1129, 1129, 1403, 1401, 1129, 1129, 1129, 1129, - /* 210 */ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 220 */ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 230 */ 1129, 1129, 1129, 1129, 1231, 1129, 1129, 1129, 1129, 1129, - /* 240 */ 1129, 1129, 1129, 1129, 1129, 1450, 1129, 1376, 1213, 1231, - /* 250 */ 1231, 1231, 1231, 1233, 1214, 1212, 1225, 1160, 1136, 1492, - /* 260 */ 1275, 1254, 1254, 1489, 1275, 1275, 1489, 1174, 1470, 1171, - /* 270 */ 1265, 1265, 1265, 1254, 1343, 1232, 1225, 1129, 1492, 1240, - /* 280 */ 1240, 1491, 1491, 1240, 1364, 1284, 1290, 1202, 1275, 1208, - /* 290 */ 1208, 1208, 1208, 1240, 1147, 1275, 1275, 1284, 1290, 1202, - /* 300 */ 1202, 1275, 1240, 1147, 1380, 1486, 1240, 1147, 1354, 1240, - /* 310 */ 1147, 1240, 1147, 1354, 1200, 1200, 1200, 1189, 1354, 1200, - /* 320 */ 1174, 1200, 1189, 1200, 1200, 1354, 1358, 1358, 1354, 1258, - /* 330 */ 1253, 1258, 1253, 1258, 1253, 1258, 1253, 1240, 1259, 1425, - /* 340 */ 1129, 1270, 1259, 1349, 1240, 1129, 1270, 1268, 1266, 1275, - /* 350 */ 1153, 1192, 1453, 1453, 1449, 1449, 1449, 1497, 1497, 1412, - /* 360 */ 1465, 1160, 1160, 1160, 1160, 1465, 1176, 1176, 1160, 1160, - /* 370 */ 1160, 1160, 1465, 1129, 1129, 1129, 1129, 1129, 1129, 1460, - /* 380 */ 1129, 1365, 1244, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 390 */ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 400 */ 1129, 1129, 1129, 1129, 1129, 1295, 1129, 1132, 1409, 1129, - /* 410 */ 1129, 1407, 1129, 1129, 1129, 1129, 1129, 1129, 1245, 1129, - /* 420 */ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 430 */ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1488, 1129, 1129, - /* 440 */ 1129, 1129, 1129, 1129, 1379, 1378, 1129, 1129, 1242, 1129, - /* 450 */ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 460 */ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 470 */ 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 480 */ 1129, 1129, 1129, 1129, 1129, 1129, 1267, 1129, 1424, 1129, - /* 490 */ 1129, 1129, 1129, 1129, 1129, 1129, 1438, 1260, 1129, 1129, - /* 500 */ 1479, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, 1129, - /* 510 */ 1129, 1129, 1129, 1129, 1129, 1474, 1216, 1297, 1129, 1296, - /* 520 */ 1300, 1129, 1141, 1129, + /* 0 */ 1536, 1536, 1536, 1376, 1159, 1265, 1159, 1159, 1159, 1376, + /* 10 */ 1376, 1376, 1159, 1295, 1295, 1429, 1190, 1159, 1159, 1159, + /* 20 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1375, 1159, 1159, + /* 30 */ 1159, 1159, 1459, 1459, 1159, 1159, 1159, 1159, 1159, 1159, + /* 40 */ 1159, 1159, 1159, 1301, 1159, 1159, 1159, 1159, 1159, 1377, + /* 50 */ 1378, 1159, 1159, 1159, 1428, 1430, 1393, 1311, 1310, 1309, + /* 60 */ 1308, 1411, 1282, 1306, 1299, 1303, 1371, 1372, 1370, 1374, + /* 70 */ 1378, 1377, 1159, 1302, 1342, 1356, 1341, 1159, 1159, 1159, + /* 80 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + /* 90 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + /* 100 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + /* 110 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + /* 120 */ 1159, 1159, 1159, 1159, 1350, 1355, 1361, 1354, 1351, 1344, + /* 130 */ 1343, 1345, 1346, 1159, 1180, 1229, 1159, 1159, 1159, 1159, + /* 140 */ 1447, 1446, 1159, 1159, 1190, 1347, 1348, 1358, 1357, 1436, + /* 150 */ 1492, 1491, 1394, 1159, 1159, 1159, 1159, 1159, 1159, 1459, + /* 160 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + /* 170 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + /* 180 */ 1159, 1159, 1159, 1159, 1459, 1459, 1159, 1190, 1459, 1459, + /* 190 */ 1186, 1336, 1335, 1186, 1289, 1159, 1442, 1265, 1256, 1159, + /* 200 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + /* 210 */ 1159, 1159, 1159, 1433, 1431, 1159, 1159, 1159, 1159, 1159, + /* 220 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + /* 230 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + /* 240 */ 1159, 1159, 1159, 1261, 1159, 1159, 1159, 1159, 1159, 1159, + /* 250 */ 1159, 1159, 1159, 1159, 1159, 1486, 1159, 1406, 1243, 1261, + /* 260 */ 1261, 1261, 1261, 1263, 1244, 1242, 1255, 1190, 1166, 1528, + /* 270 */ 1305, 1284, 1284, 1525, 1305, 1305, 1525, 1204, 1506, 1201, + /* 280 */ 1295, 1295, 1295, 1284, 1289, 1289, 1373, 1262, 1255, 1159, + /* 290 */ 1528, 1270, 1270, 1527, 1527, 1270, 1394, 1314, 1320, 1232, + /* 300 */ 1305, 1238, 1238, 1238, 1238, 1270, 1177, 1305, 1305, 1314, + /* 310 */ 1320, 1232, 1232, 1305, 1270, 1177, 1410, 1522, 1270, 1177, + /* 320 */ 1384, 1270, 1177, 1270, 1177, 1384, 1230, 1230, 1230, 1219, + /* 330 */ 1384, 1230, 1204, 1230, 1219, 1230, 1230, 1384, 1388, 1388, + /* 340 */ 1384, 1288, 1283, 1288, 1283, 1288, 1283, 1288, 1283, 1270, + /* 350 */ 1469, 1469, 1300, 1289, 1379, 1270, 1159, 1300, 1298, 1296, + /* 360 */ 1305, 1183, 1222, 1489, 1489, 1485, 1485, 1485, 1533, 1533, + /* 370 */ 1442, 1501, 1190, 1190, 1190, 1190, 1501, 1206, 1206, 1190, + /* 380 */ 1190, 1190, 1190, 1501, 1159, 1159, 1159, 1159, 1159, 1159, + /* 390 */ 1496, 1159, 1395, 1274, 1159, 1159, 1159, 1159, 1159, 1159, + /* 400 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + /* 410 */ 1159, 1159, 1159, 1159, 1159, 1159, 1325, 1159, 1162, 1439, + /* 420 */ 1159, 1159, 1437, 1159, 1159, 1159, 1159, 1159, 1159, 1275, + /* 430 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + /* 440 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1524, 1159, + /* 450 */ 1159, 1159, 1159, 1159, 1159, 1409, 1408, 1159, 1159, 1272, + /* 460 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + /* 470 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + /* 480 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + /* 490 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1297, 1159, + /* 500 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + /* 510 */ 1159, 1159, 1159, 1474, 1290, 1159, 1159, 1515, 1159, 1159, + /* 520 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + /* 530 */ 1159, 1159, 1510, 1246, 1327, 1159, 1326, 1330, 1159, 1171, + /* 540 */ 1159, }; /********** End of lemon-generated parsing tables *****************************/ @@ -148334,6 +149183,10 @@ static const YYCODETYPE yyFallback[] = { 59, /* PRECEDING => ID */ 59, /* RANGE => ID */ 59, /* UNBOUNDED => ID */ + 59, /* EXCLUDE => ID */ + 59, /* GROUPS => ID */ + 59, /* OTHERS => ID */ + 59, /* TIES => ID */ 59, /* REINDEX => ID */ 59, /* RENAME => ID */ 59, /* CTIME_KW => ID */ @@ -148512,196 +149365,219 @@ static const char *const yyTokenName[] = { /* 85 */ "PRECEDING", /* 86 */ "RANGE", /* 87 */ "UNBOUNDED", - /* 88 */ "REINDEX", - /* 89 */ "RENAME", - /* 90 */ "CTIME_KW", - /* 91 */ "ANY", - /* 92 */ "BITAND", - /* 93 */ "BITOR", - /* 94 */ "LSHIFT", - /* 95 */ "RSHIFT", - /* 96 */ "PLUS", - /* 97 */ "MINUS", - /* 98 */ "STAR", - /* 99 */ "SLASH", - /* 100 */ "REM", - /* 101 */ "CONCAT", - /* 102 */ "COLLATE", - /* 103 */ "BITNOT", - /* 104 */ "ON", - /* 105 */ "INDEXED", - /* 106 */ "STRING", - /* 107 */ "JOIN_KW", - /* 108 */ "CONSTRAINT", - /* 109 */ "DEFAULT", - /* 110 */ "NULL", - /* 111 */ "PRIMARY", - /* 112 */ "UNIQUE", - /* 113 */ "CHECK", - /* 114 */ "REFERENCES", - /* 115 */ "AUTOINCR", - /* 116 */ "INSERT", - /* 117 */ "DELETE", - /* 118 */ "UPDATE", - /* 119 */ "SET", - /* 120 */ "DEFERRABLE", - /* 121 */ "FOREIGN", - /* 122 */ "DROP", - /* 123 */ "UNION", - /* 124 */ "ALL", - /* 125 */ "EXCEPT", - /* 126 */ "INTERSECT", - /* 127 */ "SELECT", - /* 128 */ "VALUES", - /* 129 */ "DISTINCT", - /* 130 */ "DOT", - /* 131 */ "FROM", - /* 132 */ "JOIN", - /* 133 */ "USING", - /* 134 */ "ORDER", - /* 135 */ "GROUP", - /* 136 */ "HAVING", - /* 137 */ "LIMIT", - /* 138 */ "WHERE", - /* 139 */ "INTO", - /* 140 */ "NOTHING", - /* 141 */ "FLOAT", - /* 142 */ "BLOB", - /* 143 */ "INTEGER", - /* 144 */ "VARIABLE", - /* 145 */ "CASE", - /* 146 */ "WHEN", - /* 147 */ "THEN", - /* 148 */ "ELSE", - /* 149 */ "INDEX", - /* 150 */ "ALTER", - /* 151 */ "ADD", - /* 152 */ "WINDOW", - /* 153 */ "OVER", - /* 154 */ "FILTER", - /* 155 */ "input", - /* 156 */ "cmdlist", - /* 157 */ "ecmd", - /* 158 */ "cmdx", - /* 159 */ "explain", - /* 160 */ "cmd", - /* 161 */ "transtype", - /* 162 */ "trans_opt", - /* 163 */ "nm", - /* 164 */ "savepoint_opt", - /* 165 */ "create_table", - /* 166 */ "create_table_args", - /* 167 */ "createkw", - /* 168 */ "temp", - /* 169 */ "ifnotexists", - /* 170 */ "dbnm", - /* 171 */ "columnlist", - /* 172 */ "conslist_opt", - /* 173 */ "table_options", - /* 174 */ "select", - /* 175 */ "columnname", - /* 176 */ "carglist", - /* 177 */ "typetoken", - /* 178 */ "typename", - /* 179 */ "signed", - /* 180 */ "plus_num", - /* 181 */ "minus_num", - /* 182 */ "scanpt", - /* 183 */ "ccons", - /* 184 */ "term", - /* 185 */ "expr", - /* 186 */ "onconf", - /* 187 */ "sortorder", - /* 188 */ "autoinc", - /* 189 */ "eidlist_opt", - /* 190 */ "refargs", - /* 191 */ "defer_subclause", - /* 192 */ "refarg", - /* 193 */ "refact", - /* 194 */ "init_deferred_pred_opt", - /* 195 */ "conslist", - /* 196 */ "tconscomma", - /* 197 */ "tcons", - /* 198 */ "sortlist", - /* 199 */ "eidlist", - /* 200 */ "defer_subclause_opt", - /* 201 */ "orconf", - /* 202 */ "resolvetype", - /* 203 */ "raisetype", - /* 204 */ "ifexists", - /* 205 */ "fullname", - /* 206 */ "selectnowith", - /* 207 */ "oneselect", - /* 208 */ "wqlist", - /* 209 */ "multiselect_op", - /* 210 */ "distinct", - /* 211 */ "selcollist", - /* 212 */ "from", - /* 213 */ "where_opt", - /* 214 */ "groupby_opt", - /* 215 */ "having_opt", - /* 216 */ "orderby_opt", - /* 217 */ "limit_opt", - /* 218 */ "window_clause", - /* 219 */ "values", - /* 220 */ "nexprlist", - /* 221 */ "sclp", - /* 222 */ "as", - /* 223 */ "seltablist", - /* 224 */ "stl_prefix", - /* 225 */ "joinop", - /* 226 */ "indexed_opt", - /* 227 */ "on_opt", - /* 228 */ "using_opt", - /* 229 */ "exprlist", - /* 230 */ "xfullname", - /* 231 */ "idlist", - /* 232 */ "with", - /* 233 */ "setlist", - /* 234 */ "insert_cmd", - /* 235 */ "idlist_opt", - /* 236 */ "upsert", - /* 237 */ "over_clause", - /* 238 */ "likeop", - /* 239 */ "between_op", - /* 240 */ "in_op", - /* 241 */ "paren_exprlist", - /* 242 */ "case_operand", - /* 243 */ "case_exprlist", - /* 244 */ "case_else", - /* 245 */ "uniqueflag", - /* 246 */ "collate", - /* 247 */ "vinto", - /* 248 */ "nmnum", - /* 249 */ "trigger_decl", - /* 250 */ "trigger_cmd_list", - /* 251 */ "trigger_time", - /* 252 */ "trigger_event", - /* 253 */ "foreach_clause", - /* 254 */ "when_clause", - /* 255 */ "trigger_cmd", - /* 256 */ "trnm", - /* 257 */ "tridxby", - /* 258 */ "database_kw_opt", - /* 259 */ "key_opt", - /* 260 */ "add_column_fullname", - /* 261 */ "kwcolumn_opt", - /* 262 */ "create_vtab", - /* 263 */ "vtabarglist", - /* 264 */ "vtabarg", - /* 265 */ "vtabargtoken", - /* 266 */ "lp", - /* 267 */ "anylist", - /* 268 */ "windowdefn_list", - /* 269 */ "windowdefn", - /* 270 */ "window", - /* 271 */ "frame_opt", - /* 272 */ "part_opt", - /* 273 */ "filter_opt", - /* 274 */ "range_or_rows", - /* 275 */ "frame_bound", - /* 276 */ "frame_bound_s", - /* 277 */ "frame_bound_e", + /* 88 */ "EXCLUDE", + /* 89 */ "GROUPS", + /* 90 */ "OTHERS", + /* 91 */ "TIES", + /* 92 */ "REINDEX", + /* 93 */ "RENAME", + /* 94 */ "CTIME_KW", + /* 95 */ "ANY", + /* 96 */ "BITAND", + /* 97 */ "BITOR", + /* 98 */ "LSHIFT", + /* 99 */ "RSHIFT", + /* 100 */ "PLUS", + /* 101 */ "MINUS", + /* 102 */ "STAR", + /* 103 */ "SLASH", + /* 104 */ "REM", + /* 105 */ "CONCAT", + /* 106 */ "COLLATE", + /* 107 */ "BITNOT", + /* 108 */ "ON", + /* 109 */ "INDEXED", + /* 110 */ "STRING", + /* 111 */ "JOIN_KW", + /* 112 */ "CONSTRAINT", + /* 113 */ "DEFAULT", + /* 114 */ "NULL", + /* 115 */ "PRIMARY", + /* 116 */ "UNIQUE", + /* 117 */ "CHECK", + /* 118 */ "REFERENCES", + /* 119 */ "AUTOINCR", + /* 120 */ "INSERT", + /* 121 */ "DELETE", + /* 122 */ "UPDATE", + /* 123 */ "SET", + /* 124 */ "DEFERRABLE", + /* 125 */ "FOREIGN", + /* 126 */ "DROP", + /* 127 */ "UNION", + /* 128 */ "ALL", + /* 129 */ "EXCEPT", + /* 130 */ "INTERSECT", + /* 131 */ "SELECT", + /* 132 */ "VALUES", + /* 133 */ "DISTINCT", + /* 134 */ "DOT", + /* 135 */ "FROM", + /* 136 */ "JOIN", + /* 137 */ "USING", + /* 138 */ "ORDER", + /* 139 */ "GROUP", + /* 140 */ "HAVING", + /* 141 */ "LIMIT", + /* 142 */ "WHERE", + /* 143 */ "INTO", + /* 144 */ "NOTHING", + /* 145 */ "FLOAT", + /* 146 */ "BLOB", + /* 147 */ "INTEGER", + /* 148 */ "VARIABLE", + /* 149 */ "CASE", + /* 150 */ "WHEN", + /* 151 */ "THEN", + /* 152 */ "ELSE", + /* 153 */ "INDEX", + /* 154 */ "ALTER", + /* 155 */ "ADD", + /* 156 */ "WINDOW", + /* 157 */ "OVER", + /* 158 */ "FILTER", + /* 159 */ "TRUEFALSE", + /* 160 */ "ISNOT", + /* 161 */ "FUNCTION", + /* 162 */ "COLUMN", + /* 163 */ "AGG_FUNCTION", + /* 164 */ "AGG_COLUMN", + /* 165 */ "UMINUS", + /* 166 */ "UPLUS", + /* 167 */ "TRUTH", + /* 168 */ "REGISTER", + /* 169 */ "VECTOR", + /* 170 */ "SELECT_COLUMN", + /* 171 */ "IF_NULL_ROW", + /* 172 */ "ASTERISK", + /* 173 */ "SPAN", + /* 174 */ "SPACE", + /* 175 */ "ILLEGAL", + /* 176 */ "input", + /* 177 */ "cmdlist", + /* 178 */ "ecmd", + /* 179 */ "cmdx", + /* 180 */ "explain", + /* 181 */ "cmd", + /* 182 */ "transtype", + /* 183 */ "trans_opt", + /* 184 */ "nm", + /* 185 */ "savepoint_opt", + /* 186 */ "create_table", + /* 187 */ "create_table_args", + /* 188 */ "createkw", + /* 189 */ "temp", + /* 190 */ "ifnotexists", + /* 191 */ "dbnm", + /* 192 */ "columnlist", + /* 193 */ "conslist_opt", + /* 194 */ "table_options", + /* 195 */ "select", + /* 196 */ "columnname", + /* 197 */ "carglist", + /* 198 */ "typetoken", + /* 199 */ "typename", + /* 200 */ "signed", + /* 201 */ "plus_num", + /* 202 */ "minus_num", + /* 203 */ "scanpt", + /* 204 */ "ccons", + /* 205 */ "term", + /* 206 */ "expr", + /* 207 */ "onconf", + /* 208 */ "sortorder", + /* 209 */ "autoinc", + /* 210 */ "eidlist_opt", + /* 211 */ "refargs", + /* 212 */ "defer_subclause", + /* 213 */ "refarg", + /* 214 */ "refact", + /* 215 */ "init_deferred_pred_opt", + /* 216 */ "conslist", + /* 217 */ "tconscomma", + /* 218 */ "tcons", + /* 219 */ "sortlist", + /* 220 */ "eidlist", + /* 221 */ "defer_subclause_opt", + /* 222 */ "orconf", + /* 223 */ "resolvetype", + /* 224 */ "raisetype", + /* 225 */ "ifexists", + /* 226 */ "fullname", + /* 227 */ "selectnowith", + /* 228 */ "oneselect", + /* 229 */ "wqlist", + /* 230 */ "multiselect_op", + /* 231 */ "distinct", + /* 232 */ "selcollist", + /* 233 */ "from", + /* 234 */ "where_opt", + /* 235 */ "groupby_opt", + /* 236 */ "having_opt", + /* 237 */ "orderby_opt", + /* 238 */ "limit_opt", + /* 239 */ "window_clause", + /* 240 */ "values", + /* 241 */ "nexprlist", + /* 242 */ "sclp", + /* 243 */ "as", + /* 244 */ "seltablist", + /* 245 */ "stl_prefix", + /* 246 */ "joinop", + /* 247 */ "indexed_opt", + /* 248 */ "on_opt", + /* 249 */ "using_opt", + /* 250 */ "exprlist", + /* 251 */ "xfullname", + /* 252 */ "idlist", + /* 253 */ "with", + /* 254 */ "setlist", + /* 255 */ "insert_cmd", + /* 256 */ "idlist_opt", + /* 257 */ "upsert", + /* 258 */ "over_clause", + /* 259 */ "likeop", + /* 260 */ "between_op", + /* 261 */ "in_op", + /* 262 */ "paren_exprlist", + /* 263 */ "case_operand", + /* 264 */ "case_exprlist", + /* 265 */ "case_else", + /* 266 */ "uniqueflag", + /* 267 */ "collate", + /* 268 */ "vinto", + /* 269 */ "nmnum", + /* 270 */ "trigger_decl", + /* 271 */ "trigger_cmd_list", + /* 272 */ "trigger_time", + /* 273 */ "trigger_event", + /* 274 */ "foreach_clause", + /* 275 */ "when_clause", + /* 276 */ "trigger_cmd", + /* 277 */ "trnm", + /* 278 */ "tridxby", + /* 279 */ "database_kw_opt", + /* 280 */ "key_opt", + /* 281 */ "add_column_fullname", + /* 282 */ "kwcolumn_opt", + /* 283 */ "create_vtab", + /* 284 */ "vtabarglist", + /* 285 */ "vtabarg", + /* 286 */ "vtabargtoken", + /* 287 */ "lp", + /* 288 */ "anylist", + /* 289 */ "windowdefn_list", + /* 290 */ "windowdefn", + /* 291 */ "window", + /* 292 */ "frame_opt", + /* 293 */ "part_opt", + /* 294 */ "filter_opt", + /* 295 */ "range_or_rows", + /* 296 */ "frame_bound", + /* 297 */ "frame_bound_s", + /* 298 */ "frame_bound_e", + /* 299 */ "frame_exclude_opt", + /* 300 */ "frame_exclude", }; #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ @@ -148999,85 +149875,91 @@ static const char *const yyRuleName[] = { /* 287 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", /* 288 */ "windowdefn_list ::= windowdefn", /* 289 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", - /* 290 */ "windowdefn ::= nm AS window", - /* 291 */ "window ::= LP part_opt orderby_opt frame_opt RP", - /* 292 */ "part_opt ::= PARTITION BY nexprlist", - /* 293 */ "part_opt ::=", - /* 294 */ "frame_opt ::=", - /* 295 */ "frame_opt ::= range_or_rows frame_bound_s", - /* 296 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e", - /* 297 */ "range_or_rows ::= RANGE", - /* 298 */ "range_or_rows ::= ROWS", - /* 299 */ "frame_bound_s ::= frame_bound", - /* 300 */ "frame_bound_s ::= UNBOUNDED PRECEDING", - /* 301 */ "frame_bound_e ::= frame_bound", - /* 302 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", - /* 303 */ "frame_bound ::= expr PRECEDING", - /* 304 */ "frame_bound ::= CURRENT ROW", - /* 305 */ "frame_bound ::= expr FOLLOWING", - /* 306 */ "window_clause ::= WINDOW windowdefn_list", - /* 307 */ "over_clause ::= filter_opt OVER window", - /* 308 */ "over_clause ::= filter_opt OVER nm", - /* 309 */ "filter_opt ::=", - /* 310 */ "filter_opt ::= FILTER LP WHERE expr RP", - /* 311 */ "input ::= cmdlist", - /* 312 */ "cmdlist ::= cmdlist ecmd", - /* 313 */ "cmdlist ::= ecmd", - /* 314 */ "ecmd ::= SEMI", - /* 315 */ "ecmd ::= cmdx SEMI", - /* 316 */ "ecmd ::= explain cmdx", - /* 317 */ "trans_opt ::=", - /* 318 */ "trans_opt ::= TRANSACTION", - /* 319 */ "trans_opt ::= TRANSACTION nm", - /* 320 */ "savepoint_opt ::= SAVEPOINT", - /* 321 */ "savepoint_opt ::=", - /* 322 */ "cmd ::= create_table create_table_args", - /* 323 */ "columnlist ::= columnlist COMMA columnname carglist", - /* 324 */ "columnlist ::= columnname carglist", - /* 325 */ "nm ::= ID|INDEXED", - /* 326 */ "nm ::= STRING", - /* 327 */ "nm ::= JOIN_KW", - /* 328 */ "typetoken ::= typename", - /* 329 */ "typename ::= ID|STRING", - /* 330 */ "signed ::= plus_num", - /* 331 */ "signed ::= minus_num", - /* 332 */ "carglist ::= carglist ccons", - /* 333 */ "carglist ::=", - /* 334 */ "ccons ::= NULL onconf", - /* 335 */ "conslist_opt ::= COMMA conslist", - /* 336 */ "conslist ::= conslist tconscomma tcons", - /* 337 */ "conslist ::= tcons", - /* 338 */ "tconscomma ::=", - /* 339 */ "defer_subclause_opt ::= defer_subclause", - /* 340 */ "resolvetype ::= raisetype", - /* 341 */ "selectnowith ::= oneselect", - /* 342 */ "oneselect ::= values", - /* 343 */ "sclp ::= selcollist COMMA", - /* 344 */ "as ::= ID|STRING", - /* 345 */ "expr ::= term", - /* 346 */ "likeop ::= LIKE_KW|MATCH", - /* 347 */ "exprlist ::= nexprlist", - /* 348 */ "nmnum ::= plus_num", - /* 349 */ "nmnum ::= nm", - /* 350 */ "nmnum ::= ON", - /* 351 */ "nmnum ::= DELETE", - /* 352 */ "nmnum ::= DEFAULT", - /* 353 */ "plus_num ::= INTEGER|FLOAT", - /* 354 */ "foreach_clause ::=", - /* 355 */ "foreach_clause ::= FOR EACH ROW", - /* 356 */ "trnm ::= nm", - /* 357 */ "tridxby ::=", - /* 358 */ "database_kw_opt ::= DATABASE", - /* 359 */ "database_kw_opt ::=", - /* 360 */ "kwcolumn_opt ::=", - /* 361 */ "kwcolumn_opt ::= COLUMNKW", - /* 362 */ "vtabarglist ::= vtabarg", - /* 363 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 364 */ "vtabarg ::= vtabarg vtabargtoken", - /* 365 */ "anylist ::=", - /* 366 */ "anylist ::= anylist LP anylist RP", - /* 367 */ "anylist ::= anylist ANY", - /* 368 */ "with ::=", + /* 290 */ "windowdefn ::= nm AS LP window RP", + /* 291 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt", + /* 292 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt", + /* 293 */ "window ::= ORDER BY sortlist frame_opt", + /* 294 */ "window ::= nm ORDER BY sortlist frame_opt", + /* 295 */ "window ::= frame_opt", + /* 296 */ "window ::= nm frame_opt", + /* 297 */ "frame_opt ::=", + /* 298 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt", + /* 299 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt", + /* 300 */ "range_or_rows ::= RANGE|ROWS|GROUPS", + /* 301 */ "frame_bound_s ::= frame_bound", + /* 302 */ "frame_bound_s ::= UNBOUNDED PRECEDING", + /* 303 */ "frame_bound_e ::= frame_bound", + /* 304 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", + /* 305 */ "frame_bound ::= expr PRECEDING|FOLLOWING", + /* 306 */ "frame_bound ::= CURRENT ROW", + /* 307 */ "frame_exclude_opt ::=", + /* 308 */ "frame_exclude_opt ::= EXCLUDE frame_exclude", + /* 309 */ "frame_exclude ::= NO OTHERS", + /* 310 */ "frame_exclude ::= CURRENT ROW", + /* 311 */ "frame_exclude ::= GROUP|TIES", + /* 312 */ "window_clause ::= WINDOW windowdefn_list", + /* 313 */ "over_clause ::= filter_opt OVER LP window RP", + /* 314 */ "over_clause ::= filter_opt OVER nm", + /* 315 */ "filter_opt ::=", + /* 316 */ "filter_opt ::= FILTER LP WHERE expr RP", + /* 317 */ "input ::= cmdlist", + /* 318 */ "cmdlist ::= cmdlist ecmd", + /* 319 */ "cmdlist ::= ecmd", + /* 320 */ "ecmd ::= SEMI", + /* 321 */ "ecmd ::= cmdx SEMI", + /* 322 */ "ecmd ::= explain cmdx", + /* 323 */ "trans_opt ::=", + /* 324 */ "trans_opt ::= TRANSACTION", + /* 325 */ "trans_opt ::= TRANSACTION nm", + /* 326 */ "savepoint_opt ::= SAVEPOINT", + /* 327 */ "savepoint_opt ::=", + /* 328 */ "cmd ::= create_table create_table_args", + /* 329 */ "columnlist ::= columnlist COMMA columnname carglist", + /* 330 */ "columnlist ::= columnname carglist", + /* 331 */ "nm ::= ID|INDEXED", + /* 332 */ "nm ::= STRING", + /* 333 */ "nm ::= JOIN_KW", + /* 334 */ "typetoken ::= typename", + /* 335 */ "typename ::= ID|STRING", + /* 336 */ "signed ::= plus_num", + /* 337 */ "signed ::= minus_num", + /* 338 */ "carglist ::= carglist ccons", + /* 339 */ "carglist ::=", + /* 340 */ "ccons ::= NULL onconf", + /* 341 */ "conslist_opt ::= COMMA conslist", + /* 342 */ "conslist ::= conslist tconscomma tcons", + /* 343 */ "conslist ::= tcons", + /* 344 */ "tconscomma ::=", + /* 345 */ "defer_subclause_opt ::= defer_subclause", + /* 346 */ "resolvetype ::= raisetype", + /* 347 */ "selectnowith ::= oneselect", + /* 348 */ "oneselect ::= values", + /* 349 */ "sclp ::= selcollist COMMA", + /* 350 */ "as ::= ID|STRING", + /* 351 */ "expr ::= term", + /* 352 */ "likeop ::= LIKE_KW|MATCH", + /* 353 */ "exprlist ::= nexprlist", + /* 354 */ "nmnum ::= plus_num", + /* 355 */ "nmnum ::= nm", + /* 356 */ "nmnum ::= ON", + /* 357 */ "nmnum ::= DELETE", + /* 358 */ "nmnum ::= DEFAULT", + /* 359 */ "plus_num ::= INTEGER|FLOAT", + /* 360 */ "foreach_clause ::=", + /* 361 */ "foreach_clause ::= FOR EACH ROW", + /* 362 */ "trnm ::= nm", + /* 363 */ "tridxby ::=", + /* 364 */ "database_kw_opt ::= DATABASE", + /* 365 */ "database_kw_opt ::=", + /* 366 */ "kwcolumn_opt ::=", + /* 367 */ "kwcolumn_opt ::= COLUMNKW", + /* 368 */ "vtabarglist ::= vtabarg", + /* 369 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 370 */ "vtabarg ::= vtabarg vtabargtoken", + /* 371 */ "anylist ::=", + /* 372 */ "anylist ::= anylist LP anylist RP", + /* 373 */ "anylist ::= anylist ANY", + /* 374 */ "with ::=", }; #endif /* NDEBUG */ @@ -149203,97 +150085,97 @@ static void yy_destructor( ** inside the C code. */ /********* Begin destructor definitions ***************************************/ - case 174: /* select */ - case 206: /* selectnowith */ - case 207: /* oneselect */ - case 219: /* values */ + case 195: /* select */ + case 227: /* selectnowith */ + case 228: /* oneselect */ + case 240: /* values */ { -sqlite3SelectDelete(pParse->db, (yypminor->yy423)); +sqlite3SelectDelete(pParse->db, (yypminor->yy457)); } break; - case 184: /* term */ - case 185: /* expr */ - case 213: /* where_opt */ - case 215: /* having_opt */ - case 227: /* on_opt */ - case 242: /* case_operand */ - case 244: /* case_else */ - case 247: /* vinto */ - case 254: /* when_clause */ - case 259: /* key_opt */ - case 273: /* filter_opt */ + case 205: /* term */ + case 206: /* expr */ + case 234: /* where_opt */ + case 236: /* having_opt */ + case 248: /* on_opt */ + case 263: /* case_operand */ + case 265: /* case_else */ + case 268: /* vinto */ + case 275: /* when_clause */ + case 280: /* key_opt */ + case 294: /* filter_opt */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy490)); +sqlite3ExprDelete(pParse->db, (yypminor->yy524)); } break; - case 189: /* eidlist_opt */ - case 198: /* sortlist */ - case 199: /* eidlist */ - case 211: /* selcollist */ - case 214: /* groupby_opt */ - case 216: /* orderby_opt */ - case 220: /* nexprlist */ - case 221: /* sclp */ - case 229: /* exprlist */ - case 233: /* setlist */ - case 241: /* paren_exprlist */ - case 243: /* case_exprlist */ - case 272: /* part_opt */ + case 210: /* eidlist_opt */ + case 219: /* sortlist */ + case 220: /* eidlist */ + case 232: /* selcollist */ + case 235: /* groupby_opt */ + case 237: /* orderby_opt */ + case 241: /* nexprlist */ + case 242: /* sclp */ + case 250: /* exprlist */ + case 254: /* setlist */ + case 262: /* paren_exprlist */ + case 264: /* case_exprlist */ + case 293: /* part_opt */ { -sqlite3ExprListDelete(pParse->db, (yypminor->yy42)); +sqlite3ExprListDelete(pParse->db, (yypminor->yy434)); } break; - case 205: /* fullname */ - case 212: /* from */ - case 223: /* seltablist */ - case 224: /* stl_prefix */ - case 230: /* xfullname */ + case 226: /* fullname */ + case 233: /* from */ + case 244: /* seltablist */ + case 245: /* stl_prefix */ + case 251: /* xfullname */ { -sqlite3SrcListDelete(pParse->db, (yypminor->yy167)); +sqlite3SrcListDelete(pParse->db, (yypminor->yy483)); } break; - case 208: /* wqlist */ + case 229: /* wqlist */ { -sqlite3WithDelete(pParse->db, (yypminor->yy499)); +sqlite3WithDelete(pParse->db, (yypminor->yy59)); } break; - case 218: /* window_clause */ - case 268: /* windowdefn_list */ + case 239: /* window_clause */ + case 289: /* windowdefn_list */ { -sqlite3WindowListDelete(pParse->db, (yypminor->yy147)); +sqlite3WindowListDelete(pParse->db, (yypminor->yy295)); } break; - case 228: /* using_opt */ - case 231: /* idlist */ - case 235: /* idlist_opt */ + case 249: /* using_opt */ + case 252: /* idlist */ + case 256: /* idlist_opt */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy336)); +sqlite3IdListDelete(pParse->db, (yypminor->yy62)); } break; - case 237: /* over_clause */ - case 269: /* windowdefn */ - case 270: /* window */ - case 271: /* frame_opt */ + case 258: /* over_clause */ + case 290: /* windowdefn */ + case 291: /* window */ + case 292: /* frame_opt */ { -sqlite3WindowDelete(pParse->db, (yypminor->yy147)); +sqlite3WindowDelete(pParse->db, (yypminor->yy295)); } break; - case 250: /* trigger_cmd_list */ - case 255: /* trigger_cmd */ + case 271: /* trigger_cmd_list */ + case 276: /* trigger_cmd */ { -sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy119)); +sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy455)); } break; - case 252: /* trigger_event */ + case 273: /* trigger_event */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy350).b); +sqlite3IdListDelete(pParse->db, (yypminor->yy90).b); } break; - case 275: /* frame_bound */ - case 276: /* frame_bound_s */ - case 277: /* frame_bound_e */ + case 296: /* frame_bound */ + case 297: /* frame_bound_s */ + case 298: /* frame_bound_e */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy317).pExpr); +sqlite3ExprDelete(pParse->db, (yypminor->yy201).pExpr); } break; /********* End destructor definitions *****************************************/ @@ -149588,375 +150470,381 @@ static void yy_shift( /* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side ** of that rule */ static const YYCODETYPE yyRuleInfoLhs[] = { - 159, /* (0) explain ::= EXPLAIN */ - 159, /* (1) explain ::= EXPLAIN QUERY PLAN */ - 158, /* (2) cmdx ::= cmd */ - 160, /* (3) cmd ::= BEGIN transtype trans_opt */ - 161, /* (4) transtype ::= */ - 161, /* (5) transtype ::= DEFERRED */ - 161, /* (6) transtype ::= IMMEDIATE */ - 161, /* (7) transtype ::= EXCLUSIVE */ - 160, /* (8) cmd ::= COMMIT|END trans_opt */ - 160, /* (9) cmd ::= ROLLBACK trans_opt */ - 160, /* (10) cmd ::= SAVEPOINT nm */ - 160, /* (11) cmd ::= RELEASE savepoint_opt nm */ - 160, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ - 165, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ - 167, /* (14) createkw ::= CREATE */ - 169, /* (15) ifnotexists ::= */ - 169, /* (16) ifnotexists ::= IF NOT EXISTS */ - 168, /* (17) temp ::= TEMP */ - 168, /* (18) temp ::= */ - 166, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_options */ - 166, /* (20) create_table_args ::= AS select */ - 173, /* (21) table_options ::= */ - 173, /* (22) table_options ::= WITHOUT nm */ - 175, /* (23) columnname ::= nm typetoken */ - 177, /* (24) typetoken ::= */ - 177, /* (25) typetoken ::= typename LP signed RP */ - 177, /* (26) typetoken ::= typename LP signed COMMA signed RP */ - 178, /* (27) typename ::= typename ID|STRING */ - 182, /* (28) scanpt ::= */ - 183, /* (29) ccons ::= CONSTRAINT nm */ - 183, /* (30) ccons ::= DEFAULT scanpt term scanpt */ - 183, /* (31) ccons ::= DEFAULT LP expr RP */ - 183, /* (32) ccons ::= DEFAULT PLUS term scanpt */ - 183, /* (33) ccons ::= DEFAULT MINUS term scanpt */ - 183, /* (34) ccons ::= DEFAULT scanpt ID|INDEXED */ - 183, /* (35) ccons ::= NOT NULL onconf */ - 183, /* (36) ccons ::= PRIMARY KEY sortorder onconf autoinc */ - 183, /* (37) ccons ::= UNIQUE onconf */ - 183, /* (38) ccons ::= CHECK LP expr RP */ - 183, /* (39) ccons ::= REFERENCES nm eidlist_opt refargs */ - 183, /* (40) ccons ::= defer_subclause */ - 183, /* (41) ccons ::= COLLATE ID|STRING */ - 188, /* (42) autoinc ::= */ - 188, /* (43) autoinc ::= AUTOINCR */ - 190, /* (44) refargs ::= */ - 190, /* (45) refargs ::= refargs refarg */ - 192, /* (46) refarg ::= MATCH nm */ - 192, /* (47) refarg ::= ON INSERT refact */ - 192, /* (48) refarg ::= ON DELETE refact */ - 192, /* (49) refarg ::= ON UPDATE refact */ - 193, /* (50) refact ::= SET NULL */ - 193, /* (51) refact ::= SET DEFAULT */ - 193, /* (52) refact ::= CASCADE */ - 193, /* (53) refact ::= RESTRICT */ - 193, /* (54) refact ::= NO ACTION */ - 191, /* (55) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ - 191, /* (56) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ - 194, /* (57) init_deferred_pred_opt ::= */ - 194, /* (58) init_deferred_pred_opt ::= INITIALLY DEFERRED */ - 194, /* (59) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ - 172, /* (60) conslist_opt ::= */ - 196, /* (61) tconscomma ::= COMMA */ - 197, /* (62) tcons ::= CONSTRAINT nm */ - 197, /* (63) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ - 197, /* (64) tcons ::= UNIQUE LP sortlist RP onconf */ - 197, /* (65) tcons ::= CHECK LP expr RP onconf */ - 197, /* (66) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ - 200, /* (67) defer_subclause_opt ::= */ - 186, /* (68) onconf ::= */ - 186, /* (69) onconf ::= ON CONFLICT resolvetype */ - 201, /* (70) orconf ::= */ - 201, /* (71) orconf ::= OR resolvetype */ - 202, /* (72) resolvetype ::= IGNORE */ - 202, /* (73) resolvetype ::= REPLACE */ - 160, /* (74) cmd ::= DROP TABLE ifexists fullname */ - 204, /* (75) ifexists ::= IF EXISTS */ - 204, /* (76) ifexists ::= */ - 160, /* (77) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ - 160, /* (78) cmd ::= DROP VIEW ifexists fullname */ - 160, /* (79) cmd ::= select */ - 174, /* (80) select ::= WITH wqlist selectnowith */ - 174, /* (81) select ::= WITH RECURSIVE wqlist selectnowith */ - 174, /* (82) select ::= selectnowith */ - 206, /* (83) selectnowith ::= selectnowith multiselect_op oneselect */ - 209, /* (84) multiselect_op ::= UNION */ - 209, /* (85) multiselect_op ::= UNION ALL */ - 209, /* (86) multiselect_op ::= EXCEPT|INTERSECT */ - 207, /* (87) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ - 207, /* (88) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ - 219, /* (89) values ::= VALUES LP nexprlist RP */ - 219, /* (90) values ::= values COMMA LP nexprlist RP */ - 210, /* (91) distinct ::= DISTINCT */ - 210, /* (92) distinct ::= ALL */ - 210, /* (93) distinct ::= */ - 221, /* (94) sclp ::= */ - 211, /* (95) selcollist ::= sclp scanpt expr scanpt as */ - 211, /* (96) selcollist ::= sclp scanpt STAR */ - 211, /* (97) selcollist ::= sclp scanpt nm DOT STAR */ - 222, /* (98) as ::= AS nm */ - 222, /* (99) as ::= */ - 212, /* (100) from ::= */ - 212, /* (101) from ::= FROM seltablist */ - 224, /* (102) stl_prefix ::= seltablist joinop */ - 224, /* (103) stl_prefix ::= */ - 223, /* (104) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ - 223, /* (105) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ - 223, /* (106) seltablist ::= stl_prefix LP select RP as on_opt using_opt */ - 223, /* (107) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ - 170, /* (108) dbnm ::= */ - 170, /* (109) dbnm ::= DOT nm */ - 205, /* (110) fullname ::= nm */ - 205, /* (111) fullname ::= nm DOT nm */ - 230, /* (112) xfullname ::= nm */ - 230, /* (113) xfullname ::= nm DOT nm */ - 230, /* (114) xfullname ::= nm DOT nm AS nm */ - 230, /* (115) xfullname ::= nm AS nm */ - 225, /* (116) joinop ::= COMMA|JOIN */ - 225, /* (117) joinop ::= JOIN_KW JOIN */ - 225, /* (118) joinop ::= JOIN_KW nm JOIN */ - 225, /* (119) joinop ::= JOIN_KW nm nm JOIN */ - 227, /* (120) on_opt ::= ON expr */ - 227, /* (121) on_opt ::= */ - 226, /* (122) indexed_opt ::= */ - 226, /* (123) indexed_opt ::= INDEXED BY nm */ - 226, /* (124) indexed_opt ::= NOT INDEXED */ - 228, /* (125) using_opt ::= USING LP idlist RP */ - 228, /* (126) using_opt ::= */ - 216, /* (127) orderby_opt ::= */ - 216, /* (128) orderby_opt ::= ORDER BY sortlist */ - 198, /* (129) sortlist ::= sortlist COMMA expr sortorder */ - 198, /* (130) sortlist ::= expr sortorder */ - 187, /* (131) sortorder ::= ASC */ - 187, /* (132) sortorder ::= DESC */ - 187, /* (133) sortorder ::= */ - 214, /* (134) groupby_opt ::= */ - 214, /* (135) groupby_opt ::= GROUP BY nexprlist */ - 215, /* (136) having_opt ::= */ - 215, /* (137) having_opt ::= HAVING expr */ - 217, /* (138) limit_opt ::= */ - 217, /* (139) limit_opt ::= LIMIT expr */ - 217, /* (140) limit_opt ::= LIMIT expr OFFSET expr */ - 217, /* (141) limit_opt ::= LIMIT expr COMMA expr */ - 160, /* (142) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */ - 213, /* (143) where_opt ::= */ - 213, /* (144) where_opt ::= WHERE expr */ - 160, /* (145) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */ - 233, /* (146) setlist ::= setlist COMMA nm EQ expr */ - 233, /* (147) setlist ::= setlist COMMA LP idlist RP EQ expr */ - 233, /* (148) setlist ::= nm EQ expr */ - 233, /* (149) setlist ::= LP idlist RP EQ expr */ - 160, /* (150) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ - 160, /* (151) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */ - 236, /* (152) upsert ::= */ - 236, /* (153) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */ - 236, /* (154) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */ - 236, /* (155) upsert ::= ON CONFLICT DO NOTHING */ - 234, /* (156) insert_cmd ::= INSERT orconf */ - 234, /* (157) insert_cmd ::= REPLACE */ - 235, /* (158) idlist_opt ::= */ - 235, /* (159) idlist_opt ::= LP idlist RP */ - 231, /* (160) idlist ::= idlist COMMA nm */ - 231, /* (161) idlist ::= nm */ - 185, /* (162) expr ::= LP expr RP */ - 185, /* (163) expr ::= ID|INDEXED */ - 185, /* (164) expr ::= JOIN_KW */ - 185, /* (165) expr ::= nm DOT nm */ - 185, /* (166) expr ::= nm DOT nm DOT nm */ - 184, /* (167) term ::= NULL|FLOAT|BLOB */ - 184, /* (168) term ::= STRING */ - 184, /* (169) term ::= INTEGER */ - 185, /* (170) expr ::= VARIABLE */ - 185, /* (171) expr ::= expr COLLATE ID|STRING */ - 185, /* (172) expr ::= CAST LP expr AS typetoken RP */ - 185, /* (173) expr ::= ID|INDEXED LP distinct exprlist RP */ - 185, /* (174) expr ::= ID|INDEXED LP STAR RP */ - 185, /* (175) expr ::= ID|INDEXED LP distinct exprlist RP over_clause */ - 185, /* (176) expr ::= ID|INDEXED LP STAR RP over_clause */ - 184, /* (177) term ::= CTIME_KW */ - 185, /* (178) expr ::= LP nexprlist COMMA expr RP */ - 185, /* (179) expr ::= expr AND expr */ - 185, /* (180) expr ::= expr OR expr */ - 185, /* (181) expr ::= expr LT|GT|GE|LE expr */ - 185, /* (182) expr ::= expr EQ|NE expr */ - 185, /* (183) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ - 185, /* (184) expr ::= expr PLUS|MINUS expr */ - 185, /* (185) expr ::= expr STAR|SLASH|REM expr */ - 185, /* (186) expr ::= expr CONCAT expr */ - 238, /* (187) likeop ::= NOT LIKE_KW|MATCH */ - 185, /* (188) expr ::= expr likeop expr */ - 185, /* (189) expr ::= expr likeop expr ESCAPE expr */ - 185, /* (190) expr ::= expr ISNULL|NOTNULL */ - 185, /* (191) expr ::= expr NOT NULL */ - 185, /* (192) expr ::= expr IS expr */ - 185, /* (193) expr ::= expr IS NOT expr */ - 185, /* (194) expr ::= NOT expr */ - 185, /* (195) expr ::= BITNOT expr */ - 185, /* (196) expr ::= PLUS|MINUS expr */ - 239, /* (197) between_op ::= BETWEEN */ - 239, /* (198) between_op ::= NOT BETWEEN */ - 185, /* (199) expr ::= expr between_op expr AND expr */ - 240, /* (200) in_op ::= IN */ - 240, /* (201) in_op ::= NOT IN */ - 185, /* (202) expr ::= expr in_op LP exprlist RP */ - 185, /* (203) expr ::= LP select RP */ - 185, /* (204) expr ::= expr in_op LP select RP */ - 185, /* (205) expr ::= expr in_op nm dbnm paren_exprlist */ - 185, /* (206) expr ::= EXISTS LP select RP */ - 185, /* (207) expr ::= CASE case_operand case_exprlist case_else END */ - 243, /* (208) case_exprlist ::= case_exprlist WHEN expr THEN expr */ - 243, /* (209) case_exprlist ::= WHEN expr THEN expr */ - 244, /* (210) case_else ::= ELSE expr */ - 244, /* (211) case_else ::= */ - 242, /* (212) case_operand ::= expr */ - 242, /* (213) case_operand ::= */ - 229, /* (214) exprlist ::= */ - 220, /* (215) nexprlist ::= nexprlist COMMA expr */ - 220, /* (216) nexprlist ::= expr */ - 241, /* (217) paren_exprlist ::= */ - 241, /* (218) paren_exprlist ::= LP exprlist RP */ - 160, /* (219) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ - 245, /* (220) uniqueflag ::= UNIQUE */ - 245, /* (221) uniqueflag ::= */ - 189, /* (222) eidlist_opt ::= */ - 189, /* (223) eidlist_opt ::= LP eidlist RP */ - 199, /* (224) eidlist ::= eidlist COMMA nm collate sortorder */ - 199, /* (225) eidlist ::= nm collate sortorder */ - 246, /* (226) collate ::= */ - 246, /* (227) collate ::= COLLATE ID|STRING */ - 160, /* (228) cmd ::= DROP INDEX ifexists fullname */ - 160, /* (229) cmd ::= VACUUM vinto */ - 160, /* (230) cmd ::= VACUUM nm vinto */ - 247, /* (231) vinto ::= INTO expr */ - 247, /* (232) vinto ::= */ - 160, /* (233) cmd ::= PRAGMA nm dbnm */ - 160, /* (234) cmd ::= PRAGMA nm dbnm EQ nmnum */ - 160, /* (235) cmd ::= PRAGMA nm dbnm LP nmnum RP */ - 160, /* (236) cmd ::= PRAGMA nm dbnm EQ minus_num */ - 160, /* (237) cmd ::= PRAGMA nm dbnm LP minus_num RP */ - 180, /* (238) plus_num ::= PLUS INTEGER|FLOAT */ - 181, /* (239) minus_num ::= MINUS INTEGER|FLOAT */ - 160, /* (240) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ - 249, /* (241) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ - 251, /* (242) trigger_time ::= BEFORE|AFTER */ - 251, /* (243) trigger_time ::= INSTEAD OF */ - 251, /* (244) trigger_time ::= */ - 252, /* (245) trigger_event ::= DELETE|INSERT */ - 252, /* (246) trigger_event ::= UPDATE */ - 252, /* (247) trigger_event ::= UPDATE OF idlist */ - 254, /* (248) when_clause ::= */ - 254, /* (249) when_clause ::= WHEN expr */ - 250, /* (250) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ - 250, /* (251) trigger_cmd_list ::= trigger_cmd SEMI */ - 256, /* (252) trnm ::= nm DOT nm */ - 257, /* (253) tridxby ::= INDEXED BY nm */ - 257, /* (254) tridxby ::= NOT INDEXED */ - 255, /* (255) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */ - 255, /* (256) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ - 255, /* (257) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ - 255, /* (258) trigger_cmd ::= scanpt select scanpt */ - 185, /* (259) expr ::= RAISE LP IGNORE RP */ - 185, /* (260) expr ::= RAISE LP raisetype COMMA nm RP */ - 203, /* (261) raisetype ::= ROLLBACK */ - 203, /* (262) raisetype ::= ABORT */ - 203, /* (263) raisetype ::= FAIL */ - 160, /* (264) cmd ::= DROP TRIGGER ifexists fullname */ - 160, /* (265) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ - 160, /* (266) cmd ::= DETACH database_kw_opt expr */ - 259, /* (267) key_opt ::= */ - 259, /* (268) key_opt ::= KEY expr */ - 160, /* (269) cmd ::= REINDEX */ - 160, /* (270) cmd ::= REINDEX nm dbnm */ - 160, /* (271) cmd ::= ANALYZE */ - 160, /* (272) cmd ::= ANALYZE nm dbnm */ - 160, /* (273) cmd ::= ALTER TABLE fullname RENAME TO nm */ - 160, /* (274) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ - 260, /* (275) add_column_fullname ::= fullname */ - 160, /* (276) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ - 160, /* (277) cmd ::= create_vtab */ - 160, /* (278) cmd ::= create_vtab LP vtabarglist RP */ - 262, /* (279) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ - 264, /* (280) vtabarg ::= */ - 265, /* (281) vtabargtoken ::= ANY */ - 265, /* (282) vtabargtoken ::= lp anylist RP */ - 266, /* (283) lp ::= LP */ - 232, /* (284) with ::= WITH wqlist */ - 232, /* (285) with ::= WITH RECURSIVE wqlist */ - 208, /* (286) wqlist ::= nm eidlist_opt AS LP select RP */ - 208, /* (287) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ - 268, /* (288) windowdefn_list ::= windowdefn */ - 268, /* (289) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - 269, /* (290) windowdefn ::= nm AS window */ - 270, /* (291) window ::= LP part_opt orderby_opt frame_opt RP */ - 272, /* (292) part_opt ::= PARTITION BY nexprlist */ - 272, /* (293) part_opt ::= */ - 271, /* (294) frame_opt ::= */ - 271, /* (295) frame_opt ::= range_or_rows frame_bound_s */ - 271, /* (296) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e */ - 274, /* (297) range_or_rows ::= RANGE */ - 274, /* (298) range_or_rows ::= ROWS */ - 276, /* (299) frame_bound_s ::= frame_bound */ - 276, /* (300) frame_bound_s ::= UNBOUNDED PRECEDING */ - 277, /* (301) frame_bound_e ::= frame_bound */ - 277, /* (302) frame_bound_e ::= UNBOUNDED FOLLOWING */ - 275, /* (303) frame_bound ::= expr PRECEDING */ - 275, /* (304) frame_bound ::= CURRENT ROW */ - 275, /* (305) frame_bound ::= expr FOLLOWING */ - 218, /* (306) window_clause ::= WINDOW windowdefn_list */ - 237, /* (307) over_clause ::= filter_opt OVER window */ - 237, /* (308) over_clause ::= filter_opt OVER nm */ - 273, /* (309) filter_opt ::= */ - 273, /* (310) filter_opt ::= FILTER LP WHERE expr RP */ - 155, /* (311) input ::= cmdlist */ - 156, /* (312) cmdlist ::= cmdlist ecmd */ - 156, /* (313) cmdlist ::= ecmd */ - 157, /* (314) ecmd ::= SEMI */ - 157, /* (315) ecmd ::= cmdx SEMI */ - 157, /* (316) ecmd ::= explain cmdx */ - 162, /* (317) trans_opt ::= */ - 162, /* (318) trans_opt ::= TRANSACTION */ - 162, /* (319) trans_opt ::= TRANSACTION nm */ - 164, /* (320) savepoint_opt ::= SAVEPOINT */ - 164, /* (321) savepoint_opt ::= */ - 160, /* (322) cmd ::= create_table create_table_args */ - 171, /* (323) columnlist ::= columnlist COMMA columnname carglist */ - 171, /* (324) columnlist ::= columnname carglist */ - 163, /* (325) nm ::= ID|INDEXED */ - 163, /* (326) nm ::= STRING */ - 163, /* (327) nm ::= JOIN_KW */ - 177, /* (328) typetoken ::= typename */ - 178, /* (329) typename ::= ID|STRING */ - 179, /* (330) signed ::= plus_num */ - 179, /* (331) signed ::= minus_num */ - 176, /* (332) carglist ::= carglist ccons */ - 176, /* (333) carglist ::= */ - 183, /* (334) ccons ::= NULL onconf */ - 172, /* (335) conslist_opt ::= COMMA conslist */ - 195, /* (336) conslist ::= conslist tconscomma tcons */ - 195, /* (337) conslist ::= tcons */ - 196, /* (338) tconscomma ::= */ - 200, /* (339) defer_subclause_opt ::= defer_subclause */ - 202, /* (340) resolvetype ::= raisetype */ - 206, /* (341) selectnowith ::= oneselect */ - 207, /* (342) oneselect ::= values */ - 221, /* (343) sclp ::= selcollist COMMA */ - 222, /* (344) as ::= ID|STRING */ - 185, /* (345) expr ::= term */ - 238, /* (346) likeop ::= LIKE_KW|MATCH */ - 229, /* (347) exprlist ::= nexprlist */ - 248, /* (348) nmnum ::= plus_num */ - 248, /* (349) nmnum ::= nm */ - 248, /* (350) nmnum ::= ON */ - 248, /* (351) nmnum ::= DELETE */ - 248, /* (352) nmnum ::= DEFAULT */ - 180, /* (353) plus_num ::= INTEGER|FLOAT */ - 253, /* (354) foreach_clause ::= */ - 253, /* (355) foreach_clause ::= FOR EACH ROW */ - 256, /* (356) trnm ::= nm */ - 257, /* (357) tridxby ::= */ - 258, /* (358) database_kw_opt ::= DATABASE */ - 258, /* (359) database_kw_opt ::= */ - 261, /* (360) kwcolumn_opt ::= */ - 261, /* (361) kwcolumn_opt ::= COLUMNKW */ - 263, /* (362) vtabarglist ::= vtabarg */ - 263, /* (363) vtabarglist ::= vtabarglist COMMA vtabarg */ - 264, /* (364) vtabarg ::= vtabarg vtabargtoken */ - 267, /* (365) anylist ::= */ - 267, /* (366) anylist ::= anylist LP anylist RP */ - 267, /* (367) anylist ::= anylist ANY */ - 232, /* (368) with ::= */ + 180, /* (0) explain ::= EXPLAIN */ + 180, /* (1) explain ::= EXPLAIN QUERY PLAN */ + 179, /* (2) cmdx ::= cmd */ + 181, /* (3) cmd ::= BEGIN transtype trans_opt */ + 182, /* (4) transtype ::= */ + 182, /* (5) transtype ::= DEFERRED */ + 182, /* (6) transtype ::= IMMEDIATE */ + 182, /* (7) transtype ::= EXCLUSIVE */ + 181, /* (8) cmd ::= COMMIT|END trans_opt */ + 181, /* (9) cmd ::= ROLLBACK trans_opt */ + 181, /* (10) cmd ::= SAVEPOINT nm */ + 181, /* (11) cmd ::= RELEASE savepoint_opt nm */ + 181, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ + 186, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ + 188, /* (14) createkw ::= CREATE */ + 190, /* (15) ifnotexists ::= */ + 190, /* (16) ifnotexists ::= IF NOT EXISTS */ + 189, /* (17) temp ::= TEMP */ + 189, /* (18) temp ::= */ + 187, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_options */ + 187, /* (20) create_table_args ::= AS select */ + 194, /* (21) table_options ::= */ + 194, /* (22) table_options ::= WITHOUT nm */ + 196, /* (23) columnname ::= nm typetoken */ + 198, /* (24) typetoken ::= */ + 198, /* (25) typetoken ::= typename LP signed RP */ + 198, /* (26) typetoken ::= typename LP signed COMMA signed RP */ + 199, /* (27) typename ::= typename ID|STRING */ + 203, /* (28) scanpt ::= */ + 204, /* (29) ccons ::= CONSTRAINT nm */ + 204, /* (30) ccons ::= DEFAULT scanpt term scanpt */ + 204, /* (31) ccons ::= DEFAULT LP expr RP */ + 204, /* (32) ccons ::= DEFAULT PLUS term scanpt */ + 204, /* (33) ccons ::= DEFAULT MINUS term scanpt */ + 204, /* (34) ccons ::= DEFAULT scanpt ID|INDEXED */ + 204, /* (35) ccons ::= NOT NULL onconf */ + 204, /* (36) ccons ::= PRIMARY KEY sortorder onconf autoinc */ + 204, /* (37) ccons ::= UNIQUE onconf */ + 204, /* (38) ccons ::= CHECK LP expr RP */ + 204, /* (39) ccons ::= REFERENCES nm eidlist_opt refargs */ + 204, /* (40) ccons ::= defer_subclause */ + 204, /* (41) ccons ::= COLLATE ID|STRING */ + 209, /* (42) autoinc ::= */ + 209, /* (43) autoinc ::= AUTOINCR */ + 211, /* (44) refargs ::= */ + 211, /* (45) refargs ::= refargs refarg */ + 213, /* (46) refarg ::= MATCH nm */ + 213, /* (47) refarg ::= ON INSERT refact */ + 213, /* (48) refarg ::= ON DELETE refact */ + 213, /* (49) refarg ::= ON UPDATE refact */ + 214, /* (50) refact ::= SET NULL */ + 214, /* (51) refact ::= SET DEFAULT */ + 214, /* (52) refact ::= CASCADE */ + 214, /* (53) refact ::= RESTRICT */ + 214, /* (54) refact ::= NO ACTION */ + 212, /* (55) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ + 212, /* (56) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ + 215, /* (57) init_deferred_pred_opt ::= */ + 215, /* (58) init_deferred_pred_opt ::= INITIALLY DEFERRED */ + 215, /* (59) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ + 193, /* (60) conslist_opt ::= */ + 217, /* (61) tconscomma ::= COMMA */ + 218, /* (62) tcons ::= CONSTRAINT nm */ + 218, /* (63) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ + 218, /* (64) tcons ::= UNIQUE LP sortlist RP onconf */ + 218, /* (65) tcons ::= CHECK LP expr RP onconf */ + 218, /* (66) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ + 221, /* (67) defer_subclause_opt ::= */ + 207, /* (68) onconf ::= */ + 207, /* (69) onconf ::= ON CONFLICT resolvetype */ + 222, /* (70) orconf ::= */ + 222, /* (71) orconf ::= OR resolvetype */ + 223, /* (72) resolvetype ::= IGNORE */ + 223, /* (73) resolvetype ::= REPLACE */ + 181, /* (74) cmd ::= DROP TABLE ifexists fullname */ + 225, /* (75) ifexists ::= IF EXISTS */ + 225, /* (76) ifexists ::= */ + 181, /* (77) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ + 181, /* (78) cmd ::= DROP VIEW ifexists fullname */ + 181, /* (79) cmd ::= select */ + 195, /* (80) select ::= WITH wqlist selectnowith */ + 195, /* (81) select ::= WITH RECURSIVE wqlist selectnowith */ + 195, /* (82) select ::= selectnowith */ + 227, /* (83) selectnowith ::= selectnowith multiselect_op oneselect */ + 230, /* (84) multiselect_op ::= UNION */ + 230, /* (85) multiselect_op ::= UNION ALL */ + 230, /* (86) multiselect_op ::= EXCEPT|INTERSECT */ + 228, /* (87) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ + 228, /* (88) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ + 240, /* (89) values ::= VALUES LP nexprlist RP */ + 240, /* (90) values ::= values COMMA LP nexprlist RP */ + 231, /* (91) distinct ::= DISTINCT */ + 231, /* (92) distinct ::= ALL */ + 231, /* (93) distinct ::= */ + 242, /* (94) sclp ::= */ + 232, /* (95) selcollist ::= sclp scanpt expr scanpt as */ + 232, /* (96) selcollist ::= sclp scanpt STAR */ + 232, /* (97) selcollist ::= sclp scanpt nm DOT STAR */ + 243, /* (98) as ::= AS nm */ + 243, /* (99) as ::= */ + 233, /* (100) from ::= */ + 233, /* (101) from ::= FROM seltablist */ + 245, /* (102) stl_prefix ::= seltablist joinop */ + 245, /* (103) stl_prefix ::= */ + 244, /* (104) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ + 244, /* (105) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ + 244, /* (106) seltablist ::= stl_prefix LP select RP as on_opt using_opt */ + 244, /* (107) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ + 191, /* (108) dbnm ::= */ + 191, /* (109) dbnm ::= DOT nm */ + 226, /* (110) fullname ::= nm */ + 226, /* (111) fullname ::= nm DOT nm */ + 251, /* (112) xfullname ::= nm */ + 251, /* (113) xfullname ::= nm DOT nm */ + 251, /* (114) xfullname ::= nm DOT nm AS nm */ + 251, /* (115) xfullname ::= nm AS nm */ + 246, /* (116) joinop ::= COMMA|JOIN */ + 246, /* (117) joinop ::= JOIN_KW JOIN */ + 246, /* (118) joinop ::= JOIN_KW nm JOIN */ + 246, /* (119) joinop ::= JOIN_KW nm nm JOIN */ + 248, /* (120) on_opt ::= ON expr */ + 248, /* (121) on_opt ::= */ + 247, /* (122) indexed_opt ::= */ + 247, /* (123) indexed_opt ::= INDEXED BY nm */ + 247, /* (124) indexed_opt ::= NOT INDEXED */ + 249, /* (125) using_opt ::= USING LP idlist RP */ + 249, /* (126) using_opt ::= */ + 237, /* (127) orderby_opt ::= */ + 237, /* (128) orderby_opt ::= ORDER BY sortlist */ + 219, /* (129) sortlist ::= sortlist COMMA expr sortorder */ + 219, /* (130) sortlist ::= expr sortorder */ + 208, /* (131) sortorder ::= ASC */ + 208, /* (132) sortorder ::= DESC */ + 208, /* (133) sortorder ::= */ + 235, /* (134) groupby_opt ::= */ + 235, /* (135) groupby_opt ::= GROUP BY nexprlist */ + 236, /* (136) having_opt ::= */ + 236, /* (137) having_opt ::= HAVING expr */ + 238, /* (138) limit_opt ::= */ + 238, /* (139) limit_opt ::= LIMIT expr */ + 238, /* (140) limit_opt ::= LIMIT expr OFFSET expr */ + 238, /* (141) limit_opt ::= LIMIT expr COMMA expr */ + 181, /* (142) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */ + 234, /* (143) where_opt ::= */ + 234, /* (144) where_opt ::= WHERE expr */ + 181, /* (145) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */ + 254, /* (146) setlist ::= setlist COMMA nm EQ expr */ + 254, /* (147) setlist ::= setlist COMMA LP idlist RP EQ expr */ + 254, /* (148) setlist ::= nm EQ expr */ + 254, /* (149) setlist ::= LP idlist RP EQ expr */ + 181, /* (150) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ + 181, /* (151) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */ + 257, /* (152) upsert ::= */ + 257, /* (153) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */ + 257, /* (154) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */ + 257, /* (155) upsert ::= ON CONFLICT DO NOTHING */ + 255, /* (156) insert_cmd ::= INSERT orconf */ + 255, /* (157) insert_cmd ::= REPLACE */ + 256, /* (158) idlist_opt ::= */ + 256, /* (159) idlist_opt ::= LP idlist RP */ + 252, /* (160) idlist ::= idlist COMMA nm */ + 252, /* (161) idlist ::= nm */ + 206, /* (162) expr ::= LP expr RP */ + 206, /* (163) expr ::= ID|INDEXED */ + 206, /* (164) expr ::= JOIN_KW */ + 206, /* (165) expr ::= nm DOT nm */ + 206, /* (166) expr ::= nm DOT nm DOT nm */ + 205, /* (167) term ::= NULL|FLOAT|BLOB */ + 205, /* (168) term ::= STRING */ + 205, /* (169) term ::= INTEGER */ + 206, /* (170) expr ::= VARIABLE */ + 206, /* (171) expr ::= expr COLLATE ID|STRING */ + 206, /* (172) expr ::= CAST LP expr AS typetoken RP */ + 206, /* (173) expr ::= ID|INDEXED LP distinct exprlist RP */ + 206, /* (174) expr ::= ID|INDEXED LP STAR RP */ + 206, /* (175) expr ::= ID|INDEXED LP distinct exprlist RP over_clause */ + 206, /* (176) expr ::= ID|INDEXED LP STAR RP over_clause */ + 205, /* (177) term ::= CTIME_KW */ + 206, /* (178) expr ::= LP nexprlist COMMA expr RP */ + 206, /* (179) expr ::= expr AND expr */ + 206, /* (180) expr ::= expr OR expr */ + 206, /* (181) expr ::= expr LT|GT|GE|LE expr */ + 206, /* (182) expr ::= expr EQ|NE expr */ + 206, /* (183) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ + 206, /* (184) expr ::= expr PLUS|MINUS expr */ + 206, /* (185) expr ::= expr STAR|SLASH|REM expr */ + 206, /* (186) expr ::= expr CONCAT expr */ + 259, /* (187) likeop ::= NOT LIKE_KW|MATCH */ + 206, /* (188) expr ::= expr likeop expr */ + 206, /* (189) expr ::= expr likeop expr ESCAPE expr */ + 206, /* (190) expr ::= expr ISNULL|NOTNULL */ + 206, /* (191) expr ::= expr NOT NULL */ + 206, /* (192) expr ::= expr IS expr */ + 206, /* (193) expr ::= expr IS NOT expr */ + 206, /* (194) expr ::= NOT expr */ + 206, /* (195) expr ::= BITNOT expr */ + 206, /* (196) expr ::= PLUS|MINUS expr */ + 260, /* (197) between_op ::= BETWEEN */ + 260, /* (198) between_op ::= NOT BETWEEN */ + 206, /* (199) expr ::= expr between_op expr AND expr */ + 261, /* (200) in_op ::= IN */ + 261, /* (201) in_op ::= NOT IN */ + 206, /* (202) expr ::= expr in_op LP exprlist RP */ + 206, /* (203) expr ::= LP select RP */ + 206, /* (204) expr ::= expr in_op LP select RP */ + 206, /* (205) expr ::= expr in_op nm dbnm paren_exprlist */ + 206, /* (206) expr ::= EXISTS LP select RP */ + 206, /* (207) expr ::= CASE case_operand case_exprlist case_else END */ + 264, /* (208) case_exprlist ::= case_exprlist WHEN expr THEN expr */ + 264, /* (209) case_exprlist ::= WHEN expr THEN expr */ + 265, /* (210) case_else ::= ELSE expr */ + 265, /* (211) case_else ::= */ + 263, /* (212) case_operand ::= expr */ + 263, /* (213) case_operand ::= */ + 250, /* (214) exprlist ::= */ + 241, /* (215) nexprlist ::= nexprlist COMMA expr */ + 241, /* (216) nexprlist ::= expr */ + 262, /* (217) paren_exprlist ::= */ + 262, /* (218) paren_exprlist ::= LP exprlist RP */ + 181, /* (219) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + 266, /* (220) uniqueflag ::= UNIQUE */ + 266, /* (221) uniqueflag ::= */ + 210, /* (222) eidlist_opt ::= */ + 210, /* (223) eidlist_opt ::= LP eidlist RP */ + 220, /* (224) eidlist ::= eidlist COMMA nm collate sortorder */ + 220, /* (225) eidlist ::= nm collate sortorder */ + 267, /* (226) collate ::= */ + 267, /* (227) collate ::= COLLATE ID|STRING */ + 181, /* (228) cmd ::= DROP INDEX ifexists fullname */ + 181, /* (229) cmd ::= VACUUM vinto */ + 181, /* (230) cmd ::= VACUUM nm vinto */ + 268, /* (231) vinto ::= INTO expr */ + 268, /* (232) vinto ::= */ + 181, /* (233) cmd ::= PRAGMA nm dbnm */ + 181, /* (234) cmd ::= PRAGMA nm dbnm EQ nmnum */ + 181, /* (235) cmd ::= PRAGMA nm dbnm LP nmnum RP */ + 181, /* (236) cmd ::= PRAGMA nm dbnm EQ minus_num */ + 181, /* (237) cmd ::= PRAGMA nm dbnm LP minus_num RP */ + 201, /* (238) plus_num ::= PLUS INTEGER|FLOAT */ + 202, /* (239) minus_num ::= MINUS INTEGER|FLOAT */ + 181, /* (240) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + 270, /* (241) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + 272, /* (242) trigger_time ::= BEFORE|AFTER */ + 272, /* (243) trigger_time ::= INSTEAD OF */ + 272, /* (244) trigger_time ::= */ + 273, /* (245) trigger_event ::= DELETE|INSERT */ + 273, /* (246) trigger_event ::= UPDATE */ + 273, /* (247) trigger_event ::= UPDATE OF idlist */ + 275, /* (248) when_clause ::= */ + 275, /* (249) when_clause ::= WHEN expr */ + 271, /* (250) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + 271, /* (251) trigger_cmd_list ::= trigger_cmd SEMI */ + 277, /* (252) trnm ::= nm DOT nm */ + 278, /* (253) tridxby ::= INDEXED BY nm */ + 278, /* (254) tridxby ::= NOT INDEXED */ + 276, /* (255) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */ + 276, /* (256) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ + 276, /* (257) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ + 276, /* (258) trigger_cmd ::= scanpt select scanpt */ + 206, /* (259) expr ::= RAISE LP IGNORE RP */ + 206, /* (260) expr ::= RAISE LP raisetype COMMA nm RP */ + 224, /* (261) raisetype ::= ROLLBACK */ + 224, /* (262) raisetype ::= ABORT */ + 224, /* (263) raisetype ::= FAIL */ + 181, /* (264) cmd ::= DROP TRIGGER ifexists fullname */ + 181, /* (265) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + 181, /* (266) cmd ::= DETACH database_kw_opt expr */ + 280, /* (267) key_opt ::= */ + 280, /* (268) key_opt ::= KEY expr */ + 181, /* (269) cmd ::= REINDEX */ + 181, /* (270) cmd ::= REINDEX nm dbnm */ + 181, /* (271) cmd ::= ANALYZE */ + 181, /* (272) cmd ::= ANALYZE nm dbnm */ + 181, /* (273) cmd ::= ALTER TABLE fullname RENAME TO nm */ + 181, /* (274) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + 281, /* (275) add_column_fullname ::= fullname */ + 181, /* (276) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ + 181, /* (277) cmd ::= create_vtab */ + 181, /* (278) cmd ::= create_vtab LP vtabarglist RP */ + 283, /* (279) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + 285, /* (280) vtabarg ::= */ + 286, /* (281) vtabargtoken ::= ANY */ + 286, /* (282) vtabargtoken ::= lp anylist RP */ + 287, /* (283) lp ::= LP */ + 253, /* (284) with ::= WITH wqlist */ + 253, /* (285) with ::= WITH RECURSIVE wqlist */ + 229, /* (286) wqlist ::= nm eidlist_opt AS LP select RP */ + 229, /* (287) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ + 289, /* (288) windowdefn_list ::= windowdefn */ + 289, /* (289) windowdefn_list ::= windowdefn_list COMMA windowdefn */ + 290, /* (290) windowdefn ::= nm AS LP window RP */ + 291, /* (291) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + 291, /* (292) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + 291, /* (293) window ::= ORDER BY sortlist frame_opt */ + 291, /* (294) window ::= nm ORDER BY sortlist frame_opt */ + 291, /* (295) window ::= frame_opt */ + 291, /* (296) window ::= nm frame_opt */ + 292, /* (297) frame_opt ::= */ + 292, /* (298) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + 292, /* (299) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + 295, /* (300) range_or_rows ::= RANGE|ROWS|GROUPS */ + 297, /* (301) frame_bound_s ::= frame_bound */ + 297, /* (302) frame_bound_s ::= UNBOUNDED PRECEDING */ + 298, /* (303) frame_bound_e ::= frame_bound */ + 298, /* (304) frame_bound_e ::= UNBOUNDED FOLLOWING */ + 296, /* (305) frame_bound ::= expr PRECEDING|FOLLOWING */ + 296, /* (306) frame_bound ::= CURRENT ROW */ + 299, /* (307) frame_exclude_opt ::= */ + 299, /* (308) frame_exclude_opt ::= EXCLUDE frame_exclude */ + 300, /* (309) frame_exclude ::= NO OTHERS */ + 300, /* (310) frame_exclude ::= CURRENT ROW */ + 300, /* (311) frame_exclude ::= GROUP|TIES */ + 239, /* (312) window_clause ::= WINDOW windowdefn_list */ + 258, /* (313) over_clause ::= filter_opt OVER LP window RP */ + 258, /* (314) over_clause ::= filter_opt OVER nm */ + 294, /* (315) filter_opt ::= */ + 294, /* (316) filter_opt ::= FILTER LP WHERE expr RP */ + 176, /* (317) input ::= cmdlist */ + 177, /* (318) cmdlist ::= cmdlist ecmd */ + 177, /* (319) cmdlist ::= ecmd */ + 178, /* (320) ecmd ::= SEMI */ + 178, /* (321) ecmd ::= cmdx SEMI */ + 178, /* (322) ecmd ::= explain cmdx */ + 183, /* (323) trans_opt ::= */ + 183, /* (324) trans_opt ::= TRANSACTION */ + 183, /* (325) trans_opt ::= TRANSACTION nm */ + 185, /* (326) savepoint_opt ::= SAVEPOINT */ + 185, /* (327) savepoint_opt ::= */ + 181, /* (328) cmd ::= create_table create_table_args */ + 192, /* (329) columnlist ::= columnlist COMMA columnname carglist */ + 192, /* (330) columnlist ::= columnname carglist */ + 184, /* (331) nm ::= ID|INDEXED */ + 184, /* (332) nm ::= STRING */ + 184, /* (333) nm ::= JOIN_KW */ + 198, /* (334) typetoken ::= typename */ + 199, /* (335) typename ::= ID|STRING */ + 200, /* (336) signed ::= plus_num */ + 200, /* (337) signed ::= minus_num */ + 197, /* (338) carglist ::= carglist ccons */ + 197, /* (339) carglist ::= */ + 204, /* (340) ccons ::= NULL onconf */ + 193, /* (341) conslist_opt ::= COMMA conslist */ + 216, /* (342) conslist ::= conslist tconscomma tcons */ + 216, /* (343) conslist ::= tcons */ + 217, /* (344) tconscomma ::= */ + 221, /* (345) defer_subclause_opt ::= defer_subclause */ + 223, /* (346) resolvetype ::= raisetype */ + 227, /* (347) selectnowith ::= oneselect */ + 228, /* (348) oneselect ::= values */ + 242, /* (349) sclp ::= selcollist COMMA */ + 243, /* (350) as ::= ID|STRING */ + 206, /* (351) expr ::= term */ + 259, /* (352) likeop ::= LIKE_KW|MATCH */ + 250, /* (353) exprlist ::= nexprlist */ + 269, /* (354) nmnum ::= plus_num */ + 269, /* (355) nmnum ::= nm */ + 269, /* (356) nmnum ::= ON */ + 269, /* (357) nmnum ::= DELETE */ + 269, /* (358) nmnum ::= DEFAULT */ + 201, /* (359) plus_num ::= INTEGER|FLOAT */ + 274, /* (360) foreach_clause ::= */ + 274, /* (361) foreach_clause ::= FOR EACH ROW */ + 277, /* (362) trnm ::= nm */ + 278, /* (363) tridxby ::= */ + 279, /* (364) database_kw_opt ::= DATABASE */ + 279, /* (365) database_kw_opt ::= */ + 282, /* (366) kwcolumn_opt ::= */ + 282, /* (367) kwcolumn_opt ::= COLUMNKW */ + 284, /* (368) vtabarglist ::= vtabarg */ + 284, /* (369) vtabarglist ::= vtabarglist COMMA vtabarg */ + 285, /* (370) vtabarg ::= vtabarg vtabargtoken */ + 288, /* (371) anylist ::= */ + 288, /* (372) anylist ::= anylist LP anylist RP */ + 288, /* (373) anylist ::= anylist ANY */ + 253, /* (374) with ::= */ }; /* For rule J, yyRuleInfoNRhs[J] contains the negative of the number @@ -150252,85 +151140,91 @@ static const signed char yyRuleInfoNRhs[] = { -8, /* (287) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ -1, /* (288) windowdefn_list ::= windowdefn */ -3, /* (289) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - -3, /* (290) windowdefn ::= nm AS window */ - -5, /* (291) window ::= LP part_opt orderby_opt frame_opt RP */ - -3, /* (292) part_opt ::= PARTITION BY nexprlist */ - 0, /* (293) part_opt ::= */ - 0, /* (294) frame_opt ::= */ - -2, /* (295) frame_opt ::= range_or_rows frame_bound_s */ - -5, /* (296) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e */ - -1, /* (297) range_or_rows ::= RANGE */ - -1, /* (298) range_or_rows ::= ROWS */ - -1, /* (299) frame_bound_s ::= frame_bound */ - -2, /* (300) frame_bound_s ::= UNBOUNDED PRECEDING */ - -1, /* (301) frame_bound_e ::= frame_bound */ - -2, /* (302) frame_bound_e ::= UNBOUNDED FOLLOWING */ - -2, /* (303) frame_bound ::= expr PRECEDING */ - -2, /* (304) frame_bound ::= CURRENT ROW */ - -2, /* (305) frame_bound ::= expr FOLLOWING */ - -2, /* (306) window_clause ::= WINDOW windowdefn_list */ - -3, /* (307) over_clause ::= filter_opt OVER window */ - -3, /* (308) over_clause ::= filter_opt OVER nm */ - 0, /* (309) filter_opt ::= */ - -5, /* (310) filter_opt ::= FILTER LP WHERE expr RP */ - -1, /* (311) input ::= cmdlist */ - -2, /* (312) cmdlist ::= cmdlist ecmd */ - -1, /* (313) cmdlist ::= ecmd */ - -1, /* (314) ecmd ::= SEMI */ - -2, /* (315) ecmd ::= cmdx SEMI */ - -2, /* (316) ecmd ::= explain cmdx */ - 0, /* (317) trans_opt ::= */ - -1, /* (318) trans_opt ::= TRANSACTION */ - -2, /* (319) trans_opt ::= TRANSACTION nm */ - -1, /* (320) savepoint_opt ::= SAVEPOINT */ - 0, /* (321) savepoint_opt ::= */ - -2, /* (322) cmd ::= create_table create_table_args */ - -4, /* (323) columnlist ::= columnlist COMMA columnname carglist */ - -2, /* (324) columnlist ::= columnname carglist */ - -1, /* (325) nm ::= ID|INDEXED */ - -1, /* (326) nm ::= STRING */ - -1, /* (327) nm ::= JOIN_KW */ - -1, /* (328) typetoken ::= typename */ - -1, /* (329) typename ::= ID|STRING */ - -1, /* (330) signed ::= plus_num */ - -1, /* (331) signed ::= minus_num */ - -2, /* (332) carglist ::= carglist ccons */ - 0, /* (333) carglist ::= */ - -2, /* (334) ccons ::= NULL onconf */ - -2, /* (335) conslist_opt ::= COMMA conslist */ - -3, /* (336) conslist ::= conslist tconscomma tcons */ - -1, /* (337) conslist ::= tcons */ - 0, /* (338) tconscomma ::= */ - -1, /* (339) defer_subclause_opt ::= defer_subclause */ - -1, /* (340) resolvetype ::= raisetype */ - -1, /* (341) selectnowith ::= oneselect */ - -1, /* (342) oneselect ::= values */ - -2, /* (343) sclp ::= selcollist COMMA */ - -1, /* (344) as ::= ID|STRING */ - -1, /* (345) expr ::= term */ - -1, /* (346) likeop ::= LIKE_KW|MATCH */ - -1, /* (347) exprlist ::= nexprlist */ - -1, /* (348) nmnum ::= plus_num */ - -1, /* (349) nmnum ::= nm */ - -1, /* (350) nmnum ::= ON */ - -1, /* (351) nmnum ::= DELETE */ - -1, /* (352) nmnum ::= DEFAULT */ - -1, /* (353) plus_num ::= INTEGER|FLOAT */ - 0, /* (354) foreach_clause ::= */ - -3, /* (355) foreach_clause ::= FOR EACH ROW */ - -1, /* (356) trnm ::= nm */ - 0, /* (357) tridxby ::= */ - -1, /* (358) database_kw_opt ::= DATABASE */ - 0, /* (359) database_kw_opt ::= */ - 0, /* (360) kwcolumn_opt ::= */ - -1, /* (361) kwcolumn_opt ::= COLUMNKW */ - -1, /* (362) vtabarglist ::= vtabarg */ - -3, /* (363) vtabarglist ::= vtabarglist COMMA vtabarg */ - -2, /* (364) vtabarg ::= vtabarg vtabargtoken */ - 0, /* (365) anylist ::= */ - -4, /* (366) anylist ::= anylist LP anylist RP */ - -2, /* (367) anylist ::= anylist ANY */ - 0, /* (368) with ::= */ + -5, /* (290) windowdefn ::= nm AS LP window RP */ + -5, /* (291) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + -6, /* (292) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + -4, /* (293) window ::= ORDER BY sortlist frame_opt */ + -5, /* (294) window ::= nm ORDER BY sortlist frame_opt */ + -1, /* (295) window ::= frame_opt */ + -2, /* (296) window ::= nm frame_opt */ + 0, /* (297) frame_opt ::= */ + -3, /* (298) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + -6, /* (299) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + -1, /* (300) range_or_rows ::= RANGE|ROWS|GROUPS */ + -1, /* (301) frame_bound_s ::= frame_bound */ + -2, /* (302) frame_bound_s ::= UNBOUNDED PRECEDING */ + -1, /* (303) frame_bound_e ::= frame_bound */ + -2, /* (304) frame_bound_e ::= UNBOUNDED FOLLOWING */ + -2, /* (305) frame_bound ::= expr PRECEDING|FOLLOWING */ + -2, /* (306) frame_bound ::= CURRENT ROW */ + 0, /* (307) frame_exclude_opt ::= */ + -2, /* (308) frame_exclude_opt ::= EXCLUDE frame_exclude */ + -2, /* (309) frame_exclude ::= NO OTHERS */ + -2, /* (310) frame_exclude ::= CURRENT ROW */ + -1, /* (311) frame_exclude ::= GROUP|TIES */ + -2, /* (312) window_clause ::= WINDOW windowdefn_list */ + -5, /* (313) over_clause ::= filter_opt OVER LP window RP */ + -3, /* (314) over_clause ::= filter_opt OVER nm */ + 0, /* (315) filter_opt ::= */ + -5, /* (316) filter_opt ::= FILTER LP WHERE expr RP */ + -1, /* (317) input ::= cmdlist */ + -2, /* (318) cmdlist ::= cmdlist ecmd */ + -1, /* (319) cmdlist ::= ecmd */ + -1, /* (320) ecmd ::= SEMI */ + -2, /* (321) ecmd ::= cmdx SEMI */ + -2, /* (322) ecmd ::= explain cmdx */ + 0, /* (323) trans_opt ::= */ + -1, /* (324) trans_opt ::= TRANSACTION */ + -2, /* (325) trans_opt ::= TRANSACTION nm */ + -1, /* (326) savepoint_opt ::= SAVEPOINT */ + 0, /* (327) savepoint_opt ::= */ + -2, /* (328) cmd ::= create_table create_table_args */ + -4, /* (329) columnlist ::= columnlist COMMA columnname carglist */ + -2, /* (330) columnlist ::= columnname carglist */ + -1, /* (331) nm ::= ID|INDEXED */ + -1, /* (332) nm ::= STRING */ + -1, /* (333) nm ::= JOIN_KW */ + -1, /* (334) typetoken ::= typename */ + -1, /* (335) typename ::= ID|STRING */ + -1, /* (336) signed ::= plus_num */ + -1, /* (337) signed ::= minus_num */ + -2, /* (338) carglist ::= carglist ccons */ + 0, /* (339) carglist ::= */ + -2, /* (340) ccons ::= NULL onconf */ + -2, /* (341) conslist_opt ::= COMMA conslist */ + -3, /* (342) conslist ::= conslist tconscomma tcons */ + -1, /* (343) conslist ::= tcons */ + 0, /* (344) tconscomma ::= */ + -1, /* (345) defer_subclause_opt ::= defer_subclause */ + -1, /* (346) resolvetype ::= raisetype */ + -1, /* (347) selectnowith ::= oneselect */ + -1, /* (348) oneselect ::= values */ + -2, /* (349) sclp ::= selcollist COMMA */ + -1, /* (350) as ::= ID|STRING */ + -1, /* (351) expr ::= term */ + -1, /* (352) likeop ::= LIKE_KW|MATCH */ + -1, /* (353) exprlist ::= nexprlist */ + -1, /* (354) nmnum ::= plus_num */ + -1, /* (355) nmnum ::= nm */ + -1, /* (356) nmnum ::= ON */ + -1, /* (357) nmnum ::= DELETE */ + -1, /* (358) nmnum ::= DEFAULT */ + -1, /* (359) plus_num ::= INTEGER|FLOAT */ + 0, /* (360) foreach_clause ::= */ + -3, /* (361) foreach_clause ::= FOR EACH ROW */ + -1, /* (362) trnm ::= nm */ + 0, /* (363) tridxby ::= */ + -1, /* (364) database_kw_opt ::= DATABASE */ + 0, /* (365) database_kw_opt ::= */ + 0, /* (366) kwcolumn_opt ::= */ + -1, /* (367) kwcolumn_opt ::= COLUMNKW */ + -1, /* (368) vtabarglist ::= vtabarg */ + -3, /* (369) vtabarglist ::= vtabarglist COMMA vtabarg */ + -2, /* (370) vtabarg ::= vtabarg vtabargtoken */ + 0, /* (371) anylist ::= */ + -4, /* (372) anylist ::= anylist LP anylist RP */ + -2, /* (373) anylist ::= anylist ANY */ + 0, /* (374) with ::= */ }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -150427,15 +151321,16 @@ static YYACTIONTYPE yy_reduce( { sqlite3FinishCoding(pParse); } break; case 3: /* cmd ::= BEGIN transtype trans_opt */ -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy96);} +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy494);} break; case 4: /* transtype ::= */ -{yymsp[1].minor.yy96 = TK_DEFERRED;} +{yymsp[1].minor.yy494 = TK_DEFERRED;} break; case 5: /* transtype ::= DEFERRED */ case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6); case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7); -{yymsp[0].minor.yy96 = yymsp[0].major; /*A-overwrites-X*/} + case 300: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==300); +{yymsp[0].minor.yy494 = yymsp[0].major; /*A-overwrites-X*/} break; case 8: /* cmd ::= COMMIT|END trans_opt */ case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9); @@ -150458,7 +151353,7 @@ static YYACTIONTYPE yy_reduce( break; case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ { - sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy96,0,0,yymsp[-2].minor.yy96); + sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy494,0,0,yymsp[-2].minor.yy494); } break; case 14: /* createkw ::= CREATE */ @@ -150473,32 +151368,32 @@ static YYACTIONTYPE yy_reduce( case 76: /* ifexists ::= */ yytestcase(yyruleno==76); case 93: /* distinct ::= */ yytestcase(yyruleno==93); case 226: /* collate ::= */ yytestcase(yyruleno==226); -{yymsp[1].minor.yy96 = 0;} +{yymsp[1].minor.yy494 = 0;} break; case 16: /* ifnotexists ::= IF NOT EXISTS */ -{yymsp[-2].minor.yy96 = 1;} +{yymsp[-2].minor.yy494 = 1;} break; case 17: /* temp ::= TEMP */ case 43: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==43); -{yymsp[0].minor.yy96 = 1;} +{yymsp[0].minor.yy494 = 1;} break; case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_options */ { - sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy96,0); + sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy494,0); } break; case 20: /* create_table_args ::= AS select */ { - sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy423); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy423); + sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy457); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy457); } break; case 22: /* table_options ::= WITHOUT nm */ { if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ - yymsp[-1].minor.yy96 = TF_WithoutRowid | TF_NoVisibleRowid; + yymsp[-1].minor.yy494 = TF_WithoutRowid | TF_NoVisibleRowid; }else{ - yymsp[-1].minor.yy96 = 0; + yymsp[-1].minor.yy494 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } @@ -150527,7 +151422,7 @@ static YYACTIONTYPE yy_reduce( case 28: /* scanpt ::= */ { assert( yyLookahead!=YYNOCODE ); - yymsp[1].minor.yy464 = yyLookaheadToken.z; + yymsp[1].minor.yy294 = yyLookaheadToken.z; } break; case 29: /* ccons ::= CONSTRAINT nm */ @@ -150535,18 +151430,18 @@ static YYACTIONTYPE yy_reduce( {pParse->constraintName = yymsp[0].minor.yy0;} break; case 30: /* ccons ::= DEFAULT scanpt term scanpt */ -{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy490,yymsp[-2].minor.yy464,yymsp[0].minor.yy464);} +{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy524,yymsp[-2].minor.yy294,yymsp[0].minor.yy294);} break; case 31: /* ccons ::= DEFAULT LP expr RP */ -{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy490,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} +{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy524,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} break; case 32: /* ccons ::= DEFAULT PLUS term scanpt */ -{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy490,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy464);} +{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy524,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy294);} break; case 33: /* ccons ::= DEFAULT MINUS term scanpt */ { - Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[-1].minor.yy490, 0); - sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy464); + Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[-1].minor.yy524, 0); + sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy294); } break; case 34: /* ccons ::= DEFAULT scanpt ID|INDEXED */ @@ -150560,170 +151455,170 @@ static YYACTIONTYPE yy_reduce( } break; case 35: /* ccons ::= NOT NULL onconf */ -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy96);} +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy494);} break; case 36: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy96,yymsp[0].minor.yy96,yymsp[-2].minor.yy96);} +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy494,yymsp[0].minor.yy494,yymsp[-2].minor.yy494);} break; case 37: /* ccons ::= UNIQUE onconf */ -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy96,0,0,0,0, +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy494,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; case 38: /* ccons ::= CHECK LP expr RP */ -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy490);} +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy524);} break; case 39: /* ccons ::= REFERENCES nm eidlist_opt refargs */ -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy42,yymsp[0].minor.yy96);} +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy434,yymsp[0].minor.yy494);} break; case 40: /* ccons ::= defer_subclause */ -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy96);} +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy494);} break; case 41: /* ccons ::= COLLATE ID|STRING */ {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} break; case 44: /* refargs ::= */ -{ yymsp[1].minor.yy96 = OE_None*0x0101; /* EV: R-19803-45884 */} +{ yymsp[1].minor.yy494 = OE_None*0x0101; /* EV: R-19803-45884 */} break; case 45: /* refargs ::= refargs refarg */ -{ yymsp[-1].minor.yy96 = (yymsp[-1].minor.yy96 & ~yymsp[0].minor.yy367.mask) | yymsp[0].minor.yy367.value; } +{ yymsp[-1].minor.yy494 = (yymsp[-1].minor.yy494 & ~yymsp[0].minor.yy355.mask) | yymsp[0].minor.yy355.value; } break; case 46: /* refarg ::= MATCH nm */ -{ yymsp[-1].minor.yy367.value = 0; yymsp[-1].minor.yy367.mask = 0x000000; } +{ yymsp[-1].minor.yy355.value = 0; yymsp[-1].minor.yy355.mask = 0x000000; } break; case 47: /* refarg ::= ON INSERT refact */ -{ yymsp[-2].minor.yy367.value = 0; yymsp[-2].minor.yy367.mask = 0x000000; } +{ yymsp[-2].minor.yy355.value = 0; yymsp[-2].minor.yy355.mask = 0x000000; } break; case 48: /* refarg ::= ON DELETE refact */ -{ yymsp[-2].minor.yy367.value = yymsp[0].minor.yy96; yymsp[-2].minor.yy367.mask = 0x0000ff; } +{ yymsp[-2].minor.yy355.value = yymsp[0].minor.yy494; yymsp[-2].minor.yy355.mask = 0x0000ff; } break; case 49: /* refarg ::= ON UPDATE refact */ -{ yymsp[-2].minor.yy367.value = yymsp[0].minor.yy96<<8; yymsp[-2].minor.yy367.mask = 0x00ff00; } +{ yymsp[-2].minor.yy355.value = yymsp[0].minor.yy494<<8; yymsp[-2].minor.yy355.mask = 0x00ff00; } break; case 50: /* refact ::= SET NULL */ -{ yymsp[-1].minor.yy96 = OE_SetNull; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy494 = OE_SetNull; /* EV: R-33326-45252 */} break; case 51: /* refact ::= SET DEFAULT */ -{ yymsp[-1].minor.yy96 = OE_SetDflt; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy494 = OE_SetDflt; /* EV: R-33326-45252 */} break; case 52: /* refact ::= CASCADE */ -{ yymsp[0].minor.yy96 = OE_Cascade; /* EV: R-33326-45252 */} +{ yymsp[0].minor.yy494 = OE_Cascade; /* EV: R-33326-45252 */} break; case 53: /* refact ::= RESTRICT */ -{ yymsp[0].minor.yy96 = OE_Restrict; /* EV: R-33326-45252 */} +{ yymsp[0].minor.yy494 = OE_Restrict; /* EV: R-33326-45252 */} break; case 54: /* refact ::= NO ACTION */ -{ yymsp[-1].minor.yy96 = OE_None; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy494 = OE_None; /* EV: R-33326-45252 */} break; case 55: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ -{yymsp[-2].minor.yy96 = 0;} +{yymsp[-2].minor.yy494 = 0;} break; case 56: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ case 71: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==71); case 156: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==156); -{yymsp[-1].minor.yy96 = yymsp[0].minor.yy96;} +{yymsp[-1].minor.yy494 = yymsp[0].minor.yy494;} break; case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75); case 198: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==198); case 201: /* in_op ::= NOT IN */ yytestcase(yyruleno==201); case 227: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==227); -{yymsp[-1].minor.yy96 = 1;} +{yymsp[-1].minor.yy494 = 1;} break; case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ -{yymsp[-1].minor.yy96 = 0;} +{yymsp[-1].minor.yy494 = 0;} break; case 61: /* tconscomma ::= COMMA */ {pParse->constraintName.n = 0;} break; case 63: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy42,yymsp[0].minor.yy96,yymsp[-2].minor.yy96,0);} +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy434,yymsp[0].minor.yy494,yymsp[-2].minor.yy494,0);} break; case 64: /* tcons ::= UNIQUE LP sortlist RP onconf */ -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy42,yymsp[0].minor.yy96,0,0,0,0, +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy434,yymsp[0].minor.yy494,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; case 65: /* tcons ::= CHECK LP expr RP onconf */ -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy490);} +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy524);} break; case 66: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ { - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy42, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy42, yymsp[-1].minor.yy96); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy96); + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy434, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy434, yymsp[-1].minor.yy494); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy494); } break; case 68: /* onconf ::= */ case 70: /* orconf ::= */ yytestcase(yyruleno==70); -{yymsp[1].minor.yy96 = OE_Default;} +{yymsp[1].minor.yy494 = OE_Default;} break; case 69: /* onconf ::= ON CONFLICT resolvetype */ -{yymsp[-2].minor.yy96 = yymsp[0].minor.yy96;} +{yymsp[-2].minor.yy494 = yymsp[0].minor.yy494;} break; case 72: /* resolvetype ::= IGNORE */ -{yymsp[0].minor.yy96 = OE_Ignore;} +{yymsp[0].minor.yy494 = OE_Ignore;} break; case 73: /* resolvetype ::= REPLACE */ case 157: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==157); -{yymsp[0].minor.yy96 = OE_Replace;} +{yymsp[0].minor.yy494 = OE_Replace;} break; case 74: /* cmd ::= DROP TABLE ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy167, 0, yymsp[-1].minor.yy96); + sqlite3DropTable(pParse, yymsp[0].minor.yy483, 0, yymsp[-1].minor.yy494); } break; case 77: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ { - sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy42, yymsp[0].minor.yy423, yymsp[-7].minor.yy96, yymsp[-5].minor.yy96); + sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy434, yymsp[0].minor.yy457, yymsp[-7].minor.yy494, yymsp[-5].minor.yy494); } break; case 78: /* cmd ::= DROP VIEW ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy167, 1, yymsp[-1].minor.yy96); + sqlite3DropTable(pParse, yymsp[0].minor.yy483, 1, yymsp[-1].minor.yy494); } break; case 79: /* cmd ::= select */ { SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0}; - sqlite3Select(pParse, yymsp[0].minor.yy423, &dest); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy423); + sqlite3Select(pParse, yymsp[0].minor.yy457, &dest); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy457); } break; case 80: /* select ::= WITH wqlist selectnowith */ { - Select *p = yymsp[0].minor.yy423; + Select *p = yymsp[0].minor.yy457; if( p ){ - p->pWith = yymsp[-1].minor.yy499; + p->pWith = yymsp[-1].minor.yy59; parserDoubleLinkSelect(pParse, p); }else{ - sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy499); + sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy59); } - yymsp[-2].minor.yy423 = p; + yymsp[-2].minor.yy457 = p; } break; case 81: /* select ::= WITH RECURSIVE wqlist selectnowith */ { - Select *p = yymsp[0].minor.yy423; + Select *p = yymsp[0].minor.yy457; if( p ){ - p->pWith = yymsp[-1].minor.yy499; + p->pWith = yymsp[-1].minor.yy59; parserDoubleLinkSelect(pParse, p); }else{ - sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy499); + sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy59); } - yymsp[-3].minor.yy423 = p; + yymsp[-3].minor.yy457 = p; } break; case 82: /* select ::= selectnowith */ { - Select *p = yymsp[0].minor.yy423; + Select *p = yymsp[0].minor.yy457; if( p ){ parserDoubleLinkSelect(pParse, p); } - yymsp[0].minor.yy423 = p; /*A-overwrites-X*/ + yymsp[0].minor.yy457 = p; /*A-overwrites-X*/ } break; case 83: /* selectnowith ::= selectnowith multiselect_op oneselect */ { - Select *pRhs = yymsp[0].minor.yy423; - Select *pLhs = yymsp[-2].minor.yy423; + Select *pRhs = yymsp[0].minor.yy457; + Select *pLhs = yymsp[-2].minor.yy457; if( pRhs && pRhs->pPrior ){ SrcList *pFrom; Token x; @@ -150733,63 +151628,63 @@ static YYACTIONTYPE yy_reduce( pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0); } if( pRhs ){ - pRhs->op = (u8)yymsp[-1].minor.yy96; + pRhs->op = (u8)yymsp[-1].minor.yy494; pRhs->pPrior = pLhs; if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue; pRhs->selFlags &= ~SF_MultiValue; - if( yymsp[-1].minor.yy96!=TK_ALL ) pParse->hasCompound = 1; + if( yymsp[-1].minor.yy494!=TK_ALL ) pParse->hasCompound = 1; }else{ sqlite3SelectDelete(pParse->db, pLhs); } - yymsp[-2].minor.yy423 = pRhs; + yymsp[-2].minor.yy457 = pRhs; } break; case 84: /* multiselect_op ::= UNION */ case 86: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==86); -{yymsp[0].minor.yy96 = yymsp[0].major; /*A-overwrites-OP*/} +{yymsp[0].minor.yy494 = yymsp[0].major; /*A-overwrites-OP*/} break; case 85: /* multiselect_op ::= UNION ALL */ -{yymsp[-1].minor.yy96 = TK_ALL;} +{yymsp[-1].minor.yy494 = TK_ALL;} break; case 87: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { - yymsp[-8].minor.yy423 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy42,yymsp[-5].minor.yy167,yymsp[-4].minor.yy490,yymsp[-3].minor.yy42,yymsp[-2].minor.yy490,yymsp[-1].minor.yy42,yymsp[-7].minor.yy96,yymsp[0].minor.yy490); + yymsp[-8].minor.yy457 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy434,yymsp[-5].minor.yy483,yymsp[-4].minor.yy524,yymsp[-3].minor.yy434,yymsp[-2].minor.yy524,yymsp[-1].minor.yy434,yymsp[-7].minor.yy494,yymsp[0].minor.yy524); } break; case 88: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ { - yymsp[-9].minor.yy423 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy42,yymsp[-6].minor.yy167,yymsp[-5].minor.yy490,yymsp[-4].minor.yy42,yymsp[-3].minor.yy490,yymsp[-1].minor.yy42,yymsp[-8].minor.yy96,yymsp[0].minor.yy490); - if( yymsp[-9].minor.yy423 ){ - yymsp[-9].minor.yy423->pWinDefn = yymsp[-2].minor.yy147; + yymsp[-9].minor.yy457 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy434,yymsp[-6].minor.yy483,yymsp[-5].minor.yy524,yymsp[-4].minor.yy434,yymsp[-3].minor.yy524,yymsp[-1].minor.yy434,yymsp[-8].minor.yy494,yymsp[0].minor.yy524); + if( yymsp[-9].minor.yy457 ){ + yymsp[-9].minor.yy457->pWinDefn = yymsp[-2].minor.yy295; }else{ - sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy147); + sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy295); } } break; case 89: /* values ::= VALUES LP nexprlist RP */ { - yymsp[-3].minor.yy423 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy42,0,0,0,0,0,SF_Values,0); + yymsp[-3].minor.yy457 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy434,0,0,0,0,0,SF_Values,0); } break; case 90: /* values ::= values COMMA LP nexprlist RP */ { - Select *pRight, *pLeft = yymsp[-4].minor.yy423; - pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy42,0,0,0,0,0,SF_Values|SF_MultiValue,0); + Select *pRight, *pLeft = yymsp[-4].minor.yy457; + pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy434,0,0,0,0,0,SF_Values|SF_MultiValue,0); if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; if( pRight ){ pRight->op = TK_ALL; pRight->pPrior = pLeft; - yymsp[-4].minor.yy423 = pRight; + yymsp[-4].minor.yy457 = pRight; }else{ - yymsp[-4].minor.yy423 = pLeft; + yymsp[-4].minor.yy457 = pLeft; } } break; case 91: /* distinct ::= DISTINCT */ -{yymsp[0].minor.yy96 = SF_Distinct;} +{yymsp[0].minor.yy494 = SF_Distinct;} break; case 92: /* distinct ::= ALL */ -{yymsp[0].minor.yy96 = SF_All;} +{yymsp[0].minor.yy494 = SF_All;} break; case 94: /* sclp ::= */ case 127: /* orderby_opt ::= */ yytestcase(yyruleno==127); @@ -150797,19 +151692,19 @@ static YYACTIONTYPE yy_reduce( case 214: /* exprlist ::= */ yytestcase(yyruleno==214); case 217: /* paren_exprlist ::= */ yytestcase(yyruleno==217); case 222: /* eidlist_opt ::= */ yytestcase(yyruleno==222); -{yymsp[1].minor.yy42 = 0;} +{yymsp[1].minor.yy434 = 0;} break; case 95: /* selcollist ::= sclp scanpt expr scanpt as */ { - yymsp[-4].minor.yy42 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy42, yymsp[-2].minor.yy490); - if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy42, &yymsp[0].minor.yy0, 1); - sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy42,yymsp[-3].minor.yy464,yymsp[-1].minor.yy464); + yymsp[-4].minor.yy434 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy434, yymsp[-2].minor.yy524); + if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy434, &yymsp[0].minor.yy0, 1); + sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy434,yymsp[-3].minor.yy294,yymsp[-1].minor.yy294); } break; case 96: /* selcollist ::= sclp scanpt STAR */ { Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); - yymsp[-2].minor.yy42 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy42, p); + yymsp[-2].minor.yy434 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy434, p); } break; case 97: /* selcollist ::= sclp scanpt nm DOT STAR */ @@ -150817,7 +151712,7 @@ static YYACTIONTYPE yy_reduce( Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); - yymsp[-4].minor.yy42 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy42, pDot); + yymsp[-4].minor.yy434 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy434, pDot); } break; case 98: /* as ::= AS nm */ @@ -150827,48 +151722,48 @@ static YYACTIONTYPE yy_reduce( {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} break; case 100: /* from ::= */ -{yymsp[1].minor.yy167 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy167));} +{yymsp[1].minor.yy483 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy483));} break; case 101: /* from ::= FROM seltablist */ { - yymsp[-1].minor.yy167 = yymsp[0].minor.yy167; - sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy167); + yymsp[-1].minor.yy483 = yymsp[0].minor.yy483; + sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy483); } break; case 102: /* stl_prefix ::= seltablist joinop */ { - if( ALWAYS(yymsp[-1].minor.yy167 && yymsp[-1].minor.yy167->nSrc>0) ) yymsp[-1].minor.yy167->a[yymsp[-1].minor.yy167->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy96; + if( ALWAYS(yymsp[-1].minor.yy483 && yymsp[-1].minor.yy483->nSrc>0) ) yymsp[-1].minor.yy483->a[yymsp[-1].minor.yy483->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy494; } break; case 103: /* stl_prefix ::= */ -{yymsp[1].minor.yy167 = 0;} +{yymsp[1].minor.yy483 = 0;} break; case 104: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ { - yymsp[-6].minor.yy167 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy167,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy490,yymsp[0].minor.yy336); - sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy167, &yymsp[-2].minor.yy0); + yymsp[-6].minor.yy483 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy483,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy524,yymsp[0].minor.yy62); + sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy483, &yymsp[-2].minor.yy0); } break; case 105: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ { - yymsp[-8].minor.yy167 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy167,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy490,yymsp[0].minor.yy336); - sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy167, yymsp[-4].minor.yy42); + yymsp[-8].minor.yy483 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy483,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy524,yymsp[0].minor.yy62); + sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy483, yymsp[-4].minor.yy434); } break; case 106: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ { - yymsp[-6].minor.yy167 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy167,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy423,yymsp[-1].minor.yy490,yymsp[0].minor.yy336); + yymsp[-6].minor.yy483 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy483,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy457,yymsp[-1].minor.yy524,yymsp[0].minor.yy62); } break; case 107: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ { - if( yymsp[-6].minor.yy167==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy490==0 && yymsp[0].minor.yy336==0 ){ - yymsp[-6].minor.yy167 = yymsp[-4].minor.yy167; - }else if( yymsp[-4].minor.yy167->nSrc==1 ){ - yymsp[-6].minor.yy167 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy167,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy490,yymsp[0].minor.yy336); - if( yymsp[-6].minor.yy167 ){ - struct SrcList_item *pNew = &yymsp[-6].minor.yy167->a[yymsp[-6].minor.yy167->nSrc-1]; - struct SrcList_item *pOld = yymsp[-4].minor.yy167->a; + if( yymsp[-6].minor.yy483==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy524==0 && yymsp[0].minor.yy62==0 ){ + yymsp[-6].minor.yy483 = yymsp[-4].minor.yy483; + }else if( yymsp[-4].minor.yy483->nSrc==1 ){ + yymsp[-6].minor.yy483 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy483,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy524,yymsp[0].minor.yy62); + if( yymsp[-6].minor.yy483 ){ + struct SrcList_item *pNew = &yymsp[-6].minor.yy483->a[yymsp[-6].minor.yy483->nSrc-1]; + struct SrcList_item *pOld = yymsp[-4].minor.yy483->a; pNew->zName = pOld->zName; pNew->zDatabase = pOld->zDatabase; pNew->pSelect = pOld->pSelect; @@ -150881,12 +151776,12 @@ static YYACTIONTYPE yy_reduce( pOld->zName = pOld->zDatabase = 0; pOld->pSelect = 0; } - sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy167); + sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy483); }else{ Select *pSubquery; - sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy167); - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy167,0,0,0,0,SF_NestedFrom,0); - yymsp[-6].minor.yy167 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy167,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy490,yymsp[0].minor.yy336); + sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy483); + pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy483,0,0,0,0,SF_NestedFrom,0); + yymsp[-6].minor.yy483 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy483,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy524,yymsp[0].minor.yy62); } } break; @@ -150896,54 +151791,54 @@ static YYACTIONTYPE yy_reduce( break; case 110: /* fullname ::= nm */ { - yylhsminor.yy167 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); - if( IN_RENAME_OBJECT && yylhsminor.yy167 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy167->a[0].zName, &yymsp[0].minor.yy0); + yylhsminor.yy483 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); + if( IN_RENAME_OBJECT && yylhsminor.yy483 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy483->a[0].zName, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy167 = yylhsminor.yy167; + yymsp[0].minor.yy483 = yylhsminor.yy483; break; case 111: /* fullname ::= nm DOT nm */ { - yylhsminor.yy167 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); - if( IN_RENAME_OBJECT && yylhsminor.yy167 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy167->a[0].zName, &yymsp[0].minor.yy0); + yylhsminor.yy483 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); + if( IN_RENAME_OBJECT && yylhsminor.yy483 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy483->a[0].zName, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy167 = yylhsminor.yy167; + yymsp[-2].minor.yy483 = yylhsminor.yy483; break; case 112: /* xfullname ::= nm */ -{yymsp[0].minor.yy167 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} +{yymsp[0].minor.yy483 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} break; case 113: /* xfullname ::= nm DOT nm */ -{yymsp[-2].minor.yy167 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} +{yymsp[-2].minor.yy483 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} break; case 114: /* xfullname ::= nm DOT nm AS nm */ { - yymsp[-4].minor.yy167 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/ - if( yymsp[-4].minor.yy167 ) yymsp[-4].minor.yy167->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); + yymsp[-4].minor.yy483 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/ + if( yymsp[-4].minor.yy483 ) yymsp[-4].minor.yy483->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); } break; case 115: /* xfullname ::= nm AS nm */ { - yymsp[-2].minor.yy167 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/ - if( yymsp[-2].minor.yy167 ) yymsp[-2].minor.yy167->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); + yymsp[-2].minor.yy483 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/ + if( yymsp[-2].minor.yy483 ) yymsp[-2].minor.yy483->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); } break; case 116: /* joinop ::= COMMA|JOIN */ -{ yymsp[0].minor.yy96 = JT_INNER; } +{ yymsp[0].minor.yy494 = JT_INNER; } break; case 117: /* joinop ::= JOIN_KW JOIN */ -{yymsp[-1].minor.yy96 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} +{yymsp[-1].minor.yy494 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} break; case 118: /* joinop ::= JOIN_KW nm JOIN */ -{yymsp[-2].minor.yy96 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} +{yymsp[-2].minor.yy494 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} break; case 119: /* joinop ::= JOIN_KW nm nm JOIN */ -{yymsp[-3].minor.yy96 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} +{yymsp[-3].minor.yy494 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} break; case 120: /* on_opt ::= ON expr */ case 137: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==137); case 144: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==144); case 210: /* case_else ::= ELSE expr */ yytestcase(yyruleno==210); case 231: /* vinto ::= INTO expr */ yytestcase(yyruleno==231); -{yymsp[-1].minor.yy490 = yymsp[0].minor.yy490;} +{yymsp[-1].minor.yy524 = yymsp[0].minor.yy524;} break; case 121: /* on_opt ::= */ case 136: /* having_opt ::= */ yytestcase(yyruleno==136); @@ -150952,7 +151847,7 @@ static YYACTIONTYPE yy_reduce( case 211: /* case_else ::= */ yytestcase(yyruleno==211); case 213: /* case_operand ::= */ yytestcase(yyruleno==213); case 232: /* vinto ::= */ yytestcase(yyruleno==232); -{yymsp[1].minor.yy490 = 0;} +{yymsp[1].minor.yy524 = 0;} break; case 123: /* indexed_opt ::= INDEXED BY nm */ {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} @@ -150961,119 +151856,119 @@ static YYACTIONTYPE yy_reduce( {yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;} break; case 125: /* using_opt ::= USING LP idlist RP */ -{yymsp[-3].minor.yy336 = yymsp[-1].minor.yy336;} +{yymsp[-3].minor.yy62 = yymsp[-1].minor.yy62;} break; case 126: /* using_opt ::= */ case 158: /* idlist_opt ::= */ yytestcase(yyruleno==158); -{yymsp[1].minor.yy336 = 0;} +{yymsp[1].minor.yy62 = 0;} break; case 128: /* orderby_opt ::= ORDER BY sortlist */ case 135: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==135); -{yymsp[-2].minor.yy42 = yymsp[0].minor.yy42;} +{yymsp[-2].minor.yy434 = yymsp[0].minor.yy434;} break; case 129: /* sortlist ::= sortlist COMMA expr sortorder */ { - yymsp[-3].minor.yy42 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy42,yymsp[-1].minor.yy490); - sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy42,yymsp[0].minor.yy96); + yymsp[-3].minor.yy434 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy434,yymsp[-1].minor.yy524); + sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy434,yymsp[0].minor.yy494); } break; case 130: /* sortlist ::= expr sortorder */ { - yymsp[-1].minor.yy42 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy490); /*A-overwrites-Y*/ - sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy42,yymsp[0].minor.yy96); + yymsp[-1].minor.yy434 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy524); /*A-overwrites-Y*/ + sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy434,yymsp[0].minor.yy494); } break; case 131: /* sortorder ::= ASC */ -{yymsp[0].minor.yy96 = SQLITE_SO_ASC;} +{yymsp[0].minor.yy494 = SQLITE_SO_ASC;} break; case 132: /* sortorder ::= DESC */ -{yymsp[0].minor.yy96 = SQLITE_SO_DESC;} +{yymsp[0].minor.yy494 = SQLITE_SO_DESC;} break; case 133: /* sortorder ::= */ -{yymsp[1].minor.yy96 = SQLITE_SO_UNDEFINED;} +{yymsp[1].minor.yy494 = SQLITE_SO_UNDEFINED;} break; case 139: /* limit_opt ::= LIMIT expr */ -{yymsp[-1].minor.yy490 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy490,0);} +{yymsp[-1].minor.yy524 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy524,0);} break; case 140: /* limit_opt ::= LIMIT expr OFFSET expr */ -{yymsp[-3].minor.yy490 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy490,yymsp[0].minor.yy490);} +{yymsp[-3].minor.yy524 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy524,yymsp[0].minor.yy524);} break; case 141: /* limit_opt ::= LIMIT expr COMMA expr */ -{yymsp[-3].minor.yy490 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy490,yymsp[-2].minor.yy490);} +{yymsp[-3].minor.yy524 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy524,yymsp[-2].minor.yy524);} break; case 142: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy167, &yymsp[-1].minor.yy0); - sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy167,yymsp[0].minor.yy490,0,0); + sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy483, &yymsp[-1].minor.yy0); + sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy483,yymsp[0].minor.yy524,0,0); } break; case 145: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy167, &yymsp[-3].minor.yy0); - sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy42,"set list"); - sqlite3Update(pParse,yymsp[-4].minor.yy167,yymsp[-1].minor.yy42,yymsp[0].minor.yy490,yymsp[-5].minor.yy96,0,0,0); + sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy483, &yymsp[-3].minor.yy0); + sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy434,"set list"); + sqlite3Update(pParse,yymsp[-4].minor.yy483,yymsp[-1].minor.yy434,yymsp[0].minor.yy524,yymsp[-5].minor.yy494,0,0,0); } break; case 146: /* setlist ::= setlist COMMA nm EQ expr */ { - yymsp[-4].minor.yy42 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy42, yymsp[0].minor.yy490); - sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy42, &yymsp[-2].minor.yy0, 1); + yymsp[-4].minor.yy434 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy434, yymsp[0].minor.yy524); + sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy434, &yymsp[-2].minor.yy0, 1); } break; case 147: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ { - yymsp[-6].minor.yy42 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy42, yymsp[-3].minor.yy336, yymsp[0].minor.yy490); + yymsp[-6].minor.yy434 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy434, yymsp[-3].minor.yy62, yymsp[0].minor.yy524); } break; case 148: /* setlist ::= nm EQ expr */ { - yylhsminor.yy42 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy490); - sqlite3ExprListSetName(pParse, yylhsminor.yy42, &yymsp[-2].minor.yy0, 1); + yylhsminor.yy434 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy524); + sqlite3ExprListSetName(pParse, yylhsminor.yy434, &yymsp[-2].minor.yy0, 1); } - yymsp[-2].minor.yy42 = yylhsminor.yy42; + yymsp[-2].minor.yy434 = yylhsminor.yy434; break; case 149: /* setlist ::= LP idlist RP EQ expr */ { - yymsp[-4].minor.yy42 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy336, yymsp[0].minor.yy490); + yymsp[-4].minor.yy434 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy62, yymsp[0].minor.yy524); } break; case 150: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ { - sqlite3Insert(pParse, yymsp[-3].minor.yy167, yymsp[-1].minor.yy423, yymsp[-2].minor.yy336, yymsp[-5].minor.yy96, yymsp[0].minor.yy266); + sqlite3Insert(pParse, yymsp[-3].minor.yy483, yymsp[-1].minor.yy457, yymsp[-2].minor.yy62, yymsp[-5].minor.yy494, yymsp[0].minor.yy136); } break; case 151: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */ { - sqlite3Insert(pParse, yymsp[-3].minor.yy167, 0, yymsp[-2].minor.yy336, yymsp[-5].minor.yy96, 0); + sqlite3Insert(pParse, yymsp[-3].minor.yy483, 0, yymsp[-2].minor.yy62, yymsp[-5].minor.yy494, 0); } break; case 152: /* upsert ::= */ -{ yymsp[1].minor.yy266 = 0; } +{ yymsp[1].minor.yy136 = 0; } break; case 153: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */ -{ yymsp[-10].minor.yy266 = sqlite3UpsertNew(pParse->db,yymsp[-7].minor.yy42,yymsp[-5].minor.yy490,yymsp[-1].minor.yy42,yymsp[0].minor.yy490);} +{ yymsp[-10].minor.yy136 = sqlite3UpsertNew(pParse->db,yymsp[-7].minor.yy434,yymsp[-5].minor.yy524,yymsp[-1].minor.yy434,yymsp[0].minor.yy524);} break; case 154: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */ -{ yymsp[-7].minor.yy266 = sqlite3UpsertNew(pParse->db,yymsp[-4].minor.yy42,yymsp[-2].minor.yy490,0,0); } +{ yymsp[-7].minor.yy136 = sqlite3UpsertNew(pParse->db,yymsp[-4].minor.yy434,yymsp[-2].minor.yy524,0,0); } break; case 155: /* upsert ::= ON CONFLICT DO NOTHING */ -{ yymsp[-3].minor.yy266 = sqlite3UpsertNew(pParse->db,0,0,0,0); } +{ yymsp[-3].minor.yy136 = sqlite3UpsertNew(pParse->db,0,0,0,0); } break; case 159: /* idlist_opt ::= LP idlist RP */ -{yymsp[-2].minor.yy336 = yymsp[-1].minor.yy336;} +{yymsp[-2].minor.yy62 = yymsp[-1].minor.yy62;} break; case 160: /* idlist ::= idlist COMMA nm */ -{yymsp[-2].minor.yy336 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy336,&yymsp[0].minor.yy0);} +{yymsp[-2].minor.yy62 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy62,&yymsp[0].minor.yy0);} break; case 161: /* idlist ::= nm */ -{yymsp[0].minor.yy336 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} +{yymsp[0].minor.yy62 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} break; case 162: /* expr ::= LP expr RP */ -{yymsp[-2].minor.yy490 = yymsp[-1].minor.yy490;} +{yymsp[-2].minor.yy524 = yymsp[-1].minor.yy524;} break; case 163: /* expr ::= ID|INDEXED */ case 164: /* expr ::= JOIN_KW */ yytestcase(yyruleno==164); -{yymsp[0].minor.yy490=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} +{yymsp[0].minor.yy524=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; case 165: /* expr ::= nm DOT nm */ { @@ -151083,9 +151978,9 @@ static YYACTIONTYPE yy_reduce( sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[0].minor.yy0); sqlite3RenameTokenMap(pParse, (void*)temp1, &yymsp[-2].minor.yy0); } - yylhsminor.yy490 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); + yylhsminor.yy524 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); } - yymsp[-2].minor.yy490 = yylhsminor.yy490; + yymsp[-2].minor.yy524 = yylhsminor.yy524; break; case 166: /* expr ::= nm DOT nm DOT nm */ { @@ -151097,26 +151992,26 @@ static YYACTIONTYPE yy_reduce( sqlite3RenameTokenMap(pParse, (void*)temp3, &yymsp[0].minor.yy0); sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[-2].minor.yy0); } - yylhsminor.yy490 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); + yylhsminor.yy524 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); } - yymsp[-4].minor.yy490 = yylhsminor.yy490; + yymsp[-4].minor.yy524 = yylhsminor.yy524; break; case 167: /* term ::= NULL|FLOAT|BLOB */ case 168: /* term ::= STRING */ yytestcase(yyruleno==168); -{yymsp[0].minor.yy490=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} +{yymsp[0].minor.yy524=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; case 169: /* term ::= INTEGER */ { - yylhsminor.yy490 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); + yylhsminor.yy524 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); } - yymsp[0].minor.yy490 = yylhsminor.yy490; + yymsp[0].minor.yy524 = yylhsminor.yy524; break; case 170: /* expr ::= VARIABLE */ { if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ u32 n = yymsp[0].minor.yy0.n; - yymsp[0].minor.yy490 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); - sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy490, n); + yymsp[0].minor.yy524 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); + sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy524, n); }else{ /* When doing a nested parse, one can include terms in an expression ** that look like this: #1 #2 ... These terms refer to registers @@ -151125,63 +152020,63 @@ static YYACTIONTYPE yy_reduce( assert( t.n>=2 ); if( pParse->nested==0 ){ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t); - yymsp[0].minor.yy490 = 0; + yymsp[0].minor.yy524 = 0; }else{ - yymsp[0].minor.yy490 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); - if( yymsp[0].minor.yy490 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy490->iTable); + yymsp[0].minor.yy524 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); + if( yymsp[0].minor.yy524 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy524->iTable); } } } break; case 171: /* expr ::= expr COLLATE ID|STRING */ { - yymsp[-2].minor.yy490 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy490, &yymsp[0].minor.yy0, 1); + yymsp[-2].minor.yy524 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy524, &yymsp[0].minor.yy0, 1); } break; case 172: /* expr ::= CAST LP expr AS typetoken RP */ { - yymsp[-5].minor.yy490 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); - sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy490, yymsp[-3].minor.yy490, 0); + yymsp[-5].minor.yy524 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); + sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy524, yymsp[-3].minor.yy524, 0); } break; case 173: /* expr ::= ID|INDEXED LP distinct exprlist RP */ { - yylhsminor.yy490 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy42, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy96); + yylhsminor.yy524 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy434, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy494); } - yymsp[-4].minor.yy490 = yylhsminor.yy490; + yymsp[-4].minor.yy524 = yylhsminor.yy524; break; case 174: /* expr ::= ID|INDEXED LP STAR RP */ { - yylhsminor.yy490 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0); + yylhsminor.yy524 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0); } - yymsp[-3].minor.yy490 = yylhsminor.yy490; + yymsp[-3].minor.yy524 = yylhsminor.yy524; break; case 175: /* expr ::= ID|INDEXED LP distinct exprlist RP over_clause */ { - yylhsminor.yy490 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy42, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy96); - sqlite3WindowAttach(pParse, yylhsminor.yy490, yymsp[0].minor.yy147); + yylhsminor.yy524 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy434, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy494); + sqlite3WindowAttach(pParse, yylhsminor.yy524, yymsp[0].minor.yy295); } - yymsp[-5].minor.yy490 = yylhsminor.yy490; + yymsp[-5].minor.yy524 = yylhsminor.yy524; break; case 176: /* expr ::= ID|INDEXED LP STAR RP over_clause */ { - yylhsminor.yy490 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0); - sqlite3WindowAttach(pParse, yylhsminor.yy490, yymsp[0].minor.yy147); + yylhsminor.yy524 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0); + sqlite3WindowAttach(pParse, yylhsminor.yy524, yymsp[0].minor.yy295); } - yymsp[-4].minor.yy490 = yylhsminor.yy490; + yymsp[-4].minor.yy524 = yylhsminor.yy524; break; case 177: /* term ::= CTIME_KW */ { - yylhsminor.yy490 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0); + yylhsminor.yy524 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0); } - yymsp[0].minor.yy490 = yylhsminor.yy490; + yymsp[0].minor.yy524 = yylhsminor.yy524; break; case 178: /* expr ::= LP nexprlist COMMA expr RP */ { - ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy42, yymsp[-1].minor.yy490); - yymsp[-4].minor.yy490 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); - if( yymsp[-4].minor.yy490 ){ - yymsp[-4].minor.yy490->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy434, yymsp[-1].minor.yy524); + yymsp[-4].minor.yy524 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); + if( yymsp[-4].minor.yy524 ){ + yymsp[-4].minor.yy524->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } @@ -151195,7 +152090,7 @@ static YYACTIONTYPE yy_reduce( case 184: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==184); case 185: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==185); case 186: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==186); -{yymsp[-2].minor.yy490=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy490,yymsp[0].minor.yy490);} +{yymsp[-2].minor.yy524=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy524,yymsp[0].minor.yy524);} break; case 187: /* likeop ::= NOT LIKE_KW|MATCH */ {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} @@ -151205,11 +152100,11 @@ static YYACTIONTYPE yy_reduce( ExprList *pList; int bNot = yymsp[-1].minor.yy0.n & 0x80000000; yymsp[-1].minor.yy0.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy490); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy490); - yymsp[-2].minor.yy490 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); - if( bNot ) yymsp[-2].minor.yy490 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy490, 0); - if( yymsp[-2].minor.yy490 ) yymsp[-2].minor.yy490->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy524); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy524); + yymsp[-2].minor.yy524 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); + if( bNot ) yymsp[-2].minor.yy524 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy524, 0); + if( yymsp[-2].minor.yy524 ) yymsp[-2].minor.yy524->flags |= EP_InfixFunc; } break; case 189: /* expr ::= expr likeop expr ESCAPE expr */ @@ -151217,62 +152112,62 @@ static YYACTIONTYPE yy_reduce( ExprList *pList; int bNot = yymsp[-3].minor.yy0.n & 0x80000000; yymsp[-3].minor.yy0.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy490); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy490); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy490); - yymsp[-4].minor.yy490 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0); - if( bNot ) yymsp[-4].minor.yy490 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy490, 0); - if( yymsp[-4].minor.yy490 ) yymsp[-4].minor.yy490->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy524); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy524); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy524); + yymsp[-4].minor.yy524 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0); + if( bNot ) yymsp[-4].minor.yy524 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy524, 0); + if( yymsp[-4].minor.yy524 ) yymsp[-4].minor.yy524->flags |= EP_InfixFunc; } break; case 190: /* expr ::= expr ISNULL|NOTNULL */ -{yymsp[-1].minor.yy490 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy490,0);} +{yymsp[-1].minor.yy524 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy524,0);} break; case 191: /* expr ::= expr NOT NULL */ -{yymsp[-2].minor.yy490 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy490,0);} +{yymsp[-2].minor.yy524 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy524,0);} break; case 192: /* expr ::= expr IS expr */ { - yymsp[-2].minor.yy490 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy490,yymsp[0].minor.yy490); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy490, yymsp[-2].minor.yy490, TK_ISNULL); + yymsp[-2].minor.yy524 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy524,yymsp[0].minor.yy524); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy524, yymsp[-2].minor.yy524, TK_ISNULL); } break; case 193: /* expr ::= expr IS NOT expr */ { - yymsp[-3].minor.yy490 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy490,yymsp[0].minor.yy490); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy490, yymsp[-3].minor.yy490, TK_NOTNULL); + yymsp[-3].minor.yy524 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy524,yymsp[0].minor.yy524); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy524, yymsp[-3].minor.yy524, TK_NOTNULL); } break; case 194: /* expr ::= NOT expr */ case 195: /* expr ::= BITNOT expr */ yytestcase(yyruleno==195); -{yymsp[-1].minor.yy490 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy490, 0);/*A-overwrites-B*/} +{yymsp[-1].minor.yy524 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy524, 0);/*A-overwrites-B*/} break; case 196: /* expr ::= PLUS|MINUS expr */ { - yymsp[-1].minor.yy490 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy490, 0); + yymsp[-1].minor.yy524 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy524, 0); /*A-overwrites-B*/ } break; case 197: /* between_op ::= BETWEEN */ case 200: /* in_op ::= IN */ yytestcase(yyruleno==200); -{yymsp[0].minor.yy96 = 0;} +{yymsp[0].minor.yy494 = 0;} break; case 199: /* expr ::= expr between_op expr AND expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy490); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy490); - yymsp[-4].minor.yy490 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy490, 0); - if( yymsp[-4].minor.yy490 ){ - yymsp[-4].minor.yy490->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy524); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy524); + yymsp[-4].minor.yy524 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy524, 0); + if( yymsp[-4].minor.yy524 ){ + yymsp[-4].minor.yy524->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } - if( yymsp[-3].minor.yy96 ) yymsp[-4].minor.yy490 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy490, 0); + if( yymsp[-3].minor.yy494 ) yymsp[-4].minor.yy524 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy524, 0); } break; case 202: /* expr ::= expr in_op LP exprlist RP */ { - if( yymsp[-1].minor.yy42==0 ){ + if( yymsp[-1].minor.yy434==0 ){ /* Expressions of the form ** ** expr1 IN () @@ -151282,10 +152177,10 @@ static YYACTIONTYPE yy_reduce( ** regardless of the value of expr1. */ if( IN_RENAME_OBJECT==0 ){ - sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy490); - yymsp[-4].minor.yy490 = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy96],1); + sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy524); + yymsp[-4].minor.yy524 = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy494],1); } - }else if( yymsp[-1].minor.yy42->nExpr==1 ){ + }else if( yymsp[-1].minor.yy434->nExpr==1 ){ /* Expressions of the form: ** ** expr1 IN (?1) @@ -151302,100 +152197,100 @@ static YYACTIONTYPE yy_reduce( ** affinity or the collating sequence to use for comparison. Otherwise, ** the semantics would be subtly different from IN or NOT IN. */ - Expr *pRHS = yymsp[-1].minor.yy42->a[0].pExpr; - yymsp[-1].minor.yy42->a[0].pExpr = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy42); + Expr *pRHS = yymsp[-1].minor.yy434->a[0].pExpr; + yymsp[-1].minor.yy434->a[0].pExpr = 0; + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy434); /* pRHS cannot be NULL because a malloc error would have been detected ** before now and control would have never reached this point */ if( ALWAYS(pRHS) ){ pRHS->flags &= ~EP_Collate; pRHS->flags |= EP_Generic; } - yymsp[-4].minor.yy490 = sqlite3PExpr(pParse, yymsp[-3].minor.yy96 ? TK_NE : TK_EQ, yymsp[-4].minor.yy490, pRHS); + yymsp[-4].minor.yy524 = sqlite3PExpr(pParse, yymsp[-3].minor.yy494 ? TK_NE : TK_EQ, yymsp[-4].minor.yy524, pRHS); }else{ - yymsp[-4].minor.yy490 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy490, 0); - if( yymsp[-4].minor.yy490 ){ - yymsp[-4].minor.yy490->x.pList = yymsp[-1].minor.yy42; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy490); + yymsp[-4].minor.yy524 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy524, 0); + if( yymsp[-4].minor.yy524 ){ + yymsp[-4].minor.yy524->x.pList = yymsp[-1].minor.yy434; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy524); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy42); + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy434); } - if( yymsp[-3].minor.yy96 ) yymsp[-4].minor.yy490 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy490, 0); + if( yymsp[-3].minor.yy494 ) yymsp[-4].minor.yy524 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy524, 0); } } break; case 203: /* expr ::= LP select RP */ { - yymsp[-2].minor.yy490 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); - sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy490, yymsp[-1].minor.yy423); + yymsp[-2].minor.yy524 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); + sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy524, yymsp[-1].minor.yy457); } break; case 204: /* expr ::= expr in_op LP select RP */ { - yymsp[-4].minor.yy490 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy490, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy490, yymsp[-1].minor.yy423); - if( yymsp[-3].minor.yy96 ) yymsp[-4].minor.yy490 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy490, 0); + yymsp[-4].minor.yy524 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy524, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy524, yymsp[-1].minor.yy457); + if( yymsp[-3].minor.yy494 ) yymsp[-4].minor.yy524 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy524, 0); } break; case 205: /* expr ::= expr in_op nm dbnm paren_exprlist */ { SrcList *pSrc = sqlite3SrcListAppend(pParse, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0); - if( yymsp[0].minor.yy42 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy42); - yymsp[-4].minor.yy490 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy490, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy490, pSelect); - if( yymsp[-3].minor.yy96 ) yymsp[-4].minor.yy490 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy490, 0); + if( yymsp[0].minor.yy434 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy434); + yymsp[-4].minor.yy524 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy524, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy524, pSelect); + if( yymsp[-3].minor.yy494 ) yymsp[-4].minor.yy524 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy524, 0); } break; case 206: /* expr ::= EXISTS LP select RP */ { Expr *p; - p = yymsp[-3].minor.yy490 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); - sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy423); + p = yymsp[-3].minor.yy524 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); + sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy457); } break; case 207: /* expr ::= CASE case_operand case_exprlist case_else END */ { - yymsp[-4].minor.yy490 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy490, 0); - if( yymsp[-4].minor.yy490 ){ - yymsp[-4].minor.yy490->x.pList = yymsp[-1].minor.yy490 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy42,yymsp[-1].minor.yy490) : yymsp[-2].minor.yy42; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy490); + yymsp[-4].minor.yy524 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy524, 0); + if( yymsp[-4].minor.yy524 ){ + yymsp[-4].minor.yy524->x.pList = yymsp[-1].minor.yy524 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy434,yymsp[-1].minor.yy524) : yymsp[-2].minor.yy434; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy524); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy42); - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy490); + sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy434); + sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy524); } } break; case 208: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { - yymsp[-4].minor.yy42 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy42, yymsp[-2].minor.yy490); - yymsp[-4].minor.yy42 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy42, yymsp[0].minor.yy490); + yymsp[-4].minor.yy434 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy434, yymsp[-2].minor.yy524); + yymsp[-4].minor.yy434 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy434, yymsp[0].minor.yy524); } break; case 209: /* case_exprlist ::= WHEN expr THEN expr */ { - yymsp[-3].minor.yy42 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy490); - yymsp[-3].minor.yy42 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy42, yymsp[0].minor.yy490); + yymsp[-3].minor.yy434 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy524); + yymsp[-3].minor.yy434 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy434, yymsp[0].minor.yy524); } break; case 212: /* case_operand ::= expr */ -{yymsp[0].minor.yy490 = yymsp[0].minor.yy490; /*A-overwrites-X*/} +{yymsp[0].minor.yy524 = yymsp[0].minor.yy524; /*A-overwrites-X*/} break; case 215: /* nexprlist ::= nexprlist COMMA expr */ -{yymsp[-2].minor.yy42 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy42,yymsp[0].minor.yy490);} +{yymsp[-2].minor.yy434 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy434,yymsp[0].minor.yy524);} break; case 216: /* nexprlist ::= expr */ -{yymsp[0].minor.yy42 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy490); /*A-overwrites-Y*/} +{yymsp[0].minor.yy434 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy524); /*A-overwrites-Y*/} break; case 218: /* paren_exprlist ::= LP exprlist RP */ case 223: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==223); -{yymsp[-2].minor.yy42 = yymsp[-1].minor.yy42;} +{yymsp[-2].minor.yy434 = yymsp[-1].minor.yy434;} break; case 219: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ { sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, - sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy42, yymsp[-10].minor.yy96, - &yymsp[-11].minor.yy0, yymsp[0].minor.yy490, SQLITE_SO_ASC, yymsp[-8].minor.yy96, SQLITE_IDXTYPE_APPDEF); + sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy434, yymsp[-10].minor.yy494, + &yymsp[-11].minor.yy0, yymsp[0].minor.yy524, SQLITE_SO_ASC, yymsp[-8].minor.yy494, SQLITE_IDXTYPE_APPDEF); if( IN_RENAME_OBJECT && pParse->pNewIndex ){ sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0); } @@ -151403,29 +152298,29 @@ static YYACTIONTYPE yy_reduce( break; case 220: /* uniqueflag ::= UNIQUE */ case 262: /* raisetype ::= ABORT */ yytestcase(yyruleno==262); -{yymsp[0].minor.yy96 = OE_Abort;} +{yymsp[0].minor.yy494 = OE_Abort;} break; case 221: /* uniqueflag ::= */ -{yymsp[1].minor.yy96 = OE_None;} +{yymsp[1].minor.yy494 = OE_None;} break; case 224: /* eidlist ::= eidlist COMMA nm collate sortorder */ { - yymsp[-4].minor.yy42 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy42, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy96, yymsp[0].minor.yy96); + yymsp[-4].minor.yy434 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy434, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy494, yymsp[0].minor.yy494); } break; case 225: /* eidlist ::= nm collate sortorder */ { - yymsp[-2].minor.yy42 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy96, yymsp[0].minor.yy96); /*A-overwrites-Y*/ + yymsp[-2].minor.yy434 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy494, yymsp[0].minor.yy494); /*A-overwrites-Y*/ } break; case 228: /* cmd ::= DROP INDEX ifexists fullname */ -{sqlite3DropIndex(pParse, yymsp[0].minor.yy167, yymsp[-1].minor.yy96);} +{sqlite3DropIndex(pParse, yymsp[0].minor.yy483, yymsp[-1].minor.yy494);} break; case 229: /* cmd ::= VACUUM vinto */ -{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy490);} +{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy524);} break; case 230: /* cmd ::= VACUUM nm vinto */ -{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy490);} +{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy524);} break; case 233: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} @@ -151447,51 +152342,51 @@ static YYACTIONTYPE yy_reduce( Token all; all.z = yymsp[-3].minor.yy0.z; all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy119, &all); + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy455, &all); } break; case 241: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ { - sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy96, yymsp[-4].minor.yy350.a, yymsp[-4].minor.yy350.b, yymsp[-2].minor.yy167, yymsp[0].minor.yy490, yymsp[-10].minor.yy96, yymsp[-8].minor.yy96); + sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy494, yymsp[-4].minor.yy90.a, yymsp[-4].minor.yy90.b, yymsp[-2].minor.yy483, yymsp[0].minor.yy524, yymsp[-10].minor.yy494, yymsp[-8].minor.yy494); yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ } break; case 242: /* trigger_time ::= BEFORE|AFTER */ -{ yymsp[0].minor.yy96 = yymsp[0].major; /*A-overwrites-X*/ } +{ yymsp[0].minor.yy494 = yymsp[0].major; /*A-overwrites-X*/ } break; case 243: /* trigger_time ::= INSTEAD OF */ -{ yymsp[-1].minor.yy96 = TK_INSTEAD;} +{ yymsp[-1].minor.yy494 = TK_INSTEAD;} break; case 244: /* trigger_time ::= */ -{ yymsp[1].minor.yy96 = TK_BEFORE; } +{ yymsp[1].minor.yy494 = TK_BEFORE; } break; case 245: /* trigger_event ::= DELETE|INSERT */ case 246: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==246); -{yymsp[0].minor.yy350.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy350.b = 0;} +{yymsp[0].minor.yy90.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy90.b = 0;} break; case 247: /* trigger_event ::= UPDATE OF idlist */ -{yymsp[-2].minor.yy350.a = TK_UPDATE; yymsp[-2].minor.yy350.b = yymsp[0].minor.yy336;} +{yymsp[-2].minor.yy90.a = TK_UPDATE; yymsp[-2].minor.yy90.b = yymsp[0].minor.yy62;} break; case 248: /* when_clause ::= */ case 267: /* key_opt ::= */ yytestcase(yyruleno==267); - case 309: /* filter_opt ::= */ yytestcase(yyruleno==309); -{ yymsp[1].minor.yy490 = 0; } + case 315: /* filter_opt ::= */ yytestcase(yyruleno==315); +{ yymsp[1].minor.yy524 = 0; } break; case 249: /* when_clause ::= WHEN expr */ case 268: /* key_opt ::= KEY expr */ yytestcase(yyruleno==268); -{ yymsp[-1].minor.yy490 = yymsp[0].minor.yy490; } +{ yymsp[-1].minor.yy524 = yymsp[0].minor.yy524; } break; case 250: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { - assert( yymsp[-2].minor.yy119!=0 ); - yymsp[-2].minor.yy119->pLast->pNext = yymsp[-1].minor.yy119; - yymsp[-2].minor.yy119->pLast = yymsp[-1].minor.yy119; + assert( yymsp[-2].minor.yy455!=0 ); + yymsp[-2].minor.yy455->pLast->pNext = yymsp[-1].minor.yy455; + yymsp[-2].minor.yy455->pLast = yymsp[-1].minor.yy455; } break; case 251: /* trigger_cmd_list ::= trigger_cmd SEMI */ { - assert( yymsp[-1].minor.yy119!=0 ); - yymsp[-1].minor.yy119->pLast = yymsp[-1].minor.yy119; + assert( yymsp[-1].minor.yy455!=0 ); + yymsp[-1].minor.yy455->pLast = yymsp[-1].minor.yy455; } break; case 252: /* trnm ::= nm DOT nm */ @@ -151517,58 +152412,58 @@ static YYACTIONTYPE yy_reduce( } break; case 255: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */ -{yylhsminor.yy119 = sqlite3TriggerUpdateStep(pParse, &yymsp[-5].minor.yy0, yymsp[-2].minor.yy42, yymsp[-1].minor.yy490, yymsp[-6].minor.yy96, yymsp[-7].minor.yy0.z, yymsp[0].minor.yy464);} - yymsp[-7].minor.yy119 = yylhsminor.yy119; +{yylhsminor.yy455 = sqlite3TriggerUpdateStep(pParse, &yymsp[-5].minor.yy0, yymsp[-2].minor.yy434, yymsp[-1].minor.yy524, yymsp[-6].minor.yy494, yymsp[-7].minor.yy0.z, yymsp[0].minor.yy294);} + yymsp[-7].minor.yy455 = yylhsminor.yy455; break; case 256: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ { - yylhsminor.yy119 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy336,yymsp[-2].minor.yy423,yymsp[-6].minor.yy96,yymsp[-1].minor.yy266,yymsp[-7].minor.yy464,yymsp[0].minor.yy464);/*yylhsminor.yy119-overwrites-yymsp[-6].minor.yy96*/ + yylhsminor.yy455 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy62,yymsp[-2].minor.yy457,yymsp[-6].minor.yy494,yymsp[-1].minor.yy136,yymsp[-7].minor.yy294,yymsp[0].minor.yy294);/*yylhsminor.yy455-overwrites-yymsp[-6].minor.yy494*/ } - yymsp[-7].minor.yy119 = yylhsminor.yy119; + yymsp[-7].minor.yy455 = yylhsminor.yy455; break; case 257: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ -{yylhsminor.yy119 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy490, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy464);} - yymsp[-5].minor.yy119 = yylhsminor.yy119; +{yylhsminor.yy455 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy524, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy294);} + yymsp[-5].minor.yy455 = yylhsminor.yy455; break; case 258: /* trigger_cmd ::= scanpt select scanpt */ -{yylhsminor.yy119 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy423, yymsp[-2].minor.yy464, yymsp[0].minor.yy464); /*yylhsminor.yy119-overwrites-yymsp[-1].minor.yy423*/} - yymsp[-2].minor.yy119 = yylhsminor.yy119; +{yylhsminor.yy455 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy457, yymsp[-2].minor.yy294, yymsp[0].minor.yy294); /*yylhsminor.yy455-overwrites-yymsp[-1].minor.yy457*/} + yymsp[-2].minor.yy455 = yylhsminor.yy455; break; case 259: /* expr ::= RAISE LP IGNORE RP */ { - yymsp[-3].minor.yy490 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); - if( yymsp[-3].minor.yy490 ){ - yymsp[-3].minor.yy490->affinity = OE_Ignore; + yymsp[-3].minor.yy524 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); + if( yymsp[-3].minor.yy524 ){ + yymsp[-3].minor.yy524->affinity = OE_Ignore; } } break; case 260: /* expr ::= RAISE LP raisetype COMMA nm RP */ { - yymsp[-5].minor.yy490 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); - if( yymsp[-5].minor.yy490 ) { - yymsp[-5].minor.yy490->affinity = (char)yymsp[-3].minor.yy96; + yymsp[-5].minor.yy524 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); + if( yymsp[-5].minor.yy524 ) { + yymsp[-5].minor.yy524->affinity = (char)yymsp[-3].minor.yy494; } } break; case 261: /* raisetype ::= ROLLBACK */ -{yymsp[0].minor.yy96 = OE_Rollback;} +{yymsp[0].minor.yy494 = OE_Rollback;} break; case 263: /* raisetype ::= FAIL */ -{yymsp[0].minor.yy96 = OE_Fail;} +{yymsp[0].minor.yy494 = OE_Fail;} break; case 264: /* cmd ::= DROP TRIGGER ifexists fullname */ { - sqlite3DropTrigger(pParse,yymsp[0].minor.yy167,yymsp[-1].minor.yy96); + sqlite3DropTrigger(pParse,yymsp[0].minor.yy483,yymsp[-1].minor.yy494); } break; case 265: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { - sqlite3Attach(pParse, yymsp[-3].minor.yy490, yymsp[-1].minor.yy490, yymsp[0].minor.yy490); + sqlite3Attach(pParse, yymsp[-3].minor.yy524, yymsp[-1].minor.yy524, yymsp[0].minor.yy524); } break; case 266: /* cmd ::= DETACH database_kw_opt expr */ { - sqlite3Detach(pParse, yymsp[0].minor.yy490); + sqlite3Detach(pParse, yymsp[0].minor.yy524); } break; case 269: /* cmd ::= REINDEX */ @@ -151585,7 +152480,7 @@ static YYACTIONTYPE yy_reduce( break; case 273: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy167,&yymsp[0].minor.yy0); + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy483,&yymsp[0].minor.yy0); } break; case 274: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ @@ -151597,12 +152492,12 @@ static YYACTIONTYPE yy_reduce( case 275: /* add_column_fullname ::= fullname */ { disableLookaside(pParse); - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy167); + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy483); } break; case 276: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ { - sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy167, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); + sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy483, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } break; case 277: /* cmd ::= create_vtab */ @@ -151613,7 +152508,7 @@ static YYACTIONTYPE yy_reduce( break; case 279: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ { - sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy96); + sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy494); } break; case 280: /* vtabarg ::= */ @@ -151626,182 +152521,204 @@ static YYACTIONTYPE yy_reduce( break; case 284: /* with ::= WITH wqlist */ case 285: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==285); -{ sqlite3WithPush(pParse, yymsp[0].minor.yy499, 1); } +{ sqlite3WithPush(pParse, yymsp[0].minor.yy59, 1); } break; case 286: /* wqlist ::= nm eidlist_opt AS LP select RP */ { - yymsp[-5].minor.yy499 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy42, yymsp[-1].minor.yy423); /*A-overwrites-X*/ + yymsp[-5].minor.yy59 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy434, yymsp[-1].minor.yy457); /*A-overwrites-X*/ } break; case 287: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ { - yymsp[-7].minor.yy499 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy499, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy42, yymsp[-1].minor.yy423); + yymsp[-7].minor.yy59 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy59, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy434, yymsp[-1].minor.yy457); } break; case 288: /* windowdefn_list ::= windowdefn */ -{ yylhsminor.yy147 = yymsp[0].minor.yy147; } - yymsp[0].minor.yy147 = yylhsminor.yy147; +{ yylhsminor.yy295 = yymsp[0].minor.yy295; } + yymsp[0].minor.yy295 = yylhsminor.yy295; break; case 289: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ { - assert( yymsp[0].minor.yy147!=0 ); - yymsp[0].minor.yy147->pNextWin = yymsp[-2].minor.yy147; - yylhsminor.yy147 = yymsp[0].minor.yy147; + assert( yymsp[0].minor.yy295!=0 ); + sqlite3WindowChain(pParse, yymsp[0].minor.yy295, yymsp[-2].minor.yy295); + yymsp[0].minor.yy295->pNextWin = yymsp[-2].minor.yy295; + yylhsminor.yy295 = yymsp[0].minor.yy295; } - yymsp[-2].minor.yy147 = yylhsminor.yy147; + yymsp[-2].minor.yy295 = yylhsminor.yy295; break; - case 290: /* windowdefn ::= nm AS window */ + case 290: /* windowdefn ::= nm AS LP window RP */ { - if( ALWAYS(yymsp[0].minor.yy147) ){ - yymsp[0].minor.yy147->zName = sqlite3DbStrNDup(pParse->db, yymsp[-2].minor.yy0.z, yymsp[-2].minor.yy0.n); + if( ALWAYS(yymsp[-1].minor.yy295) ){ + yymsp[-1].minor.yy295->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n); } - yylhsminor.yy147 = yymsp[0].minor.yy147; + yylhsminor.yy295 = yymsp[-1].minor.yy295; } - yymsp[-2].minor.yy147 = yylhsminor.yy147; + yymsp[-4].minor.yy295 = yylhsminor.yy295; break; - case 291: /* window ::= LP part_opt orderby_opt frame_opt RP */ + case 291: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */ { - yymsp[-4].minor.yy147 = yymsp[-1].minor.yy147; - if( ALWAYS(yymsp[-4].minor.yy147) ){ - yymsp[-4].minor.yy147->pPartition = yymsp[-3].minor.yy42; - yymsp[-4].minor.yy147->pOrderBy = yymsp[-2].minor.yy42; - } + yymsp[-4].minor.yy295 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy295, yymsp[-2].minor.yy434, yymsp[-1].minor.yy434, 0); } break; - case 292: /* part_opt ::= PARTITION BY nexprlist */ -{ yymsp[-2].minor.yy42 = yymsp[0].minor.yy42; } - break; - case 293: /* part_opt ::= */ -{ yymsp[1].minor.yy42 = 0; } - break; - case 294: /* frame_opt ::= */ -{ - yymsp[1].minor.yy147 = sqlite3WindowAlloc(pParse, TK_RANGE, TK_UNBOUNDED, 0, TK_CURRENT, 0); -} - break; - case 295: /* frame_opt ::= range_or_rows frame_bound_s */ -{ - yylhsminor.yy147 = sqlite3WindowAlloc(pParse, yymsp[-1].minor.yy96, yymsp[0].minor.yy317.eType, yymsp[0].minor.yy317.pExpr, TK_CURRENT, 0); -} - yymsp[-1].minor.yy147 = yylhsminor.yy147; - break; - case 296: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e */ -{ - yylhsminor.yy147 = sqlite3WindowAlloc(pParse, yymsp[-4].minor.yy96, yymsp[-2].minor.yy317.eType, yymsp[-2].minor.yy317.pExpr, yymsp[0].minor.yy317.eType, yymsp[0].minor.yy317.pExpr); -} - yymsp[-4].minor.yy147 = yylhsminor.yy147; - break; - case 297: /* range_or_rows ::= RANGE */ -{ yymsp[0].minor.yy96 = TK_RANGE; } - break; - case 298: /* range_or_rows ::= ROWS */ -{ yymsp[0].minor.yy96 = TK_ROWS; } - break; - case 299: /* frame_bound_s ::= frame_bound */ - case 301: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==301); -{ yylhsminor.yy317 = yymsp[0].minor.yy317; } - yymsp[0].minor.yy317 = yylhsminor.yy317; - break; - case 300: /* frame_bound_s ::= UNBOUNDED PRECEDING */ - case 302: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==302); -{yymsp[-1].minor.yy317.eType = TK_UNBOUNDED; yymsp[-1].minor.yy317.pExpr = 0;} - break; - case 303: /* frame_bound ::= expr PRECEDING */ -{ yylhsminor.yy317.eType = TK_PRECEDING; yylhsminor.yy317.pExpr = yymsp[-1].minor.yy490; } - yymsp[-1].minor.yy317 = yylhsminor.yy317; - break; - case 304: /* frame_bound ::= CURRENT ROW */ -{ yymsp[-1].minor.yy317.eType = TK_CURRENT ; yymsp[-1].minor.yy317.pExpr = 0; } - break; - case 305: /* frame_bound ::= expr FOLLOWING */ -{ yylhsminor.yy317.eType = TK_FOLLOWING; yylhsminor.yy317.pExpr = yymsp[-1].minor.yy490; } - yymsp[-1].minor.yy317 = yylhsminor.yy317; - break; - case 306: /* window_clause ::= WINDOW windowdefn_list */ -{ yymsp[-1].minor.yy147 = yymsp[0].minor.yy147; } - break; - case 307: /* over_clause ::= filter_opt OVER window */ + case 292: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ { - yylhsminor.yy147 = yymsp[0].minor.yy147; - assert( yylhsminor.yy147!=0 ); - yylhsminor.yy147->pFilter = yymsp[-2].minor.yy490; + yylhsminor.yy295 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy295, yymsp[-2].minor.yy434, yymsp[-1].minor.yy434, &yymsp[-5].minor.yy0); } - yymsp[-2].minor.yy147 = yylhsminor.yy147; + yymsp[-5].minor.yy295 = yylhsminor.yy295; break; - case 308: /* over_clause ::= filter_opt OVER nm */ + case 293: /* window ::= ORDER BY sortlist frame_opt */ { - yylhsminor.yy147 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( yylhsminor.yy147 ){ - yylhsminor.yy147->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n); - yylhsminor.yy147->pFilter = yymsp[-2].minor.yy490; + yymsp[-3].minor.yy295 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy295, 0, yymsp[-1].minor.yy434, 0); +} + break; + case 294: /* window ::= nm ORDER BY sortlist frame_opt */ +{ + yylhsminor.yy295 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy295, 0, yymsp[-1].minor.yy434, &yymsp[-4].minor.yy0); +} + yymsp[-4].minor.yy295 = yylhsminor.yy295; + break; + case 295: /* window ::= frame_opt */ +{ + yylhsminor.yy295 = yymsp[0].minor.yy295; +} + yymsp[0].minor.yy295 = yylhsminor.yy295; + break; + case 296: /* window ::= nm frame_opt */ +{ + yylhsminor.yy295 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy295, 0, 0, &yymsp[-1].minor.yy0); +} + yymsp[-1].minor.yy295 = yylhsminor.yy295; + break; + case 297: /* frame_opt ::= */ +{ + yymsp[1].minor.yy295 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0); +} + break; + case 298: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ +{ + yylhsminor.yy295 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy494, yymsp[-1].minor.yy201.eType, yymsp[-1].minor.yy201.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy238); +} + yymsp[-2].minor.yy295 = yylhsminor.yy295; + break; + case 299: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ +{ + yylhsminor.yy295 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy494, yymsp[-3].minor.yy201.eType, yymsp[-3].minor.yy201.pExpr, yymsp[-1].minor.yy201.eType, yymsp[-1].minor.yy201.pExpr, yymsp[0].minor.yy238); +} + yymsp[-5].minor.yy295 = yylhsminor.yy295; + break; + case 301: /* frame_bound_s ::= frame_bound */ + case 303: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==303); +{yylhsminor.yy201 = yymsp[0].minor.yy201;} + yymsp[0].minor.yy201 = yylhsminor.yy201; + break; + case 302: /* frame_bound_s ::= UNBOUNDED PRECEDING */ + case 304: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==304); + case 306: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==306); +{yylhsminor.yy201.eType = yymsp[-1].major; yylhsminor.yy201.pExpr = 0;} + yymsp[-1].minor.yy201 = yylhsminor.yy201; + break; + case 305: /* frame_bound ::= expr PRECEDING|FOLLOWING */ +{yylhsminor.yy201.eType = yymsp[0].major; yylhsminor.yy201.pExpr = yymsp[-1].minor.yy524;} + yymsp[-1].minor.yy201 = yylhsminor.yy201; + break; + case 307: /* frame_exclude_opt ::= */ +{yymsp[1].minor.yy238 = 0;} + break; + case 308: /* frame_exclude_opt ::= EXCLUDE frame_exclude */ +{yymsp[-1].minor.yy238 = yymsp[0].minor.yy238;} + break; + case 309: /* frame_exclude ::= NO OTHERS */ + case 310: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==310); +{yymsp[-1].minor.yy238 = yymsp[-1].major; /*A-overwrites-X*/} + break; + case 311: /* frame_exclude ::= GROUP|TIES */ +{yymsp[0].minor.yy238 = yymsp[0].major; /*A-overwrites-X*/} + break; + case 312: /* window_clause ::= WINDOW windowdefn_list */ +{ yymsp[-1].minor.yy295 = yymsp[0].minor.yy295; } + break; + case 313: /* over_clause ::= filter_opt OVER LP window RP */ +{ + yylhsminor.yy295 = yymsp[-1].minor.yy295; + assert( yylhsminor.yy295!=0 ); + yylhsminor.yy295->pFilter = yymsp[-4].minor.yy524; +} + yymsp[-4].minor.yy295 = yylhsminor.yy295; + break; + case 314: /* over_clause ::= filter_opt OVER nm */ +{ + yylhsminor.yy295 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); + if( yylhsminor.yy295 ){ + yylhsminor.yy295->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n); + yylhsminor.yy295->pFilter = yymsp[-2].minor.yy524; }else{ - sqlite3ExprDelete(pParse->db, yymsp[-2].minor.yy490); + sqlite3ExprDelete(pParse->db, yymsp[-2].minor.yy524); } } - yymsp[-2].minor.yy147 = yylhsminor.yy147; + yymsp[-2].minor.yy295 = yylhsminor.yy295; break; - case 310: /* filter_opt ::= FILTER LP WHERE expr RP */ -{ yymsp[-4].minor.yy490 = yymsp[-1].minor.yy490; } + case 316: /* filter_opt ::= FILTER LP WHERE expr RP */ +{ yymsp[-4].minor.yy524 = yymsp[-1].minor.yy524; } break; default: - /* (311) input ::= cmdlist */ yytestcase(yyruleno==311); - /* (312) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==312); - /* (313) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=313); - /* (314) ecmd ::= SEMI */ yytestcase(yyruleno==314); - /* (315) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==315); - /* (316) ecmd ::= explain cmdx */ yytestcase(yyruleno==316); - /* (317) trans_opt ::= */ yytestcase(yyruleno==317); - /* (318) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==318); - /* (319) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==319); - /* (320) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==320); - /* (321) savepoint_opt ::= */ yytestcase(yyruleno==321); - /* (322) cmd ::= create_table create_table_args */ yytestcase(yyruleno==322); - /* (323) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==323); - /* (324) columnlist ::= columnname carglist */ yytestcase(yyruleno==324); - /* (325) nm ::= ID|INDEXED */ yytestcase(yyruleno==325); - /* (326) nm ::= STRING */ yytestcase(yyruleno==326); - /* (327) nm ::= JOIN_KW */ yytestcase(yyruleno==327); - /* (328) typetoken ::= typename */ yytestcase(yyruleno==328); - /* (329) typename ::= ID|STRING */ yytestcase(yyruleno==329); - /* (330) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=330); - /* (331) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=331); - /* (332) carglist ::= carglist ccons */ yytestcase(yyruleno==332); - /* (333) carglist ::= */ yytestcase(yyruleno==333); - /* (334) ccons ::= NULL onconf */ yytestcase(yyruleno==334); - /* (335) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==335); - /* (336) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==336); - /* (337) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=337); - /* (338) tconscomma ::= */ yytestcase(yyruleno==338); - /* (339) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=339); - /* (340) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=340); - /* (341) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=341); - /* (342) oneselect ::= values */ yytestcase(yyruleno==342); - /* (343) sclp ::= selcollist COMMA */ yytestcase(yyruleno==343); - /* (344) as ::= ID|STRING */ yytestcase(yyruleno==344); - /* (345) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=345); - /* (346) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==346); - /* (347) exprlist ::= nexprlist */ yytestcase(yyruleno==347); - /* (348) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=348); - /* (349) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=349); - /* (350) nmnum ::= ON */ yytestcase(yyruleno==350); - /* (351) nmnum ::= DELETE */ yytestcase(yyruleno==351); - /* (352) nmnum ::= DEFAULT */ yytestcase(yyruleno==352); - /* (353) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==353); - /* (354) foreach_clause ::= */ yytestcase(yyruleno==354); - /* (355) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==355); - /* (356) trnm ::= nm */ yytestcase(yyruleno==356); - /* (357) tridxby ::= */ yytestcase(yyruleno==357); - /* (358) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==358); - /* (359) database_kw_opt ::= */ yytestcase(yyruleno==359); - /* (360) kwcolumn_opt ::= */ yytestcase(yyruleno==360); - /* (361) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==361); - /* (362) vtabarglist ::= vtabarg */ yytestcase(yyruleno==362); - /* (363) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==363); - /* (364) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==364); - /* (365) anylist ::= */ yytestcase(yyruleno==365); - /* (366) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==366); - /* (367) anylist ::= anylist ANY */ yytestcase(yyruleno==367); - /* (368) with ::= */ yytestcase(yyruleno==368); + /* (317) input ::= cmdlist */ yytestcase(yyruleno==317); + /* (318) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==318); + /* (319) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=319); + /* (320) ecmd ::= SEMI */ yytestcase(yyruleno==320); + /* (321) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==321); + /* (322) ecmd ::= explain cmdx */ yytestcase(yyruleno==322); + /* (323) trans_opt ::= */ yytestcase(yyruleno==323); + /* (324) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==324); + /* (325) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==325); + /* (326) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==326); + /* (327) savepoint_opt ::= */ yytestcase(yyruleno==327); + /* (328) cmd ::= create_table create_table_args */ yytestcase(yyruleno==328); + /* (329) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==329); + /* (330) columnlist ::= columnname carglist */ yytestcase(yyruleno==330); + /* (331) nm ::= ID|INDEXED */ yytestcase(yyruleno==331); + /* (332) nm ::= STRING */ yytestcase(yyruleno==332); + /* (333) nm ::= JOIN_KW */ yytestcase(yyruleno==333); + /* (334) typetoken ::= typename */ yytestcase(yyruleno==334); + /* (335) typename ::= ID|STRING */ yytestcase(yyruleno==335); + /* (336) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=336); + /* (337) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=337); + /* (338) carglist ::= carglist ccons */ yytestcase(yyruleno==338); + /* (339) carglist ::= */ yytestcase(yyruleno==339); + /* (340) ccons ::= NULL onconf */ yytestcase(yyruleno==340); + /* (341) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==341); + /* (342) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==342); + /* (343) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=343); + /* (344) tconscomma ::= */ yytestcase(yyruleno==344); + /* (345) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=345); + /* (346) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=346); + /* (347) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=347); + /* (348) oneselect ::= values */ yytestcase(yyruleno==348); + /* (349) sclp ::= selcollist COMMA */ yytestcase(yyruleno==349); + /* (350) as ::= ID|STRING */ yytestcase(yyruleno==350); + /* (351) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=351); + /* (352) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==352); + /* (353) exprlist ::= nexprlist */ yytestcase(yyruleno==353); + /* (354) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=354); + /* (355) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=355); + /* (356) nmnum ::= ON */ yytestcase(yyruleno==356); + /* (357) nmnum ::= DELETE */ yytestcase(yyruleno==357); + /* (358) nmnum ::= DEFAULT */ yytestcase(yyruleno==358); + /* (359) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==359); + /* (360) foreach_clause ::= */ yytestcase(yyruleno==360); + /* (361) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==361); + /* (362) trnm ::= nm */ yytestcase(yyruleno==362); + /* (363) tridxby ::= */ yytestcase(yyruleno==363); + /* (364) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==364); + /* (365) database_kw_opt ::= */ yytestcase(yyruleno==365); + /* (366) kwcolumn_opt ::= */ yytestcase(yyruleno==366); + /* (367) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==367); + /* (368) vtabarglist ::= vtabarg */ yytestcase(yyruleno==368); + /* (369) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==369); + /* (370) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==370); + /* (371) anylist ::= */ yytestcase(yyruleno==371); + /* (372) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==372); + /* (373) anylist ::= anylist ANY */ yytestcase(yyruleno==373); + /* (374) with ::= */ yytestcase(yyruleno==374); break; /********** End reduce actions ************************************************/ }; @@ -152264,144 +153181,144 @@ const unsigned char ebcdicToAscii[] = { ** is substantially reduced. This is important for embedded applications ** on platforms with limited memory. */ -/* Hash score: 208 */ -/* zKWText[] encodes 923 bytes of keyword text in 614 bytes */ +/* Hash score: 214 */ +/* zKWText[] encodes 950 bytes of keyword text in 629 bytes */ /* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */ -/* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */ -/* XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY */ -/* UNIQUERYWITHOUTERELEASEATTACHAVINGROUPDATEBEGINNERANGEBETWEEN */ -/* OTHINGLOBYCASCADELETECASECOLLATECREATECURRENT_DATEDETACH */ -/* IMMEDIATEJOINSERTLIKEMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMIT */ -/* WHENOTNULLWHERECURSIVEAFTERENAMEANDEFAULTAUTOINCREMENTCAST */ -/* COLUMNCOMMITCONFLICTCROSSCURRENT_TIMESTAMPARTITIONDEFERRED */ -/* ISTINCTDROPRECEDINGFAILFILTEREPLACEFOLLOWINGFROMFULLIFISNULL */ -/* ORDERESTRICTOVERIGHTROLLBACKROWSUNBOUNDEDUNIONUSINGVACUUMVIEW */ -/* INDOWINITIALLYPRIMARY */ -static const char zKWText[613] = { +/* ABLEFTHENDEFERRABLELSEXCLUDELETEMPORARYCONSTRAINTERSECTIES */ +/* AVEPOINTOFFSETRANSACTIONATURALTERAISEXCEPTRIGGEREFERENCES */ +/* UNIQUERYWITHOUTERELEASEXCLUSIVEXISTSATTACHAVINGLOBEGINNERANGE */ +/* BETWEENOTHINGROUPSCASCADETACHCASECOLLATECREATECURRENT_DATE */ +/* IMMEDIATEJOINSERTLIKEMATCHPLANALYZEPRAGMABORTUPDATEVALUES */ +/* VIRTUALIMITWHENOTNULLWHERECURSIVEAFTERENAMEANDEFAULT */ +/* AUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCROSSCURRENT_TIMESTAMP */ +/* ARTITIONDEFERREDISTINCTDROPRECEDINGFAILFILTEREPLACEFOLLOWING */ +/* FROMFULLIFISNULLORDERESTRICTOTHERSOVERIGHTROLLBACKROWS */ +/* UNBOUNDEDUNIONUSINGVACUUMVIEWINDOWBYINITIALLYPRIMARY */ +static const char zKWText[628] = { 'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H', 'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G', 'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A', 'S','E','L','E','C','T','A','B','L','E','F','T','H','E','N','D','E','F', - 'E','R','R','A','B','L','E','L','S','E','X','C','E','P','T','R','A','N', - 'S','A','C','T','I','O','N','A','T','U','R','A','L','T','E','R','A','I', - 'S','E','X','C','L','U','S','I','V','E','X','I','S','T','S','A','V','E', - 'P','O','I','N','T','E','R','S','E','C','T','R','I','G','G','E','R','E', - 'F','E','R','E','N','C','E','S','C','O','N','S','T','R','A','I','N','T', - 'O','F','F','S','E','T','E','M','P','O','R','A','R','Y','U','N','I','Q', - 'U','E','R','Y','W','I','T','H','O','U','T','E','R','E','L','E','A','S', - 'E','A','T','T','A','C','H','A','V','I','N','G','R','O','U','P','D','A', - 'T','E','B','E','G','I','N','N','E','R','A','N','G','E','B','E','T','W', - 'E','E','N','O','T','H','I','N','G','L','O','B','Y','C','A','S','C','A', - 'D','E','L','E','T','E','C','A','S','E','C','O','L','L','A','T','E','C', - 'R','E','A','T','E','C','U','R','R','E','N','T','_','D','A','T','E','D', - 'E','T','A','C','H','I','M','M','E','D','I','A','T','E','J','O','I','N', - 'S','E','R','T','L','I','K','E','M','A','T','C','H','P','L','A','N','A', - 'L','Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U', - 'E','S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','O', - 'T','N','U','L','L','W','H','E','R','E','C','U','R','S','I','V','E','A', - 'F','T','E','R','E','N','A','M','E','A','N','D','E','F','A','U','L','T', - 'A','U','T','O','I','N','C','R','E','M','E','N','T','C','A','S','T','C', - 'O','L','U','M','N','C','O','M','M','I','T','C','O','N','F','L','I','C', - 'T','C','R','O','S','S','C','U','R','R','E','N','T','_','T','I','M','E', - 'S','T','A','M','P','A','R','T','I','T','I','O','N','D','E','F','E','R', - 'R','E','D','I','S','T','I','N','C','T','D','R','O','P','R','E','C','E', - 'D','I','N','G','F','A','I','L','F','I','L','T','E','R','E','P','L','A', - 'C','E','F','O','L','L','O','W','I','N','G','F','R','O','M','F','U','L', - 'L','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S','T','R', - 'I','C','T','O','V','E','R','I','G','H','T','R','O','L','L','B','A','C', - 'K','R','O','W','S','U','N','B','O','U','N','D','E','D','U','N','I','O', - 'N','U','S','I','N','G','V','A','C','U','U','M','V','I','E','W','I','N', - 'D','O','W','I','N','I','T','I','A','L','L','Y','P','R','I','M','A','R', - 'Y', + 'E','R','R','A','B','L','E','L','S','E','X','C','L','U','D','E','L','E', + 'T','E','M','P','O','R','A','R','Y','C','O','N','S','T','R','A','I','N', + 'T','E','R','S','E','C','T','I','E','S','A','V','E','P','O','I','N','T', + 'O','F','F','S','E','T','R','A','N','S','A','C','T','I','O','N','A','T', + 'U','R','A','L','T','E','R','A','I','S','E','X','C','E','P','T','R','I', + 'G','G','E','R','E','F','E','R','E','N','C','E','S','U','N','I','Q','U', + 'E','R','Y','W','I','T','H','O','U','T','E','R','E','L','E','A','S','E', + 'X','C','L','U','S','I','V','E','X','I','S','T','S','A','T','T','A','C', + 'H','A','V','I','N','G','L','O','B','E','G','I','N','N','E','R','A','N', + 'G','E','B','E','T','W','E','E','N','O','T','H','I','N','G','R','O','U', + 'P','S','C','A','S','C','A','D','E','T','A','C','H','C','A','S','E','C', + 'O','L','L','A','T','E','C','R','E','A','T','E','C','U','R','R','E','N', + 'T','_','D','A','T','E','I','M','M','E','D','I','A','T','E','J','O','I', + 'N','S','E','R','T','L','I','K','E','M','A','T','C','H','P','L','A','N', + 'A','L','Y','Z','E','P','R','A','G','M','A','B','O','R','T','U','P','D', + 'A','T','E','V','A','L','U','E','S','V','I','R','T','U','A','L','I','M', + 'I','T','W','H','E','N','O','T','N','U','L','L','W','H','E','R','E','C', + 'U','R','S','I','V','E','A','F','T','E','R','E','N','A','M','E','A','N', + 'D','E','F','A','U','L','T','A','U','T','O','I','N','C','R','E','M','E', + 'N','T','C','A','S','T','C','O','L','U','M','N','C','O','M','M','I','T', + 'C','O','N','F','L','I','C','T','C','R','O','S','S','C','U','R','R','E', + 'N','T','_','T','I','M','E','S','T','A','M','P','A','R','T','I','T','I', + 'O','N','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T','D', + 'R','O','P','R','E','C','E','D','I','N','G','F','A','I','L','F','I','L', + 'T','E','R','E','P','L','A','C','E','F','O','L','L','O','W','I','N','G', + 'F','R','O','M','F','U','L','L','I','F','I','S','N','U','L','L','O','R', + 'D','E','R','E','S','T','R','I','C','T','O','T','H','E','R','S','O','V', + 'E','R','I','G','H','T','R','O','L','L','B','A','C','K','R','O','W','S', + 'U','N','B','O','U','N','D','E','D','U','N','I','O','N','U','S','I','N', + 'G','V','A','C','U','U','M','V','I','E','W','I','N','D','O','W','B','Y', + 'I','N','I','T','I','A','L','L','Y','P','R','I','M','A','R','Y', }; /* aKWHash[i] is the hash value for the i-th keyword */ static const unsigned char aKWHash[127] = { - 74, 109, 124, 72, 106, 45, 0, 0, 81, 0, 76, 61, 0, - 42, 12, 77, 15, 0, 123, 84, 54, 118, 125, 19, 0, 0, - 130, 0, 128, 121, 0, 22, 96, 0, 9, 0, 0, 115, 69, - 0, 67, 6, 0, 48, 93, 136, 0, 126, 104, 0, 0, 44, - 0, 107, 24, 0, 17, 0, 131, 53, 23, 0, 5, 62, 132, - 99, 0, 0, 135, 110, 60, 134, 57, 113, 55, 0, 94, 0, - 103, 26, 0, 102, 0, 0, 0, 98, 95, 100, 105, 117, 14, - 39, 116, 0, 80, 0, 133, 114, 92, 59, 0, 129, 79, 119, - 86, 46, 83, 0, 0, 97, 40, 122, 120, 0, 127, 0, 0, - 29, 0, 89, 87, 88, 0, 20, 85, 111, 56, + 75, 111, 127, 73, 108, 29, 0, 0, 83, 0, 77, 63, 0, + 37, 33, 78, 15, 0, 126, 86, 57, 120, 128, 19, 0, 0, + 133, 0, 131, 123, 0, 22, 98, 0, 9, 0, 0, 117, 71, + 0, 69, 6, 0, 49, 95, 140, 0, 129, 106, 0, 0, 54, + 0, 109, 24, 0, 17, 0, 134, 56, 23, 26, 5, 58, 135, + 101, 0, 0, 139, 112, 62, 138, 59, 115, 65, 0, 96, 0, + 105, 45, 0, 104, 0, 0, 0, 100, 97, 102, 107, 119, 14, + 31, 118, 0, 81, 0, 136, 116, 137, 61, 124, 132, 80, 121, + 88, 30, 85, 0, 0, 99, 35, 125, 122, 0, 130, 0, 0, + 41, 0, 91, 89, 90, 0, 20, 87, 113, 82, }; /* aKWNext[] forms the hash collision chain. If aKWHash[i]==0 ** then the i-th keyword has no more hash collisions. Otherwise, ** the next keyword with the same hash is aKWHash[i]-1. */ -static const unsigned char aKWNext[136] = { +static const unsigned char aKWNext[140] = { 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, - 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 33, 0, 21, 0, 0, 0, 0, 0, 50, - 0, 43, 3, 47, 0, 0, 32, 0, 0, 0, 0, 0, 0, - 0, 1, 64, 0, 0, 65, 0, 41, 0, 38, 0, 0, 0, - 0, 0, 49, 75, 0, 0, 30, 0, 58, 0, 0, 0, 31, - 63, 16, 34, 10, 0, 0, 0, 0, 0, 0, 0, 11, 70, - 91, 0, 0, 8, 0, 108, 0, 101, 28, 52, 68, 0, 112, - 0, 73, 51, 0, 90, 27, 37, 0, 71, 36, 82, 0, 35, - 66, 25, 18, 0, 0, 78, + 0, 0, 0, 21, 0, 0, 12, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 51, 28, 0, 0, 38, 0, 0, 0, 44, 0, 0, 0, 3, + 0, 0, 67, 1, 66, 0, 0, 0, 36, 0, 47, 0, 0, + 0, 0, 0, 48, 50, 76, 0, 0, 42, 0, 60, 0, 0, + 0, 43, 0, 16, 55, 10, 0, 0, 0, 0, 0, 0, 0, + 11, 72, 93, 0, 0, 8, 0, 110, 0, 103, 40, 53, 70, + 0, 114, 0, 74, 52, 0, 0, 92, 39, 46, 0, 68, 32, + 84, 0, 34, 27, 25, 18, 94, 0, 64, 79, }; /* aKWLen[i] is the length (in bytes) of the i-th keyword */ -static const unsigned char aKWLen[136] = { +static const unsigned char aKWLen[140] = { 7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6, - 7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6, - 11, 6, 2, 7, 5, 5, 9, 6, 9, 9, 7, 10, 10, - 4, 6, 2, 3, 9, 4, 2, 6, 5, 7, 4, 5, 7, - 6, 6, 5, 6, 5, 5, 5, 7, 7, 4, 2, 7, 3, - 6, 4, 7, 6, 12, 6, 9, 4, 6, 4, 5, 4, 7, - 6, 5, 6, 7, 5, 4, 7, 3, 2, 4, 5, 9, 5, - 6, 3, 7, 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, - 7, 9, 8, 8, 2, 4, 9, 4, 6, 7, 9, 4, 4, - 2, 6, 5, 8, 4, 5, 8, 4, 3, 9, 5, 5, 6, - 4, 6, 2, 9, 3, 7, + 7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 7, + 6, 9, 4, 2, 10, 9, 4, 9, 4, 6, 2, 3, 11, + 6, 2, 7, 5, 5, 6, 7, 10, 6, 5, 7, 4, 5, + 7, 9, 6, 6, 6, 4, 5, 5, 5, 7, 7, 6, 5, + 7, 3, 6, 4, 7, 6, 12, 9, 4, 6, 4, 5, 4, + 7, 6, 5, 6, 6, 7, 5, 4, 7, 3, 2, 4, 5, + 9, 5, 6, 3, 7, 13, 2, 2, 4, 6, 6, 8, 5, + 17, 12, 7, 9, 8, 8, 2, 4, 9, 4, 6, 7, 9, + 4, 4, 2, 6, 5, 8, 6, 4, 5, 8, 4, 3, 9, + 5, 5, 6, 4, 6, 2, 2, 9, 3, 7, }; /* aKWOffset[i] is the index into zKWText[] of the start of ** the text for the i-th keyword. */ -static const unsigned short int aKWOffset[136] = { +static const unsigned short int aKWOffset[140] = { 0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33, 36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81, - 86, 91, 95, 96, 101, 105, 109, 117, 122, 128, 136, 142, 152, - 159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 184, 188, 192, - 199, 204, 209, 212, 218, 221, 225, 230, 236, 242, 245, 247, 248, - 252, 258, 262, 269, 275, 287, 293, 302, 304, 310, 314, 319, 321, - 328, 333, 338, 344, 350, 355, 358, 358, 358, 361, 365, 368, 377, - 381, 387, 389, 396, 398, 400, 409, 413, 419, 425, 433, 438, 438, - 438, 454, 463, 470, 471, 478, 481, 490, 494, 499, 506, 515, 519, - 523, 525, 531, 535, 543, 546, 551, 559, 559, 563, 572, 577, 582, - 588, 591, 594, 597, 602, 606, + 86, 90, 90, 94, 99, 106, 114, 117, 123, 126, 126, 129, 131, + 136, 140, 141, 146, 150, 154, 159, 165, 175, 178, 183, 183, 187, + 191, 197, 205, 211, 216, 221, 224, 227, 231, 236, 242, 248, 248, + 254, 255, 259, 265, 269, 276, 282, 294, 303, 305, 311, 315, 320, + 322, 329, 334, 339, 345, 351, 357, 362, 365, 365, 365, 368, 372, + 375, 384, 388, 394, 396, 403, 405, 407, 416, 420, 426, 432, 440, + 445, 445, 445, 461, 470, 477, 478, 485, 488, 497, 501, 506, 513, + 522, 526, 530, 532, 538, 542, 550, 556, 559, 564, 572, 572, 576, + 585, 590, 595, 601, 604, 607, 610, 612, 617, 621, }; /* aKWCode[i] is the parser symbol code for the i-th keyword */ -static const unsigned char aKWCode[136] = { +static const unsigned char aKWCode[140] = { TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE, TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN, TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD, TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE, TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE, - TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW, - TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_SAVEPOINT, - TK_INTERSECT, TK_TRIGGER, TK_REFERENCES, TK_CONSTRAINT, TK_INTO, - TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP, - TK_OR, TK_UNIQUE, TK_QUERY, TK_WITHOUT, TK_WITH, - TK_JOIN_KW, TK_RELEASE, TK_ATTACH, TK_HAVING, TK_GROUP, - TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RANGE, TK_BETWEEN, - TK_NOTHING, TK_LIKE_KW, TK_BY, TK_CASCADE, TK_ASC, - TK_DELETE, TK_CASE, TK_COLLATE, TK_CREATE, TK_CTIME_KW, - TK_DETACH, TK_IMMEDIATE, TK_JOIN, TK_INSERT, TK_LIKE_KW, - TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, TK_ABORT, - TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN, TK_NOTNULL, - TK_NOT, TK_NO, TK_NULL, TK_WHERE, TK_RECURSIVE, - TK_AFTER, TK_RENAME, TK_AND, TK_DEFAULT, TK_AUTOINCR, - TK_TO, TK_IN, TK_CAST, TK_COLUMNKW, TK_COMMIT, - TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_CURRENT, - TK_PARTITION, TK_DEFERRED, TK_DISTINCT, TK_IS, TK_DROP, - TK_PRECEDING, TK_FAIL, TK_FILTER, TK_REPLACE, TK_FOLLOWING, - TK_FROM, TK_JOIN_KW, TK_IF, TK_ISNULL, TK_ORDER, - TK_RESTRICT, TK_OVER, TK_JOIN_KW, TK_ROLLBACK, TK_ROWS, - TK_ROW, TK_UNBOUNDED, TK_UNION, TK_USING, TK_VACUUM, - TK_VIEW, TK_WINDOW, TK_DO, TK_INITIALLY, TK_ALL, - TK_PRIMARY, + TK_EXCLUDE, TK_DELETE, TK_TEMP, TK_TEMP, TK_OR, + TK_CONSTRAINT, TK_INTERSECT, TK_TIES, TK_SAVEPOINT, TK_INTO, + TK_OFFSET, TK_OF, TK_SET, TK_TRANSACTION,TK_ACTION, + TK_ON, TK_JOIN_KW, TK_ALTER, TK_RAISE, TK_EXCEPT, + TK_TRIGGER, TK_REFERENCES, TK_UNIQUE, TK_QUERY, TK_WITHOUT, + TK_WITH, TK_JOIN_KW, TK_RELEASE, TK_EXCLUSIVE, TK_EXISTS, + TK_ATTACH, TK_HAVING, TK_LIKE_KW, TK_BEGIN, TK_JOIN_KW, + TK_RANGE, TK_BETWEEN, TK_NOTHING, TK_GROUPS, TK_GROUP, + TK_CASCADE, TK_ASC, TK_DETACH, TK_CASE, TK_COLLATE, + TK_CREATE, TK_CTIME_KW, TK_IMMEDIATE, TK_JOIN, TK_INSERT, + TK_LIKE_KW, TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, + TK_ABORT, TK_UPDATE, TK_VALUES, TK_VIRTUAL, TK_LIMIT, + TK_WHEN, TK_NOTNULL, TK_NOT, TK_NO, TK_NULL, + TK_WHERE, TK_RECURSIVE, TK_AFTER, TK_RENAME, TK_AND, + TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN, TK_CAST, + TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, + TK_CTIME_KW, TK_CURRENT, TK_PARTITION, TK_DEFERRED, TK_DISTINCT, + TK_IS, TK_DROP, TK_PRECEDING, TK_FAIL, TK_FILTER, + TK_REPLACE, TK_FOLLOWING, TK_FROM, TK_JOIN_KW, TK_IF, + TK_ISNULL, TK_ORDER, TK_RESTRICT, TK_OTHERS, TK_OVER, + TK_JOIN_KW, TK_ROLLBACK, TK_ROWS, TK_ROW, TK_UNBOUNDED, + TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_WINDOW, + TK_DO, TK_BY, TK_INITIALLY, TK_ALL, TK_PRIMARY, }; /* Check to see if z[0..n-1] is a keyword. If it is, write the ** parser symbol code for that keyword into *pType. Always @@ -152447,117 +153364,121 @@ static int keywordCode(const char *z, int n, int *pType){ testcase( i==22 ); /* END */ testcase( i==23 ); /* DEFERRABLE */ testcase( i==24 ); /* ELSE */ - testcase( i==25 ); /* EXCEPT */ - testcase( i==26 ); /* TRANSACTION */ - testcase( i==27 ); /* ACTION */ - testcase( i==28 ); /* ON */ - testcase( i==29 ); /* NATURAL */ - testcase( i==30 ); /* ALTER */ - testcase( i==31 ); /* RAISE */ - testcase( i==32 ); /* EXCLUSIVE */ - testcase( i==33 ); /* EXISTS */ - testcase( i==34 ); /* SAVEPOINT */ - testcase( i==35 ); /* INTERSECT */ - testcase( i==36 ); /* TRIGGER */ - testcase( i==37 ); /* REFERENCES */ - testcase( i==38 ); /* CONSTRAINT */ - testcase( i==39 ); /* INTO */ - testcase( i==40 ); /* OFFSET */ - testcase( i==41 ); /* OF */ - testcase( i==42 ); /* SET */ - testcase( i==43 ); /* TEMPORARY */ - testcase( i==44 ); /* TEMP */ - testcase( i==45 ); /* OR */ - testcase( i==46 ); /* UNIQUE */ - testcase( i==47 ); /* QUERY */ - testcase( i==48 ); /* WITHOUT */ - testcase( i==49 ); /* WITH */ - testcase( i==50 ); /* OUTER */ - testcase( i==51 ); /* RELEASE */ - testcase( i==52 ); /* ATTACH */ - testcase( i==53 ); /* HAVING */ - testcase( i==54 ); /* GROUP */ - testcase( i==55 ); /* UPDATE */ - testcase( i==56 ); /* BEGIN */ - testcase( i==57 ); /* INNER */ - testcase( i==58 ); /* RANGE */ - testcase( i==59 ); /* BETWEEN */ - testcase( i==60 ); /* NOTHING */ - testcase( i==61 ); /* GLOB */ - testcase( i==62 ); /* BY */ - testcase( i==63 ); /* CASCADE */ - testcase( i==64 ); /* ASC */ - testcase( i==65 ); /* DELETE */ - testcase( i==66 ); /* CASE */ - testcase( i==67 ); /* COLLATE */ - testcase( i==68 ); /* CREATE */ - testcase( i==69 ); /* CURRENT_DATE */ - testcase( i==70 ); /* DETACH */ - testcase( i==71 ); /* IMMEDIATE */ - testcase( i==72 ); /* JOIN */ - testcase( i==73 ); /* INSERT */ - testcase( i==74 ); /* LIKE */ - testcase( i==75 ); /* MATCH */ - testcase( i==76 ); /* PLAN */ - testcase( i==77 ); /* ANALYZE */ - testcase( i==78 ); /* PRAGMA */ - testcase( i==79 ); /* ABORT */ - testcase( i==80 ); /* VALUES */ - testcase( i==81 ); /* VIRTUAL */ - testcase( i==82 ); /* LIMIT */ - testcase( i==83 ); /* WHEN */ - testcase( i==84 ); /* NOTNULL */ - testcase( i==85 ); /* NOT */ - testcase( i==86 ); /* NO */ - testcase( i==87 ); /* NULL */ - testcase( i==88 ); /* WHERE */ - testcase( i==89 ); /* RECURSIVE */ - testcase( i==90 ); /* AFTER */ - testcase( i==91 ); /* RENAME */ - testcase( i==92 ); /* AND */ - testcase( i==93 ); /* DEFAULT */ - testcase( i==94 ); /* AUTOINCREMENT */ - testcase( i==95 ); /* TO */ - testcase( i==96 ); /* IN */ - testcase( i==97 ); /* CAST */ - testcase( i==98 ); /* COLUMN */ - testcase( i==99 ); /* COMMIT */ - testcase( i==100 ); /* CONFLICT */ - testcase( i==101 ); /* CROSS */ - testcase( i==102 ); /* CURRENT_TIMESTAMP */ - testcase( i==103 ); /* CURRENT_TIME */ - testcase( i==104 ); /* CURRENT */ - testcase( i==105 ); /* PARTITION */ - testcase( i==106 ); /* DEFERRED */ - testcase( i==107 ); /* DISTINCT */ - testcase( i==108 ); /* IS */ - testcase( i==109 ); /* DROP */ - testcase( i==110 ); /* PRECEDING */ - testcase( i==111 ); /* FAIL */ - testcase( i==112 ); /* FILTER */ - testcase( i==113 ); /* REPLACE */ - testcase( i==114 ); /* FOLLOWING */ - testcase( i==115 ); /* FROM */ - testcase( i==116 ); /* FULL */ - testcase( i==117 ); /* IF */ - testcase( i==118 ); /* ISNULL */ - testcase( i==119 ); /* ORDER */ - testcase( i==120 ); /* RESTRICT */ - testcase( i==121 ); /* OVER */ - testcase( i==122 ); /* RIGHT */ - testcase( i==123 ); /* ROLLBACK */ - testcase( i==124 ); /* ROWS */ - testcase( i==125 ); /* ROW */ - testcase( i==126 ); /* UNBOUNDED */ - testcase( i==127 ); /* UNION */ - testcase( i==128 ); /* USING */ - testcase( i==129 ); /* VACUUM */ - testcase( i==130 ); /* VIEW */ - testcase( i==131 ); /* WINDOW */ - testcase( i==132 ); /* DO */ - testcase( i==133 ); /* INITIALLY */ - testcase( i==134 ); /* ALL */ - testcase( i==135 ); /* PRIMARY */ + testcase( i==25 ); /* EXCLUDE */ + testcase( i==26 ); /* DELETE */ + testcase( i==27 ); /* TEMPORARY */ + testcase( i==28 ); /* TEMP */ + testcase( i==29 ); /* OR */ + testcase( i==30 ); /* CONSTRAINT */ + testcase( i==31 ); /* INTERSECT */ + testcase( i==32 ); /* TIES */ + testcase( i==33 ); /* SAVEPOINT */ + testcase( i==34 ); /* INTO */ + testcase( i==35 ); /* OFFSET */ + testcase( i==36 ); /* OF */ + testcase( i==37 ); /* SET */ + testcase( i==38 ); /* TRANSACTION */ + testcase( i==39 ); /* ACTION */ + testcase( i==40 ); /* ON */ + testcase( i==41 ); /* NATURAL */ + testcase( i==42 ); /* ALTER */ + testcase( i==43 ); /* RAISE */ + testcase( i==44 ); /* EXCEPT */ + testcase( i==45 ); /* TRIGGER */ + testcase( i==46 ); /* REFERENCES */ + testcase( i==47 ); /* UNIQUE */ + testcase( i==48 ); /* QUERY */ + testcase( i==49 ); /* WITHOUT */ + testcase( i==50 ); /* WITH */ + testcase( i==51 ); /* OUTER */ + testcase( i==52 ); /* RELEASE */ + testcase( i==53 ); /* EXCLUSIVE */ + testcase( i==54 ); /* EXISTS */ + testcase( i==55 ); /* ATTACH */ + testcase( i==56 ); /* HAVING */ + testcase( i==57 ); /* GLOB */ + testcase( i==58 ); /* BEGIN */ + testcase( i==59 ); /* INNER */ + testcase( i==60 ); /* RANGE */ + testcase( i==61 ); /* BETWEEN */ + testcase( i==62 ); /* NOTHING */ + testcase( i==63 ); /* GROUPS */ + testcase( i==64 ); /* GROUP */ + testcase( i==65 ); /* CASCADE */ + testcase( i==66 ); /* ASC */ + testcase( i==67 ); /* DETACH */ + testcase( i==68 ); /* CASE */ + testcase( i==69 ); /* COLLATE */ + testcase( i==70 ); /* CREATE */ + testcase( i==71 ); /* CURRENT_DATE */ + testcase( i==72 ); /* IMMEDIATE */ + testcase( i==73 ); /* JOIN */ + testcase( i==74 ); /* INSERT */ + testcase( i==75 ); /* LIKE */ + testcase( i==76 ); /* MATCH */ + testcase( i==77 ); /* PLAN */ + testcase( i==78 ); /* ANALYZE */ + testcase( i==79 ); /* PRAGMA */ + testcase( i==80 ); /* ABORT */ + testcase( i==81 ); /* UPDATE */ + testcase( i==82 ); /* VALUES */ + testcase( i==83 ); /* VIRTUAL */ + testcase( i==84 ); /* LIMIT */ + testcase( i==85 ); /* WHEN */ + testcase( i==86 ); /* NOTNULL */ + testcase( i==87 ); /* NOT */ + testcase( i==88 ); /* NO */ + testcase( i==89 ); /* NULL */ + testcase( i==90 ); /* WHERE */ + testcase( i==91 ); /* RECURSIVE */ + testcase( i==92 ); /* AFTER */ + testcase( i==93 ); /* RENAME */ + testcase( i==94 ); /* AND */ + testcase( i==95 ); /* DEFAULT */ + testcase( i==96 ); /* AUTOINCREMENT */ + testcase( i==97 ); /* TO */ + testcase( i==98 ); /* IN */ + testcase( i==99 ); /* CAST */ + testcase( i==100 ); /* COLUMN */ + testcase( i==101 ); /* COMMIT */ + testcase( i==102 ); /* CONFLICT */ + testcase( i==103 ); /* CROSS */ + testcase( i==104 ); /* CURRENT_TIMESTAMP */ + testcase( i==105 ); /* CURRENT_TIME */ + testcase( i==106 ); /* CURRENT */ + testcase( i==107 ); /* PARTITION */ + testcase( i==108 ); /* DEFERRED */ + testcase( i==109 ); /* DISTINCT */ + testcase( i==110 ); /* IS */ + testcase( i==111 ); /* DROP */ + testcase( i==112 ); /* PRECEDING */ + testcase( i==113 ); /* FAIL */ + testcase( i==114 ); /* FILTER */ + testcase( i==115 ); /* REPLACE */ + testcase( i==116 ); /* FOLLOWING */ + testcase( i==117 ); /* FROM */ + testcase( i==118 ); /* FULL */ + testcase( i==119 ); /* IF */ + testcase( i==120 ); /* ISNULL */ + testcase( i==121 ); /* ORDER */ + testcase( i==122 ); /* RESTRICT */ + testcase( i==123 ); /* OTHERS */ + testcase( i==124 ); /* OVER */ + testcase( i==125 ); /* RIGHT */ + testcase( i==126 ); /* ROLLBACK */ + testcase( i==127 ); /* ROWS */ + testcase( i==128 ); /* ROW */ + testcase( i==129 ); /* UNBOUNDED */ + testcase( i==130 ); /* UNION */ + testcase( i==131 ); /* USING */ + testcase( i==132 ); /* VACUUM */ + testcase( i==133 ); /* VIEW */ + testcase( i==134 ); /* WINDOW */ + testcase( i==135 ); /* DO */ + testcase( i==136 ); /* BY */ + testcase( i==137 ); /* INITIALLY */ + testcase( i==138 ); /* ALL */ + testcase( i==139 ); /* PRIMARY */ *pType = aKWCode[i]; break; } @@ -152569,7 +153490,7 @@ SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char *z, int n){ keywordCode((char*)z, n, &id); return id; } -#define SQLITE_N_KEYWORD 136 +#define SQLITE_N_KEYWORD 140 SQLITE_API int sqlite3_keyword_name(int i,const char **pzName,int *pnName){ if( i<0 || i>=SQLITE_N_KEYWORD ) return SQLITE_ERROR; *pzName = zKWText + aKWOffset[i]; @@ -153002,6 +153923,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr #ifdef sqlite3Parser_ENGINEALWAYSONSTACK yyParser sEngine; /* Space to hold the Lemon-generated Parser object */ #endif + VVA_ONLY( u8 startedWithOom = db->mallocFailed ); assert( zSql!=0 ); mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; @@ -153033,6 +153955,8 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr assert( pParse->pNewTrigger==0 ); assert( pParse->nVar==0 ); assert( pParse->pVList==0 ); + pParse->pParentParse = db->pParse; + db->pParse = pParse; while( 1 ){ n = sqlite3GetToken((u8*)zSql, &tokenType); mxSqlLen -= n; @@ -153089,7 +154013,8 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr sqlite3Parser(pEngine, tokenType, pParse->sLastToken); lastTokenParsed = tokenType; zSql += n; - if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break; + assert( db->mallocFailed==0 || pParse->rc!=SQLITE_OK || startedWithOom ); + if( pParse->rc!=SQLITE_OK ) break; } assert( nErr==0 ); #ifdef YYTRACKMAXSTACKDEPTH @@ -153157,6 +154082,8 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr pParse->pZombieTab = p->pNextZombie; sqlite3DeleteTable(db, p); } + db->pParse = pParse->pParentParse; + pParse->pParentParse = 0; assert( nErr==0 || pParse->rc!=SQLITE_OK ); return nErr; } @@ -154393,7 +155320,7 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ pStart = 0; }else if( pBuf==0 ){ sqlite3BeginBenignMalloc(); - pStart = sqlite3Malloc( sz*cnt ); /* IMP: R-61949-35727 */ + pStart = sqlite3Malloc( sz*(sqlite3_int64)cnt ); /* IMP: R-61949-35727 */ sqlite3EndBenignMalloc(); if( pStart ) cnt = sqlite3MallocSize(pStart)/sz; }else{ @@ -154531,6 +155458,8 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){ { SQLITE_DBCONFIG_TRIGGER_EQP, SQLITE_TriggerEQP }, { SQLITE_DBCONFIG_RESET_DATABASE, SQLITE_ResetDatabase }, { SQLITE_DBCONFIG_DEFENSIVE, SQLITE_Defensive }, + { SQLITE_DBCONFIG_WRITABLE_SCHEMA, SQLITE_WriteSchema| + SQLITE_NoSchemaError }, }; unsigned int i; rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ @@ -161199,7 +162128,7 @@ static int fts3ScanInteriorNode( zCsr += fts3GetVarint32(zCsr, &nSuffix); assert( nPrefix>=0 && nSuffix>=0 ); - if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr ){ + if( nPrefix>zCsr-zNode || nSuffix>zEnd-zCsr || nSuffix==0 ){ rc = FTS_CORRUPT_VTAB; goto finish_scan; } @@ -168312,7 +169241,7 @@ static void fts3TokenizerFunc( nName = sqlite3_value_bytes(argv[0])+1; if( argc==2 ){ - if( fts3TokenizerEnabled(context) ){ + if( fts3TokenizerEnabled(context) || sqlite3_value_frombind(argv[1]) ){ void *pOld; int n = sqlite3_value_bytes(argv[1]); if( zName==0 || n!=sizeof(pPtr) ){ @@ -168339,7 +169268,9 @@ static void fts3TokenizerFunc( return; } } - sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT); + if( fts3TokenizerEnabled(context) || sqlite3_value_frombind(argv[0]) ){ + sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT); + } } SQLITE_PRIVATE int sqlite3Fts3IsIdChar(char c){ @@ -168427,8 +169358,8 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer( int iArg = 0; z = &z[n+1]; while( zzInput = sqlite3_malloc(nByte+1); + pCsr->zInput = sqlite3_malloc64(nByte+1); if( pCsr->zInput==0 ){ rc = SQLITE_NOMEM; }else{ @@ -170795,7 +171726,9 @@ static int fts3SegReaderNext( /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf ** blocks have already been traversed. */ - assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock ); +#ifdef CORRUPT_DB + assert( pReader->iCurrentBlock<=pReader->iLeafEndBlock || CORRUPT_DB ); +#endif if( pReader->iCurrentBlock>=pReader->iLeafEndBlock ){ return SQLITE_OK; } @@ -171197,8 +172130,9 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderPending( } if( nElem>0 ){ - int nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *); - pReader = (Fts3SegReader *)sqlite3_malloc(nByte); + sqlite3_int64 nByte; + nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *); + pReader = (Fts3SegReader *)sqlite3_malloc64(nByte); if( !pReader ){ rc = SQLITE_NOMEM; }else{ @@ -172682,8 +173616,10 @@ static int fts3SegmentMerge( if( rc!=SQLITE_OK ) goto finished; assert( csr.nSegment>0 ); - assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) ); - assert( iNewLevel=getAbsoluteLevel(p, iLangid, iIndex, 0) ); + assert_fts3_nc( + iNewLevelnColumn ); + pBlob = sqlite3_malloc64( 10*(sqlite3_int64)p->nColumn ); if( pBlob==0 ){ *pRC = SQLITE_NOMEM; return; @@ -172860,7 +173796,7 @@ static void fts3UpdateDocTotals( const int nStat = p->nColumn+2; if( *pRC ) return; - a = sqlite3_malloc( (sizeof(u32)+10)*nStat ); + a = sqlite3_malloc64( (sizeof(u32)+10)*(sqlite3_int64)nStat ); if( a==0 ){ *pRC = SQLITE_NOMEM; return; @@ -172981,8 +173917,8 @@ static int fts3DoRebuild(Fts3Table *p){ } if( rc==SQLITE_OK ){ - int nByte = sizeof(u32) * (p->nColumn+1)*3; - aSz = (u32 *)sqlite3_malloc(nByte); + sqlite3_int64 nByte = sizeof(u32) * ((sqlite3_int64)p->nColumn+1)*3; + aSz = (u32 *)sqlite3_malloc64(nByte); if( aSz==0 ){ rc = SQLITE_NOMEM; }else{ @@ -173048,12 +173984,12 @@ static int fts3IncrmergeCsr( ){ int rc; /* Return Code */ sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */ - int nByte; /* Bytes allocated at pCsr->apSegment[] */ + sqlite3_int64 nByte; /* Bytes allocated at pCsr->apSegment[] */ /* Allocate space for the Fts3MultiSegReader.aCsr[] array */ memset(pCsr, 0, sizeof(*pCsr)); nByte = sizeof(Fts3SegReader *) * nSeg; - pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte); + pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc64(nByte); if( pCsr->apSegment==0 ){ rc = SQLITE_NOMEM; @@ -175033,7 +175969,7 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( } /* Allocate space to hold the change in document sizes */ - aSzDel = sqlite3_malloc( sizeof(aSzDel[0])*(p->nColumn+1)*2 ); + aSzDel = sqlite3_malloc64(sizeof(aSzDel[0])*((sqlite3_int64)p->nColumn+1)*2); if( aSzDel==0 ){ rc = SQLITE_NOMEM; goto update_out; @@ -175287,17 +176223,19 @@ struct StrBuffer { /* ** Allocate a two-slot MatchinfoBuffer object. */ -static MatchinfoBuffer *fts3MIBufferNew(int nElem, const char *zMatchinfo){ +static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){ MatchinfoBuffer *pRet; - int nByte = sizeof(u32) * (2*nElem + 1) + sizeof(MatchinfoBuffer); - int nStr = (int)strlen(zMatchinfo); + sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1) + + sizeof(MatchinfoBuffer); + sqlite3_int64 nStr = strlen(zMatchinfo); - pRet = sqlite3_malloc(nByte + nStr+1); + pRet = sqlite3_malloc64(nByte + nStr+1); if( pRet ){ memset(pRet, 0, nByte); pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet; - pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0] + sizeof(u32)*(nElem+1); - pRet->nElem = nElem; + pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0] + + sizeof(u32)*((int)nElem+1); + pRet->nElem = (int)nElem; pRet->zMatchinfo = ((char*)pRet) + nByte; memcpy(pRet->zMatchinfo, zMatchinfo, nStr+1); pRet->aRef[0] = 1; @@ -175588,7 +176526,7 @@ static void fts3SnippetDetails( char *pCsr = pPhrase->pTail; int iCsr = pPhrase->iTail; - while( iCsr<(iStart+pIter->nSnippet) ){ + while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){ int j; u64 mPhrase = (u64)1 << i; u64 mPos = (u64)1 << (iCsr - iStart); @@ -176158,8 +177096,8 @@ static int fts3MatchinfoCheck( return SQLITE_ERROR; } -static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){ - int nVal; /* Number of integers output by cArg */ +static size_t fts3MatchinfoSize(MatchInfo *pInfo, char cArg){ + size_t nVal; /* Number of integers output by cArg */ switch( cArg ){ case FTS3_MATCHINFO_NDOC: @@ -176443,7 +177381,7 @@ static int fts3MatchinfoValues( case FTS3_MATCHINFO_LHITS_BM: case FTS3_MATCHINFO_LHITS: { - int nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32); + size_t nZero = fts3MatchinfoSize(pInfo, zArg[i]) * sizeof(u32); memset(pInfo->aMatchinfo, 0, nZero); rc = fts3ExprLHitGather(pCsr->pExpr, pInfo); break; @@ -176512,7 +177450,7 @@ static void fts3GetMatchinfo( ** initialize those elements that are constant for every row. */ if( pCsr->pMIBuffer==0 ){ - int nMatchinfo = 0; /* Number of u32 elements in match-info */ + size_t nMatchinfo = 0; /* Number of u32 elements in match-info */ int i; /* Used to iterate through zArg */ /* Determine the number of phrases in the query */ @@ -176702,7 +177640,7 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){ nTerm = pExpr->pPhrase->nToken; if( pList ){ fts3GetDeltaPosition(&pList, &iPos); - assert( iPos>=0 ); + assert_fts3_nc( iPos>=0 ); } for(iTerm=0; iTermpList) ){ pTerm->pList = 0; }else{ @@ -183970,49 +184908,45 @@ rtreeInit_fail: ** *2 coordinates. */ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ - char *zText = 0; RtreeNode node; Rtree tree; int ii; + int nData; + int errCode; + sqlite3_str *pOut; UNUSED_PARAMETER(nArg); memset(&node, 0, sizeof(RtreeNode)); memset(&tree, 0, sizeof(Rtree)); tree.nDim = (u8)sqlite3_value_int(apArg[0]); + if( tree.nDim<1 || tree.nDim>5 ) return; tree.nDim2 = tree.nDim*2; tree.nBytesPerCell = 8 + 8 * tree.nDim; node.zData = (u8 *)sqlite3_value_blob(apArg[1]); + nData = sqlite3_value_bytes(apArg[1]); + if( nData<4 ) return; + if( nData0 ) sqlite3_str_append(pOut, " ", 1); + sqlite3_str_appendf(pOut, "{%lld", cell.iRowid); for(jj=0; jjnVertex = s.nVertex; @@ -185163,7 +186097,7 @@ static GeoPoly *geopolyBBox( if( pRc ) *pRc = SQLITE_OK; if( aCoord==0 ){ geopolyBboxFill: - pOut = sqlite3_realloc(p, GEOPOLY_SZ(4)); + pOut = sqlite3_realloc64(p, GEOPOLY_SZ(4)); if( pOut==0 ){ sqlite3_free(p); if( context ) sqlite3_result_error_nomem(context); @@ -185559,9 +186493,9 @@ static GeoSegment *geopolySortSegmentsByYAndC(GeoSegment *pList){ ** Determine the overlap between two polygons */ static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){ - int nVertex = p1->nVertex + p2->nVertex + 2; + sqlite3_int64 nVertex = p1->nVertex + p2->nVertex + 2; GeoOverlap *p; - int nByte; + sqlite3_int64 nByte; GeoEvent *pThisEvent; double rX; int rc = 0; @@ -185573,7 +186507,7 @@ static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){ nByte = sizeof(GeoEvent)*nVertex*2 + sizeof(GeoSegment)*nVertex + sizeof(GeoOverlap); - p = sqlite3_malloc( nByte ); + p = sqlite3_malloc64( nByte ); if( p==0 ) return -1; p->aEvent = (GeoEvent*)&p[1]; p->aSegment = (GeoSegment*)&p->aEvent[nVertex*2]; @@ -185732,8 +186666,8 @@ static int geopolyInit( ){ int rc = SQLITE_OK; Rtree *pRtree; - int nDb; /* Length of string argv[1] */ - int nName; /* Length of string argv[2] */ + sqlite3_int64 nDb; /* Length of string argv[1] */ + sqlite3_int64 nName; /* Length of string argv[2] */ sqlite3_str *pSql; char *zSql; int ii; @@ -185741,9 +186675,9 @@ static int geopolyInit( sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); /* Allocate the sqlite3_vtab structure */ - nDb = (int)strlen(argv[1]); - nName = (int)strlen(argv[2]); - pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); + nDb = strlen(argv[1]); + nName = strlen(argv[2]); + pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName+2); if( !pRtree ){ return SQLITE_NOMEM; } @@ -188168,6 +189102,11 @@ struct RbuUpdateStmt { ** it points to an array of flags nTblCol elements in size. The flag is ** set for each column that is either a part of the PK or a part of an ** index. Or clear otherwise. +** +** If there are one or more partial indexes on the table, all fields of +** this array set set to 1. This is because in that case, the module has +** no way to tell which fields will be required to add and remove entries +** from the partial indexes. ** */ struct RbuObjIter { @@ -188612,6 +189551,7 @@ static void rbuFossilDeltaFunc( }else{ nOut2 = rbuDeltaApply(aOrig, nOrig, aDelta, nDelta, aOut); if( nOut2!=nOut ){ + sqlite3_free(aOut); sqlite3_result_error(context, "corrupt fossil delta", -1); }else{ sqlite3_result_blob(context, aOut, nOut, sqlite3_free); @@ -188962,7 +189902,7 @@ static int rbuMPrintfExec(sqlite3rbu *p, sqlite3 *db, const char *zFmt, ...){ ** immediately without attempting the allocation or modifying the stored ** error code. */ -static void *rbuMalloc(sqlite3rbu *p, int nByte){ +static void *rbuMalloc(sqlite3rbu *p, sqlite3_int64 nByte){ void *pRet = 0; if( p->rc==SQLITE_OK ){ assert( nByte>0 ); @@ -188983,7 +189923,7 @@ static void *rbuMalloc(sqlite3rbu *p, int nByte){ ** error code in the RBU handle passed as the first argument. */ static void rbuAllocateIterArrays(sqlite3rbu *p, RbuObjIter *pIter, int nCol){ - int nByte = (2*sizeof(char*) + sizeof(int) + 3*sizeof(u8)) * nCol; + sqlite3_int64 nByte = (2*sizeof(char*) + sizeof(int) + 3*sizeof(u8)) * nCol; char **azNew; azNew = (char**)rbuMalloc(p, nByte); @@ -189177,8 +190117,12 @@ static void rbuObjIterCacheIndexedCols(sqlite3rbu *p, RbuObjIter *pIter){ pIter->nIndex = 0; while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pList) ){ const char *zIdx = (const char*)sqlite3_column_text(pList, 1); + int bPartial = sqlite3_column_int(pList, 4); sqlite3_stmt *pXInfo = 0; if( zIdx==0 ) break; + if( bPartial ){ + memset(pIter->abIndexed, 0x01, sizeof(u8)*pIter->nTblCol); + } p->rc = prepareFreeAndCollectError(p->dbMain, &pXInfo, &p->zErrmsg, sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) ); @@ -189623,7 +190567,7 @@ static char *rbuObjIterGetSetlist( */ static char *rbuObjIterGetBindlist(sqlite3rbu *p, int nBind){ char *zRet = 0; - int nByte = nBind*2 + 1; + sqlite3_int64 nByte = 2*(sqlite3_int64)nBind + 1; zRet = (char*)rbuMalloc(p, nByte); if( zRet ){ @@ -189885,6 +190829,62 @@ static void rbuTmpInsertFunc( } } +static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){ + sqlite3_stmt *pStmt = 0; + int rc = p->rc; + char *zRet = 0; + + if( rc==SQLITE_OK ){ + rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, + "SELECT trim(sql) FROM sqlite_master WHERE type='index' AND name=?" + ); + } + if( rc==SQLITE_OK ){ + int rc2; + rc = sqlite3_bind_text(pStmt, 1, pIter->zIdx, -1, SQLITE_STATIC); + if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ + const char *zSql = (const char*)sqlite3_column_text(pStmt, 0); + if( zSql ){ + int nParen = 0; /* Number of open parenthesis */ + int i; + for(i=0; zSql[i]; i++){ + char c = zSql[i]; + if( c=='(' ){ + nParen++; + } + else if( c==')' ){ + nParen--; + if( nParen==0 ){ + i++; + break; + } + }else if( c=='"' || c=='\'' || c=='`' ){ + for(i++; 1; i++){ + if( zSql[i]==c ){ + if( zSql[i+1]!=c ) break; + i++; + } + } + }else if( c=='[' ){ + for(i++; 1; i++){ + if( zSql[i]==']' ) break; + } + } + } + if( zSql[i] ){ + zRet = rbuStrndup(&zSql[i], &rc); + } + } + } + + rc2 = sqlite3_finalize(pStmt); + if( rc==SQLITE_OK ) rc = rc2; + } + + p->rc = rc; + return zRet; +} + /* ** Ensure that the SQLite statement handles required to update the ** target database object currently indicated by the iterator passed @@ -189914,6 +190914,7 @@ static int rbuObjIterPrepareAll( char *zImposterPK = 0; /* Primary key declaration for imposter */ char *zWhere = 0; /* WHERE clause on PK columns */ char *zBind = 0; + char *zPart = 0; int nBind = 0; assert( pIter->eType!=RBU_PK_VTAB ); @@ -189921,6 +190922,7 @@ static int rbuObjIterPrepareAll( p, pIter, &zImposterCols, &zImposterPK, &zWhere, &nBind ); zBind = rbuObjIterGetBindlist(p, nBind); + zPart = rbuObjIterGetIndexWhere(p, pIter); /* Create the imposter table used to write to this index. */ sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1); @@ -189953,28 +190955,30 @@ static int rbuObjIterPrepareAll( char *zSql; if( rbuIsVacuum(p) ){ zSql = sqlite3_mprintf( - "SELECT %s, 0 AS rbu_control FROM '%q' ORDER BY %s%s", + "SELECT %s, 0 AS rbu_control FROM '%q' %s ORDER BY %s%s", zCollist, pIter->zDataTbl, - zCollist, zLimit + zPart, zCollist, zLimit ); }else if( pIter->eType==RBU_PK_EXTERNAL || pIter->eType==RBU_PK_NONE ){ zSql = sqlite3_mprintf( - "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' ORDER BY %s%s", + "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' %s ORDER BY %s%s", zCollist, p->zStateDb, pIter->zDataTbl, - zCollist, zLimit + zPart, zCollist, zLimit ); }else{ zSql = sqlite3_mprintf( - "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' " + "SELECT %s, rbu_control FROM %s.'rbu_tmp_%q' %s " "UNION ALL " "SELECT %s, rbu_control FROM '%q' " - "WHERE typeof(rbu_control)='integer' AND rbu_control!=1 " + "%s %s typeof(rbu_control)='integer' AND rbu_control!=1 " "ORDER BY %s%s", - zCollist, p->zStateDb, pIter->zDataTbl, + zCollist, p->zStateDb, pIter->zDataTbl, zPart, zCollist, pIter->zDataTbl, + zPart, + (zPart ? "AND" : "WHERE"), zCollist, zLimit ); } @@ -189985,6 +190989,7 @@ static int rbuObjIterPrepareAll( sqlite3_free(zImposterPK); sqlite3_free(zWhere); sqlite3_free(zBind); + sqlite3_free(zPart); }else{ int bRbuRowid = (pIter->eType==RBU_PK_VTAB) ||(pIter->eType==RBU_PK_NONE) @@ -192418,7 +193423,7 @@ static int rbuVfsShmMap( assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); if( eStage==RBU_STAGE_OAL || eStage==RBU_STAGE_MOVE ){ if( iRegion<=p->nShm ){ - int nByte = (iRegion+1) * sizeof(char*); + sqlite3_int64 nByte = (iRegion+1) * sizeof(char*); char **apNew = (char**)sqlite3_realloc64(p->apShm, nByte); if( apNew==0 ){ rc = SQLITE_NOMEM; @@ -194929,7 +195934,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){ if( pTab->nChange==0 || pTab->nEntry>=(pTab->nChange/2) ){ int i; SessionChange **apNew; - int nNew = (pTab->nChange ? pTab->nChange : 128) * 2; + sqlite3_int64 nNew = 2*(sqlite3_int64)(pTab->nChange ? pTab->nChange : 128); apNew = (SessionChange **)sqlite3_malloc64(sizeof(SessionChange *) * nNew); if( apNew==0 ){ @@ -195856,7 +196861,7 @@ SQLITE_API int sqlite3session_attach( ** If successful, return zero. Otherwise, if an OOM condition is encountered, ** set *pRc to SQLITE_NOMEM and return non-zero. */ -static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){ +static int sessionBufferGrow(SessionBuffer *p, size_t nByte, int *pRc){ if( *pRc==SQLITE_OK && p->nAlloc-p->nBufnAlloc ? p->nAlloc : 128; @@ -196974,7 +197979,7 @@ static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){ } if( rc==SQLITE_OK ){ - int iPK = sizeof(sqlite3_value*)*p->nCol*2; + size_t iPK = sizeof(sqlite3_value*)*p->nCol*2; memset(p->tblhdr.aBuf, 0, iPK); memcpy(&p->tblhdr.aBuf[iPK], &p->in.aData[p->in.iNext], nCopy); p->in.iNext += nCopy; @@ -197889,7 +198894,7 @@ static int sessionSeekToRow( } /* -** This function is called from within sqlite3changset_apply_v2() when +** This function is called from within sqlite3changeset_apply_v2() when ** a conflict is encountered and resolved using conflict resolution ** mode eType (either SQLITE_CHANGESET_OMIT or SQLITE_CHANGESET_REPLACE).. ** It adds a conflict resolution record to the buffer in @@ -198278,7 +199283,7 @@ static int sessionRetryConstraints( rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf, 0); if( rc==SQLITE_OK ){ - int nByte = 2*pApply->nCol*sizeof(sqlite3_value*); + size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*); int rc2; pIter2->bPatchset = bPatchset; pIter2->zTab = (char*)zTab; @@ -199671,7 +200676,7 @@ struct Fts5PhraseIter { ** Save the pointer passed as the second argument as the extension functions ** "auxiliary data". The pointer may then be retrieved by the current or any ** future invocation of the same fts5 extension function made as part of -** of the same MATCH query using the xGetAuxdata() API. +** the same MATCH query using the xGetAuxdata() API. ** ** Each extension function is allocated a single auxiliary data slot for ** each FTS query (MATCH expression). If the extension function is invoked @@ -199686,7 +200691,7 @@ struct Fts5PhraseIter { ** The xDelete callback, if one is specified, is also invoked on the ** auxiliary data pointer after the FTS5 query has finished. ** -** If an error (e.g. an OOM condition) occurs within this function, an +** If an error (e.g. an OOM condition) occurs within this function, ** the auxiliary data is set to NULL and an error code returned. If the ** xDelete parameter was not NULL, it is invoked on the auxiliary data ** pointer before returning. @@ -200668,8 +201673,9 @@ static void sqlite3Fts5HashClear(Fts5Hash*); static int sqlite3Fts5HashQuery( Fts5Hash*, /* Hash table to query */ + int nPre, const char *pTerm, int nTerm, /* Query term */ - const u8 **ppDoclist, /* OUT: Pointer to doclist for pTerm */ + void **ppObj, /* OUT: Pointer to doclist for pTerm */ int *pnDoclist /* OUT: Size of doclist in bytes */ ); @@ -202739,7 +203745,7 @@ static int fts5SnippetScore( sqlite3_int64 iAdj = iFirst - (nToken - (iLast-iFirst)) / 2; if( (iAdj+nToken)>nDocsize ) iAdj = nDocsize - nToken; if( iAdj<0 ) iAdj = 0; - *piPos = iAdj; + *piPos = (int)iAdj; } return rc; @@ -202967,7 +203973,7 @@ static int fts5Bm25GetData( if( p==0 ){ rc = SQLITE_NOMEM; }else{ - memset(p, 0, nByte); + memset(p, 0, (size_t)nByte); p->nPhrase = nPhrase; p->aIDF = (double*)&p[1]; p->aFreq = &p->aIDF[nPhrase]; @@ -203130,7 +204136,7 @@ static int sqlite3Fts5BufferSize(int *pRc, Fts5Buffer *pBuf, u32 nByte){ *pRc = SQLITE_NOMEM; return 1; }else{ - pBuf->nSpace = nNew; + pBuf->nSpace = (int)nNew; pBuf->p = pNew; } } @@ -203354,7 +204360,7 @@ static void *sqlite3Fts5MallocZero(int *pRc, sqlite3_int64 nByte){ if( pRet==0 ){ if( nByte>0 ) *pRc = SQLITE_NOMEM; }else{ - memset(pRet, 0, nByte); + memset(pRet, 0, (size_t)nByte); } } return pRet; @@ -203823,7 +204829,7 @@ static int fts5ConfigParseSpecial( rc = SQLITE_ERROR; }else{ rc = sqlite3Fts5GetTokenizer(pGlobal, - (const char**)azArg, nArg, &pConfig->pTok, &pConfig->pTokApi, + (const char**)azArg, (int)nArg, &pConfig->pTok, &pConfig->pTokApi, pzErr ); } @@ -203933,7 +204939,7 @@ static const char *fts5ConfigGobbleWord( if( zOut==0 ){ *pRc = SQLITE_NOMEM; }else{ - memcpy(zOut, zIn, nIn+1); + memcpy(zOut, zIn, (size_t)(nIn+1)); if( fts5_isopenquote(zOut[0]) ){ int ii = fts5Dequote(zOut); zRet = &zIn[ii]; @@ -205947,7 +206953,7 @@ static Fts5ExprNearset *sqlite3Fts5ParseNearset( if( pRet==0 ){ pParse->rc = SQLITE_NOMEM; }else{ - memset(pRet, 0, nByte); + memset(pRet, 0, (size_t)nByte); } }else if( (pNear->nPhrase % SZALLOC)==0 ){ int nNew = pNear->nPhrase + SZALLOC; @@ -206023,7 +207029,7 @@ static int fts5ParseTokenize( if( pSyn==0 ){ rc = SQLITE_NOMEM; }else{ - memset(pSyn, 0, nByte); + memset(pSyn, 0, (size_t)nByte); pSyn->zTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer); memcpy(pSyn->zTerm, pToken, nToken); pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym; @@ -206183,7 +207189,7 @@ static int sqlite3Fts5ExprClonePhrase( nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int); pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte); if( pColset ){ - memcpy(pColset, pColsetOrig, nByte); + memcpy(pColset, pColsetOrig, (size_t)nByte); } pNew->pRoot->pNear->pColset = pColset; } @@ -206400,7 +207406,7 @@ static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){ sqlite3_int64 nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int); pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte); if( pRet ){ - memcpy(pRet, pOrig, nByte); + memcpy(pRet, pOrig, (size_t)nByte); } }else{ pRet = 0; @@ -207417,7 +208423,7 @@ static int sqlite3Fts5HashNew(Fts5Config *pConfig, Fts5Hash **ppNew, int *pnByte *ppNew = 0; rc = SQLITE_NOMEM; }else{ - memset(pNew->aSlot, 0, nByte); + memset(pNew->aSlot, 0, (size_t)nByte); } } return rc; @@ -207501,19 +208507,25 @@ static int fts5HashResize(Fts5Hash *pHash){ return SQLITE_OK; } -static void fts5HashAddPoslistSize(Fts5Hash *pHash, Fts5HashEntry *p){ +static int fts5HashAddPoslistSize( + Fts5Hash *pHash, + Fts5HashEntry *p, + Fts5HashEntry *p2 +){ + int nRet = 0; if( p->iSzPoslist ){ - u8 *pPtr = (u8*)p; + u8 *pPtr = p2 ? (u8*)p2 : (u8*)p; + int nData = p->nData; if( pHash->eDetail==FTS5_DETAIL_NONE ){ - assert( p->nData==p->iSzPoslist ); + assert( nData==p->iSzPoslist ); if( p->bDel ){ - pPtr[p->nData++] = 0x00; + pPtr[nData++] = 0x00; if( p->bContent ){ - pPtr[p->nData++] = 0x00; + pPtr[nData++] = 0x00; } } }else{ - int nSz = (p->nData - p->iSzPoslist - 1); /* Size in bytes */ + int nSz = (nData - p->iSzPoslist - 1); /* Size in bytes */ int nPos = nSz*2 + p->bDel; /* Value of nPos field */ assert( p->bDel==0 || p->bDel==1 ); @@ -207523,14 +208535,19 @@ static void fts5HashAddPoslistSize(Fts5Hash *pHash, Fts5HashEntry *p){ int nByte = sqlite3Fts5GetVarintLen((u32)nPos); memmove(&pPtr[p->iSzPoslist + nByte], &pPtr[p->iSzPoslist + 1], nSz); sqlite3Fts5PutVarint(&pPtr[p->iSzPoslist], nPos); - p->nData += (nByte-1); + nData += (nByte-1); } } - p->iSzPoslist = 0; - p->bDel = 0; - p->bContent = 0; + nRet = nData - p->nData; + if( p2==0 ){ + p->iSzPoslist = 0; + p->bDel = 0; + p->bContent = 0; + p->nData = nData; + } } + return nRet; } /* @@ -207587,7 +208604,7 @@ static int sqlite3Fts5HashWrite( p = (Fts5HashEntry*)sqlite3_malloc64(nByte); if( !p ) return SQLITE_NOMEM; memset(p, 0, sizeof(Fts5HashEntry)); - p->nAlloc = nByte; + p->nAlloc = (int)nByte; zKey = fts5EntryKey(p); zKey[0] = bByte; memcpy(&zKey[1], pToken, nToken); @@ -207642,7 +208659,7 @@ static int sqlite3Fts5HashWrite( /* If this is a new rowid, append the 4-byte size field for the previous ** entry, and the new rowid for this entry. */ if( iRowid!=p->iRowid ){ - fts5HashAddPoslistSize(pHash, p); + fts5HashAddPoslistSize(pHash, p, 0); p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid); p->iRowid = iRowid; bNew = 1; @@ -207759,7 +208776,9 @@ static int fts5HashEntrySort( for(iSlot=0; iSlotnSlot; iSlot++){ Fts5HashEntry *pIter; for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){ - if( pTerm==0 || 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm) ){ + if( pTerm==0 + || (pIter->nKey+1>=nTerm && 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm)) + ){ Fts5HashEntry *pEntry = pIter; pEntry->pScanNext = 0; for(i=0; ap[i]; i++){ @@ -207787,8 +208806,9 @@ static int fts5HashEntrySort( */ static int sqlite3Fts5HashQuery( Fts5Hash *pHash, /* Hash table to query */ + int nPre, const char *pTerm, int nTerm, /* Query term */ - const u8 **ppDoclist, /* OUT: Pointer to doclist for pTerm */ + void **ppOut, /* OUT: Pointer to new object */ int *pnDoclist /* OUT: Size of doclist in bytes */ ){ unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm); @@ -207802,11 +208822,20 @@ static int sqlite3Fts5HashQuery( } if( p ){ - fts5HashAddPoslistSize(pHash, p); - *ppDoclist = (const u8*)&zKey[nTerm+1]; - *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1); + int nHashPre = sizeof(Fts5HashEntry) + nTerm + 1; + int nList = p->nData - nHashPre; + u8 *pRet = (u8*)(*ppOut = sqlite3_malloc64(nPre + nList + 10)); + if( pRet ){ + Fts5HashEntry *pFaux = (Fts5HashEntry*)&pRet[nPre-nHashPre]; + memcpy(&pRet[nPre], &((u8*)p)[nHashPre], nList); + nList += fts5HashAddPoslistSize(pHash, p, pFaux); + *pnDoclist = nList; + }else{ + *pnDoclist = 0; + return SQLITE_NOMEM; + } }else{ - *ppDoclist = 0; + *ppOut = 0; *pnDoclist = 0; } @@ -207839,7 +208868,7 @@ static void sqlite3Fts5HashScanEntry( if( (p = pHash->pScan) ){ char *zKey = fts5EntryKey(p); int nTerm = (int)strlen(zKey); - fts5HashAddPoslistSize(pHash, p); + fts5HashAddPoslistSize(pHash, p, 0); *pzTerm = zKey; *ppDoclist = (const u8*)&zKey[nTerm+1]; *pnDoclist = p->nData - (sizeof(Fts5HashEntry) + nTerm + 1); @@ -210309,31 +211338,40 @@ static void fts5SegIterHashInit( int flags, /* Mask of FTS5INDEX_XXX flags */ Fts5SegIter *pIter /* Object to populate */ ){ - const u8 *pList = 0; int nList = 0; const u8 *z = 0; int n = 0; + Fts5Data *pLeaf = 0; assert( p->pHash ); assert( p->rc==SQLITE_OK ); if( pTerm==0 || (flags & FTS5INDEX_QUERY_SCAN) ){ + const u8 *pList = 0; + p->rc = sqlite3Fts5HashScanInit(p->pHash, (const char*)pTerm, nTerm); sqlite3Fts5HashScanEntry(p->pHash, (const char**)&z, &pList, &nList); n = (z ? (int)strlen((const char*)z) : 0); + if( pList ){ + pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data)); + if( pLeaf ){ + pLeaf->p = (u8*)pList; + } + } }else{ - pIter->flags |= FTS5_SEGITER_ONETERM; - sqlite3Fts5HashQuery(p->pHash, (const char*)pTerm, nTerm, &pList, &nList); + p->rc = sqlite3Fts5HashQuery(p->pHash, sizeof(Fts5Data), + (const char*)pTerm, nTerm, (void**)&pLeaf, &nList + ); + if( pLeaf ){ + pLeaf->p = (u8*)&pLeaf[1]; + } z = pTerm; n = nTerm; + pIter->flags |= FTS5_SEGITER_ONETERM; } - if( pList ){ - Fts5Data *pLeaf; + if( pLeaf ){ sqlite3Fts5BufferSet(&p->rc, &pIter->term, n, z); - pLeaf = fts5IdxMalloc(p, sizeof(Fts5Data)); - if( pLeaf==0 ) return; - pLeaf->p = (u8*)pList; pLeaf->nn = pLeaf->szLeaf = nList; pIter->pLeaf = pLeaf; pIter->iLeafOffset = fts5GetVarint(pLeaf->p, (u64*)&pIter->iRowid); @@ -210486,8 +211524,8 @@ static int fts5MultiIterDoCompare(Fts5Iter *pIter, int iOut){ }else{ int res = fts5BufferCompare(&p1->term, &p2->term); if( res==0 ){ - assert( i2>i1 ); - assert( i2!=0 ); + assert_nc( i2>i1 ); + assert_nc( i2!=0 ); pRes->bTermEq = 1; if( p1->iRowid==p2->iRowid ){ p1->bDel = p2->bDel; @@ -211534,7 +212572,7 @@ static int fts5WriteDlidxGrow( if( aDlidx==0 ){ p->rc = SQLITE_NOMEM; }else{ - int nByte = sizeof(Fts5DlidxWriter) * (nLvl - pWriter->nDlidx); + size_t nByte = sizeof(Fts5DlidxWriter) * (nLvl - pWriter->nDlidx); memset(&aDlidx[pWriter->nDlidx], 0, nByte); pWriter->aDlidx = aDlidx; pWriter->nDlidx = nLvl; @@ -212021,13 +213059,14 @@ static void fts5TrimSegments(Fts5Index *p, Fts5Iter *pIter){ /* Set up the new page-index array */ fts5BufferAppendVarint(&p->rc, &buf, 4); if( pSeg->iLeafPgno==pSeg->iTermLeafPgno - && pSeg->iEndofDoclistszLeaf - ){ + && pSeg->iEndofDoclistszLeaf + && pSeg->iPgidxOff<=pData->nn + ){ int nDiff = pData->szLeaf - pSeg->iEndofDoclist; fts5BufferAppendVarint(&p->rc, &buf, buf.n - 1 - nDiff - 4); fts5BufferAppendBlob(&p->rc, &buf, pData->nn - pSeg->iPgidxOff, &pData->p[pSeg->iPgidxOff] - ); + ); } pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno; @@ -215049,7 +216088,7 @@ static int fts5OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){ pCsr = (Fts5Cursor*)sqlite3_malloc64(nByte); if( pCsr ){ Fts5Global *pGlobal = pTab->pGlobal; - memset(pCsr, 0, nByte); + memset(pCsr, 0, (size_t)nByte); pCsr->aColumnSize = (int*)&pCsr[1]; pCsr->pNext = pGlobal->pCsr; pGlobal->pCsr = pCsr; @@ -215330,7 +216369,7 @@ static int fts5CursorFirstSorted( nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1); pSorter = (Fts5Sorter*)sqlite3_malloc64(nByte); if( pSorter==0 ) return SQLITE_NOMEM; - memset(pSorter, 0, nByte); + memset(pSorter, 0, (size_t)nByte); pSorter->nIdx = nPhrase; /* TODO: It would be better to have some system for reusing statement @@ -216884,14 +217923,14 @@ static int fts5CreateAux( int rc = sqlite3_overload_function(pGlobal->db, zName, -1); if( rc==SQLITE_OK ){ Fts5Auxiliary *pAux; - int nName; /* Size of zName in bytes, including \0 */ - int nByte; /* Bytes of space to allocate */ + sqlite3_int64 nName; /* Size of zName in bytes, including \0 */ + sqlite3_int64 nByte; /* Bytes of space to allocate */ - nName = (int)strlen(zName) + 1; + nName = strlen(zName) + 1; nByte = sizeof(Fts5Auxiliary) + nName; - pAux = (Fts5Auxiliary*)sqlite3_malloc(nByte); + pAux = (Fts5Auxiliary*)sqlite3_malloc64(nByte); if( pAux ){ - memset(pAux, 0, nByte); + memset(pAux, 0, (size_t)nByte); pAux->zFunc = (char*)&pAux[1]; memcpy(pAux->zFunc, zName, nName); pAux->pGlobal = pGlobal; @@ -216921,15 +217960,15 @@ static int fts5CreateTokenizer( ){ Fts5Global *pGlobal = (Fts5Global*)pApi; Fts5TokenizerModule *pNew; - int nName; /* Size of zName and its \0 terminator */ - int nByte; /* Bytes of space to allocate */ + sqlite3_int64 nName; /* Size of zName and its \0 terminator */ + sqlite3_int64 nByte; /* Bytes of space to allocate */ int rc = SQLITE_OK; - nName = (int)strlen(zName) + 1; + nName = strlen(zName) + 1; nByte = sizeof(Fts5TokenizerModule) + nName; - pNew = (Fts5TokenizerModule*)sqlite3_malloc(nByte); + pNew = (Fts5TokenizerModule*)sqlite3_malloc64(nByte); if( pNew ){ - memset(pNew, 0, nByte); + memset(pNew, 0, (size_t)nByte); pNew->zName = (char*)&pNew[1]; memcpy(pNew->zName, zName, nName); pNew->pUserData = pUserData; @@ -217064,7 +218103,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2019-02-25 16:06:06 bd49a8271d650fa89e446b42e513b595a717b9212c91dd384aab871fc1d0f6d7", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2019-04-16 19:49:53 884b4b7e502b4e991677b53971277adfaf0a04a284f8e483e2553d0f83156b50", -1, SQLITE_TRANSIENT); } /* @@ -217487,7 +218526,7 @@ static int sqlite3Fts5StorageOpen( *pp = p = (Fts5Storage*)sqlite3_malloc64(nByte); if( !p ) return SQLITE_NOMEM; - memset(p, 0, nByte); + memset(p, 0, (size_t)nByte); p->aTotalSize = (i64*)&p[1]; p->pConfig = pConfig; p->pIndex = pIndex; @@ -218709,7 +219748,7 @@ static int fts5UnicodeCreate( p->eRemoveDiacritic = FTS5_REMOVE_DIACRITICS_SIMPLE; p->nFold = 64; - p->aFold = sqlite3_malloc(p->nFold * sizeof(char)); + p->aFold = sqlite3_malloc64(p->nFold * sizeof(char)); if( p->aFold==0 ){ rc = SQLITE_NOMEM; } @@ -220397,7 +221436,7 @@ static void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){ int bToken = aArray[ aFts5UnicodeData[iTbl] & 0x1F ]; int n = (aFts5UnicodeData[iTbl] >> 5) + i; for(; i<128 && iSQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER -**
    ^This option is used to enable or disable the two-argument -** version of the [fts3_tokenizer()] function which is part of the +**
    ^This option is used to enable or disable the +** [fts3_tokenizer()] function which is part of the ** [FTS3] full-text search engine extension. ** There should be two additional arguments. ** The first argument is an integer which is 0 to disable fts3_tokenizer() or @@ -2199,6 +2202,17 @@ struct sqlite3_mem_methods { **
  • Direct writes to [shadow tables]. ** **
  • +** +** [[SQLITE_DBCONFIG_WRITABLE_SCHEMA]]
    SQLITE_DBCONFIG_WRITABLE_SCHEMA
    +**
    The SQLITE_DBCONFIG_WRITABLE_SCHEMA option activates or deactivates the +** "writable_schema" flag. This has the same effect and is logically equivalent +** to setting [PRAGMA writable_schema=ON] or [PRAGMA writable_schema=OFF]. +** The first argument to this setting is an integer which is 0 to disable +** the writable_schema, positive to enable writable_schema, or negative to +** leave the setting unchanged. The second parameter is a pointer to an +** integer into which is written 0 or 1 to indicate whether the writable_schema +** is enabled or disabled following this call. +**
    ** */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ @@ -2212,7 +2226,8 @@ struct sqlite3_mem_methods { #define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */ #define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ #define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */ -#define SQLITE_DBCONFIG_MAX 1010 /* Largest DBCONFIG */ +#define SQLITE_DBCONFIG_WRITABLE_SCHEMA 1011 /* int int* */ +#define SQLITE_DBCONFIG_MAX 1011 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes @@ -3894,6 +3909,18 @@ SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); */ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); +/* +** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement +** METHOD: sqlite3_stmt +** +** ^The sqlite3_stmt_isexplain(S) interface returns 1 if the +** prepared statement S is an EXPLAIN statement, or 2 if the +** statement S is an EXPLAIN QUERY PLAN. +** ^The sqlite3_stmt_isexplain(S) interface returns 0 if S is +** an ordinary statement or a NULL pointer. +*/ +SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt); + /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset ** METHOD: sqlite3_stmt @@ -4033,7 +4060,9 @@ typedef struct sqlite3_context sqlite3_context; ** ^The fifth argument to the BLOB and string binding interfaces ** is a destructor used to dispose of the BLOB or ** string after SQLite has finished with it. ^The destructor is called -** to dispose of the BLOB or string even if the call to bind API fails. +** to dispose of the BLOB or string even if the call to the bind API fails, +** except the destructor is not called if the third parameter is a NULL +** pointer or the fourth parameter is negative. ** ^If the fifth argument is ** the special value [SQLITE_STATIC], then SQLite assumes that the ** information is in static, unmanaged space and does not need to be freed. @@ -4950,6 +4979,8 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** sqlite3_value_nochange   ** →  True if the column is unchanged in an UPDATE ** against a virtual table. +** sqlite3_value_frombind   +** →  True if value originated from a [bound parameter] ** ** ** Details: @@ -5011,6 +5042,11 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6 ** than within an [xUpdate] method call for an UPDATE statement, then ** the return value is arbitrary and meaningless. ** +** ^The sqlite3_value_frombind(X) interface returns non-zero if the +** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()] +** interfaces. ^If X comes from an SQL literal value, or a table column, +** and expression, then sqlite3_value_frombind(X) returns zero. +** ** Please pay particular attention to the fact that the pointer returned ** from [sqlite3_value_blob()], [sqlite3_value_text()], or ** [sqlite3_value_text16()] can be invalidated by a subsequent call to @@ -5056,6 +5092,7 @@ SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); SQLITE_API int sqlite3_value_type(sqlite3_value*); SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); SQLITE_API int sqlite3_value_nochange(sqlite3_value*); +SQLITE_API int sqlite3_value_frombind(sqlite3_value*); /* ** CAPI3REF: Finding The Subtype Of SQL Values @@ -5791,7 +5828,7 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); ** associated with database N of connection D. ^The main database file ** has the name "main". If there is no attached database N on the database ** connection D, or if database N is a temporary or in-memory database, then -** a NULL pointer is returned. +** this function will return either a NULL pointer or an empty string. ** ** ^The filename returned by this function is the output of the ** xFullPathname method of the [VFS]. ^In other words, the filename @@ -10892,7 +10929,7 @@ SQLITE_API int sqlite3rebaser_configure( ** in size. This function allocates and populates a buffer with a copy ** of the changeset rebased rebased according to the configuration of the ** rebaser object passed as the first argument. If successful, (*ppOut) -** is set to point to the new buffer containing the rebased changset and +** is set to point to the new buffer containing the rebased changeset and ** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the ** responsibility of the caller to eventually free the new buffer using ** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut) @@ -11301,7 +11338,7 @@ struct Fts5PhraseIter { ** Save the pointer passed as the second argument as the extension functions ** "auxiliary data". The pointer may then be retrieved by the current or any ** future invocation of the same fts5 extension function made as part of -** of the same MATCH query using the xGetAuxdata() API. +** the same MATCH query using the xGetAuxdata() API. ** ** Each extension function is allocated a single auxiliary data slot for ** each FTS query (MATCH expression). If the extension function is invoked @@ -11316,7 +11353,7 @@ struct Fts5PhraseIter { ** The xDelete callback, if one is specified, is also invoked on the ** auxiliary data pointer after the FTS5 query has finished. ** -** If an error (e.g. an OOM condition) occurs within this function, an +** If an error (e.g. an OOM condition) occurs within this function, ** the auxiliary data is set to NULL and an error code returned. If the ** xDelete parameter was not NULL, it is invoked on the auxiliary data ** pointer before returning. diff --git a/TMessagesProj/jni/tgnet/ApiScheme.cpp b/TMessagesProj/jni/tgnet/ApiScheme.cpp index d9f81dbf4..3269c64f7 100644 --- a/TMessagesProj/jni/tgnet/ApiScheme.cpp +++ b/TMessagesProj/jni/tgnet/ApiScheme.cpp @@ -206,6 +206,7 @@ void TL_config::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool & tmp_sessions = stream->readInt32(&error); } pinned_dialogs_count_max = stream->readInt32(&error); + pinned_infolder_count_max = stream->readInt32(&error); call_receive_timeout_ms = stream->readInt32(&error); call_ring_timeout_ms = stream->readInt32(&error); call_connect_timeout_ms = stream->readInt32(&error); @@ -277,6 +278,7 @@ void TL_config::serializeToStream(NativeByteBuffer *stream) { stream->writeInt32(tmp_sessions); } stream->writeInt32(pinned_dialogs_count_max); + stream->writeInt32(pinned_infolder_count_max); stream->writeInt32(call_receive_timeout_ms); stream->writeInt32(call_ring_timeout_ms); stream->writeInt32(call_connect_timeout_ms); @@ -570,14 +572,8 @@ void TL_userStatusRecently::serializeToStream(NativeByteBuffer *stream) { FileLocation *FileLocation::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) { FileLocation *result = nullptr; switch (constructor) { - case 0x91d11eb: - result = new TL_fileLocation(); - break; - case 0x7c596b46: - result = new TL_fileLocationUnavailable(); - break; - case 0x55555554: - result = new TL_fileEncryptedLocation(); + case 0xbc7fc6cd: + result = new TL_fileLocationToBeDeprecated(); break; default: error = true; @@ -588,53 +584,15 @@ FileLocation *FileLocation::TLdeserialize(NativeByteBuffer *stream, uint32_t con return result; } -void TL_fileLocation::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) { - dc_id = stream->readInt32(&error); +void TL_fileLocationToBeDeprecated::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) { volume_id = stream->readInt64(&error); local_id = stream->readInt32(&error); - secret = stream->readInt64(&error); - file_reference = std::unique_ptr(stream->readByteArray(&error)); } -void TL_fileLocation::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); - stream->writeInt32(dc_id); - stream->writeInt64(volume_id); - stream->writeInt32(local_id); - stream->writeInt64(secret); - stream->writeByteArray(file_reference.get()); -} - -void TL_fileLocationUnavailable::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) { - volume_id = stream->readInt64(&error); - local_id = stream->readInt32(&error); - secret = stream->readInt64(&error); -} - -void TL_fileLocationUnavailable::serializeToStream(NativeByteBuffer *stream) { +void TL_fileLocationToBeDeprecated::serializeToStream(NativeByteBuffer *stream) { stream->writeInt32(constructor); stream->writeInt64(volume_id); stream->writeInt32(local_id); - stream->writeInt64(secret); -} - -void TL_fileEncryptedLocation::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) { - dc_id = stream->readInt32(&error); - volume_id = stream->readInt64(&error); - local_id = stream->readInt32(&error); - secret = stream->readInt64(&error); - key = std::unique_ptr(stream->readByteArray(&error)); - iv = std::unique_ptr(stream->readByteArray(&error)); -} - -void TL_fileEncryptedLocation::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); - stream->writeInt32(dc_id); - stream->writeInt64(volume_id); - stream->writeInt32(local_id); - stream->writeInt64(secret); - stream->writeByteArray(key.get()); - stream->writeByteArray(iv.get()); } UserProfilePhoto *UserProfilePhoto::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) { @@ -643,7 +601,7 @@ UserProfilePhoto *UserProfilePhoto::TLdeserialize(NativeByteBuffer *stream, uint case 0x4f11bae1: result = new TL_userProfilePhotoEmpty(); break; - case 0xd559d8c8: + case 0xecd75d8c: result = new TL_userProfilePhoto(); break; default: @@ -663,6 +621,7 @@ void TL_userProfilePhoto::readParams(NativeByteBuffer *stream, int32_t instanceN photo_id = stream->readInt64(&error); photo_small = std::unique_ptr(FileLocation::TLdeserialize(stream, stream->readUint32(&error), instanceNum, error)); photo_big = std::unique_ptr(FileLocation::TLdeserialize(stream, stream->readUint32(&error), instanceNum, error)); + dc_id = stream->readInt32(&error); } void TL_userProfilePhoto::serializeToStream(NativeByteBuffer *stream) { @@ -670,263 +629,9 @@ void TL_userProfilePhoto::serializeToStream(NativeByteBuffer *stream) { stream->writeInt64(photo_id); photo_small->serializeToStream(stream); photo_big->serializeToStream(stream); -} - -auth_SentCode *auth_SentCode::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) { - auth_SentCode *result = nullptr; - switch (constructor) { - case 0xe325edcf: - result = new TL_auth_sentAppCode(); - break; - case 0xefed51d9: - result = new TL_auth_sentCode(); - break; - default: - error = true; - if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in auth_SentCode", constructor); - return nullptr; - } - result->readParams(stream, instanceNum, error); - return result; -} - -void TL_auth_sentAppCode::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) { - phone_registered = stream->readBool(&error); - phone_code_hash = stream->readString(&error); - send_call_timeout = stream->readInt32(&error); - is_password = stream->readBool(&error); -} - -void TL_auth_sentAppCode::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); - stream->writeBool(phone_registered); - stream->writeString(phone_code_hash); - stream->writeInt32(send_call_timeout); - stream->writeBool(is_password); -} - -void TL_auth_sentCode::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) { - phone_registered = stream->readBool(&error); - phone_code_hash = stream->readString(&error); - send_call_timeout = stream->readInt32(&error); - is_password = stream->readBool(&error); -} - -void TL_auth_sentCode::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); - stream->writeBool(phone_registered); - stream->writeString(phone_code_hash); - stream->writeInt32(send_call_timeout); - stream->writeBool(is_password); -} - -TLObject *TL_auth_sendCode::deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) { - return auth_SentCode::TLdeserialize(stream, constructor, instanceNum, error); -} - -void TL_auth_sendCode::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); - stream->writeString(phone_number); - stream->writeInt32(sms_type); - stream->writeInt32(api_id); - stream->writeString(api_hash); - stream->writeString(lang_code); + stream->writeInt32(dc_id); } void TL_updatesTooLong::serializeToStream(NativeByteBuffer *stream) { stream->writeInt32(constructor); } - -TL_upload_file *TL_upload_file::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) { - if (TL_upload_file::constructor != constructor) { - error = true; - FileLog::e("can't parse magic %x in TL_upload_file", constructor); - return nullptr; - } - TL_upload_file *result = new TL_upload_file(); - result->readParams(stream, instanceNum, error); - return result; -} - -TL_upload_file::~TL_upload_file() { - if (bytes != nullptr) { - bytes->reuse(); - bytes = nullptr; - } -} - -void TL_upload_file::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) { - type = std::unique_ptr(storage_FileType::TLdeserialize(stream, stream->readUint32(&error), instanceNum, error)); - mtime = stream->readInt32(&error); - bytes = stream->readByteBuffer(true, &error); -} - -InputFileLocation *InputFileLocation::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) { - InputFileLocation *result = nullptr; - switch (constructor) { - case 0x430f0724: - result = new TL_inputDocumentFileLocation(); - break; - case 0x14637196: - result = new TL_inputFileLocation(); - break; - case 0xf5235d55: - result = new TL_inputEncryptedFileLocation(); - break; - default: - error = true; - FileLog::e("can't parse magic %x in InputFileLocation", constructor); - return nullptr; - } - result->readParams(stream, instanceNum, error); - return result; -} - -void TL_inputDocumentFileLocation::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) { - id = stream->readInt64(&error); - access_hash = stream->readInt64(&error); - version = stream->readInt32(&error); -} - -void TL_inputDocumentFileLocation::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); - stream->writeInt64(id); - stream->writeInt64(access_hash); - stream->writeInt32(version); -} - -void TL_inputFileLocation::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) { - volume_id = stream->readInt64(&error); - local_id = stream->readInt32(&error); - secret = stream->readInt64(&error); -} - -void TL_inputFileLocation::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); - stream->writeInt64(volume_id); - stream->writeInt32(local_id); - stream->writeInt64(secret); -} - -void TL_inputEncryptedFileLocation::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) { - id = stream->readInt64(&error); - access_hash = stream->readInt64(&error); -} - -void TL_inputEncryptedFileLocation::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); - stream->writeInt64(id); - stream->writeInt64(access_hash); -} - -storage_FileType *storage_FileType::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) { - storage_FileType *result = nullptr; - switch (constructor) { - case 0xaa963b05: - result = new TL_storage_fileUnknown(); - break; - case 0xb3cea0e4: - result = new TL_storage_fileMp4(); - break; - case 0x1081464c: - result = new TL_storage_fileWebp(); - break; - case 0xa4f63c0: - result = new TL_storage_filePng(); - break; - case 0xcae1aadf: - result = new TL_storage_fileGif(); - break; - case 0xae1e508d: - result = new TL_storage_filePdf(); - break; - case 0x528a0677: - result = new TL_storage_fileMp3(); - break; - case 0x7efe0e: - result = new TL_storage_fileJpeg(); - break; - case 0x4b09ebbc: - result = new TL_storage_fileMov(); - break; - case 0x40bc6f52: - result = new TL_storage_filePartial(); - break; - default: - error = true; - FileLog::e("can't parse magic %x in storage_FileType", constructor); - return nullptr; - } - result->readParams(stream, instanceNum, error); - return result; -} - -void TL_storage_fileUnknown::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); -} - -void TL_storage_fileMp4::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); -} - -void TL_storage_fileWebp::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); -} - -void TL_storage_filePng::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); -} - -void TL_storage_fileGif::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); -} - -void TL_storage_filePdf::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); -} - -void TL_storage_fileMp3::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); -} - -void TL_storage_fileJpeg::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); -} - -void TL_storage_fileMov::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); -} - -void TL_storage_filePartial::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); -} - -TLObject *TL_upload_saveFilePart::deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) { - return Bool::TLdeserialize(stream, constructor, instanceNum, error); -} - -void TL_upload_saveFilePart::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); - stream->writeInt64(file_id); - stream->writeInt32(file_part); - stream->writeByteArray(bytes.get()); -} - -bool TL_upload_saveFilePart::isNeedLayer() { - return true; -} - -TLObject *TL_upload_getFile::deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) { - return TL_upload_file::TLdeserialize(stream, constructor, instanceNum, error); -} - -void TL_upload_getFile::serializeToStream(NativeByteBuffer *stream) { - stream->writeInt32(constructor); - location->serializeToStream(stream); - stream->writeInt32(offset); - stream->writeInt32(limit); -} - -bool TL_upload_getFile::isNeedLayer() { - return true; -} diff --git a/TMessagesProj/jni/tgnet/ApiScheme.h b/TMessagesProj/jni/tgnet/ApiScheme.h index 03bae5799..122041cd6 100644 --- a/TMessagesProj/jni/tgnet/ApiScheme.h +++ b/TMessagesProj/jni/tgnet/ApiScheme.h @@ -98,7 +98,7 @@ public: class TL_config : public TLObject { public: - static const uint32_t constructor = 0xe6ca25f6; + static const uint32_t constructor = 0x330b4067; int32_t flags; int32_t date; @@ -128,6 +128,7 @@ public: int32_t channels_read_media_period; int32_t tmp_sessions; int32_t pinned_dialogs_count_max; + int32_t pinned_infolder_count_max; int32_t call_receive_timeout_ms; int32_t call_ring_timeout_ms; int32_t call_connect_timeout_ms; @@ -234,39 +235,16 @@ public: class FileLocation : public TLObject { public: - int32_t dc_id; int64_t volume_id; int32_t local_id; - int64_t secret; - std::unique_ptr file_reference; - std::unique_ptr key; - std::unique_ptr iv; static FileLocation *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error); }; -class TL_fileLocation : public FileLocation { +class TL_fileLocationToBeDeprecated : public FileLocation { public: - static const uint32_t constructor = 0x91d11eb; - - void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error); - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_fileEncryptedLocation : public FileLocation { - -public: - static const uint32_t constructor = 0x55555554; - - void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error); - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_fileLocationUnavailable : public FileLocation { - -public: - static const uint32_t constructor = 0x7c596b46; + static const uint32_t constructor = 0xbc7fc6cd; void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error); void serializeToStream(NativeByteBuffer *stream); @@ -278,6 +256,7 @@ public: int64_t photo_id; std::unique_ptr photo_small; std::unique_ptr photo_big; + int32_t dc_id; static UserProfilePhoto *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error); }; @@ -293,7 +272,7 @@ public: class TL_userProfilePhoto : public UserProfilePhoto { public: - static const uint32_t constructor = 0xd559d8c8; + static const uint32_t constructor = 0xecd75d8c; void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error); void serializeToStream(NativeByteBuffer *stream); @@ -387,50 +366,6 @@ public: void serializeToStream(NativeByteBuffer *stream); }; -class auth_SentCode : public TLObject { - -public: - bool phone_registered; - std::string phone_code_hash; - int32_t send_call_timeout; - bool is_password; - - static auth_SentCode *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error); -}; - -class TL_auth_sentAppCode : public auth_SentCode { - -public: - static const uint32_t constructor = 0xe325edcf; - - void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error); - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_auth_sentCode : public auth_SentCode { - -public: - static const uint32_t constructor = 0xefed51d9; - - void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error); - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_auth_sendCode : public TLObject { - -public: - static const uint32_t constructor = 0x768d5f4d; - - std::string phone_number; - int32_t sms_type; - int32_t api_id; - std::string api_hash; - std::string lang_code; - - TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error); - void serializeToStream(NativeByteBuffer *stream); -}; - class TL_updatesTooLong : public TLObject { public: @@ -439,173 +374,4 @@ public: void serializeToStream(NativeByteBuffer *stream); }; -class storage_FileType : public TLObject { - -public: - - static storage_FileType *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error); -}; - -class TL_storage_fileUnknown : public storage_FileType { - -public: - static const uint32_t constructor = 0xaa963b05; - - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_storage_fileMp4 : public storage_FileType { - -public: - static const uint32_t constructor = 0xb3cea0e4; - - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_storage_fileWebp : public storage_FileType { - -public: - static const uint32_t constructor = 0x1081464c; - - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_storage_filePng : public storage_FileType { - -public: - static const uint32_t constructor = 0xa4f63c0; - - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_storage_fileGif : public storage_FileType { - -public: - static const uint32_t constructor = 0xcae1aadf; - - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_storage_filePdf : public storage_FileType { - -public: - static const uint32_t constructor = 0xae1e508d; - - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_storage_fileMp3 : public storage_FileType { - -public: - static const uint32_t constructor = 0x528a0677; - - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_storage_fileJpeg : public storage_FileType { - -public: - static const uint32_t constructor = 0x7efe0e; - - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_storage_fileMov : public storage_FileType { - -public: - static const uint32_t constructor = 0x4b09ebbc; - - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_storage_filePartial : public storage_FileType { - -public: - static const uint32_t constructor = 0x40bc6f52; - - void serializeToStream(NativeByteBuffer *stream); -}; - -class InputFileLocation : public TLObject { - -public: - int64_t id; - int64_t access_hash; - int32_t version; - int64_t volume_id; - int32_t local_id; - int64_t secret; - - static InputFileLocation *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error); -}; - -class TL_inputDocumentFileLocation : public InputFileLocation { - -public: - static const uint32_t constructor = 0x430f0724; - - void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error); - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_inputFileLocation : public InputFileLocation { - -public: - static const uint32_t constructor = 0x14637196; - - void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error); - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_inputEncryptedFileLocation : public InputFileLocation { - -public: - static const uint32_t constructor = 0xf5235d55; - - void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error); - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_upload_saveFilePart : public TLObject { - -public: - static const uint32_t constructor = 0xb304a621; - - int64_t file_id; - int32_t file_part; - std::unique_ptr bytes; - - bool isNeedLayer(); - TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error); - void serializeToStream(NativeByteBuffer *stream); -}; - -class TL_upload_file : public TLObject { - -public: - static const uint32_t constructor = 0x96a18d5; - - std::unique_ptr type; - int32_t mtime; - NativeByteBuffer *bytes = nullptr; - - ~TL_upload_file(); - static TL_upload_file *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error); - void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error); -}; - -class TL_upload_getFile : public TLObject { - -public: - static const uint32_t constructor = 0xe3a6cfb5; - - InputFileLocation *location; - int32_t offset; - int32_t limit; - - bool isNeedLayer(); - TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error); - void serializeToStream(NativeByteBuffer *stream); -}; - #endif diff --git a/TMessagesProj/jni/tgnet/BuffersStorage.cpp b/TMessagesProj/jni/tgnet/BuffersStorage.cpp index 061cc82ac..f42bd34e1 100644 --- a/TMessagesProj/jni/tgnet/BuffersStorage.cpp +++ b/TMessagesProj/jni/tgnet/BuffersStorage.cpp @@ -111,7 +111,7 @@ void BuffersStorage::reuseFreeBuffer(NativeByteBuffer *buffer) { if (arrayToReuse->size() < maxCount) { arrayToReuse->push_back(buffer); } else { - if (LOGS_ENABLED) DEBUG_D("too more %d buffers", capacity); + if (LOGS_ENABLED) DEBUG_D("too much %d buffers", capacity); delete buffer; } if (isThreadSafe) { diff --git a/TMessagesProj/jni/tgnet/Connection.cpp b/TMessagesProj/jni/tgnet/Connection.cpp index 25b2673a8..c11b9ff27 100644 --- a/TMessagesProj/jni/tgnet/Connection.cpp +++ b/TMessagesProj/jni/tgnet/Connection.cpp @@ -288,6 +288,7 @@ void Connection::connect() { if (connectionState == TcpConnectionStageConnected || connectionState == TcpConnectionStageConnecting) { return; } + connectionInProcess = true; connectionState = TcpConnectionStageConnecting; isMediaConnection = false; uint32_t ipv6 = ConnectionsManager::getInstance(currentDatacenter->instanceNum).isIpv6Enabled() ? TcpAddressFlagIpv6 : 0; @@ -369,6 +370,7 @@ void Connection::connect() { setTimeout(12); } } + connectionInProcess = false; } void Connection::reconnect() { @@ -643,7 +645,7 @@ inline void Connection::encryptKeyWithSecret(uint8_t *bytes, uint8_t secretType) SHA256_Final(bytes, &sha256Ctx); } -void Connection::onDisconnected(int32_t reason, int32_t error) { +void Connection::onDisconnectedInternal(int32_t reason, int32_t error) { reconnectTimer->stop(); if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) disconnected with reason %d", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType, reason); bool switchToNextPort = reason == 2 && wasConnected && (!hasSomeDataSinceLastConnect || currentDatacenter->isCustomPort(currentAddressFlags)) || forceNextPort; @@ -677,7 +679,7 @@ void Connection::onDisconnected(int32_t reason, int32_t error) { willRetryConnectCount = 1; } } - if (ConnectionsManager::getInstance(currentDatacenter->instanceNum).isNetworkAvailable()) { + if (ConnectionsManager::getInstance(currentDatacenter->instanceNum).isNetworkAvailable() && connectionType != ConnectionTypeProxy) { isTryingNextPort = true; if (failedConnectionCount > willRetryConnectCount || switchToNextPort) { currentDatacenter->nextAddressOrPort(currentAddressFlags); @@ -706,6 +708,16 @@ void Connection::onDisconnected(int32_t reason, int32_t error) { usefullData = false; } +void Connection::onDisconnected(int32_t reason, int32_t error) { + if (connectionInProcess) { + ConnectionsManager::getInstance(currentDatacenter->instanceNum).scheduleTask([&, reason, error] { + onDisconnectedInternal(reason, error); + }); + } else { + onDisconnectedInternal(reason, error); + } +} + void Connection::onConnected() { connectionState = TcpConnectionStageConnected; connectionToken = lastConnectionToken++; diff --git a/TMessagesProj/jni/tgnet/Connection.h b/TMessagesProj/jni/tgnet/Connection.h index 445594046..dd984f2c1 100644 --- a/TMessagesProj/jni/tgnet/Connection.h +++ b/TMessagesProj/jni/tgnet/Connection.h @@ -69,6 +69,7 @@ private: inline void encryptKeyWithSecret(uint8_t *array, uint8_t secretType); inline std::string *getCurrentSecret(uint8_t secretType); + void onDisconnectedInternal(int32_t reason, int32_t error); ProtocolType currentProtocolType = ProtocolTypeEE; @@ -94,6 +95,7 @@ private: bool forceNextPort = false; bool isMediaConnection = false; bool waitForReconnectTimer = false; + bool connectionInProcess = false; uint32_t lastReconnectTimeout = 100; int64_t usefullDataReceiveTime; uint32_t currentTimeout = 4; diff --git a/TMessagesProj/jni/tgnet/ConnectionSocket.cpp b/TMessagesProj/jni/tgnet/ConnectionSocket.cpp index a3cc025b6..8929d21a0 100644 --- a/TMessagesProj/jni/tgnet/ConnectionSocket.cpp +++ b/TMessagesProj/jni/tgnet/ConnectionSocket.cpp @@ -51,7 +51,8 @@ void ConnectionSocket::openConnection(std::string address, uint16_t port, bool i isIpv6 = ipv6; currentAddress = address; currentPort = port; - int epolFd = ConnectionsManager::getInstance(instanceNum).epolFd; + waitingForHostResolve = ""; + adjustWriteOpAfterResolve = false; ConnectionsManager::getInstance(instanceNum).attachConnection(this); memset(&socketAddress, 0, sizeof(sockaddr_in)); @@ -96,32 +97,28 @@ void ConnectionSocket::openConnection(std::string address, uint16_t port, bool i continueCheckAddress = false; } if (continueCheckAddress) { - std::string host = ConnectionsManager::getInstance(instanceNum).delegate->getHostByName(*proxyAddress, instanceNum); - if (host.empty() || inet_pton(AF_INET, host.c_str(), &socketAddress.sin_addr.s_addr) != 1) { - continueCheckAddress = true; - if (LOGS_ENABLED) DEBUG_E("connection(%p) can't resolve host %s address via delegate", this, proxyAddress->c_str()); +#ifdef USE_DELEGATE_HOST_RESOLVE + waitingForHostResolve = *proxyAddress; + ConnectionsManager::getInstance(instanceNum).delegate->getHostByName(*proxyAddress, instanceNum, this); + return; +#else + struct hostent *he; + if ((he = gethostbyname(proxyAddress->c_str())) == nullptr) { + if (LOGS_ENABLED) DEBUG_E("connection(%p) can't resolve host %s address", this, proxyAddress->c_str()); + closeSocket(1, -1); + return; + } + struct in_addr **addr_list = (struct in_addr **) he->h_addr_list; + if (addr_list[0] != nullptr) { + socketAddress.sin_addr.s_addr = addr_list[0]->s_addr; + if (LOGS_ENABLED) DEBUG_D("connection(%p) resolved host %s address %x", this, proxyAddress->c_str(), addr_list[0]->s_addr); + ipv6 = false; } else { - continueCheckAddress = false; - if (LOGS_ENABLED) DEBUG_D("connection(%p) resolved host %s address %x via delegate", this, proxyAddress->c_str(), socketAddress.sin_addr.s_addr); - } - if (continueCheckAddress) { - struct hostent *he; - if ((he = gethostbyname(proxyAddress->c_str())) == nullptr) { - if (LOGS_ENABLED) DEBUG_E("connection(%p) can't resolve host %s address", this, proxyAddress->c_str()); - closeSocket(1, -1); - return; - } - struct in_addr **addr_list = (struct in_addr **) he->h_addr_list; - if (addr_list[0] != nullptr) { - socketAddress.sin_addr.s_addr = addr_list[0]->s_addr; - if (LOGS_ENABLED) DEBUG_D("connection(%p) resolved host %s address %x", this, proxyAddress->c_str(), addr_list[0]->s_addr); - ipv6 = false; - } else { - if (LOGS_ENABLED) DEBUG_E("connection(%p) can't resolve host %s address", this, proxyAddress->c_str()); - closeSocket(1, -1); - return; - } + if (LOGS_ENABLED) DEBUG_E("connection(%p) can't resolve host %s address", this, proxyAddress->c_str()); + closeSocket(1, -1); + return; } +#endif } } } else { @@ -150,6 +147,11 @@ void ConnectionSocket::openConnection(std::string address, uint16_t port, bool i } } + openConnectionInternal(ipv6); +} + +void ConnectionSocket::openConnectionInternal(bool ipv6) { + int epolFd = ConnectionsManager::getInstance(instanceNum).epolFd; int yes = 1; if (setsockopt(socketFd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(int))) { if (LOGS_ENABLED) DEBUG_E("connection(%p) set TCP_NODELAY failed", this); @@ -171,6 +173,9 @@ void ConnectionSocket::openConnection(std::string address, uint16_t port, bool i closeSocket(1, -1); } } + if (adjustWriteOpAfterResolve) { + adjustWriteOp(); + } } int32_t ConnectionSocket::checkSocketError(int32_t *error) { @@ -198,6 +203,8 @@ void ConnectionSocket::closeSocket(int32_t reason, int32_t error) { } socketFd = -1; } + waitingForHostResolve = ""; + adjustWriteOpAfterResolve = false; proxyAuthState = 0; onConnectedSent = false; outgoingByteStream->clean(); @@ -401,6 +408,10 @@ void ConnectionSocket::writeBuffer(NativeByteBuffer *buffer) { } void ConnectionSocket::adjustWriteOp() { + if (!waitingForHostResolve.empty()) { + adjustWriteOpAfterResolve = true; + return; + } eventMask.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLET; if (proxyAuthState == 0 && (outgoingByteStream->hasData() || !onConnectedSent) || proxyAuthState == 1 || proxyAuthState == 3 || proxyAuthState == 5) { eventMask.events |= EPOLLOUT; @@ -433,6 +444,10 @@ void ConnectionSocket::checkTimeout(int64_t now) { } } +void ConnectionSocket::resetLastEventTime() { + lastEventTime = ConnectionsManager::getInstance(instanceNum).getCurrentTimeMonotonicMillis(); +} + bool ConnectionSocket::isDisconnected() { return socketFd < 0; } @@ -447,4 +462,19 @@ void ConnectionSocket::setOverrideProxy(std::string address, uint16_t port, std: overrideProxyUser = username; overrideProxyPassword = password; overrideProxySecret = secret; -} \ No newline at end of file +} + +void ConnectionSocket::onHostNameResolved(std::string host, std::string ip, bool ipv6) { + ConnectionsManager::getInstance(instanceNum).scheduleTask([&, host, ip, ipv6] { + if (waitingForHostResolve == host) { + waitingForHostResolve = ""; + if (ip.empty() || inet_pton(AF_INET, ip.c_str(), &socketAddress.sin_addr.s_addr) != 1) { + if (LOGS_ENABLED) DEBUG_E("connection(%p) can't resolve host %s address via delegate", this, host.c_str()); + closeSocket(1, -1); + return; + } + if (LOGS_ENABLED) DEBUG_D("connection(%p) resolved host %s address %x via delegate", this, ip.c_str(), socketAddress.sin_addr.s_addr); + openConnectionInternal(ipv6); + } + }); +} diff --git a/TMessagesProj/jni/tgnet/ConnectionSocket.h b/TMessagesProj/jni/tgnet/ConnectionSocket.h index 059cb2169..f53b14d29 100644 --- a/TMessagesProj/jni/tgnet/ConnectionSocket.h +++ b/TMessagesProj/jni/tgnet/ConnectionSocket.h @@ -32,11 +32,13 @@ public: bool isDisconnected(); void dropConnection(); void setOverrideProxy(std::string address, uint16_t port, std::string username, std::string password, std::string secret); + void onHostNameResolved(std::string host, std::string ip, bool ipv6); protected: int32_t instanceNum; void onEvent(uint32_t events); void checkTimeout(int64_t now); + void resetLastEventTime(); virtual void onReceivedData(NativeByteBuffer *buffer) = 0; virtual void onDisconnected(int32_t reason, int32_t error) = 0; virtual void onConnected() = 0; @@ -63,12 +65,16 @@ private: std::string currentAddress; uint16_t currentPort; + std::string waitingForHostResolve; + bool adjustWriteOpAfterResolve; + uint8_t buffer[1024]; uint8_t proxyAuthState; int32_t checkSocketError(int32_t *error); void closeSocket(int32_t reason, int32_t error); + void openConnectionInternal(bool ipv6); void adjustWriteOp(); friend class EventObject; diff --git a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp index 83745805b..11b16b75c 100644 --- a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp +++ b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp @@ -159,7 +159,7 @@ int ConnectionsManager::callEvents(int64_t now) { if (!networkPaused) { return 1000; } - int32_t timeToPushPing = (int32_t) ((sendingPushPing ? 30000 : 60000 * 3) - llabs(now - lastPushPingTime)); + int32_t timeToPushPing = (int32_t) ((sendingPushPing ? 30000 : nextPingTimeOffset) - llabs(now - lastPushPingTime)); if (timeToPushPing <= 0) { return 1000; } @@ -168,13 +168,19 @@ int ConnectionsManager::callEvents(int64_t now) { } void ConnectionsManager::checkPendingTasks() { + int32_t count = INT_MAX; while (true) { std::function task; pthread_mutex_lock(&mutex); - if (pendingTasks.empty()) { + if (pendingTasks.empty() || count <= 0) { pthread_mutex_unlock(&mutex); return; } + if (count == INT_MAX) { + count = (int32_t) pendingTasks.size(); + } else { + count--; + } task = pendingTasks.front(); pendingTasks.pop(); pthread_mutex_unlock(&mutex); @@ -199,7 +205,7 @@ void ConnectionsManager::select() { Datacenter *datacenter = getDatacenterWithId(currentDatacenterId); if (pushConnectionEnabled) { - if ((sendingPushPing && llabs(now - lastPushPingTime) >= 30000) || llabs(now - lastPushPingTime) >= 60000 * 3 + 10000) { + if ((sendingPushPing && llabs(now - lastPushPingTime) >= 30000) || llabs(now - lastPushPingTime) >= nextPingTimeOffset + 10000) { lastPushPingTime = 0; sendingPushPing = false; if (datacenter != nullptr) { @@ -210,9 +216,12 @@ void ConnectionsManager::select() { } if (LOGS_ENABLED) DEBUG_D("push ping timeout"); } - if (llabs(now - lastPushPingTime) >= 60000 * 3) { + if (llabs(now - lastPushPingTime) >= nextPingTimeOffset) { if (LOGS_ENABLED) DEBUG_D("time for push ping"); lastPushPingTime = now; + uint8_t offset; + RAND_bytes(&offset, 1); + nextPingTimeOffset = 60000 * 3 + (offset % 40) - 20; if (datacenter != nullptr) { sendPing(datacenter, true); } @@ -669,35 +678,33 @@ void ConnectionsManager::onConnectionClosed(Connection *connection, int reason) } else if (connection->getConnectionType() == ConnectionTypePush) { if (LOGS_ENABLED) DEBUG_D("connection(%p) push connection closed", connection); sendingPushPing = false; - lastPushPingTime = getCurrentTimeMonotonicMillis() - 60000 * 3 + 4000; + lastPushPingTime = getCurrentTimeMonotonicMillis() - nextPingTimeOffset + 4000; } else if (connection->getConnectionType() == ConnectionTypeProxy) { - scheduleTask([&, connection] { - for (std::vector>::iterator iter = proxyActiveChecks.begin(); iter != proxyActiveChecks.end(); iter++) { - ProxyCheckInfo *proxyCheckInfo = iter->get(); - if (proxyCheckInfo->connectionNum == connection->getConnectionNum()) { - bool found = false; - for (requestsIter iter2 = runningRequests.begin(); iter2 != runningRequests.end(); iter2++) { - Request *request = iter2->get(); - if (connection->getConnectionToken() == request->connectionToken && request->requestToken == proxyCheckInfo->requestToken && (request->connectionType & 0x0000ffff) == ConnectionTypeProxy) { - request->completed = true; - runningRequests.erase(iter2); - proxyCheckInfo->onRequestTime(-1); - found = true; - break; - } + for (std::vector>::iterator iter = proxyActiveChecks.begin(); iter != proxyActiveChecks.end(); iter++) { + ProxyCheckInfo *proxyCheckInfo = iter->get(); + if (proxyCheckInfo->connectionNum == connection->getConnectionNum()) { + bool found = false; + for (requestsIter iter2 = runningRequests.begin(); iter2 != runningRequests.end(); iter2++) { + Request *request = iter2->get(); + if (connection->getConnectionToken() == request->connectionToken && request->requestToken == proxyCheckInfo->requestToken && (request->connectionType & 0x0000ffff) == ConnectionTypeProxy) { + request->completed = true; + runningRequests.erase(iter2); + proxyCheckInfo->onRequestTime(-1); + found = true; + break; } - if (found) { - proxyActiveChecks.erase(iter); - if (!proxyCheckQueue.empty()) { - proxyCheckInfo = proxyCheckQueue[0].release(); - proxyCheckQueue.erase(proxyCheckQueue.begin()); - checkProxyInternal(proxyCheckInfo); - } - } - break; } + if (found) { + proxyActiveChecks.erase(iter); + if (!proxyCheckQueue.empty()) { + proxyCheckInfo = proxyCheckQueue[0].release(); + proxyCheckQueue.erase(proxyCheckQueue.begin()); + checkProxyInternal(proxyCheckInfo); + } + } + break; } - }); + } } } @@ -2365,7 +2372,7 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t } else { currentCount = 0; } - if (!networkAvailable || currentCount >= 6) { + if (!networkAvailable || currentCount >= 10) { iter++; continue; } @@ -2427,6 +2434,9 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t networkMessage->invokeAfter = (request->requestFlags & RequestFlagInvokeAfter) != 0; networkMessage->needQuickAck = (request->requestFlags & RequestFlagNeedQuickAck) != 0; + if (!hasPendingRequestsForConnection(connection)) { + connection->resetLastEventTime(); + } runningRequests.push_back(std::move(*iter)); switch (request->connectionType & 0x0000ffff) { @@ -3202,7 +3212,7 @@ void ConnectionsManager::checkProxyInternal(ProxyCheckInfo *proxyCheckInfo) { } else { ConnectionType connectionType = (ConnectionType) (ConnectionTypeProxy | (freeConnectionNum << 16)); Datacenter *datacenter = getDatacenterWithId(DEFAULT_DATACENTER_ID); - Connection *connection = datacenter->getConnectionByType(connectionType, true, 1); + Connection *connection = datacenter->getProxyConnection((uint8_t) freeConnectionNum, true, false); if (connection != nullptr) { connection->setOverrideProxy(proxyCheckInfo->address, proxyCheckInfo->port, proxyCheckInfo->username, proxyCheckInfo->password, proxyCheckInfo->secret); connection->suspendConnection(); diff --git a/TMessagesProj/jni/tgnet/ConnectionsManager.h b/TMessagesProj/jni/tgnet/ConnectionsManager.h index 05f7e6c84..a5dee782b 100644 --- a/TMessagesProj/jni/tgnet/ConnectionsManager.h +++ b/TMessagesProj/jni/tgnet/ConnectionsManager.h @@ -146,6 +146,7 @@ private: int32_t currentPingTime = 0; bool registeringForPush = false; int64_t lastPushPingTime = 0; + int32_t nextPingTimeOffset = 60000 * 3; bool sendingPushPing = false; bool sendingPing = false; bool updatingDcSettings = false; @@ -233,7 +234,6 @@ private: friend class TL_message; friend class TL_rpc_result; friend class Config; - friend class FileLoadOperation; friend class FileLog; friend class Handshake; }; diff --git a/TMessagesProj/jni/tgnet/Datacenter.cpp b/TMessagesProj/jni/tgnet/Datacenter.cpp index 9e5c16e48..6ac13dd91 100644 --- a/TMessagesProj/jni/tgnet/Datacenter.cpp +++ b/TMessagesProj/jni/tgnet/Datacenter.cpp @@ -1255,13 +1255,16 @@ Connection *Datacenter::createConnectionByType(uint32_t connectionType) { } } -Connection *Datacenter::getProxyConnection(uint8_t num, bool create) { +Connection *Datacenter::getProxyConnection(uint8_t num, bool create, bool connect) { ByteArray *authKey = getAuthKey(ConnectionTypeProxy, false, nullptr, 1); if (authKey == nullptr) { return nullptr; } if (create) { - createProxyConnection(num)->connect(); + Connection *connection = createProxyConnection(num); + if (connect) { + connection->connect(); + } } return proxyConnection[num]; } @@ -1349,7 +1352,7 @@ Connection *Datacenter::getConnectionByType(uint32_t connectionType, bool create case ConnectionTypeTemp: return getTempConnection(create); case ConnectionTypeProxy: - return getProxyConnection(connectionNum, create); + return getProxyConnection(connectionNum, create, create); default: return nullptr; } diff --git a/TMessagesProj/jni/tgnet/Datacenter.h b/TMessagesProj/jni/tgnet/Datacenter.h index 85ee3a992..85c580416 100644 --- a/TMessagesProj/jni/tgnet/Datacenter.h +++ b/TMessagesProj/jni/tgnet/Datacenter.h @@ -59,7 +59,7 @@ public: void resetInitVersion(); Connection *getDownloadConnection(uint8_t num, bool create); - Connection *getProxyConnection(uint8_t num, bool create); + Connection *getProxyConnection(uint8_t num, bool create, bool connect); Connection *getUploadConnection(uint8_t num, bool create); Connection *getGenericConnection(bool create, int32_t allowPendingKey); Connection *getGenericMediaConnection(bool create, int32_t allowPendingKey); diff --git a/TMessagesProj/jni/tgnet/Defines.h b/TMessagesProj/jni/tgnet/Defines.h index c14003cfd..359dbcacb 100644 --- a/TMessagesProj/jni/tgnet/Defines.h +++ b/TMessagesProj/jni/tgnet/Defines.h @@ -30,6 +30,7 @@ #define UPLOAD_CONNECTIONS_COUNT 4 #define CONNECTION_BACKGROUND_KEEP_TIME 10000 #define MAX_ACCOUNT_COUNT 3 +#define USE_DELEGATE_HOST_RESOLVE #define DOWNLOAD_CHUNK_SIZE 1024 * 32 #define DOWNLOAD_CHUNK_BIG_SIZE 1024 * 128 @@ -47,8 +48,8 @@ class Request; class TL_message; class TL_config; class NativeByteBuffer; -class FileLoadOperation; class Handshake; +class ConnectionSocket; typedef std::function onCompleteFunc; typedef std::function onQuickAckFunc; @@ -151,7 +152,7 @@ typedef struct ConnectiosManagerDelegate { virtual void onBytesReceived(int32_t amount, int32_t networkType, int32_t instanceNum) = 0; virtual void onRequestNewServerIpAndPort(int32_t second, int32_t instanceNum) = 0; virtual void onProxyError(int32_t instanceNum) = 0; - virtual std::string getHostByName(std::string domain, int32_t instanceNum) = 0; + virtual void getHostByName(std::string domain, int32_t instanceNum, ConnectionSocket *socket) = 0; virtual int32_t getInitFlags(int32_t instanceNum) = 0; } ConnectiosManagerDelegate; diff --git a/TMessagesProj/jni/tgnet/FileLoadOperation.cpp b/TMessagesProj/jni/tgnet/FileLoadOperation.cpp deleted file mode 100644 index 9bf5060aa..000000000 --- a/TMessagesProj/jni/tgnet/FileLoadOperation.cpp +++ /dev/null @@ -1,395 +0,0 @@ -/* - * This is the source code of tgnet library v. 1.1 - * 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, 2015-2018. - */ - -#include "FileLoadOperation.h" -#include -#include "ApiScheme.h" -#include "ByteArray.h" -#include "MTProtoScheme.h" -#include "FileLog.h" -#include "ConnectionsManager.h" -#include "NativeByteBuffer.h" -#include "Datacenter.h" - -FileLoadOperation::FileLoadOperation(int32_t dc_id, int64_t id, int64_t volume_id, int64_t access_hash, int32_t local_id, uint8_t *encKey, uint8_t *encIv, std::string extension, int32_t version, int32_t size, std::string dest, std::string temp) { - if (!dest.empty() && dest.find_last_of('/') != dest.size() - 1) { - dest += "/"; - } - if (!temp.empty() && temp.find_last_of('/') != temp.size() - 1) { - temp += "/"; - } - if (encKey != nullptr) { - location = std::unique_ptr(new TL_inputEncryptedFileLocation()); - location->id = id; - location->access_hash = access_hash; - location->volume_id = volume_id; - location->local_id = local_id; - key = std::unique_ptr(new ByteArray(encKey, 32)); - iv = std::unique_ptr(new ByteArray(encIv, 32)); - } else { - if (volume_id != 0) { - location = std::unique_ptr(new TL_inputFileLocation()); - location->volume_id = volume_id; - location->local_id = local_id; - location->secret = access_hash; - } else { - location = std::unique_ptr(new TL_inputDocumentFileLocation()); - location->id = id; - location->access_hash = access_hash; - location->version = version; - } - } - destPath = dest; - tempPath = temp; - datacenter_id = dc_id; - totalBytesCount = size; - ext = extension; - if (key != nullptr) { - if (totalBytesCount % 16 != 0) { - bytesCountPadding = 16 - totalBytesCount % 16; - totalBytesCount += bytesCountPadding; - } - } -} - -FileLoadOperation::~FileLoadOperation() { -#ifdef ANDROID - if (ptr1 != nullptr) { - jniEnv[0]->DeleteGlobalRef(ptr1); - ptr1 = nullptr; - } -#endif -} - -void FileLoadOperation::start() { - ConnectionsManager::getInstance(0).scheduleTask([&] { - if (state != FileLoadStateIdle) { - return; - } - currentDownloadChunkSize = totalBytesCount >= DOWNLOAD_BIG_FILE_MIN_SIZE ? DOWNLOAD_CHUNK_BIG_SIZE : DOWNLOAD_CHUNK_SIZE; - currentMaxDownloadRequests = totalBytesCount >= DOWNLOAD_BIG_FILE_MIN_SIZE ? DOWNLOAD_MAX_BIG_REQUESTS : DOWNLOAD_MAX_REQUESTS; - state = FileLoadStateDownloading; - if (location == nullptr) { - onFailedLoadingFile(FileLoadFailReasonError); - return; - } - std::string prefix; - if (location->volume_id != 0 && location->local_id != 0) { - if (datacenter_id == INT_MIN || location->volume_id == INT_MIN || datacenter_id == 0) { - onFailedLoadingFile(FileLoadFailReasonError); - return; - } - prefix = to_string_uint64(location->volume_id) + "_" + to_string_int32(location->local_id); - } else { - if (datacenter_id == 0 || location->id == 0) { - onFailedLoadingFile(FileLoadFailReasonError); - return; - } - prefix = to_string_int32(datacenter_id) + "_" + to_string_uint64(location->id); - } - filePath = destPath + prefix + "." + ext; - tempFilePath = tempPath + prefix + ".temp"; - if (key != nullptr) { - tempFileIvPath = tempPath + prefix + ".iv"; - } - - FILE *destFile = fopen(filePath.c_str(), "rb"); - if (destFile != nullptr) { - long len = ftell(destFile); - if (totalBytesCount != 0 && totalBytesCount != len) { - fclose(destFile); - destFile = nullptr; - remove(filePath.c_str()); - } - } - - if (destFile == nullptr) { - tempFile = fopen(tempFilePath.c_str(), "r+b"); - if (tempFile != nullptr) { - if (!fseek(tempFile, 0, SEEK_END) && (downloadedBytes = ftell(tempFile)) != -1L) { - nextDownloadOffset = downloadedBytes = downloadedBytes / currentDownloadChunkSize * currentDownloadChunkSize; - } else { - fclose(tempFile); - tempFile = nullptr; - } - } - - if (key != nullptr) { - if (tempFile != nullptr) { - tempIvFile = fopen(tempFileIvPath.c_str(), "r+b"); - if (tempIvFile != nullptr) { - if (fread(iv->bytes, sizeof(uint8_t), 32, tempIvFile) != 32) { - fclose(tempIvFile); - tempIvFile = nullptr; - } - } - } - if (tempIvFile == nullptr) { - tempIvFile = fopen(tempFileIvPath.c_str(), "w+b"); - nextDownloadOffset = downloadedBytes = 0; - if (tempIvFile == nullptr) { - onFailedLoadingFile(FileLoadFailReasonError); - return; - } - } - } - - if (tempFile != nullptr) { - if (downloadedBytes != 0) { - if (!fseek(tempFile, downloadedBytes, SEEK_SET)) { - if (LOGS_ENABLED) DEBUG_D("resume loading file to temp = %s final = %s from %d", tempFilePath.c_str(), filePath.c_str(), nextDownloadOffset); - } else { - fclose(tempFile); - tempFile = nullptr; - } - } - } - if (tempFile == nullptr) { - nextDownloadOffset = downloadedBytes = 0; - tempFile = fopen(tempFilePath.c_str(), "w+b"); - if (tempFile == nullptr) { - onFailedLoadingFile(FileLoadFailReasonError); - return; - } - if (LOGS_ENABLED) DEBUG_D("start loading file to temp = %s final = %s", tempFilePath.c_str(), filePath.c_str()); - } - if (totalBytesCount != 0 && downloadedBytes == totalBytesCount) { - onFinishLoadingFile(); - } else { - startDownloadRequest(); - } - } else { - fclose(destFile); - onFinishLoadingFile(); - } - }); -} - -/*void setForceRequest(boolean forceRequest) { TODO - isForceRequest = forceRequest; -} - -boolean isForceRequest() { - return isForceRequest; -} -*/ - -void FileLoadOperation::cancel() { - ConnectionsManager::getInstance(0).scheduleTask([&] { - if (state == FileLoadStateFinished || state == FileLoadStateFailed) { - return; - } - onFailedLoadingFile(FileLoadFailReasonCanceled); - }); -} - -void FileLoadOperation::setDelegate(onFinishedFunc onFinished, onFailedFunc onFailed, onProgressChangedFunc onProgressChanged) { - onFinishedCallback = onFinished; - onFailedCallback = onFailed; - onProgressChangedCallback = onProgressChanged; -} - -void FileLoadOperation::cleanup() { - ConnectionsManager::getInstance(0).scheduleTask([&] { - if (tempFile != nullptr) { - fclose(tempFile); - tempFile = nullptr; - } - if (tempIvFile != nullptr) { - fclose(tempIvFile); - tempIvFile = nullptr; - } - for (size_t a = 0; a < requestInfos.size(); a++) { - if (requestInfos[a] != nullptr && requestInfos[a]->requestToken != 0) { - ConnectionsManager::getInstance(0).cancelRequestInternal(requestInfos[a]->requestToken, 0, true, false); - } - } - requestInfos.clear(); - delayedRequestInfos.clear(); - delete this; - }); -} - -void FileLoadOperation::onFinishLoadingFile() { - if (state != FileLoadStateDownloading) { - return; - } - state = FileLoadStateFinished; - if (tempIvFile != nullptr) { - fclose(tempIvFile); - tempIvFile = nullptr; - remove(tempFileIvPath.c_str()); - } - if (tempFile != nullptr) { - fclose(tempFile); - tempFile = nullptr; - if (rename(tempFilePath.c_str(), filePath.c_str())) { - if (LOGS_ENABLED) DEBUG_E("unable to rename temp = %s to final = %s", tempFilePath.c_str(), filePath.c_str()); - filePath = tempFilePath; - } - } - if (LOGS_ENABLED) DEBUG_D("finished downloading file %s", filePath.c_str()); - if (onFinishedCallback != nullptr) { - onFinishedCallback(filePath); - } - cleanup(); -} - -void FileLoadOperation::onFailedLoadingFile(int reason) { - if (state == FileLoadStateFailed) { - return; - } - state = FileLoadStateFailed; - if (onFailedCallback != nullptr) { - onFailedCallback(FileLoadFailReasonCanceled); - } - cleanup(); -} - -void FileLoadOperation::processRequestResult(RequestInfo *requestInfo, TL_error *error, bool next) { - std::unique_ptr info; - if (!next) { - std::vector>::iterator iter = std::find_if(requestInfos.begin(), requestInfos.end(), [&](std::unique_ptr &p) { - return p.get() == requestInfo; - }); - if (iter != requestInfos.end()) { - info = std::move(*iter); - requestInfos.erase(iter); - } - } - if (error == nullptr) { - if (!next && downloadedBytes != requestInfo->offset) { - if (state == FileLoadStateDownloading) { - delayedRequestInfos.push_back(std::move(info)); - startDownloadRequest(); - } - return; - } - - if (requestInfo->bytes == nullptr || requestInfo->bytes->limit() == 0) { - onFinishLoadingFile(); - return; - } - int32_t currentBytesSize = requestInfo->bytes->limit(); - downloadedBytes += currentBytesSize; - bool finishedDownloading = currentBytesSize != currentDownloadChunkSize || ((totalBytesCount == downloadedBytes || downloadedBytes % currentDownloadChunkSize != 0) && (totalBytesCount <= 0 || totalBytesCount <= downloadedBytes)); - - if (key != nullptr) { - Datacenter::aesIgeEncryption(requestInfo->bytes->bytes(), key->bytes, iv->bytes, false, true, currentBytesSize); - if (finishedDownloading && bytesCountPadding != 0) { - requestInfo->bytes->limit(currentBytesSize = (currentBytesSize - bytesCountPadding)); - } - } - if (tempFile != nullptr) { - if (fwrite(requestInfo->bytes->bytes(), sizeof(uint8_t), currentBytesSize, tempFile) != (uint32_t) currentBytesSize) { - onFailedLoadingFile(FileLoadFailReasonError); - return; - } - } - if (tempIvFile != nullptr) { - if (fseek(tempIvFile, 0, SEEK_SET) || fwrite(iv->bytes, sizeof(uint8_t), 32, tempIvFile) != 32) { - onFailedLoadingFile(FileLoadFailReasonError); - return; - } - } - if (totalBytesCount > 0 && state == FileLoadStateDownloading) { - float progress = (float) downloadedBytes / (float) totalBytesCount; - if (progress > 1.0f) { - progress = 1.0f; - } - if (onProgressChangedCallback != nullptr) { - onProgressChangedCallback(progress); - } - } - - for (std::vector>::iterator iter = delayedRequestInfos.begin(); iter != delayedRequestInfos.end(); iter++) { - if (downloadedBytes == (*iter)->offset) { - info = std::move(*iter); - delayedRequestInfos.erase(iter); - processRequestResult(info.get(), nullptr, true); - break; - } - } - - if (finishedDownloading) { - onFinishLoadingFile(); - } else { - startDownloadRequest(); - } - } else { - static std::string fileMigrate = "FILE_MIGRATE_"; - static std::string offsetInvalid = "OFFSET_INVALID"; - static std::string retryLimit = "RETRY_LIMIT"; - if (error->text.find(fileMigrate) != std::string::npos) { - /*std::string num = error->text.substr(fileMigrate.size(), error->text.size() - fileMigrate.size()); - int32_t dcId = atoi(num.c_str()); - if (dcId <= 0) { - onFailedLoadingFile(FileLoadFailReasonError); - } else { - datacenter_id = dcId; - nextDownloadOffset = downloadedBytes = 0; - startDownloadRequest(); - }*/ - onFailedLoadingFile(FileLoadFailReasonError); - } else if (error->text.find(offsetInvalid) != std::string::npos) { - if (downloadedBytes % currentDownloadChunkSize == 0) { - onFinishLoadingFile(); - } else { - onFailedLoadingFile(FileLoadFailReasonError); - } - } else if (error->text.find(retryLimit) != std::string::npos) { - onFailedLoadingFile(FileLoadFailReasonRetryLimit); - } else { - onFailedLoadingFile(FileLoadFailReasonError); - } - } -} - -void FileLoadOperation::startDownloadRequest() { - if (state != FileLoadStateDownloading || (totalBytesCount > 0 && nextDownloadOffset >= totalBytesCount) || ((requestInfos.size() + delayedRequestInfos.size()) >= currentMaxDownloadRequests)) { - return; - } - int32_t count = 1; - if (totalBytesCount > 0) { - count = currentMaxDownloadRequests - requestInfos.size(); - } - - for (int32_t a = 0; a < count; a++) { - if (totalBytesCount > 0 && nextDownloadOffset >= totalBytesCount) { - break; - } - bool isLast = totalBytesCount <= 0 || a == count - 1 || (totalBytesCount > 0 && (nextDownloadOffset + currentDownloadChunkSize) >= totalBytesCount); - - RequestInfo *requestInfo = new RequestInfo(); - requestInfos.push_back(std::unique_ptr(requestInfo)); - - TL_upload_getFile *request = new TL_upload_getFile(); - request->location = location.get(); - requestInfo->offset = request->offset = nextDownloadOffset; - request->limit = currentDownloadChunkSize; - nextDownloadOffset += currentDownloadChunkSize; - - requestInfo->requestToken = ConnectionsManager::getInstance(0).sendRequest(request, [&, requestInfo](TLObject *response, TL_error *error, int32_t connectionType) { - requestInfo->requestToken = 0; - if (response != nullptr) { - TL_upload_file *res = (TL_upload_file *) response; - requestInfo->bytes = res->bytes; - res->bytes = nullptr; - } - processRequestResult(requestInfo, error, false); - }, nullptr, (isForceRequest ? RequestFlagForceDownload : 0) | RequestFlagFailOnServerErrors, datacenter_id, requestsCount % 2 == 0 ? ConnectionTypeDownload : (ConnectionType) (ConnectionTypeDownload | (1 << 16)), isLast); - requestsCount++; - } -} - -FileLoadOperation::RequestInfo::~RequestInfo() { - if (bytes != nullptr) { - bytes->reuse(); - bytes = nullptr; - } -} diff --git a/TMessagesProj/jni/tgnet/FileLoadOperation.h b/TMessagesProj/jni/tgnet/FileLoadOperation.h deleted file mode 100644 index 7740369b3..000000000 --- a/TMessagesProj/jni/tgnet/FileLoadOperation.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This is the source code of tgnet library v. 1.1 - * 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, 2015-2018. - */ - -#ifndef FILELOADOPERATION_H -#define FILELOADOPERATION_H - -#include -#include "Defines.h" - -#ifdef ANDROID -#include -#endif - -class TL_upload_file; -class InputFileLocation; -class ByteArray; -class FileLocation; - -class FileLoadOperation { - -public: - FileLoadOperation(int32_t dc_id, int64_t id, int64_t volume_id, int64_t access_hash, int32_t local_id, uint8_t *encKey, uint8_t *encIv, std::string extension, int32_t version, int32_t size, std::string dest, std::string temp); - ~FileLoadOperation(); - - void start(); - void cancel(); - void setDelegate(onFinishedFunc onFinished, onFailedFunc onFailed, onProgressChangedFunc onProgressChanged); - -#ifdef ANDROID - jobject ptr1 = nullptr; -#endif - -private: - - class RequestInfo { - - public: - int32_t requestToken = 0; - int32_t offset = 0; - NativeByteBuffer *bytes = nullptr; - - ~RequestInfo(); - }; - - void cleanup(); - void onFinishLoadingFile(); - void startDownloadRequest(); - void processRequestResult(RequestInfo *requestInfo, TL_error *error, bool next); - void onFailedLoadingFile(int reason); - - int32_t datacenter_id; - std::unique_ptr location; - FileLoadState state = FileLoadStateIdle; - int32_t downloadedBytes = 0; - int32_t totalBytesCount = 0; - int32_t bytesCountPadding = 0; - std::unique_ptr key; - std::unique_ptr iv; - int32_t currentDownloadChunkSize = 0; - uint32_t currentMaxDownloadRequests = 0; - int32_t requestsCount = 0; - - int32_t nextDownloadOffset = 0; - std::vector> requestInfos; - std::vector> delayedRequestInfos; - - std::string ext; - - std::string filePath; - std::string tempFilePath; - std::string tempFileIvPath; - - FILE *tempFile = nullptr; - FILE *tempIvFile = nullptr; - - std::string destPath; - std::string tempPath; - - bool isForceRequest = false; - - onFinishedFunc onFinishedCallback = nullptr; - onFailedFunc onFailedCallback = nullptr; - onProgressChangedFunc onProgressChangedCallback = nullptr; -}; - -#endif diff --git a/TMessagesProj/proguard-rules.pro b/TMessagesProj/proguard-rules.pro index 5a196c38f..344807a02 100644 --- a/TMessagesProj/proguard-rules.pro +++ b/TMessagesProj/proguard-rules.pro @@ -4,11 +4,8 @@ @com.google.android.gms.common.annotation.KeepName *; } -keep class org.telegram.** { *; } -#-keep class com.google.android.exoplayer2.** { *; } -keep class com.google.android.exoplayer2.ext.** { *; } -keep class com.google.android.exoplayer2.util.** { *; } --keep class com.coremedia.** { *; } --keep class com.googlecode.mp4parser.** { *; } -dontwarn com.coremedia.** -dontwarn org.telegram.** -dontwarn com.google.android.exoplayer2.ext.** diff --git a/TMessagesProj/src/main/AndroidManifest.xml b/TMessagesProj/src/main/AndroidManifest.xml index 9aeea77a2..f36e36692 100644 --- a/TMessagesProj/src/main/AndroidManifest.xml +++ b/TMessagesProj/src/main/AndroidManifest.xml @@ -70,8 +70,8 @@ android:name="org.telegram.messenger.${applicationClassName}" android:allowBackup="false" android:hardwareAccelerated="@bool/useHardwareAcceleration" - android:icon="@drawable/ic_launcher" - android:roundIcon="@drawable/ic_launcher" + android:icon="@mipmap/ic_launcher" + android:roundIcon="@mipmap/ic_launcher_round" android:largeHeap="true" android:theme="@style/Theme.TMessages.Start" android:manageSpaceActivity="org.telegram.ui.ExternalActionActivity" @@ -135,7 +135,7 @@ - + @@ -151,7 +151,7 @@ android:excludeFromRecents="true" android:stateNotNeeded="true" android:theme="@style/Theme.TMessages.Transparent"> - + @@ -163,7 +163,7 @@ android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:hardwareAccelerated="@bool/useHardwareAcceleration" android:windowSoftInputMode="adjustPan"> - + @@ -349,7 +349,7 @@ @@ -369,6 +369,8 @@ android:name=".voip.CallNotificationSoundProvider" android:exported="true"/> + + @@ -383,7 +385,6 @@ -
    diff --git a/TMessagesProj/src/main/assets/dark.attheme b/TMessagesProj/src/main/assets/dark.attheme index 267154f89..83ed80211 100644 --- a/TMessagesProj/src/main/assets/dark.attheme +++ b/TMessagesProj/src/main/assets/dark.attheme @@ -30,8 +30,10 @@ emptyListPlaceholder=-11247768 chat_inAudioSelectedProgress=-14925469 chats_nameMessage=-8932123 chat_inMediaIcon=-1 +actionBarDefaultArchived=-13684171 avatar_subtitleInProfileViolet=-7697782 chat_messagePanelCancelInlineBot=-6971219 +dialogSearchBackground=-13946829 chat_outAudioSeekbarFill=-8272902 chat_botKeyboardButtonBackgroundPressed=-13617349 player_time=-8550517 @@ -41,6 +43,7 @@ chat_inFileProgressSelected=-5845010 changephoneinfo_image=-10786960 chat_inAudioPerfomerText=-8351328 player_button=-1 +key_sheet_other=754974719 chat_inContactNameText=-1 switch2Track=-2135965 chats_menuPhoneCats=-8287602 @@ -53,12 +56,14 @@ chat_outVoiceSeekbar=-1300913456 player_actionBarTitle=-1 dialogGrayLine=-13354948 chat_outFileIcon=-13143396 +chats_nameMessage_threeLines=-1644826 chat_inFileProgress=-10653824 dialogIcon=-8747891 chat_emojiPanelEmptyText=-11511454 chat_emojiPanelBackspace=-10458511 chat_inContactPhoneSelectedText=-8085320 chat_replyPanelClose=-6905432 +dialogSearchText=-723724 chat_outAudioTitleText=-1 chat_emojiPanelBackground=-14999775 chats_unreadCounter=-11032854 @@ -97,6 +102,7 @@ chat_outFileSelectedIcon=-13925429 picker_disabledButton=-10524558 groupcreate_spanBackground=-14143949 dialogButton=-10964761 +contextProgressInner1=800774134 chat_inLoaderPhotoIconSelected=-5648402 actionBarDefaultSubtitle=-8156785 chat_inContactPhoneText=-8812393 @@ -147,11 +153,13 @@ avatar_nameInMessageRed=-1084559 chat_outLoaderPhoto=-13077852 chat_botSwitchToInlineText=-9456666 dialogTextRed2=-892058 +chats_nameMessageArchived=-9011322 avatar_nameInMessageOrange=-1265812 chats_pinnedIcon=-10524305 chat_replyPanelLine=1907997 avatar_subtitleInProfileOrange=-7697782 chat_outSentCheckSelected=-7156228 +dialogSearchHint=-8288371 chat_inVenueInfoSelectedText=-8085320 dialogTextBlue2=-9456666 avatar_backgroundGroupCreateSpanBlue=-12751207 @@ -180,7 +188,7 @@ avatar_nameInMessageCyan=-8270884 chat_mediaLoaderPhotoIconSelected=-1842205 chat_inLocationBackground=-13419450 radioBackground=-10524811 -contextProgressOuter1=-11358225 +contextProgressOuter1=-10702088 chat_inFileIcon=-13946055 avatar_backgroundActionBarPink=-14605274 dialogTextGray3=-7892583 @@ -208,6 +216,7 @@ chat_outForwardedNameText=-5515009 dialogRoundCheckBox=-9912583 chat_emojiPanelTrendingTitle=-2167820 switchThumbChecked=-13600600 +chats_nameMessageArchived_threeLines=-1644826 chat_outSiteNameText=-5515009 windowBackgroundWhite=-14737118 chat_inVoiceSeekbarSelected=-2057139272 @@ -271,12 +280,12 @@ windowBackgroundWhiteGrayText=-9603715 musicPicker_buttonBackground=-11035162 avatar_actionBarSelectorViolet=-11972268 avatar_nameInMessageBlue=-9456666 -dialogTextBlack=-1 +dialogTextBlack=-328966 actionBarDefault=-14276309 profile_actionIcon=-1 windowBackgroundUnchecked=-14473945 actionBarDefaultSelector=-11972268 -chats_menuTopShadow=-15724528 +chats_menuTopShadow=-1558504677 chat_outAudioPerfomerText=-6965025 sharedMedia_startStopLoadIcon=-11164432 chat_serviceBackgroundSelected=1614498132 @@ -287,7 +296,7 @@ chat_outSentClockSelected=-6764038 switchTrackBlueSelectorChecked=848091135 musicPicker_checkbox=-11621658 chat_outFileBackground=-11829594 -chats_name=-1 +chats_name=-657931 chat_attachSendBackground=-10242065 switchTrackBlueSelector=431611386 dialogBadgeBackground=-10371847 @@ -338,6 +347,7 @@ chat_messagePanelVoiceDelete=-9997440 chat_inAudioProgress=-1 chats_date=-9011322 chat_messagePanelText=-1 +key_sheet_scrollUp=603979775 player_buttonActive=-9456666 chat_outLoaderPhotoIcon=-9263664 chat_outContactBackground=-9194520 @@ -360,10 +370,13 @@ chats_sentClock=-8740661 chat_inAudioSeekbar=-581869200 avatar_subtitleInProfileRed=-7697782 avatar_backgroundActionBarRed=-14605274 +dialogSearchIcon=-8814973 chat_inPreviewInstantText=-9456666 +chats_archiveBackground=-10642482 chat_inViews=-8812137 chat_outLoaderSelected=-9194520 dialogButtonSelector=352321535 +chats_archivePinBackground=-13749706 player_actionBarItems=-1 chat_sentError=-1551526 player_progressBackground=-13288897 diff --git a/TMessagesProj/src/main/assets/darkblue.attheme b/TMessagesProj/src/main/assets/darkblue.attheme index 27655b6dd..d64cc1da8 100644 --- a/TMessagesProj/src/main/assets/darkblue.attheme +++ b/TMessagesProj/src/main/assets/darkblue.attheme @@ -22,7 +22,7 @@ switchTrack=-10984850 chat_inPreviewInstantSelectedText=-5648402 chat_attachAudioBackground=-619421 location_sendLocationBackground=-9919529 -actionBarDefaultSubmenuBackground=-13878451 +actionBarDefaultSubmenuBackground=-14075831 switchTrackBlueThumb=-14866637 avatar_nameInMessageViolet=-6643205 emptyListPlaceholder=-8549479 @@ -30,8 +30,10 @@ chat_inAudioSelectedProgress=-1 chats_nameMessage=-1446156 chat_messagePanelShadow=2030043136 chat_inMediaIcon=-1 +actionBarDefaultArchived=-13748149 avatar_subtitleInProfileViolet=-7628894 chat_messagePanelCancelInlineBot=-8549479 +dialogSearchBackground=-14010037 chat_outAudioSeekbarFill=-7944965 chat_botKeyboardButtonBackgroundPressed=-12956574 player_time=-8549479 @@ -41,6 +43,7 @@ chat_inFileProgressSelected=-1 changephoneinfo_image=-12693922 chat_inAudioPerfomerText=-8812393 player_button=-1 +key_sheet_other=1140850687 chat_inContactNameText=-8796932 chats_menuPhoneCats=-11049613 chat_outPreviewLine=-6631937 @@ -51,12 +54,14 @@ chat_outVoiceSeekbar=-429551165 player_actionBarTitle=-1 dialogGrayLine=-15790062 chat_outFileIcon=-12689015 +chats_nameMessage_threeLines=-1446156 chat_inFileProgress=-1 -dialogIcon=-8944238 +dialogIcon=-7627862 chat_emojiPanelEmptyText=-8549479 chat_emojiPanelBackspace=-9996665 chat_replyPanelClose=-10062202 chat_inContactPhoneSelectedText=-7490861 +dialogSearchText=-1 chat_outAudioTitleText=-1 chat_emojiPanelBackground=-14866637 chats_unreadCounter=-10177041 @@ -92,6 +97,7 @@ chat_outFileSelectedIcon=-13925429 picker_disabledButton=-11047552 groupcreate_spanBackground=-13878194 dialogButton=-10177041 +contextProgressInner1=-11509903 chat_inLoaderPhotoIconSelected=-1 actionBarDefaultSubtitle=-7628894 chat_inContactPhoneText=-8812393 @@ -142,11 +148,13 @@ avatar_nameInMessageRed=-21124 chat_outLoaderPhoto=-12623479 chat_botSwitchToInlineText=-8796932 dialogTextRed2=-1152913 +chats_nameMessageArchived=-8549479 avatar_nameInMessageOrange=-13984 chats_pinnedIcon=-10982016 chat_replyPanelLine=1779898909 avatar_subtitleInProfileOrange=-7628894 chat_outSentCheckSelected=-4268038 +dialogSearchHint=-8419182 chat_inVenueInfoSelectedText=-7490861 dialogTextBlue2=-10177041 avatar_backgroundGroupCreateSpanBlue=-13803892 @@ -173,7 +181,7 @@ windowBackgroundWhiteBlueText=-10177041 avatar_nameInMessageCyan=-10623523 chat_inLocationBackground=-13417903 radioBackground=-1635939431 -contextProgressOuter1=-10177041 +contextProgressOuter1=-9914632 chat_inFileIcon=-14470078 avatar_backgroundActionBarPink=-14602949 dialogTextGray3=-8549479 @@ -195,22 +203,25 @@ chat_inBubbleSelected=-13546911 chat_mediaMenu=-1 chat_outViewsSelected=-4268038 chat_outInstant=-7551233 -chat_emojiPanelShadowLine=251658239 -actionBarActionModeDefaultSelector=2047809827 +chat_emojiPanelShadowLine=838860800 +actionBarActionModeDefaultSelector=2050907520 chat_outForwardedNameText=-7551233 dialogRoundCheckBox=-10177041 chat_emojiPanelTrendingTitle=-1 switchThumbChecked=-10376479 +chat_stickersHintPanel=-13484721 chat_outSiteNameText=-1 windowBackgroundWhite=-14866637 groupcreate_offlineText=-8549479 chat_inVoiceSeekbarSelected=-9203285 dialogTextGray=-8549479 chat_messageLinkOut=-6631937 +avatar_backgroundArchived=-13087910 chat_outFileInfoSelectedText=-4268038 chats_tabletSelectedOverlay=268435455 chat_outAudioDurationSelectedText=-4268038 chat_attachCameraIcon1=-32171 +undo_background=-182112197 avatar_actionBarSelectorPink=-12758164 dialogTextHint=-8549479 chat_topPanelTitle=-11164709 @@ -226,7 +237,7 @@ chats_sentCheck=-10177041 chats_unreadCounterMuted=-12692893 chat_outVoiceSeekbarFill=-7944965 chat_outReplyLine=-6631937 -chat_messagePanelIcons=-9996665 +chat_messagePanelIcons=-9733492 chat_inReplyMediaMessageText=-8812393 inappPlayerTitle=-8549479 chat_emojiPanelIconSelected=-10177041 @@ -259,7 +270,7 @@ avatar_nameInMessagePink=-624741 windowBackgroundWhiteGrayText=-8549479 avatar_actionBarSelectorViolet=-12758164 avatar_nameInMessageBlue=-8796932 -dialogTextBlack=-1 +dialogTextBlack=-592138 actionBarDefault=-14602949 location_placeLocationBackground=-9919529 profile_actionIcon=-1 @@ -330,6 +341,7 @@ chat_messagePanelVoiceDelete=-1 chat_inAudioProgress=-1 chats_date=-9207925 chat_messagePanelText=-1 +key_sheet_scrollUp=637534207 player_buttonActive=-10177041 chat_outLoaderPhotoIcon=-1 chat_outContactBackground=-9919529 @@ -345,17 +357,21 @@ windowBackgroundWhiteLinkSelection=862238205 player_background=-14734794 inappPlayerClose=-8549479 chat_outMediaIcon=-1 +chats_message_threeLines=-8549479 player_actionBarSubtitle=-8549479 chat_outAudioCacheSeekbar=-10120765 chats_sentClock=-11772054 chat_inAudioSeekbar=-11443856 avatar_subtitleInProfileRed=-7628894 avatar_backgroundActionBarRed=-14602949 +dialogSearchIcon=-8945521 chat_inPreviewInstantText=-8796932 +chats_archiveBackground=-11036980 dialog_liveLocationProgress=-9919529 chat_inViews=-8812137 chat_outLoaderSelected=-9919529 dialogButtonSelector=352321535 +chats_archivePinBackground=-13746613 player_actionBarItems=-1 chat_sentError=-633010 player_progressBackground=-13023400 diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_0_0.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_0_0.png deleted file mode 100644 index 5de24d885..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_0_0.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_0_1.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_0_1.png deleted file mode 100644 index 814ffd773..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_0_1.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_0_2.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_0_2.png deleted file mode 100644 index 65d219df6..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_0_2.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_0_3.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_0_3.png deleted file mode 100644 index d7dbe7199..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_0_3.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_1_0.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_1_0.png deleted file mode 100644 index dddc0eb07..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_1_0.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_1_1.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_1_1.png deleted file mode 100644 index 1be3e01cb..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_1_1.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_1_2.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_1_2.png deleted file mode 100644 index 57eeae7ac..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_1_2.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_1_3.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_1_3.png deleted file mode 100644 index cea6a614d..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_1_3.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_2_0.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_2_0.png deleted file mode 100644 index 8714775ed..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_2_0.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_2_1.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_2_1.png deleted file mode 100644 index 85ef70e76..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_2_1.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_2_2.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_2_2.png deleted file mode 100644 index 72c00bf8a..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_2_2.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_2_3.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_2_3.png deleted file mode 100644 index e6bd7749b..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_2_3.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_3_0.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_3_0.png deleted file mode 100644 index b847c7e08..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_3_0.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_3_1.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_3_1.png deleted file mode 100644 index 81ef90d67..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_3_1.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_3_2.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_3_2.png deleted file mode 100644 index a5730b1e3..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_3_2.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_3_3.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_3_3.png deleted file mode 100644 index 562038397..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_3_3.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_4_0.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_4_0.png deleted file mode 100644 index ef953d223..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_4_0.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_4_1.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_4_1.png deleted file mode 100644 index 4aa650eea..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_4_1.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_4_2.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_4_2.png deleted file mode 100644 index 4267d0b1f..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_4_2.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_4_3.png b/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_4_3.png deleted file mode 100644 index ccacc731d..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v13_emoji2.0x_4_3.png and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_0_0.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_0_0.png new file mode 100644 index 000000000..ffe91d279 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_0_0.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_0_1.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_0_1.png new file mode 100644 index 000000000..32cf16152 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_0_1.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_0_2.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_0_2.png new file mode 100644 index 000000000..1c4a23eef Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_0_2.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_0_3.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_0_3.png new file mode 100644 index 000000000..ac2da0e7b Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_0_3.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_1_0.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_1_0.png new file mode 100644 index 000000000..5889565d6 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_1_0.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_1_1.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_1_1.png new file mode 100644 index 000000000..41fd881d8 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_1_1.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_1_2.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_1_2.png new file mode 100644 index 000000000..120f69a09 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_1_2.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_1_3.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_1_3.png new file mode 100644 index 000000000..58b6c5062 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_1_3.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_2_0.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_2_0.png new file mode 100644 index 000000000..5a08dc006 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_2_0.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_2_1.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_2_1.png new file mode 100644 index 000000000..61bba77e9 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_2_1.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_2_2.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_2_2.png new file mode 100644 index 000000000..f0926ddf6 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_2_2.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_2_3.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_2_3.png new file mode 100644 index 000000000..9bc9ed68d Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_2_3.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_3_0.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_3_0.png new file mode 100644 index 000000000..9f19ca4b6 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_3_0.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_3_1.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_3_1.png new file mode 100644 index 000000000..18c62f9d0 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_3_1.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_3_2.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_3_2.png new file mode 100644 index 000000000..75fccebe7 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_3_2.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_3_3.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_3_3.png new file mode 100644 index 000000000..2b4a010e0 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_3_3.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_4_0.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_4_0.png new file mode 100644 index 000000000..7d49e63b8 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_4_0.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_4_1.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_4_1.png new file mode 100644 index 000000000..99e9e73e1 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_4_1.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_4_2.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_4_2.png new file mode 100644 index 000000000..e2af94533 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_4_2.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_4_3.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_4_3.png new file mode 100644 index 000000000..608efc9f9 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_4_3.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_5_0.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_5_0.png new file mode 100644 index 000000000..3f40d6346 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_5_0.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_5_1.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_5_1.png new file mode 100644 index 000000000..e088ec174 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_5_1.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_5_2.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_5_2.png new file mode 100644 index 000000000..dccbe3c04 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_5_2.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_5_3.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_5_3.png new file mode 100644 index 000000000..58035b325 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_5_3.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_6_0.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_6_0.png new file mode 100644 index 000000000..c6c7adfe9 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_6_0.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_6_1.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_6_1.png new file mode 100644 index 000000000..072789201 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_6_1.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_6_2.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_6_2.png new file mode 100644 index 000000000..839c435ab Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_6_2.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_6_3.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_6_3.png new file mode 100644 index 000000000..260e1351f Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_6_3.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_7_0.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_7_0.png new file mode 100644 index 000000000..bc4f7b92a Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_7_0.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_7_1.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_7_1.png new file mode 100644 index 000000000..5b31cf29e Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_7_1.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_7_2.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_7_2.png new file mode 100644 index 000000000..ec4fb4d3a Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_7_2.png differ diff --git a/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_7_3.png b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_7_3.png new file mode 100644 index 000000000..c447a16d0 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v14_emoji2.0x_7_3.png differ diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/AdapterHelper.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/AdapterHelper.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/AdapterHelper.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/AdapterHelper.java index 6771c4247..f909f6781 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/AdapterHelper.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/AdapterHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,11 +14,12 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; -import android.support.v4.util.Pools; import android.util.Log; +import androidx.core.util.Pools; + import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/AdapterListUpdateCallback.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/AdapterListUpdateCallback.java similarity index 92% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/util/AdapterListUpdateCallback.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/AdapterListUpdateCallback.java index 5c35f0502..53931ba41 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/AdapterListUpdateCallback.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/AdapterListUpdateCallback.java @@ -14,10 +14,9 @@ * limitations under the License. */ -package org.telegram.messenger.support.util; +package androidx.recyclerview.widget; -import android.support.annotation.NonNull; -import org.telegram.messenger.support.widget.RecyclerView; +import androidx.annotation.NonNull; /** * ListUpdateCallback that dispatches update events to the given adapter. diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/AsyncDifferConfig.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/AsyncDifferConfig.java new file mode 100644 index 000000000..86956e216 --- /dev/null +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/AsyncDifferConfig.java @@ -0,0 +1,147 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.recyclerview.widget; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RestrictTo; + +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +/** + * Configuration object for {@link ListAdapter}, {@link AsyncListDiffer}, and similar + * background-thread list diffing adapter logic. + *

    + * At minimum, defines item diffing behavior with a {@link DiffUtil.ItemCallback}, used to compute + * item differences to pass to a RecyclerView adapter. + * + * @param Type of items in the lists, and being compared. + */ +public final class AsyncDifferConfig { + @Nullable + private final Executor mMainThreadExecutor; + @NonNull + private final Executor mBackgroundThreadExecutor; + @NonNull + private final DiffUtil.ItemCallback mDiffCallback; + + @SuppressWarnings("WeakerAccess") /* synthetic access */ + AsyncDifferConfig( + @Nullable Executor mainThreadExecutor, + @NonNull Executor backgroundThreadExecutor, + @NonNull DiffUtil.ItemCallback diffCallback) { + mMainThreadExecutor = mainThreadExecutor; + mBackgroundThreadExecutor = backgroundThreadExecutor; + mDiffCallback = diffCallback; + } + + /** @hide */ + @SuppressWarnings("WeakerAccess") + @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) + @Nullable + public Executor getMainThreadExecutor() { + return mMainThreadExecutor; + } + + @SuppressWarnings("WeakerAccess") + @NonNull + public Executor getBackgroundThreadExecutor() { + return mBackgroundThreadExecutor; + } + + @SuppressWarnings("WeakerAccess") + @NonNull + public DiffUtil.ItemCallback getDiffCallback() { + return mDiffCallback; + } + + /** + * Builder class for {@link AsyncDifferConfig}. + * + * @param + */ + public static final class Builder { + @Nullable + private Executor mMainThreadExecutor; + private Executor mBackgroundThreadExecutor; + private final DiffUtil.ItemCallback mDiffCallback; + + public Builder(@NonNull DiffUtil.ItemCallback diffCallback) { + mDiffCallback = diffCallback; + } + + /** + * If provided, defines the main thread executor used to dispatch adapter update + * notifications on the main thread. + *

    + * If not provided, it will default to the main thread. + * + * @param executor The executor which can run tasks in the UI thread. + * @return this + * + * @hide + */ + @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) + @NonNull + public Builder setMainThreadExecutor(Executor executor) { + mMainThreadExecutor = executor; + return this; + } + + /** + * If provided, defines the background executor used to calculate the diff between an old + * and a new list. + *

    + * If not provided, defaults to two thread pool executor, shared by all ListAdapterConfigs. + * + * @param executor The background executor to run list diffing. + * @return this + */ + @SuppressWarnings({"unused", "WeakerAccess"}) + @NonNull + public Builder setBackgroundThreadExecutor(Executor executor) { + mBackgroundThreadExecutor = executor; + return this; + } + + /** + * Creates a {@link AsyncListDiffer} with the given parameters. + * + * @return A new AsyncDifferConfig. + */ + @NonNull + public AsyncDifferConfig build() { + if (mBackgroundThreadExecutor == null) { + synchronized (sExecutorLock) { + if (sDiffExecutor == null) { + sDiffExecutor = Executors.newFixedThreadPool(2); + } + } + mBackgroundThreadExecutor = sDiffExecutor; + } + return new AsyncDifferConfig<>( + mMainThreadExecutor, + mBackgroundThreadExecutor, + mDiffCallback); + } + + // TODO: remove the below once supportlib has its own appropriate executors + private static final Object sExecutorLock = new Object(); + private static Executor sDiffExecutor = null; + } +} diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/AsyncListDiffer.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/AsyncListDiffer.java new file mode 100644 index 000000000..1c345be03 --- /dev/null +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/AsyncListDiffer.java @@ -0,0 +1,405 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.recyclerview.widget; + +import android.os.Handler; +import android.os.Looper; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Executor; + +/** + * Helper for computing the difference between two lists via {@link DiffUtil} on a background + * thread. + *

    + * It can be connected to a + * {@link RecyclerView.Adapter RecyclerView.Adapter}, and will signal the + * adapter of changes between sumbitted lists. + *

    + * For simplicity, the {@link ListAdapter} wrapper class can often be used instead of the + * AsyncListDiffer directly. This AsyncListDiffer can be used for complex cases, where overriding an + * adapter base class to support asynchronous List diffing isn't convenient. + *

    + * The AsyncListDiffer can consume the values from a LiveData of List and present the + * data simply for an adapter. It computes differences in list contents via {@link DiffUtil} on a + * background thread as new Lists are received. + *

    + * Use {@link #getCurrentList()} to access the current List, and present its data objects. Diff + * results will be dispatched to the ListUpdateCallback immediately before the current list is + * updated. If you're dispatching list updates directly to an Adapter, this means the Adapter can + * safely access list items and total size via {@link #getCurrentList()}. + *

    + * A complete usage pattern with Room would look like this: + *

    + * {@literal @}Dao
    + * interface UserDao {
    + *     {@literal @}Query("SELECT * FROM user ORDER BY lastName ASC")
    + *     public abstract LiveData<List<User>> usersByLastName();
    + * }
    + *
    + * class MyViewModel extends ViewModel {
    + *     public final LiveData<List<User>> usersList;
    + *     public MyViewModel(UserDao userDao) {
    + *         usersList = userDao.usersByLastName();
    + *     }
    + * }
    + *
    + * class MyActivity extends AppCompatActivity {
    + *     {@literal @}Override
    + *     public void onCreate(Bundle savedState) {
    + *         super.onCreate(savedState);
    + *         MyViewModel viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
    + *         RecyclerView recyclerView = findViewById(R.id.user_list);
    + *         UserAdapter adapter = new UserAdapter();
    + *         viewModel.usersList.observe(this, list -> adapter.submitList(list));
    + *         recyclerView.setAdapter(adapter);
    + *     }
    + * }
    + *
    + * class UserAdapter extends RecyclerView.Adapter<UserViewHolder> {
    + *     private final AsyncListDiffer<User> mDiffer = new AsyncListDiffer(this, DIFF_CALLBACK);
    + *     {@literal @}Override
    + *     public int getItemCount() {
    + *         return mDiffer.getCurrentList().size();
    + *     }
    + *     public void submitList(List<User> list) {
    + *         mDiffer.submitList(list);
    + *     }
    + *     {@literal @}Override
    + *     public void onBindViewHolder(UserViewHolder holder, int position) {
    + *         User user = mDiffer.getCurrentList().get(position);
    + *         holder.bindTo(user);
    + *     }
    + *     public static final DiffUtil.ItemCallback<User> DIFF_CALLBACK
    + *             = new DiffUtil.ItemCallback<User>() {
    + *         {@literal @}Override
    + *         public boolean areItemsTheSame(
    + *                 {@literal @}NonNull User oldUser, {@literal @}NonNull User newUser) {
    + *             // User properties may have changed if reloaded from the DB, but ID is fixed
    + *             return oldUser.getId() == newUser.getId();
    + *         }
    + *         {@literal @}Override
    + *         public boolean areContentsTheSame(
    + *                 {@literal @}NonNull User oldUser, {@literal @}NonNull User newUser) {
    + *             // NOTE: if you use equals, your object must properly override Object#equals()
    + *             // Incorrectly returning false here will result in too many animations.
    + *             return oldUser.equals(newUser);
    + *         }
    + *     }
    + * }
    + * + * @param Type of the lists this AsyncListDiffer will receive. + * + * @see DiffUtil + * @see AdapterListUpdateCallback + */ +public class AsyncListDiffer { + private final ListUpdateCallback mUpdateCallback; + @SuppressWarnings("WeakerAccess") /* synthetic access */ + final AsyncDifferConfig mConfig; + Executor mMainThreadExecutor; + + private static class MainThreadExecutor implements Executor { + final Handler mHandler = new Handler(Looper.getMainLooper()); + MainThreadExecutor() {} + @Override + public void execute(@NonNull Runnable command) { + mHandler.post(command); + } + } + + // TODO: use MainThreadExecutor from supportlib once one exists + private static final Executor sMainThreadExecutor = new MainThreadExecutor(); + + /** + * Listener for when the current List is updated. + * + * @param Type of items in List + */ + public interface ListListener { + /** + * Called after the current List has been updated. + * + * @param previousList The previous list. + * @param currentList The new current list. + */ + void onCurrentListChanged(@NonNull List previousList, @NonNull List currentList); + } + + private final List> mListeners = new CopyOnWriteArrayList<>(); + + /** + * Convenience for + * {@code AsyncListDiffer(new AdapterListUpdateCallback(adapter), + * new AsyncDifferConfig.Builder().setDiffCallback(diffCallback).build());} + * + * @param adapter Adapter to dispatch position updates to. + * @param diffCallback ItemCallback that compares items to dispatch appropriate animations when + * + * @see DiffUtil.DiffResult#dispatchUpdatesTo(RecyclerView.Adapter) + */ + public AsyncListDiffer(@NonNull RecyclerView.Adapter adapter, + @NonNull DiffUtil.ItemCallback diffCallback) { + this(new AdapterListUpdateCallback(adapter), + new AsyncDifferConfig.Builder<>(diffCallback).build()); + } + + /** + * Create a AsyncListDiffer with the provided config, and ListUpdateCallback to dispatch + * updates to. + * + * @param listUpdateCallback Callback to dispatch updates to. + * @param config Config to define background work Executor, and DiffUtil.ItemCallback for + * computing List diffs. + * + * @see DiffUtil.DiffResult#dispatchUpdatesTo(RecyclerView.Adapter) + */ + @SuppressWarnings("WeakerAccess") + public AsyncListDiffer(@NonNull ListUpdateCallback listUpdateCallback, + @NonNull AsyncDifferConfig config) { + mUpdateCallback = listUpdateCallback; + mConfig = config; + if (config.getMainThreadExecutor() != null) { + mMainThreadExecutor = config.getMainThreadExecutor(); + } else { + mMainThreadExecutor = sMainThreadExecutor; + } + } + + @Nullable + private List mList; + + /** + * Non-null, unmodifiable version of mList. + *

    + * Collections.emptyList when mList is null, wrapped by Collections.unmodifiableList otherwise + */ + @NonNull + private List mReadOnlyList = Collections.emptyList(); + + // Max generation of currently scheduled runnable + @SuppressWarnings("WeakerAccess") /* synthetic access */ + int mMaxScheduledGeneration; + + /** + * Get the current List - any diffing to present this list has already been computed and + * dispatched via the ListUpdateCallback. + *

    + * If a null List, or no List has been submitted, an empty list will be returned. + *

    + * The returned list may not be mutated - mutations to content must be done through + * {@link #submitList(List)}. + * + * @return current List. + */ + @NonNull + public List getCurrentList() { + return mReadOnlyList; + } + + /** + * Pass a new List to the AdapterHelper. Adapter updates will be computed on a background + * thread. + *

    + * If a List is already present, a diff will be computed asynchronously on a background thread. + * When the diff is computed, it will be applied (dispatched to the {@link ListUpdateCallback}), + * and the new List will be swapped in. + * + * @param newList The new List. + */ + @SuppressWarnings("WeakerAccess") + public void submitList(@Nullable final List newList) { + submitList(newList, null); + } + + /** + * Pass a new List to the AdapterHelper. Adapter updates will be computed on a background + * thread. + *

    + * If a List is already present, a diff will be computed asynchronously on a background thread. + * When the diff is computed, it will be applied (dispatched to the {@link ListUpdateCallback}), + * and the new List will be swapped in. + *

    + * The commit callback can be used to know when the List is committed, but note that it + * may not be executed. If List B is submitted immediately after List A, and is + * committed directly, the callback associated with List A will not be run. + * + * @param newList The new List. + * @param commitCallback Optional runnable that is executed when the List is committed, if + * it is committed. + */ + @SuppressWarnings("WeakerAccess") + public void submitList(@Nullable final List newList, + @Nullable final Runnable commitCallback) { + // incrementing generation means any currently-running diffs are discarded when they finish + final int runGeneration = ++mMaxScheduledGeneration; + + if (newList == mList) { + // nothing to do (Note - still had to inc generation, since may have ongoing work) + if (commitCallback != null) { + commitCallback.run(); + } + return; + } + + final List previousList = mReadOnlyList; + + // fast simple remove all + if (newList == null) { + //noinspection ConstantConditions + int countRemoved = mList.size(); + mList = null; + mReadOnlyList = Collections.emptyList(); + // notify last, after list is updated + mUpdateCallback.onRemoved(0, countRemoved); + onCurrentListChanged(previousList, commitCallback); + return; + } + + // fast simple first insert + if (mList == null) { + mList = newList; + mReadOnlyList = Collections.unmodifiableList(newList); + // notify last, after list is updated + mUpdateCallback.onInserted(0, newList.size()); + onCurrentListChanged(previousList, commitCallback); + return; + } + + final List oldList = mList; + mConfig.getBackgroundThreadExecutor().execute(new Runnable() { + @Override + public void run() { + final DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() { + @Override + public int getOldListSize() { + return oldList.size(); + } + + @Override + public int getNewListSize() { + return newList.size(); + } + + @Override + public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { + T oldItem = oldList.get(oldItemPosition); + T newItem = newList.get(newItemPosition); + if (oldItem != null && newItem != null) { + return mConfig.getDiffCallback().areItemsTheSame(oldItem, newItem); + } + // If both items are null we consider them the same. + return oldItem == null && newItem == null; + } + + @Override + public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { + T oldItem = oldList.get(oldItemPosition); + T newItem = newList.get(newItemPosition); + if (oldItem != null && newItem != null) { + return mConfig.getDiffCallback().areContentsTheSame(oldItem, newItem); + } + if (oldItem == null && newItem == null) { + return true; + } + // There is an implementation bug if we reach this point. Per the docs, this + // method should only be invoked when areItemsTheSame returns true. That + // only occurs when both items are non-null or both are null and both of + // those cases are handled above. + throw new AssertionError(); + } + + @Nullable + @Override + public Object getChangePayload(int oldItemPosition, int newItemPosition) { + T oldItem = oldList.get(oldItemPosition); + T newItem = newList.get(newItemPosition); + if (oldItem != null && newItem != null) { + return mConfig.getDiffCallback().getChangePayload(oldItem, newItem); + } + // There is an implementation bug if we reach this point. Per the docs, this + // method should only be invoked when areItemsTheSame returns true AND + // areContentsTheSame returns false. That only occurs when both items are + // non-null which is the only case handled above. + throw new AssertionError(); + } + }); + + mMainThreadExecutor.execute(new Runnable() { + @Override + public void run() { + if (mMaxScheduledGeneration == runGeneration) { + latchList(newList, result, commitCallback); + } + } + }); + } + }); + } + + @SuppressWarnings("WeakerAccess") /* synthetic access */ + void latchList( + @NonNull List newList, + @NonNull DiffUtil.DiffResult diffResult, + @Nullable Runnable commitCallback) { + final List previousList = mReadOnlyList; + mList = newList; + // notify last, after list is updated + mReadOnlyList = Collections.unmodifiableList(newList); + diffResult.dispatchUpdatesTo(mUpdateCallback); + onCurrentListChanged(previousList, commitCallback); + } + + private void onCurrentListChanged(@NonNull List previousList, + @Nullable Runnable commitCallback) { + // current list is always mReadOnlyList + for (ListListener listener : mListeners) { + listener.onCurrentListChanged(previousList, mReadOnlyList); + } + if (commitCallback != null) { + commitCallback.run(); + } + } + + /** + * Add a ListListener to receive updates when the current List changes. + * + * @param listener Listener to receive updates. + * + * @see #getCurrentList() + * @see #removeListListener(ListListener) + */ + public void addListListener(@NonNull ListListener listener) { + mListeners.add(listener); + } + + /** + * Remove a previously registered ListListener. + * + * @param listener Previously registered listener. + * @see #getCurrentList() + * @see #addListListener(ListListener) + */ + public void removeListListener(@NonNull ListListener listener) { + mListeners.remove(listener); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/AsyncListUtil.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/AsyncListUtil.java similarity index 96% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/util/AsyncListUtil.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/AsyncListUtil.java index 6b4cb52da..b50f6a813 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/AsyncListUtil.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/AsyncListUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,17 @@ * limitations under the License. */ -package org.telegram.messenger.support.util; +package androidx.recyclerview.widget; -import android.support.annotation.UiThread; -import android.support.annotation.WorkerThread; import android.util.Log; import android.util.SparseBooleanArray; import android.util.SparseIntArray; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.UiThread; +import androidx.annotation.WorkerThread; + /** * A utility class that supports asynchronous content loading. *

    @@ -39,7 +42,7 @@ import android.util.SparseIntArray; * Note that this class uses a single thread to load the data, so it suitable to load data from * secondary storage such as disk, but not from network. *

    - * This class is designed to work with {@link android.support.v7.widget.RecyclerView}, but it does + * This class is designed to work with {@link RecyclerView}, but it does * not depend on it and can be used with other list views. * */ @@ -84,8 +87,8 @@ public class AsyncListUtil { * @param dataCallback Data access callback. * @param viewCallback Callback for querying visible item range and update notifications. */ - public AsyncListUtil(Class klass, int tileSize, DataCallback dataCallback, - ViewCallback viewCallback) { + public AsyncListUtil(@NonNull Class klass, int tileSize, + @NonNull DataCallback dataCallback, @NonNull ViewCallback viewCallback) { mTClass = klass; mTileSize = tileSize; mDataCallback = dataCallback; @@ -110,7 +113,7 @@ public class AsyncListUtil { *

    * Identifies the data items that have not been loaded yet and initiates loading them in the * background. Should be called from the view's scroll listener (such as - * {@link android.support.v7.widget.RecyclerView.OnScrollListener#onScrolled}). + * {@link RecyclerView.OnScrollListener#onScrolled}). */ public void onRangeChanged() { if (isRefreshPending()) { @@ -147,6 +150,7 @@ public class AsyncListUtil { * @return The data item at the given position or null if it has not been loaded * yet. */ + @Nullable public T getItem(int position) { if (position < 0 || position >= mItemCount) { throw new IndexOutOfBoundsException(position + " is not within 0 and " + mItemCount); @@ -471,7 +475,7 @@ public class AsyncListUtil { * itemCount. */ @WorkerThread - public abstract void fillData(T[] data, int startPosition, int itemCount); + public abstract void fillData(@NonNull T[] data, int startPosition, int itemCount); /** * Recycle the objects created in {@link #fillData} if necessary. @@ -481,7 +485,7 @@ public class AsyncListUtil { * @param itemCount The data item count. */ @WorkerThread - public void recycleData(T[] data, int itemCount) { + public void recycleData(@NonNull T[] data, int itemCount) { } /** @@ -548,7 +552,7 @@ public class AsyncListUtil { * @param outRange The visible item range. */ @UiThread - public abstract void getItemRangeInto(int[] outRange); + public abstract void getItemRangeInto(@NonNull int[] outRange); /** * Compute a wider range of items that will be loaded for smoother scrolling. @@ -569,7 +573,7 @@ public class AsyncListUtil { * @param scrollHint The scroll direction hint. */ @UiThread - public void extendRangeInto(int[] range, int[] outRange, int scrollHint) { + public void extendRangeInto(@NonNull int[] range, @NonNull int[] outRange, int scrollHint) { final int fullRange = range[1] - range[0] + 1; final int halfRange = fullRange / 2; outRange[0] = range[0] - (scrollHint == HINT_SCROLL_DESC ? fullRange : halfRange); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/BatchingListUpdateCallback.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/BatchingListUpdateCallback.java similarity index 94% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/util/BatchingListUpdateCallback.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/BatchingListUpdateCallback.java index 5025cb841..f49451fe2 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/BatchingListUpdateCallback.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/BatchingListUpdateCallback.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.telegram.messenger.support.util; +package androidx.recyclerview.widget; + +import androidx.annotation.NonNull; /** * Wraps a {@link ListUpdateCallback} callback and batches operations that can be merged. @@ -22,7 +24,7 @@ package org.telegram.messenger.support.util; * BatchingListUpdateCallback merges them and calls the wrapped callback only once. *

    * This is a general purpose class and is also used by - * {@link android.support.v7.util.DiffUtil.DiffResult DiffResult} and + * {@link DiffUtil.DiffResult DiffResult} and * {@link SortedList} to minimize the number of updates that are dispatched. *

    * If you use this class to batch updates, you must call {@link #dispatchLastEvent()} when the @@ -41,7 +43,7 @@ public class BatchingListUpdateCallback implements ListUpdateCallback { int mLastEventCount = -1; Object mLastEventPayload = null; - public BatchingListUpdateCallback(ListUpdateCallback callback) { + public BatchingListUpdateCallback(@NonNull ListUpdateCallback callback) { mWrapped = callback; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/ChildHelper.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChildHelper.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/ChildHelper.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/ChildHelper.java index 734db8c62..b566ba577 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/ChildHelper.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChildHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; import android.util.Log; import android.view.View; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/DefaultItemAnimator.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java similarity index 86% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/DefaultItemAnimator.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java index 7c4ff828f..5a6a2a1b5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/DefaultItemAnimator.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,18 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; -import android.support.annotation.NonNull; -import android.support.v4.view.ViewCompat; -import org.telegram.messenger.support.widget.RecyclerView.ViewHolder; import android.view.View; import android.view.ViewPropertyAnimator; +import androidx.annotation.NonNull; +import androidx.core.view.ViewCompat; + import java.util.ArrayList; import java.util.List; @@ -40,27 +40,27 @@ public class DefaultItemAnimator extends SimpleItemAnimator { private static TimeInterpolator sDefaultInterpolator; - private ArrayList mPendingRemovals = new ArrayList<>(); - private ArrayList mPendingAdditions = new ArrayList<>(); + private ArrayList mPendingRemovals = new ArrayList<>(); + private ArrayList mPendingAdditions = new ArrayList<>(); private ArrayList mPendingMoves = new ArrayList<>(); private ArrayList mPendingChanges = new ArrayList<>(); - ArrayList> mAdditionsList = new ArrayList<>(); + ArrayList> mAdditionsList = new ArrayList<>(); ArrayList> mMovesList = new ArrayList<>(); ArrayList> mChangesList = new ArrayList<>(); - ArrayList mAddAnimations = new ArrayList<>(); - ArrayList mMoveAnimations = new ArrayList<>(); - ArrayList mRemoveAnimations = new ArrayList<>(); - ArrayList mChangeAnimations = new ArrayList<>(); + ArrayList mAddAnimations = new ArrayList<>(); + ArrayList mMoveAnimations = new ArrayList<>(); + ArrayList mRemoveAnimations = new ArrayList<>(); + ArrayList mChangeAnimations = new ArrayList<>(); private boolean delayAnimations = true; private static class MoveInfo { - public ViewHolder holder; + public RecyclerView.ViewHolder holder; public int fromX, fromY, toX, toY; - MoveInfo(ViewHolder holder, int fromX, int fromY, int toX, int toY) { + MoveInfo(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) { this.holder = holder; this.fromX = fromX; this.fromY = fromY; @@ -70,14 +70,14 @@ public class DefaultItemAnimator extends SimpleItemAnimator { } private static class ChangeInfo { - public ViewHolder oldHolder, newHolder; + public RecyclerView.ViewHolder oldHolder, newHolder; public int fromX, fromY, toX, toY; - private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder) { + private ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder) { this.oldHolder = oldHolder; this.newHolder = newHolder; } - ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder, + ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) { this(oldHolder, newHolder); this.fromX = fromX; @@ -110,13 +110,14 @@ public class DefaultItemAnimator extends SimpleItemAnimator { return; } // First, remove stuff - for (ViewHolder holder : mPendingRemovals) { + for (RecyclerView.ViewHolder holder : mPendingRemovals) { animateRemoveImpl(holder); } mPendingRemovals.clear(); // Next, move stuff if (movesPending) { - final ArrayList moves = new ArrayList<>(mPendingMoves); + final ArrayList moves = new ArrayList<>(); + moves.addAll(mPendingMoves); mMovesList.add(moves); mPendingMoves.clear(); Runnable mover = new Runnable() { @@ -139,7 +140,8 @@ public class DefaultItemAnimator extends SimpleItemAnimator { } // Next, change stuff, to run in parallel with move animations if (changesPending) { - final ArrayList changes = new ArrayList<>(mPendingChanges); + final ArrayList changes = new ArrayList<>(); + changes.addAll(mPendingChanges); mChangesList.add(changes); mPendingChanges.clear(); Runnable changer = new Runnable() { @@ -153,7 +155,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { } }; if (delayAnimations && removalsPending) { - ViewHolder holder = changes.get(0).oldHolder; + RecyclerView.ViewHolder holder = changes.get(0).oldHolder; ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration()); } else { changer.run(); @@ -161,13 +163,14 @@ public class DefaultItemAnimator extends SimpleItemAnimator { } // Next, add stuff if (additionsPending) { - final ArrayList additions = new ArrayList<>(mPendingAdditions); + final ArrayList additions = new ArrayList<>(); + additions.addAll(mPendingAdditions); mAdditionsList.add(additions); mPendingAdditions.clear(); Runnable adder = new Runnable() { @Override public void run() { - for (ViewHolder holder : additions) { + for (RecyclerView.ViewHolder holder : additions) { animateAddImpl(holder); } additions.clear(); @@ -188,7 +191,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { } @Override - public boolean animateRemove(final ViewHolder holder) { + public boolean animateRemove(final RecyclerView.ViewHolder holder) { resetAnimation(holder); mPendingRemovals.add(holder); return true; @@ -198,7 +201,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { delayAnimations = value; } - private void animateRemoveImpl(final ViewHolder holder) { + private void animateRemoveImpl(final RecyclerView.ViewHolder holder) { final View view = holder.itemView; final ViewPropertyAnimator animation = view.animate(); mRemoveAnimations.add(holder); @@ -221,14 +224,14 @@ public class DefaultItemAnimator extends SimpleItemAnimator { } @Override - public boolean animateAdd(final ViewHolder holder) { + public boolean animateAdd(final RecyclerView.ViewHolder holder) { resetAnimation(holder); holder.itemView.setAlpha(0); mPendingAdditions.add(holder); return true; } - void animateAddImpl(final ViewHolder holder) { + void animateAddImpl(final RecyclerView.ViewHolder holder) { final View view = holder.itemView; final ViewPropertyAnimator animation = view.animate(); mAddAnimations.add(holder); @@ -255,7 +258,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { } @Override - public boolean animateMove(final ViewHolder holder, int fromX, int fromY, + public boolean animateMove(final RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) { final View view = holder.itemView; fromX += (int) holder.itemView.getTranslationX(); @@ -277,7 +280,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { return true; } - void animateMoveImpl(final ViewHolder holder, int fromX, int fromY, int toX, int toY) { + void animateMoveImpl(final RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) { final View view = holder.itemView; final int deltaX = toX - fromX; final int deltaY = toY - fromY; @@ -319,7 +322,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { } @Override - public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder, + public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) { if (oldHolder == newHolder) { // Don't know how to run change animations when the same view holder is re-used. @@ -348,9 +351,9 @@ public class DefaultItemAnimator extends SimpleItemAnimator { } void animateChangeImpl(final ChangeInfo changeInfo) { - final ViewHolder holder = changeInfo.oldHolder; + final RecyclerView.ViewHolder holder = changeInfo.oldHolder; final View view = holder == null ? null : holder.itemView; - final ViewHolder newHolder = changeInfo.newHolder; + final RecyclerView.ViewHolder newHolder = changeInfo.newHolder; final View newView = newHolder != null ? newHolder.itemView : null; if (view != null) { final ViewPropertyAnimator oldViewAnim = view.animate().setDuration( @@ -399,7 +402,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { } } - private void endChangeAnimation(List infoList, ViewHolder item) { + private void endChangeAnimation(List infoList, RecyclerView.ViewHolder item) { for (int i = infoList.size() - 1; i >= 0; i--) { ChangeInfo changeInfo = infoList.get(i); if (endChangeAnimationIfNecessary(changeInfo, item)) { @@ -418,7 +421,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder); } } - private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, ViewHolder item) { + private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, RecyclerView.ViewHolder item) { boolean oldItem = false; if (changeInfo.newHolder == item) { changeInfo.newHolder = null; @@ -436,7 +439,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { } @Override - public void endAnimation(ViewHolder item) { + public void endAnimation(RecyclerView.ViewHolder item) { final View view = item.itemView; // this will trigger end callback which should set properties to their target values. view.animate().cancel(); @@ -484,7 +487,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { } } for (int i = mAdditionsList.size() - 1; i >= 0; i--) { - ArrayList additions = mAdditionsList.get(i); + ArrayList additions = mAdditionsList.get(i); if (additions.remove(item)) { view.setAlpha(1); dispatchAddFinished(item); @@ -521,7 +524,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { dispatchFinishedWhenDone(); } - private void resetAnimation(ViewHolder holder) { + private void resetAnimation(RecyclerView.ViewHolder holder) { if (sDefaultInterpolator == null) { sDefaultInterpolator = new ValueAnimator().getInterpolator(); } @@ -552,9 +555,14 @@ public class DefaultItemAnimator extends SimpleItemAnimator { void dispatchFinishedWhenDone() { if (!isRunning()) { dispatchAnimationsFinished(); + onAllAnimationsDone(); } } + protected void onAllAnimationsDone() { + + } + @Override public void endAnimations() { int count = mPendingMoves.size(); @@ -568,13 +576,13 @@ public class DefaultItemAnimator extends SimpleItemAnimator { } count = mPendingRemovals.size(); for (int i = count - 1; i >= 0; i--) { - ViewHolder item = mPendingRemovals.get(i); + RecyclerView.ViewHolder item = mPendingRemovals.get(i); dispatchRemoveFinished(item); mPendingRemovals.remove(i); } count = mPendingAdditions.size(); for (int i = count - 1; i >= 0; i--) { - ViewHolder item = mPendingAdditions.get(i); + RecyclerView.ViewHolder item = mPendingAdditions.get(i); item.itemView.setAlpha(1); dispatchAddFinished(item); mPendingAdditions.remove(i); @@ -594,7 +602,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { count = moves.size(); for (int j = count - 1; j >= 0; j--) { MoveInfo moveInfo = moves.get(j); - ViewHolder item = moveInfo.holder; + RecyclerView.ViewHolder item = moveInfo.holder; View view = item.itemView; view.setTranslationY(0); view.setTranslationX(0); @@ -607,10 +615,10 @@ public class DefaultItemAnimator extends SimpleItemAnimator { } listCount = mAdditionsList.size(); for (int i = listCount - 1; i >= 0; i--) { - ArrayList additions = mAdditionsList.get(i); + ArrayList additions = mAdditionsList.get(i); count = additions.size(); for (int j = count - 1; j >= 0; j--) { - ViewHolder item = additions.get(j); + RecyclerView.ViewHolder item = additions.get(j); View view = item.itemView; view.setAlpha(1); dispatchAddFinished(item); @@ -640,7 +648,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { dispatchAnimationsFinished(); } - void cancelAll(List viewHolders) { + void cancelAll(List viewHolders) { for (int i = viewHolders.size() - 1; i >= 0; i--) { viewHolders.get(i).itemView.animate().cancel(); } @@ -652,18 +660,18 @@ public class DefaultItemAnimator extends SimpleItemAnimator { * If the payload list is not empty, DefaultItemAnimator returns true. * When this is the case: *

      - *
    • If you override {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)}, both + *
    • If you override {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}, both * ViewHolder arguments will be the same instance. *
    • *
    • - * If you are not overriding {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)}, - * then DefaultItemAnimator will call {@link #animateMove(ViewHolder, int, int, int, int)} and + * If you are not overriding {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}, + * then DefaultItemAnimator will call {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int)} and * run a move animation instead. *
    • *
    */ @Override - public boolean canReuseUpdatedViewHolder(@NonNull ViewHolder viewHolder, + public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull List payloads) { return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/DiffUtil.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/DiffUtil.java similarity index 89% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/util/DiffUtil.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/DiffUtil.java index f3c588510..8f8d8e64d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/DiffUtil.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/DiffUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,11 +14,12 @@ * limitations under the License. */ -package org.telegram.messenger.support.util; +package androidx.recyclerview.widget; -import android.support.annotation.Nullable; -import android.support.annotation.VisibleForTesting; -import org.telegram.messenger.support.widget.RecyclerView; +import androidx.annotation.IntRange; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import java.util.ArrayList; import java.util.Arrays; @@ -27,18 +28,23 @@ import java.util.Comparator; import java.util.List; /** - * DiffUtil is a utility class that can calculate the difference between two lists and output a + * DiffUtil is a utility class that calculates the difference between two lists and outputs a * list of update operations that converts the first list into the second one. *

    - * It can be used to calculate updates for a RecyclerView Adapter. See - * {@link android.support.v7.recyclerview.extensions.ListAdapter} and - * {@link android.support.v7.recyclerview.extensions.AsyncListDiffer} which can compute diffs using - * DiffUtil on a background thread. + * It can be used to calculate updates for a RecyclerView Adapter. See {@link ListAdapter} and + * {@link AsyncListDiffer} which can simplify the use of DiffUtil on a background thread. *

    * DiffUtil uses Eugene W. Myers's difference algorithm to calculate the minimal number of updates * to convert one list into another. Myers's algorithm does not handle items that are moved so * DiffUtil runs a second pass on the result to detect items that were moved. *

    + * Note that DiffUtil, ListAdapter, and AsyncListDiffer require the list to not mutate while in use. + * This generally means that both the lists themselves and their elements (or at least, the + * properties of elements used in diffing) should not be modified directly. Instead, new lists + * should be provided any time content changes. It's common for lists passed to DiffUtil to share + * elements that have not mutated, so it is not strictly required to reload all data to use + * DiffUtil. + *

    * If the lists are large, this operation may take significant time so you are advised to run this * on a background thread, get the {@link DiffResult} then apply it on the RecyclerView on the main * thread. @@ -66,7 +72,8 @@ import java.util.List; *

    * Due to implementation constraints, the max size of the list can be 2^26. * - * @see android.support.v7.recyclerview.extensions.AsyncListDiffer + * @see ListAdapter + * @see AsyncListDiffer */ public class DiffUtil { @@ -93,7 +100,8 @@ public class DiffUtil { * @return A DiffResult that contains the information about the edit sequence to convert the * old list into the new list. */ - public static DiffResult calculateDiff(Callback cb) { + @NonNull + public static DiffResult calculateDiff(@NonNull Callback cb) { return calculateDiff(cb, true); } @@ -110,7 +118,8 @@ public class DiffUtil { * @return A DiffResult that contains the information about the edit sequence to convert the * old list into the new list. */ - public static DiffResult calculateDiff(Callback cb, boolean detectMoves) { + @NonNull + public static DiffResult calculateDiff(@NonNull Callback cb, boolean detectMoves) { final int oldSize = cb.getOldListSize(); final int newSize = cb.getNewListSize(); @@ -316,7 +325,7 @@ public class DiffUtil { * DiffUtil uses this method to check equality instead of {@link Object#equals(Object)} * so that you can change its behavior depending on your UI. * For example, if you are using DiffUtil with a - * {@link android.support.v7.widget.RecyclerView.Adapter RecyclerView.Adapter}, you should + * {@link RecyclerView.Adapter RecyclerView.Adapter}, you should * return whether the items' visual representations are the same. *

    * This method is called only if {@link #areItemsTheSame(int, int)} returns @@ -336,7 +345,7 @@ public class DiffUtil { *

    * For example, if you are using DiffUtil with {@link RecyclerView}, you can return the * particular field that changed in the item and your - * {@link android.support.v7.widget.RecyclerView.ItemAnimator ItemAnimator} can use that + * {@link RecyclerView.ItemAnimator ItemAnimator} can use that * information to run the correct animation. *

    * Default implementation returns {@code null}. @@ -366,6 +375,10 @@ public class DiffUtil { * Called to check whether two objects represent the same item. *

    * For example, if your items have unique ids, this method should check their id equality. + *

    + * Note: {@code null} items in the list are assumed to be the same as another {@code null} + * item and are assumed to not be the same as a non-{@code null} item. This callback will + * not be invoked for either of those cases. * * @param oldItem The item in the old list. * @param newItem The item in the new list. @@ -373,7 +386,7 @@ public class DiffUtil { * * @see Callback#areItemsTheSame(int, int) */ - public abstract boolean areItemsTheSame(T oldItem, T newItem); + public abstract boolean areItemsTheSame(@NonNull T oldItem, @NonNull T newItem); /** * Called to check whether two items have the same data. @@ -384,11 +397,14 @@ public class DiffUtil { * change its behavior depending on your UI. *

    * For example, if you are using DiffUtil with a - * {@link android.support.v7.widget.RecyclerView.Adapter RecyclerView.Adapter}, you should + * {@link RecyclerView.Adapter RecyclerView.Adapter}, you should * return whether the items' visual representations are the same. *

    * This method is called only if {@link #areItemsTheSame(T, T)} returns {@code true} for * these items. + *

    + * Note: Two {@code null} items are assumed to represent the same contents. This callback + * will not be invoked for this case. * * @param oldItem The item in the old list. * @param newItem The item in the new list. @@ -396,7 +412,7 @@ public class DiffUtil { * * @see Callback#areContentsTheSame(int, int) */ - public abstract boolean areContentsTheSame(T oldItem, T newItem); + public abstract boolean areContentsTheSame(@NonNull T oldItem, @NonNull T newItem); /** * When {@link #areItemsTheSame(T, T)} returns {@code true} for two items and @@ -405,7 +421,7 @@ public class DiffUtil { *

    * For example, if you are using DiffUtil with {@link RecyclerView}, you can return the * particular field that changed in the item and your - * {@link android.support.v7.widget.RecyclerView.ItemAnimator ItemAnimator} can use that + * {@link RecyclerView.ItemAnimator ItemAnimator} can use that * information to run the correct animation. *

    * Default implementation returns {@code null}. @@ -413,7 +429,8 @@ public class DiffUtil { * @see Callback#getChangePayload(int, int) */ @SuppressWarnings({"WeakerAccess", "unused"}) - public Object getChangePayload(T oldItem, T newItem) { + @Nullable + public Object getChangePayload(@NonNull T oldItem, @NonNull T newItem) { return null; } } @@ -482,6 +499,12 @@ public class DiffUtil { * {@link RecyclerView.Adapter} via {@link #dispatchUpdatesTo(RecyclerView.Adapter)}. */ public static class DiffResult { + /** + * Signifies an item not present in the list. + */ + public static final int NO_POSITION = -1; + + /** * While reading the flags below, keep in mind that when multiple items move in a list, * Myers's may pick any of them as the anchor item and consider that one NOT_CHANGED while @@ -633,6 +656,54 @@ public class DiffUtil { findMatchingItem(x, y, snakeIndex, true); } + /** + * Given a position in the old list, returns the position in the new list, or + * {@code NO_POSITION} if it was removed. + * + * @param oldListPosition Position of item in old list + * + * @return Position of item in new list, or {@code NO_POSITION} if not present. + * + * @see #NO_POSITION + * @see #convertNewPositionToOld(int) + */ + public int convertOldPositionToNew(@IntRange(from = 0) int oldListPosition) { + if (oldListPosition < 0 || oldListPosition >= mOldListSize) { + throw new IndexOutOfBoundsException("Index out of bounds - passed position = " + + oldListPosition + ", old list size = " + mOldListSize); + } + final int status = mOldItemStatuses[oldListPosition]; + if ((status & FLAG_MASK) == 0) { + return NO_POSITION; + } else { + return status >> FLAG_OFFSET; + } + } + + /** + * Given a position in the new list, returns the position in the old list, or + * {@code NO_POSITION} if it was removed. + * + * @param newListPosition Position of item in new list + * + * @return Position of item in old list, or {@code NO_POSITION} if not present. + * + * @see #NO_POSITION + * @see #convertOldPositionToNew(int) + */ + public int convertNewPositionToOld(@IntRange(from = 0) int newListPosition) { + if (newListPosition < 0 || newListPosition >= mNewListSize) { + throw new IndexOutOfBoundsException("Index out of bounds - passed position = " + + newListPosition + ", new list size = " + mNewListSize); + } + final int status = mNewItemStatuses[newListPosition]; + if ((status & FLAG_MASK) == 0) { + return NO_POSITION; + } else { + return status >> FLAG_OFFSET; + } + } + /** * Finds a matching item that is before the given coordinates in the matrix * (before : left and above). @@ -698,7 +769,7 @@ public class DiffUtil { /** * Dispatches the update events to the given adapter. *

    - * For example, if you have an {@link android.support.v7.widget.RecyclerView.Adapter Adapter} + * For example, if you have an {@link RecyclerView.Adapter Adapter} * that is backed by a {@link List}, you can swap the list with the new one then call this * method to dispatch all updates to the RecyclerView. *

    @@ -714,11 +785,11 @@ public class DiffUtil {
              * before RecyclerView tries to read it.
              * 

    * On the other hand, if you have another - * {@link android.support.v7.widget.RecyclerView.AdapterDataObserver AdapterDataObserver} + * {@link RecyclerView.AdapterDataObserver AdapterDataObserver} * that tries to process events synchronously, this may confuse that observer because the * list is instantly moved to its final state while the adapter updates are dispatched later * on, one by one. If you have such an - * {@link android.support.v7.widget.RecyclerView.AdapterDataObserver AdapterDataObserver}, + * {@link RecyclerView.AdapterDataObserver AdapterDataObserver}, * you can use * {@link #dispatchUpdatesTo(ListUpdateCallback)} to handle each modification * manually. @@ -727,7 +798,7 @@ public class DiffUtil { * displaying the new list. * @see AdapterListUpdateCallback */ - public void dispatchUpdatesTo(final RecyclerView.Adapter adapter) { + public void dispatchUpdatesTo(@NonNull final RecyclerView.Adapter adapter) { dispatchUpdatesTo(new AdapterListUpdateCallback(adapter)); } @@ -740,7 +811,7 @@ public class DiffUtil { * @param updateCallback The callback to receive the update operations. * @see #dispatchUpdatesTo(RecyclerView.Adapter) */ - public void dispatchUpdatesTo(ListUpdateCallback updateCallback) { + public void dispatchUpdatesTo(@NonNull ListUpdateCallback updateCallback) { final BatchingListUpdateCallback batchingCallback; if (updateCallback instanceof BatchingListUpdateCallback) { batchingCallback = (BatchingListUpdateCallback) updateCallback; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/DividerItemDecoration.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/DividerItemDecoration.java similarity index 95% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/DividerItemDecoration.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/DividerItemDecoration.java index 0d07c6b6b..ef9e9bae0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/DividerItemDecoration.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/DividerItemDecoration.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,18 +15,20 @@ */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; import android.util.Log; import android.view.View; import android.widget.LinearLayout; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + /** * DividerItemDecoration is a {@link RecyclerView.ItemDecoration} that can be used as a divider * between items of a {@link LinearLayoutManager}. It supports both {@link #HORIZONTAL} and @@ -98,6 +100,14 @@ public class DividerItemDecoration extends RecyclerView.ItemDecoration { mDivider = drawable; } + /** + * @return the {@link Drawable} for this divider. + */ + @Nullable + public Drawable getDrawable() { + return mDivider; + } + @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { if (parent.getLayoutManager() == null || mDivider == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/FastScroller.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/FastScroller.java similarity index 93% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/FastScroller.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/FastScroller.java index 56e4267d0..37a6ce32e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/FastScroller.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/FastScroller.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -23,15 +23,14 @@ import android.animation.ValueAnimator.AnimatorUpdateListener; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.graphics.drawable.StateListDrawable; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; -import android.support.annotation.VisibleForTesting; -import android.support.v4.view.ViewCompat; -import org.telegram.messenger.support.widget.RecyclerView.ItemDecoration; -import org.telegram.messenger.support.widget.RecyclerView.OnItemTouchListener; -import org.telegram.messenger.support.widget.RecyclerView.OnScrollListener; import android.view.MotionEvent; +import androidx.annotation.IntDef; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; +import androidx.core.view.ViewCompat; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -39,7 +38,7 @@ import java.lang.annotation.RetentionPolicy; * Class responsible to animate and provide a fast scroller. */ @VisibleForTesting -class FastScroller extends ItemDecoration implements OnItemTouchListener { +class FastScroller extends RecyclerView.ItemDecoration implements RecyclerView.OnItemTouchListener { @IntDef({STATE_HIDDEN, STATE_VISIBLE, STATE_DRAGGING}) @Retention(RetentionPolicy.SOURCE) private @interface State { } @@ -79,8 +78,10 @@ class FastScroller extends ItemDecoration implements OnItemTouchListener { private final int mMargin; // Final values for the vertical scroll bar - private final StateListDrawable mVerticalThumbDrawable; - private final Drawable mVerticalTrackDrawable; + @SuppressWarnings("WeakerAccess") /* synthetic access */ + final StateListDrawable mVerticalThumbDrawable; + @SuppressWarnings("WeakerAccess") /* synthetic access */ + final Drawable mVerticalTrackDrawable; private final int mVerticalThumbWidth; private final int mVerticalTrackWidth; @@ -115,15 +116,18 @@ class FastScroller extends ItemDecoration implements OnItemTouchListener { private final int[] mVerticalRange = new int[2]; private final int[] mHorizontalRange = new int[2]; - private final ValueAnimator mShowHideAnimator = ValueAnimator.ofFloat(0, 1); - @AnimationState private int mAnimationState = ANIMATION_STATE_OUT; + @SuppressWarnings("WeakerAccess") /* synthetic access */ + final ValueAnimator mShowHideAnimator = ValueAnimator.ofFloat(0, 1); + @SuppressWarnings("WeakerAccess") /* synthetic access */ + @AnimationState int mAnimationState = ANIMATION_STATE_OUT; private final Runnable mHideRunnable = new Runnable() { @Override public void run() { hide(HIDE_DURATION_MS); } }; - private final OnScrollListener mOnScrollListener = new OnScrollListener() { + private final RecyclerView.OnScrollListener + mOnScrollListener = new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { updateScrollPosition(recyclerView.computeHorizontalScrollOffset(), @@ -182,11 +186,12 @@ class FastScroller extends ItemDecoration implements OnItemTouchListener { cancelHide(); } - private void requestRedraw() { + @SuppressWarnings("WeakerAccess") /* synthetic access */ + void requestRedraw() { mRecyclerView.invalidate(); } - private void setState(@State int state) { + void setState(@State int state) { if (state == STATE_DRAGGING && mState != STATE_DRAGGING) { mVerticalThumbDrawable.setState(PRESSED_STATE_SET); cancelHide(); @@ -219,11 +224,6 @@ class FastScroller extends ItemDecoration implements OnItemTouchListener { return mState == STATE_VISIBLE; } - @VisibleForTesting boolean isHidden() { - return mState == STATE_HIDDEN; - } - - public void show() { switch (mAnimationState) { case ANIMATION_STATE_FADING_OUT: @@ -239,10 +239,6 @@ class FastScroller extends ItemDecoration implements OnItemTouchListener { } } - public void hide() { - hide(0); - } - @VisibleForTesting void hide(int duration) { switch (mAnimationState) { @@ -379,7 +375,8 @@ class FastScroller extends ItemDecoration implements OnItemTouchListener { } @Override - public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent ev) { + public boolean onInterceptTouchEvent(@NonNull RecyclerView recyclerView, + @NonNull MotionEvent ev) { final boolean handled; if (mState == STATE_VISIBLE) { boolean insideVerticalThumb = isPointInsideVerticalThumb(ev.getX(), ev.getY()); @@ -408,7 +405,7 @@ class FastScroller extends ItemDecoration implements OnItemTouchListener { } @Override - public void onTouchEvent(RecyclerView recyclerView, MotionEvent me) { + public void onTouchEvent(@NonNull RecyclerView recyclerView, @NonNull MotionEvent me) { if (mState == STATE_HIDDEN) { return; } @@ -551,6 +548,9 @@ class FastScroller extends ItemDecoration implements OnItemTouchListener { private boolean mCanceled = false; + AnimatorListener() { + } + @Override public void onAnimationEnd(Animator animation) { // Cancel is always followed by a new directive, so don't update state. @@ -574,6 +574,8 @@ class FastScroller extends ItemDecoration implements OnItemTouchListener { } private class AnimatorUpdater implements AnimatorUpdateListener { + AnimatorUpdater() { + } @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/GapWorker.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/GapWorker.java similarity index 98% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/GapWorker.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/GapWorker.java index 907c29d6d..b2d9f2e77 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/GapWorker.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/GapWorker.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,12 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; -import android.support.annotation.Nullable; -import android.support.v4.os.TraceCompat; +import android.annotation.SuppressLint; import android.view.View; +import androidx.annotation.Nullable; +import androidx.core.os.TraceCompat; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -59,6 +61,7 @@ final class GapWorker implements Runnable { /** * Prefetch information associated with a specific RecyclerView. */ + @SuppressLint("VisibleForTests") static class LayoutPrefetchRegistryImpl implements RecyclerView.LayoutManager.LayoutPrefetchRegistry { int mPrefetchDx; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/GridLayoutManager.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/GridLayoutManager.java similarity index 81% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/GridLayoutManager.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/GridLayoutManager.java index 020890091..5f50bb49c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/GridLayoutManager.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/GridLayoutManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,17 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; import android.content.Context; import android.graphics.Rect; -import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; import android.util.AttributeSet; import android.util.Log; import android.util.SparseIntArray; import android.view.View; import android.view.ViewGroup; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; + import java.util.Arrays; /** @@ -47,7 +48,7 @@ public class GridLayoutManager extends LinearLayoutManager { *

    For i-th item start is {@link #mCachedBorders}[i-1] + 1 * and end is {@link #mCachedBorders}[i]. */ - int [] mCachedBorders; + protected int [] mCachedBorders; /** * Temporary array to keep views in layoutChunk method */ @@ -58,6 +59,8 @@ public class GridLayoutManager extends LinearLayoutManager { // re-used variable to acquire decor insets from RecyclerView final Rect mDecorInsets = new Rect(); + private boolean mUsingSpansToEstimateScrollBarDimensions; + /** * Creates a vertical GridLayoutManager * @@ -183,27 +186,32 @@ public class GridLayoutManager extends LinearLayoutManager { @Override public void onItemsAdded(RecyclerView recyclerView, int positionStart, int itemCount) { mSpanSizeLookup.invalidateSpanIndexCache(); + mSpanSizeLookup.invalidateSpanGroupIndexCache(); } @Override public void onItemsChanged(RecyclerView recyclerView) { mSpanSizeLookup.invalidateSpanIndexCache(); + mSpanSizeLookup.invalidateSpanGroupIndexCache(); } @Override public void onItemsRemoved(RecyclerView recyclerView, int positionStart, int itemCount) { mSpanSizeLookup.invalidateSpanIndexCache(); + mSpanSizeLookup.invalidateSpanGroupIndexCache(); } @Override public void onItemsUpdated(RecyclerView recyclerView, int positionStart, int itemCount, Object payload) { mSpanSizeLookup.invalidateSpanIndexCache(); + mSpanSizeLookup.invalidateSpanGroupIndexCache(); } @Override public void onItemsMoved(RecyclerView recyclerView, int from, int to, int itemCount) { mSpanSizeLookup.invalidateSpanIndexCache(); + mSpanSizeLookup.invalidateSpanGroupIndexCache(); } @Override @@ -290,7 +298,7 @@ public class GridLayoutManager extends LinearLayoutManager { /** * @param totalSpace Total available space after padding is removed */ - protected void calculateItemBorders(int totalSpace) { + private void calculateItemBorders(int totalSpace) { mCachedBorders = calculateItemBorders(mCachedBorders, mSpanCount, totalSpace); } @@ -433,7 +441,7 @@ public class GridLayoutManager extends LinearLayoutManager { private int getSpanGroupIndex(RecyclerView.Recycler recycler, RecyclerView.State state, int viewPosition) { if (!state.isPreLayout()) { - return mSpanSizeLookup.getSpanGroupIndex(viewPosition, mSpanCount); + return mSpanSizeLookup.getCachedSpanGroupIndex(viewPosition, mSpanCount); } final int adapterPosition = recycler.convertPreLayoutPositionToPostLayout(viewPosition); if (adapterPosition == -1) { @@ -444,7 +452,7 @@ public class GridLayoutManager extends LinearLayoutManager { Log.w(TAG, "Cannot find span size for pre layout position. " + viewPosition); return 0; } - return mSpanSizeLookup.getSpanGroupIndex(adapterPosition, mSpanCount); + return mSpanSizeLookup.getCachedSpanGroupIndex(adapterPosition, mSpanCount); } private int getSpanIndex(RecyclerView.Recycler recycler, RecyclerView.State state, int pos) { @@ -556,7 +564,7 @@ public class GridLayoutManager extends LinearLayoutManager { float maxSizeInOther = 0; // use a float to get size per span // we should assign spans before item decor offsets are calculated - assignSpans(recycler, state, count, consumedSpanCount, layingOutInPrimaryDirection); + assignSpans(recycler, state, count, layingOutInPrimaryDirection); for (int i = 0; i < count; i++) { View view = mSet[i]; if (layoutState.mScrapList == null) { @@ -747,7 +755,7 @@ public class GridLayoutManager extends LinearLayoutManager { } protected void assignSpans(RecyclerView.Recycler recycler, RecyclerView.State state, int count, - int consumedSpanCount, boolean layingOutInPrimaryDirection) { + boolean layingOutInPrimaryDirection) { // spans are always assigned from 0 to N no matter if it is RTL or not. // RTL is used only when positioning the view. int span, start, end, diff; @@ -814,8 +822,10 @@ public class GridLayoutManager extends LinearLayoutManager { public abstract static class SpanSizeLookup { final SparseIntArray mSpanIndexCache = new SparseIntArray(); + final SparseIntArray mSpanGroupIndexCache = new SparseIntArray(); private boolean mCacheSpanIndices = false; + private boolean mCacheSpanGroupIndices = false; /** * Returns the number of span occupied by the item at position. @@ -828,14 +838,35 @@ public class GridLayoutManager extends LinearLayoutManager { /** * Sets whether the results of {@link #getSpanIndex(int, int)} method should be cached or * not. By default these values are not cached. If you are not overriding - * {@link #getSpanIndex(int, int)}, you should set this to true for better performance. + * {@link #getSpanIndex(int, int)} with something highly performant, you should set this + * to true for better performance. * * @param cacheSpanIndices Whether results of getSpanIndex should be cached or not. */ public void setSpanIndexCacheEnabled(boolean cacheSpanIndices) { + if (!cacheSpanIndices) { + mSpanGroupIndexCache.clear(); + } mCacheSpanIndices = cacheSpanIndices; } + /** + * Sets whether the results of {@link #getSpanGroupIndex(int, int)} method should be cached + * or not. By default these values are not cached. If you are not overriding + * {@link #getSpanGroupIndex(int, int)} with something highly performant, and you are using + * spans to calculate scrollbar offset and range, you should set this to true for better + * performance. + * + * @param cacheSpanGroupIndices Whether results of getGroupSpanIndex should be cached or + * not. + */ + public void setSpanGroupIndexCacheEnabled(boolean cacheSpanGroupIndices) { + if (!cacheSpanGroupIndices) { + mSpanGroupIndexCache.clear(); + } + mCacheSpanGroupIndices = cacheSpanGroupIndices; + } + /** * Clears the span index cache. GridLayoutManager automatically calls this method when * adapter changes occur. @@ -844,6 +875,14 @@ public class GridLayoutManager extends LinearLayoutManager { mSpanIndexCache.clear(); } + /** + * Clears the span group index cache. GridLayoutManager automatically calls this method + * when adapter changes occur. + */ + public void invalidateSpanGroupIndexCache() { + mSpanGroupIndexCache.clear(); + } + /** * Returns whether results of {@link #getSpanIndex(int, int)} method are cached or not. * @@ -853,6 +892,15 @@ public class GridLayoutManager extends LinearLayoutManager { return mCacheSpanIndices; } + /** + * Returns whether results of {@link #getSpanGroupIndex(int, int)} method are cached or not. + * + * @return True if results of {@link #getSpanGroupIndex(int, int)} are cached. + */ + public boolean isSpanGroupIndexCacheEnabled() { + return mCacheSpanGroupIndices; + } + int getCachedSpanIndex(int position, int spanCount) { if (!mCacheSpanIndices) { return getSpanIndex(position, spanCount); @@ -866,6 +914,19 @@ public class GridLayoutManager extends LinearLayoutManager { return value; } + int getCachedSpanGroupIndex(int position, int spanCount) { + if (!mCacheSpanGroupIndices) { + return getSpanGroupIndex(position, spanCount); + } + final int existing = mSpanGroupIndexCache.get(position, -1); + if (existing != -1) { + return existing; + } + final int value = getSpanGroupIndex(position, spanCount); + mSpanGroupIndexCache.put(position, value); + return value; + } + /** * Returns the final span index of the provided position. *

    @@ -897,8 +958,8 @@ public class GridLayoutManager extends LinearLayoutManager { int span = 0; int startPos = 0; // If caching is enabled, try to jump - if (mCacheSpanIndices && mSpanIndexCache.size() > 0) { - int prevKey = findReferenceIndexFromCache(position); + if (mCacheSpanIndices) { + int prevKey = findFirstKeyLessThan(mSpanIndexCache, position); if (prevKey >= 0) { span = mSpanIndexCache.get(prevKey) + getSpanSize(prevKey); startPos = prevKey + 1; @@ -920,13 +981,15 @@ public class GridLayoutManager extends LinearLayoutManager { return 0; } - int findReferenceIndexFromCache(int position) { + static int findFirstKeyLessThan(SparseIntArray cache, int position) { int lo = 0; - int hi = mSpanIndexCache.size() - 1; + int hi = cache.size() - 1; while (lo <= hi) { + // Using unsigned shift here to divide by two because it is guaranteed to not + // overflow. final int mid = (lo + hi) >>> 1; - final int midVal = mSpanIndexCache.keyAt(mid); + final int midVal = cache.keyAt(mid); if (midVal < position) { lo = mid + 1; } else { @@ -934,8 +997,8 @@ public class GridLayoutManager extends LinearLayoutManager { } } int index = lo - 1; - if (index >= 0 && index < mSpanIndexCache.size()) { - return mSpanIndexCache.keyAt(index); + if (index >= 0 && index < cache.size()) { + return cache.keyAt(index); } return -1; } @@ -953,8 +1016,22 @@ public class GridLayoutManager extends LinearLayoutManager { public int getSpanGroupIndex(int adapterPosition, int spanCount) { int span = 0; int group = 0; + int start = 0; + if (mCacheSpanGroupIndices) { + // This finds the first non empty cached group cache key. + int prevKey = findFirstKeyLessThan(mSpanGroupIndexCache, adapterPosition); + if (prevKey != -1) { + group = mSpanGroupIndexCache.get(prevKey); + start = prevKey + 1; + span = getCachedSpanIndex(prevKey, spanCount) + getSpanSize(prevKey); + if (span == spanCount) { + span = 0; + group++; + } + } + } int positionSpanSize = getSpanSize(adapterPosition); - for (int i = 0; i < adapterPosition; i++) { + for (int i = start; i < adapterPosition; i++) { int size = getSpanSize(i); span += size; if (span == spanCount) { @@ -1101,6 +1178,158 @@ public class GridLayoutManager extends LinearLayoutManager { return mPendingSavedState == null && !mPendingSpanCountChange; } + @Override + public int computeHorizontalScrollRange(RecyclerView.State state) { + if (mUsingSpansToEstimateScrollBarDimensions) { + return computeScrollRangeWithSpanInfo(state); + } else { + return super.computeHorizontalScrollRange(state); + } + } + + @Override + public int computeVerticalScrollRange(RecyclerView.State state) { + if (mUsingSpansToEstimateScrollBarDimensions) { + return computeScrollRangeWithSpanInfo(state); + } else { + return super.computeVerticalScrollRange(state); + } + } + + @Override + public int computeHorizontalScrollOffset(RecyclerView.State state) { + if (mUsingSpansToEstimateScrollBarDimensions) { + return computeScrollOffsetWithSpanInfo(state); + } else { + return super.computeHorizontalScrollOffset(state); + } + } + + @Override + public int computeVerticalScrollOffset(RecyclerView.State state) { + if (mUsingSpansToEstimateScrollBarDimensions) { + return computeScrollOffsetWithSpanInfo(state); + } else { + return super.computeVerticalScrollOffset(state); + } + } + + /** + * When this flag is set, the scroll offset and scroll range calculations will take account + * of span information. + * + *

    This is will increase the accuracy of the scroll bar's size and offset but will require + * more calls to {@link SpanSizeLookup#getSpanGroupIndex(int, int)}". + * + *

    This additional accuracy may or may not be needed, depending on the characteristics of + * your layout. You will likely benefit from this accuracy when: + * + *

      + *
    • The variation in item span sizes is large. + *
    • The size of your data set is small (if your data set is large, the scrollbar will + * likely be very small anyway, and thus the increased accuracy has less impact). + *
    • Calls to {@link SpanSizeLookup#getSpanGroupIndex(int, int)} are fast. + *
    + * + *

    If you decide to enable this feature, you should be sure that calls to + * {@link SpanSizeLookup#getSpanGroupIndex(int, int)} are fast, that set span group index + * caching is set to true via a call to + * {@link SpanSizeLookup#setSpanGroupIndexCacheEnabled(boolean), + * and span index caching is also enabled via a call to + * {@link SpanSizeLookup#setSpanIndexCacheEnabled(boolean)}}. + */ + public void setUsingSpansToEstimateScrollbarDimensions( + boolean useSpansToEstimateScrollBarDimensions) { + mUsingSpansToEstimateScrollBarDimensions = useSpansToEstimateScrollBarDimensions; + } + + /** + * Returns true if the scroll offset and scroll range calculations take account of span + * information. See {@link #setUsingSpansToEstimateScrollbarDimensions(boolean)} for more + * information on this topic. Defaults to {@code false}. + * + * @return true if the scroll offset and scroll range calculations take account of span + * information. + */ + public boolean isUsingSpansToEstimateScrollbarDimensions() { + return mUsingSpansToEstimateScrollBarDimensions; + } + + private int computeScrollRangeWithSpanInfo(RecyclerView.State state) { + if (getChildCount() == 0 || state.getItemCount() == 0) { + return 0; + } + ensureLayoutState(); + + View startChild = findFirstVisibleChildClosestToStart(!isSmoothScrollbarEnabled(), true); + View endChild = findFirstVisibleChildClosestToEnd(!isSmoothScrollbarEnabled(), true); + + if (startChild == null || endChild == null) { + return 0; + } + if (!isSmoothScrollbarEnabled()) { + return mSpanSizeLookup.getCachedSpanGroupIndex( + state.getItemCount() - 1, mSpanCount) + 1; + } + + // smooth scrollbar enabled. try to estimate better. + final int laidOutArea = mOrientationHelper.getDecoratedEnd(endChild) + - mOrientationHelper.getDecoratedStart(startChild); + + final int firstVisibleSpan = + mSpanSizeLookup.getCachedSpanGroupIndex(getPosition(startChild), mSpanCount); + final int lastVisibleSpan = mSpanSizeLookup.getCachedSpanGroupIndex(getPosition(endChild), + mSpanCount); + final int totalSpans = mSpanSizeLookup.getCachedSpanGroupIndex(state.getItemCount() - 1, + mSpanCount) + 1; + final int laidOutSpans = lastVisibleSpan - firstVisibleSpan + 1; + + // estimate a size for full list. + return (int) (((float) laidOutArea / laidOutSpans) * totalSpans); + } + + private int computeScrollOffsetWithSpanInfo(RecyclerView.State state) { + if (getChildCount() == 0 || state.getItemCount() == 0) { + return 0; + } + ensureLayoutState(); + + boolean smoothScrollEnabled = isSmoothScrollbarEnabled(); + View startChild = findFirstVisibleChildClosestToStart(!smoothScrollEnabled, true); + View endChild = findFirstVisibleChildClosestToEnd(!smoothScrollEnabled, true); + if (startChild == null || endChild == null) { + return 0; + } + int startChildSpan = mSpanSizeLookup.getCachedSpanGroupIndex(getPosition(startChild), + mSpanCount); + int endChildSpan = mSpanSizeLookup.getCachedSpanGroupIndex(getPosition(endChild), + mSpanCount); + + final int minSpan = Math.min(startChildSpan, endChildSpan); + final int maxSpan = Math.max(startChildSpan, endChildSpan); + final int totalSpans = mSpanSizeLookup.getCachedSpanGroupIndex(state.getItemCount() - 1, + mSpanCount) + 1; + + final int spansBefore = mShouldReverseLayout + ? Math.max(0, totalSpans - maxSpan - 1) + : Math.max(0, minSpan); + if (!smoothScrollEnabled) { + return spansBefore; + } + final int laidOutArea = Math.abs(mOrientationHelper.getDecoratedEnd(endChild) + - mOrientationHelper.getDecoratedStart(startChild)); + + final int firstVisibleSpan = + mSpanSizeLookup.getCachedSpanGroupIndex(getPosition(startChild), mSpanCount); + final int lastVisibleSpan = mSpanSizeLookup.getCachedSpanGroupIndex(getPosition(endChild), + mSpanCount); + final int laidOutSpans = lastVisibleSpan - firstVisibleSpan + 1; + final float avgSizePerSpan = (float) laidOutArea / laidOutSpans; + + return Math.round(spansBefore * avgSizePerSpan + (mOrientationHelper.getStartAfterPadding() + - mOrientationHelper.getDecoratedStart(startChild))); + } + /** * Default implementation for {@link SpanSizeLookup}. Each item occupies 1 span. */ @@ -1133,7 +1362,7 @@ public class GridLayoutManager extends LinearLayoutManager { int mSpanIndex = INVALID_SPAN_ID; - int mSpanSize = 0; + public int mSpanSize = 0; public LayoutParams(Context c, AttributeSet attrs) { super(c, attrs); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/GridLayoutManagerFixed.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/GridLayoutManagerFixed.java similarity index 96% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/GridLayoutManagerFixed.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/GridLayoutManagerFixed.java index e66fffc86..1a58becd7 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/GridLayoutManagerFixed.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/GridLayoutManagerFixed.java @@ -5,7 +5,7 @@ * * Copyright Nikolai Kudashov, 2013-2018. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; import android.content.Context; import android.graphics.Rect; @@ -47,8 +47,9 @@ public class GridLayoutManagerFixed extends GridLayoutManager { } @Override - protected void recycleViewsFromStart(RecyclerView.Recycler recycler, int dt) { - if (dt < 0) { + protected void recycleViewsFromStart(RecyclerView.Recycler recycler, int scrollingOffset, + int noRecycleSpace) { + if (scrollingOffset < 0) { return; } // ignore padding, ViewGroup may not clip children. @@ -57,8 +58,8 @@ public class GridLayoutManagerFixed extends GridLayoutManager { for (int i = childCount - 1; i >= 0; i--) { View child = getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); - if (child.getBottom() + params.bottomMargin > dt - || child.getTop() + child.getHeight() > dt) { + if (child.getBottom() + params.bottomMargin > scrollingOffset + || child.getTop() + child.getHeight() > scrollingOffset) { // stop here recycleChildren(recycler, childCount - 1, i); return; @@ -67,8 +68,8 @@ public class GridLayoutManagerFixed extends GridLayoutManager { } else { for (int i = 0; i < childCount; i++) { View child = getChildAt(i); - if (mOrientationHelper.getDecoratedEnd(child) > dt - || mOrientationHelper.getTransformedEndWithDecoration(child) > dt) { + if (mOrientationHelper.getDecoratedEnd(child) > scrollingOffset + || mOrientationHelper.getTransformedEndWithDecoration(child) > scrollingOffset) { // stop here recycleChildren(recycler, 0, i); return; @@ -183,7 +184,7 @@ public class GridLayoutManagerFixed extends GridLayoutManager { int maxSize = 0; float maxSizeInOther = 0; - assignSpans(recycler, state, count, consumedSpanCount, layingOutInPrimaryDirection); + assignSpans(recycler, state, count, layingOutInPrimaryDirection); for (int i = 0; i < count; i++) { View view = mSet[i]; if (layoutState.mScrapList == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/helper/ItemTouchHelper.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ItemTouchHelper.java similarity index 92% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/helper/ItemTouchHelper.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/ItemTouchHelper.java index d31952231..3178efe54 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/helper/ItemTouchHelper.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ItemTouchHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget.helper; +package androidx.recyclerview.widget; import android.animation.Animator; import android.animation.ValueAnimator; @@ -22,15 +22,6 @@ import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Rect; import android.os.Build; -import android.support.annotation.Nullable; -import android.support.v4.view.GestureDetectorCompat; -import android.support.v4.view.ViewCompat; - -import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; -import org.telegram.messenger.support.widget.RecyclerView.OnItemTouchListener; -import org.telegram.messenger.support.widget.RecyclerView.ViewHolder; import android.util.Log; import android.view.GestureDetector; import android.view.HapticFeedbackConstants; @@ -41,6 +32,15 @@ import android.view.ViewConfiguration; import android.view.ViewParent; import android.view.animation.Interpolator; +import org.telegram.messenger.AndroidUtilities; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.view.GestureDetectorCompat; +import androidx.core.view.ViewCompat; +import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener; +import androidx.recyclerview.widget.RecyclerView.ViewHolder; + import java.util.ArrayList; import java.util.List; @@ -113,34 +113,39 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration /** * A View is currently being swiped. */ + @SuppressWarnings("WeakerAccess") public static final int ACTION_STATE_SWIPE = 1; /** * A View is currently being dragged. */ + @SuppressWarnings("WeakerAccess") public static final int ACTION_STATE_DRAG = 2; /** * Animation type for views which are swiped successfully. */ + @SuppressWarnings("WeakerAccess") public static final int ANIMATION_TYPE_SWIPE_SUCCESS = 1 << 1; /** * Animation type for views which are not completely swiped thus will animate back to their * original position. */ + @SuppressWarnings("WeakerAccess") public static final int ANIMATION_TYPE_SWIPE_CANCEL = 1 << 2; /** * Animation type for views that were dragged and now will animate to their final position. */ + @SuppressWarnings("WeakerAccess") public static final int ANIMATION_TYPE_DRAG = 1 << 3; - static final String TAG = "ItemTouchHelper"; + private static final String TAG = "ItemTouchHelper"; - static final boolean DEBUG = false; + private static final boolean DEBUG = false; - static final int ACTIVE_POINTER_ID_NONE = -1; + private static final int ACTIVE_POINTER_ID_NONE = -1; static final int DIRECTION_FLAG_COUNT = 8; @@ -160,7 +165,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * This is necessary after swipe dismissing an item. We wait until animator finishes its job * to clean these views. */ - final List mPendingCleanup = new ArrayList(); + final List mPendingCleanup = new ArrayList<>(); /** * Re-use array to calculate dx dy for a ViewHolder @@ -170,6 +175,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration /** * Currently selected view holder */ + @SuppressWarnings("WeakerAccess") /* synthetic access */ ViewHolder mSelected = null; /** @@ -183,12 +189,12 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration /** * Set when ItemTouchHelper is assigned to a RecyclerView. */ - float mSwipeEscapeVelocity; + private float mSwipeEscapeVelocity; /** * Set when ItemTouchHelper is assigned to a RecyclerView. */ - float mMaxSwipeVelocity; + private float mMaxSwipeVelocity; /** * The diff between the last event and initial touch. @@ -202,30 +208,33 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * when action starts so that we can consistently position it even if LayoutManager moves the * View. */ - float mSelectedStartX; + private float mSelectedStartX; - float mSelectedStartY; + private float mSelectedStartY; /** * The pointer we are tracking. */ + @SuppressWarnings("WeakerAccess") /* synthetic access */ int mActivePointerId = ACTIVE_POINTER_ID_NONE; /** * Developer callback which controls the behavior of ItemTouchHelper. */ + @NonNull Callback mCallback; /** * Current mode. */ - int mActionState = ACTION_STATE_IDLE; + private int mActionState = ACTION_STATE_IDLE; /** * The direction flags obtained from unmasking * {@link Callback#getAbsoluteMovementFlags(RecyclerView, ViewHolder)} for the current * action state. */ + @SuppressWarnings("WeakerAccess") /* synthetic access */ int mSelectedFlags; /** @@ -235,7 +244,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * Using framework animators has the side effect of clashing with ItemAnimator, creating * jumpy UIs. */ - List mRecoverAnimations = new ArrayList(); + List mRecoverAnimations = new ArrayList<>(); private int mSlop; @@ -245,6 +254,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * When user drags a view to the edge, we start scrolling the LayoutManager as long as View * is partially out of bounds. */ + @SuppressWarnings("WeakerAccess") /* synthetic access */ final Runnable mScrollRunnable = new Runnable() { @Override public void run() { @@ -279,6 +289,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * until view reaches its final position (end of recover animation), we keep a reference so * that it can be drawn above other children. */ + @SuppressWarnings("WeakerAccess") /* synthetic access */ View mOverdrawChild = null; /** @@ -286,11 +297,13 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * position callback is called. This value is invalidated whenever a child is attached or * detached. */ + @SuppressWarnings("WeakerAccess") /* synthetic access */ int mOverdrawChildPosition = -1; /** * Used to detect long press. */ + @SuppressWarnings("WeakerAccess") /* synthetic access */ GestureDetectorCompat mGestureDetector; /** @@ -300,7 +313,8 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration private final OnItemTouchListener mOnItemTouchListener = new OnItemTouchListener() { @Override - public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent event) { + public boolean onInterceptTouchEvent(@NonNull RecyclerView recyclerView, + @NonNull MotionEvent event) { mGestureDetector.onTouchEvent(event); if (DEBUG) { Log.d(TAG, "intercept: x:" + event.getX() + ",y:" + event.getY() + ", " + event); @@ -345,7 +359,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration } @Override - public void onTouchEvent(RecyclerView recyclerView, MotionEvent event) { + public void onTouchEvent(@NonNull RecyclerView recyclerView, @NonNull MotionEvent event) { mGestureDetector.onTouchEvent(event); if (DEBUG) { Log.d(TAG, @@ -430,7 +444,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * * @param callback The Callback which controls the behavior of this touch helper. */ - public ItemTouchHelper(Callback callback) { + public ItemTouchHelper(@NonNull Callback callback) { mCallback = callback; } @@ -458,7 +472,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration destroyCallbacks(); } mRecyclerView = recyclerView; - if (mRecyclerView != null) { + if (recyclerView != null) { final Resources resources = recyclerView.getResources(); mSwipeEscapeVelocity = AndroidUtilities.dp(120); mMaxSwipeVelocity = AndroidUtilities.dp(800); @@ -551,10 +565,11 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * Starts dragging or swiping the given View. Call with null if you want to clear it. * * @param selected The ViewHolder to drag or swipe. Can be null if you want to cancel the - * current action + * current action, but may not be null if actionState is ACTION_STATE_DRAG. * @param actionState The type of action */ - void select(ViewHolder selected, int actionState) { + @SuppressWarnings("WeakerAccess") /* synthetic access */ + void select(@Nullable ViewHolder selected, int actionState) { if (selected == mSelected && actionState == mActionState) { return; } @@ -564,6 +579,10 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration endRecoverAnimation(selected, true); mActionState = actionState; if (actionState == ACTION_STATE_DRAG) { + if (selected == null) { + throw new IllegalArgumentException("Must pass a ViewHolder when dragging"); + } + // we remove after animation is complete. this means we only elevate the last drag // child but that should perform good enough as it is very hard to start dragging a // new child before the previous one settles. @@ -674,6 +693,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration mRecyclerView.invalidate(); } + @SuppressWarnings("WeakerAccess") /* synthetic access */ void postDispatchSwipe(final RecoverAnimation anim, final int swipeDir) { // wait until animations are complete. mRecyclerView.post(new Runnable() { @@ -697,6 +717,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration }); } + @SuppressWarnings("WeakerAccess") /* synthetic access */ boolean hasRunningRecoverAnim() { final int size = mRecoverAnimations.size(); for (int i = 0; i < size; i++) { @@ -710,6 +731,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration /** * If user drags the view to the edge, trigger a scroll if necessary. */ + @SuppressWarnings("WeakerAccess") /* synthetic access */ boolean scrollIfNecessary() { if (mSelected == null) { mDragScrollStartTimeInMs = Long.MIN_VALUE; @@ -775,8 +797,8 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration private List findSwapTargets(ViewHolder viewHolder) { if (mSwapTargets == null) { - mSwapTargets = new ArrayList(); - mDistances = new ArrayList(); + mSwapTargets = new ArrayList<>(); + mDistances = new ArrayList<>(); } else { mSwapTargets.clear(); mDistances.clear(); @@ -825,6 +847,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration /** * Checks if we should swap w/ another view holder. */ + @SuppressWarnings("WeakerAccess") /* synthetic access */ void moveIfNecessary(ViewHolder viewHolder) { if (mRecyclerView.isLayoutRequested()) { return; @@ -862,11 +885,11 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration } @Override - public void onChildViewAttachedToWindow(View view) { + public void onChildViewAttachedToWindow(@NonNull View view) { } @Override - public void onChildViewDetachedFromWindow(View view) { + public void onChildViewDetachedFromWindow(@NonNull View view) { removeChildDrawingOrderCallbackIfNecessary(view); final ViewHolder holder = mRecyclerView.getChildViewHolder(view); if (holder == null) { @@ -885,7 +908,8 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration /** * Returns the animation type or 0 if cannot be found. */ - int endRecoverAnimation(ViewHolder viewHolder, boolean override) { + @SuppressWarnings("WeakerAccess") /* synthetic access */ + void endRecoverAnimation(ViewHolder viewHolder, boolean override) { final int recoverAnimSize = mRecoverAnimations.size(); for (int i = recoverAnimSize - 1; i >= 0; i--) { final RecoverAnimation anim = mRecoverAnimations.get(i); @@ -895,10 +919,9 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration anim.cancel(); } mRecoverAnimations.remove(i); - return anim.mAnimationType; + return; } } - return 0; } @Override @@ -907,6 +930,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration outRect.setEmpty(); } + @SuppressWarnings("WeakerAccess") /* synthetic access */ void obtainVelocityTracker() { if (mVelocityTracker != null) { mVelocityTracker.recycle(); @@ -950,17 +974,18 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration /** * Checks whether we should select a View for swiping. */ - boolean checkSelectForSwipe(int action, MotionEvent motionEvent, int pointerIndex) { + @SuppressWarnings("WeakerAccess") /* synthetic access */ + void checkSelectForSwipe(int action, MotionEvent motionEvent, int pointerIndex) { if (mSelected != null || action != MotionEvent.ACTION_MOVE || mActionState == ACTION_STATE_DRAG || !mCallback.isItemViewSwipeEnabled()) { - return false; + return; } if (mRecyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING) { - return false; + return; } final ViewHolder vh = findSwipedView(motionEvent); if (vh == null) { - return false; + return; } final int movementFlags = mCallback.getAbsoluteMovementFlags(mRecyclerView, vh); @@ -968,7 +993,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration >> (DIRECTION_FLAG_COUNT * ACTION_STATE_SWIPE); if (swipeFlags == 0) { - return false; + return; } // mDx and mDy are only set in allowed directions. We use custom x/y here instead of @@ -985,29 +1010,29 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration final float absDy = Math.abs(dy); if (absDx < mSlop && absDy < mSlop) { - return false; + return; } if (absDx > absDy) { if (dx < 0 && (swipeFlags & LEFT) == 0) { - return false; + return; } if (dx > 0 && (swipeFlags & RIGHT) == 0) { - return false; + return; } } else { if (dy < 0 && (swipeFlags & UP) == 0) { - return false; + return; } if (dy > 0 && (swipeFlags & DOWN) == 0) { - return false; + return; } } mDx = mDy = 0f; mActivePointerId = motionEvent.getPointerId(0); select(vh, ACTION_STATE_SWIPE); - return true; } + @SuppressWarnings("WeakerAccess") /* synthetic access */ View findChildView(MotionEvent event) { // first check elevated views, if none, then call RV final float x = event.getX(); @@ -1062,7 +1087,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * RecyclerView. * @see ItemTouchHelper.Callback#isItemViewSwipeEnabled() */ - public void startDrag(ViewHolder viewHolder) { + public void startDrag(@NonNull ViewHolder viewHolder) { if (!mCallback.hasDragFlag(mRecyclerView, viewHolder)) { Log.e(TAG, "Start drag has been called but dragging is not enabled"); return; @@ -1109,7 +1134,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * @param viewHolder The ViewHolder to start swiping. It must be a direct child of * RecyclerView. */ - public void startSwipe(ViewHolder viewHolder) { + public void startSwipe(@NonNull ViewHolder viewHolder) { if (!mCallback.hasSwipeFlag(mRecyclerView, viewHolder)) { Log.e(TAG, "Start swipe has been called but swiping is not enabled"); return; @@ -1124,6 +1149,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration select(viewHolder, ACTION_STATE_SWIPE); } + @SuppressWarnings("WeakerAccess") /* synthetic access */ RecoverAnimation findAnimation(MotionEvent event) { if (mRecoverAnimations.isEmpty()) { return null; @@ -1138,6 +1164,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration return null; } + @SuppressWarnings("WeakerAccess") /* synthetic access */ void updateDxDy(MotionEvent ev, int directionFlags, int pointerIndex) { final float x = ev.getX(pointerIndex); final float y = ev.getY(pointerIndex); @@ -1205,7 +1232,11 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration return 0; } - private int checkHorizontalSwipe(ViewHolder viewHolder, int flags) { + public boolean isIdle() { + return mActionState == ACTION_STATE_IDLE; + } + + public int checkHorizontalSwipe(ViewHolder viewHolder, int flags) { if ((flags & (LEFT | RIGHT)) != 0) { final int dirFlag = mDx > 0 ? RIGHT : LEFT; if (mVelocityTracker != null && mActivePointerId > -1) { @@ -1284,6 +1315,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration mRecyclerView.setChildDrawingOrderCallback(mChildDrawingOrderCallback); } + @SuppressWarnings("WeakerAccess") /* synthetic access */ void removeChildDrawingOrderCallbackIfNecessary(View view) { if (view == mOverdrawChild) { mOverdrawChild = null; @@ -1311,15 +1343,15 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * making layout stay consistent. * * @param view The View which is being dragged. It is very likely that user is still - * dragging this View so there might be other - * {@link #prepareForDrop(View, View, int, int)} after this one. + * dragging this View so there might be other calls to + * {@code prepareForDrop()} after this one. * @param target The target view which is being dropped on. * @param x The left offset of the View that is being dragged. This value * includes the movement caused by the user. * @param y The top offset of the View that is being dragged. This value * includes the movement caused by the user. */ - void prepareForDrop(View view, View target, int x, int y); + void prepareForDrop(@NonNull View view, @NonNull View target, int x, int y); } /** @@ -1355,16 +1387,16 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration @SuppressWarnings("UnusedParameters") public abstract static class Callback { + @SuppressWarnings("WeakerAccess") public static final int DEFAULT_DRAG_ANIMATION_DURATION = 200; + @SuppressWarnings("WeakerAccess") public static final int DEFAULT_SWIPE_ANIMATION_DURATION = 250; static final int RELATIVE_DIR_FLAGS = START | END | ((START | END) << DIRECTION_FLAG_COUNT) | ((START | END) << (2 * DIRECTION_FLAG_COUNT)); - private static final ItemTouchUIUtil sUICallback; - private static final int ABS_HORIZONTAL_DIR_FLAGS = LEFT | RIGHT | ((LEFT | RIGHT) << DIRECTION_FLAG_COUNT) | ((LEFT | RIGHT) << (2 * DIRECTION_FLAG_COUNT)); @@ -1391,14 +1423,6 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration private int mCachedMaxScrollSpeed = -1; - static { - if (Build.VERSION.SDK_INT >= 21) { - sUICallback = new ItemTouchUIUtilImpl.Api21Impl(); - } else { - sUICallback = new ItemTouchUIUtilImpl.BaseImpl(); - } - } - /** * Returns the {@link ItemTouchUIUtil} that is used by the {@link Callback} class for * visual @@ -1439,8 +1463,10 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * * @return The {@link ItemTouchUIUtil} instance that is used by the {@link Callback} */ + @SuppressWarnings("WeakerAccess") + @NonNull public static ItemTouchUIUtil getDefaultUIUtil() { - return sUICallback; + return ItemTouchUIUtilImpl.INSTANCE; } /** @@ -1454,6 +1480,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * of {@link #LEFT}, {@link #RIGHT}. * @see #convertToAbsoluteDirection(int, int) */ + @SuppressWarnings("WeakerAccess") public static int convertToRelativeDirection(int flags, int layoutDirection) { int masked = flags & ABS_HORIZONTAL_DIR_FLAGS; if (masked == 0) { @@ -1500,6 +1527,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * {@link #RIGHT}, {@link #LEFT} {@link #START} and {@link #END}. * @return And integer that represents the given directions in the provided actionState. */ + @SuppressWarnings("WeakerAccess") public static int makeFlag(int actionState, int directions) { return directions << (actionState * DIRECTION_FLAG_COUNT); } @@ -1531,8 +1559,8 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * @see #makeMovementFlags(int, int) * @see #makeFlag(int, int) */ - public abstract int getMovementFlags(RecyclerView recyclerView, - ViewHolder viewHolder); + public abstract int getMovementFlags(@NonNull RecyclerView recyclerView, + @NonNull ViewHolder viewHolder); /** * Converts a given set of flags to absolution direction which means {@link #START} and @@ -1543,6 +1571,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * @param layoutDirection The layout direction of the RecyclerView. * @return Updated flags which includes only absolute direction values. */ + @SuppressWarnings("WeakerAccess") public int convertToAbsoluteDirection(int flags, int layoutDirection) { int masked = flags & RELATIVE_DIR_FLAGS; if (masked == 0) { @@ -1594,8 +1623,9 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * @return True if the dragged ViewHolder can be replaced with the target ViewHolder, false * otherwise. */ - public boolean canDropOver(RecyclerView recyclerView, ViewHolder current, - ViewHolder target) { + @SuppressWarnings("WeakerAccess") + public boolean canDropOver(@NonNull RecyclerView recyclerView, @NonNull ViewHolder current, + @NonNull ViewHolder target) { return true; } @@ -1618,8 +1648,8 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * {@code target}. * @see #onMoved(RecyclerView, ViewHolder, int, ViewHolder, int, int, int) */ - public abstract boolean onMove(RecyclerView recyclerView, - ViewHolder viewHolder, ViewHolder target); + public abstract boolean onMove(@NonNull RecyclerView recyclerView, + @NonNull ViewHolder viewHolder, @NonNull ViewHolder target); /** * Returns whether ItemTouchHelper should start a drag and drop operation if an item is @@ -1658,6 +1688,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * * @return The extra margin to be added to the hit box of the dragged View. */ + @SuppressWarnings("WeakerAccess") public int getBoundingBoxMargin() { return 0; } @@ -1673,7 +1704,8 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * @return A float value that denotes the fraction of the View size. Default value * is .5f . */ - public float getSwipeThreshold(ViewHolder viewHolder) { + @SuppressWarnings("WeakerAccess") + public float getSwipeThreshold(@NonNull ViewHolder viewHolder) { return .5f; } @@ -1686,7 +1718,8 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * @return A float value that denotes the fraction of the View size. Default value is * .5f . */ - public float getMoveThreshold(ViewHolder viewHolder) { + @SuppressWarnings("WeakerAccess") + public float getMoveThreshold(@NonNull ViewHolder viewHolder) { return .5f; } @@ -1711,6 +1744,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * @see #getSwipeVelocityThreshold(float) * @see #getSwipeThreshold(ViewHolder) */ + @SuppressWarnings("WeakerAccess") public float getSwipeEscapeVelocity(float defaultValue) { return defaultValue; } @@ -1734,6 +1768,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * defaultValue parameter. * @see #getSwipeEscapeVelocity(float) */ + @SuppressWarnings("WeakerAccess") public float getSwipeVelocityThreshold(float defaultValue) { return defaultValue; } @@ -1764,8 +1799,9 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * @return A ViewHolder to whose position the dragged ViewHolder should be * moved to. */ - public ViewHolder chooseDropTarget(ViewHolder selected, - List dropTargets, int curX, int curY) { + @SuppressWarnings("WeakerAccess") + public ViewHolder chooseDropTarget(@NonNull ViewHolder selected, + @NonNull List dropTargets, int curX, int curY) { int right = curX + selected.itemView.getWidth(); int bottom = curY + selected.itemView.getHeight(); ViewHolder winner = null; @@ -1844,7 +1880,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * `direction` will be relative as well. ({@link #START} or {@link * #END}). */ - public abstract void onSwiped(ViewHolder viewHolder, int direction); + public abstract void onSwiped(@NonNull ViewHolder viewHolder, int direction); /** * Called when the ViewHolder swiped or dragged by the ItemTouchHelper is changed. @@ -1858,9 +1894,9 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * {@link ItemTouchHelper#ACTION_STATE_DRAG}. * @see #clearView(RecyclerView, RecyclerView.ViewHolder) */ - public void onSelectedChanged(ViewHolder viewHolder, int actionState) { + public void onSelectedChanged(@Nullable ViewHolder viewHolder, int actionState) { if (viewHolder != null) { - sUICallback.onSelected(viewHolder.itemView); + ItemTouchUIUtilImpl.INSTANCE.onSelected(viewHolder.itemView); } } @@ -1904,9 +1940,9 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * are applied. This value does not include margins added by * {@link RecyclerView.ItemDecoration}s. */ - public void onMoved(final RecyclerView recyclerView, - final ViewHolder viewHolder, int fromPos, final ViewHolder target, int toPos, int x, - int y) { + public void onMoved(@NonNull final RecyclerView recyclerView, + @NonNull final ViewHolder viewHolder, int fromPos, @NonNull final ViewHolder target, + int toPos, int x, int y) { final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if (layoutManager instanceof ViewDropHandler) { ((ViewDropHandler) layoutManager).prepareForDrop(viewHolder.itemView, @@ -2000,8 +2036,8 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * @param recyclerView The RecyclerView which is controlled by the ItemTouchHelper. * @param viewHolder The View that was interacted by the user. */ - public void clearView(RecyclerView recyclerView, ViewHolder viewHolder) { - sUICallback.clearView(viewHolder.itemView); + public void clearView(@NonNull RecyclerView recyclerView, @NonNull ViewHolder viewHolder) { + ItemTouchUIUtilImpl.INSTANCE.clearView(viewHolder.itemView); } /** @@ -2031,11 +2067,11 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * @see #onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int, * boolean) */ - public void onChildDraw(Canvas c, RecyclerView recyclerView, - ViewHolder viewHolder, + public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, + @NonNull ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { - sUICallback.onDraw(c, recyclerView, viewHolder.itemView, dX, dY, actionState, - isCurrentlyActive); + ItemTouchUIUtilImpl.INSTANCE.onDraw(c, recyclerView, viewHolder.itemView, dX, dY, + actionState, isCurrentlyActive); } /** @@ -2065,11 +2101,11 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * @see #onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int, * boolean) */ - public void onChildDrawOver(Canvas c, RecyclerView recyclerView, + public void onChildDrawOver(@NonNull Canvas c, @NonNull RecyclerView recyclerView, ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { - sUICallback.onDrawOver(c, recyclerView, viewHolder.itemView, dX, dY, actionState, - isCurrentlyActive); + ItemTouchUIUtilImpl.INSTANCE.onDrawOver(c, recyclerView, viewHolder.itemView, dX, dY, + actionState, isCurrentlyActive); } /** @@ -2092,7 +2128,8 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * @param animateDy The vertical distance that the animation will offset * @return The duration for the animation */ - public long getAnimationDuration(RecyclerView recyclerView, int animationType, + @SuppressWarnings("WeakerAccess") + public long getAnimationDuration(@NonNull RecyclerView recyclerView, int animationType, float animateDx, float animateDy) { final RecyclerView.ItemAnimator itemAnimator = recyclerView.getItemAnimator(); if (itemAnimator == null) { @@ -2124,7 +2161,8 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * @return The amount that RecyclerView should scroll. Keep in mind that this value will * be passed to {@link RecyclerView#scrollBy(int, int)} method. */ - public int interpolateOutOfBoundsScroll(RecyclerView recyclerView, + @SuppressWarnings("WeakerAccess") + public int interpolateOutOfBoundsScroll(@NonNull RecyclerView recyclerView, int viewSize, int viewSizeOutOfBounds, int totalSize, long msSinceStartScroll) { final int maxScroll = getMaxDragScroll(recyclerView); @@ -2159,7 +2197,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * ItemTouchHelper mIth = new ItemTouchHelper( * new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, * ItemTouchHelper.LEFT) { - * public abstract boolean onMove(RecyclerView recyclerView, + * public boolean onMove(RecyclerView recyclerView, * ViewHolder viewHolder, ViewHolder target) { * final int fromPos = viewHolder.getAdapterPosition(); * final int toPos = target.getAdapterPosition(); @@ -2205,7 +2243,8 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * * @param defaultSwipeDirs Binary OR of directions in which the ViewHolders can be swiped. */ - public void setDefaultSwipeDirs(int defaultSwipeDirs) { + @SuppressWarnings({"WeakerAccess", "unused"}) + public void setDefaultSwipeDirs(@SuppressWarnings("unused") int defaultSwipeDirs) { mDefaultSwipeDirs = defaultSwipeDirs; } @@ -2215,7 +2254,8 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * * @param defaultDragDirs Binary OR of directions in which the ViewHolders can be dragged. */ - public void setDefaultDragDirs(int defaultDragDirs) { + @SuppressWarnings({"WeakerAccess", "unused"}) + public void setDefaultDragDirs(@SuppressWarnings("unused") int defaultDragDirs) { mDefaultDragDirs = defaultDragDirs; } @@ -2225,10 +2265,12 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * {@link #setDefaultSwipeDirs(int)}. * * @param recyclerView The RecyclerView to which the ItemTouchHelper is attached to. - * @param viewHolder The RecyclerView for which the swipe direction is queried. + * @param viewHolder The ViewHolder for which the swipe direction is queried. * @return A binary OR of direction flags. */ - public int getSwipeDirs(RecyclerView recyclerView, ViewHolder viewHolder) { + @SuppressWarnings("WeakerAccess") + public int getSwipeDirs(@SuppressWarnings("unused") @NonNull RecyclerView recyclerView, + @NonNull @SuppressWarnings("unused") ViewHolder viewHolder) { return mDefaultSwipeDirs; } @@ -2238,15 +2280,18 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration * {@link #setDefaultDragDirs(int)}. * * @param recyclerView The RecyclerView to which the ItemTouchHelper is attached to. - * @param viewHolder The RecyclerView for which the swipe direction is queried. + * @param viewHolder The ViewHolder for which the swipe direction is queried. * @return A binary OR of direction flags. */ - public int getDragDirs(RecyclerView recyclerView, ViewHolder viewHolder) { + @SuppressWarnings("WeakerAccess") + public int getDragDirs(@SuppressWarnings("unused") @NonNull RecyclerView recyclerView, + @SuppressWarnings("unused") @NonNull ViewHolder viewHolder) { return mDefaultDragDirs; } @Override - public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) { + public int getMovementFlags(@NonNull RecyclerView recyclerView, + @NonNull ViewHolder viewHolder) { return makeMovementFlags(getDragDirs(recyclerView, viewHolder), getSwipeDirs(recyclerView, viewHolder)); } @@ -2340,7 +2385,7 @@ public class ItemTouchHelper extends RecyclerView.ItemDecoration final int mAnimationType; - public boolean mIsPendingCleanup; + boolean mIsPendingCleanup; float mX; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/helper/ItemTouchUIUtil.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ItemTouchUIUtil.java similarity index 93% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/helper/ItemTouchUIUtil.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/ItemTouchUIUtil.java index eeb69da1a..788ceb053 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/helper/ItemTouchUIUtil.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ItemTouchUIUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,9 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget.helper; +package androidx.recyclerview.widget; import android.graphics.Canvas; -import org.telegram.messenger.support.widget.RecyclerView; import android.view.View; /** diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/ItemTouchUIUtilImpl.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ItemTouchUIUtilImpl.java new file mode 100644 index 000000000..fb7ef010c --- /dev/null +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ItemTouchUIUtilImpl.java @@ -0,0 +1,89 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.recyclerview.widget; + +import android.graphics.Canvas; +import android.os.Build; +import android.view.View; + +import androidx.core.view.ViewCompat; + +/** + * Package private class to keep implementations. Putting them inside ItemTouchUIUtil makes them + * public API, which is not desired in this case. + */ +class ItemTouchUIUtilImpl implements ItemTouchUIUtil { + static final ItemTouchUIUtil INSTANCE = new ItemTouchUIUtilImpl(); + + @Override + public void onDraw(Canvas c, RecyclerView recyclerView, View view, float dX, float dY, + int actionState, boolean isCurrentlyActive) { + if (Build.VERSION.SDK_INT >= 21) { + if (isCurrentlyActive) { + Object originalElevation = view.getTag(); + if (originalElevation == null) { + originalElevation = ViewCompat.getElevation(view); + float newElevation = 1f + findMaxElevation(recyclerView, view); + ViewCompat.setElevation(view, newElevation); + view.setTag(originalElevation); + } + } + } + + view.setTranslationX(dX); + view.setTranslationY(dY); + } + + private static float findMaxElevation(RecyclerView recyclerView, View itemView) { + final int childCount = recyclerView.getChildCount(); + float max = 0; + for (int i = 0; i < childCount; i++) { + final View child = recyclerView.getChildAt(i); + if (child == itemView) { + continue; + } + final float elevation = ViewCompat.getElevation(child); + if (elevation > max) { + max = elevation; + } + } + return max; + } + + @Override + public void onDrawOver(Canvas c, RecyclerView recyclerView, View view, float dX, float dY, + int actionState, boolean isCurrentlyActive) { + } + + @Override + public void clearView(View view) { + if (Build.VERSION.SDK_INT >= 21) { + final Object tag = view.getTag(); + if (tag instanceof Float) { + ViewCompat.setElevation(view, (Float) tag); + } + view.setTag(null); + } + + view.setTranslationX(0f); + view.setTranslationY(0f); + } + + @Override + public void onSelected(View view) { + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LayoutState.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LayoutState.java similarity index 95% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LayoutState.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/LayoutState.java index d0b905b65..8805c1cc9 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LayoutState.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LayoutState.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; import android.view.View; @@ -24,8 +24,6 @@ import android.view.View; */ class LayoutState { - static final String TAG = "LayoutState"; - static final int LAYOUT_START = -1; static final int LAYOUT_END = 1; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LinearLayoutManager.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java similarity index 89% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LinearLayoutManager.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java index a1082465d..57ee7b380 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LinearLayoutManager.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,31 +14,30 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; -import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; -import static org.telegram.messenger.support.widget.RecyclerView.NO_POSITION; -import static org.telegram.messenger.support.widget.RecyclerView.VERBOSE_TRACING; +import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.PointF; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.RestrictTo; -import android.support.v4.os.TraceCompat; -import android.support.v4.view.ViewCompat; -import org.telegram.messenger.support.widget.RecyclerView.LayoutParams; -import org.telegram.messenger.support.widget.helper.ItemTouchHelper; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; +import androidx.annotation.NonNull; +import androidx.annotation.RestrictTo; +import androidx.core.os.TraceCompat; +import androidx.core.view.ViewCompat; + import java.util.List; /** - * A {@link android.support.v7.widget.RecyclerView.LayoutManager} implementation which provides + * A {@link RecyclerView.LayoutManager} implementation which provides * similar functionality to {@link android.widget.ListView}. */ public class LinearLayoutManager extends RecyclerView.LayoutManager implements @@ -118,7 +117,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements * When LayoutManager needs to scroll to a position, it sets this variable and requests a * layout which will check this variable and re-layout accordingly. */ - int mPendingScrollPosition = NO_POSITION; + int mPendingScrollPosition = RecyclerView.NO_POSITION; boolean mPendingScrollPositionBottom = true; @@ -148,6 +147,11 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements */ private int mInitialPrefetchItemCount = 2; + // Reusable int array to be passed to method calls that mutate it in order to "return" two ints. + // This should only be used used transiently and should not be used to retain any state over + // time. + private int[] mReusableIntPair = new int[2]; + /** * Creates a vertical LinearLayoutManager * @@ -178,8 +182,8 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements * {@inheritDoc} */ @Override - public LayoutParams generateDefaultLayoutParams() { - return new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + public RecyclerView.LayoutParams generateDefaultLayoutParams() { + return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); } @@ -313,7 +317,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements } /** - * Sets the orientation of the layout. {@link android.support.v7.widget.LinearLayoutManager} + * Sets the orientation of the layout. {@link LinearLayoutManager} * will do its best to keep scroll position. * * @param orientation {@link #HORIZONTAL} or {@link #VERTICAL} @@ -364,8 +368,8 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements * laid out at the end of the UI, second item is laid out before it etc. * * For horizontal layouts, it depends on the layout direction. - * When set to true, If {@link android.support.v7.widget.RecyclerView} is LTR, than it will - * layout from RTL, if {@link android.support.v7.widget.RecyclerView}} is RTL, it will layout + * When set to true, If {@link RecyclerView} is LTR, than it will + * layout from RTL, if {@link RecyclerView}} is RTL, it will layout * from LTR. * * If you are looking for the exact same behavior of @@ -405,7 +409,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements /** *

    Returns the amount of extra space that should be laid out by LayoutManager.

    * - *

    By default, {@link android.support.v7.widget.LinearLayoutManager} lays out 1 extra page + *

    By default, {@link LinearLayoutManager} lays out 1 extra page * of items while smooth scrolling and 0 otherwise. You can override this method to implement * your custom layout pre-cache logic.

    * @@ -421,7 +425,10 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements * enough to handle it.

    * * @return The extra space that should be laid out (in pixels). + * @deprecated Use {@link #calculateExtraLayoutSpace(RecyclerView.State, int[])} instead. */ + @SuppressWarnings("DeprecatedIsStillUsed") + @Deprecated protected int getExtraLayoutSpace(RecyclerView.State state) { if (state.hasTargetScrollPosition()) { return mOrientationHelper.getTotalSpace(); @@ -430,6 +437,51 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements } } + /** + *

    Calculates the amount of extra space (in pixels) that should be laid out by {@link + * LinearLayoutManager} and stores the result in {@code extraLayoutSpace}. {@code + * extraLayoutSpace[0]} should be used for the extra space at the top/left, and {@code + * extraLayoutSpace[1]} should be used for the extra space at the bottom/right (depending on the + * orientation). Thus, the side where it is applied is unaffected by {@link + * #getLayoutDirection()} (LTR vs RTL), {@link #getStackFromEnd()} and {@link + * #getReverseLayout()}. Negative values are ignored.

    + * + *

    By default, {@code LinearLayoutManager} lays out 1 extra page of items while smooth + * scrolling, in the direction of the scroll, and no extra space is laid out in all other + * situations. You can override this method to implement your own custom pre-cache logic. Use + * {@link RecyclerView.State#hasTargetScrollPosition()} to find out if a smooth scroll to a + * position is in progress, and {@link RecyclerView.State#getTargetScrollPosition()} to find out + * which item it is scrolling to.

    + * + *

    Note:Laying out extra items generally comes with significant performance + * cost. It's typically only desirable in places like smooth scrolling to an unknown location, + * where 1) the extra content helps LinearLayoutManager know in advance when its target is + * approaching, so it can decelerate early and smoothly and 2) while motion is continuous.

    + * + *

    Extending the extra layout space is especially expensive if done while the user may change + * scrolling direction. In the default implementation, changing direction will cause the extra + * layout space to swap to the opposite side of the viewport, incurring many rebinds/recycles, + * unless the cache is large enough to handle it.

    + */ + protected void calculateExtraLayoutSpace(@NonNull RecyclerView.State state, + @NonNull int[] extraLayoutSpace) { + int extraLayoutSpaceStart = 0; + int extraLayoutSpaceEnd = 0; + + // If calculateExtraLayoutSpace is not overridden, call the + // deprecated getExtraLayoutSpace for backwards compatibility + @SuppressWarnings("deprecation") + int extraScrollSpace = getExtraLayoutSpace(state); + if (mLayoutState.mLayoutDirection == LayoutState.LAYOUT_START) { + extraLayoutSpaceStart = extraScrollSpace; + } else { + extraLayoutSpaceEnd = extraScrollSpace; + } + + extraLayoutSpace[0] = extraLayoutSpaceStart; + extraLayoutSpace[1] = extraLayoutSpaceEnd; + } + @Override public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { @@ -468,7 +520,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements if (DEBUG) { Log.d(TAG, "is pre layout:" + state.isPreLayout()); } - if (mPendingSavedState != null || mPendingScrollPosition != NO_POSITION) { + if (mPendingSavedState != null || mPendingScrollPosition != RecyclerView.NO_POSITION) { if (state.getItemCount() == 0) { removeAndRecycleAllViews(recycler); return; @@ -484,7 +536,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements resolveShouldLayoutReverse(); final View focused = getFocusedChild(); - if (!mAnchorInfo.mValid || mPendingScrollPosition != NO_POSITION + if (!mAnchorInfo.mValid || mPendingScrollPosition != RecyclerView.NO_POSITION || mPendingSavedState != null) { mAnchorInfo.reset(); mAnchorInfo.mLayoutFromEnd = mShouldReverseLayout ^ mStackFromEnd; @@ -514,21 +566,17 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements // LLM may decide to layout items for "extra" pixels to account for scrolling target, // caching or predictive animations. - int extraForStart; - int extraForEnd; - final int extra = getExtraLayoutSpace(state); - // If the previous scroll delta was less than zero, the extra space should be laid out - // at the start. Otherwise, it should be at the end. - if (mLayoutState.mLastScrollDelta >= 0) { - extraForEnd = extra; - extraForStart = 0; - } else { - extraForStart = extra; - extraForEnd = 0; - } - extraForStart += mOrientationHelper.getStartAfterPadding(); - extraForEnd += mOrientationHelper.getEndPadding(); - if (state.isPreLayout() && mPendingScrollPosition != NO_POSITION + + mLayoutState.mLayoutDirection = mLayoutState.mLastScrollDelta >= 0 + ? LayoutState.LAYOUT_END : LayoutState.LAYOUT_START; + mReusableIntPair[0] = 0; + mReusableIntPair[1] = 0; + calculateExtraLayoutSpace(state, mReusableIntPair); + int extraForStart = Math.max(0, mReusableIntPair[0]) + + mOrientationHelper.getStartAfterPadding(); + int extraForEnd = Math.max(0, mReusableIntPair[1]) + + mOrientationHelper.getEndPadding(); + if (state.isPreLayout() && mPendingScrollPosition != RecyclerView.NO_POSITION && mPendingScrollPositionOffset != INVALID_OFFSET) { // if the child is visible and we are going to move it around, we should layout // extra items in the opposite direction to make sure new items animate nicely @@ -568,10 +616,13 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements detachAndScrapAttachedViews(recycler); mLayoutState.mInfinite = resolveIsInfinite(); mLayoutState.mIsPreLayout = state.isPreLayout(); + // noRecycleSpace not needed: recycling doesn't happen in below's fill + // invocations because mScrollingOffset is set to SCROLLING_OFFSET_NaN + mLayoutState.mNoRecycleSpace = 0; if (mAnchorInfo.mLayoutFromEnd) { // fill towards start updateLayoutStateToFillStart(mAnchorInfo); - mLayoutState.mExtra = extraForStart; + mLayoutState.mExtraFillSpace = extraForStart; fill(recycler, mLayoutState, state, false); startOffset = mLayoutState.mOffset; final int firstElement = mLayoutState.mCurrentPosition; @@ -580,7 +631,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements } // fill towards end updateLayoutStateToFillEnd(mAnchorInfo); - mLayoutState.mExtra = extraForEnd; + mLayoutState.mExtraFillSpace = extraForEnd; mLayoutState.mCurrentPosition += mLayoutState.mItemDirection; fill(recycler, mLayoutState, state, false); endOffset = mLayoutState.mOffset; @@ -589,14 +640,14 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements // end could not consume all. add more items towards start extraForStart = mLayoutState.mAvailable; updateLayoutStateToFillStart(firstElement, startOffset); - mLayoutState.mExtra = extraForStart; + mLayoutState.mExtraFillSpace = extraForStart; fill(recycler, mLayoutState, state, false); startOffset = mLayoutState.mOffset; } } else { // fill towards end updateLayoutStateToFillEnd(mAnchorInfo); - mLayoutState.mExtra = extraForEnd; + mLayoutState.mExtraFillSpace = extraForEnd; fill(recycler, mLayoutState, state, false); endOffset = mLayoutState.mOffset; final int lastElement = mLayoutState.mCurrentPosition; @@ -605,7 +656,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements } // fill towards start updateLayoutStateToFillStart(mAnchorInfo); - mLayoutState.mExtra = extraForStart; + mLayoutState.mExtraFillSpace = extraForStart; mLayoutState.mCurrentPosition += mLayoutState.mItemDirection; fill(recycler, mLayoutState, state, false); startOffset = mLayoutState.mOffset; @@ -614,7 +665,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements extraForEnd = mLayoutState.mAvailable; // start could not consume all it should. add more items towards end updateLayoutStateToFillEnd(lastElement, endOffset); - mLayoutState.mExtra = extraForEnd; + mLayoutState.mExtraFillSpace = extraForEnd; fill(recycler, mLayoutState, state, false); endOffset = mLayoutState.mOffset; } @@ -659,7 +710,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements public void onLayoutCompleted(RecyclerView.State state) { super.onLayoutCompleted(state); mPendingSavedState = null; // we don't need this anymore - mPendingScrollPosition = NO_POSITION; + mPendingScrollPosition = RecyclerView.NO_POSITION; mPendingScrollPositionOffset = INVALID_OFFSET; mAnchorInfo.reset(); } @@ -719,7 +770,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements if (scrapExtraStart > 0) { View anchor = getChildClosestToStart(); updateLayoutStateToFillStart(getPosition(anchor), startOffset); - mLayoutState.mExtra = scrapExtraStart; + mLayoutState.mExtraFillSpace = scrapExtraStart; mLayoutState.mAvailable = 0; mLayoutState.assignPositionFromScrapList(); fill(recycler, mLayoutState, state, false); @@ -728,7 +779,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements if (scrapExtraEnd > 0) { View anchor = getChildClosestToEnd(); updateLayoutStateToFillEnd(getPosition(anchor), endOffset); - mLayoutState.mExtra = scrapExtraEnd; + mLayoutState.mExtraFillSpace = scrapExtraEnd; mLayoutState.mAvailable = 0; mLayoutState.assignPositionFromScrapList(); fill(recycler, mLayoutState, state, false); @@ -807,12 +858,12 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements * data and returns true */ private boolean updateAnchorFromPendingData(RecyclerView.State state, AnchorInfo anchorInfo) { - if (state.isPreLayout() || mPendingScrollPosition == NO_POSITION) { + if (state.isPreLayout() || mPendingScrollPosition == RecyclerView.NO_POSITION) { return false; } // validate scroll position if (mPendingScrollPosition < 0 || mPendingScrollPosition >= state.getItemCount()) { - mPendingScrollPosition = NO_POSITION; + mPendingScrollPosition = RecyclerView.NO_POSITION; mPendingScrollPositionOffset = INVALID_OFFSET; if (DEBUG) { Log.e(TAG, "ignoring invalid scroll position " + mPendingScrollPosition); @@ -1043,6 +1094,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements requestLayout(); } + /** * {@inheritDoc} */ @@ -1166,11 +1218,18 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements boolean canUseExistingSpace, RecyclerView.State state) { // If parent provides a hint, don't measure unlimited. mLayoutState.mInfinite = resolveIsInfinite(); - mLayoutState.mExtra = getExtraLayoutSpace(state); mLayoutState.mLayoutDirection = layoutDirection; + mReusableIntPair[0] = 0; + mReusableIntPair[1] = 0; + calculateExtraLayoutSpace(state, mReusableIntPair); + int extraForStart = Math.max(0, mReusableIntPair[0]); + int extraForEnd = Math.max(0, mReusableIntPair[1]); + boolean layoutToEnd = layoutDirection == LayoutState.LAYOUT_END; + mLayoutState.mExtraFillSpace = layoutToEnd ? extraForEnd : extraForStart; + mLayoutState.mNoRecycleSpace = layoutToEnd ? extraForStart : extraForEnd; int scrollingOffset; - if (layoutDirection == LayoutState.LAYOUT_END) { - mLayoutState.mExtra += mOrientationHelper.getEndPadding(); + if (layoutToEnd) { + mLayoutState.mExtraFillSpace += mOrientationHelper.getEndPadding(); // get the first child in the direction we are going final View child = getChildClosestToEnd(); // the direction in which we are traversing children @@ -1184,7 +1243,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements } else { final View child = getChildClosestToStart(); - mLayoutState.mExtra += mOrientationHelper.getStartAfterPadding(); + mLayoutState.mExtraFillSpace += mOrientationHelper.getStartAfterPadding(); mLayoutState.mItemDirection = mShouldReverseLayout ? LayoutState.ITEM_DIRECTION_TAIL : LayoutState.ITEM_DIRECTION_HEAD; mLayoutState.mCurrentPosition = getPosition(child) + mLayoutState.mItemDirection; @@ -1224,7 +1283,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements } else { resolveShouldLayoutReverse(); fromEnd = mShouldReverseLayout; - if (mPendingScrollPosition == NO_POSITION) { + if (mPendingScrollPosition == RecyclerView.NO_POSITION) { anchorPos = fromEnd ? adapterItemCount - 1 : 0; } else { anchorPos = mPendingScrollPosition; @@ -1305,20 +1364,20 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements ensureLayoutState(); final int layoutDirection = delta > 0 ? LayoutState.LAYOUT_END : LayoutState.LAYOUT_START; - final int absDy = Math.abs(delta); - updateLayoutState(layoutDirection, absDy, true, state); + final int absDelta = Math.abs(delta); + updateLayoutState(layoutDirection, absDelta, true, state); collectPrefetchPositionsForLayoutState(state, mLayoutState, layoutPrefetchRegistry); } - int scrollBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) { - if (getChildCount() == 0 || dy == 0) { + int scrollBy(int delta, RecyclerView.Recycler recycler, RecyclerView.State state) { + if (getChildCount() == 0 || delta == 0) { return 0; } - mLayoutState.mRecycle = true; ensureLayoutState(); - final int layoutDirection = dy > 0 ? LayoutState.LAYOUT_END : LayoutState.LAYOUT_START; - final int absDy = Math.abs(dy); - updateLayoutState(layoutDirection, absDy, true, state); + mLayoutState.mRecycle = true; + final int layoutDirection = delta > 0 ? LayoutState.LAYOUT_END : LayoutState.LAYOUT_START; + final int absDelta = Math.abs(delta); + updateLayoutState(layoutDirection, absDelta, true, state); final int consumed = mLayoutState.mScrollingOffset + fill(recycler, mLayoutState, state, false); if (consumed < 0) { @@ -1327,10 +1386,10 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements } return 0; } - final int scrolled = absDy > consumed ? layoutDirection * consumed : dy; + final int scrolled = absDelta > consumed ? layoutDirection * consumed : delta; mOrientationHelper.offsetChildren(-scrolled); if (DEBUG) { - Log.d(TAG, "scroll req: " + dy + " scrolled: " + scrolled); + Log.d(TAG, "scroll req: " + delta + " scrolled: " + scrolled); } mLayoutState.mLastScrollDelta = scrolled; return scrolled; @@ -1372,13 +1431,17 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements *

    * Checks both layout position and visible position to guarantee that the view is not visible. * - * @param recycler Recycler instance of {@link android.support.v7.widget.RecyclerView} - * @param dt This can be used to add additional padding to the visible area. This is used - * to detect children that will go out of bounds after scrolling, without - * actually moving them. + * @param recycler Recycler instance of {@link RecyclerView} + * @param scrollingOffset This can be used to add additional padding to the visible area. This + * is used to detect children that will go out of bounds after scrolling, + * without actually moving them. + * @param noRecycleSpace Extra space that should be excluded from recycling. This is the space + * from {@code extraLayoutSpace[0]}, calculated in {@link + * #calculateExtraLayoutSpace}. */ - protected void recycleViewsFromStart(RecyclerView.Recycler recycler, int dt) { - if (dt < 0) { + protected void recycleViewsFromStart(RecyclerView.Recycler recycler, int scrollingOffset, + int noRecycleSpace) { + if (scrollingOffset < 0) { if (DEBUG) { Log.d(TAG, "Called recycle from start with a negative value. This might happen" + " during layout changes but may be sign of a bug"); @@ -1386,7 +1449,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements return; } // ignore padding, ViewGroup may not clip children. - final int limit = dt; + final int limit = scrollingOffset - noRecycleSpace; final int childCount = getChildCount(); if (mShouldReverseLayout) { for (int i = childCount - 1; i >= 0; i--) { @@ -1417,21 +1480,25 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements *

    * Checks both layout position and visible position to guarantee that the view is not visible. * - * @param recycler Recycler instance of {@link android.support.v7.widget.RecyclerView} - * @param dt This can be used to add additional padding to the visible area. This is used - * to detect children that will go out of bounds after scrolling, without - * actually moving them. + * @param recycler Recycler instance of {@link RecyclerView} + * @param scrollingOffset This can be used to add additional padding to the visible area. This + * is used to detect children that will go out of bounds after scrolling, + * without actually moving them. + * @param noRecycleSpace Extra space that should be excluded from recycling. This is the space + * from {@code extraLayoutSpace[1]}, calculated in {@link + * #calculateExtraLayoutSpace}. */ - private void recycleViewsFromEnd(RecyclerView.Recycler recycler, int dt) { + private void recycleViewsFromEnd(RecyclerView.Recycler recycler, int scrollingOffset, + int noRecycleSpace) { final int childCount = getChildCount(); - if (dt < 0) { + if (scrollingOffset < 0) { if (DEBUG) { Log.d(TAG, "Called recycle from end with a negative value. This might happen" + " during layout changes but may be sign of a bug"); } return; } - final int limit = mOrientationHelper.getEnd() - dt; + final int limit = mOrientationHelper.getEnd() - scrollingOffset + noRecycleSpace; if (mShouldReverseLayout) { for (int i = 0; i < childCount; i++) { View child = getChildAt(i); @@ -1462,24 +1529,26 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements * @param layoutState Current layout state. Right now, this object does not change but * we may consider moving it out of this view so passing around as a * parameter for now, rather than accessing {@link #mLayoutState} - * @see #recycleViewsFromStart(android.support.v7.widget.RecyclerView.Recycler, int) - * @see #recycleViewsFromEnd(android.support.v7.widget.RecyclerView.Recycler, int) - * @see android.support.v7.widget.LinearLayoutManager.LayoutState#mLayoutDirection + * @see #recycleViewsFromStart(RecyclerView.Recycler, int, int) + * @see #recycleViewsFromEnd(RecyclerView.Recycler, int, int) + * @see LinearLayoutManager.LayoutState#mLayoutDirection */ private void recycleByLayoutState(RecyclerView.Recycler recycler, LayoutState layoutState) { if (!layoutState.mRecycle || layoutState.mInfinite) { return; } + int scrollingOffset = layoutState.mScrollingOffset; + int noRecycleSpace = layoutState.mNoRecycleSpace; if (layoutState.mLayoutDirection == LayoutState.LAYOUT_START) { - recycleViewsFromEnd(recycler, layoutState.mScrollingOffset); + recycleViewsFromEnd(recycler, scrollingOffset, noRecycleSpace); } else { - recycleViewsFromStart(recycler, layoutState.mScrollingOffset); + recycleViewsFromStart(recycler, scrollingOffset, noRecycleSpace); } } /** * The magic functions :). Fills the given layout, defined by the layoutState. This is fairly - * independent from the rest of the {@link android.support.v7.widget.LinearLayoutManager} + * independent from the rest of the {@link LinearLayoutManager} * and with little change, can be made publicly available as a helper class. * * @param recycler Current recycler that is attached to RecyclerView @@ -1499,15 +1568,15 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements } recycleByLayoutState(recycler, layoutState); } - int remainingSpace = layoutState.mAvailable + layoutState.mExtra; + int remainingSpace = layoutState.mAvailable + layoutState.mExtraFillSpace; LayoutChunkResult layoutChunkResult = mLayoutChunkResult; while ((layoutState.mInfinite || remainingSpace > 0) && layoutState.hasMore(state)) { layoutChunkResult.resetInternal(); - if (VERBOSE_TRACING) { + if (RecyclerView.VERBOSE_TRACING) { TraceCompat.beginSection("LLM LayoutChunk"); } layoutChunk(recycler, state, layoutState, layoutChunkResult); - if (VERBOSE_TRACING) { + if (RecyclerView.VERBOSE_TRACING) { TraceCompat.endSection(); } if (layoutChunkResult.mFinished) { @@ -1520,7 +1589,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements * * OR we are laying out scrap children * * OR we are not doing pre-layout */ - if (!layoutChunkResult.mIgnoreConsumed || mLayoutState.mScrapList != null + if (!layoutChunkResult.mIgnoreConsumed || layoutState.mScrapList != null || !state.isPreLayout()) { layoutState.mAvailable -= layoutChunkResult.mConsumed; // we keep a separate remaining space because mAvailable is important for recycling @@ -1556,7 +1625,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements result.mFinished = true; return; } - LayoutParams params = (LayoutParams) view.getLayoutParams(); + RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams(); if (layoutState.mScrapList == null) { if (mShouldReverseLayout == (layoutState.mLayoutDirection == LayoutState.LAYOUT_START)) { @@ -1700,7 +1769,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements * @param completelyVisible Whether child should be completely visible or not * @return The first visible child closest to start of the layout from user's perspective. */ - private View findFirstVisibleChildClosestToStart(boolean completelyVisible, + View findFirstVisibleChildClosestToStart(boolean completelyVisible, boolean acceptPartiallyVisible) { if (mShouldReverseLayout) { return findOneVisibleChild(getChildCount() - 1, -1, completelyVisible, @@ -1718,7 +1787,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements * @param completelyVisible Whether child should be completely visible or not * @return The first visible child closest to end of the layout from user's perspective. */ - private View findFirstVisibleChildClosestToEnd(boolean completelyVisible, + View findFirstVisibleChildClosestToEnd(boolean completelyVisible, boolean acceptPartiallyVisible) { if (mShouldReverseLayout) { return findOneVisibleChild(0, getChildCount(), completelyVisible, @@ -1784,7 +1853,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements final View view = getChildAt(i); final int position = getPosition(view); if (position >= 0 && position < itemCount) { - if (((LayoutParams) view.getLayoutParams()).isItemRemoved()) { + if (((RecyclerView.LayoutParams) view.getLayoutParams()).isItemRemoved()) { if (invalidMatch == null) { invalidMatch = view; // removed item, least preferred } @@ -1803,27 +1872,23 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements // returns the out-of-bound child view closest to RV's end bounds. An out-of-bound child is // defined as a child that's either partially or fully invisible (outside RV's padding area). - private View findPartiallyOrCompletelyInvisibleChildClosestToEnd(RecyclerView.Recycler recycler, - RecyclerView.State state) { - return mShouldReverseLayout ? findFirstPartiallyOrCompletelyInvisibleChild(recycler, state) - : findLastPartiallyOrCompletelyInvisibleChild(recycler, state); + private View findPartiallyOrCompletelyInvisibleChildClosestToEnd() { + return mShouldReverseLayout ? findFirstPartiallyOrCompletelyInvisibleChild() + : findLastPartiallyOrCompletelyInvisibleChild(); } // returns the out-of-bound child view closest to RV's starting bounds. An out-of-bound child is // defined as a child that's either partially or fully invisible (outside RV's padding area). - private View findPartiallyOrCompletelyInvisibleChildClosestToStart( - RecyclerView.Recycler recycler, RecyclerView.State state) { - return mShouldReverseLayout ? findLastPartiallyOrCompletelyInvisibleChild(recycler, state) : - findFirstPartiallyOrCompletelyInvisibleChild(recycler, state); + private View findPartiallyOrCompletelyInvisibleChildClosestToStart() { + return mShouldReverseLayout ? findLastPartiallyOrCompletelyInvisibleChild() : + findFirstPartiallyOrCompletelyInvisibleChild(); } - private View findFirstPartiallyOrCompletelyInvisibleChild(RecyclerView.Recycler recycler, - RecyclerView.State state) { + private View findFirstPartiallyOrCompletelyInvisibleChild() { return findOnePartiallyOrCompletelyInvisibleChild(0, getChildCount()); } - private View findLastPartiallyOrCompletelyInvisibleChild(RecyclerView.Recycler recycler, - RecyclerView.State state) { + private View findLastPartiallyOrCompletelyInvisibleChild() { return findOnePartiallyOrCompletelyInvisibleChild(getChildCount() - 1, -1); } @@ -1847,7 +1912,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements */ public int findFirstVisibleItemPosition() { final View child = findOneVisibleChild(0, getChildCount(), false, true); - return child == null ? NO_POSITION : getPosition(child); + return child == null ? RecyclerView.NO_POSITION : getPosition(child); } /** @@ -1864,7 +1929,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements */ public int findFirstCompletelyVisibleItemPosition() { final View child = findOneVisibleChild(0, getChildCount(), true, false); - return child == null ? NO_POSITION : getPosition(child); + return child == null ? RecyclerView.NO_POSITION : getPosition(child); } /** @@ -1887,7 +1952,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements */ public int findLastVisibleItemPosition() { final View child = findOneVisibleChild(getChildCount() - 1, -1, false, true); - return child == null ? NO_POSITION : getPosition(child); + return child == null ? RecyclerView.NO_POSITION : getPosition(child); } /** @@ -1904,7 +1969,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements */ public int findLastCompletelyVisibleItemPosition() { final View child = findOneVisibleChild(getChildCount() - 1, -1, true, false); - return child == null ? NO_POSITION : getPosition(child); + return child == null ? RecyclerView.NO_POSITION : getPosition(child); } // Returns the first child that is visible in the provided index range, i.e. either partially or @@ -1974,7 +2039,6 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements return null; } ensureLayoutState(); - ensureLayoutState(); final int maxScroll = (int) (MAX_SCROLL_FACTOR * mOrientationHelper.getTotalSpace()); updateLayoutState(layoutDir, maxScroll, false, state); mLayoutState.mScrollingOffset = LayoutState.SCROLLING_OFFSET_NaN; @@ -1987,9 +2051,9 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements // the screen if no focusable views are found in the given layout direction. final View nextCandidate; if (layoutDir == LayoutState.LAYOUT_START) { - nextCandidate = findPartiallyOrCompletelyInvisibleChildClosestToStart(recycler, state); + nextCandidate = findPartiallyOrCompletelyInvisibleChildClosestToStart(); } else { - nextCandidate = findPartiallyOrCompletelyInvisibleChildClosestToEnd(recycler, state); + nextCandidate = findPartiallyOrCompletelyInvisibleChildClosestToEnd(); } // nextFocus is meaningful only if it refers to a focusable child, in which case it // indicates the next view to gain focus. @@ -2080,9 +2144,9 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements /** * @hide This method should be called by ItemTouchHelper only. */ - @RestrictTo(LIBRARY_GROUP) + @RestrictTo(LIBRARY_GROUP_PREFIX) @Override - public void prepareForDrop(View view, View target, int x, int y) { + public void prepareForDrop(@NonNull View view, @NonNull View target, int x, int y) { assertNotInLayoutOrScroll("Cannot drop a view during a scroll or layout calculation"); ensureLayoutState(); resolveShouldLayoutReverse(); @@ -2174,9 +2238,16 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements /** * Used if you want to pre-layout items that are not yet visible. * The difference with {@link #mAvailable} is that, when recycling, distance laid out for - * {@link #mExtra} is not considered to avoid recycling visible children. + * {@link #mExtraFillSpace} is not considered to avoid recycling visible children. */ - int mExtra = 0; + int mExtraFillSpace = 0; + + /** + * Contains the {@link #calculateExtraLayoutSpace(RecyclerView.State, int[])} extra layout + * space} that should be excluded for recycling when cleaning up the tail of the list during + * a smooth scroll. + */ + int mNoRecycleSpace = 0; /** * Equal to {@link RecyclerView.State#isPreLayout()}. When consuming scrap, if this value @@ -2235,7 +2306,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements final int size = mScrapList.size(); for (int i = 0; i < size; i++) { final View view = mScrapList.get(i).itemView; - final LayoutParams lp = (LayoutParams) view.getLayoutParams(); + final RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) view.getLayoutParams(); if (lp.isItemRemoved()) { continue; } @@ -2254,9 +2325,9 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements public void assignPositionFromScrapList(View ignore) { final View closest = nextViewInLimitedList(ignore); if (closest == null) { - mCurrentPosition = NO_POSITION; + mCurrentPosition = RecyclerView.NO_POSITION; } else { - mCurrentPosition = ((LayoutParams) closest.getLayoutParams()) + mCurrentPosition = ((RecyclerView.LayoutParams) closest.getLayoutParams()) .getViewLayoutPosition(); } } @@ -2270,7 +2341,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements } for (int i = 0; i < size; i++) { View view = mScrapList.get(i).itemView; - final LayoutParams lp = (LayoutParams) view.getLayoutParams(); + final RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) view.getLayoutParams(); if (view == ignore || lp.isItemRemoved()) { continue; } @@ -2299,7 +2370,8 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements /** * @hide */ - @RestrictTo(LIBRARY_GROUP) + @RestrictTo(LIBRARY_GROUP_PREFIX) + @SuppressLint("BanParcelableUsage") public static class SavedState implements Parcelable { int mAnchorPosition; @@ -2329,7 +2401,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements } void invalidateAnchor() { - mAnchorPosition = NO_POSITION; + mAnchorPosition = RecyclerView.NO_POSITION; } @Override @@ -2373,7 +2445,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements } void reset() { - mPosition = NO_POSITION; + mPosition = RecyclerView.NO_POSITION; mCoordinate = INVALID_OFFSET; mLayoutFromEnd = false; mValid = false; @@ -2400,7 +2472,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements } boolean isViewValidAsAnchor(View child, RecyclerView.State state) { - LayoutParams lp = (LayoutParams) child.getLayoutParams(); + RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) child.getLayoutParams(); return !lp.isItemRemoved() && lp.getViewLayoutPosition() >= 0 && lp.getViewLayoutPosition() < state.getItemCount(); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LinearSmoothScroller.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearSmoothScroller.java similarity index 90% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LinearSmoothScroller.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearSmoothScroller.java index 73dc5aae9..37bb647d0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LinearSmoothScroller.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearSmoothScroller.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +14,11 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; import android.content.Context; import android.graphics.PointF; -import android.support.annotation.Nullable; import android.util.DisplayMetrics; -import android.util.Log; import android.view.View; import android.view.animation.DecelerateInterpolator; import android.view.animation.LinearInterpolator; @@ -37,8 +35,6 @@ import android.view.animation.LinearInterpolator; */ public class LinearSmoothScroller extends RecyclerView.SmoothScroller { - private static final String TAG = "LinearSmoothScroller"; - private static final boolean DEBUG = false; private static final float MILLISECONDS_PER_INCH = 25f; @@ -86,14 +82,16 @@ public class LinearSmoothScroller extends RecyclerView.SmoothScroller { protected PointF mTargetVector; - private final float MILLISECONDS_PER_PX; + private final DisplayMetrics mDisplayMetrics; + private boolean mHasCalculatedMillisPerPixel = false; + private float mMillisPerPixel; // Temporary variables to keep track of the interim scroll target. These values do not // point to a real item position, rather point to an estimated location pixels. protected int mInterimTargetDx = 0, mInterimTargetDy = 0; public LinearSmoothScroller(Context context) { - MILLISECONDS_PER_PX = calculateSpeedPerPixel(context.getResources().getDisplayMetrics()); + mDisplayMetrics = context.getResources().getDisplayMetrics(); } /** @@ -123,6 +121,9 @@ public class LinearSmoothScroller extends RecyclerView.SmoothScroller { */ @Override protected void onSeekTargetStep(int dx, int dy, RecyclerView.State state, Action action) { + // TODO(b/72745539): Is there ever a time when onSeekTargetStep should be called when + // getChildCount returns 0? Should this logic be extracted out of this method such that + // this method is not called if getChildCount() returns 0? if (getChildCount() == 0) { stop(); return; @@ -154,6 +155,9 @@ public class LinearSmoothScroller extends RecyclerView.SmoothScroller { /** * Calculates the scroll speed. * + *

    By default, LinearSmoothScroller assumes this method always returns the same value and + * caches the result of calling it. + * * @param displayMetrics DisplayMetrics to be used for real dimension calculations * @return The time (in ms) it should take for each pixel. For instance, if returned value is * 2 ms, it means scrolling 1000 pixels with LinearInterpolation should take 2 seconds. @@ -162,6 +166,14 @@ public class LinearSmoothScroller extends RecyclerView.SmoothScroller { return MILLISECONDS_PER_INCH / displayMetrics.densityDpi; } + private float getSpeedPerPixel() { + if (!mHasCalculatedMillisPerPixel) { + mMillisPerPixel = calculateSpeedPerPixel(mDisplayMetrics); + mHasCalculatedMillisPerPixel = true; + } + return mMillisPerPixel; + } + /** *

    Calculates the time for deceleration so that transition from LinearInterpolator to * DecelerateInterpolator looks smooth.

    @@ -190,7 +202,7 @@ public class LinearSmoothScroller extends RecyclerView.SmoothScroller { // In a case where dx is very small, rounding may return 0 although dx > 0. // To avoid that issue, ceil the result so that if dx > 0, we'll always return positive // time. - return (int) Math.ceil(Math.abs(dx) * MILLISECONDS_PER_PX); + return (int) Math.ceil(Math.abs(dx) * getSpeedPerPixel()); } /** @@ -336,26 +348,4 @@ public class LinearSmoothScroller extends RecyclerView.SmoothScroller { final int end = layoutManager.getWidth() - layoutManager.getPaddingRight(); return calculateDtToFit(left, right, start, end, snapPreference); } - - /** - * Compute the scroll vector for a given target position. - *

    - * This method can return null if the layout manager cannot calculate a scroll vector - * for the given position (e.g. it has no current scroll position). - * - * @param targetPosition the position to which the scroller is scrolling - * - * @return the scroll vector for a given target position - */ - @Nullable - public PointF computeScrollVectorForPosition(int targetPosition) { - RecyclerView.LayoutManager layoutManager = getLayoutManager(); - if (layoutManager instanceof ScrollVectorProvider) { - return ((ScrollVectorProvider) layoutManager) - .computeScrollVectorForPosition(targetPosition); - } - Log.w(TAG, "You should override computeScrollVectorForPosition when the LayoutManager" - + " does not implement " + ScrollVectorProvider.class.getCanonicalName()); - return null; - } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LinearSmoothScrollerEnd.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearSmoothScrollerEnd.java similarity index 98% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LinearSmoothScrollerEnd.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearSmoothScrollerEnd.java index 050b98e24..a62a99085 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LinearSmoothScrollerEnd.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearSmoothScrollerEnd.java @@ -6,11 +6,11 @@ * Copyright Nikolai Kudashov, 2013-2018. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; import android.content.Context; import android.graphics.PointF; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.view.View; import android.view.animation.DecelerateInterpolator; import android.view.animation.LinearInterpolator; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LinearSmoothScrollerMiddle.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearSmoothScrollerMiddle.java similarity index 98% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LinearSmoothScrollerMiddle.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearSmoothScrollerMiddle.java index f47846ca6..9cb8c19f9 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LinearSmoothScrollerMiddle.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearSmoothScrollerMiddle.java @@ -6,11 +6,11 @@ * Copyright Nikolai Kudashov, 2013-2018. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; import android.content.Context; import android.graphics.PointF; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.view.View; import android.view.animation.DecelerateInterpolator; import android.view.animation.LinearInterpolator; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LinearSnapHelper.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearSnapHelper.java similarity index 98% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LinearSnapHelper.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearSnapHelper.java index 67de4ed0a..36417eab4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/LinearSnapHelper.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearSnapHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +14,14 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; import android.graphics.PointF; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.view.View; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + /** * Implementation of the {@link SnapHelper} supporting snapping in either vertical or horizontal * orientation. diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/ListAdapter.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ListAdapter.java new file mode 100644 index 000000000..d00e84c4d --- /dev/null +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ListAdapter.java @@ -0,0 +1,190 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.recyclerview.widget; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.List; + +/** + * {@link RecyclerView.Adapter RecyclerView.Adapter} base class for presenting List data in a + * {@link RecyclerView}, including computing diffs between Lists on a background thread. + *

    + * This class is a convenience wrapper around {@link AsyncListDiffer} that implements Adapter common + * default behavior for item access and counting. + *

    + * While using a LiveData<List> is an easy way to provide data to the adapter, it isn't required + * - you can use {@link #submitList(List)} when new lists are available. + *

    + * A complete usage pattern with Room would look like this: + *

    + * {@literal @}Dao
    + * interface UserDao {
    + *     {@literal @}Query("SELECT * FROM user ORDER BY lastName ASC")
    + *     public abstract LiveData<List<User>> usersByLastName();
    + * }
    + *
    + * class MyViewModel extends ViewModel {
    + *     public final LiveData<List<User>> usersList;
    + *     public MyViewModel(UserDao userDao) {
    + *         usersList = userDao.usersByLastName();
    + *     }
    + * }
    + *
    + * class MyActivity extends AppCompatActivity {
    + *     {@literal @}Override
    + *     public void onCreate(Bundle savedState) {
    + *         super.onCreate(savedState);
    + *         MyViewModel viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
    + *         RecyclerView recyclerView = findViewById(R.id.user_list);
    + *         UserAdapter<User> adapter = new UserAdapter();
    + *         viewModel.usersList.observe(this, list -> adapter.submitList(list));
    + *         recyclerView.setAdapter(adapter);
    + *     }
    + * }
    + *
    + * class UserAdapter extends ListAdapter<User, UserViewHolder> {
    + *     public UserAdapter() {
    + *         super(User.DIFF_CALLBACK);
    + *     }
    + *     {@literal @}Override
    + *     public void onBindViewHolder(UserViewHolder holder, int position) {
    + *         holder.bindTo(getItem(position));
    + *     }
    + *     public static final DiffUtil.ItemCallback<User> DIFF_CALLBACK =
    + *             new DiffUtil.ItemCallback<User>() {
    + *         {@literal @}Override
    + *         public boolean areItemsTheSame(
    + *                 {@literal @}NonNull User oldUser, {@literal @}NonNull User newUser) {
    + *             // User properties may have changed if reloaded from the DB, but ID is fixed
    + *             return oldUser.getId() == newUser.getId();
    + *         }
    + *         {@literal @}Override
    + *         public boolean areContentsTheSame(
    + *                 {@literal @}NonNull User oldUser, {@literal @}NonNull User newUser) {
    + *             // NOTE: if you use equals, your object must properly override Object#equals()
    + *             // Incorrectly returning false here will result in too many animations.
    + *             return oldUser.equals(newUser);
    + *         }
    + *     }
    + * }
    + * + * Advanced users that wish for more control over adapter behavior, or to provide a specific base + * class should refer to {@link AsyncListDiffer}, which provides custom mapping from diff events + * to adapter positions. + * + * @param Type of the Lists this Adapter will receive. + * @param A class that extends ViewHolder that will be used by the adapter. + */ +public abstract class ListAdapter + extends RecyclerView.Adapter { + final AsyncListDiffer mDiffer; + private final AsyncListDiffer.ListListener mListener = + new AsyncListDiffer.ListListener() { + @Override + public void onCurrentListChanged( + @NonNull List previousList, @NonNull List currentList) { + ListAdapter.this.onCurrentListChanged(previousList, currentList); + } + }; + + @SuppressWarnings("unused") + protected ListAdapter(@NonNull DiffUtil.ItemCallback diffCallback) { + mDiffer = new AsyncListDiffer<>(new AdapterListUpdateCallback(this), + new AsyncDifferConfig.Builder<>(diffCallback).build()); + mDiffer.addListListener(mListener); + } + + @SuppressWarnings("unused") + protected ListAdapter(@NonNull AsyncDifferConfig config) { + mDiffer = new AsyncListDiffer<>(new AdapterListUpdateCallback(this), config); + mDiffer.addListListener(mListener); + } + + /** + * Submits a new list to be diffed, and displayed. + *

    + * If a list is already being displayed, a diff will be computed on a background thread, which + * will dispatch Adapter.notifyItem events on the main thread. + * + * @param list The new list to be displayed. + */ + public void submitList(@Nullable List list) { + mDiffer.submitList(list); + } + + /** + * Set the new list to be displayed. + *

    + * If a List is already being displayed, a diff will be computed on a background thread, which + * will dispatch Adapter.notifyItem events on the main thread. + *

    + * The commit callback can be used to know when the List is committed, but note that it + * may not be executed. If List B is submitted immediately after List A, and is + * committed directly, the callback associated with List A will not be run. + * + * @param list The new list to be displayed. + * @param commitCallback Optional runnable that is executed when the List is committed, if + * it is committed. + */ + public void submitList(@Nullable List list, @Nullable final Runnable commitCallback) { + mDiffer.submitList(list, commitCallback); + } + + protected T getItem(int position) { + return mDiffer.getCurrentList().get(position); + } + + @Override + public int getItemCount() { + return mDiffer.getCurrentList().size(); + } + + /** + * Get the current List - any diffing to present this list has already been computed and + * dispatched via the ListUpdateCallback. + *

    + * If a null List, or no List has been submitted, an empty list will be returned. + *

    + * The returned list may not be mutated - mutations to content must be done through + * {@link #submitList(List)}. + * + * @return The list currently being displayed. + * + * @see #onCurrentListChanged(List, List) + */ + @NonNull + public List getCurrentList() { + return mDiffer.getCurrentList(); + } + + /** + * Called when the current List is updated. + *

    + * If a null List is passed to {@link #submitList(List)}, or no List has been + * submitted, the current List is represented as an empty List. + * + * @param previousList List that was displayed previously. + * @param currentList new List being displayed, will be empty if {@code null} was passed to + * {@link #submitList(List)}. + * + * @see #getCurrentList() + */ + public void onCurrentListChanged(@NonNull List previousList, @NonNull List currentList) { + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/ListUpdateCallback.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ListUpdateCallback.java similarity index 90% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/util/ListUpdateCallback.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/ListUpdateCallback.java index 40b18b62f..ed8e7fc67 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/ListUpdateCallback.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ListUpdateCallback.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.telegram.messenger.support.util; +package androidx.recyclerview.widget; + +import androidx.annotation.Nullable; /** * An interface that can receive Update operations that are applied to a list. @@ -51,5 +53,5 @@ public interface ListUpdateCallback { * @param position The position of the item which has been updated. * @param count The number of items which has changed. */ - void onChanged(int position, int count, Object payload); + void onChanged(int position, int count, @Nullable Object payload); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/MessageThreadUtil.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/MessageThreadUtil.java similarity index 94% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/util/MessageThreadUtil.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/MessageThreadUtil.java index d88a3e61e..7234d922a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/MessageThreadUtil.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/MessageThreadUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.telegram.messenger.support.util; +package androidx.recyclerview.widget; import android.os.AsyncTask; import android.os.Handler; @@ -66,8 +66,9 @@ class MessageThreadUtil implements ThreadUtil { callback.updateItemCount(msg.arg1, msg.arg2); break; case ADD_TILE: - //noinspection unchecked - callback.addTile(msg.arg1, (TileList.Tile) msg.data); + @SuppressWarnings("unchecked") + TileList.Tile tile = (TileList.Tile) msg.data; + callback.addTile(msg.arg1, tile); break; case REMOVE_TILE: callback.removeTile(msg.arg1, msg.arg2); @@ -155,8 +156,9 @@ class MessageThreadUtil implements ThreadUtil { callback.loadTile(msg.arg1, msg.arg2); break; case RECYCLE_TILE: - //noinspection unchecked - callback.recycleTile((TileList.Tile) msg.data); + @SuppressWarnings("unchecked") + TileList.Tile tile = (TileList.Tile) msg.data; + callback.recycleTile(tile); break; default: Log.e("ThreadUtil", "Unsupported message, what=" + msg.what); @@ -176,7 +178,7 @@ class MessageThreadUtil implements ThreadUtil { private static SyncQueueItem sPool; private static final Object sPoolLock = new Object(); - private SyncQueueItem next; + SyncQueueItem next; public int what; public int arg1; public int arg2; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/OpReorderer.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/OpReorderer.java similarity index 78% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/OpReorderer.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/OpReorderer.java index a42dbac4a..722960c82 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/OpReorderer.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/OpReorderer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,7 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget; - -import static org.telegram.messenger.support.widget.AdapterHelper.UpdateOp.ADD; -import static org.telegram.messenger.support.widget.AdapterHelper.UpdateOp.MOVE; -import static org.telegram.messenger.support.widget.AdapterHelper.UpdateOp.REMOVE; -import static org.telegram.messenger.support.widget.AdapterHelper.UpdateOp.UPDATE; - -import org.telegram.messenger.support.widget.AdapterHelper.UpdateOp; +package androidx.recyclerview.widget; import java.util.List; @@ -33,7 +26,7 @@ class OpReorderer { mCallback = callback; } - void reorderOps(List ops) { + void reorderOps(List ops) { // since move operations breaks continuity, their effects on ADD/RM are hard to handle. // we push them to the end of the list so that they can be handled easily. int badMove; @@ -42,25 +35,25 @@ class OpReorderer { } } - private void swapMoveOp(List list, int badMove, int next) { - final UpdateOp moveOp = list.get(badMove); - final UpdateOp nextOp = list.get(next); + private void swapMoveOp(List list, int badMove, int next) { + final AdapterHelper.UpdateOp moveOp = list.get(badMove); + final AdapterHelper.UpdateOp nextOp = list.get(next); switch (nextOp.cmd) { - case REMOVE: + case AdapterHelper.UpdateOp.REMOVE: swapMoveRemove(list, badMove, moveOp, next, nextOp); break; - case ADD: + case AdapterHelper.UpdateOp.ADD: swapMoveAdd(list, badMove, moveOp, next, nextOp); break; - case UPDATE: + case AdapterHelper.UpdateOp.UPDATE: swapMoveUpdate(list, badMove, moveOp, next, nextOp); break; } } - void swapMoveRemove(List list, int movePos, UpdateOp moveOp, - int removePos, UpdateOp removeOp) { - UpdateOp extraRm = null; + void swapMoveRemove(List list, int movePos, AdapterHelper.UpdateOp moveOp, + int removePos, AdapterHelper.UpdateOp removeOp) { + AdapterHelper.UpdateOp extraRm = null; // check if move is nulled out by remove boolean revertedMove = false; final boolean moveIsBackwards; @@ -85,7 +78,7 @@ class OpReorderer { } else if (moveOp.itemCount < removeOp.positionStart + removeOp.itemCount) { // move is removed. removeOp.itemCount--; - moveOp.cmd = REMOVE; + moveOp.cmd = AdapterHelper.UpdateOp.REMOVE; moveOp.itemCount = 1; if (removeOp.itemCount == 0) { list.remove(removePos); @@ -101,7 +94,7 @@ class OpReorderer { } else if (moveOp.positionStart < removeOp.positionStart + removeOp.itemCount) { final int remaining = removeOp.positionStart + removeOp.itemCount - moveOp.positionStart; - extraRm = mCallback.obtainUpdateOp(REMOVE, moveOp.positionStart + 1, remaining, null); + extraRm = mCallback.obtainUpdateOp(AdapterHelper.UpdateOp.REMOVE, moveOp.positionStart + 1, remaining, null); removeOp.itemCount = moveOp.positionStart - removeOp.positionStart; } @@ -157,8 +150,8 @@ class OpReorderer { } } - private void swapMoveAdd(List list, int move, UpdateOp moveOp, int add, - UpdateOp addOp) { + private void swapMoveAdd(List list, int move, AdapterHelper.UpdateOp moveOp, int add, + AdapterHelper.UpdateOp addOp) { int offset = 0; // going in reverse, first revert the effect of add if (moveOp.itemCount < addOp.positionStart) { @@ -178,17 +171,17 @@ class OpReorderer { list.set(add, moveOp); } - void swapMoveUpdate(List list, int move, UpdateOp moveOp, int update, - UpdateOp updateOp) { - UpdateOp extraUp1 = null; - UpdateOp extraUp2 = null; + void swapMoveUpdate(List list, int move, AdapterHelper.UpdateOp moveOp, int update, + AdapterHelper.UpdateOp updateOp) { + AdapterHelper.UpdateOp extraUp1 = null; + AdapterHelper.UpdateOp extraUp2 = null; // going in reverse, first revert the effect of add if (moveOp.itemCount < updateOp.positionStart) { updateOp.positionStart--; } else if (moveOp.itemCount < updateOp.positionStart + updateOp.itemCount) { // moved item is updated. add an update for it updateOp.itemCount--; - extraUp1 = mCallback.obtainUpdateOp(UPDATE, moveOp.positionStart, 1, updateOp.payload); + extraUp1 = mCallback.obtainUpdateOp(AdapterHelper.UpdateOp.UPDATE, moveOp.positionStart, 1, updateOp.payload); } // now affect of add is consumed. now apply effect of first remove if (moveOp.positionStart <= updateOp.positionStart) { @@ -196,7 +189,8 @@ class OpReorderer { } else if (moveOp.positionStart < updateOp.positionStart + updateOp.itemCount) { final int remaining = updateOp.positionStart + updateOp.itemCount - moveOp.positionStart; - extraUp2 = mCallback.obtainUpdateOp(UPDATE, moveOp.positionStart + 1, remaining, + extraUp2 = mCallback.obtainUpdateOp( + AdapterHelper.UpdateOp.UPDATE, moveOp.positionStart + 1, remaining, updateOp.payload); updateOp.itemCount -= remaining; } @@ -215,11 +209,11 @@ class OpReorderer { } } - private int getLastMoveOutOfOrder(List list) { + private int getLastMoveOutOfOrder(List list) { boolean foundNonMove = false; for (int i = list.size() - 1; i >= 0; i--) { - final UpdateOp op1 = list.get(i); - if (op1.cmd == MOVE) { + final AdapterHelper.UpdateOp op1 = list.get(i); + if (op1.cmd == AdapterHelper.UpdateOp.MOVE) { if (foundNonMove) { return i; } @@ -232,8 +226,8 @@ class OpReorderer { interface Callback { - UpdateOp obtainUpdateOp(int cmd, int startPosition, int itemCount, Object payload); + AdapterHelper.UpdateOp obtainUpdateOp(int cmd, int startPosition, int itemCount, Object payload); - void recycleUpdateOp(UpdateOp op); + void recycleUpdateOp(AdapterHelper.UpdateOp op); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/OrientationHelper.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/OrientationHelper.java similarity index 98% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/OrientationHelper.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/OrientationHelper.java index 3b456519d..f94e0dd16 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/OrientationHelper.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/OrientationHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; import android.graphics.Rect; import android.view.View; @@ -48,7 +48,7 @@ public abstract class OrientationHelper { } /** - * Returns the {@link android.support.v7.widget.RecyclerView.LayoutManager LayoutManager} that + * Returns the {@link RecyclerView.LayoutManager LayoutManager} that * is associated with this OrientationHelper. */ public RecyclerView.LayoutManager getLayoutManager() { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/PagerSnapHelper.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/PagerSnapHelper.java similarity index 68% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/PagerSnapHelper.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/PagerSnapHelper.java index 7627daa2b..1dbc495e1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/PagerSnapHelper.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/PagerSnapHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,23 +14,24 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; import android.graphics.PointF; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.DisplayMetrics; import android.view.View; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + /** * Implementation of the {@link SnapHelper} supporting pager style snapping in either vertical or * horizontal orientation. * *

    * - * PagerSnapHelper can help achieve a similar behavior to {@link android.support.v4.view.ViewPager}. - * Set both {@link RecyclerView} and the items of the - * {@link android.support.v7.widget.RecyclerView.Adapter} to have + * PagerSnapHelper can help achieve a similar behavior to + * {@link androidx.viewpager.widget.ViewPager}. Set both {@link RecyclerView} and the items of the + * {@link RecyclerView.Adapter} to have * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT} height and width and then attach * PagerSnapHelper to the {@link RecyclerView} using {@link #attachToRecyclerView(RecyclerView)}. */ @@ -83,39 +84,84 @@ public class PagerSnapHelper extends SnapHelper { return RecyclerView.NO_POSITION; } - View mStartMostChildView = null; - if (layoutManager.canScrollVertically()) { - mStartMostChildView = findStartView(layoutManager, getVerticalHelper(layoutManager)); - } else if (layoutManager.canScrollHorizontally()) { - mStartMostChildView = findStartView(layoutManager, getHorizontalHelper(layoutManager)); - } - - if (mStartMostChildView == null) { - return RecyclerView.NO_POSITION; - } - final int centerPosition = layoutManager.getPosition(mStartMostChildView); - if (centerPosition == RecyclerView.NO_POSITION) { + final OrientationHelper orientationHelper = getOrientationHelper(layoutManager); + if (orientationHelper == null) { return RecyclerView.NO_POSITION; } - final boolean forwardDirection; + // A child that is exactly in the center is eligible for both before and after + View closestChildBeforeCenter = null; + int distanceBefore = Integer.MIN_VALUE; + View closestChildAfterCenter = null; + int distanceAfter = Integer.MAX_VALUE; + + // Find the first view before the center, and the first view after the center + final int childCount = layoutManager.getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = layoutManager.getChildAt(i); + if (child == null) { + continue; + } + final int distance = distanceToCenter(layoutManager, child, orientationHelper); + + if (distance <= 0 && distance > distanceBefore) { + // Child is before the center and closer then the previous best + distanceBefore = distance; + closestChildBeforeCenter = child; + } + if (distance >= 0 && distance < distanceAfter) { + // Child is after the center and closer then the previous best + distanceAfter = distance; + closestChildAfterCenter = child; + } + } + + // Return the position of the first child from the center, in the direction of the fling + final boolean forwardDirection = isForwardFling(layoutManager, velocityX, velocityY); + if (forwardDirection && closestChildAfterCenter != null) { + return layoutManager.getPosition(closestChildAfterCenter); + } else if (!forwardDirection && closestChildBeforeCenter != null) { + return layoutManager.getPosition(closestChildBeforeCenter); + } + + // There is no child in the direction of the fling. Either it doesn't exist (start/end of + // the list), or it is not yet attached (very rare case when children are larger then the + // viewport). Extrapolate from the child that is visible to get the position of the view to + // snap to. + View visibleView = forwardDirection ? closestChildBeforeCenter : closestChildAfterCenter; + if (visibleView == null) { + return RecyclerView.NO_POSITION; + } + int visiblePosition = layoutManager.getPosition(visibleView); + int snapToPosition = visiblePosition + + (isReverseLayout(layoutManager) == forwardDirection ? -1 : +1); + + if (snapToPosition < 0 || snapToPosition >= itemCount) { + return RecyclerView.NO_POSITION; + } + return snapToPosition; + } + + private boolean isForwardFling(RecyclerView.LayoutManager layoutManager, int velocityX, + int velocityY) { if (layoutManager.canScrollHorizontally()) { - forwardDirection = velocityX > 0; + return velocityX > 0; } else { - forwardDirection = velocityY > 0; + return velocityY > 0; } - boolean reverseLayout = false; + } + + private boolean isReverseLayout(RecyclerView.LayoutManager layoutManager) { + final int itemCount = layoutManager.getItemCount(); if ((layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider)) { RecyclerView.SmoothScroller.ScrollVectorProvider vectorProvider = (RecyclerView.SmoothScroller.ScrollVectorProvider) layoutManager; PointF vectorForEnd = vectorProvider.computeScrollVectorForPosition(itemCount - 1); if (vectorForEnd != null) { - reverseLayout = vectorForEnd.x < 0 || vectorForEnd.y < 0; + return vectorForEnd.x < 0 || vectorForEnd.y < 0; } } - return reverseLayout - ? (forwardDirection ? centerPosition - 1 : centerPosition) - : (forwardDirection ? centerPosition + 1 : centerPosition); + return false; } @Override @@ -193,7 +239,7 @@ public class PagerSnapHelper extends SnapHelper { + (helper.getDecoratedMeasurement(child) / 2); int absDistance = Math.abs(childCenter - center); - /** if child center is closer than previous closest, set it as closest **/ + /* if child center is closer than previous closest, set it as closest */ if (absDistance < absClosest) { absClosest = absDistance; closestChild = child; @@ -202,37 +248,15 @@ public class PagerSnapHelper extends SnapHelper { return closestChild; } - /** - * Return the child view that is currently closest to the start of this parent. - * - * @param layoutManager The {@link RecyclerView.LayoutManager} associated with the attached - * {@link RecyclerView}. - * @param helper The relevant {@link OrientationHelper} for the attached {@link RecyclerView}. - * - * @return the child view that is currently closest to the start of this parent. - */ @Nullable - private View findStartView(RecyclerView.LayoutManager layoutManager, - OrientationHelper helper) { - int childCount = layoutManager.getChildCount(); - if (childCount == 0) { + private OrientationHelper getOrientationHelper(RecyclerView.LayoutManager layoutManager) { + if (layoutManager.canScrollVertically()) { + return getVerticalHelper(layoutManager); + } else if (layoutManager.canScrollHorizontally()) { + return getHorizontalHelper(layoutManager); + } else { return null; } - - View closestChild = null; - int startest = Integer.MAX_VALUE; - - for (int i = 0; i < childCount; i++) { - final View child = layoutManager.getChildAt(i); - int childStart = helper.getDecoratedStart(child); - - /** if child is more to start than previous closest, set it as closest **/ - if (childStart < startest) { - startest = childStart; - closestChild = child; - } - } - return closestChild; } @NonNull diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/RecyclerView.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerView.java similarity index 92% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/RecyclerView.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerView.java index 54bfdaeb8..1997f1099 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/RecyclerView.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerView.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,12 +15,14 @@ */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; -import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; -import static android.support.v4.view.ViewCompat.TYPE_NON_TOUCH; -import static android.support.v4.view.ViewCompat.TYPE_TOUCH; +import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX; +import static androidx.core.view.ViewCompat.TYPE_NON_TOUCH; +import static androidx.core.view.ViewCompat.TYPE_TOUCH; +import android.animation.LayoutTransition; +import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; @@ -37,28 +39,6 @@ import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; -import android.support.annotation.CallSuper; -import android.support.annotation.IntDef; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.RestrictTo; -import android.support.annotation.VisibleForTesting; -import android.support.v4.os.TraceCompat; -import android.support.v4.util.Preconditions; -import android.support.v4.view.AbsSavedState; -import android.support.v4.view.InputDeviceCompat; -import android.support.v4.view.MotionEventCompat; -import android.support.v4.view.NestedScrollingChild2; -import android.support.v4.view.NestedScrollingChildHelper; -import android.support.v4.view.ScrollingView; -import android.support.v4.view.ViewCompat; -import android.support.v4.view.ViewConfigurationCompat; -import android.support.v4.view.accessibility.AccessibilityEventCompat; -import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; -import android.support.v4.widget.EdgeEffectCompat; - -import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.support.widget.RecyclerView.ItemAnimator.ItemHolderInfo; import android.util.AttributeSet; import android.util.Log; import android.util.SparseArray; @@ -78,6 +58,32 @@ import android.widget.EdgeEffect; import android.widget.LinearLayout; import android.widget.OverScroller; +import org.telegram.messenger.AndroidUtilities; + +import androidx.annotation.CallSuper; +import androidx.annotation.IntDef; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.Px; +import androidx.annotation.RestrictTo; +import androidx.annotation.VisibleForTesting; +import androidx.core.os.TraceCompat; +import androidx.core.util.Preconditions; +import androidx.core.view.AccessibilityDelegateCompat; +import androidx.core.view.InputDeviceCompat; +import androidx.core.view.MotionEventCompat; +import androidx.core.view.NestedScrollingChild2; +import androidx.core.view.NestedScrollingChild3; +import androidx.core.view.NestedScrollingChildHelper; +import androidx.core.view.ScrollingView; +import androidx.core.view.ViewCompat; +import androidx.core.view.ViewConfigurationCompat; +import androidx.core.view.accessibility.AccessibilityEventCompat; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; +import androidx.core.widget.EdgeEffectCompat; +import androidx.customview.view.AbsSavedState; +import androidx.recyclerview.widget.RecyclerView.ItemAnimator.ItemHolderInfo; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; @@ -112,7 +118,7 @@ import java.util.List; * being displayed. * * - *

    Positions in RecyclerView:

    + *

    Positions in RecyclerView:

    *

    * RecyclerView introduces an additional level of abstraction between the {@link Adapter} and * {@link LayoutManager} to be able to detect data set changes in batches during a layout @@ -151,10 +157,58 @@ import java.util.List; *

    * When writing a {@link LayoutManager} you almost always want to use layout positions whereas when * writing an {@link Adapter}, you probably want to use adapter positions. + *

    + *

    Presenting Dynamic Data

    + * To display updatable data in a RecyclerView, your adapter needs to signal inserts, moves, and + * deletions to RecyclerView. You can build this yourself by manually calling + * {@code adapter.notify*} methods when content changes, or you can use one of the easier solutions + * RecyclerView provides: + *

    + *

    List diffing with DiffUtil

    + * If your RecyclerView is displaying a list that is re-fetched from scratch for each update (e.g. + * from the network, or from a database), {@link DiffUtil} can calculate the difference between + * versions of the list. {@code DiffUtil} takes both lists as input and computes the difference, + * which can be passed to RecyclerView to trigger minimal animations and updates to keep your UI + * performant, and animations meaningful. This approach requires that each list is represented in + * memory with immutable content, and relies on receiving updates as new instances of lists. This + * approach is also ideal if your UI layer doesn't implement sorting, it just presents the data in + * the order it's given. + *

    + * The best part of this approach is that it extends to any arbitrary changes - item updates, + * moves, addition and removal can all be computed and handled the same way. Though you do have + * to keep two copies of the list in memory while diffing, and must avoid mutating them, it's + * possible to share unmodified elements between list versions. + *

    + * There are three primary ways to do this for RecyclerView. We recommend you start with + * {@link ListAdapter}, the higher-level API that builds in {@link List} diffing on a background + * thread, with minimal code. {@link AsyncListDiffer} also provides this behavior, but without + * defining an Adapter to subclass. If you want more control, {@link DiffUtil} is the lower-level + * API you can use to compute the diffs yourself. Each approach allows you to specify how diffs + * should be computed based on item data. + *

    + *

    List mutation with SortedList

    + * If your RecyclerView receives updates incrementally, e.g. item X is inserted, or item Y is + * removed, you can use {@link SortedList} to manage your list. You define how to order items, + * and it will automatically trigger update signals that RecyclerView can use. SortedList works + * if you only need to handle insert and remove events, and has the benefit that you only ever + * need to have a single copy of the list in memory. It can also compute differences with + * {@link SortedList#replaceAll(Object[])}, but this method is more limited than the list diffing + * behavior above. + *

    + *

    Paging Library

    + * The Paging + * library extends the diff-based approach to additionally support paged loading. It provides + * the {@link androidx.paging.PagedList} class that operates as a self-loading list, provided a + * source of data like a database, or paginated network API. It provides convenient list diffing + * support out of the box, similar to {@code ListAdapter} and {@code AsyncListDiffer}. For more + * information about the Paging library, see the + * library + * documentation. * - * @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_layoutManager + * {@link androidx.recyclerview.R.attr#layoutManager} */ -public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild2 { +public class RecyclerView extends ViewGroup implements ScrollingView, + NestedScrollingChild2, NestedScrollingChild3 { static final String TAG = "RecyclerView"; @@ -189,7 +243,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * On L+, with RenderThread, the UI thread has idle time after it has passed a frame off to * RenderThread but before the next frame begins. We schedule prefetch work in this window. */ - private static final boolean ALLOW_THREAD_GAP_WORK = Build.VERSION.SDK_INT >= 21; + static final boolean ALLOW_THREAD_GAP_WORK = Build.VERSION.SDK_INT >= 21; /** * FocusFinder#findNextFocus is broken on ICS MR1 and older for View.FOCUS_BACKWARD direction. @@ -210,7 +264,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro static final boolean DISPATCH_TEMP_DETACH = false; /** @hide */ - @RestrictTo(LIBRARY_GROUP) + @RestrictTo(LIBRARY_GROUP_PREFIX) @IntDef({HORIZONTAL, VERTICAL}) @Retention(RetentionPolicy.SOURCE) public @interface Orientation {} @@ -237,6 +291,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro */ public static final int TOUCH_SLOP_PAGING = 1; + static final int UNDEFINED_DURATION = Integer.MIN_VALUE; + static final int MAX_SCROLL_DURATION = 2000; /** @@ -350,7 +406,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro // if we are not attached yet, mark us as requiring layout and skip return; } - if (mLayoutFrozen) { + if (mLayoutSuppressed) { mLayoutWasDefered = true; return; //we'll process updates when ice age ends. } @@ -367,7 +423,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro final ArrayList mItemDecorations = new ArrayList<>(); private final ArrayList mOnItemTouchListeners = new ArrayList<>(); - private OnItemTouchListener mActiveOnItemTouchListener; + private OnItemTouchListener mInterceptingOnItemTouchListener; boolean mIsAttached; boolean mHasFixedSize; boolean mEnableFastScroller; @@ -388,7 +444,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro */ boolean mLayoutWasDefered; - boolean mLayoutFrozen; + boolean mLayoutSuppressed; private boolean mIgnoreMotionEventTillDown; // binary OR of change events that were eaten during a layout or scroll. @@ -515,7 +571,6 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro private NestedScrollingChildHelper mScrollingChildHelper; private final int[] mScrollOffset = new int[2]; - private final int[] mScrollConsumed = new int[2]; private final int[] mNestedOffsets = new int[2]; private int topGlowOffset = 0; @@ -570,6 +625,9 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } } + // Reusable int array to be passed to method calls that mutate it in order to "return" two ints. + final int[] mReusableIntPair = new int[2]; + /** * These are views that had their a11y importance changed during a layout. We defer these events * until the end of the layout because a11y service may make sync calls back to the RV while @@ -635,15 +693,15 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } }; - public RecyclerView(Context context) { + public RecyclerView(@NonNull Context context) { this(context, null); } - public RecyclerView(Context context, @Nullable AttributeSet attrs) { + public RecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } - public RecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { + public RecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); if (attrs != null) { TypedArray a = context.obtainStyledAttributes(attrs, CLIP_TO_PADDING_ATTR, defStyle, 0); @@ -668,6 +726,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro mItemAnimator.setListener(mItemAnimatorListener); initAdapterManager(); initChildrenHelper(); + initAutofill(); // If not explicitly specified this view is important for accessibility. if (ViewCompat.getImportantForAccessibility(this) == ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO) { @@ -680,7 +739,6 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro // Create the layoutManager if specified. boolean nestedScrollingEnabled = true; - setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); // Re-set whether nested scrolling is enabled so that it is set on all API levels @@ -698,10 +756,25 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro + ", context:" + getContext(); } + /** + * If not explicitly specified, this view and its children don't support autofill. + *

    + * This is done because autofill's means of uniquely identifying views doesn't work out of the + * box with View recycling. + */ + @SuppressLint("InlinedApi") + private void initAutofill() { + if (ViewCompat.getImportantForAutofill(this) == View.IMPORTANT_FOR_AUTOFILL_AUTO) { + ViewCompat.setImportantForAutofill(this, + View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS); + } + } + /** * Returns the accessibility delegate compatibility implementation used by the RecyclerView. * @return An instance of AccessibilityDelegateCompat used by RecyclerView */ + @Nullable public RecyclerViewAccessibilityDelegate getCompatAccessibilityDelegate() { return mAccessibilityDelegate; } @@ -711,11 +784,16 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param accessibilityDelegate The accessibility delegate to be used by RecyclerView. */ public void setAccessibilityDelegateCompat( - RecyclerViewAccessibilityDelegate accessibilityDelegate) { + @Nullable RecyclerViewAccessibilityDelegate accessibilityDelegate) { mAccessibilityDelegate = accessibilityDelegate; ViewCompat.setAccessibilityDelegate(this, mAccessibilityDelegate); } + @Override + public CharSequence getAccessibilityClassName() { + return "androidx.recyclerview.widget.RecyclerView"; + } + /** * Instantiate and set a LayoutManager, if specified in the attributes. */ @@ -734,7 +812,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro classLoader = context.getClassLoader(); } Class layoutManagerClass = - classLoader.loadClass(className).asSubclass(LayoutManager.class); + Class.forName(className, false, classLoader) + .asSubclass(LayoutManager.class); Constructor constructor; Object[] constructorArgs = null; try { @@ -1080,7 +1159,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * this to false. * @see #setAdapter(Adapter) */ - public void swapAdapter(Adapter adapter, boolean removeAndRecycleExistingViews) { + public void swapAdapter(@Nullable Adapter adapter, boolean removeAndRecycleExistingViews) { // bail out if layout is frozen setLayoutFrozen(false); setAdapterInternal(adapter, true, removeAndRecycleExistingViews); @@ -1096,7 +1175,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param adapter The new adapter to set, or null to set no adapter. * @see #swapAdapter(Adapter, boolean) */ - public void setAdapter(Adapter adapter) { + public void setAdapter(@Nullable Adapter adapter) { // bail out if layout is frozen setLayoutFrozen(false); setAdapterInternal(adapter, false, true); @@ -1133,7 +1212,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param removeAndRecycleViews If true, we'll remove and recycle all existing views. If * compatibleWithPrevious is false, this parameter is ignored. */ - private void setAdapterInternal(Adapter adapter, boolean compatibleWithPrevious, + private void setAdapterInternal(@Nullable Adapter adapter, boolean compatibleWithPrevious, boolean removeAndRecycleViews) { if (mAdapter != null) { mAdapter.unregisterAdapterDataObserver(mObserver); @@ -1162,6 +1241,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return The previously set adapter * @see #setAdapter(Adapter) */ + @Nullable public Adapter getAdapter() { return mAdapter; } @@ -1176,7 +1256,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param listener Listener to register, or null to clear */ - public void setRecyclerListener(RecyclerListener listener) { + public void setRecyclerListener(@Nullable RecyclerListener listener) { mRecyclerListener = listener; } @@ -1208,7 +1288,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param listener Listener to register */ - public void addOnChildAttachStateChangeListener(OnChildAttachStateChangeListener listener) { + public void addOnChildAttachStateChangeListener( + @NonNull OnChildAttachStateChangeListener listener) { if (mOnChildAttachStateListeners == null) { mOnChildAttachStateListeners = new ArrayList<>(); } @@ -1220,7 +1301,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param listener Listener to unregister */ - public void removeOnChildAttachStateChangeListener(OnChildAttachStateChangeListener listener) { + public void removeOnChildAttachStateChangeListener( + @NonNull OnChildAttachStateChangeListener listener) { if (mOnChildAttachStateListeners == null) { return; } @@ -1249,7 +1331,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param layout LayoutManager to use */ - public void setLayoutManager(LayoutManager layout) { + public void setLayoutManager(@Nullable LayoutManager layout) { if (layout == mLayout) { return; } @@ -1407,6 +1489,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @return The currently bound LayoutManager */ + @Nullable public LayoutManager getLayoutManager() { return mLayout; } @@ -1419,6 +1502,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return The pool used to store recycled item views for reuse. * @see #setRecycledViewPool(RecycledViewPool) */ + @NonNull public RecycledViewPool getRecycledViewPool() { return mRecycler.getRecycledViewPool(); } @@ -1427,11 +1511,11 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * Recycled view pools allow multiple RecyclerViews to share a common pool of scrap views. * This can be useful if you have multiple RecyclerViews with adapters that use the same * view types, for example if you have several data sets with the same kinds of item views - * displayed by a {@link android.support.v4.view.ViewPager ViewPager}. + * displayed by a {@link androidx.viewpager.widget.ViewPager}. * * @param pool Pool to set. If this parameter is null a new pool will be created and used. */ - public void setRecycledViewPool(RecycledViewPool pool) { + public void setRecycledViewPool(@Nullable RecycledViewPool pool) { mRecycler.setRecycledViewPool(pool); } @@ -1442,7 +1526,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @see ViewCacheExtension#getViewForPositionAndType(Recycler, int, int) */ - public void setViewCacheExtension(ViewCacheExtension extension) { + public void setViewCacheExtension(@Nullable ViewCacheExtension extension) { mRecycler.setViewCacheExtension(extension); } @@ -1500,7 +1584,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param index Position in the decoration chain to insert this decoration at. If this value * is negative the decoration will be added at the end. */ - public void addItemDecoration(ItemDecoration decor, int index) { + public void addItemDecoration(@NonNull ItemDecoration decor, int index) { if (mLayout != null) { mLayout.assertNotInLayoutOrScroll("Cannot add item decoration during a scroll or" + " layout"); @@ -1529,7 +1613,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param decor Decoration to add */ - public void addItemDecoration(ItemDecoration decor) { + public void addItemDecoration(@NonNull ItemDecoration decor) { addItemDecoration(decor, -1); } @@ -1537,8 +1621,10 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * Returns an {@link ItemDecoration} previously added to this RecyclerView. * * @param index The index position of the desired ItemDecoration. - * @return the ItemDecoration at index position, or null if invalid index. + * @return the ItemDecoration at index position + * @throws IndexOutOfBoundsException on invalid index */ + @NonNull public ItemDecoration getItemDecorationAt(int index) { final int size = getItemDecorationCount(); if (index < 0 || index >= size) { @@ -1580,7 +1666,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param decor Decoration to remove * @see #addItemDecoration(ItemDecoration) */ - public void removeItemDecoration(ItemDecoration decor) { + public void removeItemDecoration(@NonNull ItemDecoration decor) { if (mLayout != null) { mLayout.assertNotInLayoutOrScroll("Cannot remove item decoration during a scroll or" + " layout"); @@ -1605,7 +1691,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param childDrawingOrderCallback The ChildDrawingOrderCallback to be used by the drawing * system. */ - public void setChildDrawingOrderCallback(ChildDrawingOrderCallback childDrawingOrderCallback) { + public void setChildDrawingOrderCallback( + @Nullable ChildDrawingOrderCallback childDrawingOrderCallback) { if (childDrawingOrderCallback == mChildDrawingOrderCallback) { return; } @@ -1622,7 +1709,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * {@link #removeOnScrollListener(OnScrollListener)} */ @Deprecated - public void setOnScrollListener(OnScrollListener listener) { + public void setOnScrollListener(@Nullable OnScrollListener listener) { mScrollListener = listener; } @@ -1633,9 +1720,9 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * Other components that take ownership of a view may call {@link #clearOnScrollListeners()} * to remove all attached listeners.

    * - * @param listener listener to set or null to clear + * @param listener listener to set */ - public void addOnScrollListener(OnScrollListener listener) { + public void addOnScrollListener(@NonNull OnScrollListener listener) { if (mScrollListeners == null) { mScrollListeners = new ArrayList<>(); } @@ -1647,7 +1734,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param listener listener to set or null to clear */ - public void removeOnScrollListener(OnScrollListener listener) { + public void removeOnScrollListener(@NonNull OnScrollListener listener) { if (mScrollListeners != null) { mScrollListeners.remove(listener); } @@ -1666,12 +1753,12 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * Convenience method to scroll to a certain position. * * RecyclerView does not implement scrolling logic, rather forwards the call to - * {@link android.support.v7.widget.RecyclerView.LayoutManager#scrollToPosition(int)} + * {@link RecyclerView.LayoutManager#scrollToPosition(int)} * @param position Scroll to this adapter position - * @see android.support.v7.widget.RecyclerView.LayoutManager#scrollToPosition(int) + * @see RecyclerView.LayoutManager#scrollToPosition(int) */ public void scrollToPosition(int position) { - if (mLayoutFrozen) { + if (mLayoutSuppressed) { return; } stopScroll(); @@ -1688,6 +1775,10 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro if (mLayout == null) { return; } + + // If we are jumping to a position, we are in fact scrolling the contents of the RV, so + // we should be sure that we are in the settling state. + setScrollState(SCROLL_STATE_SETTLING); mLayout.scrollToPosition(position); awakenScrollBars(); } @@ -1708,7 +1799,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @see LayoutManager#smoothScrollToPosition(RecyclerView, State, int) */ public void smoothScrollToPosition(int position) { - if (mLayoutFrozen) { + if (mLayoutSuppressed) { return; } if (mLayout == null) { @@ -1732,7 +1823,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro + "Call setLayoutManager with a non-null argument."); return; } - if (mLayoutFrozen) { + if (mLayoutSuppressed) { return; } final boolean canScrollHorizontal = mLayout.canScrollHorizontally(); @@ -1742,6 +1833,46 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } } + /** + * Scrolls the RV by 'dx' and 'dy' via calls to + * {@link LayoutManager#scrollHorizontallyBy(int, Recycler, State)} and + * {@link LayoutManager#scrollVerticallyBy(int, Recycler, State)}. + * + * Also sets how much of the scroll was actually consumed in 'consumed' parameter (indexes 0 and + * 1 for the x axis and y axis, respectively). + * + * This method should only be called in the context of an existing scroll operation such that + * any other necessary operations (such as a call to {@link #consumePendingUpdateOperations()}) + * is already handled. + */ + void scrollStep(int dx, int dy, @Nullable int[] consumed) { + startInterceptRequestLayout(); + onEnterLayoutOrScroll(); + + TraceCompat.beginSection(TRACE_SCROLL_TAG); + fillRemainingScrollValues(mState); + + int consumedX = 0; + int consumedY = 0; + if (dx != 0) { + consumedX = mLayout.scrollHorizontallyBy(dx, mRecycler, mState); + } + if (dy != 0) { + consumedY = mLayout.scrollVerticallyBy(dy, mRecycler, mState); + } + + TraceCompat.endSection(); + repositionShadowingViews(); + + onExitLayoutOrScroll(); + stopInterceptRequestLayout(false); + + if (consumed != null) { + consumed[0] = consumedX; + consumed[1] = consumedY; + } + } + /** * Helper method reflect data changes to the state. *

    @@ -1817,43 +1948,42 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return Whether any scroll was consumed in either direction. */ boolean scrollByInternal(int x, int y, MotionEvent ev) { - int unconsumedX = 0, unconsumedY = 0; - int consumedX = 0, consumedY = 0; + int unconsumedX = 0; + int unconsumedY = 0; + int consumedX = 0; + int consumedY = 0; consumePendingUpdateOperations(); if (mAdapter != null) { - startInterceptRequestLayout(); - onEnterLayoutOrScroll(); - TraceCompat.beginSection(TRACE_SCROLL_TAG); - fillRemainingScrollValues(mState); - if (x != 0) { - consumedX = mLayout.scrollHorizontallyBy(x, mRecycler, mState); - unconsumedX = x - consumedX; - } - if (y != 0) { - consumedY = mLayout.scrollVerticallyBy(y, mRecycler, mState); - unconsumedY = y - consumedY; - } - TraceCompat.endSection(); - repositionShadowingViews(); - onExitLayoutOrScroll(); - stopInterceptRequestLayout(false); + mReusableIntPair[0] = 0; + mReusableIntPair[1] = 0; + scrollStep(x, y, mReusableIntPair); + consumedX = mReusableIntPair[0]; + consumedY = mReusableIntPair[1]; + unconsumedX = x - consumedX; + unconsumedY = y - consumedY; } if (!mItemDecorations.isEmpty()) { invalidate(); } - if (dispatchNestedScroll(consumedX, consumedY, unconsumedX, unconsumedY, mScrollOffset, - TYPE_TOUCH)) { - // Update the last touch co-ords, taking any scroll offset into account - mLastTouchX -= mScrollOffset[0]; - mLastTouchY -= mScrollOffset[1]; - if (ev != null) { - ev.offsetLocation(mScrollOffset[0], mScrollOffset[1]); - } - mNestedOffsets[0] += mScrollOffset[0]; - mNestedOffsets[1] += mScrollOffset[1]; - } else if (getOverScrollMode() != View.OVER_SCROLL_NEVER) { + mReusableIntPair[0] = 0; + mReusableIntPair[1] = 0; + dispatchNestedScroll(consumedX, consumedY, unconsumedX, unconsumedY, mScrollOffset, + TYPE_TOUCH, mReusableIntPair); + unconsumedX -= mReusableIntPair[0]; + unconsumedY -= mReusableIntPair[1]; + + // Update the last touch co-ords, taking any scroll offset into account + mLastTouchX -= mScrollOffset[0]; + mLastTouchY -= mScrollOffset[1]; + if (ev != null) { + ev.offsetLocation(mScrollOffset[0], mScrollOffset[1]); + } + mNestedOffsets[0] += mScrollOffset[0]; + mNestedOffsets[1] += mScrollOffset[1]; + + if (getOverScrollMode() != View.OVER_SCROLL_NEVER) { if (ev != null && !MotionEventCompat.isFromSource(ev, InputDevice.SOURCE_MOUSE)) { pullGlows(ev.getX(), unconsumedX, ev.getY(), unconsumedY); } @@ -1883,7 +2013,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * LayoutManager.

    * * @return The horizontal offset of the scrollbar's thumb - * @see android.support.v7.widget.RecyclerView.LayoutManager#computeHorizontalScrollOffset + * @see RecyclerView.LayoutManager#computeHorizontalScrollOffset * (RecyclerView.State) */ @Override @@ -1956,7 +2086,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * LayoutManager.

    * * @return The vertical offset of the scrollbar's thumb - * @see android.support.v7.widget.RecyclerView.LayoutManager#computeVerticalScrollOffset + * @see RecyclerView.LayoutManager#computeVerticalScrollOffset * (RecyclerView.State) */ @Override @@ -2027,7 +2157,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro */ void startInterceptRequestLayout() { mInterceptRequestLayoutDepth++; - if (mInterceptRequestLayoutDepth == 1 && !mLayoutFrozen) { + if (mInterceptRequestLayoutDepth == 1 && !mLayoutSuppressed) { mLayoutWasDefered = false; } } @@ -2052,7 +2182,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } mInterceptRequestLayoutDepth = 1; } - if (!performLayoutChildren && !mLayoutFrozen) { + if (!performLayoutChildren && !mLayoutSuppressed) { // Reset the layout request eaten counter. // This is necessary since eatRequest calls can be nested in which case the other // call will override the inner one. @@ -2065,17 +2195,73 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } if (mInterceptRequestLayoutDepth == 1) { // when layout is frozen we should delay dispatchLayout() - if (performLayoutChildren && mLayoutWasDefered && !mLayoutFrozen + if (performLayoutChildren && mLayoutWasDefered && !mLayoutSuppressed && mLayout != null && mAdapter != null) { dispatchLayout(); } - if (!mLayoutFrozen) { + if (!mLayoutSuppressed) { mLayoutWasDefered = false; } } mInterceptRequestLayoutDepth--; } + /** + * Tells this RecyclerView to suppress all layout and scroll calls until layout + * suppression is disabled with a later call to suppressLayout(false). + * When layout suppression is disabled, a requestLayout() call is sent + * if requestLayout() was attempted while layout was being suppressed. + *

    + * In addition to the layout suppression {@link #smoothScrollBy(int, int)}, + * {@link #scrollBy(int, int)}, {@link #scrollToPosition(int)} and + * {@link #smoothScrollToPosition(int)} are dropped; TouchEvents and GenericMotionEvents are + * dropped; {@link LayoutManager#onFocusSearchFailed(View, int, Recycler, State)} will not be + * called. + * + *

    + * suppressLayout(true) does not prevent app from directly calling {@link + * LayoutManager#scrollToPosition(int)}, {@link LayoutManager#smoothScrollToPosition( + * RecyclerView, State, int)}. + *

    + * {@link #setAdapter(Adapter)} and {@link #swapAdapter(Adapter, boolean)} will automatically + * stop suppressing. + *

    + * Note: Running ItemAnimator is not stopped automatically, it's caller's + * responsibility to call ItemAnimator.end(). + * + * @param suppress true to suppress layout and scroll, false to re-enable. + */ + public final void suppressLayout(boolean suppress) { + if (suppress != mLayoutSuppressed) { + assertNotInLayoutOrScroll("Do not suppressLayout in layout or scroll"); + if (!suppress) { + mLayoutSuppressed = false; + if (mLayoutWasDefered && mLayout != null && mAdapter != null) { + requestLayout(); + } + mLayoutWasDefered = false; + } else { + final long now = SystemClock.uptimeMillis(); + MotionEvent cancelEvent = MotionEvent.obtain(now, now, + MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); + onTouchEvent(cancelEvent); + mLayoutSuppressed = true; + mIgnoreMotionEventTillDown = true; + stopScroll(); + } + } + } + + /** + * Returns whether layout and scroll calls on this container are currently being + * suppressed, due to an earlier call to {@link #suppressLayout(boolean)}. + * + * @return true if layout and scroll are currently suppressed, false otherwise. + */ + public final boolean isLayoutSuppressed() { + return mLayoutSuppressed; + } + /** * Enable or disable layout and scroll. After setLayoutFrozen(true) is called, * Layout requests will be postponed until setLayoutFrozen(false) is called; @@ -2097,36 +2283,37 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * responsibility to call ItemAnimator.end(). * * @param frozen true to freeze layout and scroll, false to re-enable. + * + * @deprecated Use {@link #suppressLayout(boolean)}. */ + @Deprecated public void setLayoutFrozen(boolean frozen) { - if (frozen != mLayoutFrozen) { - assertNotInLayoutOrScroll("Do not setLayoutFrozen in layout or scroll"); - if (!frozen) { - mLayoutFrozen = false; - if (mLayoutWasDefered && mLayout != null && mAdapter != null) { - requestLayout(); - } - mLayoutWasDefered = false; - } else { - final long now = SystemClock.uptimeMillis(); - MotionEvent cancelEvent = MotionEvent.obtain(now, now, - MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); - onTouchEvent(cancelEvent); - mLayoutFrozen = true; - mIgnoreMotionEventTillDown = true; - stopScroll(); - } - } + suppressLayout(frozen); } /** - * Returns true if layout and scroll are frozen. - * * @return true if layout and scroll are frozen - * @see #setLayoutFrozen(boolean) + * + * @deprecated Use {@link #isLayoutSuppressed()}. */ + @Deprecated public boolean isLayoutFrozen() { - return mLayoutFrozen; + return isLayoutSuppressed(); + } + + /** + * @deprecated Use {@link #setItemAnimator(ItemAnimator)} ()}. + */ + @Deprecated + @Override + public void setLayoutTransition(LayoutTransition transition) { + if (transition == null) { + super.setLayoutTransition(null); + } else { + throw new IllegalArgumentException("Providing a LayoutTransition into RecyclerView is " + + "not supported. Please use setItemAnimator() instead for animating changes " + + "to the items in this RecyclerView"); + } } /** @@ -2135,7 +2322,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param dx Pixels to scroll horizontally * @param dy Pixels to scroll vertically */ - public void smoothScrollBy(int dx, int dy) { + public void smoothScrollBy(@Px int dx, @Px int dy) { smoothScrollBy(dx, dy, null); } @@ -2147,13 +2334,13 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param interpolator {@link Interpolator} to be used for scrolling. If it is * {@code null}, RecyclerView is going to use the default interpolator. */ - public void smoothScrollBy(int dx, int dy, Interpolator interpolator) { + public void smoothScrollBy(@Px int dx, @Px int dy, @Nullable Interpolator interpolator) { if (mLayout == null) { Log.e(TAG, "Cannot smooth scroll without a LayoutManager set. " + "Call setLayoutManager with a non-null argument."); return; } - if (mLayoutFrozen) { + if (mLayoutSuppressed) { return; } if (!mLayout.canScrollHorizontally()) { @@ -2163,7 +2350,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro dy = 0; } if (dx != 0 || dy != 0) { - mViewFlinger.smoothScrollBy(dx, dy, interpolator); + mViewFlinger.smoothScrollBy(dx, dy, UNDEFINED_DURATION, interpolator); } } @@ -2186,7 +2373,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro + "Call setLayoutManager with a non-null argument."); return false; } - if (mLayoutFrozen) { + if (mLayoutSuppressed) { return false; } @@ -2348,18 +2535,26 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro void absorbGlows(int velocityX, int velocityY) { if (velocityX < 0) { ensureLeftGlow(); - mLeftGlow.onAbsorb(-velocityX); + if (mLeftGlow.isFinished()) { + mLeftGlow.onAbsorb(-velocityX); + } } else if (velocityX > 0) { ensureRightGlow(); - mRightGlow.onAbsorb(velocityX); + if (mRightGlow.isFinished()) { + mRightGlow.onAbsorb(velocityX); + } } if (velocityY < 0) { ensureTopGlow(); - mTopGlow.onAbsorb(-velocityY); + if (mTopGlow.isFinished()) { + mTopGlow.onAbsorb(-velocityY); + } } else if (velocityY > 0) { ensureBottomGlow(); - mBottomGlow.onAbsorb(velocityY); + if (mBottomGlow.isFinished()) { + mBottomGlow.onAbsorb(velocityY); + } } if (velocityX != 0 || velocityY != 0) { @@ -2437,6 +2632,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param edgeEffectFactory The {@link EdgeEffectFactory} instance. */ public void setEdgeEffectFactory(@NonNull EdgeEffectFactory edgeEffectFactory) { + Preconditions.checkNotNull(edgeEffectFactory); mEdgeEffectFactory = edgeEffectFactory; invalidateGlows(); } @@ -2448,6 +2644,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return The previously set {@link EdgeEffectFactory} * @see #setEdgeEffectFactory(EdgeEffectFactory) */ + @NonNull public EdgeEffectFactory getEdgeEffectFactory() { return mEdgeEffectFactory; } @@ -2489,7 +2686,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro return result; } final boolean canRunFocusFailure = mAdapter != null && mLayout != null - && !isComputingLayout() && !mLayoutFrozen; + && !isComputingLayout() && !mLayoutSuppressed; final FocusFinder ff = FocusFinder.getInstance(); if (canRunFocusFailure @@ -2814,7 +3011,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param listener Listener to add * @see SimpleOnItemTouchListener */ - public void addOnItemTouchListener(OnItemTouchListener listener) { + public void addOnItemTouchListener(@NonNull OnItemTouchListener listener) { mOnItemTouchListeners.add(listener); } @@ -2823,70 +3020,91 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param listener Listener to remove */ - public void removeOnItemTouchListener(OnItemTouchListener listener) { + public void removeOnItemTouchListener(@NonNull OnItemTouchListener listener) { mOnItemTouchListeners.remove(listener); - if (mActiveOnItemTouchListener == listener) { - mActiveOnItemTouchListener = null; + if (mInterceptingOnItemTouchListener == listener) { + mInterceptingOnItemTouchListener = null; } } - private boolean dispatchOnItemTouchIntercept(MotionEvent e) { - final int action = e.getAction(); - if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_DOWN) { - mActiveOnItemTouchListener = null; - } + /** + * Dispatches the motion event to the intercepting OnItemTouchListener or provides opportunity + * for OnItemTouchListeners to intercept. + * @param e The MotionEvent + * @return True if handled by an intercepting OnItemTouchListener. + */ + private boolean dispatchToOnItemTouchListeners(MotionEvent e) { + // OnItemTouchListeners should receive calls to their methods in the same pattern that + // ViewGroups do. That pattern is a bit confusing, which in turn makes the below code a + // bit confusing. Here are rules for the pattern: + // + // 1. A single MotionEvent should not be passed to either OnInterceptTouchEvent or + // OnTouchEvent twice. + // 2. ACTION_DOWN MotionEvents may be passed to both onInterceptTouchEvent and + // onTouchEvent. + // 3. All other MotionEvents should be passed to either onInterceptTouchEvent or + // onTouchEvent, not both. + + // Side Note: We don't currently perfectly mimic how MotionEvents work in the view system. + // If we were to do so, for every MotionEvent, any OnItemTouchListener that is before the + // intercepting OnItemTouchEvent should still have a chance to intercept, and if it does, + // the previously intercepting OnItemTouchEvent should get an ACTION_CANCEL event. + + if (mInterceptingOnItemTouchListener == null) { + if (e.getAction() == MotionEvent.ACTION_DOWN) { + return false; + } + return findInterceptingOnItemTouchListener(e); + } else { + mInterceptingOnItemTouchListener.onTouchEvent(this, e); + final int action = e.getAction(); + if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { + mInterceptingOnItemTouchListener = null; + } + return true; + } + } + + /** + * Looks for an OnItemTouchListener that wants to intercept. + * + *

    Calls {@link OnItemTouchListener#onInterceptTouchEvent(RecyclerView, MotionEvent)} on each + * of the registered {@link OnItemTouchListener}s, passing in the + * MotionEvent. If one returns true and the action is not ACTION_CANCEL, saves the intercepting + * OnItemTouchListener to be called for future {@link RecyclerView#onTouchEvent(MotionEvent)} + * and immediately returns true. If none want to intercept or the action is ACTION_CANCEL, + * returns false. + * + * @param e The MotionEvent + * @return true if an OnItemTouchListener is saved as intercepting. + */ + private boolean findInterceptingOnItemTouchListener(MotionEvent e) { + int action = e.getAction(); final int listenerCount = mOnItemTouchListeners.size(); for (int i = 0; i < listenerCount; i++) { final OnItemTouchListener listener = mOnItemTouchListeners.get(i); if (listener.onInterceptTouchEvent(this, e) && action != MotionEvent.ACTION_CANCEL) { - mActiveOnItemTouchListener = listener; + mInterceptingOnItemTouchListener = listener; return true; } } return false; } - private boolean dispatchOnItemTouch(MotionEvent e) { - final int action = e.getAction(); - if (mActiveOnItemTouchListener != null) { - if (action == MotionEvent.ACTION_DOWN) { - // Stale state from a previous gesture, we're starting a new one. Clear it. - mActiveOnItemTouchListener = null; - } else { - mActiveOnItemTouchListener.onTouchEvent(this, e); - if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { - // Clean up for the next gesture. - mActiveOnItemTouchListener = null; - } - return true; - } - } - - // Listeners will have already received the ACTION_DOWN via dispatchOnItemTouchIntercept - // as called from onInterceptTouchEvent; skip it. - if (action != MotionEvent.ACTION_DOWN) { - final int listenerCount = mOnItemTouchListeners.size(); - for (int i = 0; i < listenerCount; i++) { - final OnItemTouchListener listener = mOnItemTouchListeners.get(i); - if (listener.onInterceptTouchEvent(this, e)) { - mActiveOnItemTouchListener = listener; - return true; - } - } - } - return false; - } - @Override public boolean onInterceptTouchEvent(MotionEvent e) { - if (mLayoutFrozen) { - // When layout is frozen, RV does not intercept the motion event. + if (mLayoutSuppressed) { + // When layout is suppressed, RV does not intercept the motion event. // A child view e.g. a button may still get the click. return false; } - if (dispatchOnItemTouchIntercept(e)) { - cancelTouch(); + + // Clear the active onInterceptTouchListener. None should be set at this time, and if one + // is, it's because some other code didn't follow the standard contract. + mInterceptingOnItemTouchListener = null; + if (findInterceptingOnItemTouchListener(e)) { + cancelScroll(); return true; } @@ -2917,6 +3135,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro if (mScrollState == SCROLL_STATE_SETTLING) { getParent().requestDisallowInterceptTouchEvent(true); setScrollState(SCROLL_STATE_DRAGGING); + stopNestedScroll(TYPE_NON_TOUCH); } // Clear the nested offsets @@ -2976,7 +3195,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } break; case MotionEvent.ACTION_CANCEL: { - cancelTouch(); + cancelScroll(); } } return mScrollState == SCROLL_STATE_DRAGGING; @@ -2994,11 +3213,11 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro @Override public boolean onTouchEvent(MotionEvent e) { - if (mLayoutFrozen || mIgnoreMotionEventTillDown) { + if (mLayoutSuppressed || mIgnoreMotionEventTillDown) { return false; } - if (dispatchOnItemTouch(e)) { - cancelTouch(); + if (dispatchToOnItemTouchListeners(e)) { + cancelScroll(); return true; } @@ -3058,9 +3277,11 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro int dx = mLastTouchX - x; int dy = mLastTouchY - y; - if (dispatchNestedPreScroll(dx, dy, mScrollConsumed, mScrollOffset, TYPE_TOUCH)) { - dx -= mScrollConsumed[0]; - dy -= mScrollConsumed[1]; + mReusableIntPair[0] = 0; + mReusableIntPair[1] = 0; + if (dispatchNestedPreScroll(dx, dy, mReusableIntPair, mScrollOffset, TYPE_TOUCH)) { + dx -= mReusableIntPair[0]; + dy -= mReusableIntPair[1]; vtev.offsetLocation(mScrollOffset[0], mScrollOffset[1]); // Updated the nested offsets mNestedOffsets[0] += mScrollOffset[0]; @@ -3121,11 +3342,11 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro if (!((xvel != 0 || yvel != 0) && fling((int) xvel, (int) yvel))) { setScrollState(SCROLL_STATE_IDLE); } - resetTouch(); + resetScroll(); } break; case MotionEvent.ACTION_CANCEL: { - cancelTouch(); + cancelScroll(); } break; } @@ -3137,7 +3358,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro return true; } - private void resetTouch() { + private void resetScroll() { if (mVelocityTracker != null) { mVelocityTracker.clear(); } @@ -3145,8 +3366,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro releaseGlows(); } - private void cancelTouch() { - resetTouch(); + private void cancelScroll() { + resetScroll(); setScrollState(SCROLL_STATE_IDLE); } @@ -3166,10 +3387,10 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro if (mLayout == null) { return false; } - if (mLayoutFrozen) { + if (mLayoutSuppressed) { return false; } - if (event.getAction() == MotionEventCompat.ACTION_SCROLL) { + if (event.getAction() == MotionEvent.ACTION_SCROLL) { final float vScroll, hScroll; if ((event.getSource() & InputDeviceCompat.SOURCE_CLASS_POINTER) != 0) { if (mLayout.canScrollVertically()) { @@ -3339,7 +3560,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param animator The ItemAnimator being set. If null, no animations will occur * when changes occur to the items in this RecyclerView. */ - public void setItemAnimator(ItemAnimator animator) { + public void setItemAnimator(@Nullable ItemAnimator animator) { if (mItemAnimator != null) { mItemAnimator.endAnimations(); mItemAnimator.setListener(null); @@ -3382,7 +3603,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro mEatenAccessibilityChangeFlags = 0; if (flags != 0 && isAccessibilityEnabled()) { final AccessibilityEvent event = AccessibilityEvent.obtain(); - event.setEventType(AccessibilityEventCompat.TYPE_WINDOW_CONTENT_CHANGED); + event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); AccessibilityEventCompat.setContentChangeTypes(event, flags); sendAccessibilityEventUnchecked(event); } @@ -3442,6 +3663,12 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro super.sendAccessibilityEventUnchecked(event); } + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + onPopulateAccessibilityEvent(event); + return true; + } + /** * Gets the current ItemAnimator for this RecyclerView. A null return value * indicates that there is no animator and that item changes will happen without @@ -3451,6 +3678,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return ItemAnimator The current ItemAnimator. If null, no animations will occur * when changes occur to the items in this RecyclerView. */ + @Nullable public ItemAnimator getItemAnimator() { return mItemAnimator; } @@ -3712,7 +3940,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro final void fillRemainingScrollValues(State state) { if (getScrollState() == SCROLL_STATE_SETTLING) { - final OverScroller scroller = mViewFlinger.mScroller; + final OverScroller scroller = mViewFlinger.mOverScroller; state.mRemainingScrollHorizontal = scroller.getFinalX() - scroller.getCurrX(); state.mRemainingScrollVertical = scroller.getFinalY() - scroller.getCurrY(); } else { @@ -4107,7 +4335,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro @Override public void requestLayout() { - if (mInterceptRequestLayoutDepth == 0 && !mLayoutFrozen) { + if (mInterceptRequestLayoutDepth == 0 && !mLayoutSuppressed) { super.requestLayout(); } else { mLayoutWasDefered = true; @@ -4465,7 +4693,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param child Child of this RecyclerView to query for its ViewHolder * @return The child view's ViewHolder */ - public ViewHolder getChildViewHolder(View child) { + public ViewHolder getChildViewHolder(@NonNull View child) { final ViewParent parent = child.getParent(); if (parent != null && parent != this) { throw new IllegalArgumentException("View " + child + " is not a direct child of " @@ -4488,7 +4716,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @see #findContainingViewHolder(View) */ @Nullable - public View findContainingItemView(View view) { + public View findContainingItemView(@NonNull View view) { ViewParent parent = view.getParent(); while (parent != null && parent != this && parent instanceof View) { view = (View) parent; @@ -4506,7 +4734,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * descendant of this RecyclerView. */ @Nullable - public ViewHolder findContainingViewHolder(View view) { + public ViewHolder findContainingViewHolder(@NonNull View view) { View itemView = findContainingItemView(view); return itemView == null ? null : getChildViewHolder(itemView); } @@ -4524,7 +4752,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * {@link #getChildLayoutPosition(View)}. */ @Deprecated - public int getChildPosition(View child) { + public int getChildPosition(@NonNull View child) { return getChildAdapterPosition(child); } @@ -4534,7 +4762,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param child Child View to query * @return Adapter position corresponding to the given view or {@link #NO_POSITION} */ - public int getChildAdapterPosition(View child) { + public int getChildAdapterPosition(@NonNull View child) { final ViewHolder holder = getChildViewHolderInt(child); return holder != null ? holder.getAdapterPosition() : NO_POSITION; } @@ -4549,7 +4777,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return Adapter position of the given View as of last layout pass or {@link #NO_POSITION} if * the View is representing a removed item. */ - public int getChildLayoutPosition(View child) { + public int getChildLayoutPosition(@NonNull View child) { final ViewHolder holder = getChildViewHolderInt(child); return holder != null ? holder.getLayoutPosition() : NO_POSITION; } @@ -4560,7 +4788,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param child Child View to query * @return Item id corresponding to the given view or {@link #NO_ID} */ - public long getChildItemId(View child) { + public long getChildItemId(@NonNull View child) { if (mAdapter == null || !mAdapter.hasStableIds()) { return NO_ID; } @@ -4573,6 +4801,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * {@link #findViewHolderForAdapterPosition(int)} */ @Deprecated + @Nullable public ViewHolder findViewHolderForPosition(int position) { return findViewHolderForPosition(position, false); } @@ -4596,6 +4825,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param position The position of the item in the data set of the adapter * @return The ViewHolder at position or null if there is no such item */ + @Nullable public ViewHolder findViewHolderForLayoutPosition(int position) { return findViewHolderForPosition(position, false); } @@ -4617,6 +4847,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param position The position of the item in the data set of the adapter * @return The ViewHolder at position or null if there is no such item */ + @Nullable public ViewHolder findViewHolderForAdapterPosition(int position) { if (mDataSetHasChangedAfterLayout) { return null; @@ -4638,6 +4869,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro return hidden; } + @Nullable ViewHolder findViewHolderForPosition(int position, boolean checkNewPosition) { final int childCount = mChildHelper.getUnfilteredChildCount(); ViewHolder hidden = null; @@ -4704,6 +4936,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param y Vertical position in pixels to search * @return The child view under (x, y) or null if no matching child is found */ + @Nullable public View findChildViewUnder(float x, float y) { final int count = mChildHelper.getChildCount(); for (int i = count - 1; i >= 0; i--) { @@ -4731,7 +4964,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param dy Vertical pixel offset to apply to the bounds of all child views */ - public void offsetChildrenVertical(int dy) { + public void offsetChildrenVertical(@Px int dy) { final int childCount = mChildHelper.getChildCount(); for (int i = 0; i < childCount; i++) { mChildHelper.getChildAt(i).offsetTopAndBottom(dy); @@ -4748,7 +4981,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param child Child view that is now attached to this RecyclerView and its associated window */ - public void onChildAttachedToWindow(View child) { + public void onChildAttachedToWindow(@NonNull View child) { } /** @@ -4760,7 +4993,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param child Child view that is now detached from this RecyclerView and its associated window */ - public void onChildDetachedFromWindow(View child) { + public void onChildDetachedFromWindow(@NonNull View child) { } /** @@ -4769,7 +5002,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param dx Horizontal pixel offset to apply to the bounds of all child views */ - public void offsetChildrenHorizontal(int dx) { + public void offsetChildrenHorizontal(@Px int dx) { final int childCount = mChildHelper.getChildCount(); for (int i = 0; i < childCount; i++) { mChildHelper.getChildAt(i).offsetLeftAndRight(dx); @@ -4783,7 +5016,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param outBounds A rect that will receive the bounds of the element including its * decoration and margins. */ - public void getDecoratedBoundsWithMargins(View view, Rect outBounds) { + public void getDecoratedBoundsWithMargins(@NonNull View view, @NonNull Rect outBounds) { getDecoratedBoundsWithMarginsInt(view, outBounds); } @@ -4841,7 +5074,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param dx horizontal distance scrolled in pixels * @param dy vertical distance scrolled in pixels */ - public void onScrolled(int dx, int dy) { + public void onScrolled(@Px int dx, @Px int dy) { // Do nothing } @@ -4926,10 +5159,9 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro class ViewFlinger implements Runnable { private int mLastFlingX; private int mLastFlingY; - private OverScroller mScroller; + OverScroller mOverScroller; Interpolator mInterpolator = sQuinticInterpolator; - // When set to true, postOnAnimation callbacks are delayed until the run method completes private boolean mEatRunOnAnimationRequest = false; @@ -4937,7 +5169,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro private boolean mReSchedulePostAnimationCallback = false; ViewFlinger() { - mScroller = new OverScroller(getContext(), sQuinticInterpolator); + mOverScroller = new OverScroller(getContext(), sQuinticInterpolator); } @Override @@ -4946,48 +5178,61 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro stop(); return; // no layout, cannot scroll. } - disableRunOnAnimationRequests(); + + mReSchedulePostAnimationCallback = false; + mEatRunOnAnimationRequest = true; + consumePendingUpdateOperations(); - // keep a local reference so that if it is changed during onAnimation method, it won't + + // TODO(72745539): After reviewing the code, it seems to me we may actually want to + // update the reference to the OverScroller after onAnimation. It looks to me like + // it is possible that a new OverScroller could be created (due to a new Interpolator + // being used), when the current OverScroller knows it's done after + // scroller.computeScrollOffset() is called. If that happens, and we don't update the + // reference, it seems to me that we could prematurely stop the newly created scroller + // due to setScrollState(SCROLL_STATE_IDLE) being called below. + + // Keep a local reference so that if it is changed during onAnimation method, it won't // cause unexpected behaviors - final OverScroller scroller = mScroller; - final SmoothScroller smoothScroller = mLayout.mSmoothScroller; + final OverScroller scroller = mOverScroller; if (scroller.computeScrollOffset()) { - final int[] scrollConsumed = mScrollConsumed; final int x = scroller.getCurrX(); final int y = scroller.getCurrY(); - int dx = x - mLastFlingX; - int dy = y - mLastFlingY; - int hresult = 0; - int vresult = 0; + int unconsumedX = x - mLastFlingX; + int unconsumedY = y - mLastFlingY; mLastFlingX = x; mLastFlingY = y; - int overscrollX = 0, overscrollY = 0; + int consumedX = 0; + int consumedY = 0; - if (dispatchNestedPreScroll(dx, dy, scrollConsumed, null, TYPE_NON_TOUCH)) { - dx -= scrollConsumed[0]; - dy -= scrollConsumed[1]; + // Nested Pre Scroll + mReusableIntPair[0] = 0; + mReusableIntPair[1] = 0; + if (dispatchNestedPreScroll(unconsumedX, unconsumedY, mReusableIntPair, null, + TYPE_NON_TOUCH)) { + unconsumedX -= mReusableIntPair[0]; + unconsumedY -= mReusableIntPair[1]; } + // Based on movement, we may want to trigger the hiding of existing over scroll + // glows. + if (getOverScrollMode() != View.OVER_SCROLL_NEVER) { + considerReleasingGlowsOnScroll(unconsumedX, unconsumedY); + } + + // Local Scroll if (mAdapter != null) { - startInterceptRequestLayout(); - onEnterLayoutOrScroll(); - TraceCompat.beginSection(TRACE_SCROLL_TAG); - fillRemainingScrollValues(mState); - if (dx != 0) { - hresult = mLayout.scrollHorizontallyBy(dx, mRecycler, mState); - overscrollX = dx - hresult; - } - if (dy != 0) { - vresult = mLayout.scrollVerticallyBy(dy, mRecycler, mState); - overscrollY = dy - vresult; - } - TraceCompat.endSection(); - repositionShadowingViews(); - - onExitLayoutOrScroll(); - stopInterceptRequestLayout(false); + mReusableIntPair[0] = 0; + mReusableIntPair[1] = 0; + scrollStep(unconsumedX, unconsumedY, mReusableIntPair); + consumedX = mReusableIntPair[0]; + consumedY = mReusableIntPair[1]; + unconsumedX -= consumedX; + unconsumedY -= consumedY; + // If SmoothScroller exists, this ViewFlinger was started by it, so we must + // report back to SmoothScroller. + SmoothScroller smoothScroller = mLayout.mSmoothScroller; if (smoothScroller != null && !smoothScroller.isPendingInitialRun() && smoothScroller.isRunning()) { final int adapterSize = mState.getItemCount(); @@ -4995,93 +5240,87 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro smoothScroller.stop(); } else if (smoothScroller.getTargetPosition() >= adapterSize) { smoothScroller.setTargetPosition(adapterSize - 1); - smoothScroller.onAnimation(dx - overscrollX, dy - overscrollY); + smoothScroller.onAnimation(consumedX, consumedY); } else { - smoothScroller.onAnimation(dx - overscrollX, dy - overscrollY); + smoothScroller.onAnimation(consumedX, consumedY); } } } + if (!mItemDecorations.isEmpty()) { invalidate(); } - if (getOverScrollMode() != View.OVER_SCROLL_NEVER) { - considerReleasingGlowsOnScroll(dx, dy); - } - if (!dispatchNestedScroll(hresult, vresult, overscrollX, overscrollY, null, - TYPE_NON_TOUCH) - && (overscrollX != 0 || overscrollY != 0)) { - final int vel = (int) scroller.getCurrVelocity(); + // Nested Post Scroll + mReusableIntPair[0] = 0; + mReusableIntPair[1] = 0; + dispatchNestedScroll(consumedX, consumedY, unconsumedX, unconsumedY, null, + TYPE_NON_TOUCH, mReusableIntPair); + unconsumedX -= mReusableIntPair[0]; + unconsumedY -= mReusableIntPair[1]; - int velX = 0; - if (overscrollX != x) { - velX = overscrollX < 0 ? -vel : overscrollX > 0 ? vel : 0; - } - - int velY = 0; - if (overscrollY != y) { - velY = overscrollY < 0 ? -vel : overscrollY > 0 ? vel : 0; - } - - if (getOverScrollMode() != View.OVER_SCROLL_NEVER) { - absorbGlows(velX, velY); - } - if ((velX != 0 || overscrollX == x || scroller.getFinalX() == 0) - && (velY != 0 || overscrollY == y || scroller.getFinalY() == 0)) { - scroller.abortAnimation(); - } - } - if (hresult != 0 || vresult != 0) { - dispatchOnScrolled(hresult, vresult); + if (consumedX != 0 || consumedY != 0) { + dispatchOnScrolled(consumedX, consumedY); } if (!awakenScrollBars()) { invalidate(); } - final boolean fullyConsumedVertical = dy != 0 && mLayout.canScrollVertically() - && vresult == dy; - final boolean fullyConsumedHorizontal = dx != 0 && mLayout.canScrollHorizontally() - && hresult == dx; - final boolean fullyConsumedAny = (dx == 0 && dy == 0) || fullyConsumedHorizontal - || fullyConsumedVertical; + // We are done scrolling if scroller is finished, or for both the x and y dimension, + // we are done scrolling or we can't scroll further (we know we can't scroll further + // when we have unconsumed scroll distance). It's possible that we don't need + // to also check for scroller.isFinished() at all, but no harm in doing so in case + // of old bugs in Overscroller. + boolean scrollerFinishedX = scroller.getCurrX() == scroller.getFinalX(); + boolean scrollerFinishedY = scroller.getCurrY() == scroller.getFinalY(); + final boolean doneScrolling = scroller.isFinished() + || ((scrollerFinishedX || unconsumedX != 0) + && (scrollerFinishedY || unconsumedY != 0)); + + // Get the current smoothScroller. It may have changed by this point and we need to + // make sure we don't stop scrolling if it has changed and it's pending an initial + // run. + SmoothScroller smoothScroller = mLayout.mSmoothScroller; + boolean smoothScrollerPending = + smoothScroller != null && smoothScroller.isPendingInitialRun(); + + if (!smoothScrollerPending && doneScrolling) { + // If we are done scrolling and the layout's SmoothScroller is not pending, + // do the things we do at the end of a scroll and don't postOnAnimation. + + if (getOverScrollMode() != View.OVER_SCROLL_NEVER) { + final int vel = (int) scroller.getCurrVelocity(); + int velX = unconsumedX < 0 ? -vel : unconsumedX > 0 ? vel : 0; + int velY = unconsumedY < 0 ? -vel : unconsumedY > 0 ? vel : 0; + absorbGlows(velX, velY); + } - if (scroller.isFinished() || (!fullyConsumedAny - && !hasNestedScrollingParent(TYPE_NON_TOUCH))) { - // setting state to idle will stop this. - setScrollState(SCROLL_STATE_IDLE); if (ALLOW_THREAD_GAP_WORK) { mPrefetchRegistry.clearPrefetchPositions(); } - stopNestedScroll(TYPE_NON_TOUCH); } else { + // Otherwise continue the scroll. + postOnAnimation(); if (mGapWorker != null) { - mGapWorker.postFromTraversal(RecyclerView.this, dx, dy); + mGapWorker.postFromTraversal(RecyclerView.this, unconsumedX, unconsumedY); } } } + + SmoothScroller smoothScroller = mLayout.mSmoothScroller; // call this after the onAnimation is complete not to have inconsistent callbacks etc. - if (smoothScroller != null) { - if (smoothScroller.isPendingInitialRun()) { - smoothScroller.onAnimation(0, 0); - } - if (!mReSchedulePostAnimationCallback) { - smoothScroller.stop(); //stop if it does not trigger any scroll - } + if (smoothScroller != null && smoothScroller.isPendingInitialRun()) { + smoothScroller.onAnimation(0, 0); } - enableRunOnAnimationRequests(); - } - private void disableRunOnAnimationRequests() { - mReSchedulePostAnimationCallback = false; - mEatRunOnAnimationRequest = true; - } - - private void enableRunOnAnimationRequests() { mEatRunOnAnimationRequest = false; if (mReSchedulePostAnimationCallback) { - postOnAnimation(); + internalPostOnAnimation(); + } else { + setScrollState(SCROLL_STATE_IDLE); + stopNestedScroll(TYPE_NON_TOUCH); } } @@ -5089,25 +5328,63 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro if (mEatRunOnAnimationRequest) { mReSchedulePostAnimationCallback = true; } else { - removeCallbacks(this); - ViewCompat.postOnAnimation(RecyclerView.this, this); + internalPostOnAnimation(); } } + private void internalPostOnAnimation() { + removeCallbacks(this); + ViewCompat.postOnAnimation(RecyclerView.this, this); + } + public void fling(int velocityX, int velocityY) { setScrollState(SCROLL_STATE_SETTLING); mLastFlingX = mLastFlingY = 0; - mScroller.fling(0, 0, velocityX, velocityY, + // Because you can't define a custom interpolator for flinging, we should make sure we + // reset ourselves back to the teh default interpolator in case a different call + // changed our interpolator. + if (mInterpolator != sQuinticInterpolator) { + mInterpolator = sQuinticInterpolator; + mOverScroller = new OverScroller(getContext(), sQuinticInterpolator); + } + mOverScroller.fling(0, 0, velocityX, velocityY, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE); postOnAnimation(); } - public void smoothScrollBy(int dx, int dy) { - smoothScrollBy(dx, dy, 0, 0); - } + public void smoothScrollBy(int dx, int dy, int duration, + @Nullable Interpolator interpolator) { - public void smoothScrollBy(int dx, int dy, int vx, int vy) { - smoothScrollBy(dx, dy, computeScrollDuration(dx, dy, vx, vy)); + // Handle cases where parameter values aren't defined. + if (duration == UNDEFINED_DURATION) { + duration = computeScrollDuration(dx, dy, 0, 0); + } + if (interpolator == null) { + interpolator = sQuinticInterpolator; + } + + // If the Interpolator has changed, create a new OverScroller with the new + // interpolator. + if (mInterpolator != interpolator) { + mInterpolator = interpolator; + mOverScroller = new OverScroller(getContext(), interpolator); + } + + // Reset the last fling information. + mLastFlingX = mLastFlingY = 0; + + // Set to settling state and start scrolling. + setScrollState(SCROLL_STATE_SETTLING); + mOverScroller.startScroll(0, 0, dx, dy, duration); + + if (Build.VERSION.SDK_INT < 23) { + // b/64931938 before API 23, startScroll() does not reset getCurX()/getCurY() + // to start values, which causes fillRemainingScrollValues() put in obsolete values + // for LayoutManager.onLayoutChildren(). + mOverScroller.computeScrollOffset(); + } + + postOnAnimation(); } private float distanceInfluenceForSnapDuration(float f) { @@ -5138,35 +5415,9 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro return Math.min(duration, MAX_SCROLL_DURATION); } - public void smoothScrollBy(int dx, int dy, int duration) { - smoothScrollBy(dx, dy, duration, sQuinticInterpolator); - } - - public void smoothScrollBy(int dx, int dy, Interpolator interpolator) { - smoothScrollBy(dx, dy, computeScrollDuration(dx, dy, 0, 0), - interpolator == null ? sQuinticInterpolator : interpolator); - } - - public void smoothScrollBy(int dx, int dy, int duration, Interpolator interpolator) { - if (mInterpolator != interpolator) { - mInterpolator = interpolator; - mScroller = new OverScroller(getContext(), interpolator); - } - setScrollState(SCROLL_STATE_SETTLING); - mLastFlingX = mLastFlingY = 0; - mScroller.startScroll(0, 0, dx, dy, duration); - if (Build.VERSION.SDK_INT < 23) { - // b/64931938 before API 23, startScroll() does not reset getCurX()/getCurY() - // to start values, which causes fillRemainingScrollValues() put in obsolete values - // for LayoutManager.onLayoutChildren(). - mScroller.computeScrollOffset(); - } - postOnAnimation(); - } - public void stop() { removeCallbacks(this); - mScroller.abortAnimation(); + mOverScroller.abortAnimation(); } } @@ -5281,7 +5532,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro /** * Create a new EdgeEffect for the provided direction. */ - protected @NonNull EdgeEffect createEdgeEffect(RecyclerView view, + protected @NonNull EdgeEffect createEdgeEffect(@NonNull RecyclerView view, @EdgeDirection int direction) { return new EdgeEffect(view.getContext()); } @@ -5367,7 +5618,11 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro final ScrapData scrapData = mScrap.get(viewType); if (scrapData != null && !scrapData.mScrapHeap.isEmpty()) { final ArrayList scrapHeap = scrapData.mScrapHeap; - return scrapHeap.remove(scrapHeap.size() - 1); + for (int i = scrapHeap.size() - 1; i >= 0; i--) { + if (!scrapHeap.get(i).isAttachedToTransitionOverlay()) { + return scrapHeap.remove(i); + } + } } return null; } @@ -5437,7 +5692,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro return expectedDurationNs == 0 || (approxCurrentNs + expectedDurationNs < deadlineNs); } - void attach(Adapter adapter) { + void attach() { mAttachCount++; } @@ -5466,7 +5721,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro clear(); } if (newAdapter != null) { - attach(newAdapter); + attach(); } } @@ -5605,6 +5860,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @return List of ViewHolders in the scrap list. */ + @NonNull public List getScrapList() { return mUnmodifiableAttachedScrap; } @@ -5656,7 +5912,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * bind the holder. * @return */ - private boolean tryBindViewHolderByDeadline(ViewHolder holder, int offsetPosition, + private boolean tryBindViewHolderByDeadline(@NonNull ViewHolder holder, int offsetPosition, int position, long deadlineNs) { holder.mOwnerRecyclerView = RecyclerView.this; final int viewType = holder.getItemViewType(); @@ -5691,7 +5947,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param view The view to update. * @param position The position of the item to bind to this View. */ - public void bindViewToPosition(View view, int position) { + public void bindViewToPosition(@NonNull View view, int position) { ViewHolder holder = getChildViewHolderInt(view); if (holder == null) { throw new IllegalArgumentException("The view does not have a ViewHolder. You cannot" @@ -5766,6 +6022,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param position Position to obtain a view for * @return A view representing the data at position from adapter */ + @NonNull public View getViewForPosition(int position) { return getViewForPosition(position, false); } @@ -5959,7 +6216,10 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro ViewCompat.setImportantForAccessibility(itemView, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES); } - if (!ViewCompat.hasAccessibilityDelegate(itemView)) { + AccessibilityDelegateCompat delegate = + ViewCompat.getAccessibilityDelegate(itemView); + if (delegate == null + || delegate.getClass().equals(AccessibilityDelegateCompat.class)) { holder.addFlags(ViewHolder.FLAG_SET_A11Y_ITEM_DELEGATE); ViewCompat.setAccessibilityDelegate(itemView, mAccessibilityDelegate.getItemDelegate()); @@ -6004,7 +6264,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param view Removed view for recycling * @see LayoutManager#removeAndRecycleView(View, Recycler) */ - public void recycleView(View view) { + public void recycleView(@NonNull View view) { // This public recycle method tries to make view recycle-able since layout manager // intended to recycle this view (e.g. even if it is in scrap or change cache) ViewHolder holder = getChildViewHolderInt(view); @@ -6017,15 +6277,23 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro holder.clearReturnedFromScrapFlag(); } recycleViewHolderInternal(holder); - } - - /** - * Internally, use this method instead of {@link #recycleView(android.view.View)} to - * catch potential bugs. - * @param view - */ - void recycleViewInternal(View view) { - recycleViewHolderInternal(getChildViewHolderInt(view)); + // In most cases we dont need call endAnimation() because when view is detached, + // ViewPropertyAnimation will end. But if the animation is based on ObjectAnimator or + // if the ItemAnimator uses "pending runnable" and the ViewPropertyAnimation has not + // started yet, the ItemAnimatior on the view may not be cleared. + // In b/73552923, the View is removed by scroll pass while it's waiting in + // the "pending moving" list of DefaultItemAnimator and DefaultItemAnimator later in + // a post runnable, incorrectly performs postDelayed() on the detached view. + // To fix the issue, we issue endAnimation() here to make sure animation of this view + // finishes. + // + // Note the order: we must call endAnimation() after recycleViewHolderInternal() + // to avoid recycle twice. If ViewHolder isRecyclable is false, + // recycleViewHolderInternal() will not recycle it, endAnimation() will reset + // isRecyclable flag and recycle the view. + if (mItemAnimator != null && !holder.isRecyclable()) { + mItemAnimator.endAnimation(holder); + } } void recycleAndClearCachedViews() { @@ -6086,9 +6354,9 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro + " should first call stopIgnoringView(view) before calling recycle." + exceptionLabel()); } - //noinspection unchecked final boolean transientStatePreventsRecycling = holder .doesTransientStatePreventRecycling(); + @SuppressWarnings("unchecked") final boolean forceRecycle = mAdapter != null && transientStatePreventsRecycling && mAdapter.onFailedToRecycleView(holder); @@ -6162,7 +6430,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param holder Holder to be added to the pool. * @param dispatchRecycled True to dispatch View recycled callbacks. */ - void addViewHolderToRecycledViewPool(ViewHolder holder, boolean dispatchRecycled) { + void addViewHolderToRecycledViewPool(@NonNull ViewHolder holder, boolean dispatchRecycled) { clearNestedRecyclerViewIfNotNested(holder); if (holder.hasAnyOfTheFlags(ViewHolder.FLAG_SET_A11Y_ITEM_DELEGATE)) { holder.setFlags(0, ViewHolder.FLAG_SET_A11Y_ITEM_DELEGATE); @@ -6326,7 +6594,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro final ViewHolder holder = mCachedViews.get(i); // invalid view holders may be in cache if adapter has stable ids as they can be // retrieved via getScrapOrCachedViewForId - if (!holder.isInvalid() && holder.getLayoutPosition() == position) { + if (!holder.isInvalid() && holder.getLayoutPosition() == position + && !holder.isAttachedToTransitionOverlay()) { if (!dryRun) { mCachedViews.remove(i); } @@ -6378,7 +6647,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro final int cacheSize = mCachedViews.size(); for (int i = cacheSize - 1; i >= 0; i--) { final ViewHolder holder = mCachedViews.get(i); - if (holder.getItemId() == id) { + if (holder.getItemId() == id && !holder.isAttachedToTransitionOverlay()) { if (type == holder.getItemViewType()) { if (!dryRun) { mCachedViews.remove(i); @@ -6393,7 +6662,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro return null; } - void dispatchViewRecycled(ViewHolder holder) { + void dispatchViewRecycled(@NonNull ViewHolder holder) { if (mRecyclerListener != null) { mRecyclerListener.onViewRecycled(holder); } @@ -6492,8 +6761,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro mRecyclerPool.detach(); } mRecyclerPool = pool; - if (pool != null) { - mRecyclerPool.attach(getAdapter()); + if (mRecyclerPool != null && getAdapter() != null) { + mRecyclerPool.attach(); } } @@ -6600,7 +6869,9 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return A View that is bound to the given position or NULL if there is no View to re-use * @see LayoutManager#ignoreView(View) */ - public abstract View getViewForPositionAndType(Recycler recycler, int position, int type); + @Nullable + public abstract View getViewForPositionAndType(@NonNull Recycler recycler, int position, + int type); } /** @@ -6701,6 +6972,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @see #onCreateViewHolder(ViewGroup, int) */ + @NonNull public final VH createViewHolder(@NonNull ViewGroup parent, int viewType) { try { TraceCompat.beginSection(TRACE_CREATE_VIEW_TAG); @@ -6901,7 +7173,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * *

    The adapter may publish a variety of events describing specific changes. * Not all adapters may support all change types and some may fall back to a generic - * {@link android.support.v7.widget.RecyclerView.AdapterDataObserver#onChanged() + * {@link RecyclerView.AdapterDataObserver#onChanged() * "something changed"} event if more specific data is not available.

    * *

    Components registering observers with an adapter are responsible for @@ -7216,16 +7488,6 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro */ private final ViewBoundsCheck.Callback mHorizontalBoundCheckCallback = new ViewBoundsCheck.Callback() { - @Override - public int getChildCount() { - return LayoutManager.this.getChildCount(); - } - - @Override - public View getParent() { - return mRecyclerView; - } - @Override public View getChildAt(int index) { return LayoutManager.this.getChildAt(index); @@ -7262,16 +7524,6 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro */ private final ViewBoundsCheck.Callback mVerticalBoundCheckCallback = new ViewBoundsCheck.Callback() { - @Override - public int getChildCount() { - return LayoutManager.this.getChildCount(); - } - - @Override - public View getParent() { - return mRecyclerView; - } - @Override public View getChildAt(int index) { return LayoutManager.this.getChildAt(index); @@ -8099,8 +8351,13 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } /** - *

    Starts a smooth scroll using the provided SmoothScroller.

    - *

    Calling this method will cancel any previous smooth scroll request.

    + * Starts a smooth scroll using the provided {@link SmoothScroller}. + * + *

    Each instance of SmoothScroller is intended to only be used once. Provide a new + * SmoothScroller instance each time this method is called. + * + *

    Calling this method will cancel any previous smooth scroll request. + * * @param smoothScroller Instance which defines how smooth scroll should be animated */ public void startSmoothScroll(SmoothScroller smoothScroller) { @@ -8113,19 +8370,18 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } /** - * @return true if RecycylerView is currently in the state of smooth scrolling. + * @return true if RecyclerView is currently in the state of smooth scrolling. */ public boolean isSmoothScrolling() { return mSmoothScroller != null && mSmoothScroller.isRunning(); } - /** * Returns the resolved layout direction for this RecyclerView. * - * @return {@link android.support.v4.view.ViewCompat#LAYOUT_DIRECTION_RTL} if the layout + * @return {@link androidx.core.view.ViewCompat#LAYOUT_DIRECTION_RTL} if the layout * direction is RTL or returns - * {@link android.support.v4.view.ViewCompat#LAYOUT_DIRECTION_LTR} if the layout direction + * {@link androidx.core.view.ViewCompat#LAYOUT_DIRECTION_LTR} if the layout direction * is not RTL. */ public int getLayoutDirection() { @@ -8312,7 +8568,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param view The view to query * @return The adapter position of the item which is rendered by this View. */ - public int getPosition(View view) { + public int getPosition(@NonNull View view) { return ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewLayoutPosition(); } @@ -8322,7 +8578,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param view The view to query * @return The type of the view assigned by the adapter. */ - public int getItemViewType(View view) { + public int getItemViewType(@NonNull View view) { return getChildViewHolderInt(view).getItemViewType(); } @@ -8342,7 +8598,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @see RecyclerView#findContainingViewHolder(View) */ @Nullable - public View findContainingItemView(View view) { + public View findContainingItemView(@NonNull View view) { if (mRecyclerView == null) { return null; } @@ -8369,6 +8625,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return The child view that represents the given position or null if the position is not * laid out */ + @Nullable public View findViewByPosition(int position) { final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { @@ -8400,7 +8657,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param child Child to detach */ - public void detachView(View child) { + public void detachView(@NonNull View child) { final int ind = mChildHelper.indexOfChild(child); if (ind >= 0) { detachViewInternal(ind, child); @@ -8426,7 +8683,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro detachViewInternal(index, getChildAt(index)); } - private void detachViewInternal(int index, View view) { + private void detachViewInternal(int index, @NonNull View view) { if (DISPATCH_TEMP_DETACH) { ViewCompat.dispatchStartTemporaryDetach(view); } @@ -8442,7 +8699,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param index Intended child index for child * @param lp LayoutParams for child */ - public void attachView(View child, int index, LayoutParams lp) { + public void attachView(@NonNull View child, int index, LayoutParams lp) { ViewHolder vh = getChildViewHolderInt(child); if (vh.isRemoved()) { mRecyclerView.mViewInfoStore.addToDisappearedInLayout(vh); @@ -8463,7 +8720,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param child Child to reattach * @param index Intended child index for child */ - public void attachView(View child, int index) { + public void attachView(@NonNull View child, int index) { attachView(child, index, (LayoutParams) child.getLayoutParams()); } @@ -8474,7 +8731,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param child Child to reattach */ - public void attachView(View child) { + public void attachView(@NonNull View child) { attachView(child, -1); } @@ -8484,7 +8741,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param child Detached child to remove */ - public void removeDetachedView(View child) { + public void removeDetachedView(@NonNull View child) { mRecyclerView.removeDetachedView(child, false); } @@ -8513,7 +8770,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param child Child to detach and scrap * @param recycler Recycler to deposit the new scrap view into */ - public void detachAndScrapView(View child, Recycler recycler) { + public void detachAndScrapView(@NonNull View child, @NonNull Recycler recycler) { int index = mChildHelper.indexOfChild(child); scrapOrRecycleView(recycler, index, child); } @@ -8527,7 +8784,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param index Index of child to detach and scrap * @param recycler Recycler to deposit the new scrap view into */ - public void detachAndScrapViewAt(int index, Recycler recycler) { + public void detachAndScrapViewAt(int index, @NonNull Recycler recycler) { final View child = getChildAt(index); scrapOrRecycleView(recycler, index, child); } @@ -8538,7 +8795,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param child Child to remove and recycle * @param recycler Recycler to use to recycle child */ - public void removeAndRecycleView(View child, Recycler recycler) { + public void removeAndRecycleView(@NonNull View child, @NonNull Recycler recycler) { removeView(child); recycler.recycleView(child); } @@ -8549,7 +8806,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param index Index of child to remove and recycle * @param recycler Recycler to use to recycle child */ - public void removeAndRecycleViewAt(int index, Recycler recycler) { + public void removeAndRecycleViewAt(int index, @NonNull Recycler recycler) { final View view = getChildAt(index); removeViewAt(index); recycler.recycleView(view); @@ -8570,6 +8827,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param index Index of child to return * @return Child view at index */ + @Nullable public View getChildAt(int index) { return mChildHelper != null ? mChildHelper.getChildAt(index) : null; } @@ -8619,6 +8877,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @return Width in pixels */ + @Px public int getWidth() { return mWidth; } @@ -8634,6 +8893,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @return Height in pixels */ + @Px public int getHeight() { return mHeight; } @@ -8643,6 +8903,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @return Padding in pixels */ + @Px public int getPaddingLeft() { return mRecyclerView != null ? mRecyclerView.getPaddingLeft() : 0; } @@ -8652,6 +8913,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @return Padding in pixels */ + @Px public int getPaddingTop() { return mRecyclerView != null ? mRecyclerView.getPaddingTop() : 0; } @@ -8661,6 +8923,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @return Padding in pixels */ + @Px public int getPaddingRight() { return mRecyclerView != null ? mRecyclerView.getPaddingRight() : 0; } @@ -8670,6 +8933,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @return Padding in pixels */ + @Px public int getPaddingBottom() { return mRecyclerView != null ? mRecyclerView.getPaddingBottom() : 0; } @@ -8679,6 +8943,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @return Padding in pixels */ + @Px public int getPaddingStart() { return mRecyclerView != null ? ViewCompat.getPaddingStart(mRecyclerView) : 0; } @@ -8688,6 +8953,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @return Padding in pixels */ + @Px public int getPaddingEnd() { return mRecyclerView != null ? ViewCompat.getPaddingEnd(mRecyclerView) : 0; } @@ -8717,6 +8983,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @return A direct child of RecyclerView which has focus or contains the focused child. */ + @Nullable public View getFocusedChild() { if (mRecyclerView == null) { return null; @@ -8751,7 +9018,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param dx Pixels to offset by */ - public void offsetChildrenHorizontal(int dx) { + public void offsetChildrenHorizontal(@Px int dx) { if (mRecyclerView != null) { mRecyclerView.offsetChildrenHorizontal(dx); } @@ -8763,7 +9030,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param dy Pixels to offset by */ - public void offsetChildrenVertical(int dy) { + public void offsetChildrenVertical(@Px int dy) { if (mRecyclerView != null) { mRecyclerView.offsetChildrenVertical(dy); } @@ -8785,7 +9052,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param view View to ignore. * @see #stopIgnoringView(View) */ - public void ignoreView(View view) { + public void ignoreView(@NonNull View view) { if (view.getParent() != mRecyclerView || mRecyclerView.indexOfChild(view) == -1) { // checking this because calling this method on a recycled or detached view may // cause loss of state. @@ -8806,7 +9073,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param view View to ignore. */ - public void stopIgnoringView(View view) { + public void stopIgnoringView(@NonNull View view) { final ViewHolder vh = getChildViewHolderInt(view); vh.stopIgnoring(); vh.resetInternal(); @@ -8820,7 +9087,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param recycler Recycler to scrap views into */ - public void detachAndScrapAttachedViews(Recycler recycler) { + public void detachAndScrapAttachedViews(@NonNull Recycler recycler) { final int childCount = getChildCount(); for (int i = childCount - 1; i >= 0; i--) { final View v = getChildAt(i); @@ -8898,7 +9165,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param widthUsed Width in pixels currently consumed by other views, if relevant * @param heightUsed Height in pixels currently consumed by other views, if relevant */ - public void measureChild(View child, int widthUsed, int heightUsed) { + public void measureChild(@NonNull View child, int widthUsed, int heightUsed) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); final Rect insets = mRecyclerView.getItemDecorInsetsForChild(child); @@ -8997,7 +9264,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param widthUsed Width in pixels currently consumed by other views, if relevant * @param heightUsed Height in pixels currently consumed by other views, if relevant */ - public void measureChildWithMargins(View child, int widthUsed, int heightUsed) { + public void measureChildWithMargins(@NonNull View child, int widthUsed, int heightUsed) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); final Rect insets = mRecyclerView.getItemDecorInsetsForChild(child); @@ -9128,7 +9395,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @see View#getMeasuredWidth() */ - public int getDecoratedMeasuredWidth(View child) { + public int getDecoratedMeasuredWidth(@NonNull View child) { final Rect insets = ((LayoutParams) child.getLayoutParams()).mDecorInsets; return child.getMeasuredWidth() + insets.left + insets.right; } @@ -9142,7 +9409,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @see View#getMeasuredHeight() */ - public int getDecoratedMeasuredHeight(View child) { + public int getDecoratedMeasuredHeight(@NonNull View child) { final Rect insets = ((LayoutParams) child.getLayoutParams()).mDecorInsets; return child.getMeasuredHeight() + insets.top + insets.bottom; } @@ -9177,7 +9444,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @see View#layout(int, int, int, int) * @see #layoutDecoratedWithMargins(View, int, int, int, int) */ - public void layoutDecorated(View child, int left, int top, int right, int bottom) { + public void layoutDecorated(@NonNull View child, int left, int top, int right, int bottom) { final Rect insets = ((LayoutParams) child.getLayoutParams()).mDecorInsets; child.layout(left + insets.left, top + insets.top, right - insets.right, bottom - insets.bottom); @@ -9212,7 +9479,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @see View#layout(int, int, int, int) * @see #layoutDecorated(View, int, int, int, int) */ - public void layoutDecoratedWithMargins(View child, int left, int top, int right, + public void layoutDecoratedWithMargins(@NonNull View child, int left, int top, int right, int bottom) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); final Rect insets = lp.mDecorInsets; @@ -9232,7 +9499,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param includeDecorInsets True if the decor insets should be included in the bounding box * @param out The rectangle into which the output will be written. */ - public void getTransformedBoundingBox(View child, boolean includeDecorInsets, Rect out) { + public void getTransformedBoundingBox(@NonNull View child, boolean includeDecorInsets, + @NonNull Rect out) { if (includeDecorInsets) { Rect insets = ((LayoutParams) child.getLayoutParams()).mDecorInsets; out.set(-insets.left, -insets.top, @@ -9265,7 +9533,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param outBounds A rect that will receive the bounds of the element including its * decoration and margins. */ - public void getDecoratedBoundsWithMargins(View view, Rect outBounds) { + public void getDecoratedBoundsWithMargins(@NonNull View view, @NonNull Rect outBounds) { RecyclerView.getDecoratedBoundsWithMarginsInt(view, outBounds); } @@ -9277,7 +9545,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return Child left edge with offsets applied * @see #getLeftDecorationWidth(View) */ - public int getDecoratedLeft(View child) { + public int getDecoratedLeft(@NonNull View child) { return child.getLeft() - getLeftDecorationWidth(child); } @@ -9289,7 +9557,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return Child top edge with offsets applied * @see #getTopDecorationHeight(View) */ - public int getDecoratedTop(View child) { + public int getDecoratedTop(@NonNull View child) { return child.getTop() - getTopDecorationHeight(child); } @@ -9301,7 +9569,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return Child right edge with offsets applied * @see #getRightDecorationWidth(View) */ - public int getDecoratedRight(View child) { + public int getDecoratedRight(@NonNull View child) { return child.getRight() + getRightDecorationWidth(child); } @@ -9313,7 +9581,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return Child bottom edge with offsets applied * @see #getBottomDecorationHeight(View) */ - public int getDecoratedBottom(View child) { + public int getDecoratedBottom(@NonNull View child) { return child.getBottom() + getBottomDecorationHeight(child); } @@ -9334,7 +9602,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param child The child view whose decorations should be calculated * @param outRect The Rect to hold result values */ - public void calculateItemDecorationsForChild(View child, Rect outRect) { + public void calculateItemDecorationsForChild(@NonNull View child, @NonNull Rect outRect) { if (mRecyclerView == null) { outRect.set(0, 0, 0, 0); return; @@ -9354,7 +9622,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @see #getDecoratedTop(View) * @see #calculateItemDecorationsForChild(View, Rect) */ - public int getTopDecorationHeight(View child) { + public int getTopDecorationHeight(@NonNull View child) { return ((LayoutParams) child.getLayoutParams()).mDecorInsets.top; } @@ -9369,7 +9637,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @see #getDecoratedBottom(View) * @see #calculateItemDecorationsForChild(View, Rect) */ - public int getBottomDecorationHeight(View child) { + public int getBottomDecorationHeight(@NonNull View child) { return ((LayoutParams) child.getLayoutParams()).mDecorInsets.bottom; } @@ -9384,7 +9652,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @see #getDecoratedLeft(View) * @see #calculateItemDecorationsForChild(View, Rect) */ - public int getLeftDecorationWidth(View child) { + public int getLeftDecorationWidth(@NonNull View child) { return ((LayoutParams) child.getLayoutParams()).mDecorInsets.left; } @@ -9399,7 +9667,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @see #getDecoratedRight(View) * @see #calculateItemDecorationsForChild(View, Rect) */ - public int getRightDecorationWidth(View child) { + public int getRightDecorationWidth(@NonNull View child) { return ((LayoutParams) child.getLayoutParams()).mDecorInsets.right; } @@ -9426,8 +9694,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * unfocusable view to become visible onto the screen, else null. */ @Nullable - public View onFocusSearchFailed(View focused, int direction, Recycler recycler, - State state) { + public View onFocusSearchFailed(@NonNull View focused, int direction, + @NonNull Recycler recycler, @NonNull State state) { return null; } @@ -9447,24 +9715,21 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return A descendant view to focus or null to fall back to default behavior. * The default implementation returns null. */ - public View onInterceptFocusSearch(View focused, int direction) { + @Nullable + public View onInterceptFocusSearch(@NonNull View focused, int direction) { return null; } /** * Returns the scroll amount that brings the given rect in child's coordinate system within * the padded area of RecyclerView. - * @param parent The parent RecyclerView. * @param child The direct child making the request. * @param rect The rectangle in the child's coordinates the child * wishes to be on the screen. - * @param immediate True to forbid animated or delayed scrolling, - * false otherwise * @return The array containing the scroll amount in x and y directions that brings the * given rect into RV's padded area. */ - private int[] getChildRectangleOnScreenScrollAmount(RecyclerView parent, View child, - Rect rect, boolean immediate) { + private int[] getChildRectangleOnScreenScrollAmount(View child, Rect rect) { int[] out = new int[2]; final int parentLeft = getPaddingLeft(); final int parentTop = getPaddingTop(); @@ -9515,8 +9780,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * false otherwise * @return Whether the group scrolled to handle the operation */ - public boolean requestChildRectangleOnScreen(RecyclerView parent, View child, Rect rect, - boolean immediate) { + public boolean requestChildRectangleOnScreen(@NonNull RecyclerView parent, + @NonNull View child, @NonNull Rect rect, boolean immediate) { return requestChildRectangleOnScreen(parent, child, rect, immediate, false); } @@ -9534,11 +9799,11 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param focusedChildVisible Whether the currently focused view must stay visible. * @return Whether the group scrolled to handle the operation */ - public boolean requestChildRectangleOnScreen(RecyclerView parent, View child, Rect rect, - boolean immediate, + public boolean requestChildRectangleOnScreen(@NonNull RecyclerView parent, + @NonNull View child, @NonNull Rect rect, boolean immediate, boolean focusedChildVisible) { - int[] scrollAmount = getChildRectangleOnScreenScrollAmount(parent, child, rect, - immediate); + int[] scrollAmount = getChildRectangleOnScreenScrollAmount(child, rect + ); int dx = scrollAmount[0]; int dy = scrollAmount[1]; if (!focusedChildVisible || isFocusedChildVisibleAfterScrolling(parent, dx, dy)) { @@ -9619,7 +9884,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @deprecated Use {@link #onRequestChildFocus(RecyclerView, State, View, View)} */ @Deprecated - public boolean onRequestChildFocus(RecyclerView parent, View child, View focused) { + public boolean onRequestChildFocus(@NonNull RecyclerView parent, @NonNull View child, + @Nullable View focused) { // eat the request if we are in the middle of a scroll or layout return isSmoothScrolling() || parent.isComputingLayout(); } @@ -9641,8 +9907,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * null * @return true if the default scroll behavior should be suppressed */ - public boolean onRequestChildFocus(RecyclerView parent, State state, View child, - View focused) { + public boolean onRequestChildFocus(@NonNull RecyclerView parent, @NonNull State state, + @NonNull View child, @Nullable View focused) { return onRequestChildFocus(parent, child, focused); } @@ -9660,7 +9926,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param newAdapter The new adapter instance. Might be null if * {@link #setAdapter(RecyclerView.Adapter)} is called with {@code null}. */ - public void onAdapterChanged(Adapter oldAdapter, Adapter newAdapter) { + public void onAdapterChanged(@Nullable Adapter oldAdapter, @Nullable Adapter newAdapter) { } /** @@ -9687,8 +9953,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @see #FOCUSABLES_ALL * @see #FOCUSABLES_TOUCH_MODE */ - public boolean onAddFocusables(RecyclerView recyclerView, ArrayList views, - int direction, int focusableMode) { + public boolean onAddFocusables(@NonNull RecyclerView recyclerView, + @NonNull ArrayList views, int direction, int focusableMode) { return false; } @@ -9699,7 +9965,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param recyclerView */ - public void onItemsChanged(RecyclerView recyclerView) { + public void onItemsChanged(@NonNull RecyclerView recyclerView) { } /** @@ -9711,7 +9977,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param positionStart * @param itemCount */ - public void onItemsAdded(RecyclerView recyclerView, int positionStart, int itemCount) { + public void onItemsAdded(@NonNull RecyclerView recyclerView, int positionStart, + int itemCount) { } /** @@ -9721,7 +9988,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param positionStart * @param itemCount */ - public void onItemsRemoved(RecyclerView recyclerView, int positionStart, int itemCount) { + public void onItemsRemoved(@NonNull RecyclerView recyclerView, int positionStart, + int itemCount) { } /** @@ -9733,7 +10001,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param positionStart * @param itemCount */ - public void onItemsUpdated(RecyclerView recyclerView, int positionStart, int itemCount) { + public void onItemsUpdated(@NonNull RecyclerView recyclerView, int positionStart, + int itemCount) { } /** @@ -9745,8 +10014,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param itemCount * @param payload */ - public void onItemsUpdated(RecyclerView recyclerView, int positionStart, int itemCount, - Object payload) { + public void onItemsUpdated(@NonNull RecyclerView recyclerView, int positionStart, + int itemCount, @Nullable Object payload) { onItemsUpdated(recyclerView, positionStart, itemCount); } @@ -9762,7 +10031,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param to * @param itemCount */ - public void onItemsMoved(RecyclerView recyclerView, int from, int to, int itemCount) { + public void onItemsMoved(@NonNull RecyclerView recyclerView, int from, int to, + int itemCount) { } @@ -9778,7 +10048,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return The horizontal extent of the scrollbar's thumb * @see RecyclerView#computeHorizontalScrollExtent() */ - public int computeHorizontalScrollExtent(State state) { + public int computeHorizontalScrollExtent(@NonNull State state) { return 0; } @@ -9793,7 +10063,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return The horizontal offset of the scrollbar's thumb * @see RecyclerView#computeHorizontalScrollOffset() */ - public int computeHorizontalScrollOffset(State state) { + public int computeHorizontalScrollOffset(@NonNull State state) { return 0; } @@ -9808,7 +10078,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return The total horizontal range represented by the vertical scrollbar * @see RecyclerView#computeHorizontalScrollRange() */ - public int computeHorizontalScrollRange(State state) { + public int computeHorizontalScrollRange(@NonNull State state) { return 0; } @@ -9823,7 +10093,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return The vertical extent of the scrollbar's thumb * @see RecyclerView#computeVerticalScrollExtent() */ - public int computeVerticalScrollExtent(State state) { + public int computeVerticalScrollExtent(@NonNull State state) { return 0; } @@ -9838,7 +10108,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return The vertical offset of the scrollbar's thumb * @see RecyclerView#computeVerticalScrollOffset() */ - public int computeVerticalScrollOffset(State state) { + public int computeVerticalScrollOffset(@NonNull State state) { return 0; } @@ -9853,7 +10123,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return The total vertical range represented by the vertical scrollbar * @see RecyclerView#computeVerticalScrollRange() */ - public int computeVerticalScrollRange(State state) { + public int computeVerticalScrollRange(@NonNull State state) { return 0; } @@ -9880,7 +10150,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @see #isAutoMeasureEnabled() * @see #setMeasuredDimension(int, int) */ - public void onMeasure(Recycler recycler, State state, int widthSpec, int heightSpec) { + public void onMeasure(@NonNull Recycler recycler, @NonNull State state, int widthSpec, + int heightSpec) { mRecyclerView.defaultOnMeasure(widthSpec, heightSpec); } @@ -9898,6 +10169,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro /** * @return The host RecyclerView's {@link View#getMinimumWidth()} */ + @Px public int getMinimumWidth() { return ViewCompat.getMinimumWidth(mRecyclerView); } @@ -9905,6 +10177,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro /** * @return The host RecyclerView's {@link View#getMinimumHeight()} */ + @Px public int getMinimumHeight() { return ViewCompat.getMinimumHeight(mRecyclerView); } @@ -9918,6 +10191,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @return Necessary information for LayoutManager to be able to restore its state */ + @Nullable public Parcelable onSaveInstanceState() { return null; } @@ -9933,7 +10207,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } } - private void onSmoothScrollerStopped(SmoothScroller smoothScroller) { + void onSmoothScrollerStopped(SmoothScroller smoothScroller) { if (mSmoothScroller == smoothScroller) { mSmoothScroller = null; } @@ -9959,7 +10233,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @see #removeAndRecycleViewAt(int, Recycler) * @see #ignoreView(View) */ - public void removeAndRecycleAllViews(Recycler recycler) { + public void removeAndRecycleAllViews(@NonNull Recycler recycler) { for (int i = getChildCount() - 1; i >= 0; i--) { final View view = getChildAt(i); if (!getChildViewHolderInt(view).shouldIgnore()) { @@ -9978,7 +10252,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * be populated. *

    * Default implementation adds a {@link - * android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat}. + * androidx.core.view.accessibility.AccessibilityNodeInfoCompat.CollectionInfoCompat}. *

    * You should override * {@link #getRowCountForAccessibility(RecyclerView.Recycler, RecyclerView.State)}, @@ -9998,8 +10272,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @see #isLayoutHierarchical(RecyclerView.Recycler, RecyclerView.State) * @see #getSelectionModeForAccessibility(RecyclerView.Recycler, RecyclerView.State) */ - public void onInitializeAccessibilityNodeInfo(Recycler recycler, State state, - AccessibilityNodeInfoCompat info) { + public void onInitializeAccessibilityNodeInfo(@NonNull Recycler recycler, + @NonNull State state, @NonNull AccessibilityNodeInfoCompat info) { if (mRecyclerView.canScrollVertically(-1) || mRecyclerView.canScrollHorizontally(-1)) { info.addAction(AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD); info.setScrollable(true); @@ -10018,7 +10292,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } // called by accessibility delegate - public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + public void onInitializeAccessibilityEvent(@NonNull AccessibilityEvent event) { onInitializeAccessibilityEvent(mRecyclerView.mRecycler, mRecyclerView.mState, event); } @@ -10033,8 +10307,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param event The event instance to initialize * @see View#onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent) */ - public void onInitializeAccessibilityEvent(Recycler recycler, State state, - AccessibilityEvent event) { + public void onInitializeAccessibilityEvent(@NonNull Recycler recycler, @NonNull State state, + @NonNull AccessibilityEvent event) { if (mRecyclerView == null || event == null) { return; } @@ -10072,8 +10346,9 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @see android.widget.AbsListView#onInitializeAccessibilityNodeInfoForItem(View, int, * android.view.accessibility.AccessibilityNodeInfo) */ - public void onInitializeAccessibilityNodeInfoForItem(Recycler recycler, State state, - View host, AccessibilityNodeInfoCompat info) { + public void onInitializeAccessibilityNodeInfoForItem(@NonNull Recycler recycler, + @NonNull State state, @NonNull View host, + @NonNull AccessibilityNodeInfoCompat info) { int rowIndexGuess = canScrollVertically() ? getPosition(host) : 0; int columnIndexGuess = canScrollHorizontally() ? getPosition(host) : 0; final AccessibilityNodeInfoCompat.CollectionItemInfoCompat itemInfo = @@ -10111,7 +10386,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return Selection mode for accessibility. Default implementation returns * {@link AccessibilityNodeInfoCompat.CollectionInfoCompat#SELECTION_MODE_NONE}. */ - public int getSelectionModeForAccessibility(Recycler recycler, State state) { + public int getSelectionModeForAccessibility(@NonNull Recycler recycler, + @NonNull State state) { return AccessibilityNodeInfoCompat.CollectionInfoCompat.SELECTION_MODE_NONE; } @@ -10127,7 +10403,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param state The current state of RecyclerView * @return The number of rows in LayoutManager for accessibility. */ - public int getRowCountForAccessibility(Recycler recycler, State state) { + public int getRowCountForAccessibility(@NonNull Recycler recycler, @NonNull State state) { if (mRecyclerView == null || mRecyclerView.mAdapter == null) { return 1; } @@ -10146,7 +10422,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param state The current state of RecyclerView * @return The number of rows in LayoutManager for accessibility. */ - public int getColumnCountForAccessibility(Recycler recycler, State state) { + public int getColumnCountForAccessibility(@NonNull Recycler recycler, + @NonNull State state) { if (mRecyclerView == null || mRecyclerView.mAdapter == null) { return 1; } @@ -10163,12 +10440,12 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param state The current state of RecyclerView * @return True if layout is hierarchical. */ - public boolean isLayoutHierarchical(Recycler recycler, State state) { + public boolean isLayoutHierarchical(@NonNull Recycler recycler, @NonNull State state) { return false; } // called by accessibility delegate - boolean performAccessibilityAction(int action, Bundle args) { + boolean performAccessibilityAction(int action, @Nullable Bundle args) { return performAccessibilityAction(mRecyclerView.mRecycler, mRecyclerView.mState, action, args); } @@ -10183,8 +10460,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param args Optional action arguments * @see View#performAccessibilityAction(int, android.os.Bundle) */ - public boolean performAccessibilityAction(Recycler recycler, State state, int action, - Bundle args) { + public boolean performAccessibilityAction(@NonNull Recycler recycler, @NonNull State state, + int action, @Nullable Bundle args) { if (mRecyclerView == null) { return false; } @@ -10210,12 +10487,13 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro if (vScroll == 0 && hScroll == 0) { return false; } - mRecyclerView.scrollBy(hScroll, vScroll); + mRecyclerView.smoothScrollBy(hScroll, vScroll); return true; } // called by accessibility delegate - boolean performAccessibilityActionForItem(View view, int action, Bundle args) { + boolean performAccessibilityActionForItem(@NonNull View view, int action, + @Nullable Bundle args) { return performAccessibilityActionForItem(mRecyclerView.mRecycler, mRecyclerView.mState, view, action, args); } @@ -10235,22 +10513,11 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return true if action is handled * @see View#performAccessibilityAction(int, android.os.Bundle) */ - public boolean performAccessibilityActionForItem(Recycler recycler, State state, View view, - int action, Bundle args) { + public boolean performAccessibilityActionForItem(@NonNull Recycler recycler, + @NonNull State state, @NonNull View view, int action, @Nullable Bundle args) { return false; } - /** - * Parse the xml attributes to get the most common properties used by layout managers. - * - * @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_android_orientation - * @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_spanCount - * @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_reverseLayout - * @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_stackFromEnd - * - * @return an object containing the properties as specified in the attrs. - */ - void setExactMeasureSpecsFrom(RecyclerView recyclerView) { setMeasureSpecs( MeasureSpec.makeMeasureSpec(recyclerView.getWidth(), MeasureSpec.EXACTLY), @@ -10288,13 +10555,13 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * Some general properties that a LayoutManager may want to use. */ public static class Properties { - /** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_android_orientation */ + /** {@link android.R.attr#orientation} */ public int orientation; - /** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_spanCount */ + /** {@link androidx.recyclerview.R.attr#spanCount} */ public int spanCount; - /** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_reverseLayout */ + /** {@link androidx.recyclerview.R.attr#reverseLayout} */ public boolean reverseLayout; - /** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_stackFromEnd */ + /** {@link androidx.recyclerview.R.attr#stackFromEnd} */ public boolean stackFromEnd; } } @@ -10319,7 +10586,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param parent RecyclerView this ItemDecoration is drawing into * @param state The current state of RecyclerView */ - public void onDraw(Canvas c, RecyclerView parent, State state) { + public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull State state) { onDraw(c, parent); } @@ -10328,7 +10595,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * Override {@link #onDraw(Canvas, RecyclerView, RecyclerView.State)} */ @Deprecated - public void onDraw(Canvas c, RecyclerView parent) { + public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent) { } /** @@ -10340,7 +10607,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param parent RecyclerView this ItemDecoration is drawing into * @param state The current state of RecyclerView. */ - public void onDrawOver(Canvas c, RecyclerView parent, State state) { + public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, + @NonNull State state) { onDrawOver(c, parent); } @@ -10349,7 +10617,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * Override {@link #onDrawOver(Canvas, RecyclerView, RecyclerView.State)} */ @Deprecated - public void onDrawOver(Canvas c, RecyclerView parent) { + public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent) { } @@ -10358,7 +10626,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * Use {@link #getItemOffsets(Rect, View, RecyclerView, State)} */ @Deprecated - public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { + public void getItemOffsets(@NonNull Rect outRect, int itemPosition, + @NonNull RecyclerView parent) { outRect.set(0, 0, 0, 0); } @@ -10382,7 +10651,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param parent RecyclerView this ItemDecoration is decorating * @param state The current state of RecyclerView. */ - public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) { + public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, + @NonNull RecyclerView parent, @NonNull State state) { getItemOffsets(outRect, ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition(), parent); } @@ -10415,7 +10685,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * to continue with the current behavior and continue observing future events in * the gesture. */ - boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e); + boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e); /** * Process a touch event as part of a gesture that was claimed by returning true from @@ -10424,7 +10694,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param e MotionEvent describing the touch event. All coordinates are in * the RecyclerView's coordinate system. */ - void onTouchEvent(RecyclerView rv, MotionEvent e); + void onTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e); /** * Called when a child of RecyclerView does not want RecyclerView and its ancestors to @@ -10449,12 +10719,12 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro */ public static class SimpleOnItemTouchListener implements RecyclerView.OnItemTouchListener { @Override - public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { + public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) { return false; } @Override - public void onTouchEvent(RecyclerView rv, MotionEvent e) { + public void onTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) { } @Override @@ -10479,7 +10749,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param newState The updated scroll state. One of {@link #SCROLL_STATE_IDLE}, * {@link #SCROLL_STATE_DRAGGING} or {@link #SCROLL_STATE_SETTLING}. */ - public void onScrollStateChanged(RecyclerView recyclerView, int newState){} + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState){} /** * Callback method to be invoked when the RecyclerView has been scrolled. This will be @@ -10492,7 +10762,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param dx The amount of horizontal scroll. * @param dy The amount of vertical scroll. */ - public void onScrolled(RecyclerView recyclerView, int dx, int dy){} + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy){} } /** @@ -10513,7 +10783,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param holder The ViewHolder containing the view that was recycled */ - void onViewRecycled(ViewHolder holder); + void onViewRecycled(@NonNull ViewHolder holder); } /** @@ -10527,14 +10797,14 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param view The View which is attached to the RecyclerView */ - void onChildViewAttachedToWindow(View view); + void onChildViewAttachedToWindow(@NonNull View view); /** * Called when a view is detached from RecyclerView. * * @param view The View which is being detached from the RecyclerView */ - void onChildViewDetachedFromWindow(View view); + void onChildViewDetachedFromWindow(@NonNull View view); } /** @@ -10551,6 +10821,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * strong references to extra off-screen item views for caching purposes

    */ public abstract static class ViewHolder { + @NonNull public final View itemView; WeakReference mNestedRecyclerView; int mPosition = NO_POSITION; @@ -10663,9 +10934,9 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro */ static final int FLAG_SET_A11Y_ITEM_DELEGATE = 1 << 14; - private int mFlags; + int mFlags; - private static final List FULLUPDATE_PAYLOADS = Collections.EMPTY_LIST; + private static final List FULLUPDATE_PAYLOADS = Collections.emptyList(); List mPayloads = null; List mUnmodifiedPayloads = null; @@ -10674,9 +10945,9 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro // If non-null, view is currently considered scrap and may be reused for other data by the // scrap container. - private Recycler mScrapContainer = null; + Recycler mScrapContainer = null; // Keeps whether this ViewHolder lives in Change scrap or Attached scrap - private boolean mInChangeScrap = false; + boolean mInChangeScrap = false; // Saves isImportantForAccessibility value for the view item while it's in hidden state and // marked as unimportant for accessibility. @@ -10692,7 +10963,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro */ RecyclerView mOwnerRecyclerView; - public ViewHolder(View itemView) { + public ViewHolder(@NonNull View itemView) { if (itemView == null) { throw new IllegalArgumentException("itemView may not be null"); } @@ -10738,7 +11009,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro /** * @deprecated This method is deprecated because its meaning is ambiguous due to the async - * handling of adapter updates. Please use {@link #getLayoutPosition()} or + * handling of adapter updates. You should use {@link #getLayoutPosition()} or * {@link #getAdapterPosition()} depending on your use case. * * @see #getLayoutPosition() @@ -10889,6 +11160,10 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro return (mFlags & FLAG_TMP_DETACHED) != 0; } + boolean isAttachedToTransitionOverlay() { + return itemView.getParent() != null && itemView.getParent() != mOwnerRecyclerView; + } + boolean isAdapterPositionUnknown() { return (mFlags & FLAG_ADAPTER_POSITION_UNKNOWN) != 0 || isInvalid(); } @@ -10956,7 +11231,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro /** * Called when the child view enters the hidden state */ - private void onEnteredHiddenState(RecyclerView parent) { + void onEnteredHiddenState(RecyclerView parent) { // While the view item is in hidden state, make it invisible for the accessibility. if (mPendingAccessibilityState != PENDING_ACCESSIBILITY_STATE_NOT_SET) { mWasImportantForAccessibilityBeforeHidden = mPendingAccessibilityState; @@ -10971,7 +11246,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro /** * Called when the child view leaves the hidden state */ - private void onLeftHiddenState(RecyclerView parent) { + void onLeftHiddenState(RecyclerView parent) { parent.setChildImportantForAccessibilityInternal(this, mWasImportantForAccessibilityBeforeHidden); mWasImportantForAccessibilityBeforeHidden = ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO; @@ -11047,7 +11322,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * Returns whether we have animations referring to this view holder or not. * This is similar to isRecyclable flag but does not check transient state. */ - private boolean shouldBeKeptAsChild() { + boolean shouldBeKeptAsChild() { return (mFlags & FLAG_NOT_RECYCLABLE) != 0; } @@ -11055,7 +11330,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @return True if ViewHolder is not referenced by RecyclerView animations but has * transient state which will prevent it from being recycled. */ - private boolean doesTransientStatePreventRecycling() { + boolean doesTransientStatePreventRecycling() { return (mFlags & FLAG_NOT_RECYCLABLE) == 0 && ViewCompat.hasTransientState(itemView); } @@ -11179,6 +11454,13 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro dxUnconsumed, dyUnconsumed, offsetInWindow, type); } + @Override + public final void dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, + int dyUnconsumed, int[] offsetInWindow, int type, int[] consumed) { + getScrollingChildHelper().dispatchNestedScroll(dxConsumed, dyConsumed, + dxUnconsumed, dyUnconsumed, offsetInWindow, type, consumed); + } + @Override public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { return getScrollingChildHelper().dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); @@ -11209,7 +11491,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro */ public static class LayoutParams extends android.view.ViewGroup.MarginLayoutParams { ViewHolder mViewHolder; - final Rect mDecorInsets = new Rect(); + public final Rect mDecorInsets = new Rect(); boolean mInsetsDirty = true; // Flag is set to true if the view is bound while it is detached from RV. // In this case, we need to manually call invalidate after view is added to guarantee that @@ -11342,8 +11624,11 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } /** - *

    Base class for smooth scrolling. Handles basic tracking of the target view position and - * provides methods to trigger a programmatic scroll.

    + * Base class for smooth scrolling. Handles basic tracking of the target view position and + * provides methods to trigger a programmatic scroll. + * + *

    An instance of SmoothScroller is only intended to be used once. You should create a new + * instance for each call to {@link LayoutManager#startSmoothScroll(SmoothScroller)}. * * @see LinearSmoothScroller */ @@ -11363,6 +11648,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro private final Action mRecyclingAction; + private boolean mStarted; + public SmoothScroller() { mRecyclingAction = new Action(0, 0); } @@ -11380,6 +11667,17 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * stop calling SmoothScroller in each animation step.

    */ void start(RecyclerView recyclerView, LayoutManager layoutManager) { + + // Stop any previous ViewFlinger animations now because we are about to start a new one. + recyclerView.mViewFlinger.stop(); + + if (mStarted) { + Log.w(TAG, "An instance of " + this.getClass().getSimpleName() + " was started " + + "more than once. Each instance of" + this.getClass().getSimpleName() + " " + + "is intended to only be used once. You should create a new instance for " + + "each use."); + } + mRecyclerView = recyclerView; mLayoutManager = layoutManager; if (mTargetPosition == RecyclerView.NO_POSITION) { @@ -11391,12 +11689,36 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro mTargetView = findViewByPosition(getTargetPosition()); onStart(); mRecyclerView.mViewFlinger.postOnAnimation(); + + mStarted = true; } public void setTargetPosition(int targetPosition) { mTargetPosition = targetPosition; } + /** + * Compute the scroll vector for a given target position. + *

    + * This method can return null if the layout manager cannot calculate a scroll vector + * for the given position (e.g. it has no current scroll position). + * + * @param targetPosition the position to which the scroller is scrolling + * + * @return the scroll vector for a given target position + */ + @Nullable + public PointF computeScrollVectorForPosition(int targetPosition) { + LayoutManager layoutManager = getLayoutManager(); + if (layoutManager instanceof ScrollVectorProvider) { + return ((ScrollVectorProvider) layoutManager) + .computeScrollVectorForPosition(targetPosition); + } + Log.w(TAG, "You should override computeScrollVectorForPosition when the LayoutManager" + + " does not implement " + ScrollVectorProvider.class.getCanonicalName()); + return null; + } + /** * @return The LayoutManager to which this SmoothScroller is attached. Will return * null after the SmoothScroller is stopped. @@ -11458,12 +11780,29 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro return mTargetPosition; } - private void onAnimation(int dx, int dy) { + void onAnimation(int dx, int dy) { final RecyclerView recyclerView = mRecyclerView; - if (!mRunning || mTargetPosition == RecyclerView.NO_POSITION || recyclerView == null) { + if (mTargetPosition == RecyclerView.NO_POSITION || recyclerView == null) { stop(); } + + // The following if block exists to have the LayoutManager scroll 1 pixel in the correct + // direction in order to cause the LayoutManager to draw two pages worth of views so + // that the target view may be found before scrolling any further. This is done to + // prevent an initial scroll distance from scrolling past the view, which causes a + // jittery looking animation. + if (mPendingInitialRun && mTargetView == null && mLayoutManager != null) { + PointF pointF = computeScrollVectorForPosition(mTargetPosition); + if (pointF != null && (pointF.x != 0 || pointF.y != 0)) { + recyclerView.scrollStep( + (int) Math.signum(pointF.x), + (int) Math.signum(pointF.y), + null); + } + } + mPendingInitialRun = false; + if (mTargetView != null) { // verify target position if (getChildPosition(mTargetView) == mTargetPosition) { @@ -11484,8 +11823,6 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro if (mRunning) { mPendingInitialRun = true; recyclerView.mViewFlinger.postOnAnimation(); - } else { - stop(); // done } } } @@ -11534,7 +11871,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * Normalizes the vector. * @param scrollVector The vector that points to the target scroll position */ - protected void normalize(PointF scrollVector) { + protected void normalize(@NonNull PointF scrollVector) { final float magnitude = (float) Math.sqrt(scrollVector.x * scrollVector.x + scrollVector.y * scrollVector.y); scrollVector.x /= magnitude; @@ -11564,7 +11901,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param action If you want to trigger a new smooth scroll and cancel the previous one, * update this object. */ - protected abstract void onSeekTargetStep(int dx, int dy, State state, Action action); + protected abstract void onSeekTargetStep(@Px int dx, @Px int dy, @NonNull State state, + @NonNull Action action); /** * Called when the target position is laid out. This is the last callback SmoothScroller @@ -11575,14 +11913,15 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param action Action instance that you should update to define final scroll action * towards the targetView */ - protected abstract void onTargetFound(View targetView, State state, Action action); + protected abstract void onTargetFound(@NonNull View targetView, @NonNull State state, + @NonNull Action action); /** * Holds information about a smooth scroll request by a {@link SmoothScroller}. */ public static class Action { - public static final int UNDEFINED_DURATION = Integer.MIN_VALUE; + public static final int UNDEFINED_DURATION = RecyclerView.UNDEFINED_DURATION; private int mDx; @@ -11604,7 +11943,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param dx Pixels to scroll horizontally * @param dy Pixels to scroll vertically */ - public Action(int dx, int dy) { + public Action(@Px int dx, @Px int dy) { this(dx, dy, UNDEFINED_DURATION, null); } @@ -11613,7 +11952,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param dy Pixels to scroll vertically * @param duration Duration of the animation in milliseconds */ - public Action(int dx, int dy, int duration) { + public Action(@Px int dx, @Px int dy, int duration) { this(dx, dy, duration, null); } @@ -11624,7 +11963,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param interpolator Interpolator to be used when calculating scroll position in each * animation step */ - public Action(int dx, int dy, int duration, Interpolator interpolator) { + public Action(@Px int dx, @Px int dy, int duration, + @Nullable Interpolator interpolator) { mDx = dx; mDy = dy; mDuration = duration; @@ -11664,16 +12004,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } if (mChanged) { validate(); - if (mInterpolator == null) { - if (mDuration == UNDEFINED_DURATION) { - recyclerView.mViewFlinger.smoothScrollBy(mDx, mDy); - } else { - recyclerView.mViewFlinger.smoothScrollBy(mDx, mDy, mDuration); - } - } else { - recyclerView.mViewFlinger.smoothScrollBy( - mDx, mDy, mDuration, mInterpolator); - } + recyclerView.mViewFlinger.smoothScrollBy(mDx, mDy, mDuration, mInterpolator); mConsecutiveUpdates++; if (mConsecutiveUpdates > 10) { // A new action is being set in every animation step. This looks like a bad @@ -11696,20 +12027,22 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } } + @Px public int getDx() { return mDx; } - public void setDx(int dx) { + public void setDx(@Px int dx) { mChanged = true; mDx = dx; } + @Px public int getDy() { return mDy; } - public void setDy(int dy) { + public void setDy(@Px int dy) { mChanged = true; mDy = dy; } @@ -11723,6 +12056,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro mDuration = duration; } + @Nullable public Interpolator getInterpolator() { return mInterpolator; } @@ -11733,7 +12067,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * also set the duration. * @see #setDuration(int) */ - public void setInterpolator(Interpolator interpolator) { + public void setInterpolator(@Nullable Interpolator interpolator) { mChanged = true; mInterpolator = interpolator; } @@ -11746,7 +12080,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param interpolator Interpolator to be used when calculating scroll position in each * animation step */ - public void update(int dx, int dy, int duration, Interpolator interpolator) { + public void update(@Px int dx, @Px int dy, int duration, + @Nullable Interpolator interpolator) { mDx = dx; mDy = dy; mDuration = duration; @@ -11776,6 +12111,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @return the scroll vector for a given position. */ + @Nullable PointF computeScrollVectorForPosition(int targetPosition); } } @@ -11841,7 +12177,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * This is public so that the CREATOR can be accessed on cold launch. * @hide */ - @RestrictTo(LIBRARY_GROUP) + @RestrictTo(LIBRARY_GROUP_PREFIX) public static class SavedState extends AbsSavedState { Parcelable mLayoutState; @@ -11915,7 +12251,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro /** Owned by SmoothScroller */ - private int mTargetPosition = RecyclerView.NO_POSITION; + int mTargetPosition = RecyclerView.NO_POSITION; private SparseArray mData; @@ -11989,17 +12325,6 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro //////////////////////////////////////////////////////////////////////////////////////////// - State reset() { - mTargetPosition = RecyclerView.NO_POSITION; - if (mData != null) { - mData.clear(); - } - mItemCount = 0; - mStructureChanged = false; - mIsMeasuring = false; - return this; - } - /** * Prepare for a prefetch occurring on the RecyclerView in between traversals, potentially * prior to any layout passes. @@ -12703,7 +13028,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @param item The item for which an animation should be stopped. */ - public abstract void endAnimation(ViewHolder item); + public abstract void endAnimation(@NonNull ViewHolder item); /** * Method called when all item animations should be ended immediately. @@ -12745,7 +13070,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param viewHolder The ViewHolder whose animation is finished. * @see #onAnimationFinished(ViewHolder) */ - public final void dispatchAnimationFinished(ViewHolder viewHolder) { + public final void dispatchAnimationFinished(@NonNull ViewHolder viewHolder) { onAnimationFinished(viewHolder); if (mListener != null) { mListener.onAnimationFinished(viewHolder); @@ -12760,7 +13085,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * animations running on this ViewHolder. * @see #dispatchAnimationFinished(ViewHolder) */ - public void onAnimationFinished(ViewHolder viewHolder) { + public void onAnimationFinished(@NonNull ViewHolder viewHolder) { } /** @@ -12786,7 +13111,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param viewHolder The ViewHolder whose animation is starting. * @see #onAnimationStarted(ViewHolder) */ - public final void dispatchAnimationStarted(ViewHolder viewHolder) { + public final void dispatchAnimationStarted(@NonNull ViewHolder viewHolder) { onAnimationStarted(viewHolder); } @@ -12797,7 +13122,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * might already be animating and this might be another animation. * @see #dispatchAnimationStarted(ViewHolder) */ - public void onAnimationStarted(ViewHolder viewHolder) { + public void onAnimationStarted(@NonNull ViewHolder viewHolder) { } @@ -12817,7 +13142,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * equivalent to calling {@link #isRunning()}. * @return true if there are any item animations currently running, false otherwise. */ - public final boolean isRunning(ItemAnimatorFinishedListener listener) { + public final boolean isRunning(@Nullable ItemAnimatorFinishedListener listener) { boolean running = isRunning(); if (listener != null) { if (!running) { @@ -12905,6 +13230,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * * @return A new {@link ItemHolderInfo}. */ + @NonNull public ItemHolderInfo obtainHolderInfo() { return new ItemHolderInfo(); } @@ -12915,7 +13241,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * create directly. */ interface ItemAnimatorListener { - void onAnimationFinished(ViewHolder item); + void onAnimationFinished(@NonNull ViewHolder item); } /** @@ -12983,7 +13309,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * @param holder The ViewHolder whose bounds should be copied. * @return This {@link ItemHolderInfo} */ - public ItemHolderInfo setFrom(RecyclerView.ViewHolder holder) { + @NonNull + public ItemHolderInfo setFrom(@NonNull RecyclerView.ViewHolder holder) { return setFrom(holder, 0); } @@ -12997,7 +13324,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro * List)}. * @return This {@link ItemHolderInfo} */ - public ItemHolderInfo setFrom(RecyclerView.ViewHolder holder, + @NonNull + public ItemHolderInfo setFrom(@NonNull RecyclerView.ViewHolder holder, @AdapterChanges int flags) { final View view = holder.itemView; this.left = view.getLeft(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/RecyclerViewAccessibilityDelegate.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerViewAccessibilityDelegate.java similarity index 90% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/RecyclerViewAccessibilityDelegate.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerViewAccessibilityDelegate.java index ad4745213..adfbb4369 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/RecyclerViewAccessibilityDelegate.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerViewAccessibilityDelegate.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,16 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; import android.os.Bundle; -import android.support.v4.view.AccessibilityDelegateCompat; -import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; import android.view.View; import android.view.accessibility.AccessibilityEvent; +import androidx.annotation.NonNull; +import androidx.core.view.AccessibilityDelegateCompat; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; + /** * The AccessibilityDelegate used by RecyclerView. *

    @@ -32,7 +34,7 @@ public class RecyclerViewAccessibilityDelegate extends AccessibilityDelegateComp final AccessibilityDelegateCompat mItemDelegate; - public RecyclerViewAccessibilityDelegate(RecyclerView recyclerView) { + public RecyclerViewAccessibilityDelegate(@NonNull RecyclerView recyclerView) { mRecyclerView = recyclerView; mItemDelegate = new ItemDelegate(this); } @@ -56,7 +58,6 @@ public class RecyclerViewAccessibilityDelegate extends AccessibilityDelegateComp @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) { super.onInitializeAccessibilityNodeInfo(host, info); - info.setClassName(RecyclerView.class.getName()); if (!shouldIgnore() && mRecyclerView.getLayoutManager() != null) { mRecyclerView.getLayoutManager().onInitializeAccessibilityNodeInfo(info); } @@ -65,7 +66,6 @@ public class RecyclerViewAccessibilityDelegate extends AccessibilityDelegateComp @Override public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { super.onInitializeAccessibilityEvent(host, event); - event.setClassName(RecyclerView.class.getName()); if (host instanceof RecyclerView && !shouldIgnore()) { RecyclerView rv = (RecyclerView) host; if (rv.getLayoutManager() != null) { @@ -79,6 +79,7 @@ public class RecyclerViewAccessibilityDelegate extends AccessibilityDelegateComp * A basic item delegate is provided by default, but you can override this * method to provide a custom per-item delegate. */ + @NonNull public AccessibilityDelegateCompat getItemDelegate() { return mItemDelegate; } @@ -99,7 +100,7 @@ public class RecyclerViewAccessibilityDelegate extends AccessibilityDelegateComp * * @param recyclerViewDelegate The parent RecyclerView's accessibility delegate. */ - public ItemDelegate(RecyclerViewAccessibilityDelegate recyclerViewDelegate) { + public ItemDelegate(@NonNull RecyclerViewAccessibilityDelegate recyclerViewDelegate) { mRecyclerViewDelegate = recyclerViewDelegate; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/ScrollbarHelper.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ScrollbarHelper.java similarity index 97% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/ScrollbarHelper.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/ScrollbarHelper.java index 8d979dbf7..8cc24aeb1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/ScrollbarHelper.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ScrollbarHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; import android.view.View; @@ -95,4 +95,7 @@ class ScrollbarHelper { // estimate a size for full list. return (int) ((float) laidOutArea / laidOutRange * state.getItemCount()); } + + private ScrollbarHelper() { + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/SimpleItemAnimator.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/SimpleItemAnimator.java similarity index 73% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/SimpleItemAnimator.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/SimpleItemAnimator.java index c98e468bd..536eb6d43 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/SimpleItemAnimator.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/SimpleItemAnimator.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,25 +14,23 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import org.telegram.messenger.support.widget.RecyclerView.Adapter; -import org.telegram.messenger.support.widget.RecyclerView.ItemAnimator.ItemHolderInfo; -import org.telegram.messenger.support.widget.RecyclerView.ViewHolder; import android.util.Log; import android.view.View; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + /** * A wrapper class for ItemAnimator that records View bounds and decides whether it should run * move, change, add or remove animations. This class also replicates the original ItemAnimator * API. *

    - * It uses {@link ItemHolderInfo} to track the bounds information of the Views. If you would like + * It uses {@link RecyclerView.ItemAnimator.ItemHolderInfo} to track the bounds information of the Views. If you would like * to * extend this class, you can override {@link #obtainHolderInfo()} method to provide your own info - * class that extends {@link ItemHolderInfo}. + * class that extends {@link RecyclerView.ItemAnimator.ItemHolderInfo}. */ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { @@ -57,17 +55,17 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * If you set this property to false, actions on the data set which change the * contents of items will not be animated. What those animations do is left * up to the discretion of the ItemAnimator subclass, in its - * {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)} implementation. + * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)} implementation. * The value of this property is true by default. * * @param supportsChangeAnimations true if change animations are supported by * this ItemAnimator, false otherwise. If the property is false, * the ItemAnimator * will not receive a call to - * {@link #animateChange(ViewHolder, ViewHolder, int, int, int, + * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, * int)} when changes occur. - * @see Adapter#notifyItemChanged(int) - * @see Adapter#notifyItemRangeChanged(int, int) + * @see RecyclerView.Adapter#notifyItemChanged(int) + * @see RecyclerView.Adapter#notifyItemRangeChanged(int, int) */ public void setSupportsChangeAnimations(boolean supportsChangeAnimations) { mSupportsChangeAnimations = supportsChangeAnimations; @@ -87,7 +85,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { } @Override - public boolean animateDisappearance(@NonNull ViewHolder viewHolder, + public boolean animateDisappearance(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull ItemHolderInfo preLayoutInfo, @Nullable ItemHolderInfo postLayoutInfo) { int oldLeft = preLayoutInfo.left; int oldTop = preLayoutInfo.top; @@ -111,7 +109,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { } @Override - public boolean animateAppearance(@NonNull ViewHolder viewHolder, + public boolean animateAppearance(@NonNull RecyclerView.ViewHolder viewHolder, @Nullable ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) { if (preLayoutInfo != null && (preLayoutInfo.left != postLayoutInfo.left || preLayoutInfo.top != postLayoutInfo.top)) { @@ -130,7 +128,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { } @Override - public boolean animatePersistence(@NonNull ViewHolder viewHolder, + public boolean animatePersistence(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) { if (preInfo.left != postInfo.left || preInfo.top != postInfo.top) { if (DEBUG) { @@ -145,7 +143,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { } @Override - public boolean animateChange(@NonNull ViewHolder oldHolder, @NonNull ViewHolder newHolder, + public boolean animateChange(@NonNull RecyclerView.ViewHolder oldHolder, @NonNull RecyclerView.ViewHolder newHolder, @NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) { if (DEBUG) { Log.d(TAG, "CHANGED: " + oldHolder + " with view " + oldHolder.itemView); @@ -166,15 +164,15 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { /** * Called when an item is removed from the RecyclerView. Implementors can choose * whether and how to animate that change, but must always call - * {@link #dispatchRemoveFinished(ViewHolder)} when done, either + * {@link #dispatchRemoveFinished(RecyclerView.ViewHolder)} when done, either * immediately (if no animation will occur) or after the animation actually finishes. * The return value indicates whether an animation has been set up and whether the * ItemAnimator's {@link #runPendingAnimations()} method should be called at the * next opportunity. This mechanism allows ItemAnimator to set up individual animations - * as separate calls to {@link #animateAdd(ViewHolder) animateAdd()}, - * {@link #animateMove(ViewHolder, int, int, int, int) animateMove()}, - * {@link #animateRemove(ViewHolder) animateRemove()}, and - * {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)} come in one by one, + * as separate calls to {@link #animateAdd(RecyclerView.ViewHolder) animateAdd()}, + * {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int) animateMove()}, + * {@link #animateRemove(RecyclerView.ViewHolder) animateRemove()}, and + * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)} come in one by one, * then start the animations together in the later call to {@link #runPendingAnimations()}. * *

    This method may also be called for disappearing items which continue to exist in the @@ -186,20 +184,20 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * @return true if a later call to {@link #runPendingAnimations()} is requested, * false otherwise. */ - public abstract boolean animateRemove(ViewHolder holder); + public abstract boolean animateRemove(RecyclerView.ViewHolder holder); /** * Called when an item is added to the RecyclerView. Implementors can choose * whether and how to animate that change, but must always call - * {@link #dispatchAddFinished(ViewHolder)} when done, either + * {@link #dispatchAddFinished(RecyclerView.ViewHolder)} when done, either * immediately (if no animation will occur) or after the animation actually finishes. * The return value indicates whether an animation has been set up and whether the * ItemAnimator's {@link #runPendingAnimations()} method should be called at the * next opportunity. This mechanism allows ItemAnimator to set up individual animations - * as separate calls to {@link #animateAdd(ViewHolder) animateAdd()}, - * {@link #animateMove(ViewHolder, int, int, int, int) animateMove()}, - * {@link #animateRemove(ViewHolder) animateRemove()}, and - * {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)} come in one by one, + * as separate calls to {@link #animateAdd(RecyclerView.ViewHolder) animateAdd()}, + * {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int) animateMove()}, + * {@link #animateRemove(RecyclerView.ViewHolder) animateRemove()}, and + * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)} come in one by one, * then start the animations together in the later call to {@link #runPendingAnimations()}. * *

    This method may also be called for appearing items which were already in the @@ -211,48 +209,48 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * @return true if a later call to {@link #runPendingAnimations()} is requested, * false otherwise. */ - public abstract boolean animateAdd(ViewHolder holder); + public abstract boolean animateAdd(RecyclerView.ViewHolder holder); /** * Called when an item is moved in the RecyclerView. Implementors can choose * whether and how to animate that change, but must always call - * {@link #dispatchMoveFinished(ViewHolder)} when done, either + * {@link #dispatchMoveFinished(RecyclerView.ViewHolder)} when done, either * immediately (if no animation will occur) or after the animation actually finishes. * The return value indicates whether an animation has been set up and whether the * ItemAnimator's {@link #runPendingAnimations()} method should be called at the * next opportunity. This mechanism allows ItemAnimator to set up individual animations - * as separate calls to {@link #animateAdd(ViewHolder) animateAdd()}, - * {@link #animateMove(ViewHolder, int, int, int, int) animateMove()}, - * {@link #animateRemove(ViewHolder) animateRemove()}, and - * {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)} come in one by one, + * as separate calls to {@link #animateAdd(RecyclerView.ViewHolder) animateAdd()}, + * {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int) animateMove()}, + * {@link #animateRemove(RecyclerView.ViewHolder) animateRemove()}, and + * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)} come in one by one, * then start the animations together in the later call to {@link #runPendingAnimations()}. * * @param holder The item that is being moved. * @return true if a later call to {@link #runPendingAnimations()} is requested, * false otherwise. */ - public abstract boolean animateMove(ViewHolder holder, int fromX, int fromY, + public abstract boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY); /** * Called when an item is changed in the RecyclerView, as indicated by a call to - * {@link Adapter#notifyItemChanged(int)} or - * {@link Adapter#notifyItemRangeChanged(int, int)}. + * {@link RecyclerView.Adapter#notifyItemChanged(int)} or + * {@link RecyclerView.Adapter#notifyItemRangeChanged(int, int)}. *

    * Implementers can choose whether and how to animate changes, but must always call - * {@link #dispatchChangeFinished(ViewHolder, boolean)} for each non-null distinct ViewHolder, + * {@link #dispatchChangeFinished(RecyclerView.ViewHolder, boolean)} for each non-null distinct ViewHolder, * either immediately (if no animation will occur) or after the animation actually finishes. * If the {@code oldHolder} is the same ViewHolder as the {@code newHolder}, you must call - * {@link #dispatchChangeFinished(ViewHolder, boolean)} once and only once. In that case, the + * {@link #dispatchChangeFinished(RecyclerView.ViewHolder, boolean)} once and only once. In that case, the * second parameter of {@code dispatchChangeFinished} is ignored. *

    * The return value indicates whether an animation has been set up and whether the * ItemAnimator's {@link #runPendingAnimations()} method should be called at the * next opportunity. This mechanism allows ItemAnimator to set up individual animations - * as separate calls to {@link #animateAdd(ViewHolder) animateAdd()}, - * {@link #animateMove(ViewHolder, int, int, int, int) animateMove()}, - * {@link #animateRemove(ViewHolder) animateRemove()}, and - * {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)} come in one by one, + * as separate calls to {@link #animateAdd(RecyclerView.ViewHolder) animateAdd()}, + * {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int) animateMove()}, + * {@link #animateRemove(RecyclerView.ViewHolder) animateRemove()}, and + * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)} come in one by one, * then start the animations together in the later call to {@link #runPendingAnimations()}. * * @param oldHolder The original item that changed. @@ -264,17 +262,17 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * @return true if a later call to {@link #runPendingAnimations()} is requested, * false otherwise. */ - public abstract boolean animateChange(ViewHolder oldHolder, - ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop); + public abstract boolean animateChange(RecyclerView.ViewHolder oldHolder, + RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop); /** * Method to be called by subclasses when a remove animation is done. * * @param item The item which has been removed - * @see RecyclerView.ItemAnimator#animateDisappearance(ViewHolder, ItemHolderInfo, + * @see RecyclerView.ItemAnimator#animateDisappearance(RecyclerView.ViewHolder, ItemHolderInfo, * ItemHolderInfo) */ - public final void dispatchRemoveFinished(ViewHolder item) { + public final void dispatchRemoveFinished(RecyclerView.ViewHolder item) { onRemoveFinished(item); dispatchAnimationFinished(item); } @@ -283,12 +281,13 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * Method to be called by subclasses when a move animation is done. * * @param item The item which has been moved - * @see RecyclerView.ItemAnimator#animateDisappearance(ViewHolder, ItemHolderInfo, + * @see RecyclerView.ItemAnimator#animateDisappearance(RecyclerView.ViewHolder, ItemHolderInfo, * ItemHolderInfo) - * @see RecyclerView.ItemAnimator#animatePersistence(ViewHolder, ItemHolderInfo, ItemHolderInfo) - * @see RecyclerView.ItemAnimator#animateAppearance(ViewHolder, ItemHolderInfo, ItemHolderInfo) + * @see RecyclerView.ItemAnimator#animatePersistence(RecyclerView.ViewHolder, ItemHolderInfo, ItemHolderInfo) + * + * @see RecyclerView.ItemAnimator#animateAppearance(RecyclerView.ViewHolder, ItemHolderInfo, ItemHolderInfo) */ - public final void dispatchMoveFinished(ViewHolder item) { + public final void dispatchMoveFinished(RecyclerView.ViewHolder item) { onMoveFinished(item); dispatchAnimationFinished(item); } @@ -298,7 +297,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * * @param item The item which has been added */ - public final void dispatchAddFinished(ViewHolder item) { + public final void dispatchAddFinished(RecyclerView.ViewHolder item) { onAddFinished(item); dispatchAnimationFinished(item); } @@ -308,12 +307,12 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * * @param item The item which has been changed (this method must be called for * each non-null ViewHolder passed into - * {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)}). + * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}). * @param oldItem true if this is the old item that was changed, false if * it is the new item that replaced the old item. - * @see #animateChange(ViewHolder, ViewHolder, int, int, int, int) + * @see #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int) */ - public final void dispatchChangeFinished(ViewHolder item, boolean oldItem) { + public final void dispatchChangeFinished(RecyclerView.ViewHolder item, boolean oldItem) { onChangeFinished(item, oldItem); dispatchAnimationFinished(item); } @@ -323,7 +322,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * * @param item The item being removed */ - public final void dispatchRemoveStarting(ViewHolder item) { + public final void dispatchRemoveStarting(RecyclerView.ViewHolder item) { onRemoveStarting(item); } @@ -332,7 +331,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * * @param item The item being moved */ - public final void dispatchMoveStarting(ViewHolder item) { + public final void dispatchMoveStarting(RecyclerView.ViewHolder item) { onMoveStarting(item); } @@ -341,7 +340,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * * @param item The item being added */ - public final void dispatchAddStarting(ViewHolder item) { + public final void dispatchAddStarting(RecyclerView.ViewHolder item) { onAddStarting(item); } @@ -350,11 +349,11 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * * @param item The item which has been changed (this method must be called for * each non-null ViewHolder passed into - * {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)}). + * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}). * @param oldItem true if this is the old item that was changed, false if * it is the new item that replaced the old item. */ - public final void dispatchChangeStarting(ViewHolder item, boolean oldItem) { + public final void dispatchChangeStarting(RecyclerView.ViewHolder item, boolean oldItem) { onChangeStarting(item, oldItem); } @@ -367,7 +366,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * @param item The ViewHolder being animated. */ @SuppressWarnings("UnusedParameters") - public void onRemoveStarting(ViewHolder item) { + public void onRemoveStarting(RecyclerView.ViewHolder item) { } /** @@ -378,7 +377,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * * @param item The ViewHolder being animated. */ - public void onRemoveFinished(ViewHolder item) { + public void onRemoveFinished(RecyclerView.ViewHolder item) { } /** @@ -390,7 +389,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * @param item The ViewHolder being animated. */ @SuppressWarnings("UnusedParameters") - public void onAddStarting(ViewHolder item) { + public void onAddStarting(RecyclerView.ViewHolder item) { } /** @@ -401,7 +400,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * * @param item The ViewHolder being animated. */ - public void onAddFinished(ViewHolder item) { + public void onAddFinished(RecyclerView.ViewHolder item) { } /** @@ -413,7 +412,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * @param item The ViewHolder being animated. */ @SuppressWarnings("UnusedParameters") - public void onMoveStarting(ViewHolder item) { + public void onMoveStarting(RecyclerView.ViewHolder item) { } /** @@ -424,7 +423,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * * @param item The ViewHolder being animated. */ - public void onMoveFinished(ViewHolder item) { + public void onMoveFinished(RecyclerView.ViewHolder item) { } /** @@ -438,7 +437,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * it is the new item that replaced the old item. */ @SuppressWarnings("UnusedParameters") - public void onChangeStarting(ViewHolder item, boolean oldItem) { + public void onChangeStarting(RecyclerView.ViewHolder item, boolean oldItem) { } /** @@ -451,7 +450,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { * @param oldItem true if this is the old item that was changed, false if * it is the new item that replaced the old item. */ - public void onChangeFinished(ViewHolder item, boolean oldItem) { + public void onChangeFinished(RecyclerView.ViewHolder item, boolean oldItem) { } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/SnapHelper.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/SnapHelper.java similarity index 88% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/SnapHelper.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/SnapHelper.java index a6a9426ac..ae987e38a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/SnapHelper.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/SnapHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,23 +14,21 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import org.telegram.messenger.support.widget.RecyclerView.LayoutManager; -import org.telegram.messenger.support.widget.RecyclerView.SmoothScroller; -import org.telegram.messenger.support.widget.RecyclerView.SmoothScroller.ScrollVectorProvider; import android.util.DisplayMetrics; import android.view.View; import android.view.animation.DecelerateInterpolator; import android.widget.Scroller; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + /** * Class intended to support snapping for a {@link RecyclerView}. *

    * SnapHelper tries to handle fling as well but for this to work properly, the - * {@link RecyclerView.LayoutManager} must implement the {@link ScrollVectorProvider} interface or + * {@link RecyclerView.LayoutManager} must implement the {@link RecyclerView.SmoothScroller.ScrollVectorProvider} interface or * you should override {@link #onFling(int, int)} and handle fling manually. */ public abstract class SnapHelper extends RecyclerView.OnFlingListener { @@ -64,7 +62,7 @@ public abstract class SnapHelper extends RecyclerView.OnFlingListener { @Override public boolean onFling(int velocityX, int velocityY) { - LayoutManager layoutManager = mRecyclerView.getLayoutManager(); + RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager(); if (layoutManager == null) { return false; } @@ -147,20 +145,20 @@ public abstract class SnapHelper extends RecyclerView.OnFlingListener { /** * Helper method to facilitate for snapping triggered by a fling. * - * @param layoutManager The {@link LayoutManager} associated with the attached + * @param layoutManager The {@link RecyclerView.LayoutManager} associated with the attached * {@link RecyclerView}. * @param velocityX Fling velocity on the horizontal axis. * @param velocityY Fling velocity on the vertical axis. * * @return true if it is handled, false otherwise. */ - private boolean snapFromFling(@NonNull LayoutManager layoutManager, int velocityX, + private boolean snapFromFling(@NonNull RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) { - if (!(layoutManager instanceof ScrollVectorProvider)) { + if (!(layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider)) { return false; } - SmoothScroller smoothScroller = createScroller(layoutManager); + RecyclerView.SmoothScroller smoothScroller = createScroller(layoutManager); if (smoothScroller == null) { return false; } @@ -184,7 +182,7 @@ public abstract class SnapHelper extends RecyclerView.OnFlingListener { if (mRecyclerView == null) { return; } - LayoutManager layoutManager = mRecyclerView.getLayoutManager(); + RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager(); if (layoutManager == null) { return; } @@ -204,10 +202,10 @@ public abstract class SnapHelper extends RecyclerView.OnFlingListener { * @param layoutManager The {@link RecyclerView.LayoutManager} associated with the attached * {@link RecyclerView}. * - * @return a {@link SmoothScroller} which will handle the scrolling. + * @return a {@link RecyclerView.SmoothScroller} which will handle the scrolling. */ @Nullable - protected SmoothScroller createScroller(LayoutManager layoutManager) { + protected RecyclerView.SmoothScroller createScroller(RecyclerView.LayoutManager layoutManager) { return createSnapScroller(layoutManager); } @@ -218,12 +216,12 @@ public abstract class SnapHelper extends RecyclerView.OnFlingListener { * {@link RecyclerView}. * * @return a {@link LinearSmoothScroller} which will handle the scrolling. - * @deprecated use {@link #createScroller(LayoutManager)} instead. + * @deprecated use {@link #createScroller(RecyclerView.LayoutManager)} instead. */ @Nullable @Deprecated - protected LinearSmoothScroller createSnapScroller(LayoutManager layoutManager) { - if (!(layoutManager instanceof ScrollVectorProvider)) { + protected LinearSmoothScroller createSnapScroller(RecyclerView.LayoutManager layoutManager) { + if (!(layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider)) { return null; } return new LinearSmoothScroller(mRecyclerView.getContext()) { @@ -266,7 +264,7 @@ public abstract class SnapHelper extends RecyclerView.OnFlingListener { */ @SuppressWarnings("WeakerAccess") @Nullable - public abstract int[] calculateDistanceToFinalSnap(@NonNull LayoutManager layoutManager, + public abstract int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager, @NonNull View targetView); /** @@ -286,7 +284,7 @@ public abstract class SnapHelper extends RecyclerView.OnFlingListener { */ @SuppressWarnings("WeakerAccess") @Nullable - public abstract View findSnapView(LayoutManager layoutManager); + public abstract View findSnapView(RecyclerView.LayoutManager layoutManager); /** * Override to provide a particular adapter target position for snapping. @@ -299,6 +297,6 @@ public abstract class SnapHelper extends RecyclerView.OnFlingListener { * @return the target adapter position to you want to snap or {@link RecyclerView#NO_POSITION} * if no snapping should happen */ - public abstract int findTargetSnapPosition(LayoutManager layoutManager, int velocityX, + public abstract int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/SortedList.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/SortedList.java similarity index 97% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/util/SortedList.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/SortedList.java index bf6c2764e..54e46f955 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/SortedList.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/SortedList.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,10 @@ * limitations under the License. */ -package org.telegram.messenger.support.util; +package androidx.recyclerview.widget; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import java.lang.reflect.Array; import java.util.Arrays; @@ -27,7 +27,7 @@ import java.util.Comparator; /** * A Sorted list implementation that can keep items in order and also notify for changes in the * list - * such that it can be bound to a {@link android.support.v7.widget.RecyclerView.Adapter + * such that it can be bound to a {@link RecyclerView.Adapter * RecyclerView.Adapter}. *

    * It keeps items ordered using the {@link Callback#compare(Object, Object)} method and uses @@ -40,7 +40,7 @@ import java.util.Comparator; public class SortedList { /** - * Used by {@link #indexOf(Object)} when he item cannot be found in the list. + * Used by {@link #indexOf(Object)} when the item cannot be found in the list. */ public static final int INVALID_POSITION = -1; @@ -87,7 +87,7 @@ public class SortedList { * @param klass The class of the contents of the SortedList. * @param callback The callback that controls the behavior of SortedList. */ - public SortedList(Class klass, Callback callback) { + public SortedList(@NonNull Class klass, @NonNull Callback callback) { this(klass, callback, MIN_CAPACITY); } @@ -98,7 +98,7 @@ public class SortedList { * @param callback The callback that controls the behavior of SortedList. * @param initialCapacity The initial capacity to hold items. */ - public SortedList(Class klass, Callback callback, int initialCapacity) { + public SortedList(@NonNull Class klass, @NonNull Callback callback, int initialCapacity) { mTClass = klass; mData = (T[]) Array.newInstance(klass, initialCapacity); mCallback = callback; @@ -158,7 +158,7 @@ public class SortedList { * input array. * @see SortedList#addAll(T[] items) */ - public void addAll(T[] items, boolean mayModifyInput) { + public void addAll(@NonNull T[] items, boolean mayModifyInput) { throwIfInMutationOperation(); if (items.length == 0) { return; @@ -178,7 +178,7 @@ public class SortedList { * * @param items Array of items to be added into the list. */ - public void addAll(T... items) { + public void addAll(@NonNull T... items) { addAll(items, false); } @@ -189,7 +189,7 @@ public class SortedList { * * @param items Collection of items to be added into the list. */ - public void addAll(Collection items) { + public void addAll(@NonNull Collection items) { T[] copy = (T[]) Array.newInstance(mTClass, items.size()); addAll(items.toArray(copy), true); } @@ -876,7 +876,7 @@ public class SortedList { * that you can change its behavior depending on your UI. *

    * For example, if you are using SortedList with a - * {@link android.support.v7.widget.RecyclerView.Adapter RecyclerView.Adapter}, you should + * {@link RecyclerView.Adapter RecyclerView.Adapter}, you should * return whether the items' visual representations are the same or not. * * @param oldItem The previous representation of the object. @@ -904,9 +904,9 @@ public class SortedList { * method to get a payload about the change. *

    * For example, if you are using {@link Callback} with - * {@link android.support.v7.widget.RecyclerView}, you can return the particular field that + * {@link RecyclerView}, you can return the particular field that * changed in the item and your - * {@link android.support.v7.widget.RecyclerView.ItemAnimator ItemAnimator} can use that + * {@link RecyclerView.ItemAnimator ItemAnimator} can use that * information to run the correct animation. *

    * Default implementation returns {@code null}. diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/util/SortedListAdapterCallback.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/SortedListAdapterCallback.java similarity index 89% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/util/SortedListAdapterCallback.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/SortedListAdapterCallback.java index 79169c9f2..11f2412f9 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/util/SortedListAdapterCallback.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/SortedListAdapterCallback.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,7 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget.util; - -import org.telegram.messenger.support.util.SortedList; -import org.telegram.messenger.support.widget.RecyclerView; +package androidx.recyclerview.widget; /** * A {@link SortedList.Callback} implementation that can bind a {@link SortedList} to a diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/StaggeredGridLayoutManager.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/StaggeredGridLayoutManager.java similarity index 96% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/StaggeredGridLayoutManager.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/StaggeredGridLayoutManager.java index 4324fcbe5..dc0bd4fc3 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/StaggeredGridLayoutManager.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/StaggeredGridLayoutManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,32 +14,29 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; -import static android.support.annotation.RestrictTo.Scope.LIBRARY; -import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; -import static org.telegram.messenger.support.widget.LayoutState.ITEM_DIRECTION_HEAD; -import static org.telegram.messenger.support.widget.LayoutState.ITEM_DIRECTION_TAIL; -import static org.telegram.messenger.support.widget.LayoutState.LAYOUT_END; -import static org.telegram.messenger.support.widget.LayoutState.LAYOUT_START; -import static org.telegram.messenger.support.widget.RecyclerView.NO_POSITION; +import static androidx.annotation.RestrictTo.Scope.LIBRARY; +import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.PointF; import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.RestrictTo; -import android.support.v4.view.ViewCompat; -import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RestrictTo; +import androidx.core.view.ViewCompat; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; + import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; @@ -147,7 +144,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple * When LayoutManager needs to scroll to a position, it sets this variable and requests a * layout which will check this variable and re-layout accordingly. */ - int mPendingScrollPosition = NO_POSITION; + int mPendingScrollPosition = RecyclerView.NO_POSITION; /** * Used to keep the offset value when {@link #scrollToPositionWithOffset(int, int)} is @@ -279,7 +276,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple if (!mLaidOutInvalidFullSpan) { return false; } - int invalidGapDir = mShouldReverseLayout ? LAYOUT_START : LAYOUT_END; + int invalidGapDir = mShouldReverseLayout ? LayoutState.LAYOUT_START : LayoutState.LAYOUT_END; final LazySpanLookup.FullSpanItem invalidFsi = mLazySpanLookup .getFirstFullSpanItemInRange(minPos, maxPos + 1, invalidGapDir, true); if (invalidFsi == null) { @@ -598,7 +595,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple private void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state, boolean shouldCheckForGaps) { final AnchorInfo anchorInfo = mAnchorInfo; - if (mPendingSavedState != null || mPendingScrollPosition != NO_POSITION) { + if (mPendingSavedState != null || mPendingScrollPosition != RecyclerView.NO_POSITION) { if (state.getItemCount() == 0) { removeAndRecycleAllViews(recycler); anchorInfo.reset(); @@ -606,7 +603,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple } } - boolean recalculateAnchor = !anchorInfo.mValid || mPendingScrollPosition != NO_POSITION + boolean recalculateAnchor = !anchorInfo.mValid || mPendingScrollPosition != RecyclerView.NO_POSITION || mPendingSavedState != null; if (recalculateAnchor) { anchorInfo.reset(); @@ -619,7 +616,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple updateAnchorInfoForLayout(state, anchorInfo); anchorInfo.mValid = true; } - if (mPendingSavedState == null && mPendingScrollPosition == NO_POSITION) { + if (mPendingSavedState == null && mPendingScrollPosition == RecyclerView.NO_POSITION) { if (anchorInfo.mLayoutFromEnd != mLastLayoutFromEnd || isLayoutRTL() != mLastLayoutRTL) { mLazySpanLookup.clear(); @@ -660,18 +657,18 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple updateLayoutState(anchorInfo.mPosition, state); if (anchorInfo.mLayoutFromEnd) { // Layout start. - setLayoutStateDirection(LAYOUT_START); + setLayoutStateDirection(LayoutState.LAYOUT_START); fill(recycler, mLayoutState, state); // Layout end. - setLayoutStateDirection(LAYOUT_END); + setLayoutStateDirection(LayoutState.LAYOUT_END); mLayoutState.mCurrentPosition = anchorInfo.mPosition + mLayoutState.mItemDirection; fill(recycler, mLayoutState, state); } else { // Layout end. - setLayoutStateDirection(LAYOUT_END); + setLayoutStateDirection(LayoutState.LAYOUT_END); fill(recycler, mLayoutState, state); // Layout start. - setLayoutStateDirection(LAYOUT_START); + setLayoutStateDirection(LayoutState.LAYOUT_START); mLayoutState.mCurrentPosition = anchorInfo.mPosition + mLayoutState.mItemDirection; fill(recycler, mLayoutState, state); } @@ -713,7 +710,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple @Override public void onLayoutCompleted(RecyclerView.State state) { super.onLayoutCompleted(state); - mPendingScrollPosition = NO_POSITION; + mPendingScrollPosition = RecyclerView.NO_POSITION; mPendingScrollPositionOffset = INVALID_OFFSET; mPendingSavedState = null; // we don't need this anymore mAnchorInfo.reset(); @@ -795,7 +792,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple setReverseLayout(mPendingSavedState.mReverseLayout); resolveShouldLayoutReverse(); - if (mPendingSavedState.mAnchorPosition != NO_POSITION) { + if (mPendingSavedState.mAnchorPosition != RecyclerView.NO_POSITION) { mPendingScrollPosition = mPendingSavedState.mAnchorPosition; anchorInfo.mLayoutFromEnd = mPendingSavedState.mAnchorLayoutFromEnd; } else { @@ -835,17 +832,17 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple boolean updateAnchorFromPendingData(RecyclerView.State state, AnchorInfo anchorInfo) { // Validate scroll position if exists. - if (state.isPreLayout() || mPendingScrollPosition == NO_POSITION) { + if (state.isPreLayout() || mPendingScrollPosition == RecyclerView.NO_POSITION) { return false; } // Validate it. if (mPendingScrollPosition < 0 || mPendingScrollPosition >= state.getItemCount()) { - mPendingScrollPosition = NO_POSITION; + mPendingScrollPosition = RecyclerView.NO_POSITION; mPendingScrollPositionOffset = INVALID_OFFSET; return false; } - if (mPendingSavedState == null || mPendingSavedState.mAnchorPosition == NO_POSITION + if (mPendingSavedState == null || mPendingSavedState.mAnchorPosition == RecyclerView.NO_POSITION || mPendingSavedState.mSpanOffsetsSize < 1) { // If item is visible, make it fully visible. final View child = findViewByPosition(mPendingScrollPosition); @@ -898,7 +895,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple if (mPendingScrollPositionOffset == INVALID_OFFSET) { final int position = calculateScrollDirectionForPosition( anchorInfo.mPosition); - anchorInfo.mLayoutFromEnd = position == LAYOUT_END; + anchorInfo.mLayoutFromEnd = position == LayoutState.LAYOUT_END; anchorInfo.assignCoordinateFromPadding(); } else { anchorInfo.assignCoordinateFromPadding(mPendingScrollPositionOffset); @@ -1256,8 +1253,8 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple state.mSpanOffsets[i] = line; } } else { - state.mAnchorPosition = NO_POSITION; - state.mVisibleAnchorPosition = NO_POSITION; + state.mAnchorPosition = RecyclerView.NO_POSITION; + state.mVisibleAnchorPosition = RecyclerView.NO_POSITION; state.mSpanOffsetsSize = 0; } if (DEBUG) { @@ -1317,7 +1314,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple int findFirstVisibleItemPositionInt() { final View first = mShouldReverseLayout ? findFirstVisibleItemClosestToEnd(true) : findFirstVisibleItemClosestToStart(true); - return first == null ? NO_POSITION : getPosition(first); + return first == null ? RecyclerView.NO_POSITION : getPosition(first); } @Override @@ -1442,7 +1439,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple int endExtra = 0; if (isSmoothScrolling()) { final int targetPos = state.getTargetScrollPosition(); - if (targetPos != NO_POSITION) { + if (targetPos != RecyclerView.NO_POSITION) { if (mShouldReverseLayout == targetPos < anchorPosition) { endExtra = mPrimaryOrientation.getTotalSpace(); } else { @@ -1468,8 +1465,8 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple private void setLayoutStateDirection(int direction) { mLayoutState.mLayoutDirection = direction; - mLayoutState.mItemDirection = (mShouldReverseLayout == (direction == LAYOUT_START)) - ? ITEM_DIRECTION_TAIL : ITEM_DIRECTION_HEAD; + mLayoutState.mItemDirection = (mShouldReverseLayout == (direction == LayoutState.LAYOUT_START)) + ? LayoutState.ITEM_DIRECTION_TAIL : LayoutState.ITEM_DIRECTION_HEAD; } @Override @@ -1569,13 +1566,13 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple // Line of the furthest row. if (mLayoutState.mInfinite) { - if (layoutState.mLayoutDirection == LAYOUT_END) { + if (layoutState.mLayoutDirection == LayoutState.LAYOUT_END) { targetLine = Integer.MAX_VALUE; } else { // LAYOUT_START targetLine = Integer.MIN_VALUE; } } else { - if (layoutState.mLayoutDirection == LAYOUT_END) { + if (layoutState.mLayoutDirection == LayoutState.LAYOUT_END) { targetLine = layoutState.mEndLine + layoutState.mAvailable; } else { // LAYOUT_START targetLine = layoutState.mStartLine - layoutState.mAvailable; @@ -1615,7 +1612,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple } // assign span before measuring so that item decorators can get updated span index lp.mSpan = currentSpan; - if (layoutState.mLayoutDirection == LAYOUT_END) { + if (layoutState.mLayoutDirection == LayoutState.LAYOUT_END) { addView(view); } else { addView(view, 0); @@ -1624,14 +1621,14 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple final int start; final int end; - if (layoutState.mLayoutDirection == LAYOUT_END) { + if (layoutState.mLayoutDirection == LayoutState.LAYOUT_END) { start = lp.mFullSpan ? getMaxEnd(defaultNewViewLine) : currentSpan.getEndLine(defaultNewViewLine); end = start + mPrimaryOrientation.getDecoratedMeasurement(view); if (assignSpan && lp.mFullSpan) { LazySpanLookup.FullSpanItem fullSpanItem; fullSpanItem = createFullSpanItemFromEnd(start); - fullSpanItem.mGapDir = LAYOUT_START; + fullSpanItem.mGapDir = LayoutState.LAYOUT_START; fullSpanItem.mPosition = position; mLazySpanLookup.addFullSpanItem(fullSpanItem); } @@ -1642,19 +1639,19 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple if (assignSpan && lp.mFullSpan) { LazySpanLookup.FullSpanItem fullSpanItem; fullSpanItem = createFullSpanItemFromStart(end); - fullSpanItem.mGapDir = LAYOUT_END; + fullSpanItem.mGapDir = LayoutState.LAYOUT_END; fullSpanItem.mPosition = position; mLazySpanLookup.addFullSpanItem(fullSpanItem); } } // check if this item may create gaps in the future - if (lp.mFullSpan && layoutState.mItemDirection == ITEM_DIRECTION_HEAD) { + if (lp.mFullSpan && layoutState.mItemDirection == LayoutState.ITEM_DIRECTION_HEAD) { if (assignSpan) { mLaidOutInvalidFullSpan = true; } else { final boolean hasInvalidGap; - if (layoutState.mLayoutDirection == LAYOUT_END) { + if (layoutState.mLayoutDirection == LayoutState.LAYOUT_END) { hasInvalidGap = !areAllEndsEqual(); } else { // layoutState.mLayoutDirection == LAYOUT_START hasInvalidGap = !areAllStartsEqual(); @@ -1709,7 +1706,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple recycle(recycler, mLayoutState); } final int diff; - if (mLayoutState.mLayoutDirection == LAYOUT_START) { + if (mLayoutState.mLayoutDirection == LayoutState.LAYOUT_START) { final int minStart = getMinStart(mPrimaryOrientation.getStartAfterPadding()); diff = mPrimaryOrientation.getStartAfterPadding() - minStart; } else { @@ -1759,7 +1756,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple } if (layoutState.mAvailable == 0) { // easy, recycle line is still valid - if (layoutState.mLayoutDirection == LAYOUT_START) { + if (layoutState.mLayoutDirection == LayoutState.LAYOUT_START) { recycleFromEnd(recycler, layoutState.mEndLine); } else { recycleFromStart(recycler, layoutState.mStartLine); @@ -1767,7 +1764,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple } else { // scrolling case, recycle line can be shifted by how much space we could cover // by adding new views - if (layoutState.mLayoutDirection == LAYOUT_START) { + if (layoutState.mLayoutDirection == LayoutState.LAYOUT_START) { // calculate recycle line int scrolled = layoutState.mStartLine - getMaxStart(layoutState.mStartLine); final int line; @@ -1817,7 +1814,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple private void updateRemainingSpans(Span span, int layoutDir, int targetLine) { final int deletedSize = span.getDeletedSize(); - if (layoutDir == LAYOUT_START) { + if (layoutDir == LayoutState.LAYOUT_START) { final int line = span.getStartLine(); if (line + deletedSize <= targetLine) { mRemainingSpans.set(span.mIndex, false); @@ -1959,9 +1956,9 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple */ private boolean preferLastSpan(int layoutDir) { if (mOrientation == HORIZONTAL) { - return (layoutDir == LAYOUT_START) != mShouldReverseLayout; + return (layoutDir == LayoutState.LAYOUT_START) != mShouldReverseLayout; } - return ((layoutDir == LAYOUT_START) == mShouldReverseLayout) == isLayoutRTL(); + return ((layoutDir == LayoutState.LAYOUT_START) == mShouldReverseLayout) == isLayoutRTL(); } /** @@ -1979,7 +1976,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple endIndex = mSpanCount; diff = 1; } - if (layoutState.mLayoutDirection == LAYOUT_END) { + if (layoutState.mLayoutDirection == LayoutState.LAYOUT_END) { Span min = null; int minLine = Integer.MAX_VALUE; final int defaultLine = mPrimaryOrientation.getStartAfterPadding(); @@ -2032,10 +2029,10 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple private int calculateScrollDirectionForPosition(int position) { if (getChildCount() == 0) { - return mShouldReverseLayout ? LAYOUT_END : LAYOUT_START; + return mShouldReverseLayout ? LayoutState.LAYOUT_END : LayoutState.LAYOUT_START; } final int firstChildPos = getFirstChildPosition(); - return position < firstChildPos != mShouldReverseLayout ? LAYOUT_START : LAYOUT_END; + return position < firstChildPos != mShouldReverseLayout ? LayoutState.LAYOUT_START : LayoutState.LAYOUT_END; } @Override @@ -2126,7 +2123,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple int itemPrefetchCount = 0; for (int i = 0; i < mSpanCount; i++) { // compute number of pixels past the edge of the viewport that the current span extends - int distance = mLayoutState.mItemDirection == LAYOUT_START + int distance = mLayoutState.mItemDirection == LayoutState.LAYOUT_START ? mLayoutState.mStartLine - mSpans[i].getStartLine(mLayoutState.mStartLine) : mSpans[i].getEndLine(mLayoutState.mEndLine) - mLayoutState.mEndLine; if (distance >= 0) { @@ -2149,10 +2146,10 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple final int referenceChildPosition; final int layoutDir; if (delta > 0) { // layout towards end - layoutDir = LAYOUT_END; + layoutDir = LayoutState.LAYOUT_END; referenceChildPosition = getLastChildPosition(); } else { - layoutDir = LAYOUT_START; + layoutDir = LayoutState.LAYOUT_START; referenceChildPosition = getFirstChildPosition(); } mLayoutState.mRecycle = true; @@ -2290,7 +2287,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple boolean prevFocusFullSpan = prevFocusLayoutParams.mFullSpan; final Span prevFocusSpan = prevFocusLayoutParams.mSpan; final int referenceChildPosition; - if (layoutDir == LAYOUT_END) { // layout towards end + if (layoutDir == LayoutState.LAYOUT_END) { // layout towards end referenceChildPosition = getLastChildPosition(); } else { referenceChildPosition = getFirstChildPosition(); @@ -2525,7 +2522,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple if (lp.mFullSpan) { LazySpanLookup.FullSpanItem fsi = mLazySpanLookup .getFullSpanItem(lp.getViewLayoutPosition()); - if (fsi != null && fsi.mGapDir == LAYOUT_START) { + if (fsi != null && fsi.mGapDir == LayoutState.LAYOUT_START) { mCachedStart -= fsi.getGapForSpan(mIndex); } } @@ -2559,7 +2556,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple if (lp.mFullSpan) { LazySpanLookup.FullSpanItem fsi = mLazySpanLookup .getFullSpanItem(lp.getViewLayoutPosition()); - if (fsi != null && fsi.mGapDir == LAYOUT_END) { + if (fsi != null && fsi.mGapDir == LayoutState.LAYOUT_END) { mCachedEnd += fsi.getGapForSpan(mIndex); } } @@ -2771,7 +2768,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple } } } - return NO_POSITION; + return RecyclerView.NO_POSITION; } int findOneVisibleChild(int fromIndex, int toIndex, boolean completelyVisible) { @@ -2790,7 +2787,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple */ public View getFocusableViewAfter(int referenceChildPosition, int layoutDir) { View candidate = null; - if (layoutDir == LAYOUT_START) { + if (layoutDir == LayoutState.LAYOUT_START) { final int limit = mViews.size(); for (int i = 0; i < limit; i++) { final View view = mViews.get(i); @@ -3060,6 +3057,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple /** * We keep information about full span items because they may create gaps in the UI. */ + @SuppressLint("BanParcelableUsage") static class FullSpanItem implements Parcelable { int mPosition; @@ -3134,7 +3132,8 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple /** * @hide */ - @RestrictTo(LIBRARY_GROUP) + @RestrictTo(LIBRARY_GROUP_PREFIX) + @SuppressLint("BanParcelableUsage") public static class SavedState implements Parcelable { int mAnchorPosition; @@ -3168,9 +3167,10 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple mReverseLayout = in.readInt() == 1; mAnchorLayoutFromEnd = in.readInt() == 1; mLastLayoutRTL = in.readInt() == 1; - //noinspection unchecked - mFullSpanItems = in.readArrayList( - LazySpanLookup.FullSpanItem.class.getClassLoader()); + @SuppressWarnings("unchecked") + List fullSpanItems = + in.readArrayList(LazySpanLookup.FullSpanItem.class.getClassLoader()); + mFullSpanItems = fullSpanItems; } public SavedState(SavedState other) { @@ -3197,8 +3197,8 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple void invalidateAnchorPositionInfo() { mSpanOffsets = null; mSpanOffsetsSize = 0; - mAnchorPosition = NO_POSITION; - mVisibleAnchorPosition = NO_POSITION; + mAnchorPosition = RecyclerView.NO_POSITION; + mVisibleAnchorPosition = RecyclerView.NO_POSITION; } @Override @@ -3257,7 +3257,7 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager imple } void reset() { - mPosition = NO_POSITION; + mPosition = RecyclerView.NO_POSITION; mOffset = INVALID_OFFSET; mLayoutFromEnd = false; mInvalidateOffsets = false; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/ThreadUtil.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ThreadUtil.java similarity index 92% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/util/ThreadUtil.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/ThreadUtil.java index cdb8689fc..b32916a98 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/ThreadUtil.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ThreadUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.telegram.messenger.support.util; +package androidx.recyclerview.widget; interface ThreadUtil { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/TileList.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/TileList.java similarity index 92% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/util/TileList.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/TileList.java index 1b943d90e..c445aff37 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/util/TileList.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/TileList.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.telegram.messenger.support.util; +package androidx.recyclerview.widget; import android.util.SparseArray; @@ -90,8 +90,9 @@ class TileList { Tile mNext; // Used only for pooling recycled tiles. public Tile(Class klass, int size) { - //noinspection unchecked - mItems = (T[]) Array.newInstance(klass, size); + @SuppressWarnings("unchecked") + T[] items = (T[]) Array.newInstance(klass, size); + mItems = items; } boolean containsPosition(int pos) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/ViewBoundsCheck.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ViewBoundsCheck.java similarity index 96% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/ViewBoundsCheck.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/ViewBoundsCheck.java index 822656c05..8ea8f7533 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/ViewBoundsCheck.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ViewBoundsCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,11 +14,12 @@ * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; -import android.support.annotation.IntDef; import android.view.View; +import androidx.annotation.IntDef; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -143,10 +144,6 @@ class ViewBoundsCheck { mChildEnd = childEnd; } - void setFlags(@ViewBounds int flags, int mask) { - mBoundFlags = (mBoundFlags & ~mask) | (flags & mask); - } - void addFlags(@ViewBounds int flags) { mBoundFlags |= flags; } @@ -263,8 +260,6 @@ class ViewBoundsCheck { * parent boundaries. */ interface Callback { - int getChildCount(); - View getParent(); View getChildAt(int index); int getParentStart(); int getParentEnd(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/ViewInfoStore.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ViewInfoStore.java similarity index 75% rename from TMessagesProj/src/main/java/org/telegram/messenger/support/widget/ViewInfoStore.java rename to TMessagesProj/src/main/java/androidx/recyclerview/widget/ViewInfoStore.java index dc250de9c..09e43d387 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/ViewInfoStore.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ViewInfoStore.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,24 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.telegram.messenger.support.widget; +package androidx.recyclerview.widget; -import static org.telegram.messenger.support.widget.RecyclerView.ItemAnimator.ItemHolderInfo; -import static org.telegram.messenger.support.widget.RecyclerView.ViewHolder; -import static org.telegram.messenger.support.widget.ViewInfoStore.InfoRecord.FLAG_APPEAR; -import static org.telegram.messenger.support.widget.ViewInfoStore.InfoRecord.FLAG_APPEAR_AND_DISAPPEAR; -import static org.telegram.messenger.support.widget.ViewInfoStore.InfoRecord.FLAG_APPEAR_PRE_AND_POST; -import static org.telegram.messenger.support.widget.ViewInfoStore.InfoRecord.FLAG_DISAPPEARED; -import static org.telegram.messenger.support.widget.ViewInfoStore.InfoRecord.FLAG_POST; -import static org.telegram.messenger.support.widget.ViewInfoStore.InfoRecord.FLAG_PRE; -import static org.telegram.messenger.support.widget.ViewInfoStore.InfoRecord.FLAG_PRE_AND_POST; +import static androidx.recyclerview.widget.ViewInfoStore.InfoRecord.FLAG_APPEAR; +import static androidx.recyclerview.widget.ViewInfoStore.InfoRecord.FLAG_APPEAR_AND_DISAPPEAR; +import static androidx.recyclerview.widget.ViewInfoStore.InfoRecord.FLAG_APPEAR_PRE_AND_POST; +import static androidx.recyclerview.widget.ViewInfoStore.InfoRecord.FLAG_DISAPPEARED; +import static androidx.recyclerview.widget.ViewInfoStore.InfoRecord.FLAG_POST; +import static androidx.recyclerview.widget.ViewInfoStore.InfoRecord.FLAG_PRE; +import static androidx.recyclerview.widget.ViewInfoStore.InfoRecord.FLAG_PRE_AND_POST; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.VisibleForTesting; -import android.support.v4.util.ArrayMap; -import android.support.v4.util.LongSparseArray; -import android.support.v4.util.Pools; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; +import androidx.collection.ArrayMap; +import androidx.collection.LongSparseArray; +import androidx.core.util.Pools; /** * This class abstracts all tracking for Views to run animations. */ @@ -42,10 +40,10 @@ class ViewInfoStore { * View data records for pre-layout */ @VisibleForTesting - final ArrayMap mLayoutHolderMap = new ArrayMap<>(); + final ArrayMap mLayoutHolderMap = new ArrayMap<>(); @VisibleForTesting - final LongSparseArray mOldChangedHolders = new LongSparseArray<>(); + final LongSparseArray mOldChangedHolders = new LongSparseArray<>(); /** * Clears the state and all existing tracking data @@ -60,7 +58,7 @@ class ViewInfoStore { * @param holder The ViewHolder whose information is being saved * @param info The information to save */ - void addToPreLayout(ViewHolder holder, ItemHolderInfo info) { + void addToPreLayout(RecyclerView.ViewHolder holder, RecyclerView.ItemAnimator.ItemHolderInfo info) { InfoRecord record = mLayoutHolderMap.get(holder); if (record == null) { record = InfoRecord.obtain(); @@ -70,7 +68,7 @@ class ViewInfoStore { record.flags |= FLAG_PRE; } - boolean isDisappearing(ViewHolder holder) { + boolean isDisappearing(RecyclerView.ViewHolder holder) { final InfoRecord record = mLayoutHolderMap.get(holder); return record != null && ((record.flags & FLAG_DISAPPEARED) != 0); } @@ -82,7 +80,7 @@ class ViewInfoStore { * @return The ItemHolderInfo for the given ViewHolder or null if it does not exist */ @Nullable - ItemHolderInfo popFromPreLayout(ViewHolder vh) { + RecyclerView.ItemAnimator.ItemHolderInfo popFromPreLayout(RecyclerView.ViewHolder vh) { return popFromLayoutStep(vh, FLAG_PRE); } @@ -93,11 +91,11 @@ class ViewInfoStore { * @return The ItemHolderInfo for the given ViewHolder or null if it does not exist */ @Nullable - ItemHolderInfo popFromPostLayout(ViewHolder vh) { + RecyclerView.ItemAnimator.ItemHolderInfo popFromPostLayout(RecyclerView.ViewHolder vh) { return popFromLayoutStep(vh, FLAG_POST); } - private ItemHolderInfo popFromLayoutStep(ViewHolder vh, int flag) { + private RecyclerView.ItemAnimator.ItemHolderInfo popFromLayoutStep(RecyclerView.ViewHolder vh, int flag) { int index = mLayoutHolderMap.indexOfKey(vh); if (index < 0) { return null; @@ -105,7 +103,7 @@ class ViewInfoStore { final InfoRecord record = mLayoutHolderMap.valueAt(index); if (record != null && (record.flags & flag) != 0) { record.flags &= ~flag; - final ItemHolderInfo info; + final RecyclerView.ItemAnimator.ItemHolderInfo info; if (flag == FLAG_PRE) { info = record.preInfo; } else if (flag == FLAG_POST) { @@ -128,7 +126,7 @@ class ViewInfoStore { * @param key The key to identify the ViewHolder. * @param holder The ViewHolder to store */ - void addToOldChangeHolders(long key, ViewHolder holder) { + void addToOldChangeHolders(long key, RecyclerView.ViewHolder holder) { mOldChangedHolders.put(key, holder); } @@ -141,7 +139,7 @@ class ViewInfoStore { * @param holder The ViewHolder to store * @param info The information to save */ - void addToAppearedInPreLayoutHolders(ViewHolder holder, ItemHolderInfo info) { + void addToAppearedInPreLayoutHolders(RecyclerView.ViewHolder holder, RecyclerView.ItemAnimator.ItemHolderInfo info) { InfoRecord record = mLayoutHolderMap.get(holder); if (record == null) { record = InfoRecord.obtain(); @@ -157,7 +155,7 @@ class ViewInfoStore { * * @return True if the ViewHolder is present in preLayout, false otherwise */ - boolean isInPreLayout(ViewHolder viewHolder) { + boolean isInPreLayout(RecyclerView.ViewHolder viewHolder) { final InfoRecord record = mLayoutHolderMap.get(viewHolder); return record != null && (record.flags & FLAG_PRE) != 0; } @@ -169,7 +167,7 @@ class ViewInfoStore { * * @return A ViewHolder if exists or null if it does not exist. */ - ViewHolder getFromOldChangeHolders(long key) { + RecyclerView.ViewHolder getFromOldChangeHolders(long key) { return mOldChangedHolders.get(key); } @@ -178,7 +176,7 @@ class ViewInfoStore { * @param holder The ViewHolder whose information is being saved * @param info The information to save */ - void addToPostLayout(ViewHolder holder, ItemHolderInfo info) { + void addToPostLayout(RecyclerView.ViewHolder holder, RecyclerView.ItemAnimator.ItemHolderInfo info) { InfoRecord record = mLayoutHolderMap.get(holder); if (record == null) { record = InfoRecord.obtain(); @@ -194,7 +192,7 @@ class ViewInfoStore { * * @param holder The ViewHolder which disappeared during a layout. */ - void addToDisappearedInLayout(ViewHolder holder) { + void addToDisappearedInLayout(RecyclerView.ViewHolder holder) { InfoRecord record = mLayoutHolderMap.get(holder); if (record == null) { record = InfoRecord.obtain(); @@ -207,7 +205,7 @@ class ViewInfoStore { * Removes a ViewHolder from disappearing list. * @param holder The ViewHolder to be removed from the disappearing list. */ - void removeFromDisappearedInLayout(ViewHolder holder) { + void removeFromDisappearedInLayout(RecyclerView.ViewHolder holder) { InfoRecord record = mLayoutHolderMap.get(holder); if (record == null) { return; @@ -217,7 +215,7 @@ class ViewInfoStore { void process(ProcessCallback callback) { for (int index = mLayoutHolderMap.size() - 1; index >= 0; index--) { - final ViewHolder viewHolder = mLayoutHolderMap.keyAt(index); + final RecyclerView.ViewHolder viewHolder = mLayoutHolderMap.keyAt(index); final InfoRecord record = mLayoutHolderMap.removeAt(index); if ((record.flags & FLAG_APPEAR_AND_DISAPPEAR) == FLAG_APPEAR_AND_DISAPPEAR) { // Appeared then disappeared. Not useful for animations. @@ -256,7 +254,7 @@ class ViewInfoStore { * Removes the ViewHolder from all list * @param holder The ViewHolder which we should stop tracking */ - void removeViewHolder(ViewHolder holder) { + void removeViewHolder(RecyclerView.ViewHolder holder) { for (int i = mOldChangedHolders.size() - 1; i >= 0; i--) { if (holder == mOldChangedHolders.valueAt(i)) { mOldChangedHolders.removeAt(i); @@ -273,18 +271,18 @@ class ViewInfoStore { InfoRecord.drainCache(); } - public void onViewDetached(ViewHolder viewHolder) { + public void onViewDetached(RecyclerView.ViewHolder viewHolder) { removeFromDisappearedInLayout(viewHolder); } interface ProcessCallback { - void processDisappeared(ViewHolder viewHolder, @NonNull ItemHolderInfo preInfo, - @Nullable ItemHolderInfo postInfo); - void processAppeared(ViewHolder viewHolder, @Nullable ItemHolderInfo preInfo, - ItemHolderInfo postInfo); - void processPersistent(ViewHolder viewHolder, @NonNull ItemHolderInfo preInfo, - @NonNull ItemHolderInfo postInfo); - void unused(ViewHolder holder); + void processDisappeared(RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ItemAnimator.ItemHolderInfo preInfo, + @Nullable RecyclerView.ItemAnimator.ItemHolderInfo postInfo); + void processAppeared(RecyclerView.ViewHolder viewHolder, @Nullable RecyclerView.ItemAnimator.ItemHolderInfo preInfo, + RecyclerView.ItemAnimator.ItemHolderInfo postInfo); + void processPersistent(RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ItemAnimator.ItemHolderInfo preInfo, + @NonNull RecyclerView.ItemAnimator.ItemHolderInfo postInfo); + void unused(RecyclerView.ViewHolder holder); } static class InfoRecord { @@ -300,8 +298,10 @@ class ViewInfoStore { static final int FLAG_PRE_AND_POST = FLAG_PRE | FLAG_POST; static final int FLAG_APPEAR_PRE_AND_POST = FLAG_APPEAR | FLAG_PRE | FLAG_POST; int flags; - @Nullable ItemHolderInfo preInfo; - @Nullable ItemHolderInfo postInfo; + @Nullable + RecyclerView.ItemAnimator.ItemHolderInfo preInfo; + @Nullable + RecyclerView.ItemAnimator.ItemHolderInfo postInfo; static Pools.Pool sPool = new Pools.SimplePool<>(20); private InfoRecord() { diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/BasePlayer.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/BasePlayer.java index 4c1b84b4f..774f1b452 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/BasePlayer.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/BasePlayer.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Util; /** Abstract base {@link Player} which implements common implementation independent methods. */ diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/BaseRenderer.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/BaseRenderer.java index 73602d85a..294dd9fee 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/BaseRenderer.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/BaseRenderer.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmSessionManager; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/C.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/C.java index 8810b5100..685093687 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/C.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/C.java @@ -21,7 +21,7 @@ import android.media.AudioFormat; import android.media.AudioManager; import android.media.MediaCodec; import android.media.MediaFormat; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import android.view.Surface; import com.google.android.exoplayer2.PlayerMessage.Target; import com.google.android.exoplayer2.audio.AuxEffectInfo; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/DefaultMediaClock.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/DefaultMediaClock.java index ed57cec70..89e7d857c 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/DefaultMediaClock.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/DefaultMediaClock.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Clock; import com.google.android.exoplayer2.util.MediaClock; import com.google.android.exoplayer2.util.StandaloneMediaClock; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java index 6ccda2b8e..eb1648ed4 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/DefaultRenderersFactory.java @@ -18,8 +18,8 @@ package com.google.android.exoplayer2; import android.content.Context; import android.os.Handler; import android.os.Looper; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.audio.AudioCapabilities; import com.google.android.exoplayer2.audio.AudioProcessor; import com.google.android.exoplayer2.audio.AudioRendererEventListener; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java index 6b8424514..29078c71a 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlaybackException.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.util.Assertions; import java.io.IOException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlayer.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlayer.java index 5ba2394c3..b2311ed2e 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlayer.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlayer.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2; import android.os.Looper; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.audio.MediaCodecAudioRenderer; import com.google.android.exoplayer2.metadata.MetadataRenderer; import com.google.android.exoplayer2.source.ClippingMediaSource; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlayerFactory.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlayerFactory.java index c63dbc04d..003cda6ef 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlayerFactory.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlayerFactory.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2; import android.content.Context; import android.os.Looper; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.analytics.AnalyticsCollector; import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java index 7ac6de993..35d2cf789 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java @@ -19,7 +19,7 @@ import android.annotation.SuppressLint; import android.os.Handler; import android.os.Looper; import android.os.Message; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.Pair; import com.google.android.exoplayer2.PlayerMessage.Target; import com.google.android.exoplayer2.source.MediaSource; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java index b4549362f..91a69194d 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java @@ -21,8 +21,8 @@ import android.os.Looper; import android.os.Message; import android.os.Process; import android.os.SystemClock; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.util.Pair; import com.google.android.exoplayer2.DefaultMediaClock.PlaybackParameterListener; import com.google.android.exoplayer2.Player.DiscontinuityReason; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/Format.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/Format.java index a72dfd8ac..ddbc86aec 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/Format.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/Format.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.util.MimeTypes; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/FormatHolder.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/FormatHolder.java index 8c7ba1eb9..fcee2241e 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/FormatHolder.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/FormatHolder.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; /** * Holds a {@link Format}. diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java index 19622c680..1183d8bd8 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/MediaPeriodHolder.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.source.ClippingMediaPeriod; import com.google.android.exoplayer2.source.EmptySampleStream; import com.google.android.exoplayer2.source.MediaPeriod; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/MediaPeriodInfo.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/MediaPeriodInfo.java index e57100931..8b931d38c 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/MediaPeriodInfo.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/MediaPeriodInfo.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.util.Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java index 7fa2abe14..05692dbe6 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/MediaPeriodQueue.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.Pair; import com.google.android.exoplayer2.Player.RepeatMode; import com.google.android.exoplayer2.source.MediaPeriod; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/NoSampleRenderer.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/NoSampleRenderer.java index 6645850d3..1259133be 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/NoSampleRenderer.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/NoSampleRenderer.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.MediaClock; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java index 4333f51bf..0792bf0c7 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/PlaybackInfo.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2; -import android.support.annotation.CheckResult; -import android.support.annotation.Nullable; +import androidx.annotation.CheckResult; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.trackselection.TrackSelectorResult; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/PlaybackParameters.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/PlaybackParameters.java index 6f2db4ff5..057cb371e 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/PlaybackParameters.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/PlaybackParameters.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Assertions; /** diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/Player.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/Player.java index 223206a23..d3ad6316c 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/Player.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/Player.java @@ -16,8 +16,8 @@ package com.google.android.exoplayer2; import android.os.Looper; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/PlayerMessage.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/PlayerMessage.java index d60d42856..7904942c1 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/PlayerMessage.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/PlayerMessage.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2; import android.os.Handler; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Assertions; /** diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/Renderer.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/Renderer.java index 1d4d587ae..ad83ecc01 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/Renderer.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/Renderer.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.util.MediaClock; import java.io.IOException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/RendererConfiguration.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/RendererConfiguration.java index 684072efc..bc8c6ff63 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/RendererConfiguration.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/RendererConfiguration.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; /** * The configuration of a {@link Renderer}. diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/RenderersFactory.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/RenderersFactory.java index e22189847..6f0d125bc 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/RenderersFactory.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/RenderersFactory.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2; import android.os.Handler; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.audio.AudioRendererEventListener; import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/SeekParameters.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/SeekParameters.java index ca0433f96..7a0ad67a2 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/SeekParameters.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/SeekParameters.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Assertions; /** diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java index 3335703e3..ea902fbb3 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java @@ -23,7 +23,7 @@ import android.media.MediaCodec; import android.media.PlaybackParams; import android.os.Handler; import android.os.Looper; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/Timeline.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/Timeline.java index 45cb37e91..9c26b546b 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/Timeline.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/Timeline.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.Pair; import com.google.android.exoplayer2.source.ads.AdPlaybackState; import com.google.android.exoplayer2.util.Assertions; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java index cbcff19ca..78fa4383e 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.analytics; import android.graphics.SurfaceTexture; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.view.Surface; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java index e5ed53026..7f74216cc 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.analytics; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.view.Surface; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java index 230b96d01..99afff42f 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.audio; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.audio.Ac3Util.SyncFrameInfo.StreamType; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioAttributes.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioAttributes.java index 848b3ee10..9c63eb42c 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioAttributes.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioAttributes.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.audio; import android.annotation.TargetApi; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; /** diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilities.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilities.java index 6a5e58ef2..e7495acd8 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilities.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilities.java @@ -22,7 +22,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.media.AudioFormat; import android.media.AudioManager; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import java.util.Arrays; /** Represents the set of audio formats that a device is capable of playing. */ diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilitiesReceiver.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilitiesReceiver.java index aa610db8b..ed7a6f91d 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilitiesReceiver.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioCapabilitiesReceiver.java @@ -21,7 +21,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.os.Handler; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioFocusManager.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioFocusManager.java index c20ede439..6e3acac6f 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioFocusManager.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioFocusManager.java @@ -18,9 +18,9 @@ package com.google.android.exoplayer2.audio; import android.content.Context; import android.media.AudioFocusRequest; import android.media.AudioManager; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; -import android.support.annotation.RequiresApi; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Player; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioRendererEventListener.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioRendererEventListener.java index 48fbea75b..042738b4f 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioRendererEventListener.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioRendererEventListener.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.audio; import android.os.Handler; import android.os.SystemClock; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Renderer; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java index 5e8efdc78..393380453 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.audio; import android.media.AudioTrack; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.PlaybackParameters; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioTimestampPoller.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioTimestampPoller.java index 569260efe..d43972d7b 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioTimestampPoller.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioTimestampPoller.java @@ -18,8 +18,8 @@ package com.google.android.exoplayer2.audio; import android.annotation.TargetApi; import android.media.AudioTimestamp; import android.media.AudioTrack; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Util; import java.lang.annotation.Documented; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioTrackPositionTracker.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioTrackPositionTracker.java index 62b120f00..2ce9b8bdb 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioTrackPositionTracker.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AudioTrackPositionTracker.java @@ -20,8 +20,8 @@ import static com.google.android.exoplayer2.util.Util.castNonNull; import android.media.AudioTimestamp; import android.media.AudioTrack; import android.os.SystemClock; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AuxEffectInfo.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AuxEffectInfo.java index 7462a9c4b..968d8aceb 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AuxEffectInfo.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/AuxEffectInfo.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.audio; import android.media.AudioTrack; import android.media.audiofx.AudioEffect; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; /** * Represents auxiliary effect information, which can be used to attach an auxiliary effect to an diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/ChannelMappingAudioProcessor.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/ChannelMappingAudioProcessor.java index e53eb08c8..64e041f69 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/ChannelMappingAudioProcessor.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/ChannelMappingAudioProcessor.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.audio; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C.Encoding; import com.google.android.exoplayer2.Format; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java index fc515dbdb..47091e781 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java @@ -22,8 +22,8 @@ import android.media.AudioManager; import android.media.AudioTrack; import android.os.ConditionVariable; import android.os.SystemClock; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.PlaybackParameters; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java index 7fc6c16db..50490306c 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java @@ -23,8 +23,8 @@ import android.media.MediaCrypto; import android.media.MediaFormat; import android.media.audiofx.Virtualizer; import android.os.Handler; -import android.support.annotation.CallSuper; -import android.support.annotation.Nullable; +import androidx.annotation.CallSuper; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayer; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/SilenceSkippingAudioProcessor.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/SilenceSkippingAudioProcessor.java index a1ff7028c..87cdd1915 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/SilenceSkippingAudioProcessor.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/SilenceSkippingAudioProcessor.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.audio; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.util.Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRenderer.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRenderer.java index f2e8a2381..553dfb118 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRenderer.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRenderer.java @@ -19,8 +19,8 @@ import android.media.audiofx.Virtualizer; import android.os.Handler; import android.os.Looper; import android.os.SystemClock; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.BaseRenderer; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/SonicAudioProcessor.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/SonicAudioProcessor.java index 2ca2d4782..f033a8a52 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/SonicAudioProcessor.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/SonicAudioProcessor.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.audio; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C.Encoding; import com.google.android.exoplayer2.Format; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/TeeAudioProcessor.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/TeeAudioProcessor.java index 0072b7c2a..0fd415d30 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/TeeAudioProcessor.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/audio/TeeAudioProcessor.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.audio; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.util.Assertions; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java index 983c96f89..7fc6fb625 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.decoder; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import com.google.android.exoplayer2.C; import java.lang.annotation.Documented; import java.lang.annotation.Retention; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/decoder/SimpleDecoder.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/decoder/SimpleDecoder.java index 7e5ae694c..f8204f6be 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/decoder/SimpleDecoder.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/decoder/SimpleDecoder.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.decoder; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import java.util.ArrayDeque; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java index faf4b68f1..775d56f40 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java @@ -22,7 +22,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.Pair; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java index 5f166c611..e7828c0fe 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java @@ -20,8 +20,8 @@ import android.annotation.TargetApi; import android.os.Handler; import android.os.Looper; import android.os.Message; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import android.text.TextUtils; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.drm.DefaultDrmSession.ProvisioningManager; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/DrmInitData.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/DrmInitData.java index ff01cbc2b..740239604 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/DrmInitData.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/DrmInitData.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.drm; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; import com.google.android.exoplayer2.util.Assertions; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java index a68415287..510d03084 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java @@ -17,8 +17,8 @@ package com.google.android.exoplayer2.drm; import android.annotation.TargetApi; import android.media.MediaDrm; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/ErrorStateDrmSession.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/ErrorStateDrmSession.java index f0335b50c..82fd9a554 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/ErrorStateDrmSession.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/ErrorStateDrmSession.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.drm; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Assertions; import java.util.Map; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/ExoMediaDrm.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/ExoMediaDrm.java index aca56139d..49915f3af 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/ExoMediaDrm.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/ExoMediaDrm.java @@ -21,7 +21,7 @@ import android.media.MediaDrm; import android.media.MediaDrmException; import android.media.NotProvisionedException; import android.os.Handler; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; import java.util.HashMap; import java.util.List; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java index b139288f9..c9b295a1e 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java @@ -23,7 +23,7 @@ import android.media.MediaDrm; import android.media.MediaDrmException; import android.media.NotProvisionedException; import android.media.UnsupportedSchemeException; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.text.TextUtils; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/HttpMediaDrmCallback.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/HttpMediaDrmCallback.java index 4ff0af3c0..a3e602e40 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/HttpMediaDrmCallback.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/HttpMediaDrmCallback.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.drm; import android.annotation.TargetApi; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.text.TextUtils; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java index d596b4ab9..ed77f41c8 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java @@ -19,7 +19,7 @@ import android.media.MediaDrm; import android.os.ConditionVariable; import android.os.Handler; import android.os.HandlerThread; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.Pair; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.drm.DefaultDrmSessionManager.Mode; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/UnsupportedDrmException.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/UnsupportedDrmException.java index 7f4a0f5f0..a89196dc0 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/UnsupportedDrmException.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/UnsupportedDrmException.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.drm; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/WidevineUtil.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/WidevineUtil.java index b8b80490a..9fed3b38e 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/WidevineUtil.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/drm/WidevineUtil.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.drm; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.Pair; import com.google.android.exoplayer2.C; import java.util.Map; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java index 02787abe6..220159bd1 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.ext.ffmpeg; import android.os.Handler; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegDecoder.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegDecoder.java index 7ee347934..2b7a50402 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegDecoder.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegDecoder.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.ext.ffmpeg; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.decoder.DecoderInputBuffer; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegLibrary.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegLibrary.java index 6e822b2c5..bba5d0908 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegLibrary.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegLibrary.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.ext.ffmpeg; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.util.MimeTypes; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java index 8f5dcef16..249a13c19 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java @@ -17,8 +17,8 @@ package com.google.android.exoplayer2.ext.flac; import static com.google.android.exoplayer2.util.Util.getPcmEncoding; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.extractor.BinarySearchSeeker; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/BinarySearchSeeker.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/BinarySearchSeeker.java index af40206ed..06d3ed603 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/BinarySearchSeeker.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/BinarySearchSeeker.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.extractor; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/DummyTrackOutput.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/DummyTrackOutput.java index 9eaf0f7ef..f1aeccacb 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/DummyTrackOutput.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/DummyTrackOutput.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.util.ParsableByteArray; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/Extractor.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/Extractor.java index 05f5d98d3..083f31bcc 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/Extractor.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/Extractor.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import com.google.android.exoplayer2.C; import java.io.IOException; import java.lang.annotation.Documented; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/Id3Peeker.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/Id3Peeker.java index 8dbcfafaf..255799c02 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/Id3Peeker.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/Id3Peeker.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.extractor; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.id3.Id3Decoder; import com.google.android.exoplayer2.util.ParsableByteArray; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/SeekMap.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/SeekMap.java index b7aaa2a31..0cb55dffa 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/SeekMap.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/SeekMap.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/SeekPoint.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/SeekPoint.java index 8b920bc02..182db85c9 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/SeekPoint.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/SeekPoint.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; /** Defines a seek point in a media stream. */ public final class SeekPoint { diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/TrackOutput.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/TrackOutput.java index 7b832eb40..d7a1c7530 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/TrackOutput.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/TrackOutput.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.util.ParsableByteArray; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/amr/AmrExtractor.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/amr/AmrExtractor.java index b93969acf..caf12948a 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/amr/AmrExtractor.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/amr/AmrExtractor.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.extractor.amr; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.ParserException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/flv/FlvExtractor.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/flv/FlvExtractor.java index 4211cab48..0a2c0c46f 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/flv/FlvExtractor.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/flv/FlvExtractor.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.flv; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.ExtractorInput; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReader.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReader.java index 0987bc473..54afcf6e9 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReader.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReader.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.mkv; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.extractor.ExtractorInput; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlReaderOutput.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlReaderOutput.java index cc17af563..42e9d07e4 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlReaderOutput.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mkv/EbmlReaderOutput.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.mkv; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.extractor.ExtractorInput; import java.io.IOException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java index 187b9ae44..55f9b913a 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.extractor.mkv; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import android.util.Pair; import android.util.SparseArray; import com.google.android.exoplayer2.C; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.java index e8848bf98..4db715f53 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.extractor.mp3; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.ParserException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp3/VbriSeeker.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp3/VbriSeeker.java index 15e778115..ba8b26b7c 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp3/VbriSeeker.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp3/VbriSeeker.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.mp3; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.extractor.MpegAudioHeader; import com.google.android.exoplayer2.extractor.SeekPoint; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp3/XingSeeker.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp3/XingSeeker.java index 42752e55f..116a12309 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp3/XingSeeker.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp3/XingSeeker.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.mp3; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.extractor.MpegAudioHeader; import com.google.android.exoplayer2.extractor.SeekPoint; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/Atom.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/Atom.java index 8d7833761..6971dcf1c 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/Atom.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/Atom.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.mp4; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.Util; import java.util.ArrayList; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java index 008a155d1..77076a82a 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.extractor.mp4; import static com.google.android.exoplayer2.util.MimeTypes.getMimeTypeFromMp4ObjectType; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.Pair; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java index 72bcaa9fe..2fe5064ef 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.extractor.mp4; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import android.util.Pair; import android.util.SparseArray; import com.google.android.exoplayer2.C; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/MdtaMetadataEntry.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/MdtaMetadataEntry.java index b458a8f0f..e50fbd54f 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/MdtaMetadataEntry.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/MdtaMetadataEntry.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.extractor.mp4; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.util.Util; import java.util.Arrays; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java index 02522897c..e9c9f7faf 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.mp4; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.extractor.GaplessInfoHolder; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java index 8009fef67..23a37a0cd 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.mp4; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.ParserException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.java index 40cfa1332..957c3ba20 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.mp4; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.ParsableByteArray; import java.nio.ByteBuffer; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/Track.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/Track.java index b4a7b278c..9d3635e8b 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/Track.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/Track.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.extractor.mp4; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import java.lang.annotation.Documented; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackEncryptionBox.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackEncryptionBox.java index f09e6ae42..5bd29c6e7 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackEncryptionBox.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/mp4/TrackEncryptionBox.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.mp4; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.util.Assertions; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java index d251dc1d5..c83662ee8 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.ogg; -import android.support.annotation.VisibleForTesting; +import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.extractor.SeekMap; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPacket.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPacket.java index ca79c838d..01a766264 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPacket.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggPacket.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.ogg; -import android.support.annotation.VisibleForTesting; +import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.util.Assertions; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ogg/VorbisReader.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ogg/VorbisReader.java index 3c62f7a82..2675edd5b 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ogg/VorbisReader.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ogg/VorbisReader.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.ogg; -import android.support.annotation.VisibleForTesting; +import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.extractor.ogg.VorbisUtil.Mode; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Reader.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Reader.java index 93724be92..a5fd290e4 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Reader.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Reader.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.ts; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.audio.Ac3Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractor.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractor.java index 77b79fa19..9526a6576 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractor.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsExtractor.java @@ -17,8 +17,8 @@ package com.google.android.exoplayer2.extractor.ts; import static com.google.android.exoplayer2.extractor.ts.TsPayloadReader.FLAG_DATA_ALIGNMENT_INDICATOR; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.extractor.ConstantBitrateSeekMap; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java index a5506e2cf..402d1b418 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.ts; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import android.util.SparseArray; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.EsInfo; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/LatmReader.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/LatmReader.java index 2a633c191..39e74ae6a 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/LatmReader.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/LatmReader.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.ts; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.Pair; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java index d91842423..c243458dd 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.extractor.ts; import static com.google.android.exoplayer2.extractor.ts.TsPayloadReader.FLAG_PAYLOAD_UNIT_START_INDICATOR; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.SparseIntArray; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.java index a034b0569..19fb7d8b1 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.extractor.ts; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import android.util.SparseArray; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.extractor.ExtractorOutput; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java index 107ab9efd..e41af72c9 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java @@ -22,7 +22,7 @@ import android.media.MediaCodecInfo.AudioCapabilities; import android.media.MediaCodecInfo.CodecCapabilities; import android.media.MediaCodecInfo.CodecProfileLevel; import android.media.MediaCodecInfo.VideoCapabilities; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.Pair; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.util.Assertions; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java index 77d3b31ab..9ca1c6b61 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java @@ -25,9 +25,9 @@ import android.media.MediaFormat; import android.os.Bundle; import android.os.Looper; import android.os.SystemClock; -import android.support.annotation.CheckResult; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.CheckResult; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.BaseRenderer; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecSelector.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecSelector.java index d92e93d45..496d015b5 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecSelector.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecSelector.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.mediacodec; import android.media.MediaCodec; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException; import java.util.Collections; import java.util.List; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java index 9ae50179c..85257cd01 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java @@ -20,7 +20,7 @@ import android.annotation.TargetApi; import android.media.MediaCodecInfo.CodecCapabilities; import android.media.MediaCodecInfo.CodecProfileLevel; import android.media.MediaCodecList; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.text.TextUtils; import android.util.Pair; import android.util.SparseIntArray; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaFormatUtil.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaFormatUtil.java index 3cfefc073..230469cce 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaFormatUtil.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaFormatUtil.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.mediacodec; import android.annotation.TargetApi; import android.media.MediaFormat; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.video.ColorInfo; import java.nio.ByteBuffer; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/Metadata.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/Metadata.java index fbed096aa..ff2463dfa 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/Metadata.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/Metadata.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.metadata; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Util; import java.util.Arrays; import java.util.List; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/MetadataDecoder.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/MetadataDecoder.java index 7e4861a8c..1d95d3229 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/MetadataDecoder.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/MetadataDecoder.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.metadata; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; /** * Decodes metadata from binary data. diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java index 864616e81..d36022487 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java @@ -19,7 +19,7 @@ import android.os.Handler; import android.os.Handler.Callback; import android.os.Looper; import android.os.Message; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.BaseRenderer; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessage.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessage.java index 7d70d9de1..0984eaf6e 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessage.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessage.java @@ -19,7 +19,7 @@ import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.util.Util; import java.util.Arrays; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessageEncoder.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessageEncoder.java index eca498a6d..3be376848 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessageEncoder.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/emsg/EventMessageEncoder.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.metadata.emsg; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/icy/IcyDecoder.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/icy/IcyDecoder.java index 1eac66395..d04cd3a99 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/icy/IcyDecoder.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/icy/IcyDecoder.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.metadata.icy; -import android.support.annotation.Nullable; -import android.support.annotation.VisibleForTesting; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.MetadataDecoder; import com.google.android.exoplayer2.metadata.MetadataInputBuffer; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/icy/IcyHeaders.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/icy/IcyHeaders.java index cd8c5b17d..35c5be86d 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/icy/IcyHeaders.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/icy/IcyHeaders.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.metadata.icy; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.metadata.Metadata; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/icy/IcyInfo.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/icy/IcyInfo.java index a9671bb68..e6b915a6c 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/icy/IcyInfo.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/icy/IcyInfo.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.metadata.icy; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.util.Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/ApicFrame.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/ApicFrame.java index 53976da0d..c233ad61b 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/ApicFrame.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/ApicFrame.java @@ -19,7 +19,7 @@ import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Util; import java.util.Arrays; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/BinaryFrame.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/BinaryFrame.java index c48829ae5..6c6057bb7 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/BinaryFrame.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/BinaryFrame.java @@ -19,7 +19,7 @@ import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import java.util.Arrays; /** diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterFrame.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterFrame.java index 7ffb6d028..bf5d2de6e 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterFrame.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterFrame.java @@ -18,7 +18,7 @@ package com.google.android.exoplayer2.metadata.id3; import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Util; import java.util.Arrays; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterTocFrame.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterTocFrame.java index c4a7c06e4..98688ad09 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterTocFrame.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapterTocFrame.java @@ -18,7 +18,7 @@ package com.google.android.exoplayer2.metadata.id3; import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Util; import java.util.Arrays; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/CommentFrame.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/CommentFrame.java index 5666e4893..363057f17 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/CommentFrame.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/CommentFrame.java @@ -19,7 +19,7 @@ import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Util; /** diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/GeobFrame.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/GeobFrame.java index 990d8f2e4..6023f76aa 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/GeobFrame.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/GeobFrame.java @@ -19,7 +19,7 @@ import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Util; import java.util.Arrays; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java index 63bf30dd1..4bc864935 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.metadata.id3; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.MetadataDecoder; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/InternalFrame.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/InternalFrame.java index c191676ce..762ca0da0 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/InternalFrame.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/InternalFrame.java @@ -18,7 +18,7 @@ package com.google.android.exoplayer2.metadata.id3; import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Util; /** Internal ID3 frame that is intended for use by the player. */ diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/MlltFrame.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/MlltFrame.java index 06a4dd9d2..7d0a1dba3 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/MlltFrame.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/MlltFrame.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.metadata.id3; import android.os.Parcel; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import java.util.Arrays; /** MPEG location lookup table frame. */ diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/PrivFrame.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/PrivFrame.java index a10ce229d..6e5348545 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/PrivFrame.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/PrivFrame.java @@ -19,7 +19,7 @@ import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Util; import java.util.Arrays; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrame.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrame.java index 62175ee90..8a36276b9 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrame.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrame.java @@ -19,7 +19,7 @@ import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Util; /** diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/UrlLinkFrame.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/UrlLinkFrame.java index 4b35131be..8be9ed188 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/UrlLinkFrame.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/metadata/id3/UrlLinkFrame.java @@ -19,7 +19,7 @@ import static com.google.android.exoplayer2.util.Util.castNonNull; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Util; /** diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloadIndex.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloadIndex.java index 8881a038f..93e2f6711 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloadIndex.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloadIndex.java @@ -23,9 +23,9 @@ import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteOpenHelper; import android.net.Uri; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; -import android.support.annotation.VisibleForTesting; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; import java.lang.annotation.Documented; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloaderFactory.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloaderFactory.java index 63ec72f35..db8090c22 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloaderFactory.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DefaultDownloaderFactory.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.offline; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import java.lang.reflect.Constructor; import java.util.List; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadAction.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadAction.java index 40ea094b5..512c236d5 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadAction.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadAction.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.offline; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; import java.io.ByteArrayInputStream; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java index e799aff4b..74d139083 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java @@ -18,7 +18,7 @@ package com.google.android.exoplayer2.offline; import android.net.Uri; import android.os.Handler; import android.os.Looper; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.SparseIntArray; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadIndex.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadIndex.java index 71726b64a..8b07c49cd 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadIndex.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadIndex.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.offline; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; /** Persists {@link DownloadState}s. */ interface DownloadIndex { diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadIndexUtil.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadIndexUtil.java index 63602c764..836ef6d9f 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadIndexUtil.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadIndexUtil.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.offline; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.offline.DownloadState.State; import com.google.android.exoplayer2.util.Assertions; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java index 8932140a3..07c3a10fc 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadManager.java @@ -33,7 +33,7 @@ import android.os.ConditionVariable; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.scheduler.Requirements; import com.google.android.exoplayer2.scheduler.RequirementsWatcher; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadService.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadService.java index d424ed5ef..3ffc7fdc3 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadService.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadService.java @@ -22,8 +22,8 @@ import android.content.Intent; import android.os.Handler; import android.os.IBinder; import android.os.Looper; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; import com.google.android.exoplayer2.scheduler.Requirements; import com.google.android.exoplayer2.scheduler.Scheduler; import com.google.android.exoplayer2.util.Assertions; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadState.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadState.java index 7bbd07882..2a448cd80 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadState.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloadState.java @@ -16,8 +16,8 @@ package com.google.android.exoplayer2.offline; import android.net.Uri; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import java.lang.annotation.Documented; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloaderConstructorHelper.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloaderConstructorHelper.java index 59a11934b..a799f183d 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloaderConstructorHelper.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/DownloaderConstructorHelper.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.offline; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.upstream.DataSink; import com.google.android.exoplayer2.upstream.DataSource; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/FilteringManifestParser.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/FilteringManifestParser.java index c25e5099c..7e15987c4 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/FilteringManifestParser.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/FilteringManifestParser.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.offline; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.upstream.ParsingLoadable.Parser; import java.io.IOException; import java.io.InputStream; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/ProgressiveDownloadHelper.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/ProgressiveDownloadHelper.java index 2ec14368c..37c16fa90 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/ProgressiveDownloadHelper.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/ProgressiveDownloadHelper.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.offline; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.source.TrackGroupArray; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/ProgressiveDownloader.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/ProgressiveDownloader.java index 25b4e07bc..e712f9ddc 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/ProgressiveDownloader.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/ProgressiveDownloader.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.offline; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.cache.Cache; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/SegmentDownloader.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/SegmentDownloader.java index 1b32abff6..e0c906469 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/SegmentDownloader.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/SegmentDownloader.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.offline; import android.net.Uri; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSpec; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/StreamKey.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/StreamKey.java index 1caeaca61..4d1de5f32 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/StreamKey.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/offline/StreamKey.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.offline; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; /** * A key for a subset of media which can be separately loaded (a "stream"). diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/scheduler/PlatformScheduler.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/scheduler/PlatformScheduler.java index b8272dc03..aa77078b7 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/scheduler/PlatformScheduler.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/scheduler/PlatformScheduler.java @@ -24,7 +24,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.os.PersistableBundle; -import android.support.annotation.RequiresPermission; +import androidx.annotation.RequiresPermission; import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/scheduler/Requirements.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/scheduler/Requirements.java index 77630a454..ef3c13631 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/scheduler/Requirements.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/scheduler/Requirements.java @@ -24,7 +24,7 @@ import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.os.BatteryManager; import android.os.PowerManager; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/scheduler/RequirementsWatcher.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/scheduler/RequirementsWatcher.java index 686f19d16..bf58261eb 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/scheduler/RequirementsWatcher.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/scheduler/RequirementsWatcher.java @@ -27,7 +27,7 @@ import android.net.NetworkRequest; import android.os.Handler; import android.os.Looper; import android.os.PowerManager; -import android.support.annotation.RequiresApi; +import androidx.annotation.RequiresApi; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/BaseMediaSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/BaseMediaSource.java index 189467b47..f6ea3da08 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/BaseMediaSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/BaseMediaSource.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.source; import android.os.Handler; import android.os.Looper; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.util.Assertions; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java index d3b822682..ce6254e97 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.source; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.upstream.Allocator; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/CompositeMediaSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/CompositeMediaSource.java index dbf5812f9..9323f7505 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/CompositeMediaSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/CompositeMediaSource.java @@ -16,8 +16,8 @@ package com.google.android.exoplayer2.source; import android.os.Handler; -import android.support.annotation.CallSuper; -import android.support.annotation.Nullable; +import androidx.annotation.CallSuper; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.util.Assertions; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java index 6dc7a0a32..01b5429b1 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java @@ -17,9 +17,9 @@ package com.google.android.exoplayer2.source; import android.os.Handler; import android.os.Message; -import android.support.annotation.GuardedBy; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.GuardedBy; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.util.Pair; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Timeline; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceEventListener.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceEventListener.java index fd7c037fb..14bafdaf4 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceEventListener.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceEventListener.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import java.io.IOException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/DeferredMediaPeriod.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/DeferredMediaPeriod.java index 858769180..abf02541c 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/DeferredMediaPeriod.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/DeferredMediaPeriod.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.SeekParameters; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java index 7fd231f4e..f8817e985 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.source; import android.net.Uri; import android.os.Handler; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java index 5403f9f33..601d0223b 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.source; import android.net.Uri; import android.os.Handler; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/IcyDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/IcyDataSource.java index 96546d4f8..3d31e2a77 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/IcyDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/IcyDataSource.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.source; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSpec; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/LoopingMediaSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/LoopingMediaSource.java index 0cd87561e..08fe24b1a 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/LoopingMediaSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/LoopingMediaSource.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Player; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/MediaSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/MediaSource.java index 1419f9a98..f5d3daa7d 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/MediaSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/MediaSource.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.source; import android.os.Handler; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.upstream.Allocator; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java index 98d1d0a2a..233e19b29 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java @@ -19,8 +19,8 @@ import android.net.Uri; import android.os.Handler; import android.os.Looper; import android.os.SystemClock; -import android.support.annotation.CheckResult; -import android.support.annotation.Nullable; +import androidx.annotation.CheckResult; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Player; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/MergingMediaSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/MergingMediaSource.java index 1ea3404e8..6b1a362b5 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/MergingMediaSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/MergingMediaSource.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.source; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.TransferListener; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java index 0886e79d2..133de437d 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/SinglePeriodTimeline.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/SinglePeriodTimeline.java index 9e33a2d89..acdfbcc8c 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/SinglePeriodTimeline.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/SinglePeriodTimeline.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.util.Assertions; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java index 73d590951..386b637b2 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java index d13fa0643..80c57c8ac 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.source; import android.net.Uri; import android.os.Handler; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.upstream.Allocator; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/TrackGroup.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/TrackGroup.java index 56c9989f3..9e837bf05 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/TrackGroup.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/TrackGroup.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.source; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.util.Assertions; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/TrackGroupArray.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/TrackGroupArray.java index a155032a9..e737a5faf 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/TrackGroupArray.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/TrackGroupArray.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.source; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import java.util.Arrays; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java index fc1355df6..be9dea91f 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ads/AdPlaybackState.java @@ -16,8 +16,8 @@ package com.google.android.exoplayer2.source.ads; import android.net.Uri; -import android.support.annotation.CheckResult; -import android.support.annotation.IntDef; +import androidx.annotation.CheckResult; +import androidx.annotation.IntDef; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import java.lang.annotation.Documented; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ads/AdsLoader.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ads/AdsLoader.java index 51de22541..72f78ccd5 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ads/AdsLoader.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ads/AdsLoader.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source.ads; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.view.ViewGroup; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Player; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java index 475446623..74cfa80f2 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java @@ -18,8 +18,8 @@ package com.google.android.exoplayer2.source.ads; import android.net.Uri; import android.os.Handler; import android.os.Looper; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import android.view.ViewGroup; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Timeline; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ads/SinglePeriodAdTimeline.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ads/SinglePeriodAdTimeline.java index 0594a635a..25a1440c8 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ads/SinglePeriodAdTimeline.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/ads/SinglePeriodAdTimeline.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source.ads; -import android.support.annotation.VisibleForTesting; +import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.source.ForwardingTimeline; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/chunk/Chunk.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/chunk/Chunk.java index 91c3afec8..2e7581eba 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/chunk/Chunk.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/chunk/Chunk.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.source.chunk; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.upstream.DataSource; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java index a8676b5a0..fc07a318b 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source.chunk; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.SparseArray; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java index 9fac69b28..18eada470 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source.chunk; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java index eecf471b2..37c70d549 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/chunk/InitializationChunk.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source.chunk; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.extractor.DefaultExtractorInput; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DashChunkSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DashChunkSource.java index c6cdc88f2..f808d7c1b 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DashChunkSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DashChunkSource.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.source.dash; import android.os.SystemClock; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.source.chunk.ChunkSource; import com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerTrackEmsgHandler; import com.google.android.exoplayer2.source.dash.manifest.DashManifest; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java index cba7a9941..a3a5363ef 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.source.dash; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import android.util.Pair; import android.util.SparseIntArray; import com.google.android.exoplayer2.C; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java index cfdbdac1e..732ca61b6 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java @@ -18,7 +18,7 @@ package com.google.android.exoplayer2.source.dash; import android.net.Uri; import android.os.Handler; import android.os.SystemClock; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.text.TextUtils; import android.util.SparseArray; import com.google.android.exoplayer2.C; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DashUtil.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DashUtil.java index 743462bd8..6a6e08ce1 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DashUtil.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DashUtil.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.source.dash; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.drm.DrmInitData; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java index a02b2f1ee..6282195d6 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java @@ -17,8 +17,8 @@ package com.google.android.exoplayer2.source.dash; import android.net.Uri; import android.os.SystemClock; -import android.support.annotation.CheckResult; -import android.support.annotation.Nullable; +import androidx.annotation.CheckResult; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.SeekParameters; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java index 3ab9f470c..34e1ecc2b 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/PlayerEmsgHandler.java @@ -19,7 +19,7 @@ import static com.google.android.exoplayer2.util.Util.parseXsDateTime; import android.os.Handler; import android.os.Message; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifest.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifest.java index 3637b80ec..0c3f641cb 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifest.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifest.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.source.dash.manifest; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.offline.FilterableManifest; import com.google.android.exoplayer2.offline.StreamKey; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Descriptor.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Descriptor.java index 0e21df64b..493a8da09 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Descriptor.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Descriptor.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.source.dash.manifest; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Util; /** diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Period.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Period.java index b6f7ef0a3..18614ca4b 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Period.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Period.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source.dash.manifest; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import java.util.Collections; import java.util.List; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/ProgramInformation.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/ProgramInformation.java index e3072c86b..62934d743 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/ProgramInformation.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/ProgramInformation.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source.dash.manifest; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Util; /** A parsed program information element. */ diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/RangedUri.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/RangedUri.java index e22666733..c7bb4adec 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/RangedUri.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/manifest/RangedUri.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.source.dash.manifest; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.UriUtil; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloadHelper.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloadHelper.java index f86e47ed3..16310a188 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloadHelper.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloadHelper.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.source.dash.offline; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.RenderersFactory; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloader.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloader.java index 5dad46872..5636c7349 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloader.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloader.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.source.dash.offline; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.extractor.ChunkIndex; import com.google.android.exoplayer2.offline.DownloadException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/Aes128DataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/Aes128DataSource.java index 55a648a0b..4fe76cdf8 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/Aes128DataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/Aes128DataSource.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.source.hls; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSourceInputStream; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java index d01476d00..8d62bec44 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.source.hls; import android.net.Uri; import android.os.SystemClock; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.source.BehindLiveWindowException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java index da50d7cc9..154d75bd2 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source.hls; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.SeekParameters; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java index f2b76dddc..9b05cfc76 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaSource.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.source.hls; import android.net.Uri; import android.os.Handler; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.extractor.Extractor; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java index 39598c4cd..b37dd326b 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.source.hls; import android.os.Handler; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/SampleQueueMappingException.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/SampleQueueMappingException.java index 9c9cb532a..38b18da50 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/SampleQueueMappingException.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/SampleQueueMappingException.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source.hls; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.source.SampleQueue; import com.google.android.exoplayer2.source.TrackGroup; import java.io.IOException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/offline/HlsDownloadHelper.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/offline/HlsDownloadHelper.java index e0f55aa73..a8bf46087 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/offline/HlsDownloadHelper.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/offline/HlsDownloadHelper.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.source.hls.offline; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.RenderersFactory; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/playlist/DefaultHlsPlaylistTracker.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/playlist/DefaultHlsPlaylistTracker.java index 4269b66d3..ee2042357 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/playlist/DefaultHlsPlaylistTracker.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/playlist/DefaultHlsPlaylistTracker.java @@ -18,7 +18,7 @@ package com.google.android.exoplayer2.source.hls.playlist; import android.net.Uri; import android.os.Handler; import android.os.SystemClock; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java index 81d4e7a81..57a0c05f7 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMediaPlaylist.java @@ -15,9 +15,9 @@ */ package com.google.android.exoplayer2.source.hls.playlist; -import android.support.annotation.IntDef; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.offline.StreamKey; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java index 242711431..e690993cc 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.source.hls.playlist; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.Base64; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java index c73c9fa83..12df8f310 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistTracker.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.source.hls.playlist; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.hls.HlsDataSourceFactory; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java index 45521726c..59e18195e 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.source.smoothstreaming; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.SeekParameters; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsChunkSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsChunkSource.java index 4940f1592..b763a484b 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsChunkSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsChunkSource.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source.smoothstreaming; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.source.chunk.ChunkSource; import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest; import com.google.android.exoplayer2.trackselection.TrackSelection; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java index 8798ea09b..d91e33164 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.source.smoothstreaming; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.SeekParameters; import com.google.android.exoplayer2.offline.StreamKey; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java index 0f5544a99..867b17ac3 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java @@ -18,7 +18,7 @@ package com.google.android.exoplayer2.source.smoothstreaming; import android.net.Uri; import android.os.Handler; import android.os.SystemClock; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.ParserException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/offline/SsDownloadHelper.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/offline/SsDownloadHelper.java index b17768f20..18936db3e 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/offline/SsDownloadHelper.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/offline/SsDownloadHelper.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.source.smoothstreaming.offline; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.drm.DrmSessionManager; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/CaptionStyleCompat.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/CaptionStyleCompat.java index e7bb0e16b..b863d80c9 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/CaptionStyleCompat.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/CaptionStyleCompat.java @@ -18,7 +18,7 @@ package com.google.android.exoplayer2.text; import android.annotation.TargetApi; import android.graphics.Color; import android.graphics.Typeface; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import android.view.accessibility.CaptioningManager; import android.view.accessibility.CaptioningManager.CaptionStyle; import com.google.android.exoplayer2.util.Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/Cue.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/Cue.java index a5c666c44..4b54b3ea9 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/Cue.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/Cue.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.text; import android.graphics.Bitmap; import android.graphics.Color; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import android.text.Layout.Alignment; import java.lang.annotation.Documented; import java.lang.annotation.Retention; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/TextRenderer.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/TextRenderer.java index 16f82a729..55bee5bd6 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/TextRenderer.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/TextRenderer.java @@ -19,8 +19,8 @@ import android.os.Handler; import android.os.Handler.Callback; import android.os.Looper; import android.os.Message; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.BaseRenderer; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/cea/Cea708Cue.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/cea/Cea708Cue.java index 0a3f36fa8..a0201e19e 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/cea/Cea708Cue.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/cea/Cea708Cue.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.text.cea; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.text.Layout.Alignment; import com.google.android.exoplayer2.text.Cue; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/cea/CeaDecoder.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/cea/CeaDecoder.java index 3efc16bdd..ce9da9f5d 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/cea/CeaDecoder.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/cea/CeaDecoder.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.text.cea; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.text.Subtitle; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/subrip/SubripDecoder.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/subrip/SubripDecoder.java index 3b039061b..56fc8b09c 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/subrip/SubripDecoder.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/subrip/SubripDecoder.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.text.subrip; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.text.Html; import android.text.Spanned; import android.text.TextUtils; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java index 020bbe201..ecf5c8b0a 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.text.ttml; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.text.SpannableStringBuilder; import android.util.Base64; import android.util.Pair; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlStyle.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlStyle.java index a4f0cca95..9fdcc48c1 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlStyle.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlStyle.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.text.ttml; import android.graphics.Typeface; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import android.text.Layout; import com.google.android.exoplayer2.util.Assertions; import java.lang.annotation.Documented; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlSubtitle.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlSubtitle.java index 1779d9890..6a52338a9 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlSubtitle.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlSubtitle.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.text.ttml; -import android.support.annotation.VisibleForTesting; +import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Subtitle; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCssStyle.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCssStyle.java index fe274a624..ded7ef73f 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCssStyle.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCssStyle.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.text.webvtt; import android.graphics.Typeface; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import android.text.Layout; import com.google.android.exoplayer2.util.Util; import java.lang.annotation.Documented; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParser.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParser.java index 9900ca0e7..2361c9729 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParser.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParser.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.text.webvtt; import android.graphics.Typeface; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.text.Layout.Alignment; import android.text.Spannable; import android.text.SpannableStringBuilder; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelection.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelection.java index dd2d0001f..32e6a499c 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelection.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelection.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.trackselection; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayerFactory; import com.google.android.exoplayer2.Format; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/BaseTrackSelection.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/BaseTrackSelection.java index 798b6ce81..dc0b3f674 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/BaseTrackSelection.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/BaseTrackSelection.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.trackselection; import android.os.SystemClock; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.source.TrackGroup; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/BufferSizeAdaptationBuilder.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/BufferSizeAdaptationBuilder.java index 5c8350cb1..65ce7dce7 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/BufferSizeAdaptationBuilder.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/BufferSizeAdaptationBuilder.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.trackselection; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.Pair; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.DefaultLoadControl; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java index 06b11b3d6..1cc740103 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java @@ -19,8 +19,8 @@ import android.content.Context; import android.graphics.Point; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.text.TextUtils; import android.util.Pair; import android.util.SparseArray; @@ -328,7 +328,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { */ public ParametersBuilder setViewportSizeToPhysicalDisplaySize( Context context, boolean viewportOrientationMayChange) { - // Assume the viewport is fullscreen. + // Assume the viewport is isFullscreen. Point viewportSize = Util.getPhysicalDisplaySize(context); return setViewportSize(viewportSize.x, viewportSize.y, viewportOrientationMayChange); } diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/FixedTrackSelection.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/FixedTrackSelection.java index 79b5d93dc..3bdaeeeaf 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/FixedTrackSelection.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/FixedTrackSelection.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.trackselection; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.chunk.MediaChunk; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/MappingTrackSelector.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/MappingTrackSelector.java index f9c63805f..2738ee592 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/MappingTrackSelector.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/MappingTrackSelector.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.trackselection; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import android.util.Pair; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/RandomTrackSelection.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/RandomTrackSelection.java index 217a16e4a..805321296 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/RandomTrackSelection.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/RandomTrackSelection.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.trackselection; import android.os.SystemClock; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.chunk.MediaChunk; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackBitrateEstimator.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackBitrateEstimator.java index 94513b825..1cd6c09bf 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackBitrateEstimator.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackBitrateEstimator.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.trackselection; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.source.chunk.MediaChunk; import com.google.android.exoplayer2.source.chunk.MediaChunkIterator; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelection.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelection.java index 251c0ac76..e244bf4a8 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelection.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelection.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.trackselection; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.source.TrackGroup; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionArray.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionArray.java index 48151002b..bc905ace4 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionArray.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionArray.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.trackselection; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import java.util.Arrays; import org.checkerframework.checker.nullness.compatqual.NullableType; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionUtil.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionUtil.java index 7800495a6..5db5c646e 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionUtil.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionUtil.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.trackselection; -import android.support.annotation.Nullable; -import android.support.annotation.VisibleForTesting; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.source.chunk.MediaChunk; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelector.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelector.java index 2a66186b2..f2fbd8911 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelector.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelector.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.trackselection; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Renderer; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectorResult.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectorResult.java index 4bc4975a1..fc723134f 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectorResult.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectorResult.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.trackselection; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.RendererConfiguration; import com.google.android.exoplayer2.util.Util; import org.checkerframework.checker.nullness.compatqual.NullableType; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/WindowedTrackBitrateEstimator.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/WindowedTrackBitrateEstimator.java index 0def71c80..25f7e4ea7 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/WindowedTrackBitrateEstimator.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/trackselection/WindowedTrackBitrateEstimator.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.trackselection; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.source.chunk.MediaChunk; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ui/AspectRatioFrameLayout.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ui/AspectRatioFrameLayout.java index 222b23c13..397330f67 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/ui/AspectRatioFrameLayout.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/ui/AspectRatioFrameLayout.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.ui; import android.content.Context; import android.graphics.Matrix; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import android.view.TextureView; import android.view.View; import android.widget.FrameLayout; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/AssetDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/AssetDataSource.java index 16c27ccde..9224e14d4 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/AssetDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/AssetDataSource.java @@ -18,7 +18,7 @@ package com.google.android.exoplayer2.upstream; import android.content.Context; import android.content.res.AssetManager; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import java.io.EOFException; import java.io.IOException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/BandwidthMeter.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/BandwidthMeter.java index 85bcda4e3..853a9af52 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/BandwidthMeter.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/BandwidthMeter.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream; import android.os.Handler; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; /** * Provides estimates of the currently available bandwidth. diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/BaseDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/BaseDataSource.java index 5ed2e33d2..21f2d5993 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/BaseDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/BaseDataSource.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.upstream; import static com.google.android.exoplayer2.util.Util.castNonNull; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import java.util.ArrayList; /** diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/ByteArrayDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/ByteArrayDataSource.java index 16637b405..c45089667 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/ByteArrayDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/ByteArrayDataSource.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import java.io.IOException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java index 30051a53e..c723d3f1c 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/ContentDataSource.java @@ -19,7 +19,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import java.io.EOFException; import java.io.FileInputStream; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSchemeDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSchemeDataSource.java index 2d2a7587f..de4a75d60 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSchemeDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSchemeDataSource.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.Base64; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSource.java index ab22e1835..204b9d4d6 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSource.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import java.io.IOException; import java.util.Collections; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSourceInputStream.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSourceInputStream.java index 2f2075f35..6c4e77a90 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSourceInputStream.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSourceInputStream.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.upstream; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import java.io.IOException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java index 2996de452..6a4ed4315 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java @@ -16,8 +16,8 @@ package com.google.android.exoplayer2.upstream; import android.net.Uri; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import java.lang.annotation.Documented; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.java index d1bda8010..f3792b3f2 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultBandwidthMeter.java @@ -22,7 +22,7 @@ import android.content.IntentFilter; import android.net.ConnectivityManager; import android.os.Handler; import android.os.Looper; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.SparseArray; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSource.java index 808252fb1..8b4107850 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSource.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.upstream; import android.content.Context; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSourceFactory.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSourceFactory.java index 8183a8906..9639b4ede 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSourceFactory.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSourceFactory.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream; import android.content.Context; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.upstream.DataSource.Factory; /** diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java index ebeb9a191..6aad51700 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSource.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.text.TextUtils; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.metadata.icy.IcyHeaders; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceFactory.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceFactory.java index 95ea49132..ef1a3aa7a 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceFactory.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DefaultHttpDataSourceFactory.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.upstream; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.upstream.HttpDataSource.BaseFactory; import com.google.android.exoplayer2.upstream.HttpDataSource.Factory; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DummyDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DummyDataSource.java index 13c5732a6..026bc0b9c 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DummyDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/DummyDataSource.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import java.io.IOException; /** diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/FileDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/FileDataSource.java index 582b2b06d..3cfdc4812 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/FileDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/FileDataSource.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import java.io.EOFException; import java.io.IOException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/FileDataSourceFactory.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/FileDataSourceFactory.java index fd1920991..3a47df765 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/FileDataSourceFactory.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/FileDataSourceFactory.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.upstream; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; /** * A {@link DataSource.Factory} that produces {@link FileDataSource}. diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/HttpDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/HttpDataSource.java index e3e93bd6f..07155ee2b 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/HttpDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/HttpDataSource.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.upstream; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import android.text.TextUtils; import com.google.android.exoplayer2.util.Predicate; import com.google.android.exoplayer2.util.Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/Loader.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/Loader.java index ac3b3c5c5..878c40dc9 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/Loader.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/Loader.java @@ -20,8 +20,8 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.SystemClock; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Log; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/ParsingLoadable.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/ParsingLoadable.java index b41f1aa09..edec849b8 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/ParsingLoadable.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/ParsingLoadable.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.upstream.Loader.Loadable; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/PriorityDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/PriorityDataSource.java index 9f9a3f9a9..62e68cd92 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/PriorityDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/PriorityDataSource.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.PriorityTaskManager; import java.io.IOException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/RawResourceDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/RawResourceDataSource.java index 7f51efda0..1f0313594 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/RawResourceDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/RawResourceDataSource.java @@ -19,7 +19,7 @@ import android.content.Context; import android.content.res.AssetFileDescriptor; import android.content.res.Resources; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.text.TextUtils; import com.google.android.exoplayer2.C; import java.io.EOFException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/StatsDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/StatsDataSource.java index 04b29b531..b7a01505f 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/StatsDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/StatsDataSource.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import java.io.IOException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/TeeDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/TeeDataSource.java index 3c021b0b7..ecf25f2eb 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/TeeDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/TeeDataSource.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import java.io.IOException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/UdpDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/UdpDataSource.java index 8d6b39fa9..e7aab31cc 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/UdpDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/UdpDataSource.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import java.io.IOException; import java.net.DatagramPacket; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/Cache.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/Cache.java index 6bbe1edd1..c477c8795 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/Cache.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/Cache.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.upstream.cache; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import java.io.File; import java.io.IOException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java index 909bd4002..58b2d176c 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSource.java @@ -16,8 +16,8 @@ package com.google.android.exoplayer2.upstream.cache; import android.net.Uri; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.upstream.DataSink; import com.google.android.exoplayer2.upstream.DataSource; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceFactory.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceFactory.java index 9675aa176..2f0f6caa2 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceFactory.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheDataSourceFactory.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.upstream.cache; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.upstream.DataSink; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.FileDataSourceFactory; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheSpan.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheSpan.java index 2082740bb..7dbcd4a92 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheSpan.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheSpan.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.upstream.cache; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import java.io.File; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java index 9714df6ad..e41fa98ee 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CacheUtil.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream.cache; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSpec; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContent.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContent.java index 5494454d5..00ab04708 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContent.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContent.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.upstream.cache; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.upstream.cache.Cache.CacheException; import com.google.android.exoplayer2.util.Assertions; import java.io.DataInputStream; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContentIndex.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContentIndex.java index a74491723..faaf5f061 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContentIndex.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedContentIndex.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.upstream.cache; -import android.support.annotation.VisibleForTesting; +import androidx.annotation.VisibleForTesting; import android.util.SparseArray; import android.util.SparseBooleanArray; import com.google.android.exoplayer2.upstream.cache.Cache.CacheException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedRegionTracker.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedRegionTracker.java index e8315385e..fb2d4f694 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedRegionTracker.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/CachedRegionTracker.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.upstream.cache; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import com.google.android.exoplayer2.extractor.ChunkIndex; import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/ContentMetadata.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/ContentMetadata.java index f0075343a..4cc6e6b86 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/ContentMetadata.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/ContentMetadata.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream.cache; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; /** diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/ContentMetadataMutations.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/ContentMetadataMutations.java index fb3f6e362..5715b8fbd 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/ContentMetadataMutations.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/ContentMetadataMutations.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream.cache; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import java.util.ArrayList; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/DefaultContentMetadata.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/DefaultContentMetadata.java index 843dd1944..57371a579 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/DefaultContentMetadata.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/DefaultContentMetadata.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.upstream.cache; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import java.io.DataInputStream; import java.io.DataOutputStream; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCache.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCache.java index 80eb779e3..77b48dc88 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCache.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCache.java @@ -16,8 +16,8 @@ package com.google.android.exoplayer2.upstream.cache; import android.os.ConditionVariable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Log; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpan.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpan.java index dfa553ffe..579e77feb 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpan.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/cache/SimpleCacheSpan.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.upstream.cache; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSource.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSource.java index 801c84dc5..7a7af6b8a 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSource.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/upstream/crypto/AesCipherDataSource.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.upstream.crypto; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSpec; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/Assertions.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/Assertions.java index c6ad5dfe5..b4ccc5bcc 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/Assertions.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/Assertions.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.util; import android.os.Looper; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.text.TextUtils; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import org.checkerframework.checker.nullness.qual.EnsuresNonNull; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/AtomicFile.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/AtomicFile.java index 2466d5a04..d20646841 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/AtomicFile.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/AtomicFile.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.util; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/Clock.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/Clock.java index 36fc3b1bf..7a87d7d9a 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/Clock.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/Clock.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.util; import android.os.Handler; import android.os.Looper; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; /** * An interface through which system clocks can be read and {@link HandlerWrapper}s created. The diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java index 627cf7e07..16a891dbc 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.util; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.util.Pair; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/EGLSurfaceTexture.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/EGLSurfaceTexture.java index 216ddb3c4..33b50934f 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/EGLSurfaceTexture.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/EGLSurfaceTexture.java @@ -24,8 +24,8 @@ import android.opengl.EGLDisplay; import android.opengl.EGLSurface; import android.opengl.GLES20; import android.os.Handler; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/EventLogger.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/EventLogger.java index 25f3a0c10..bb3dc8b83 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/EventLogger.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/EventLogger.java @@ -16,7 +16,7 @@ package com.google.android.exoplayer2.util; import android.os.SystemClock; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.view.Surface; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/Log.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/Log.java index 34fb684d2..2c3e4f1e7 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/Log.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/Log.java @@ -15,8 +15,8 @@ */ package com.google.android.exoplayer2.util; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import android.text.TextUtils; import java.lang.annotation.Documented; import java.lang.annotation.Retention; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java index c5ce93a23..7e8ecfddc 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.util; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.text.TextUtils; import com.google.android.exoplayer2.C; import java.util.ArrayList; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/NotificationUtil.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/NotificationUtil.java index e45ab0952..e1c98c657 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/NotificationUtil.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/NotificationUtil.java @@ -21,9 +21,9 @@ import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; import android.content.Intent; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/ParsableByteArray.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/ParsableByteArray.java index b928ffc02..0c5116624 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/ParsableByteArray.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/ParsableByteArray.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.util; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import java.nio.ByteBuffer; import java.nio.charset.Charset; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/RepeatModeUtil.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/RepeatModeUtil.java index cc23c9763..3485877bc 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/RepeatModeUtil.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/RepeatModeUtil.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.util; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import com.google.android.exoplayer2.Player; import java.lang.annotation.Documented; import java.lang.annotation.Retention; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/SystemClock.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/SystemClock.java index 72d3df46e..be526595c 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/SystemClock.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/SystemClock.java @@ -18,7 +18,7 @@ package com.google.android.exoplayer2.util; import android.os.Handler; import android.os.Handler.Callback; import android.os.Looper; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; /** * The standard implementation of {@link Clock}. diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/TimedValueQueue.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/TimedValueQueue.java index 3fe3c56c1..3ac76eb54 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/TimedValueQueue.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/TimedValueQueue.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.util; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import java.util.Arrays; import org.checkerframework.checker.nullness.compatqual.NullableType; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/Util.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/Util.java index 1e1153d36..4e947c333 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/Util.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/Util.java @@ -39,7 +39,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Parcel; import android.security.NetworkSecurityPolicy; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.view.Display; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/XmlPullParserUtil.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/XmlPullParserUtil.java index 3b72a60fb..a9b252b77 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/XmlPullParserUtil.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/util/XmlPullParserUtil.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.util; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java index 77ca936a9..a6c62b16f 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.video; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.util.Util; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/DummySurface.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/DummySurface.java index c43d81010..f302279f0 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/DummySurface.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/DummySurface.java @@ -29,7 +29,7 @@ import android.os.Handler; import android.os.Handler.Callback; import android.os.HandlerThread; import android.os.Message; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.view.Surface; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.EGLSurfaceTexture; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java index 089ff6343..727883f67 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.video; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.util.NalUnitUtil; import com.google.android.exoplayer2.util.ParsableByteArray; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java index b92dd44eb..50788303d 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java @@ -25,9 +25,9 @@ import android.media.MediaCrypto; import android.media.MediaFormat; import android.os.Handler; import android.os.SystemClock; -import android.support.annotation.CallSuper; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.CallSuper; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.view.Surface; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/VideoFrameReleaseTimeHelper.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/VideoFrameReleaseTimeHelper.java index 3c0fb9219..16d74d0fa 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/VideoFrameReleaseTimeHelper.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/VideoFrameReleaseTimeHelper.java @@ -21,7 +21,7 @@ import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.view.Choreographer; import android.view.Choreographer.FrameCallback; import android.view.Display; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java index f2f451b3d..2f76a2c23 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.video; import android.os.Handler; import android.os.SystemClock; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.view.Surface; import android.view.TextureView; import com.google.android.exoplayer2.Format; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/spherical/CameraMotionRenderer.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/spherical/CameraMotionRenderer.java index 663c9fe28..eb7110834 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/spherical/CameraMotionRenderer.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/spherical/CameraMotionRenderer.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.video.spherical; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.BaseRenderer; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/spherical/Projection.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/spherical/Projection.java index 3d4879d50..8ba24bb06 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/spherical/Projection.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/spherical/Projection.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.video.spherical; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C.StereoMode; import com.google.android.exoplayer2.util.Assertions; diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/spherical/ProjectionDecoder.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/spherical/ProjectionDecoder.java index 7a3c4998b..527aa5db4 100755 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/spherical/ProjectionDecoder.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/video/spherical/ProjectionDecoder.java @@ -15,7 +15,7 @@ */ package com.google.android.exoplayer2.video.spherical; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.ParsableBitArray; import com.google.android.exoplayer2.util.ParsableByteArray; diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteCursor.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteCursor.java index cc13f6624..4a55bb933 100755 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteCursor.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteCursor.java @@ -32,6 +32,10 @@ public class SQLiteCursor { return columnIsNull(preparedStatement.getStatementHandle(), columnIndex) == 1; } + public SQLitePreparedStatement getPreparedStatement() { + return preparedStatement; + } + public int intValue(int columnIndex) throws SQLiteException { checkRow(); return columnIntValue(preparedStatement.getStatementHandle(), columnIndex); @@ -101,6 +105,10 @@ public class SQLiteCursor { return preparedStatement.getStatementHandle(); } + public int getColumnCount() { + return columnCount(preparedStatement.getStatementHandle()); + } + public void dispose() { preparedStatement.dispose(); } @@ -112,6 +120,7 @@ public class SQLiteCursor { } native int columnType(long statementHandle, int columnIndex); + native int columnCount(long statementHandle); native int columnIsNull(long statementHandle, int columnIndex); native int columnIntValue(long statementHandle, int columnIndex); native long columnLongValue(long statementHandle, int columnIndex); diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteDatabase.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteDatabase.java index d311d8159..a9cece4b6 100755 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteDatabase.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteDatabase.java @@ -51,6 +51,20 @@ public class SQLiteDatabase { } } + public void explainQuery(String sql, Object... args) throws SQLiteException { + checkOpened(); + SQLiteCursor cursor = new SQLitePreparedStatement(this, "EXPLAIN QUERY PLAN " + sql, true).query(args); + while (cursor.next()) { + int count = cursor.getColumnCount(); + StringBuilder builder = new StringBuilder(); + for (int a = 0; a < count; a++) { + builder.append(cursor.stringValue(a)).append(", "); + } + FileLog.d("EXPLAIN QUERY PLAN " + builder.toString()); + } + cursor.dispose(); + } + public SQLiteCursor queryFinalized(String sql, Object... args) throws SQLiteException { checkOpened(); return new SQLitePreparedStatement(this, sql, true).query(args); diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java index c2479afc9..5959b3dd0 100755 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java @@ -63,6 +63,8 @@ public class SQLitePreparedStatement { bindDouble(sqliteStatementHandle, i, (Double) obj); } else if (obj instanceof String) { bindString(sqliteStatementHandle, i, (String) obj); + } else if (obj instanceof Long) { + bindLong(sqliteStatementHandle, i, (Long) obj); } else { throw new IllegalArgumentException(); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AccountInstance.java b/TMessagesProj/src/main/java/org/telegram/messenger/AccountInstance.java new file mode 100644 index 000000000..a863d7977 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AccountInstance.java @@ -0,0 +1,57 @@ +package org.telegram.messenger; + +import org.telegram.tgnet.ConnectionsManager; + +public class AccountInstance { + + private int currentAccount; + private static volatile AccountInstance[] Instance = new AccountInstance[UserConfig.MAX_ACCOUNT_COUNT]; + public static AccountInstance getInstance(int num) { + AccountInstance localInstance = Instance[num]; + if (localInstance == null) { + synchronized (AccountInstance.class) { + localInstance = Instance[num]; + if (localInstance == null) { + Instance[num] = localInstance = new AccountInstance(num); + } + } + } + return localInstance; + } + + public AccountInstance(int instance) { + currentAccount = instance; + } + + public MessagesController getMessagesController() { + return MessagesController.getInstance(currentAccount); + } + + public MessagesStorage getMessagesStorage() { + return MessagesStorage.getInstance(currentAccount); + } + + public ContactsController getContactsController() { + return ContactsController.getInstance(currentAccount); + } + + public DataQuery getDataQuery() { + return DataQuery.getInstance(currentAccount); + } + + public ConnectionsManager getConnectionsManager() { + return ConnectionsManager.getInstance(currentAccount); + } + + public NotificationsController getNotificationsController() { + return NotificationsController.getInstance(currentAccount); + } + + public NotificationCenter getNotificationCenter() { + return NotificationCenter.getInstance(currentAccount); + } + + public UserConfig getUserConfig() { + return UserConfig.getInstance(currentAccount); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index 4c5991cbc..b0419b648 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -43,9 +43,9 @@ import android.os.PowerManager; import android.provider.DocumentsContract; import android.provider.MediaStore; import android.provider.Settings; -import android.support.v4.content.FileProvider; -import android.support.v4.view.ViewPager; -import android.support.v4.widget.EdgeEffectCompat; +import androidx.core.content.FileProvider; +import androidx.viewpager.widget.ViewPager; +import androidx.core.widget.EdgeEffectCompat; import android.telephony.TelephonyManager; import android.text.Selection; import android.text.Spannable; @@ -65,10 +65,13 @@ import android.view.Surface; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.view.animation.OvershootInterpolator; import android.view.inputmethod.InputMethodManager; +import android.view.inputmethod.InputMethodSubtype; import android.webkit.MimeTypeMap; import android.widget.EdgeEffect; import android.widget.HorizontalScrollView; @@ -132,6 +135,7 @@ public class AndroidUtilities { private static final Object callLock = new Object(); public static int statusBarHeight = 0; + public static boolean firstConfigurationWas; public static float density = 1; public static Point displaySize = new Point(); public static int roundMessageSize; @@ -186,14 +190,14 @@ public class AndroidUtilities { checkDisplaySize(ApplicationLoader.applicationContext, null); } - private static int documentIcons[] = { + private static int[] documentIcons = { R.drawable.media_doc_blue, R.drawable.media_doc_green, R.drawable.media_doc_red, R.drawable.media_doc_yellow }; - private static int documentMediaIcons[] = { + private static int[] documentMediaIcons = { R.drawable.media_doc_blue_b, R.drawable.media_doc_green_b, R.drawable.media_doc_red_b, @@ -228,7 +232,7 @@ public class AndroidUtilities { public static int[] calcDrawableColor(Drawable drawable) { int bitmapColor = 0xff000000; - int result[] = new int[4]; + int[] result = new int[4]; try { if (drawable instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); @@ -251,7 +255,7 @@ public class AndroidUtilities { double[] hsv = rgbToHsv((bitmapColor >> 16) & 0xff, (bitmapColor >> 8) & 0xff, bitmapColor & 0xff); hsv[1] = Math.min(1.0, hsv[1] + 0.05 + 0.1 * (1.0 - hsv[1])); double v = Math.max(0, hsv[2] * 0.65); - int rgb[] = hsvToRgb(hsv[0], hsv[1], v); + int[] rgb = hsvToRgb(hsv[0], hsv[1], v); result[0] = Color.argb(0x66, rgb[0], rgb[1], rgb[2]); result[1] = Color.argb(0x88, rgb[0], rgb[1], rgb[2]); @@ -336,6 +340,15 @@ public class AndroidUtilities { adjustOwnerClassGuid = classGuid; } + public static void setAdjustResizeToNothing(Activity activity, int classGuid) { + if (activity == null || isTablet()) { + return; + } + if (adjustOwnerClassGuid == classGuid) { + activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING); + } + } + public static void removeAdjustResize(Activity activity, int classGuid) { if (activity == null || isTablet()) { return; @@ -415,6 +428,7 @@ public class AndroidUtilities { return pathString != null && pathString.toLowerCase().contains("/data/data/" + ApplicationLoader.applicationContext.getPackageName()); } + @SuppressLint("WrongConstant") public static void lockOrientation(Activity activity) { if (activity == null || prevOrientation != -10) { return; @@ -457,6 +471,7 @@ public class AndroidUtilities { } } + @SuppressLint("WrongConstant") public static void unlockOrientation(Activity activity) { if (activity == null) { return; @@ -490,7 +505,7 @@ public class AndroidUtilities { } String valueType = fullData.substring(0, idx); - String value = fullData.substring(idx + 1, fullData.length()); + String value = fullData.substring(idx + 1); String nameEncoding = null; String nameCharset = "UTF-8"; @@ -539,7 +554,7 @@ public class AndroidUtilities { } String valueType = fullData.substring(0, idx); - String value = fullData.substring(idx + 1, fullData.length()); + String value = fullData.substring(idx + 1); String nameEncoding = null; String nameCharset = "UTF-8"; @@ -608,7 +623,7 @@ public class AndroidUtilities { String value = fullData.substring(0, idx); if (type == 20) { value = value.substring(2); - String args[] = value.split(";"); + String[] args = value.split(";"); if (first) { value = args[0]; } else if (args.length > 1) { @@ -617,7 +632,7 @@ public class AndroidUtilities { value = ""; } } else { - String args[] = value.split(";"); + String[] args = value.split(";"); for (int a = 0; a < args.length; a++) { if (args[a].indexOf('=') >= 0) { continue; @@ -646,10 +661,10 @@ public class AndroidUtilities { String value = fullData.substring(0, idx); if (type == 20) { value = value.substring(2); - String args[] = value.split(";"); + String[] args = value.split(";"); value = args[0]; } else { - String args[] = value.split(";"); + String[] args = value.split(";"); for (int a = 0; a < args.length; a++) { if (args[a].indexOf('=') >= 0) { continue; @@ -659,19 +674,26 @@ public class AndroidUtilities { if (value.startsWith("X-")) { value = value.substring(2); } - if ("PREF".equals(value)) { - value = LocaleController.getString("PhoneMain", R.string.PhoneMain); - } else if ("HOME".equals(value)) { - value = LocaleController.getString("PhoneHome", R.string.PhoneHome); - } else if ("MOBILE".equals(value) || "CELL".equals(value)) { - value = LocaleController.getString("PhoneMobile", R.string.PhoneMobile); - } else if ("OTHER".equals(value)) { - value = LocaleController.getString("PhoneOther", R.string.PhoneOther); - } else if ("WORK".equals(value)) { - value = LocaleController.getString("PhoneWork", R.string.PhoneWork); + switch (value) { + case "PREF": + value = LocaleController.getString("PhoneMain", R.string.PhoneMain); + break; + case "HOME": + value = LocaleController.getString("PhoneHome", R.string.PhoneHome); + break; + case "MOBILE": + case "CELL": + value = LocaleController.getString("PhoneMobile", R.string.PhoneMobile); + break; + case "OTHER": + value = LocaleController.getString("PhoneOther", R.string.PhoneOther); + break; + case "WORK": + value = LocaleController.getString("PhoneWork", R.string.PhoneWork); + break; } } - value = value.substring(0, 1).toUpperCase() + value.substring(1, value.length()).toLowerCase(); + value = value.substring(0, 1).toUpperCase() + value.substring(1).toLowerCase(); return value; } } @@ -785,7 +807,7 @@ public class AndroidUtilities { if (idx >= 0) { args = new String[]{ line.substring(0, idx), - line.substring(idx + 1, line.length()).trim() + line.substring(idx + 1).trim() }; } else { args = new String[]{line.trim()}; @@ -915,6 +937,16 @@ public class AndroidUtilities { } } + public static int getShadowHeight() { + if (density >= 4.0f) { + return 3; + } else if (density >= 2.0f) { + return 2; + } else { + return 1; + } + } + public static boolean isWaitingForCall() { boolean value; synchronized (callLock) { @@ -972,6 +1004,58 @@ public class AndroidUtilities { return false; } + public static String[] getCurrentKeyboardLanguage() { + try { + InputMethodManager inputManager = (InputMethodManager) ApplicationLoader.applicationContext.getSystemService(Context.INPUT_METHOD_SERVICE); + InputMethodSubtype inputMethodSubtype = inputManager.getCurrentInputMethodSubtype(); + String locale = null; + if (inputMethodSubtype != null) { + if (Build.VERSION.SDK_INT >= 24) { + locale = inputMethodSubtype.getLanguageTag(); + } + if (TextUtils.isEmpty(locale)) { + locale = inputMethodSubtype.getLocale(); + } + } else { + inputMethodSubtype = inputManager.getLastInputMethodSubtype(); + if (inputMethodSubtype != null) { + if (Build.VERSION.SDK_INT >= 24) { + locale = inputMethodSubtype.getLanguageTag(); + } + if (TextUtils.isEmpty(locale)) { + locale = inputMethodSubtype.getLocale(); + } + } + } + if (TextUtils.isEmpty(locale)) { + locale = LocaleController.getSystemLocaleStringIso639(); + String locale2; + LocaleController.LocaleInfo localeInfo = LocaleController.getInstance().getCurrentLocaleInfo(); + locale2 = localeInfo.getBaseLangCode(); + if (TextUtils.isEmpty(locale2)) { + locale2 = localeInfo.getLangCode(); + } + if (locale.contains(locale2) || locale2.contains(locale)) { + if (!locale.contains("en")) { + locale2 = "en"; + } else { + locale2 = null; + } + } + if (!TextUtils.isEmpty(locale2)) { + return new String[]{locale.replace('_', '-'), locale2}; + } else { + return new String[]{locale.replace('_', '-')}; + } + } else { + return new String[]{locale.replace('_', '-')}; + } + } catch (Exception ignore) { + + } + return new String[]{"en"}; + } + public static void hideKeyboard(View view) { if (view == null) { return; @@ -1022,6 +1106,13 @@ public class AndroidUtilities { return (int) Math.ceil(density * value); } + public static int dpr(float value) { + if (value == 0) { + return 0; + } + return Math.round(density * value); + } + public static int dp2(float value) { if (value == 0) { return 0; @@ -1047,7 +1138,13 @@ public class AndroidUtilities { public static void checkDisplaySize(Context context, Configuration newConfiguration) { try { + int oldDensity = (int) density; density = context.getResources().getDisplayMetrics().density; + int newDensity = (int) density; + if (firstConfigurationWas && oldDensity != newDensity) { + Theme.reloadAllResources(context); + } + firstConfigurationWas = true; Configuration configuration = newConfiguration; if (configuration == null) { configuration = context.getResources().getConfiguration(); @@ -1246,7 +1343,7 @@ public class AndroidUtilities { if (TextUtils.isEmpty(pattern) || pattern.equals("*")) { return true; } - String args[] = pattern.split("\\*"); + String[] args = pattern.split("\\*"); phone = PhoneFormat.stripExceptNumbers(phone); int checkStart = 0; int index; @@ -1341,27 +1438,17 @@ public class AndroidUtilities { if (Build.VERSION.SDK_INT >= 21) { try { Field field = ViewPager.class.getDeclaredField("mLeftEdge"); - field.setAccessible(true); //TODO - EdgeEffectCompat mLeftEdge = (EdgeEffectCompat) field.get(viewPager); + field.setAccessible(true); + EdgeEffect mLeftEdge = (EdgeEffect) field.get(viewPager); if (mLeftEdge != null) { - field = EdgeEffectCompat.class.getDeclaredField("mEdgeEffect"); - field.setAccessible(true); - EdgeEffect mEdgeEffect = (EdgeEffect) field.get(mLeftEdge); - if (mEdgeEffect != null) { - mEdgeEffect.setColor(color); - } + mLeftEdge.setColor(color); } field = ViewPager.class.getDeclaredField("mRightEdge"); field.setAccessible(true); - EdgeEffectCompat mRightEdge = (EdgeEffectCompat) field.get(viewPager); + EdgeEffect mRightEdge = (EdgeEffect) field.get(viewPager); if (mRightEdge != null) { - field = EdgeEffectCompat.class.getDeclaredField("mEdgeEffect"); - field.setAccessible(true); - EdgeEffect mEdgeEffect = (EdgeEffect) field.get(mRightEdge); - if (mEdgeEffect != null) { - mEdgeEffect.setColor(color); - } + mRightEdge.setColor(color); } } catch (Exception ignore) { @@ -1726,14 +1813,11 @@ public class AndroidUtilities { public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { - Cursor cursor = null; final String column = "_data"; final String[] projection = { column }; - - try { - cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); + try (Cursor cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null)) { if (cursor != null && cursor.moveToFirst()) { final int column_index = cursor.getColumnIndexOrThrow(column); String value = cursor.getString(column_index); @@ -1744,10 +1828,6 @@ public class AndroidUtilities { } } catch (Exception ignore) { - } finally { - if (cursor != null) { - cursor.close(); - } } return null; } @@ -1821,7 +1901,7 @@ public class AndroidUtilities { } if (lastIndex != -1 && lastIndex < wholeString.length()) { - builder.append(wholeString.substring(lastIndex, wholeString.length())); + builder.append(wholeString.substring(lastIndex)); } return builder; @@ -1928,22 +2008,11 @@ public class AndroidUtilities { if (!destFile.exists()) { destFile.createNewFile(); } - FileInputStream source = null; - FileOutputStream destination = null; - try { - source = new FileInputStream(sourceFile); - destination = new FileOutputStream(destFile); + try (FileInputStream source = new FileInputStream(sourceFile); FileOutputStream destination = new FileOutputStream(destFile)) { destination.getChannel().transferFrom(source.getChannel(), 0, source.getChannel().size()); } catch (Exception e) { FileLog.e(e); return false; - } finally { - if (source != null) { - source.close(); - } - if (destination != null) { - destination.close(); - } } return true; } @@ -2168,7 +2237,6 @@ public class AndroidUtilities { } else { sy = sx; } - if (translate) { matrix.setTranslate(dst.left, dst.top); } @@ -2391,6 +2459,7 @@ public class AndroidUtilities { builder.show(); } + @SuppressLint("PrivateApi") public static String getSystemProperty(String key) { try { Class props = Class.forName("android.os.SystemProperties"); @@ -2524,7 +2593,7 @@ public class AndroidUtilities { } public static int getPatternColor(int color) { - float hsb[] = RGBtoHSB(Color.red(color), Color.green(color), Color.blue(color)); + float[] hsb = RGBtoHSB(Color.red(color), Color.green(color), Color.blue(color)); if (hsb[1] > 0.0f || (hsb[2] < 1.0f && hsb[2] > 0.0f)) { hsb[1] = Math.min(1.0f, hsb[1] + 0.05f + 0.1f * (1.0f - hsb[1])); } @@ -2537,7 +2606,7 @@ public class AndroidUtilities { } public static int getPatternSideColor(int color) { - float hsb[] = RGBtoHSB(Color.red(color), Color.green(color), Color.blue(color)); + float[] hsb = RGBtoHSB(Color.red(color), Color.green(color), Color.blue(color)); hsb[1] = Math.min(1.0f, hsb[1] + 0.05f); if (hsb[2] > 0.5f) { hsb[2] = Math.max(0.0f, hsb[2] * 0.90f); @@ -2586,4 +2655,26 @@ public class AndroidUtilities { f *= 0.47123894F; return (float) Math.sin((double) f); } + + public static void makeAccessibilityAnnouncement(CharSequence what) { + AccessibilityManager am = (AccessibilityManager) ApplicationLoader.applicationContext.getSystemService(Context.ACCESSIBILITY_SERVICE); + if (am.isEnabled()) { + AccessibilityEvent ev = AccessibilityEvent.obtain(); + ev.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT); + ev.getText().add(what); + am.sendAccessibilityEvent(ev); + } + } + + public static int getOffsetColor(int color1, int color2, float offset, float alpha) { + int rF = Color.red(color2); + int gF = Color.green(color2); + int bF = Color.blue(color2); + int aF = Color.alpha(color2); + int rS = Color.red(color1); + int gS = Color.green(color1); + int bS = Color.blue(color1); + int aS = Color.alpha(color1); + return Color.argb((int) ((aS + (aF - aS) * offset) * alpha), (int) (rS + (rF - rS) * offset), (int) (gS + (gF - gS) * offset), (int) (bS + (bF - bS) * offset)); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java b/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java index a3b605078..1274f11f3 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java @@ -14,6 +14,7 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream { private volatile boolean canceled; private final Object sync = new Object(); private int lastOffset; + private boolean waitingForLoad; public AnimatedFileDrawableStream(TLRPC.Document d, Object p, int a) { document = d; @@ -46,7 +47,9 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream { countDownLatch = new CountDownLatch(1); } FileLoader.getInstance(currentAccount).setLoadingVideo(document, false, true); + waitingForLoad = true; countDownLatch.await(); + waitingForLoad = false; } } lastOffset = offset + availableLength; @@ -91,6 +94,10 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream { return currentAccount; } + public boolean isWaitingForLoad() { + return waitingForLoad; + } + @Override public void newDataAvailable() { if (countDownLatch != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageReplyReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageReplyReceiver.java index f8c213630..443ae1d5a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageReplyReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageReplyReceiver.java @@ -12,7 +12,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.v4.app.RemoteInput; +import androidx.core.app.RemoteInput; public class AutoMessageReplyReceiver extends BroadcastReceiver { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index 1f33449a8..4ff46d5d2 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -18,14 +18,14 @@ 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 = 1517; - public static String BUILD_VERSION_STRING = "5.4.0"; + public static int BUILD_VERSION = 1591; + public static String BUILD_VERSION_STRING = "5.6.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"; public static String HOCKEY_APP_HASH_DEBUG = "your-hockeyapp-api-key-here"; - public static String PLAYSTORE_APP_URL = ""; public static String SMS_HASH = ""; //https://developers.google.com/identity/sms-retriever/overview + public static String PLAYSTORE_APP_URL = ""; static { if (ApplicationLoader.applicationContext != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java index 840483a3e..2d527a6ab 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java @@ -55,11 +55,13 @@ public class ContactsController { private int loadingDeleteInfo; private int deleteAccountTTL; - private int[] loadingPrivacyInfo = new int[4]; + private int[] loadingPrivacyInfo = new int[6]; private ArrayList privacyRules; private ArrayList groupPrivacyRules; private ArrayList callPrivacyRules; private ArrayList p2pPrivacyRules; + private ArrayList profilePhotoPrivacyRules; + private ArrayList forwardsPrivacyRules; private class MyContentObserver extends ContentObserver { @@ -246,6 +248,8 @@ public class ContactsController { groupPrivacyRules = null; callPrivacyRules = null; p2pPrivacyRules = null; + profilePhotoPrivacyRules = null; + forwardsPrivacyRules = null; Utilities.globalQueue.postRunnable(() -> { migratingContacts = false; @@ -1566,6 +1570,10 @@ public class ContactsController { }); } + public boolean isContact(int uid) { + return contactsDict.get(uid) != null; + } + private void reloadContactsStatusesMaybe() { try { SharedPreferences preferences = MessagesController.getMainSettings(currentAccount); @@ -2300,9 +2308,15 @@ public class ContactsController { req.key = new TLRPC.TL_inputPrivacyKeyPhoneCall(); break; case 3: - default: req.key = new TLRPC.TL_inputPrivacyKeyPhoneP2P(); break; + case 4: + req.key = new TLRPC.TL_inputPrivacyKeyProfilePhoto(); + break; + case 5: + default: + req.key = new TLRPC.TL_inputPrivacyKeyForwards(); + break; } ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { @@ -2321,9 +2335,15 @@ public class ContactsController { callPrivacyRules = rules.rules; break; case 3: - default: p2pPrivacyRules = rules.rules; break; + case 4: + profilePhotoPrivacyRules = rules.rules; + break; + case 5: + default: + forwardsPrivacyRules = rules.rules; + break; } loadingPrivacyInfo[num] = 2; @@ -2353,7 +2373,11 @@ public class ContactsController { } public ArrayList getPrivacyRules(int type) { - if (type == 3) { + if (type == 5) { + return forwardsPrivacyRules; + } else if (type == 4) { + return profilePhotoPrivacyRules; + } else if (type == 3) { return p2pPrivacyRules; } else if (type == 2) { return callPrivacyRules; @@ -2365,7 +2389,11 @@ public class ContactsController { } public void setPrivacyRules(ArrayList rules, int type) { - if (type == 3) { + if (type == 5) { + forwardsPrivacyRules = rules; + } else if (type == 4) { + profilePhotoPrivacyRules = rules; + } else if (type == 3) { p2pPrivacyRules = rules; } else if (type == 2) { callPrivacyRules = rules; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DataQuery.java b/TMessagesProj/src/main/java/org/telegram/messenger/DataQuery.java index 2b4f5efcb..c1ab3be4e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DataQuery.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DataQuery.java @@ -61,6 +61,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.concurrent.CountDownLatch; @SuppressWarnings("unchecked") public class DataQuery { @@ -183,6 +184,8 @@ public class DataQuery { loadingRecentGifs = false; recentGifsLoaded = false; + currentFetchingEmoji.clear(); + loading = false; loaded = false; hints.clear(); @@ -240,6 +243,7 @@ public class DataQuery { recentStickers[type].add(0, image); } found = true; + break; } } if (!found && !remove) { @@ -291,7 +295,7 @@ public class DataQuery { if (!remove) { ArrayList arrayList = new ArrayList<>(); arrayList.add(document); - processLoadedRecentDocuments(type, arrayList, false, date); + processLoadedRecentDocuments(type, arrayList, false, date, false); } if (type == TYPE_FAVE) { NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recentDocumentsDidLoad, false, type); @@ -327,6 +331,18 @@ public class DataQuery { }); } + public boolean hasRecentGif(TLRPC.Document document) { + for (int a = 0; a < recentGifs.size(); a++) { + TLRPC.Document image = recentGifs.get(a); + if (image.id == document.id) { + recentGifs.remove(a); + recentGifs.add(0, image); + return true; + } + } + return false; + } + public void addRecentGif(TLRPC.Document document, int date) { boolean found = false; for (int a = 0; a < recentGifs.size(); a++) { @@ -335,6 +351,7 @@ public class DataQuery { recentGifs.remove(a); recentGifs.add(0, image); found = true; + break; } } if (!found) { @@ -352,7 +369,7 @@ public class DataQuery { } ArrayList arrayList = new ArrayList<>(); arrayList.add(document); - processLoadedRecentDocuments(0, arrayList, true, date); + processLoadedRecentDocuments(0, arrayList, true, date, false); } public boolean isLoadingStickers(int type) { @@ -526,6 +543,19 @@ public class DataQuery { return unreadStickerSets; } + public boolean areAllTrendingStickerSetsUnread() { + for (int a = 0, N = featuredStickerSets.size(); a < N; a++) { + TLRPC.StickerSetCovered pack = featuredStickerSets.get(a); + if (DataQuery.getInstance(currentAccount).isStickerPackInstalled(pack.set.id) || pack.covers.isEmpty() && pack.cover == null) { + continue; + } + if (!unreadStickerSets.contains(pack.set.id)) { + return false; + } + } + return true; + } + public boolean isStickerPackInstalled(long id) { return installedStickerSetsById.indexOfKey(id) >= 0; } @@ -655,7 +685,7 @@ public class DataQuery { TLRPC.TL_messages_savedGifs res = (TLRPC.TL_messages_savedGifs) response; arrayList = res.gifs; } - processLoadedRecentDocuments(type, arrayList, gif, 0); + processLoadedRecentDocuments(type, arrayList, gif, 0, true); }); } else { TLObject request; @@ -682,13 +712,13 @@ public class DataQuery { arrayList = res.stickers; } } - processLoadedRecentDocuments(type, arrayList, gif, 0); + processLoadedRecentDocuments(type, arrayList, gif, 0, true); }); } } } - protected void processLoadedRecentDocuments(final int type, final ArrayList documents, final boolean gif, final int date) { + protected void processLoadedRecentDocuments(final int type, final ArrayList documents, final boolean gif, final int date, boolean replace) { if (documents != null) { MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> { try { @@ -704,6 +734,7 @@ public class DataQuery { } } database.beginTransaction(); + SQLitePreparedStatement state = database.executeFast("REPLACE INTO web_recent_v3 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); int count = documents.size(); int cacheType; @@ -716,6 +747,9 @@ public class DataQuery { } else { cacheType = 5; } + if (replace) { + database.executeFast("DELETE FROM web_recent_v3 WHERE type = " + cacheType).stepThis().dispose(); + } for (int a = 0; a < count; a++) { if (a == maxCount) { break; @@ -1132,6 +1166,7 @@ public class DataQuery { for (int a1 = 0; a1 < newStickerArray.size(); a1++) { if (newStickerArray.get(a1) == null) { newStickerArray.remove(a1); + a1--; } } processLoadedStickers(type, newStickerArray, false, (int) (System.currentTimeMillis() / 1000), res.hash); @@ -1275,6 +1310,19 @@ public class DataQuery { return -1; } + public static TLRPC.InputStickerSet getInputStickerSet(TLRPC.Document document) { + for (int a = 0; a < document.attributes.size(); a++) { + TLRPC.DocumentAttribute attribute = document.attributes.get(a); + if (attribute instanceof TLRPC.TL_documentAttributeSticker) { + if (attribute.stickerset instanceof TLRPC.TL_inputStickerSetEmpty) { + return null; + } + return attribute.stickerset; + } + } + return null; + } + private static int calcStickersHash(ArrayList sets) { long acc = 0; for (int a = 0; a < sets.size(); a++) { @@ -1695,6 +1743,7 @@ public class DataQuery { int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (error == null) { final TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; + MessagesController.getInstance(currentAccount).removeDeletedMessagesFromArray(uid, res.messages); processLoadedMedia(res, uid, count, max_id, type, 0, classGuid, isChannel, res.messages.size() == 0); } }); @@ -2816,7 +2865,7 @@ public class DataQuery { Canvas canvas = new Canvas(result); if (selfUser) { AvatarDrawable avatarDrawable = new AvatarDrawable(user); - avatarDrawable.setSavedMessages(1); + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_SAVED); avatarDrawable.setBounds(0, 0, size, size); avatarDrawable.draw(canvas); } else { @@ -4043,4 +4092,282 @@ public class DataQuery { } //---------------- BOT END ---------------- + + //---------------- EMOJI START ---------------- + + public static class KeywordResult { + public String emoji; + public String keyword; + } + + public interface KeywordResultCallback { + void run(ArrayList param, String alias); + } + + private HashMap currentFetchingEmoji = new HashMap<>(); + + public void fetchNewEmojiKeywords(String[] langCodes) { + if (langCodes == null) { + return; + } + for (int a = 0; a < langCodes.length; a++) { + String langCode = langCodes[a]; + if (TextUtils.isEmpty(langCode)) { + return; + } + if (currentFetchingEmoji.get(langCode) != null) { + return; + } + currentFetchingEmoji.put(langCode, true); + MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> { + int version = -1; + String alias = null; + long date = 0; + try { + SQLiteCursor cursor = MessagesStorage.getInstance(currentAccount).getDatabase().queryFinalized("SELECT alias, version, date FROM emoji_keywords_info_v2 WHERE lang = ?", langCode); + if (cursor.next()) { + alias = cursor.stringValue(0); + version = cursor.intValue(1); + date = cursor.longValue(2); + } + cursor.dispose(); + } catch (Exception e) { + FileLog.e(e); + } + if (!BuildVars.DEBUG_VERSION && Math.abs(System.currentTimeMillis() - date) < 60 * 60 * 1000) { + AndroidUtilities.runOnUIThread(() -> currentFetchingEmoji.remove(langCode)); + return; + } + TLObject request; + if (version == -1) { + TLRPC.TL_messages_getEmojiKeywords req = new TLRPC.TL_messages_getEmojiKeywords(); + req.lang_code = langCode; + request = req; + } else { + TLRPC.TL_messages_getEmojiKeywordsDifference req = new TLRPC.TL_messages_getEmojiKeywordsDifference(); + req.lang_code = langCode; + req.from_version = version; + request = req; + } + String aliasFinal = alias; + int versionFinal = version; + ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> { + if (response != null) { + TLRPC.TL_emojiKeywordsDifference res = (TLRPC.TL_emojiKeywordsDifference) response; + if (versionFinal != -1 && !res.lang_code.equals(aliasFinal)) { + MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> { + try { + SQLitePreparedStatement deleteState = MessagesStorage.getInstance(currentAccount).getDatabase().executeFast("DELETE FROM emoji_keywords_info_v2 WHERE lang = ?"); + deleteState.bindString(1, langCode); + deleteState.step(); + deleteState.dispose(); + + AndroidUtilities.runOnUIThread(() -> { + currentFetchingEmoji.remove(langCode); + fetchNewEmojiKeywords(new String[]{langCode}); + }); + } catch (Exception e) { + FileLog.e(e); + } + }); + } else { + putEmojiKeywords(langCode, res); + } + } else { + AndroidUtilities.runOnUIThread(() -> currentFetchingEmoji.remove(langCode)); + } + }); + }); + } + } + + private void putEmojiKeywords(String lang, TLRPC.TL_emojiKeywordsDifference res) { + if (res == null) { + return; + } + MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> { + try { + if (!res.keywords.isEmpty()) { + SQLitePreparedStatement insertState = MessagesStorage.getInstance(currentAccount).getDatabase().executeFast("REPLACE INTO emoji_keywords_v2 VALUES(?, ?, ?)"); + SQLitePreparedStatement deleteState = MessagesStorage.getInstance(currentAccount).getDatabase().executeFast("DELETE FROM emoji_keywords_v2 WHERE lang = ? AND keyword = ? AND emoji = ?"); + MessagesStorage.getInstance(currentAccount).getDatabase().beginTransaction(); + for (int a = 0, N = res.keywords.size(); a < N; a++) { + TLRPC.EmojiKeyword keyword = res.keywords.get(a); + if (keyword instanceof TLRPC.TL_emojiKeyword) { + TLRPC.TL_emojiKeyword emojiKeyword = (TLRPC.TL_emojiKeyword) keyword; + String key = emojiKeyword.keyword.toLowerCase(); + for (int b = 0, N2 = emojiKeyword.emoticons.size(); b < N2; b++) { + insertState.requery(); + insertState.bindString(1, res.lang_code); + insertState.bindString(2, key); + insertState.bindString(3, emojiKeyword.emoticons.get(b)); + insertState.step(); + } + } else if (keyword instanceof TLRPC.TL_emojiKeywordDeleted) { + TLRPC.TL_emojiKeywordDeleted keywordDeleted = (TLRPC.TL_emojiKeywordDeleted) keyword; + String key = keywordDeleted.keyword.toLowerCase(); + for (int b = 0, N2 = keywordDeleted.emoticons.size(); b < N2; b++) { + deleteState.requery(); + deleteState.bindString(1, res.lang_code); + deleteState.bindString(2, key); + deleteState.bindString(3, keywordDeleted.emoticons.get(b)); + deleteState.step(); + } + } + } + MessagesStorage.getInstance(currentAccount).getDatabase().commitTransaction(); + insertState.dispose(); + deleteState.dispose(); + } + + SQLitePreparedStatement infoState = MessagesStorage.getInstance(currentAccount).getDatabase().executeFast("REPLACE INTO emoji_keywords_info_v2 VALUES(?, ?, ?, ?)"); + infoState.bindString(1, lang); + infoState.bindString(2, res.lang_code); + infoState.bindInteger(3, res.version); + infoState.bindLong(4, System.currentTimeMillis()); + infoState.step(); + infoState.dispose(); + + AndroidUtilities.runOnUIThread(() -> { + currentFetchingEmoji.remove(lang); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.newEmojiSuggestionsAvailable, lang); + }); + } catch (Exception e) { + FileLog.e(e); + } + }); + } + + public void getEmojiSuggestions(String[] langCodes, String keyword, boolean fullMatch, KeywordResultCallback callback) { + getEmojiSuggestions(langCodes, keyword, fullMatch, callback, null); + } + + public void getEmojiSuggestions(String[] langCodes, String keyword, boolean fullMatch, KeywordResultCallback callback, CountDownLatch sync) { + if (callback == null) { + return; + } + if (TextUtils.isEmpty(keyword) || langCodes == null) { + callback.run(new ArrayList<>(), null); + return; + } + ArrayList recentEmoji = new ArrayList<>(Emoji.recentEmoji); + MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> { + ArrayList result = new ArrayList(); + HashMap resultMap = new HashMap<>(); + String alias = null; + try { + SQLiteCursor cursor; + boolean hasAny = false; + for (int a = 0; a < langCodes.length; a++) { + cursor = MessagesStorage.getInstance(currentAccount).getDatabase().queryFinalized("SELECT alias FROM emoji_keywords_info_v2 WHERE lang = ?", langCodes[a]); + if (cursor.next()) { + alias = cursor.stringValue(0); + } + cursor.dispose(); + if (alias != null) { + hasAny = true; + } + } + if (!hasAny) { + AndroidUtilities.runOnUIThread(() -> { + for (int a = 0; a < langCodes.length; a++) { + if (currentFetchingEmoji.get(langCodes[a]) != null) { + return; + } + } + callback.run(result, null); + }); + return; + } + + String key = keyword.toLowerCase(); + for (int a = 0; a < 2; a++) { + if (a == 1) { + String translitKey = LocaleController.getInstance().getTranslitString(key, false, false); + if (translitKey.equals(key)) { + continue; + } + key = translitKey; + } + String key2 = null; + StringBuilder nextKey = new StringBuilder(key); + int pos = nextKey.length(); + while (pos > 0) { + pos--; + char value = nextKey.charAt(pos); + value++; + nextKey.setCharAt(pos, value); + if (value != 0) { + key2 = nextKey.toString(); + break; + } + } + + if (fullMatch) { + cursor = MessagesStorage.getInstance(currentAccount).getDatabase().queryFinalized("SELECT emoji, keyword FROM emoji_keywords_v2 WHERE keyword = ?", key); + } else if (key2 != null) { + cursor = MessagesStorage.getInstance(currentAccount).getDatabase().queryFinalized("SELECT emoji, keyword FROM emoji_keywords_v2 WHERE keyword >= ? AND keyword < ?", key, key2); + } else { + key += "%"; + cursor = MessagesStorage.getInstance(currentAccount).getDatabase().queryFinalized("SELECT emoji, keyword FROM emoji_keywords_v2 WHERE keyword LIKE ?", key); + } + while (cursor.next()) { + String value = cursor.stringValue(0).replace("\ufe0f", ""); + if (resultMap.get(value) != null) { + continue; + } + resultMap.put(value, true); + KeywordResult keywordResult = new KeywordResult(); + keywordResult.emoji = value; + keywordResult.keyword = cursor.stringValue(1); + result.add(keywordResult); + } + cursor.dispose(); + } + } catch (Exception e) { + FileLog.e(e); + } + Collections.sort(result, (o1, o2) -> { + int idx1 = recentEmoji.indexOf(o1.emoji); + if (idx1 < 0) { + idx1 = Integer.MAX_VALUE; + } + int idx2 = recentEmoji.indexOf(o2.emoji); + if (idx2 < 0) { + idx2 = Integer.MAX_VALUE; + } + if (idx1 < idx2) { + return -1; + } else if (idx1 > idx2) { + return 1; + } else { + int len1 = o1.keyword.length(); + int len2 = o2.keyword.length(); + + if (len1 < len2) { + return -1; + } else if (len1 > len2) { + return 1; + } + return 0; + } + }); + String aliasFinal = alias; + if (sync != null) { + callback.run(result, aliasFinal); + sync.countDown(); + } else { + AndroidUtilities.runOnUIThread(() -> callback.run(result, aliasFinal)); + } + }); + if (sync != null) { + try { + sync.await(); + } catch (Throwable ignore) { + + } + } + } + + //---------------- EMOJI END ---------------- } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DialogObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/DialogObject.java index cf8093532..dabe186ad 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DialogObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DialogObject.java @@ -12,7 +12,78 @@ import org.telegram.tgnet.TLRPC; public class DialogObject { - public static boolean isChannel(TLRPC.TL_dialog dialog) { + public static boolean isChannel(TLRPC.Dialog dialog) { return dialog != null && (dialog.flags & 1) != 0; } + + public static long makeSecretDialogId(int chatId) { + return ((long) chatId) << 32; + } + + public static long makeFolderDialogId(int folderId) { + return (((long) 2) << 32) | folderId; + } + + public static boolean isFolderDialogId(long dialogId) { + int lowerId = (int) dialogId; + int highId = (int) (dialogId >> 32); + return lowerId != 0 && highId == 2; + } + + public static boolean isPeerDialogId(long dialogId) { + int lowerId = (int) dialogId; + int highId = (int) (dialogId >> 32); + return lowerId != 0 && highId != 2 && highId != 1; + } + + public static boolean isSecretDialogId(long dialogId) { + return ((int) dialogId) == 0; + } + + public static void initDialog(TLRPC.Dialog dialog) { + if (dialog == null || dialog.id != 0) { + return; + } + if (dialog instanceof TLRPC.TL_dialog) { + if (dialog.peer == null) { + return; + } + if (dialog.peer.user_id != 0) { + dialog.id = dialog.peer.user_id; + } else if (dialog.peer.chat_id != 0) { + dialog.id = -dialog.peer.chat_id; + } else { + dialog.id = -dialog.peer.channel_id; + } + } else if (dialog instanceof TLRPC.TL_dialogFolder) { + TLRPC.TL_dialogFolder dialogFolder = (TLRPC.TL_dialogFolder) dialog; + dialog.id = makeFolderDialogId(dialogFolder.folder.id); + } + } + + public static long getPeerDialogId(TLRPC.Peer peer) { + if (peer == null) { + return 0; + } + if (peer.user_id != 0) { + return peer.user_id; + } else if (peer.chat_id != 0) { + return -peer.chat_id; + } else { + return -peer.channel_id; + } + } + + public static long getPeerDialogId(TLRPC.InputPeer peer) { + if (peer == null) { + return 0; + } + if (peer.user_id != 0) { + return peer.user_id; + } else if (peer.chat_id != 0) { + return -peer.chat_id; + } else { + return -peer.channel_id; + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java b/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java index 06735a858..c4218ef34 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java @@ -76,20 +76,6 @@ public class DownloadController implements NotificationCenter.NotificationCenter public boolean lessCallData; public boolean enabled; - public Preset(int m, int p, int v, int f, boolean pv, boolean pm, boolean e, boolean l) { - for (int a = 0; a < mask.length; a++) { - mask[a] = m; - } - sizes[PRESET_SIZE_NUM_PHOTO] = p; - sizes[PRESET_SIZE_NUM_VIDEO] = v; - sizes[PRESET_SIZE_NUM_DOCUMENT] = f; - sizes[PRESET_SIZE_NUM_AUDIO] = 512 * 1024; - preloadVideo = pv; - preloadMusic = pm; - lessCallData = l; - enabled = e; - } - public Preset(int[] m, int p, int v, int f, boolean pv, boolean pm, boolean e, boolean l) { System.arraycopy(m, 0, mask, 0, mask.length); sizes[PRESET_SIZE_NUM_PHOTO] = p; @@ -183,6 +169,15 @@ public class DownloadController implements NotificationCenter.NotificationCenter preloadVideo == obj.preloadVideo && preloadMusic == obj.preloadMusic; } + + public boolean isEnabled() { + for (int a = 0; a < mask.length; a++) { + if (mask[a] != 0) { + return true; + } + } + return false; + } } public Preset lowPreset; @@ -476,8 +471,10 @@ public class DownloadController implements NotificationCenter.NotificationCenter } else { for (int a = 0; a < photoDownloadQueue.size(); a++) { DownloadObject downloadObject = photoDownloadQueue.get(a); - if (downloadObject.object instanceof TLRPC.PhotoSize) { - FileLoader.getInstance(currentAccount).cancelLoadFile((TLRPC.PhotoSize) downloadObject.object); + if (downloadObject.object instanceof TLRPC.Photo) { + TLRPC.Photo photo = (TLRPC.Photo) downloadObject.object; + TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, AndroidUtilities.getPhotoSize()); + FileLoader.getInstance(currentAccount).cancelLoadFile(photoSize); } else if (downloadObject.object instanceof TLRPC.Document) { FileLoader.getInstance(currentAccount).cancelLoadFile((TLRPC.Document) downloadObject.object); } @@ -542,16 +539,21 @@ public class DownloadController implements NotificationCenter.NotificationCenter } public int canDownloadMedia(TLRPC.Message message) { + if (message == null) { + return 0; + } int type; boolean isVideo; - if ((isVideo = MessageObject.isVideoMessage(message)) || MessageObject.isGifMessage(message) || MessageObject.isRoundVideoMessage(message)) { + if ((isVideo = MessageObject.isVideoMessage(message)) || MessageObject.isGifMessage(message) || MessageObject.isRoundVideoMessage(message) || MessageObject.isGameMessage(message)) { type = AUTODOWNLOAD_TYPE_VIDEO; } else if (MessageObject.isVoiceMessage(message)) { type = AUTODOWNLOAD_TYPE_AUDIO; } else if (MessageObject.isPhoto(message) || MessageObject.isStickerMessage(message)) { type = AUTODOWNLOAD_TYPE_PHOTO; - } else { + } else if (MessageObject.getDocument(message) != null) { type = AUTODOWNLOAD_TYPE_DOCUMENT; + } else { + return 0; } int mask; int index; @@ -714,19 +716,32 @@ public class DownloadController implements NotificationCenter.NotificationCenter for (int a = 0; a < objects.size(); a++) { DownloadObject downloadObject = objects.get(a); String path; + TLRPC.PhotoSize photoSize = null; if (downloadObject.object instanceof TLRPC.Document) { TLRPC.Document document = (TLRPC.Document) downloadObject.object; path = FileLoader.getAttachFileName(document); - } else { + } else if (downloadObject.object instanceof TLRPC.Photo) { path = FileLoader.getAttachFileName(downloadObject.object); + TLRPC.Photo photo = (TLRPC.Photo) downloadObject.object; + photoSize = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, AndroidUtilities.getPhotoSize()); + } else { + path = null; } - if (downloadQueueKeys.containsKey(path)) { + if (path == null || downloadQueueKeys.containsKey(path)) { continue; } - boolean added = true; - if (downloadObject.object instanceof TLRPC.PhotoSize) { - FileLoader.getInstance(currentAccount).loadFile((TLRPC.PhotoSize) downloadObject.object, null, downloadObject.secret ? 2 : 0); + if (photoSize != null) { + TLRPC.Photo photo = (TLRPC.Photo) downloadObject.object; + int cacheType; + if (downloadObject.secret) { + cacheType = 2; + } else if (downloadObject.forceCache) { + cacheType = 1; + } else { + cacheType = 0; + } + FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForPhoto(photoSize, photo), downloadObject.parent, null, 0, cacheType); } else if (downloadObject.object instanceof TLRPC.Document) { TLRPC.Document document = (TLRPC.Document) downloadObject.object; FileLoader.getInstance(currentAccount).loadFile(document, downloadObject.parent, 0, downloadObject.secret ? 2 : 0); @@ -966,7 +981,7 @@ public class DownloadController implements NotificationCenter.NotificationCenter MessagesController.getInstance(currentAccount).sendTyping(dialog_id, 9, 0); } else if (delayedMessage.obj.getDocument() != null) { MessagesController.getInstance(currentAccount).sendTyping(dialog_id, 3, 0); - } else if (delayedMessage.location != null) { + } else if (delayedMessage.photoSize != null) { MessagesController.getInstance(currentAccount).sendTyping(dialog_id, 4, 0); } typingTimes.put(dialog_id, System.currentTimeMillis()); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DownloadObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/DownloadObject.java index 1ffa90b88..f830e151f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DownloadObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DownloadObject.java @@ -15,5 +15,6 @@ public class DownloadObject { public int type; public long id; public boolean secret; + public boolean forceCache; public String parent; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java b/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java index d01ca0b5e..f9b62f987 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java @@ -27,7 +27,6 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.text.Spannable; import android.text.Spanned; -import android.text.TextPaint; import android.text.style.DynamicDrawableSpan; import android.text.style.ImageSpan; import android.view.View; @@ -42,37 +41,42 @@ public class Emoji { private static boolean inited = false; private static Paint placeholderPaint; private static final int splitCount = 4; - private static Bitmap emojiBmp[][] = new Bitmap[5][splitCount]; - private static boolean loadingEmoji[][] = new boolean[5][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<>(); public static HashMap emojiColor = new HashMap<>(); private static boolean recentEmojiLoaded; + private final static int MAX_RECENT_EMOJI_COUNT = 48; + private static final int[][] cols = { {16, 16, 16, 16}, {6, 6, 6, 6}, - {9, 9, 9, 9}, - {9, 9, 9, 9}, - {10, 10, 10, 10} + {5, 5, 5, 5}, + {7, 7, 7, 7}, + {5, 5, 5, 5}, + {7, 7, 7, 7}, + {8, 8, 8, 8}, + {8, 8, 8, 8}, }; static { int emojiFullSize; int add = 2; if (AndroidUtilities.density <= 1.0f) { - emojiFullSize = 32; + emojiFullSize = 33; add = 1; } else if (AndroidUtilities.density <= 1.5f) { - emojiFullSize = 64; + emojiFullSize = 66; } else if (AndroidUtilities.density <= 2.0f) { - emojiFullSize = 64; + emojiFullSize = 66; } else { - emojiFullSize = 64; + emojiFullSize = 66; } drawImgSize = AndroidUtilities.dp(20); - bigImgSize = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 40 : 32); + bigImgSize = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 40 : 34); for (int j = 0; j < EmojiData.data.length; j++) { int count2 = (int) Math.ceil(EmojiData.data[j].length / (float) splitCount); @@ -107,38 +111,11 @@ public class Emoji { scale = 2.0f; } - /*String q = ""; - for (int a = 0; a < EmojiData.data.length; a++) { - String arr[] = EmojiData.data[a]; - for (int b = 0; b < arr.length; b++) { - String emoji = arr[b]; - for (int c = 0; c < emoji.length(); c++) { - if (emoji.charAt(c) == '\ufe0f') { - q += String.format("0x%x, ", (int) emoji.charAt(0)); - break; - } - } - } - } - FileLog.e(q);*/ - String imageName; File imageFile; try { - for (int a = 4; a < 7; a++) { - imageName = String.format(Locale.US, "v%d_emoji%.01fx_%d.jpg", a, scale, page); - imageFile = ApplicationLoader.applicationContext.getFileStreamPath(imageName); - if (imageFile.exists()) { - imageFile.delete(); - } - imageName = String.format(Locale.US, "v%d_emoji%.01fx_a_%d.jpg", a, scale, page); - imageFile = ApplicationLoader.applicationContext.getFileStreamPath(imageName); - if (imageFile.exists()) { - imageFile.delete(); - } - } - for (int a = 8; a < 12; a++) { + for (int a = 12; a < 14; a++) { imageName = String.format(Locale.US, "v%d_emoji%.01fx_%d.png", a, scale, page); imageFile = ApplicationLoader.applicationContext.getFileStreamPath(imageName); if (imageFile.exists()) { @@ -150,10 +127,13 @@ public class Emoji { } Bitmap bitmap = null; try { - InputStream is = ApplicationLoader.applicationContext.getAssets().open("emoji/" + String.format(Locale.US, "v13_emoji%.01fx_%d_%d.png", scale, page, page2)); + InputStream is = ApplicationLoader.applicationContext.getAssets().open("emoji/" + String.format(Locale.US, "v14_emoji%.01fx_%d_%d.png", scale, page, page2)); BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = false; opts.inSampleSize = imageResize; + if (Build.VERSION.SDK_INT >= 26) { + opts.inPreferredConfig = Bitmap.Config.HARDWARE; + } bitmap = BitmapFactory.decodeStream(is, null, opts); is.close(); } catch (Throwable e) { @@ -265,7 +245,6 @@ public class Emoji { private boolean fullSize = false; private static Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG); private static Rect rect = new Rect(); - private static TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); public EmojiDrawable(DrawableInfo i) { info = i; @@ -574,15 +553,10 @@ public class Emoji { if (count == null) { count = 0; } - if (count == 0 && emojiUseHistory.size() > 50) { - for (int a = recentEmoji.size() - 1; a >= 0; a--) { - String emoji = recentEmoji.get(a); - emojiUseHistory.remove(emoji); - recentEmoji.remove(a); - if (emojiUseHistory.size() <= 50) { - break; - } - } + if (count == 0 && emojiUseHistory.size() >= MAX_RECENT_EMOJI_COUNT) { + String emoji = recentEmoji.get(recentEmoji.size() - 1); + emojiUseHistory.remove(emoji); + recentEmoji.set(recentEmoji.size() - 1, code); } emojiUseHistory.put(code, ++count); } @@ -608,7 +582,7 @@ public class Emoji { } return 0; }); - while (recentEmoji.size() > 50) { + while (recentEmoji.size() > MAX_RECENT_EMOJI_COUNT) { recentEmoji.remove(recentEmoji.size() - 1); } } @@ -727,6 +701,4 @@ public class Emoji { } preferences.edit().putString("color", stringBuilder.toString()).commit(); } - - public static native Object[] getSuggestion(String query); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/EmojiData.java b/TMessagesProj/src/main/java/org/telegram/messenger/EmojiData.java index 75a027f2c..889735f68 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/EmojiData.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/EmojiData.java @@ -24,7 +24,6 @@ public class EmojiData { 0x25FC, 0x25FB, 0x25FE, 0x25FD, 0x2660, 0x2663, 0x2665, 0x2666, 0x263A, 0x2639, 0x270C, 0x261D, 0x2764 }; - //0xD83CDE2F, 0xD83CDC04, 0xD83CDE1A, 0xD83CDD7F public static final char[] dataChars = { 0x262E, 0x271D, 0x262A, 0x2638, 0x2721, 0x262F, 0x2626, 0x26CE, 0x2648, 0x2649, @@ -226,11 +225,12 @@ public class EmojiData { "🚶‍♂", "🏃‍♀", "🏃‍♂", - "👫", "👭", "👬", "💑", "👩‍❤‍👩", "👨‍❤‍👨", "💏", "👩‍❤‍💋‍👩", "👨‍❤‍💋‍👨", "👪", "👨‍👩‍👧", "👨‍👩‍👧‍👦", "👨‍👩‍👦‍👦", "👨‍👩‍👧‍👧", "👩‍👩‍👦", "👩‍👩‍👧", "👩‍👩‍👧‍👦", "👩‍👩‍👦‍👦", "👩‍👩‍👧‍👧", "👨‍👨‍👦", "👨‍👨‍👧", "👨‍👨‍👧‍👦", "👨‍👨‍👦‍👦", "👨‍👨‍👧‍👧", "👩‍👦", "👩‍👧", "👩‍👧‍👦", "👩‍👦‍👦", "👩‍👧‍👧", "👨‍👦", "👨‍👧", "👨‍👧‍👦", "👨‍👦‍👦", "👨‍👧‍👧", "🧶", "🧵", "🧥", "🥼", "👚", "👕", "👖", "👔", "👗", "👙", "👘", "🥿", "👠", "👡", "👢", "👞", "👟", "🥾", "🧦", "🧤", "🧣", "🎩", "🧢", "👒", "🎓", "⛑", "👑", "💍", "👝", "👛", "👜", "💼", "🎒", "🧳", "👓", "🕶", "🥽", "🌂", "❤", "🧡", "💛", "💚", "💙", "💜", "🖤", "💔", "❣", "💕", "💞", "💓", "💗", "💖", "💘", "💝", + "👫", "👭", "👬", "💑", "👩‍❤‍👩", "👨‍❤‍👨", "💏", "👩‍❤‍💋‍👩", "👨‍❤‍💋‍👨", "👪", "👨‍👩‍👧", "👨‍👩‍👧‍👦", "👨‍👩‍👦‍👦", "👨‍👩‍👧‍👧", "👩‍👩‍👦", "👩‍👩‍👧", "👩‍👩‍👧‍👦", "👩‍👩‍👦‍👦", "👩‍👩‍👧‍👧", "👨‍👨‍👦", "👨‍👨‍👧", "👨‍👨‍👧‍👦", "👨‍👨‍👦‍👦", "👨‍👨‍👧‍👧", "👩‍👦", "👩‍👧", "👩‍👧‍👦", "👩‍👦‍👦", "👩‍👧‍👧", "👨‍👦", "👨‍👧", "👨‍👧‍👦", "👨‍👦‍👦", "👨‍👧‍👧", "🧶", "🧵", "🧥", "🥼", "👚", "👕", "👖", "👔", "👗", "👙", "👘", "🥿", "👠", "👡", "👢", "👞", "👟", "🥾", "🧦", "🧤", "🧣", "🎩", "🧢", "👒", "🎓", "⛑", "👑", "💍", "👝", "👛", "👜", "💼", "🎒", "🧳", "👓", "🕶", "🥽", "🌂", }, null, + null, new String[]{ - "🍏", "🍎", "🍐", "🍊", "🍋", "🍌", "🍉", "🍇", "🍓", "🍈", "🍒", "🍑", "🥭", "🍍", "🥥", "🥝", "🍅", "🍆", "🥑", "🥦", "🥬", "🥒", "🌶", "🌽", "🥕", "🥔", "🍠", "🥐", "🥯", "🍞", "🥖", "🥨", "🧀", "🥚", "🍳", "🥞", "🥓", "🥩", "🍗", "🍖", "🦴", "🌭", "🍔", "🍟", "🍕", "🥪", "🥙", "🌮", "🌯", "🥗", "🥘", "🥫", "🍝", "🍜", "🍲", "🍛", "🍣", "🍱", "🥟", "🍤", "🍙", "🍚", "🍘", "🍥", "🥠", "🥮", "🍢", "🍡", "🍧", "🍨", "🍦", "🥧", "🧁", "🍰", "🎂", "🍮", "🍭", "🍬", "🍫", "🍿", "🍩", "🍪", "🌰", "🥜", "🍯", "🥛", "🍼", "☕", "🍵", "🥤", "🍶", "🍺", "🍻", "🥂", "🍷", "🥃", "🍸", "🍹", "🍾", "🥄", "🍴", "🍽", "🥣", "🥡", "🥢", "🧂", "⚽", "🏀", "🏈", "⚾", "🥎", "🎾", "🏐", "🏉", "🥏", "🎱", "🏓", "🏸", "🏒", "🏑", "🥍", "🏏", "🥅", "⛳", "🏹", "🎣", "🥊", "🥋", "🎽", "🛹", "🛷", "⛸", "🥌", "🎿", "⛷", "🏂", + "⚽", "🏀", "🏈", "⚾", "🥎", "🎾", "🏐", "🏉", "🥏", "🎱", "🏓", "🏸", "🏒", "🏑", "🥍", "🏏", "🥅", "⛳", "🏹", "🎣", "🥊", "🥋", "🎽", "🛹", "🛷", "⛸", "🥌", "🎿", "⛷", "🏂", "🏋‍♀", "🏋‍♂", "🤼‍♀", "🤼‍♂", @@ -267,14 +267,109 @@ public class EmojiData { }, null, new String[]{ - "💟", "☮", "✝", "☪", "🕉", "☸", "✡", "🔯", "🕎", "☯", "☦", "🛐", "⛎", "♈", "♉", "♊", "♋", "♌", "♍", "♎", "♏", "♐", "♑", "♒", "♓", "🆔", "⚛", "🉑", "☢", "☣", "📴", "📳", "🈶", "🈚", "🈸", "🈺", "🈷", "✴", "🆚", "💮", "🉐", "㊙", "㊗", "🈴", "🈵", "🈹", "🈲", "🅰", "🅱", "🆎", "🆑", "🅾", "🆘", "❌", "⭕", "🛑", "⛔", "📛", "🚫", "💯", "💢", "♨", "🚷", "🚯", "🚳", "🚱", "🔞", "📵", "🚭", "❗", "❕", "❓", "❔", "‼", "⁉", "🔅", "🔆", "〽", "⚠", "🚸", "🔱", "⚜", "🔰", "♻", "✅", "🈯", "💹", "❇", "✳", "❎", "🌐", "💠", "Ⓜ", "🌀", "💤", "🏧", "🚾", "♿", "🅿", "🈳", "🈂", "🛂", "🛃", "🛄", "🛅", "🚹", "🚺", "🚼", "🚻", "🚮", "🎦", "📶", "🈁", "🔣", "ℹ", "🔤", "🔡", "🔠", "🆖", "🆗", "🆙", "🆒", "🆕", "🆓", "0⃣", "1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣", "🔟", "🔢", "#⃣", "*⃣", "⏏", "▶", "⏸", "⏯", "⏹", "⏺", "⏭", "⏮", "⏩", "⏪", "⏫", "⏬", "◀", "🔼", "🔽", "➡", "⬅", "⬆", "⬇", "↗", "↘", "↙", "↖", "↕", "↔", "↪", "↩", "⤴", "⤵", "🔀", "🔁", "🔂", "🔄", "🔃", "🎵", "🎶", "➕", "➖", "➗", "✖", "♾", "💲", "💱", "™", "©", "®", "👁‍🗨", "🔚", "🔙", "🔛", "🔝", "🔜", "〰", "➰", "➿", "✔", "☑", "🔘", "⚪", "⚫", "🔴", "🔵", "🔺", "🔻", "🔸", "🔹", "🔶", "🔷", "🔳", "🔲", "▪", "▫", "◾", "◽", "◼", "◻", "⬛", "⬜", "🔈", "🔇", "🔉", "🔊", "🔔", "🔕", "📣", "📢", "💬", "💭", "🗯", "♠", "♣", "♥", "♦", "🃏", "🎴", "🀄", "🕐", "🕑", "🕒", "🕓", "🕔", "🕕", "🕖", "🕗", "🕘", "🕙", "🕚", "🕛", "🕜", "🕝", "🕞", "🕟", "🕠", "🕡", "🕢", "🕣", "🕤", "🕥", "🕦", "🕧", "⌚", "📱", "📲", "💻", "⌨", "🖥", "🖨", "🖱", "🖲", "🕹", "🗜", "💽", "💾", "💿", "📀", "📼", "📷", "📸", "📹", "🎥", "📽", "🎞", "📞", "☎", "📟", "📠", "📺", "📻", "🎙", "🎚", "🎛", "🧭", "⏱", "⏲", "⏰", "🕰", "⌛", "⏳", "📡", "🔋", "🔌", "💡", "🔦", "🕯", "🧯", "🛢", "💸", "💵", "💴", "💶", "💷", "💰", "💳", "💎", "⚖", "🧰", "🔧", "🔨", "⚒", "🛠", "⛏", "🔩", "⚙", "🧱", "⛓", "🧲", "🔫", "💣", "🧨", "🔪", "🗡", "⚔", "🛡", "🚬", "⚰", "⚱", "🏺", "🔮", "📿", "🧿", "💈", "⚗", "🔭", "🔬", "🕳", "💊", "💉", "🧬", "🦠", "🧫", "🧪", "🌡", "🧹", "🧺", "🧻", "🚽", "🚰", "🚿", "🛁", + "⌚", "📱", "📲", "💻", "⌨", "🖥", "🖨", "🖱", "🖲", "🕹", "🗜", "💽", "💾", "💿", "📀", "📼", "📷", "📸", "📹", "🎥", "📽", "🎞", "📞", "☎", "📟", "📠", "📺", "📻", "🎙", "🎚", "🎛", "🧭", "⏱", "⏲", "⏰", "🕰", "⌛", "⏳", "📡", "🔋", "🔌", "💡", "🔦", "🕯", "🧯", "🛢", "💸", "💵", "💴", "💶", "💷", "💰", "💳", "💎", "⚖", "🧰", "🔧", "🔨", "⚒", "🛠", "⛏", "🔩", "⚙", "🧱", "⛓", "🧲", "🔫", "💣", "🧨", "🔪", "🗡", "⚔", "🛡", "🚬", "⚰", "⚱", "🏺", "🔮", "📿", "🧿", "💈", "⚗", "🔭", "🔬", "🕳", "💊", "💉", "🧬", "🦠", "🧫", "🧪", "🌡", "🧹", "🧺", "🧻", "🚽", "🚰", "🚿", "🛁", "🛀", "🧼", "🧽", "🧴", "🛎", "🔑", "🗝", "🚪", "🛋", "🛏", "🛌", "🧸", "🖼", "🛍", "🛒", "🎁", "🎈", "🎏", "🎀", "🎊", "🎉", "🎎", "🏮", "🎐", "🧧", "✉", "📩", "📨", "📧", "💌", "📥", "📤", "📦", "🏷", "📪", "📫", "📬", "📭", "📮", "📯", "📜", "📃", "📄", "📑", "🧾", "📊", "📈", "📉", "🗒", "🗓", "📆", "📅", "🗑", "📇", "🗃", "🗳", "🗄", "📋", "📁", "📂", "🗂", "🗞", "📰", "📓", "📔", "📒", "📕", "📗", "📘", "📙", "📚", "📖", "🔖", "🧷", "🔗", "📎", "🖇", "📐", "📏", "🧮", "📌", "📍", "✂", "🖊", "🖋", "✒", "🖌", "🖍", "📝", "✏", "🔍", "🔎", "🔏", "🔐", "🔒", "🔓" - } + }, + null, + null }; - public static final String[] aliasOld = new String[] {"👱", "👱🏻", "👱🏼", "👱🏽", "👱🏾", "👱🏿", "👳", "👳🏻", "👳🏼", "👳🏽", "👳🏾", "👳🏿", "👷", "👷🏻", "👷🏼", "👷🏽", "👷🏾", "👷🏿", "👮", "👮🏻", "👮🏼", "👮🏽", "👮🏾", "👮🏿", "💂", "💂🏻", "💂🏼", "💂🏽", "💂🏾", "💂🏿", "🕵", "🕵🏻", "🕵🏼", "🕵🏽", "🕵🏾", "🕵🏿", "🙇", "🙇🏻", "🙇🏼", "🙇🏽", "🙇🏾", "🙇🏿", "💁", "💁🏻", "💁🏼", "💁🏽", "💁🏾", "💁🏿", "🙅", "🙅🏻", "🙅🏼", "🙅🏽", "🙅🏾", "🙅🏿", "🙆", "🙆🏻", "🙆🏼", "🙆🏽", "🙆🏾", "🙆🏿", "🙋", "🙋🏻", "🙋🏼", "🙋🏽", "🙋🏾", "🙋🏿", "🙎", "🙎🏻", "🙎🏼", "🙎🏽", "🙎🏾", "🙎🏿", "🙍", "🙍🏻", "🙍🏼", "🙍🏽", "🙍🏾", "🙍🏿", "💇", "💇🏻", "💇🏼", "💇🏽", "💇🏾", "💇🏿", "💆", "💆🏻", "💆🏼", "💆🏽", "💆🏾", "💆🏿", "🏃", "🏃🏻", "🏃🏼", "🏃🏽", "🏃🏾", "🏃🏿", "🏋", "🏋🏻", "🏋🏼", "🏋🏽", "🏋🏾", "🏋🏿", "⛹", "⛹🏻", "⛹🏼", "⛹🏽", "⛹🏾", "⛹🏿", "🏌", "🏌🏻", "🏌🏼", "🏌🏽", "🏌🏾", "🏌🏿", "🏄", "🏄🏻", "🏄🏼", "🏄🏽", "🏄🏾", "🏄🏿", "🏊", "🏊🏻", "🏊🏼", "🏊🏽", "🏊🏾", "🏊🏿", "🚣", "🚣🏻", "🚣🏼", "🚣🏽", "🚣🏾", "🚣🏿", "🚴", "🚴🏻", "🚴🏼", "🚴🏽", "🚴🏾", "🚴🏿", "🚵", "🚵🏻", "🚵🏼", "🚵🏽", "🚵🏾", "🚵🏿"}; - public static final String[] aliasNew = new String[] {"👱‍♂", "👱🏻‍♂", "👱🏼‍♂", "👱🏽‍♂", "👱🏾‍♂", "👱🏿‍♂", "👳‍♂", "👳🏻‍♂", "👳🏼‍♂", "👳🏽‍♂", "👳🏾‍♂", "👳🏿‍♂", "👷‍♂", "👷🏻‍♂", "👷🏼‍♂", "👷🏽‍♂", "👷🏾‍♂", "👷🏿‍♂", "👮‍♂", "👮🏻‍♂", "👮🏼‍♂", "👮🏽‍♂", "👮🏾‍♂", "👮🏿‍♂", "💂‍♂", "💂🏻‍♂", "💂🏼‍♂", "💂🏽‍♂", "💂🏾‍♂", "💂🏿‍♂", "🕵‍♂", "🕵🏻‍♂", "🕵🏼‍♂", "🕵🏽‍♂", "🕵🏾‍♂", "🕵🏿‍♂","🙇‍♂", "🙇🏻‍♂", "🙇🏼‍♂", "🙇🏽‍♂", "🙇🏾‍♂", "🙇🏿‍♂", "💁‍♀", "💁🏻‍♀", "💁🏼‍♀", "💁🏽‍♀", "💁🏾‍♀", "💁🏿‍♀", "🙅‍♀", "🙅🏻‍♀", "🙅🏼‍♀", "🙅🏽‍♀", "🙅🏾‍♀", "🙅🏿‍♀", "🙆‍♀", "🙆🏻‍♀", "🙆🏼‍♀", "🙆🏽‍♀", "🙆🏾‍♀", "🙆🏿‍♀", "🙋‍♀", "🙋🏻‍♀", "🙋🏼‍♀", "🙋🏽‍♀", "🙋🏾‍♀", "🙋🏿‍♀", "🙎‍♀", "🙎🏻‍♀", "🙎🏼‍♀", "🙎🏽‍♀", "🙎🏾‍♀", "🙎🏿‍♀", "🙍‍♀", "🙍🏻‍♀", "🙍🏼‍♀", "🙍🏽‍♀", "🙍🏾‍♀", "🙍🏿‍♀", "💇‍♀", "💇🏻‍♀", "💇🏼‍♀", "💇🏽‍♀", "💇🏾‍♀", "💇🏿‍♀", "💆‍♀", "💆🏻‍♀", "💆🏼‍♀", "💆🏽‍♀", "💆🏾‍♀", "💆🏿‍♀", "🏃‍♂", "🏃🏻‍♂", "🏃🏼‍♂", "🏃🏽‍♂", "🏃🏾‍♂", "🏃🏿‍♂", "🏋‍♂", "🏋🏻‍♂", "🏋🏼‍♂", "🏋🏽‍♂", "🏋🏾‍♂", "🏋🏿‍♂", "⛹‍♂", "⛹🏻‍♂", "⛹🏼‍♂", "⛹🏽‍♂", "⛹🏾‍♂", "⛹🏿‍♂", "🏌‍♂", "🏌🏻‍♂", "🏌🏼‍♂", "🏌🏽‍♂", "🏌🏾‍♂", "🏌🏿‍♂", "🏄‍♂", "🏄🏻‍♂", "🏄🏼‍♂", "🏄🏽‍♂", "🏄🏾‍♂", "🏄🏿‍♂", "🏊‍♂", "🏊🏻‍♂", "🏊🏼‍♂", "🏊🏽‍♂", "🏊🏾‍♂", "🏊🏿‍♂", "🚣‍♂", "🚣🏻‍♂", "🚣🏼‍♂", "🚣🏽‍♂", "🚣🏾‍♂", "🚣🏿‍♂", "🚴‍♂", "🚴🏻‍♂", "🚴🏼‍♂", "🚴🏽‍♂", "🚴🏾‍♂", "🚴🏿‍♂", "🚵‍♂", "🚵🏻‍♂", "🚵🏼‍♂", "🚵🏽‍♂", "🚵🏾‍♂", "🚵🏿‍♂"}; + public static final String[] aliasOld = new String[] { + "👱", "👱🏻", "👱🏼", "👱🏽", "👱🏾", "👱🏿", + "👳", "👳🏻", "👳🏼", "👳🏽", "👳🏾", "👳🏿", + "👷", "👷🏻", "👷🏼", "👷🏽", "👷🏾", "👷🏿", + "👮", "👮🏻", "👮🏼", "👮🏽", "👮🏾", "👮🏿", + "💂", "💂🏻", "💂🏼", "💂🏽", "💂🏾", "💂🏿", + "🕵", "🕵🏻", "🕵🏼", "🕵🏽", "🕵🏾", "🕵🏿", + "🙇", "🙇🏻", "🙇🏼", "🙇🏽", "🙇🏾", "🙇🏿", + "💁", "💁🏻", "💁🏼", "💁🏽", "💁🏾", "💁🏿", + "🙅", "🙅🏻", "🙅🏼", "🙅🏽", "🙅🏾", "🙅🏿", + "🙆", "🙆🏻", "🙆🏼", "🙆🏽", "🙆🏾", "🙆🏿", + "🙋", "🙋🏻", "🙋🏼", "🙋🏽", "🙋🏾", "🙋🏿", + "🙎", "🙎🏻", "🙎🏼", "🙎🏽", "🙎🏾", "🙎🏿", + "🙍", "🙍🏻", "🙍🏼", "🙍🏽", "🙍🏾", "🙍🏿", + "💇", "💇🏻", "💇🏼", "💇🏽", "💇🏾", "💇🏿", + "💆", "💆🏻", "💆🏼", "💆🏽", "💆🏾", "💆🏿", + "🏃", "🏃🏻", "🏃🏼", "🏃🏽", "🏃🏾", "🏃🏿", + "🏋", "🏋🏻", "🏋🏼", "🏋🏽", "🏋🏾", "🏋🏿", + "⛹", "⛹🏻", "⛹🏼", "⛹🏽", "⛹🏾", "⛹🏿", + "🏌", "🏌🏻", "🏌🏼", "🏌🏽", "🏌🏾", "🏌🏿", + "🏄", "🏄🏻", "🏄🏼", "🏄🏽", "🏄🏾", "🏄🏿", + "🏊", "🏊🏻", "🏊🏼", "🏊🏽", "🏊🏾", "🏊🏿", + "🚣", "🚣🏻", "🚣🏼", "🚣🏽", "🚣🏾", "🚣🏿", + "🚴", "🚴🏻", "🚴🏼", "🚴🏽", "🚴🏾", "🚴🏿", + "🚵", "🚵🏻", "🚵🏼", "🚵🏽", "🚵🏾", "🚵🏿", + + "🦸", "🦸🏻", "🦸🏼", "🦸🏽", "🦸🏾", "🦸🏿", + "🦹", "🦹🏻", "🦹🏼", "🦹🏽", "🦹🏾", "🦹🏿", + "🧙", "🧙🏻", "🧙🏼", "🧙🏽", "🧙🏾", "🧙🏿", + "🧝", "🧝🏻", "🧝🏼", "🧝🏽", "🧝🏾", "🧝🏿", + "🧛", "🧛🏻", "🧛🏼", "🧛🏽", "🧛🏾", "🧛🏿", + "🧟", + "🧞", + "🧜", "🧜🏻", "🧜🏼", "🧜🏽", "🧜🏾", "🧜🏿", + "🧚", "🧚🏻", "🧚🏼", "🧚🏽", "🧚🏾", "🧚🏿", + "🤦", "🤦🏻", "🤦🏼", "🤦🏽", "🤦🏾", "🤦🏿", + "🤷", "🤷🏻", "🤷🏼", "🤷🏽", "🤷🏾", "🤷🏿", + "🧖", "🧖🏻", "🧖🏼", "🧖🏽", "🧖🏾", "🧖🏿", + "👯", + "🚶", "🚶🏻", "🚶🏼", "🚶🏽", "🚶🏾", "🚶🏿", + "🤼", + "🤸", "🤸🏻", "🤸🏼", "🤸🏽", "🤸🏾", "🤸🏿", + "🤾", "🤾🏻", "🤾🏼", "🤾🏽", "🤾🏾", "🤾🏿", + "🧘", "🧘🏻", "🧘🏼", "🧘🏽", "🧘🏾", "🧘🏿", + "🤽", "🤽🏻", "🤽🏼", "🤽🏽", "🤽🏾", "🤽🏿", + "🧗", "🧗🏻", "🧗🏼", "🧗🏽", "🧗🏾", "🧗🏿", + "🤹", "🤹🏻", "🤹🏼", "🤹🏽", "🤹🏾", "🤹🏿"}; + + public static final String[] aliasNew = new String[] { + "👱‍♂", "👱🏻‍♂", "👱🏼‍♂", "👱🏽‍♂", "👱🏾‍♂", "👱🏿‍♂", + "👳‍♂", "👳🏻‍♂", "👳🏼‍♂", "👳🏽‍♂", "👳🏾‍♂", "👳🏿‍♂", + "👷‍♂", "👷🏻‍♂", "👷🏼‍♂", "👷🏽‍♂", "👷🏾‍♂", "👷🏿‍♂", + "👮‍♂", "👮🏻‍♂", "👮🏼‍♂", "👮🏽‍♂", "👮🏾‍♂", "👮🏿‍♂", + "💂‍♂", "💂🏻‍♂", "💂🏼‍♂", "💂🏽‍♂", "💂🏾‍♂", "💂🏿‍♂", + "🕵‍♂", "🕵🏻‍♂", "🕵🏼‍♂", "🕵🏽‍♂", "🕵🏾‍♂", "🕵🏿‍♂", + "🙇‍♂", "🙇🏻‍♂", "🙇🏼‍♂", "🙇🏽‍♂", "🙇🏾‍♂", "🙇🏿‍♂", + "💁‍♀", "💁🏻‍♀", "💁🏼‍♀", "💁🏽‍♀", "💁🏾‍♀", "💁🏿‍♀", + "🙅‍♀", "🙅🏻‍♀", "🙅🏼‍♀", "🙅🏽‍♀", "🙅🏾‍♀", "🙅🏿‍♀", + "🙆‍♀", "🙆🏻‍♀", "🙆🏼‍♀", "🙆🏽‍♀", "🙆🏾‍♀", "🙆🏿‍♀", + "🙋‍♀", "🙋🏻‍♀", "🙋🏼‍♀", "🙋🏽‍♀", "🙋🏾‍♀", "🙋🏿‍♀", + "🙎‍♀", "🙎🏻‍♀", "🙎🏼‍♀", "🙎🏽‍♀", "🙎🏾‍♀", "🙎🏿‍♀", + "🙍‍♀", "🙍🏻‍♀", "🙍🏼‍♀", "🙍🏽‍♀", "🙍🏾‍♀", "🙍🏿‍♀", + "💇‍♀", "💇🏻‍♀", "💇🏼‍♀", "💇🏽‍♀", "💇🏾‍♀", "💇🏿‍♀", + "💆‍♀", "💆🏻‍♀", "💆🏼‍♀", "💆🏽‍♀", "💆🏾‍♀", "💆🏿‍♀", + "🏃‍♂", "🏃🏻‍♂", "🏃🏼‍♂", "🏃🏽‍♂", "🏃🏾‍♂", "🏃🏿‍♂", + "🏋‍♂", "🏋🏻‍♂", "🏋🏼‍♂", "🏋🏽‍♂", "🏋🏾‍♂", "🏋🏿‍♂", + "⛹‍♂", "⛹🏻‍♂", "⛹🏼‍♂", "⛹🏽‍♂", "⛹🏾‍♂", "⛹🏿‍♂", + "🏌‍♂", "🏌🏻‍♂", "🏌🏼‍♂", "🏌🏽‍♂", "🏌🏾‍♂", "🏌🏿‍♂", + "🏄‍♂", "🏄🏻‍♂", "🏄🏼‍♂", "🏄🏽‍♂", "🏄🏾‍♂", "🏄🏿‍♂", + "🏊‍♂", "🏊🏻‍♂", "🏊🏼‍♂", "🏊🏽‍♂", "🏊🏾‍♂", "🏊🏿‍♂", + "🚣‍♂", "🚣🏻‍♂", "🚣🏼‍♂", "🚣🏽‍♂", "🚣🏾‍♂", "🚣🏿‍♂", + "🚴‍♂", "🚴🏻‍♂", "🚴🏼‍♂", "🚴🏽‍♂", "🚴🏾‍♂", "🚴🏿‍♂", + "🚵‍♂", "🚵🏻‍♂", "🚵🏼‍♂", "🚵🏽‍♂", "🚵🏾‍♂", "🚵🏿‍♂", + + "🦸‍♀", "🦸🏻‍♀", "🦸🏼‍♀", "🦸🏽‍♀", "🦸🏾‍♀", "🦸🏿‍♀", + "🦹‍♀", "🦹🏻‍♀", "🦹🏼‍♀", "🦹🏽‍♀", "🦹🏾‍♀", "🦹🏿‍♀", + "🧙‍♀", "🧙🏻‍♀", "🧙🏼‍♀", "🧙🏽‍♀", "🧙🏾‍♀", "🧙🏿‍♀", + "🧝‍♂", "🧝🏻‍♂", "🧝🏼‍♂", "🧝🏽‍♂", "🧝🏾‍♂", "🧝🏿‍♂", + "🧛‍♂", "🧛🏻‍♂", "🧛🏼‍♂", "🧛🏽‍♂", "🧛🏾‍♂", "🧛🏿‍♂", + "🧟‍♂", + "🧞‍♂", + "🧜‍♂", "🧜🏻‍♂", "🧜🏼‍♂", "🧜🏽‍♂", "🧜🏾‍♂", "🧜🏿‍♂", + "🧚‍♀", "🧚🏻‍♀", "🧚🏼‍♀", "🧚🏽‍♀", "🧚🏾‍♀", "🧚🏿‍♀", + "🤦‍♂", "🤦🏻‍♂", "🤦🏼‍♂", "🤦🏽‍♂", "🤦🏾‍♂", "🤦🏿‍♂", + "🤷‍♀", "🤷🏻‍♀", "🤷🏼‍♀", "🤷🏽‍♀", "🤷🏾‍♀", "🤷🏿‍♀", + "🧖‍♂", "🧖🏻‍♂", "🧖🏼‍♂", "🧖🏽‍♂", "🧖🏾‍♂", "🧖🏿‍♂", + "👯‍♀", + "🚶‍♂", "🚶🏻‍♂", "🚶🏼‍♂", "🚶🏽‍♂", "🚶🏾‍♂", "🚶🏿‍♂", + "🤼‍♀", + "🤸‍♂", "🤸🏻‍♂", "🤸🏼‍♂", "🤸🏽‍♂", "🤸🏾‍♂", "🤸🏿‍♂", + "🤾‍♀", "🤾🏻‍♀", "🤾🏼‍♀", "🤾🏽‍♀", "🤾🏾‍♀", "🤾🏿‍♀", + "🧘‍♀", "🧘🏻‍♀", "🧘🏼‍♀", "🧘🏽‍♀", "🧘🏾‍♀", "🧘🏿‍♀", + "🤽‍♂", "🤽🏻‍♂", "🤽🏼‍♂", "🤽🏽‍♂", "🤽🏾‍♂", "🤽🏿‍♂", + "🧗‍♂", "🧗🏻‍♂", "🧗🏼‍♂", "🧗🏽‍♂", "🧗🏾‍♂", "🧗🏿‍♂", + "🤹‍♂", "🤹🏻‍♂", "🤹🏼‍♂", "🤹🏽‍♂", "🤹🏾‍♂", "🤹🏿‍♂"}; public static final String[][] data = { new String[]{ @@ -439,13 +534,16 @@ public class EmojiData { "🚶‍♂", "🚶🏻‍♂", "🚶🏼‍♂", "🚶🏽‍♂", "🚶🏾‍♂", "🚶🏿‍♂", "🏃‍♀", "🏃🏻‍♀", "🏃🏼‍♀", "🏃🏽‍♀", "🏃🏾‍♀", "🏃🏿‍♀", "🏃‍♂", "🏃🏻‍♂", "🏃🏼‍♂", "🏃🏽‍♂", "🏃🏾‍♂", "🏃🏿‍♂", - "👫", "👭", "👬", "💑", "👩‍❤‍👩", "👨‍❤‍👨", "💏", "👩‍❤‍💋‍👩", "👨‍❤‍💋‍👨", "👪", "👨‍👩‍👧", "👨‍👩‍👧‍👦", "👨‍👩‍👦‍👦", "👨‍👩‍👧‍👧", "👩‍👩‍👦", "👩‍👩‍👧", "👩‍👩‍👧‍👦", "👩‍👩‍👦‍👦", "👩‍👩‍👧‍👧", "👨‍👨‍👦", "👨‍👨‍👧", "👨‍👨‍👧‍👦", "👨‍👨‍👦‍👦", "👨‍👨‍👧‍👧", "👩‍👦", "👩‍👧", "👩‍👧‍👦", "👩‍👦‍👦", "👩‍👧‍👧", "👨‍👦", "👨‍👧", "👨‍👧‍👦", "👨‍👦‍👦", "👨‍👧‍👧", "🧶", "🧵", "🧥", "🥼", "👚", "👕", "👖", "👔", "👗", "👙", "👘", "🥿", "👠", "👡", "👢", "👞", "👟", "🥾", "🧦", "🧤", "🧣", "🎩", "🧢", "👒", "🎓", "⛑", "👑", "💍", "👝", "👛", "👜", "💼", "🎒", "🧳", "👓", "🕶", "🥽", "🌂", "❤", "🧡", "💛", "💚", "💙", "💜", "🖤", "💔", "❣", "💕", "💞", "💓", "💗", "💖", "💘", "💝", + "👫", "👭", "👬", "💑", "👩‍❤‍👩", "👨‍❤‍👨", "💏", "👩‍❤‍💋‍👩", "👨‍❤‍💋‍👨", "👪", "👨‍👩‍👧", "👨‍👩‍👧‍👦", "👨‍👩‍👦‍👦", "👨‍👩‍👧‍👧", "👩‍👩‍👦", "👩‍👩‍👧", "👩‍👩‍👧‍👦", "👩‍👩‍👦‍👦", "👩‍👩‍👧‍👧", "👨‍👨‍👦", "👨‍👨‍👧", "👨‍👨‍👧‍👦", "👨‍👨‍👦‍👦", "👨‍👨‍👧‍👧", "👩‍👦", "👩‍👧", "👩‍👧‍👦", "👩‍👦‍👦", "👩‍👧‍👧", "👨‍👦", "👨‍👧", "👨‍👧‍👦", "👨‍👦‍👦", "👨‍👧‍👧", "🧶", "🧵", "🧥", "🥼", "👚", "👕", "👖", "👔", "👗", "👙", "👘", "🥿", "👠", "👡", "👢", "👞", "👟", "🥾", "🧦", "🧤", "🧣", "🎩", "🧢", "👒", "🎓", "⛑", "👑", "💍", "👝", "👛", "👜", "💼", "🎒", "🧳", "👓", "🕶", "🥽", "🌂", }, new String[]{ "🐶", "🐱", "🐭", "🐹", "🐰", "🦊", "🐻", "🐼", "🐨", "🐯", "🦁", "🐮", "🐷", "🐽", "🐸", "🐵", "🙈", "🙉", "🙊", "🐒", "🐔", "🐧", "🐦", "🐤", "🐣", "🐥", "🦆", "🦅", "🦉", "🦇", "🐺", "🐗", "🐴", "🦄", "🐝", "🐛", "🦋", "🐌", "🐞", "🐜", "🦟", "🦗", "🕷", "🕸", "🦂", "🐢", "🐍", "🦎", "🦖", "🦕", "🐙", "🦑", "🦐", "🦞", "🦀", "🐡", "🐠", "🐟", "🐬", "🐳", "🐋", "🦈", "🐊", "🐅", "🐆", "🦓", "🦍", "🐘", "🦛", "🦏", "🐪", "🐫", "🦒", "🦘", "🐃", "🐂", "🐄", "🐎", "🐖", "🐏", "🐑", "🦙", "🐐", "🦌", "🐕", "🐩", "🐈", "🐓", "🦃", "🦚", "🦜", "🦢", "🕊", "🐇", "🦝", "🦡", "🐁", "🐀", "🐿", "🦔", "🐾", "🐉", "🐲", "🌵", "🎄", "🌲", "🌳", "🌴", "🌱", "🌿", "☘", "🍀", "🎍", "🎋", "🍃", "🍂", "🍁", "🍄", "🐚", "🌾", "💐", "🌷", "🌹", "🥀", "🌺", "🌸", "🌼", "🌻", "🌞", "🌝", "🌛", "🌜", "🌚", "🌕", "🌖", "🌗", "🌘", "🌑", "🌒", "🌓", "🌔", "🌙", "🌎", "🌍", "🌏", "💫", "⭐", "🌟", "✨", "⚡", "☄", "💥", "🔥", "🌪", "🌈", "☀", "🌤", "⛅", "🌥", "☁", "🌦", "🌧", "⛈", "🌩", "🌨", "❄", "☃", "⛄", "🌬", "💨", "💧", "💦", "☔", "☂", "🌊", "🌫", }, new String[]{ - "🍏", "🍎", "🍐", "🍊", "🍋", "🍌", "🍉", "🍇", "🍓", "🍈", "🍒", "🍑", "🥭", "🍍", "🥥", "🥝", "🍅", "🍆", "🥑", "🥦", "🥬", "🥒", "🌶", "🌽", "🥕", "🥔", "🍠", "🥐", "🥯", "🍞", "🥖", "🥨", "🧀", "🥚", "🍳", "🥞", "🥓", "🥩", "🍗", "🍖", "🦴", "🌭", "🍔", "🍟", "🍕", "🥪", "🥙", "🌮", "🌯", "🥗", "🥘", "🥫", "🍝", "🍜", "🍲", "🍛", "🍣", "🍱", "🥟", "🍤", "🍙", "🍚", "🍘", "🍥", "🥠", "🥮", "🍢", "🍡", "🍧", "🍨", "🍦", "🥧", "🧁", "🍰", "🎂", "🍮", "🍭", "🍬", "🍫", "🍿", "🍩", "🍪", "🌰", "🥜", "🍯", "🥛", "🍼", "☕", "🍵", "🥤", "🍶", "🍺", "🍻", "🥂", "🍷", "🥃", "🍸", "🍹", "🍾", "🥄", "🍴", "🍽", "🥣", "🥡", "🥢", "🧂", "⚽", "🏀", "🏈", "⚾", "🥎", "🎾", "🏐", "🏉", "🥏", "🎱", "🏓", "🏸", "🏒", "🏑", "🥍", "🏏", "🥅", "⛳", "🏹", "🎣", "🥊", "🥋", "🎽", "🛹", "🛷", "⛸", "🥌", "🎿", "⛷", "🏂", + "🍏", "🍎", "🍐", "🍊", "🍋", "🍌", "🍉", "🍇", "🍓", "🍈", "🍒", "🍑", "🥭", "🍍", "🥥", "🥝", "🍅", "🍆", "🥑", "🥦", "🥬", "🥒", "🌶", "🌽", "🥕", "🥔", "🍠", "🥐", "🥯", "🍞", "🥖", "🥨", "🧀", "🥚", "🍳", "🥞", "🥓", "🥩", "🍗", "🍖", "🦴", "🌭", "🍔", "🍟", "🍕", "🥪", "🥙", "🌮", "🌯", "🥗", "🥘", "🥫", "🍝", "🍜", "🍲", "🍛", "🍣", "🍱", "🥟", "🍤", "🍙", "🍚", "🍘", "🍥", "🥠", "🥮", "🍢", "🍡", "🍧", "🍨", "🍦", "🥧", "🧁", "🍰", "🎂", "🍮", "🍭", "🍬", "🍫", "🍿", "🍩", "🍪", "🌰", "🥜", "🍯", "🥛", "🍼", "☕", "🍵", "🥤", "🍶", "🍺", "🍻", "🥂", "🍷", "🥃", "🍸", "🍹", "🍾", "🥄", "🍴", "🍽", "🥣", "🥡", "🥢", "🧂", + }, + new String[]{ + "⚽", "🏀", "🏈", "⚾", "🥎", "🎾", "🏐", "🏉", "🥏", "🎱", "🏓", "🏸", "🏒", "🏑", "🥍", "🏏", "🥅", "⛳", "🏹", "🎣", "🥊", "🥋", "🎽", "🛹", "🛷", "⛸", "🥌", "🎿", "⛷", "🏂", "🏋‍♀", "🏋🏻‍♀", "🏋🏼‍♀", "🏋🏽‍♀", "🏋🏾‍♀", "🏋🏿‍♀", "🏋‍♂", "🏋🏻‍♂", "🏋🏼‍♂", "🏋🏽‍♂", "🏋🏾‍♂", "🏋🏿‍♂", "🤼‍♀", "🤼‍♂", @@ -481,10 +579,18 @@ public class EmojiData { "🎭", "🎨", "🎬", "🎤", "🎧", "🎼", "🎹", "🥁", "🎷", "🎺", "🎸", "🎻", "🎲", "♟", "🎯", "🎳", "🎮", "🎰", "🧩", }, new String[]{ - "🚗", "🚕", "🚙", "🚌", "🚎", "🏎", "🚓", "🚑", "🚒", "🚐", "🚚", "🚛", "🚜", "🛴", "🚲", "🛵", "🏍", "🚨", "🚔", "🚍", "🚘", "🚖", "🚡", "🚠", "🚟", "🚃", "🚋", "🚞", "🚝", "🚄", "🚅", "🚈", "🚂", "🚆", "🚇", "🚊", "🚉", "✈", "🛫", "🛬", "🛩", "💺", "🛰", "🚀", "🛸", "🚁", "🛶", "⛵", "🚤", "🛥", "🛳", "⛴", "🚢", "⚓", "⛽", "🚧", "🚦", "🚥", "🚏", "🗺", "🗿", "🗽", "🗼", "🏰", "🏯", "🏟", "🎡", "🎢", "🎠", "⛲", "⛱", "🏖", "🏝", "🏜", "🌋", "⛰", "🏔", "🗻", "🏕", "⛺", "🏠", "🏡", "🏘", "🏚", "🏗", "🏭", "🏢", "🏬", "🏣", "🏤", "🏥", "🏦", "🏨", "🏪", "🏫", "🏩", "💒", "🏛", "⛪", "🕌", "🕍", "🕋", "⛩", "🛤", "🛣", "🗾", "🎑", "🏞", "🌅", "🌄", "🌠", "🎇", "🎆", "🌇", "🌆", "🏙", "🌃", "🌌", "🌉", "🌁", "🏳", "🏴", "🏴‍☠", "🏁", "🚩", "🏳‍🌈", "🇺🇳", "🇦🇫", "🇦🇽", "🇦🇱", "🇩🇿", "🇦🇸", "🇦🇩", "🇦🇴", "🇦🇮", "🇦🇶", "🇦🇬", "🇦🇷", "🇦🇲", "🇦🇼", "🇦🇺", "🇦🇹", "🇦🇿", "🇧🇸", "🇧🇭", "🇧🇩", "🇧🇧", "🇧🇾", "🇧🇪", "🇧🇿", "🇧🇯", "🇧🇲", "🇧🇹", "🇧🇴", "🇧🇦", "🇧🇼", "🇧🇷", "🇮🇴", "🇻🇬", "🇧🇳", "🇧🇬", "🇧🇫", "🇧🇮", "🇰🇭", "🇨🇲", "🇨🇦", "🇮🇨", "🇨🇻", "🇧🇶", "🇰🇾", "🇨🇫", "🇹🇩", "🇨🇱", "🇨🇳", "🇨🇽", "🇨🇨", "🇨🇴", "🇰🇲", "🇨🇬", "🇨🇩", "🇨🇰", "🇨🇷", "🇨🇮", "🇭🇷", "🇨🇺", "🇨🇼", "🇨🇾", "🇨🇿", "🇩🇰", "🇩🇯", "🇩🇲", "🇩🇴", "🇪🇨", "🇪🇬", "🇸🇻", "🇬🇶", "🇪🇷", "🇪🇪", "🇪🇹", "🇪🇺", "🇫🇰", "🇫🇴", "🇫🇯", "🇫🇮", "🇫🇷", "🇬🇫", "🇵🇫", "🇹🇫", "🇬🇦", "🇬🇲", "🇬🇪", "🇩🇪", "🇬🇭", "🇬🇮", "🇬🇷", "🇬🇱", "🇬🇩", "🇬🇵", "🇬🇺", "🇬🇹", "🇬🇬", "🇬🇳", "🇬🇼", "🇬🇾", "🇭🇹", "🇭🇳", "🇭🇰", "🇭🇺", "🇮🇸", "🇮🇳", "🇮🇩", "🇮🇷", "🇮🇶", "🇮🇪", "🇮🇲", "🇮🇱", "🇮🇹", "🇯🇲", "🇯🇵", "🎌", "🇯🇪", "🇯🇴", "🇰🇿", "🇰🇪", "🇰🇮", "🇽🇰", "🇰🇼", "🇰🇬", "🇱🇦", "🇱🇻", "🇱🇧", "🇱🇸", "🇱🇷", "🇱🇾", "🇱🇮", "🇱🇹", "🇱🇺", "🇲🇴", "🇲🇰", "🇲🇬", "🇲🇼", "🇲🇾", "🇲🇻", "🇲🇱", "🇲🇹", "🇲🇭", "🇲🇶", "🇲🇷", "🇲🇺", "🇾🇹", "🇲🇽", "🇫🇲", "🇲🇩", "🇲🇨", "🇲🇳", "🇲🇪", "🇲🇸", "🇲🇦", "🇲🇿", "🇲🇲", "🇳🇦", "🇳🇷", "🇳🇵", "🇳🇱", "🇳🇨", "🇳🇿", "🇳🇮", "🇳🇪", "🇳🇬", "🇳🇺", "🇳🇫", "🇰🇵", "🇲🇵", "🇳🇴", "🇴🇲", "🇵🇰", "🇵🇼", "🇵🇸", "🇵🇦", "🇵🇬", "🇵🇾", "🇵🇪", "🇵🇭", "🇵🇳", "🇵🇱", "🇵🇹", "🇵🇷", "🇶🇦", "🇷🇪", "🇷🇴", "🇷🇺", "🇷🇼", "🇼🇸", "🇸🇲", "🇸🇹", "🇸🇦", "🇸🇳", "🇷🇸", "🇸🇨", "🇸🇱", "🇸🇬", "🇸🇽", "🇸🇰", "🇸🇮", "🇬🇸", "🇸🇧", "🇸🇴", "🇿🇦", "🇰🇷", "🇸🇸", "🇪🇸", "🇱🇰", "🇧🇱", "🇸🇭", "🇰🇳", "🇱🇨", "🇵🇲", "🇻🇨", "🇸🇩", "🇸🇷", "🇸🇿", "🇸🇪", "🇨🇭", "🇸🇾", "🇹🇼", "🇹🇯", "🇹🇿", "🇹🇭", "🇹🇱", "🇹🇬", "🇹🇰", "🇹🇴", "🇹🇹", "🇹🇳", "🇹🇷", "🇹🇲", "🇹🇨", "🇹🇻", "🇻🇮", "🇺🇬", "🇺🇦", "🇦🇪", "🇬🇧", "🏴󠁧󠁢󠁥󠁮󠁧󠁿", "🏴󠁧󠁢󠁳󠁣󠁴󠁿", "🏴󠁧󠁢󠁷󠁬󠁳󠁿", "🇺🇸", "🇺🇾", "🇺🇿", "🇻🇺", "🇻🇦", "🇻🇪", "🇻🇳", "🇼🇫", "🇪🇭", "🇾🇪", "🇿🇲", "🇿🇼", + "🚗", "🚕", "🚙", "🚌", "🚎", "🏎", "🚓", "🚑", "🚒", "🚐", "🚚", "🚛", "🚜", "🛴", "🚲", "🛵", "🏍", "🚨", "🚔", "🚍", "🚘", "🚖", "🚡", "🚠", "🚟", "🚃", "🚋", "🚞", "🚝", "🚄", "🚅", "🚈", "🚂", "🚆", "🚇", "🚊", "🚉", "✈", "🛫", "🛬", "🛩", "💺", "🛰", "🚀", "🛸", "🚁", "🛶", "⛵", "🚤", "🛥", "🛳", "⛴", "🚢", "⚓", "⛽", "🚧", "🚦", "🚥", "🚏", "🗺", "🗿", "🗽", "🗼", "🏰", "🏯", "🏟", "🎡", "🎢", "🎠", "⛲", "⛱", "🏖", "🏝", "🏜", "🌋", "⛰", "🏔", "🗻", "🏕", "⛺", "🏠", "🏡", "🏘", "🏚", "🏗", "🏭", "🏢", "🏬", "🏣", "🏤", "🏥", "🏦", "🏨", "🏪", "🏫", "🏩", "💒", "🏛", "⛪", "🕌", "🕍", "🕋", "⛩", "🛤", "🛣", "🗾", "🎑", "🏞", "🌅", "🌄", "🌠", "🎇", "🎆", "🌇", "🌆", "🏙", "🌃", "🌌", "🌉", "🌁", }, new String[]{ - "💟", "☮", "✝", "☪", "🕉", "☸", "✡", "🔯", "🕎", "☯", "☦", "🛐", "⛎", "♈", "♉", "♊", "♋", "♌", "♍", "♎", "♏", "♐", "♑", "♒", "♓", "🆔", "⚛", "🉑", "☢", "☣", "📴", "📳", "🈶", "🈚", "🈸", "🈺", "🈷", "✴", "🆚", "💮", "🉐", "㊙", "㊗", "🈴", "🈵", "🈹", "🈲", "🅰", "🅱", "🆎", "🆑", "🅾", "🆘", "❌", "⭕", "🛑", "⛔", "📛", "🚫", "💯", "💢", "♨", "🚷", "🚯", "🚳", "🚱", "🔞", "📵", "🚭", "❗", "❕", "❓", "❔", "‼", "⁉", "🔅", "🔆", "〽", "⚠", "🚸", "🔱", "⚜", "🔰", "♻", "✅", "🈯", "💹", "❇", "✳", "❎", "🌐", "💠", "Ⓜ", "🌀", "💤", "🏧", "🚾", "♿", "🅿", "🈳", "🈂", "🛂", "🛃", "🛄", "🛅", "🚹", "🚺", "🚼", "🚻", "🚮", "🎦", "📶", "🈁", "🔣", "ℹ", "🔤", "🔡", "🔠", "🆖", "🆗", "🆙", "🆒", "🆕", "🆓", "0⃣", "1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣", "🔟", "🔢", "#⃣", "*⃣", "⏏", "▶", "⏸", "⏯", "⏹", "⏺", "⏭", "⏮", "⏩", "⏪", "⏫", "⏬", "◀", "🔼", "🔽", "➡", "⬅", "⬆", "⬇", "↗", "↘", "↙", "↖", "↕", "↔", "↪", "↩", "⤴", "⤵", "🔀", "🔁", "🔂", "🔄", "🔃", "🎵", "🎶", "➕", "➖", "➗", "✖", "♾", "💲", "💱", "™", "©", "®", "👁‍🗨", "🔚", "🔙", "🔛", "🔝", "🔜", "〰", "➰", "➿", "✔", "☑", "🔘", "⚪", "⚫", "🔴", "🔵", "🔺", "🔻", "🔸", "🔹", "🔶", "🔷", "🔳", "🔲", "▪", "▫", "◾", "◽", "◼", "◻", "⬛", "⬜", "🔈", "🔇", "🔉", "🔊", "🔔", "🔕", "📣", "📢", "💬", "💭", "🗯", "♠", "♣", "♥", "♦", "🃏", "🎴", "🀄", "🕐", "🕑", "🕒", "🕓", "🕔", "🕕", "🕖", "🕗", "🕘", "🕙", "🕚", "🕛", "🕜", "🕝", "🕞", "🕟", "🕠", "🕡", "🕢", "🕣", "🕤", "🕥", "🕦", "🕧", "⌚", "📱", "📲", "💻", "⌨", "🖥", "🖨", "🖱", "🖲", "🕹", "🗜", "💽", "💾", "💿", "📀", "📼", "📷", "📸", "📹", "🎥", "📽", "🎞", "📞", "☎", "📟", "📠", "📺", "📻", "🎙", "🎚", "🎛", "🧭", "⏱", "⏲", "⏰", "🕰", "⌛", "⏳", "📡", "🔋", "🔌", "💡", "🔦", "🕯", "🧯", "🛢", "💸", "💵", "💴", "💶", "💷", "💰", "💳", "💎", "⚖", "🧰", "🔧", "🔨", "⚒", "🛠", "⛏", "🔩", "⚙", "🧱", "⛓", "🧲", "🔫", "💣", "🧨", "🔪", "🗡", "⚔", "🛡", "🚬", "⚰", "⚱", "🏺", "🔮", "📿", "🧿", "💈", "⚗", "🔭", "🔬", "🕳", "💊", "💉", "🧬", "🦠", "🧫", "🧪", "🌡", "🧹", "🧺", "🧻", "🚽", "🚰", "🚿", "🛁", "🛀", "🛀🏻", "🛀🏼", "🛀🏽", "🛀🏾", "🛀🏿", "🧼", "🧽", "🧴", "🛎", "🔑", "🗝", "🚪", "🛋", "🛏", "🛌", "🧸", "🖼", "🛍", "🛒", "🎁", "🎈", "🎏", "🎀", "🎊", "🎉", "🎎", "🏮", "🎐", "🧧", "✉", "📩", "📨", "📧", "💌", "📥", "📤", "📦", "🏷", "📪", "📫", "📬", "📭", "📮", "📯", "📜", "📃", "📄", "📑", "🧾", "📊", "📈", "📉", "🗒", "🗓", "📆", "📅", "🗑", "📇", "🗃", "🗳", "🗄", "📋", "📁", "📂", "🗂", "🗞", "📰", "📓", "📔", "📒", "📕", "📗", "📘", "📙", "📚", "📖", "🔖", "🧷", "🔗", "📎", "🖇", "📐", "📏", "🧮", "📌", "📍", "✂", "🖊", "🖋", "✒", "🖌", "🖍", "📝", "✏", "🔍", "🔎", "🔏", "🔐", "🔒", "🔓" + "⌚", "📱", "📲", "💻", "⌨", "🖥", "🖨", "🖱", "🖲", "🕹", "🗜", "💽", "💾", "💿", "📀", "📼", "📷", "📸", "📹", "🎥", "📽", "🎞", "📞", "☎", "📟", "📠", "📺", "📻", "🎙", "🎚", "🎛", "🧭", "⏱", "⏲", "⏰", "🕰", "⌛", "⏳", "📡", "🔋", "🔌", "💡", "🔦", "🕯", "🧯", "🛢", "💸", "💵", "💴", "💶", "💷", "💰", "💳", "💎", "⚖", "🧰", "🔧", "🔨", "⚒", "🛠", "⛏", "🔩", "⚙", "🧱", "⛓", "🧲", "🔫", "💣", "🧨", "🔪", "🗡", "⚔", "🛡", "🚬", "⚰", "⚱", "🏺", "🔮", "📿", "🧿", "💈", "⚗", "🔭", "🔬", "🕳", "💊", "💉", "🧬", "🦠", "🧫", "🧪", "🌡", "🧹", "🧺", "🧻", "🚽", "🚰", "🚿", "🛁", + "🛀", "🛀🏻", "🛀🏼", "🛀🏽", "🛀🏾", "🛀🏿", + "🧼", "🧽", "🧴", "🛎", "🔑", "🗝", "🚪", "🛋", "🛏", "🛌", "🧸", "🖼", "🛍", "🛒", "🎁", "🎈", "🎏", "🎀", "🎊", "🎉", "🎎", "🏮", "🎐", "🧧", "✉", "📩", "📨", "📧", "💌", "📥", "📤", "📦", "🏷", "📪", "📫", "📬", "📭", "📮", "📯", "📜", "📃", "📄", "📑", "🧾", "📊", "📈", "📉", "🗒", "🗓", "📆", "📅", "🗑", "📇", "🗃", "🗳", "🗄", "📋", "📁", "📂", "🗂", "🗞", "📰", "📓", "📔", "📒", "📕", "📗", "📘", "📙", "📚", "📖", "🔖", "🧷", "🔗", "📎", "🖇", "📐", "📏", "🧮", "📌", "📍", "✂", "🖊", "🖋", "✒", "🖌", "🖍", "📝", "✏", "🔍", "🔎", "🔏", "🔐", "🔒", "🔓" + }, + new String[]{ + "❤", "🧡", "💛", "💚", "💙", "💜", "🖤", "💔", "❣", "💕", "💞", "💓", "💗", "💖", "💘", "💝", "💟", "☮", "✝", "☪", "🕉", "☸", "✡", "🔯", "🕎", "☯", "☦", "🛐", "⛎", "♈", "♉", "♊", "♋", "♌", "♍", "♎", "♏", "♐", "♑", "♒", "♓", "🆔", "⚛", "🉑", "☢", "☣", "📴", "📳", "🈶", "🈚", "🈸", "🈺", "🈷", "✴", "🆚", "💮", "🉐", "㊙", "㊗", "🈴", "🈵", "🈹", "🈲", "🅰", "🅱", "🆎", "🆑", "🅾", "🆘", "❌", "⭕", "🛑", "⛔", "📛", "🚫", "💯", "💢", "♨", "🚷", "🚯", "🚳", "🚱", "🔞", "📵", "🚭", "❗", "❕", "❓", "❔", "‼", "⁉", "🔅", "🔆", "〽", "⚠", "🚸", "🔱", "⚜", "🔰", "♻", "✅", "🈯", "💹", "❇", "✳", "❎", "🌐", "💠", "Ⓜ", "🌀", "💤", "🏧", "🚾", "♿", "🅿", "🈳", "🈂", "🛂", "🛃", "🛄", "🛅", "🚹", "🚺", "🚼", "🚻", "🚮", "🎦", "📶", "🈁", "🔣", "ℹ", "🔤", "🔡", "🔠", "🆖", "🆗", "🆙", "🆒", "🆕", "🆓", "0⃣", "1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣", "🔟", "🔢", "#⃣", "*⃣", "⏏", "▶", "⏸", "⏯", "⏹", "⏺", "⏭", "⏮", "⏩", "⏪", "⏫", "⏬", "◀", "🔼", "🔽", "➡", "⬅", "⬆", "⬇", "↗", "↘", "↙", "↖", "↕", "↔", "↪", "↩", "⤴", "⤵", "🔀", "🔁", "🔂", "🔄", "🔃", "🎵", "🎶", "➕", "➖", "➗", "✖", "♾", "💲", "💱", "™", "©", "®", "👁‍🗨", "🔚", "🔙", "🔛", "🔝", "🔜", "〰", "➰", "➿", "✔", "☑", "🔘", "⚪", "⚫", "🔴", "🔵", "🔺", "🔻", "🔸", "🔹", "🔶", "🔷", "🔳", "🔲", "▪", "▫", "◾", "◽", "◼", "◻", "⬛", "⬜", "🔈", "🔇", "🔉", "🔊", "🔔", "🔕", "📣", "📢", "💬", "💭", "🗯", "♠", "♣", "♥", "♦", "🃏", "🎴", "🀄", "🕐", "🕑", "🕒", "🕓", "🕔", "🕕", "🕖", "🕗", "🕘", "🕙", "🕚", "🕛", "🕜", "🕝", "🕞", "🕟", "🕠", "🕡", "🕢", "🕣", "🕤", "🕥", "🕦", "🕧", + }, + new String[]{ + "🏳", "🏴", "🏴‍☠", "🏁", "🚩", "🏳‍🌈", "🇺🇳", "🇦🇫", "🇦🇽", "🇦🇱", "🇩🇿", "🇦🇸", "🇦🇩", "🇦🇴", "🇦🇮", "🇦🇶", "🇦🇬", "🇦🇷", "🇦🇲", "🇦🇼", "🇦🇺", "🇦🇹", "🇦🇿", "🇧🇸", "🇧🇭", "🇧🇩", "🇧🇧", "🇧🇾", "🇧🇪", "🇧🇿", "🇧🇯", "🇧🇲", "🇧🇹", "🇧🇴", "🇧🇦", "🇧🇼", "🇧🇷", "🇮🇴", "🇻🇬", "🇧🇳", "🇧🇬", "🇧🇫", "🇧🇮", "🇰🇭", "🇨🇲", "🇨🇦", "🇮🇨", "🇨🇻", "🇧🇶", "🇰🇾", "🇨🇫", "🇹🇩", "🇨🇱", "🇨🇳", "🇨🇽", "🇨🇨", "🇨🇴", "🇰🇲", "🇨🇬", "🇨🇩", "🇨🇰", "🇨🇷", "🇨🇮", "🇭🇷", "🇨🇺", "🇨🇼", "🇨🇾", "🇨🇿", "🇩🇰", "🇩🇯", "🇩🇲", "🇩🇴", "🇪🇨", "🇪🇬", "🇸🇻", "🇬🇶", "🇪🇷", "🇪🇪", "🇪🇹", "🇪🇺", "🇫🇰", "🇫🇴", "🇫🇯", "🇫🇮", "🇫🇷", "🇬🇫", "🇵🇫", "🇹🇫", "🇬🇦", "🇬🇲", "🇬🇪", "🇩🇪", "🇬🇭", "🇬🇮", "🇬🇷", "🇬🇱", "🇬🇩", "🇬🇵", "🇬🇺", "🇬🇹", "🇬🇬", "🇬🇳", "🇬🇼", "🇬🇾", "🇭🇹", "🇭🇳", "🇭🇰", "🇭🇺", "🇮🇸", "🇮🇳", "🇮🇩", "🇮🇷", "🇮🇶", "🇮🇪", "🇮🇲", "🇮🇱", "🇮🇹", "🇯🇲", "🇯🇵", "🎌", "🇯🇪", "🇯🇴", "🇰🇿", "🇰🇪", "🇰🇮", "🇽🇰", "🇰🇼", "🇰🇬", "🇱🇦", "🇱🇻", "🇱🇧", "🇱🇸", "🇱🇷", "🇱🇾", "🇱🇮", "🇱🇹", "🇱🇺", "🇲🇴", "🇲🇰", "🇲🇬", "🇲🇼", "🇲🇾", "🇲🇻", "🇲🇱", "🇲🇹", "🇲🇭", "🇲🇶", "🇲🇷", "🇲🇺", "🇾🇹", "🇲🇽", "🇫🇲", "🇲🇩", "🇲🇨", "🇲🇳", "🇲🇪", "🇲🇸", "🇲🇦", "🇲🇿", "🇲🇲", "🇳🇦", "🇳🇷", "🇳🇵", "🇳🇱", "🇳🇨", "🇳🇿", "🇳🇮", "🇳🇪", "🇳🇬", "🇳🇺", "🇳🇫", "🇰🇵", "🇲🇵", "🇳🇴", "🇴🇲", "🇵🇰", "🇵🇼", "🇵🇸", "🇵🇦", "🇵🇬", "🇵🇾", "🇵🇪", "🇵🇭", "🇵🇳", "🇵🇱", "🇵🇹", "🇵🇷", "🇶🇦", "🇷🇪", "🇷🇴", "🇷🇺", "🇷🇼", "🇼🇸", "🇸🇲", "🇸🇹", "🇸🇦", "🇸🇳", "🇷🇸", "🇸🇨", "🇸🇱", "🇸🇬", "🇸🇽", "🇸🇰", "🇸🇮", "🇬🇸", "🇸🇧", "🇸🇴", "🇿🇦", "🇰🇷", "🇸🇸", "🇪🇸", "🇱🇰", "🇧🇱", "🇸🇭", "🇰🇳", "🇱🇨", "🇵🇲", "🇻🇨", "🇸🇩", "🇸🇷", "🇸🇿", "🇸🇪", "🇨🇭", "🇸🇾", "🇹🇼", "🇹🇯", "🇹🇿", "🇹🇭", "🇹🇱", "🇹🇬", "🇹🇰", "🇹🇴", "🇹🇹", "🇹🇳", "🇹🇷", "🇹🇲", "🇹🇨", "🇹🇻", "🇻🇮", "🇺🇬", "🇺🇦", "🇦🇪", "🇬🇧", "🏴󠁧󠁢󠁥󠁮󠁧󠁿", "🏴󠁧󠁢󠁳󠁣󠁴󠁿", "🏴󠁧󠁢󠁷󠁬󠁳󠁿", "🇺🇸", "🇺🇾", "🇺🇿", "🇻🇺", "🇻🇦", "🇻🇪", "🇻🇳", "🇼🇫", "🇪🇭", "🇾🇪", "🇿🇲", "🇿🇼", } }; @@ -506,7 +612,10 @@ public class EmojiData { for (int a = 0; a < aliasNew.length; a++) { emojiAliasMap.put(aliasOld[a], aliasNew[a]); } - dataColored[1] = data[1]; - dataColored[3] = data[3]; + for (int a = 0; a < dataColored.length; a++) { + if (dataColored[a] == null) { + dataColored[a] = data[a]; + } + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/EmojiSuggestion.java b/TMessagesProj/src/main/java/org/telegram/messenger/EmojiSuggestion.java deleted file mode 100644 index a5f33c5f7..000000000 --- a/TMessagesProj/src/main/java/org/telegram/messenger/EmojiSuggestion.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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; - -public class EmojiSuggestion { - - public EmojiSuggestion(String arg1, String arg2) { - emoji = arg1; - label = arg2; - } - - public String emoji; - public String label; -} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index 7c27b2fec..3f35122a3 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -102,7 +102,7 @@ public class FileLoadOperation { private boolean started; private int datacenterId; private int initialDatacenterId; - private TLRPC.InputFileLocation location; + protected TLRPC.InputFileLocation location; private TLRPC.InputWebFileLocation webLocation; private WebFile webFile; private volatile int state = stateIdle; @@ -165,30 +165,63 @@ public class FileLoadOperation { void didChangedLoadProgress(FileLoadOperation operation, float progress); } - public FileLoadOperation(TLRPC.FileLocation photoLocation, Object parent, String extension, int size) { + public FileLoadOperation(ImageLocation imageLocation, Object parent, String extension, int size) { parentObject = parent; - if (photoLocation instanceof TLRPC.TL_fileEncryptedLocation) { + if (imageLocation.isEncrypted()) { location = new TLRPC.TL_inputEncryptedFileLocation(); - location.id = photoLocation.volume_id; - location.volume_id = photoLocation.volume_id; - location.access_hash = photoLocation.secret; - location.local_id = photoLocation.local_id; + location.id = imageLocation.location.volume_id; + location.volume_id = imageLocation.location.volume_id; + location.local_id = imageLocation.location.local_id; + location.access_hash = imageLocation.access_hash; iv = new byte[32]; - System.arraycopy(photoLocation.iv, 0, iv, 0, iv.length); - key = photoLocation.key; - initialDatacenterId = datacenterId = photoLocation.dc_id; - } else if (photoLocation instanceof TLRPC.TL_fileLocation) { - location = new TLRPC.TL_inputFileLocation(); - location.volume_id = photoLocation.volume_id; - location.secret = photoLocation.secret; - location.local_id = photoLocation.local_id; - location.file_reference = photoLocation.file_reference; + System.arraycopy(imageLocation.iv, 0, iv, 0, iv.length); + key = imageLocation.key; + } else if (imageLocation.photoPeer != null) { + location = new TLRPC.TL_inputPeerPhotoFileLocation(); + location.id = imageLocation.location.volume_id; + location.volume_id = imageLocation.location.volume_id; + location.local_id = imageLocation.location.local_id; + location.big = imageLocation.photoPeerBig; + location.peer = imageLocation.photoPeer; + } else if (imageLocation.stickerSet != null) { + location = new TLRPC.TL_inputStickerSetThumb(); + location.id = imageLocation.location.volume_id; + location.volume_id = imageLocation.location.volume_id; + location.local_id = imageLocation.location.local_id; + location.stickerset = imageLocation.stickerSet; + } else if (imageLocation.thumbSize != null) { + if (imageLocation.photoId != 0) { + location = new TLRPC.TL_inputPhotoFileLocation(); + location.id = imageLocation.photoId; + location.volume_id = imageLocation.location.volume_id; + location.local_id = imageLocation.location.local_id; + location.access_hash = imageLocation.access_hash; + location.file_reference = imageLocation.file_reference; + location.thumb_size = imageLocation.thumbSize; + } else { + location = new TLRPC.TL_inputDocumentFileLocation(); + location.id = imageLocation.documentId; + location.volume_id = imageLocation.location.volume_id; + location.local_id = imageLocation.location.local_id; + location.access_hash = imageLocation.access_hash; + location.file_reference = imageLocation.file_reference; + location.thumb_size = imageLocation.thumbSize; + } + if (location.file_reference == null) { + location.file_reference = new byte[0]; + } + } else { + location = new TLRPC.TL_inputFileLocation(); + location.volume_id = imageLocation.location.volume_id; + location.local_id = imageLocation.location.local_id; + location.secret = imageLocation.access_hash; + location.file_reference = imageLocation.file_reference; if (location.file_reference == null) { location.file_reference = new byte[0]; } - initialDatacenterId = datacenterId = photoLocation.dc_id; allowDisordererFileSave = true; } + initialDatacenterId = datacenterId = imageLocation.dc_id; currentType = ConnectionsManager.FileTypePhoto; totalBytesCount = size; ext = extension != null ? extension : "jpg"; @@ -241,6 +274,7 @@ public class FileLoadOperation { location.id = documentLocation.id; location.access_hash = documentLocation.access_hash; location.file_reference = documentLocation.file_reference; + location.thumb_size = ""; if (location.file_reference == null) { location.file_reference = new byte[0]; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index 9b7187ec7..363f4ccde 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -453,45 +453,35 @@ public class FileLoader { } } - public void loadFile(TLRPC.PhotoSize photo, String ext, int cacheType) { - if (photo == null) { + public void loadFile(ImageLocation imageLocation, Object parentObject, String ext, int priority, int cacheType) { + if (imageLocation == null) { return; } - if (cacheType == 0 && photo != null && (photo.size == 0 || photo.location.key != null)) { + if (cacheType == 0 && (imageLocation.isEncrypted() || imageLocation.photoSize != null && imageLocation.getSize() == 0)) { cacheType = 1; } - loadFile(null, null, null, photo.location, null, ext, photo.size, 0, cacheType); + loadFile(imageLocation.document, imageLocation.secureDocument, imageLocation.webFile, imageLocation.location, imageLocation, parentObject, ext, imageLocation.getSize(), priority, cacheType); } public void loadFile(SecureDocument secureDocument, int priority) { if (secureDocument == null) { return; } - loadFile(null, secureDocument, null, null, null, null, 0, priority, 1); + loadFile(null, secureDocument, null, null, null, null, null, 0, priority, 1); } public void loadFile(TLRPC.Document document, Object parentObject, int priority, int cacheType) { if (document == null) { return; } - if (cacheType == 0 && document != null && document.key != null) { + if (cacheType == 0 && document.key != null) { cacheType = 1; } - loadFile(document, null, null, null, parentObject, null, 0, priority, cacheType); + loadFile(document, null, null, null, null, parentObject, null, 0, priority, cacheType); } public void loadFile(WebFile document, int priority, int cacheType) { - loadFile(null, null, document, null, null, null, 0, priority, cacheType); - } - - public void loadFile(TLRPC.FileLocation location, Object parentObject, String ext, int size, int priority, int cacheType) { - if (location == null) { - return; - } - if (cacheType == 0 && (size == 0 || location != null && location.key != null)) { - cacheType = 1; - } - loadFile(null, null, null, location, parentObject, ext, size, priority, cacheType); + loadFile(null, null, document, null, null, null, null, 0, priority, cacheType); } private void pauseCurrentFileLoadOperations(FileLoadOperation newOperation) { @@ -512,7 +502,7 @@ public class FileLoader { } } - private FileLoadOperation loadFileInternal(final TLRPC.Document document, final SecureDocument secureDocument, final WebFile webDocument, final TLRPC.FileLocation location, Object parentObject, final String locationExt, final int locationSize, final int priority, final FileLoadOperationStream stream, final int streamOffset, final int cacheType) { + private FileLoadOperation loadFileInternal(final TLRPC.Document document, final SecureDocument secureDocument, final WebFile webDocument, TLRPC.TL_fileLocationToBeDeprecated location, final ImageLocation imageLocation, Object parentObject, final String locationExt, final int locationSize, final int priority, final FileLoadOperationStream stream, final int streamOffset, final int cacheType) { String fileName = null; if (location != null) { fileName = getAttachFileName(location, locationExt); @@ -601,7 +591,7 @@ public class FileLoader { operation = new FileLoadOperation(secureDocument); type = MEDIA_DIR_DOCUMENT; } else if (location != null) { - operation = new FileLoadOperation(location, parentObject, locationExt, locationSize); + operation = new FileLoadOperation(imageLocation, parentObject, locationExt, locationSize); type = MEDIA_DIR_IMAGE; } else if (document != null) { operation = new FileLoadOperation(document, parentObject); @@ -698,7 +688,7 @@ public class FileLoader { addOperationToQueue(operation, photoLoadOperationQueue); } } else { - int maxCount = priority > 0 ? 3 : 1; + int maxCount = priority > 0 ? 4 : 1; int count = currentLoadOperationsCount.get(datacenterId); if (stream != null || count < maxCount) { if (operation.start(stream, streamOffset)) { @@ -732,7 +722,7 @@ public class FileLoader { } } - private void loadFile(final TLRPC.Document document, final SecureDocument secureDocument, final WebFile webDocument, final TLRPC.FileLocation location, final Object parentObject, final String locationExt, final int locationSize, final int priority, final int cacheType) { + private void loadFile(final TLRPC.Document document, final SecureDocument secureDocument, final WebFile webDocument, TLRPC.TL_fileLocationToBeDeprecated location, final ImageLocation imageLocation, final Object parentObject, final String locationExt, final int locationSize, final int priority, final int cacheType) { String fileName; if (location != null) { fileName = getAttachFileName(location, locationExt); @@ -746,14 +736,14 @@ public class FileLoader { if (cacheType != 10 && !TextUtils.isEmpty(fileName) && !fileName.contains("" + Integer.MIN_VALUE)) { loadOperationPathsUI.put(fileName, true); } - fileLoaderQueue.postRunnable(() -> loadFileInternal(document, secureDocument, webDocument, location, parentObject, locationExt, locationSize, priority, null, 0, cacheType)); + fileLoaderQueue.postRunnable(() -> loadFileInternal(document, secureDocument, webDocument, location, imageLocation, parentObject, locationExt, locationSize, priority, null, 0, cacheType)); } protected FileLoadOperation loadStreamFile(final FileLoadOperationStream stream, final TLRPC.Document document, final Object parentObject, final int offset) { final CountDownLatch semaphore = new CountDownLatch(1); final FileLoadOperation[] result = new FileLoadOperation[1]; fileLoaderQueue.postRunnable(() -> { - result[0] = loadFileInternal(document, null, null, null, parentObject, null, 0, 1, stream, offset, 0); + result[0] = loadFileInternal(document, null, null, null, null, parentObject, null, 0, 1, stream, offset, 0); semaphore.countDown(); }); try { @@ -1166,9 +1156,6 @@ public class FileLoader { } TLRPC.FileLocation location = (TLRPC.FileLocation) attach; return location.volume_id + "_" + location.local_id + "." + (ext != null ? ext : "jpg"); - } else if (attach instanceof TLRPC.Photo) { - TLRPC.FileLocation location = (TLRPC.FileLocation) attach; - return location.volume_id + "_" + location.local_id + "." + (ext != null ? ext : "jpg"); } return ""; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java index f2d507a2e..6ef1f9a71 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java @@ -106,7 +106,7 @@ public class FileRefController { } else if (req.media instanceof TLRPC.TL_inputMediaPhoto) { TLRPC.TL_inputMediaPhoto mediaPhoto = (TLRPC.TL_inputMediaPhoto) req.media; locationKey = "photo_" + mediaPhoto.id.id; - location = new TLRPC.TL_inputSecureFileLocation(); + location = new TLRPC.TL_inputPhotoFileLocation(); location.id = mediaPhoto.id.id; } else { sendErrorToObject(args, 0); @@ -135,7 +135,7 @@ public class FileRefController { } else if (req.media instanceof TLRPC.TL_inputMediaPhoto) { TLRPC.TL_inputMediaPhoto mediaPhoto = (TLRPC.TL_inputMediaPhoto) req.media; locationKey = "photo_" + mediaPhoto.id.id; - location = new TLRPC.TL_inputSecureFileLocation(); + location = new TLRPC.TL_inputPhotoFileLocation(); location.id = mediaPhoto.id.id; } else { sendErrorToObject(args, 0); @@ -151,7 +151,7 @@ public class FileRefController { } else if (req.media instanceof TLRPC.TL_inputMediaPhoto) { TLRPC.TL_inputMediaPhoto mediaPhoto = (TLRPC.TL_inputMediaPhoto) req.media; locationKey = "photo_" + mediaPhoto.id.id; - location = new TLRPC.TL_inputSecureFileLocation(); + location = new TLRPC.TL_inputPhotoFileLocation(); location.id = mediaPhoto.id.id; } else { sendErrorToObject(args, 0); @@ -182,7 +182,7 @@ public class FileRefController { } else if (req.media instanceof TLRPC.TL_inputStickeredMediaPhoto) { TLRPC.TL_inputStickeredMediaPhoto mediaPhoto = (TLRPC.TL_inputStickeredMediaPhoto) req.media; locationKey = "photo_" + mediaPhoto.id.id; - location = new TLRPC.TL_inputSecureFileLocation(); + location = new TLRPC.TL_inputPhotoFileLocation(); location.id = mediaPhoto.id.id; } else { sendErrorToObject(args, 0); @@ -194,6 +194,9 @@ public class FileRefController { } else if (args[0] instanceof TLRPC.TL_inputDocumentFileLocation) { location = (TLRPC.TL_inputDocumentFileLocation) args[0]; locationKey = "file_" + location.id; + } else if (args[0] instanceof TLRPC.TL_inputPhotoFileLocation) { + location = (TLRPC.TL_inputPhotoFileLocation) args[0]; + locationKey = "photo_" + location.id; } else { sendErrorToObject(args, 0); return; @@ -206,7 +209,6 @@ public class FileRefController { } String parentKey = getKeyForParentObject(parentObject); - if (parentKey == null) { sendErrorToObject(args, 0); return; @@ -308,7 +310,7 @@ public class FileRefController { if ("wallpaper".equals(string)) { TLRPC.TL_account_getWallPapers req = new TLRPC.TL_account_getWallPapers(); ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true)); - } else if ("gif".equals(string)) { + } else if (string.startsWith("gif")) { TLRPC.TL_messages_getSavedGifs req = new TLRPC.TL_messages_getSavedGifs(); ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true)); } else if ("recent".equals(string)) { @@ -385,7 +387,7 @@ public class FileRefController { } @SuppressWarnings("unchecked") - private void onUpdateObjectReference(Requester requester, byte[] file_reference) { + private void onUpdateObjectReference(Requester requester, byte[] file_reference, TLRPC.InputFileLocation locationReplacement) { if (BuildVars.DEBUG_VERSION) { FileLog.d("fileref updated for " + requester.args[0] + " " + requester.locationKey); } @@ -471,9 +473,12 @@ public class FileRefController { } ConnectionsManager.getInstance(currentAccount).sendRequest(req, (RequestDelegate) requester.args[1]); } else if (requester.args[1] instanceof FileLoadOperation) { - requester.location.file_reference = file_reference; - FileLoadOperation fileLoadOperation = (FileLoadOperation) requester.args[1]; + if (locationReplacement != null) { + fileLoadOperation.location = locationReplacement; + } else { + requester.location.file_reference = file_reference; + } fileLoadOperation.requestingReference = false; fileLoadOperation.startDownloadRequest(); } @@ -543,6 +548,8 @@ public class FileRefController { } } byte result[] = null; + TLRPC.InputFileLocation[] locationReplacement = null; + boolean needReplacement[] = null; ArrayList arrayList = locationRequester.get(locationKey); if (arrayList == null) { return found; @@ -552,6 +559,10 @@ public class FileRefController { if (requester.completed) { continue; } + if (requester.location instanceof TLRPC.TL_inputFileLocation) { + locationReplacement = new TLRPC.InputFileLocation[1]; + needReplacement = new boolean[1]; + } requester.completed = true; if (response instanceof TLRPC.messages_Messages) { TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; @@ -560,19 +571,19 @@ public class FileRefController { TLRPC.Message message = res.messages.get(i); if (message.media != null) { if (message.media.document != null) { - result = getFileReference(message.media.document, requester.location); + result = getFileReference(message.media.document, requester.location, needReplacement, locationReplacement); } else if (message.media.game != null) { - result = getFileReference(message.media.game.document, requester.location); + result = getFileReference(message.media.game.document, requester.location, needReplacement, locationReplacement); if (result == null) { - result = getFileReference(message.media.game.photo, requester.location); + result = getFileReference(message.media.game.photo, requester.location, needReplacement, locationReplacement); } } else if (message.media.photo != null) { - result = getFileReference(message.media.photo, requester.location); + result = getFileReference(message.media.photo, requester.location, needReplacement, locationReplacement); } else if (message.media.webpage != null) { - result = getFileReference(message.media.webpage, requester.location); + result = getFileReference(message.media.webpage, requester.location, needReplacement, locationReplacement); } } else if (message.action instanceof TLRPC.TL_messageActionChatEditPhoto) { - result = getFileReference(message.action.photo, requester.location); + result = getFileReference(message.action.photo, requester.location, needReplacement, locationReplacement); } if (result != null) { if (cache) { @@ -587,18 +598,24 @@ public class FileRefController { } } } - MessagesStorage.getInstance(currentAccount).replaceMessageIfExists(message); + MessagesStorage.getInstance(currentAccount).replaceMessageIfExists(message, currentAccount, res.users, res.chats, false); } break; } } + if (result == null) { + MessagesStorage.getInstance(currentAccount).replaceMessageIfExists(res.messages.get(0), currentAccount, res.users, res.chats,true); + if (BuildVars.DEBUG_VERSION) { + FileLog.d("file ref not found in messages, replacing message"); + } + } } } else if (response instanceof TLRPC.WebPage) { - result = getFileReference((TLRPC.WebPage) response, requester.location); + result = getFileReference((TLRPC.WebPage) response, requester.location, needReplacement, locationReplacement); } else if (response instanceof TLRPC.TL_account_wallPapers) { TLRPC.TL_account_wallPapers accountWallPapers = (TLRPC.TL_account_wallPapers) response; for (int i = 0, size10 = accountWallPapers.wallpapers.size(); i < size10; i++) { - result = getFileReference(((TLRPC.TL_wallPaper) accountWallPapers.wallpapers.get(i)).document, requester.location); + result = getFileReference(((TLRPC.TL_wallPaper) accountWallPapers.wallpapers.get(i)).document, requester.location, needReplacement, locationReplacement); if (result != null) { break; } @@ -608,7 +625,7 @@ public class FileRefController { } } else if (response instanceof TLRPC.TL_wallPaper) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) response; - result = getFileReference(wallPaper.document, requester.location); + result = getFileReference(wallPaper.document, requester.location, needReplacement, locationReplacement); if (result != null && cache) { ArrayList wallpapers = new ArrayList<>(); wallpapers.add(wallPaper); @@ -621,7 +638,7 @@ public class FileRefController { Object object = vector.objects.get(i); if (object instanceof TLRPC.User) { TLRPC.User user = (TLRPC.User) object; - result = getFileReference(user.photo, requester.location); + result = getFileReference(user, requester.location, needReplacement, locationReplacement); if (cache && result != null) { ArrayList arrayList1 = new ArrayList<>(); arrayList1.add(user); @@ -630,7 +647,7 @@ public class FileRefController { } } else if (object instanceof TLRPC.Chat) { TLRPC.Chat chat = (TLRPC.Chat) object; - result = getFileReference(chat.photo, requester.location); + result = getFileReference(chat, requester.location, needReplacement, locationReplacement); if (cache && result != null) { ArrayList arrayList1 = new ArrayList<>(); arrayList1.add(chat); @@ -648,7 +665,7 @@ public class FileRefController { if (!res.chats.isEmpty()) { for (int i = 0, size10 = res.chats.size(); i < size10; i++) { TLRPC.Chat chat = res.chats.get(i); - result = getFileReference(chat.photo, requester.location); + result = getFileReference(chat, requester.location, needReplacement, locationReplacement); if (result != null) { if (cache) { ArrayList arrayList1 = new ArrayList<>(); @@ -663,20 +680,22 @@ public class FileRefController { } else if (response instanceof TLRPC.TL_messages_savedGifs) { TLRPC.TL_messages_savedGifs savedGifs = (TLRPC.TL_messages_savedGifs) response; for (int b = 0, size2 = savedGifs.gifs.size(); b < size2; b++) { - result = getFileReference(savedGifs.gifs.get(b), requester.location); + result = getFileReference(savedGifs.gifs.get(b), requester.location, needReplacement, locationReplacement); if (result != null) { break; } } if (cache) { - DataQuery.getInstance(currentAccount).processLoadedRecentDocuments(DataQuery.TYPE_IMAGE, savedGifs.gifs, true, 0); + DataQuery.getInstance(currentAccount).processLoadedRecentDocuments(DataQuery.TYPE_IMAGE, savedGifs.gifs, true, 0, true); } } else if (response instanceof TLRPC.TL_messages_stickerSet) { TLRPC.TL_messages_stickerSet stickerSet = (TLRPC.TL_messages_stickerSet) response; - for (int b = 0, size2 = stickerSet.documents.size(); b < size2; b++) { - result = getFileReference(stickerSet.documents.get(b), requester.location); - if (result != null) { - break; + if (result == null) { + for (int b = 0, size2 = stickerSet.documents.size(); b < size2; b++) { + result = getFileReference(stickerSet.documents.get(b), requester.location, needReplacement, locationReplacement); + if (result != null) { + break; + } } } if (cache) { @@ -685,36 +704,36 @@ public class FileRefController { } else if (response instanceof TLRPC.TL_messages_recentStickers) { TLRPC.TL_messages_recentStickers recentStickers = (TLRPC.TL_messages_recentStickers) response; for (int b = 0, size2 = recentStickers.stickers.size(); b < size2; b++) { - result = getFileReference(recentStickers.stickers.get(b), requester.location); + result = getFileReference(recentStickers.stickers.get(b), requester.location, needReplacement, locationReplacement); if (result != null) { break; } } if (cache) { - DataQuery.getInstance(currentAccount).processLoadedRecentDocuments(DataQuery.TYPE_IMAGE, recentStickers.stickers, false, 0); + DataQuery.getInstance(currentAccount).processLoadedRecentDocuments(DataQuery.TYPE_IMAGE, recentStickers.stickers, false, 0, true); } } else if (response instanceof TLRPC.TL_messages_favedStickers) { TLRPC.TL_messages_favedStickers favedStickers = (TLRPC.TL_messages_favedStickers) response; for (int b = 0, size2 = favedStickers.stickers.size(); b < size2; b++) { - result = getFileReference(favedStickers.stickers.get(b), requester.location); + result = getFileReference(favedStickers.stickers.get(b), requester.location, needReplacement, locationReplacement); if (result != null) { break; } } if (cache) { - DataQuery.getInstance(currentAccount).processLoadedRecentDocuments(DataQuery.TYPE_FAVE, favedStickers.stickers, false, 0); + DataQuery.getInstance(currentAccount).processLoadedRecentDocuments(DataQuery.TYPE_FAVE, favedStickers.stickers, false, 0, true); } } else if (response instanceof TLRPC.photos_Photos) { TLRPC.photos_Photos res = (TLRPC.photos_Photos) response; for (int b = 0, size = res.photos.size(); b < size; b++) { - result = getFileReference(res.photos.get(b), requester.location); + result = getFileReference(res.photos.get(b), requester.location, needReplacement, locationReplacement); if (result != null) { break; } } } if (result != null) { - onUpdateObjectReference(requester, result); + onUpdateObjectReference(requester, result, locationReplacement != null ? locationReplacement[0] : null); found = true; } else { sendErrorToObject(requester.args, 1); @@ -770,7 +789,7 @@ public class FileRefController { cachedResult.lastQueryTime = SystemClock.uptimeMillis(); } - private byte[] getFileReference(TLRPC.Document document, TLRPC.InputFileLocation location) { + private byte[] getFileReference(TLRPC.Document document, TLRPC.InputFileLocation location, boolean[] needReplacement, TLRPC.InputFileLocation[] replacement) { if (document == null || location == null) { return null; } @@ -780,7 +799,18 @@ public class FileRefController { } } else { for (int a = 0, size = document.thumbs.size(); a < size; a++) { - byte[] result = getFileReference(document.thumbs.get(a), location); + TLRPC.PhotoSize photoSize = document.thumbs.get(a); + byte[] result = getFileReference(photoSize, location, needReplacement); + if (needReplacement != null && needReplacement[0]) { + replacement[0] = new TLRPC.TL_inputDocumentFileLocation(); + replacement[0].id = document.id; + replacement[0].volume_id = location.volume_id; + replacement[0].local_id = location.local_id; + replacement[0].access_hash = document.access_hash; + replacement[0].file_reference = document.file_reference; + replacement[0].thumb_size = photoSize.type; + return document.file_reference; + } if (result != null) { return result; } @@ -789,37 +819,91 @@ public class FileRefController { return null; } - private byte[] getFileReference(TLRPC.UserProfilePhoto photo, TLRPC.InputFileLocation location) { - if (photo == null || !(location instanceof TLRPC.TL_inputFileLocation)) { + private boolean getPeerReferenceReplacement(TLRPC.User user, TLRPC.Chat chat, boolean big, TLRPC.InputFileLocation location, TLRPC.InputFileLocation[] replacement, boolean[] needReplacement) { + if (needReplacement != null && needReplacement[0]) { + replacement[0] = new TLRPC.TL_inputPeerPhotoFileLocation(); + replacement[0].id = location.volume_id; + replacement[0].volume_id = location.volume_id; + replacement[0].local_id = location.local_id; + replacement[0].big = big; + TLRPC.InputPeer peer; + if (user != null) { + TLRPC.TL_inputPeerUser inputPeerUser = new TLRPC.TL_inputPeerUser(); + inputPeerUser.user_id = user.id; + inputPeerUser.access_hash = user.access_hash; + peer = inputPeerUser; + } else { + if (ChatObject.isChannel(chat)) { + TLRPC.TL_inputPeerChat inputPeerChat = new TLRPC.TL_inputPeerChat(); + inputPeerChat.chat_id = chat.id; + peer = inputPeerChat; + } else { + TLRPC.TL_inputPeerChannel inputPeerChannel = new TLRPC.TL_inputPeerChannel(); + inputPeerChannel.channel_id = chat.id; + inputPeerChannel.access_hash = chat.access_hash; + peer = inputPeerChannel; + } + } + replacement[0].peer = peer; + return true; + } + return false; + } + + private byte[] getFileReference(TLRPC.User user, TLRPC.InputFileLocation location, boolean[] needReplacement, TLRPC.InputFileLocation[] replacement) { + if (user == null || user.photo == null || !(location instanceof TLRPC.TL_inputFileLocation)) { return null; } - byte[] result = getFileReference(photo.photo_small, location); + byte[] result = getFileReference(user.photo.photo_small, location, needReplacement); + if (getPeerReferenceReplacement(user, null, false, location, replacement, needReplacement)) { + return new byte[0]; + } if (result == null) { - result = getFileReference(photo.photo_big, location); + result = getFileReference(user.photo.photo_big, location, needReplacement); + if (getPeerReferenceReplacement(user, null, true, location, replacement, needReplacement)) { + return new byte[0]; + } } return result; } - private byte[] getFileReference(TLRPC.ChatPhoto photo, TLRPC.InputFileLocation location) { - if (photo == null || !(location instanceof TLRPC.TL_inputFileLocation)) { + private byte[] getFileReference(TLRPC.Chat chat, TLRPC.InputFileLocation location, boolean[] needReplacement, TLRPC.InputFileLocation[] replacement) { + if (chat == null || chat.photo == null || !(location instanceof TLRPC.TL_inputFileLocation)) { return null; } - byte[] result = getFileReference(photo.photo_small, location); + byte[] result = getFileReference(chat.photo.photo_small, location, needReplacement); + if (getPeerReferenceReplacement(null, chat, false, location, replacement, needReplacement)) { + return new byte[0]; + } if (result == null) { - result = getFileReference(photo.photo_big, location); + result = getFileReference(chat.photo.photo_big, location, needReplacement); + if (getPeerReferenceReplacement(null, chat, true, location, replacement, needReplacement)) { + return new byte[0]; + } } return result; } - private byte[] getFileReference(TLRPC.Photo photo, TLRPC.InputFileLocation location) { + private byte[] getFileReference(TLRPC.Photo photo, TLRPC.InputFileLocation location, boolean[] needReplacement, TLRPC.InputFileLocation[] replacement) { if (photo == null) { return null; } - if (location instanceof TLRPC.TL_inputSecureFileLocation) { + if (location instanceof TLRPC.TL_inputPhotoFileLocation) { return photo.id == location.id ? photo.file_reference : null; } else if (location instanceof TLRPC.TL_inputFileLocation) { for (int a = 0, size = photo.sizes.size(); a < size; a++) { - byte[] result = getFileReference(photo.sizes.get(a), location); + TLRPC.PhotoSize photoSize = photo.sizes.get(a); + byte[] result = getFileReference(photoSize, location, needReplacement); + if (needReplacement != null && needReplacement[0]) { + replacement[0] = new TLRPC.TL_inputPhotoFileLocation(); + replacement[0].id = photo.id; + replacement[0].volume_id = location.volume_id; + replacement[0].local_id = location.local_id; + replacement[0].access_hash = photo.access_hash; + replacement[0].file_reference = photo.file_reference; + replacement[0].thumb_size = photoSize.type; + return photo.file_reference; + } if (result != null) { return result; } @@ -828,41 +912,44 @@ public class FileRefController { return null; } - private byte[] getFileReference(TLRPC.PhotoSize photoSize, TLRPC.InputFileLocation location) { + private byte[] getFileReference(TLRPC.PhotoSize photoSize, TLRPC.InputFileLocation location, boolean[] needReplacement) { if (photoSize == null || !(location instanceof TLRPC.TL_inputFileLocation)) { return null; } - return getFileReference(photoSize.location, location); + return getFileReference(photoSize.location, location, needReplacement); } - private byte[] getFileReference(TLRPC.FileLocation fileLocation, TLRPC.InputFileLocation location) { + private byte[] getFileReference(TLRPC.FileLocation fileLocation, TLRPC.InputFileLocation location, boolean[] needReplacement) { if (fileLocation == null || !(location instanceof TLRPC.TL_inputFileLocation)) { return null; } if (fileLocation.local_id == location.local_id && fileLocation.volume_id == location.volume_id) { + if (fileLocation.file_reference == null && needReplacement != null) { + needReplacement[0] = true; + } return fileLocation.file_reference; } return null; } - private byte[] getFileReference(TLRPC.WebPage webpage, TLRPC.InputFileLocation location) { - byte[] result = getFileReference(webpage.document, location); + private byte[] getFileReference(TLRPC.WebPage webpage, TLRPC.InputFileLocation location, boolean[] needReplacement, TLRPC.InputFileLocation[] replacement) { + byte[] result = getFileReference(webpage.document, location, needReplacement, replacement); if (result != null) { return result; } - result = getFileReference(webpage.photo, location); + result = getFileReference(webpage.photo, location, needReplacement, replacement); if (result != null) { return result; } if (result == null && webpage.cached_page != null) { for (int b = 0, size2 = webpage.cached_page.documents.size(); b < size2; b++) { - result = getFileReference(webpage.cached_page.documents.get(b), location); + result = getFileReference(webpage.cached_page.documents.get(b), location, needReplacement, replacement); if (result != null) { return result; } } for (int b = 0, size2 = webpage.cached_page.photos.size(); b < size2; b++) { - result = getFileReference(webpage.cached_page.photos.get(b), location); + result = getFileReference(webpage.cached_page.photos.get(b), location, needReplacement, replacement); if (result != null) { return result; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java index 6644ed329..457a9b5d8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java @@ -9,7 +9,7 @@ package org.telegram.messenger; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.upstream.BaseDataSource; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java b/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java index a169402ff..be7766aec 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java @@ -11,6 +11,7 @@ package org.telegram.messenger; import android.os.SystemClock; import android.text.TextUtils; import android.util.Base64; +import android.util.SparseArray; import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage; @@ -97,7 +98,7 @@ public class GcmPushListenerService extends FirebaseMessagingService { int len = buffer.readInt32(true); byte[] strBytes = new byte[len]; buffer.readBytes(strBytes, true); - jsonString = new String(strBytes, "UTF-8"); + jsonString = new String(strBytes); JSONObject json = new JSONObject(jsonString); if (json.has("loc_key")) { @@ -179,6 +180,15 @@ public class GcmPushListenerService extends FirebaseMessagingService { countDownLatch.countDown(); return; } + case "SESSION_REVOKE": { + AndroidUtilities.runOnUIThread(() -> { + if (UserConfig.getInstance(accountFinal).getClientUserId() != 0) { + UserConfig.getInstance(accountFinal).clearConfig(); + MessagesController.getInstance(accountFinal).performLogout(0); + } + }); + return; + } } int channel_id; @@ -216,7 +226,24 @@ public class GcmPushListenerService extends FirebaseMessagingService { } else { badge = 1; }*/ - if (!TextUtils.isEmpty(loc_key)) { + if ("MESSAGE_DELETED".equals(loc_key)) { + String messages = custom.getString("messages"); + String[] messagesArgs = messages.split(","); + SparseArray> deletedMessages = new SparseArray<>(); + ArrayList ids = new ArrayList<>(); + for (int a = 0; a < messagesArgs.length; a++) { + ids.add(Utilities.parseInt(messagesArgs[a])); + } + deletedMessages.put(channel_id, ids); + NotificationsController.getInstance(currentAccount).removeDeletedMessagesFromNotifications(deletedMessages); + + final long dialogIdFinal = dialog_id; + MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> { + MessagesStorage.getInstance(accountFinal).deletePushMessages(dialogIdFinal, ids); + ArrayList dialogIds = MessagesStorage.getInstance(accountFinal).markMessagesAsDeleted(ids, false, channel_id); + MessagesStorage.getInstance(accountFinal).updateDialogsWithDeletedMessages(ids, dialogIds, false, channel_id); + }); + } else if (!TextUtils.isEmpty(loc_key)) { int msg_id; if (custom.has("msg_id")) { msg_id = custom.getInt("msg_id"); @@ -248,16 +275,16 @@ public class GcmPushListenerService extends FirebaseMessagingService { } if (processNotification) { int chat_from_id; - boolean mention; if (custom.has("chat_from_id")) { chat_from_id = custom.getInt("chat_from_id"); } else { chat_from_id = 0; } - mention = custom.has("mention") && custom.getInt("mention") != 0; + boolean mention = custom.has("mention") && custom.getInt("mention") != 0; + boolean silent = custom.has("silent") && custom.getInt("silent") != 0; - String args[]; + String[] args; if (json.has("loc_args")) { JSONArray loc_args = json.getJSONArray("loc_args"); args = new String[loc_args.length()]; @@ -275,6 +302,7 @@ public class GcmPushListenerService extends FirebaseMessagingService { boolean supergroup = false; boolean pinned = false; boolean channel = false; + boolean edited = custom.has("edit_date"); if (loc_key.startsWith("CHAT_")) { supergroup = channel_id != 0; userName = name; @@ -350,12 +378,12 @@ public class GcmPushListenerService extends FirebaseMessagingService { break; } case "MESSAGE_CONTACT": { - messageText = LocaleController.formatString("NotificationMessageContact", R.string.NotificationMessageContact, args[0]); + messageText = LocaleController.formatString("NotificationMessageContact2", R.string.NotificationMessageContact2, args[0], args[1]); message1 = LocaleController.getString("AttachContact", R.string.AttachContact); break; } case "MESSAGE_POLL": { - messageText = LocaleController.formatString("NotificationMessagePoll", R.string.NotificationMessagePoll, args[0]); + messageText = LocaleController.formatString("NotificationMessagePoll2", R.string.NotificationMessagePoll2, args[0], args[1]); message1 = LocaleController.getString("Poll", R.string.Poll); break; } @@ -375,10 +403,14 @@ public class GcmPushListenerService extends FirebaseMessagingService { break; } case "MESSAGE_GAME": { - messageText = LocaleController.formatString("NotificationMessageGame", R.string.NotificationMessageGame, args[0]); + messageText = LocaleController.formatString("NotificationMessageGame", R.string.NotificationMessageGame, args[0], args[1]); message1 = LocaleController.getString("AttachGame", R.string.AttachGame); break; } + case "MESSAGE_GAME_SCORE": { + messageText = LocaleController.formatString("NotificationMessageGameScored", R.string.NotificationMessageGameScored, args[0], args[1], args[2]); + break; + } case "MESSAGE_INVOICE": { messageText = LocaleController.formatString("NotificationMessageInvoice", R.string.NotificationMessageInvoice, args[0], args[1]); message1 = LocaleController.getString("PaymentInvoice", R.string.PaymentInvoice); @@ -394,8 +426,13 @@ public class GcmPushListenerService extends FirebaseMessagingService { localMessage = true; break; } + case "MESSAGE_VIDEOS": { + messageText = LocaleController.formatString("NotificationMessageFew", R.string.NotificationMessageFew, args[0], LocaleController.formatPluralString("Videos", Utilities.parseInt(args[1]))); + localMessage = true; + break; + } case "MESSAGES": { - messageText = LocaleController.formatString("NotificationMessageFew", R.string.NotificationMessageFew, args[0], LocaleController.formatPluralString("messages", Utilities.parseInt(args[1]))); + messageText = LocaleController.formatString("NotificationMessageAlbum", R.string.NotificationMessageAlbum, args[0]); localMessage = true; break; } @@ -445,12 +482,12 @@ public class GcmPushListenerService extends FirebaseMessagingService { break; } case "CHANNEL_MESSAGE_CONTACT": { - messageText = LocaleController.formatString("ChannelMessageContact", R.string.ChannelMessageContact, args[0]); + messageText = LocaleController.formatString("ChannelMessageContact2", R.string.ChannelMessageContact2, args[0], args[1]); message1 = LocaleController.getString("AttachContact", R.string.AttachContact); break; } case "CHANNEL_MESSAGE_POLL": { - messageText = LocaleController.formatString("ChannelMessagePoll", R.string.ChannelMessagePoll, args[0]); + messageText = LocaleController.formatString("ChannelMessagePoll2", R.string.ChannelMessagePoll2, args[0], args[1]); message1 = LocaleController.getString("Poll", R.string.Poll); break; } @@ -474,6 +511,10 @@ public class GcmPushListenerService extends FirebaseMessagingService { 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; @@ -484,8 +525,13 @@ public class GcmPushListenerService extends FirebaseMessagingService { localMessage = true; break; } + case "CHANNEL_MESSAGE_VIDEOS": { + messageText = LocaleController.formatString("ChannelMessageFew", R.string.ChannelMessageFew, args[0], LocaleController.formatPluralString("Videos", Utilities.parseInt(args[1]))); + localMessage = true; + break; + } case "CHANNEL_MESSAGES": { - messageText = LocaleController.formatString("ChannelMessageFew", R.string.ChannelMessageFew, args[0], LocaleController.formatPluralString("messages", Utilities.parseInt(args[1]))); + messageText = LocaleController.formatString("ChannelMessageAlbum", R.string.ChannelMessageAlbum, args[0]); localMessage = true; break; } @@ -535,12 +581,12 @@ public class GcmPushListenerService extends FirebaseMessagingService { break; } case "CHAT_MESSAGE_CONTACT": { - messageText = LocaleController.formatString("NotificationMessageGroupContact", R.string.NotificationMessageGroupContact, args[0], args[1]); + messageText = LocaleController.formatString("NotificationMessageGroupContact2", R.string.NotificationMessageGroupContact2, args[0], args[1], args[2]); message1 = LocaleController.getString("AttachContact", R.string.AttachContact); break; } case "CHAT_MESSAGE_POLL": { - messageText = LocaleController.formatString("NotificationMessageGroupPoll", R.string.NotificationMessageGroupPoll, args[0], args[1]); + messageText = LocaleController.formatString("NotificationMessageGroupPoll2", R.string.NotificationMessageGroupPoll2, args[0], args[1], args[2]); message1 = LocaleController.getString("Poll", R.string.Poll); break; } @@ -564,6 +610,10 @@ public class GcmPushListenerService extends FirebaseMessagingService { message1 = LocaleController.getString("AttachGame", R.string.AttachGame); break; } + case "CHAT_MESSAGE_GAME_SCORE": { + messageText = LocaleController.formatString("NotificationMessageGroupGameScored", R.string.NotificationMessageGroupGameScored, args[0], args[1], args[2], args[3]); + break; + } case "CHAT_MESSAGE_INVOICE": { messageText = LocaleController.formatString("NotificationMessageGroupInvoice", R.string.NotificationMessageGroupInvoice, args[0], args[1], args[2]); message1 = LocaleController.getString("PaymentInvoice", R.string.PaymentInvoice); @@ -619,8 +669,13 @@ public class GcmPushListenerService extends FirebaseMessagingService { localMessage = true; break; } + case "CHAT_MESSAGE_VIDEOS": { + messageText = LocaleController.formatString("NotificationGroupFew", R.string.NotificationGroupFew, args[0], args[1], LocaleController.formatPluralString("Videos", Utilities.parseInt(args[2]))); + localMessage = true; + break; + } case "CHAT_MESSAGES": { - messageText = LocaleController.formatString("NotificationGroupFew", R.string.NotificationGroupFew, args[0], args[1], LocaleController.formatPluralString("messages", Utilities.parseInt(args[2]))); + messageText = LocaleController.formatString("NotificationGroupAlbum", R.string.NotificationGroupAlbum, args[0], args[1]); localMessage = true; break; } @@ -698,17 +753,17 @@ public class GcmPushListenerService extends FirebaseMessagingService { } case "PINNED_CONTACT": { if (chat_from_id != 0) { - messageText = LocaleController.formatString("NotificationActionPinnedContact", R.string.NotificationActionPinnedContact, args[0], args[1]); + messageText = LocaleController.formatString("NotificationActionPinnedContact2", R.string.NotificationActionPinnedContact2, args[0], args[1], args[2]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedContactChannel", R.string.NotificationActionPinnedContactChannel, args[0]); + messageText = LocaleController.formatString("NotificationActionPinnedContactChannel2", R.string.NotificationActionPinnedContactChannel2, args[0], args[1]); } break; } case "PINNED_POLL": { if (chat_from_id != 0) { - messageText = LocaleController.formatString("NotificationActionPinnedPoll", R.string.NotificationActionPinnedPoll, args[0], args[1]); + messageText = LocaleController.formatString("NotificationActionPinnedPoll2", R.string.NotificationActionPinnedPoll2, args[0], args[1], args[2]); } else { - messageText = LocaleController.formatString("NotificationActionPinnedPollChannel", R.string.NotificationActionPinnedPollChannel, args[0]); + messageText = LocaleController.formatString("NotificationActionPinnedPollChannel2", R.string.NotificationActionPinnedPollChannel2, args[0], args[1]); } break; } @@ -736,6 +791,14 @@ public class GcmPushListenerService extends FirebaseMessagingService { } break; } + case "PINNED_GAME_SCORE": { + if (chat_from_id != 0) { + messageText = LocaleController.formatString("NotificationActionPinnedGameScore", R.string.NotificationActionPinnedGameScore, args[0], args[1]); + } else { + messageText = LocaleController.formatString("NotificationActionPinnedGameScoreChannel", R.string.NotificationActionPinnedGameScoreChannel, args[0]); + } + break; + } case "PINNED_INVOICE": { if (chat_from_id != 0) { messageText = LocaleController.formatString("NotificationActionPinnedInvoice", R.string.NotificationActionPinnedInvoice, args[0], args[1]); @@ -815,9 +878,10 @@ public class GcmPushListenerService extends FirebaseMessagingService { messageOwner.to_id.user_id = user_id; } messageOwner.from_id = chat_from_id; - messageOwner.mentioned = mention; + messageOwner.mentioned = mention || pinned; + messageOwner.silent = silent; - MessageObject messageObject = new MessageObject(currentAccount, messageOwner, messageText, name, userName, localMessage, channel); + MessageObject messageObject = new MessageObject(currentAccount, messageOwner, messageText, name, userName, localMessage, channel, edited); ArrayList arrayList = new ArrayList<>(); arrayList.add(messageObject); NotificationsController.getInstance(currentAccount).processNewMessages(arrayList, true, true, countDownLatch); @@ -875,7 +939,7 @@ public class GcmPushListenerService extends FirebaseMessagingService { try { countDownLatch.await(); } catch (Throwable ignore) { - FileLog.e(ignore); + } if (BuildVars.DEBUG_VERSION) { FileLog.d("finished GCM service, time = " + (SystemClock.uptimeMillis() - receiveTime)); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java index 97547188b..ab29e1c33 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -17,7 +17,9 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.drawable.BitmapDrawable; -import android.support.media.ExifInterface; +import androidx.exifinterface.media.ExifInterface; + +import android.graphics.drawable.Drawable; import android.media.ThumbnailUtils; import android.net.Uri; import android.os.AsyncTask; @@ -27,6 +29,9 @@ import android.provider.MediaStore; import android.text.TextUtils; import android.util.SparseArray; +import com.airbnb.lottie.LottieCompositionFactory; +import com.airbnb.lottie.LottieDrawable; + import org.json.JSONArray; import org.json.JSONObject; import org.telegram.messenger.secretmedia.EncryptedFileInputStream; @@ -100,7 +105,7 @@ public class ImageLoader { private File telegramPath = null; - public static final String VIDEO_FILTER = "g"; + public static final String AUTOPLAY_FILTER = "g"; private class ThumbGenerateInfo { private TLRPC.Document parentDocument; @@ -290,7 +295,7 @@ public class ImageLoader { public ArtworkLoadTask(CacheImage cacheImage) { this.cacheImage = cacheImage; - Uri uri = Uri.parse((String) cacheImage.location); + Uri uri = Uri.parse(cacheImage.imageLocation.path); small = uri.getQueryParameter("s") != null; } @@ -298,7 +303,7 @@ public class ImageLoader { ByteArrayOutputStream outbuf = null; InputStream httpConnectionStream = null; try { - String location = (String) cacheImage.location; + String location = cacheImage.imageLocation.path; URL downloadUrl = new URL(location.replace("athumb://", "https://")); httpConnection = (HttpURLConnection) downloadUrl.openConnection(); httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.38 (KHTML, like Gecko) Version/10.0 Mobile/14A5297c Safari/602.1"); @@ -334,7 +339,7 @@ public class ImageLoader { } } canRetry = false; - JSONObject object = new JSONObject(new String(outbuf.toByteArray(), "UTF-8")); + JSONObject object = new JSONObject(new String(outbuf.toByteArray())); JSONArray array = object.getJSONArray("results"); if (array.length() > 0) { JSONObject media = array.getJSONObject(0); @@ -442,7 +447,7 @@ public class ImageLoader { if (!isCancelled()) { try { - String location = (String) cacheImage.location; + String location = cacheImage.imageLocation.path; if (location.startsWith("https://static-maps") || location.startsWith("https://maps.googleapis")) { int provider = MessagesController.getInstance(cacheImage.currentAccount).mapProvider; if (provider == 3 || provider == 4) { @@ -736,13 +741,13 @@ public class ImageLoader { } } - if (cacheImage.location instanceof TLRPC.TL_photoStrippedSize) { + if (cacheImage.imageLocation.photoSize instanceof TLRPC.TL_photoStrippedSize) { synchronized (sync) { if (isCancelled) { return; } } - TLRPC.TL_photoStrippedSize photoSize = (TLRPC.TL_photoStrippedSize) cacheImage.location; + TLRPC.TL_photoStrippedSize photoSize = (TLRPC.TL_photoStrippedSize) cacheImage.imageLocation.photoSize; int len = photoSize.bytes.length - 3 + Bitmaps.header.length + Bitmaps.footer.length; byte[] bytes = bytesLocal.get(); byte[] data = bytes != null && bytes.length >= len ? bytes : null; @@ -762,6 +767,25 @@ public class ImageLoader { Utilities.blurBitmap(bitmap, 3, 1, bitmap.getWidth(), bitmap.getHeight(), bitmap.getRowBytes()); } onPostExecute(bitmap != null ? new BitmapDrawable(bitmap) : null); + } else if (cacheImage.lottieFile) { + synchronized (sync) { + if (isCancelled) { + return; + } + } + LottieDrawable lottieDrawable = new LottieDrawable(); + try { + FileInputStream is = new FileInputStream(cacheImage.finalFilePath); + lottieDrawable.setComposition(LottieCompositionFactory.fromJsonInputStreamSync(is, cacheImage.finalFilePath.toString()).getValue()); + is.close(); + } catch (Throwable e) { + FileLog.e(e); + } + lottieDrawable.setRepeatMode(LottieDrawable.RESTART); + lottieDrawable.setRepeatCount(LottieDrawable.INFINITE); + lottieDrawable.start(); + Thread.interrupted(); + onPostExecute(lottieDrawable); } else if (cacheImage.animatedFile) { synchronized (sync) { if (isCancelled) { @@ -769,8 +793,8 @@ public class ImageLoader { } } AnimatedFileDrawable fileDrawable; - if (VIDEO_FILTER.equals(cacheImage.filter) && !(cacheImage.location instanceof TLRPC.TL_documentEncrypted)) { - fileDrawable = new AnimatedFileDrawable(cacheImage.finalFilePath, false, cacheImage.size, cacheImage.location instanceof TLRPC.Document ? (TLRPC.Document) cacheImage.location : null, cacheImage.parentObject, cacheImage.currentAccount); + if (AUTOPLAY_FILTER.equals(cacheImage.filter) && !(cacheImage.imageLocation.document instanceof TLRPC.TL_documentEncrypted)) { + fileDrawable = new AnimatedFileDrawable(cacheImage.finalFilePath, false, cacheImage.size, cacheImage.imageLocation.document instanceof TLRPC.Document ? cacheImage.imageLocation.document : null, cacheImage.parentObject, cacheImage.currentAccount); } else { fileDrawable = new AnimatedFileDrawable(cacheImage.finalFilePath, "d".equals(cacheImage.filter), 0, null, null, cacheImage.currentAccount); } @@ -798,7 +822,7 @@ public class ImageLoader { secureDocumentHash = null; } boolean canDeleteFile = true; - boolean useNativeWebpLoaded = false; + boolean useNativeWebpLoader = false; if (Build.VERSION.SDK_INT < 19) { RandomAccessFile randomAccessFile = null; @@ -814,7 +838,7 @@ public class ImageLoader { String str = new String(bytes).toLowerCase(); str = str.toLowerCase(); if (str.startsWith("riff") && str.endsWith("webp")) { - useNativeWebpLoaded = true; + useNativeWebpLoader = true; } randomAccessFile.close(); } catch (Exception e) { @@ -830,10 +854,48 @@ public class ImageLoader { } } - if (cacheImage.imageType == ImageReceiver.TYPE_THUMB) { - int blurType = 0; - boolean checkInversion = false; + String mediaThumbPath = null; + if (cacheImage.imageLocation.path != null) { + String location = cacheImage.imageLocation.path; + if (location.startsWith("thumb://")) { + int idx = location.indexOf(":", 8); + if (idx >= 0) { + mediaId = Long.parseLong(location.substring(8, idx)); + mediaIsVideo = false; + mediaThumbPath = location.substring(idx + 1); + } + canDeleteFile = false; + } else if (location.startsWith("vthumb://")) { + int idx = location.indexOf(":", 9); + if (idx >= 0) { + mediaId = Long.parseLong(location.substring(9, idx)); + mediaIsVideo = true; + } + canDeleteFile = false; + } else if (!location.startsWith("http")) { + canDeleteFile = false; + } + } + + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inSampleSize = 1; + + if (Build.VERSION.SDK_INT < 21) { + opts.inPurgeable = true; + } + + float w_filter = 0; + float h_filter = 0; + int blurType = 0; + boolean checkInversion = false; + boolean force8888 = canForce8888; + try { if (cacheImage.filter != null) { + String[] args = cacheImage.filter.split("_"); + if (args.length >= 2) { + w_filter = Float.parseFloat(args[0]) * AndroidUtilities.density; + h_filter = Float.parseFloat(args[1]) * AndroidUtilities.density; + } if (cacheImage.filter.contains("b2")) { blurType = 3; } else if (cacheImage.filter.contains("b1")) { @@ -844,8 +906,86 @@ public class ImageLoader { if (cacheImage.filter.contains("i")) { checkInversion = true; } - } + if (cacheImage.filter.contains("f")) { + force8888 = true; + } + if (!useNativeWebpLoader && w_filter != 0 && h_filter != 0) { + opts.inJustDecodeBounds = true; + if (mediaId != null && mediaThumbPath == null) { + if (mediaIsVideo) { + MediaStore.Video.Thumbnails.getThumbnail(ApplicationLoader.applicationContext.getContentResolver(), mediaId, MediaStore.Video.Thumbnails.MINI_KIND, opts); + } else { + MediaStore.Images.Thumbnails.getThumbnail(ApplicationLoader.applicationContext.getContentResolver(), mediaId, MediaStore.Images.Thumbnails.MINI_KIND, opts); + } + } else { + if (secureDocumentKey != null) { + RandomAccessFile f = new RandomAccessFile(cacheFileFinal, "r"); + int len = (int) f.length(); + byte[] bytes = bytesLocal.get(); + byte[] data = bytes != null && bytes.length >= len ? bytes : null; + if (data == null) { + bytes = data = new byte[len]; + bytesLocal.set(bytes); + } + f.readFully(data, 0, len); + f.close(); + EncryptedFileInputStream.decryptBytesWithKeyFile(data, 0, len, secureDocumentKey); + byte[] hash = Utilities.computeSHA256(data, 0, len); + boolean error = false; + if (secureDocumentHash == null || !Arrays.equals(hash, secureDocumentHash)) { + error = true; + } + int offset = (data[0] & 0xff); + len -= offset; + if (!error) { + BitmapFactory.decodeByteArray(data, offset, len, opts); + } + } else { + FileInputStream is; + if (inEncryptedFile) { + is = new EncryptedFileInputStream(cacheFileFinal, cacheImage.encryptionKeyPath); + } else { + is = new FileInputStream(cacheFileFinal); + } + BitmapFactory.decodeStream(is, null, opts); + is.close(); + } + } + + float photoW = opts.outWidth; + float photoH = opts.outHeight; + float scaleFactor = Math.max(photoW / w_filter, photoH / h_filter); + if (scaleFactor < 1) { + scaleFactor = 1; + } + opts.inJustDecodeBounds = false; + opts.inSampleSize = (int) scaleFactor; + } + } else if (mediaThumbPath != null) { + opts.inJustDecodeBounds = true; + opts.inPreferredConfig = force8888 ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; + FileInputStream is = new FileInputStream(cacheFileFinal); + image = BitmapFactory.decodeStream(is, null, opts); + is.close(); + int photoW2 = opts.outWidth; + int photoH2 = opts.outHeight; + opts.inJustDecodeBounds = false; + float scaleFactor = Math.max(photoW2 / 200, photoH2 / 200); + if (scaleFactor < 1) { + scaleFactor = 1; + } + int sample = 1; + do { + sample *= 2; + } while (sample * 2 < scaleFactor); + opts.inSampleSize = sample; + } + } catch (Throwable e) { + FileLog.e(e); + } + + if (cacheImage.imageType == ImageReceiver.TYPE_THUMB) { try { lastCacheOutTime = System.currentTimeMillis(); synchronized (sync) { @@ -854,14 +994,7 @@ public class ImageLoader { } } - BitmapFactory.Options opts = new BitmapFactory.Options(); - opts.inSampleSize = 1; - - if (Build.VERSION.SDK_INT < 21) { - opts.inPurgeable = true; - } - - if (useNativeWebpLoaded) { + if (useNativeWebpLoader) { RandomAccessFile file = new RandomAccessFile(cacheFileFinal, "r"); ByteBuffer buffer = file.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, cacheFileFinal.length()); @@ -917,6 +1050,18 @@ public class ImageLoader { cacheFileFinal.delete(); } } else { + if (cacheImage.filter != null) { + float bitmapW = image.getWidth(); + float bitmapH = image.getHeight(); + if (!opts.inPurgeable && w_filter != 0 && bitmapW != w_filter && bitmapW > w_filter + 20) { + float scaleFactor = bitmapW / w_filter; + Bitmap scaledBitmap = Bitmaps.createScaledBitmap(image, (int) w_filter, (int) (bitmapH / scaleFactor), true); + if (image != scaledBitmap) { + image.recycle(); + image = scaledBitmap; + } + } + } if (checkInversion) { needInvert = Utilities.needInvert(image, opts.inPurgeable ? 0 : 1, image.getWidth(), image.getHeight(), image.getRowBytes()) != 0; } @@ -943,29 +1088,6 @@ public class ImageLoader { } } else { try { - String mediaThumbPath = null; - if (cacheImage.location instanceof String) { - String location = (String) cacheImage.location; - if (location.startsWith("thumb://")) { - int idx = location.indexOf(":", 8); - if (idx >= 0) { - mediaId = Long.parseLong(location.substring(8, idx)); - mediaIsVideo = false; - mediaThumbPath = location.substring(idx + 1); - } - canDeleteFile = false; - } else if (location.startsWith("vthumb://")) { - int idx = location.indexOf(":", 9); - if (idx >= 0) { - mediaId = Long.parseLong(location.substring(9, idx)); - mediaIsVideo = true; - } - canDeleteFile = false; - } else if (!location.startsWith("http")) { - canDeleteFile = false; - } - } - int delay = 20; if (mediaId != null) { delay = 0; @@ -980,115 +1102,11 @@ public class ImageLoader { } } - BitmapFactory.Options opts = new BitmapFactory.Options(); - opts.inSampleSize = 1; - - float w_filter = 0; - float h_filter = 0; - boolean blur = false; - boolean checkInversion = false; - boolean force8888 = canForce8888; - if (cacheImage.filter != null) { - String args[] = cacheImage.filter.split("_"); - if (args.length >= 2) { - w_filter = Float.parseFloat(args[0]) * AndroidUtilities.density; - h_filter = Float.parseFloat(args[1]) * AndroidUtilities.density; - } - if (cacheImage.filter.contains("b")) { - blur = true; - } - if (cacheImage.filter.contains("i")) { - checkInversion = true; - } - if (cacheImage.filter.contains("f")) { - force8888 = true; - } - if (w_filter != 0 && h_filter != 0) { - opts.inJustDecodeBounds = true; - - if (mediaId != null && mediaThumbPath == null) { - if (mediaIsVideo) { - MediaStore.Video.Thumbnails.getThumbnail(ApplicationLoader.applicationContext.getContentResolver(), mediaId, MediaStore.Video.Thumbnails.MINI_KIND, opts); - } else { - MediaStore.Images.Thumbnails.getThumbnail(ApplicationLoader.applicationContext.getContentResolver(), mediaId, MediaStore.Images.Thumbnails.MINI_KIND, opts); - } - } else { - if (secureDocumentKey != null) { - RandomAccessFile f = new RandomAccessFile(cacheFileFinal, "r"); - int len = (int) f.length(); - byte[] bytes = bytesLocal.get(); - byte[] data = bytes != null && bytes.length >= len ? bytes : null; - if (data == null) { - bytes = data = new byte[len]; - bytesLocal.set(bytes); - } - f.readFully(data, 0, len); - f.close(); - EncryptedFileInputStream.decryptBytesWithKeyFile(data, 0, len, secureDocumentKey); - byte[] hash = Utilities.computeSHA256(data, 0, len); - boolean error = false; - if (secureDocumentHash == null || !Arrays.equals(hash, secureDocumentHash)) { - error = true; - } - int offset = (data[0] & 0xff); - len -= offset; - if (!error) { - image = BitmapFactory.decodeByteArray(data, offset, len, opts); - } - } else { - FileInputStream is; - if (inEncryptedFile) { - is = new EncryptedFileInputStream(cacheFileFinal, cacheImage.encryptionKeyPath); - } else { - is = new FileInputStream(cacheFileFinal); - } - image = BitmapFactory.decodeStream(is, null, opts); - is.close(); - } - } - - float photoW = opts.outWidth; - float photoH = opts.outHeight; - float scaleFactor = Math.max(photoW / w_filter, photoH / h_filter); - if (scaleFactor < 1) { - scaleFactor = 1; - } - opts.inJustDecodeBounds = false; - opts.inSampleSize = (int) scaleFactor; - } - } else if (mediaThumbPath != null) { - opts.inJustDecodeBounds = true; - opts.inPreferredConfig = force8888 ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; - FileInputStream is = new FileInputStream(cacheFileFinal); - image = BitmapFactory.decodeStream(is, null, opts); - is.close(); - int photoW2 = opts.outWidth; - int photoH2 = opts.outHeight; - opts.inJustDecodeBounds = false; - float scaleFactor = Math.max(photoW2 / 200, photoH2 / 200); - if (scaleFactor < 1) { - scaleFactor = 1; - } - int sample = 1; - do { - sample *= 2; - } while (sample * 2 < scaleFactor); - opts.inSampleSize = sample; - } - synchronized (sync) { - if (isCancelled) { - return; - } - } - - if (force8888 || cacheImage.filter == null || blur || cacheImage.location instanceof String) { + if (force8888 || cacheImage.filter == null || blurType != 0 || cacheImage.imageLocation.path != null) { opts.inPreferredConfig = Bitmap.Config.ARGB_8888; } else { opts.inPreferredConfig = Bitmap.Config.RGB_565; } - if (Build.VERSION.SDK_INT < 21) { - opts.inPurgeable = true; - } opts.inDither = false; if (mediaId != null && mediaThumbPath == null) { @@ -1099,7 +1117,7 @@ public class ImageLoader { } } if (image == null) { - if (useNativeWebpLoaded) { + if (useNativeWebpLoader) { RandomAccessFile file = new RandomAccessFile(cacheFileFinal, "r"); ByteBuffer buffer = file.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, cacheFileFinal.length()); @@ -1145,7 +1163,7 @@ public class ImageLoader { } else { is = new FileInputStream(cacheFileFinal); } - if (cacheImage.location instanceof TLRPC.TL_document) { + if (cacheImage.imageLocation.document instanceof TLRPC.TL_document) { try { ExifInterface exif = new ExifInterface(is); int attribute = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1); @@ -1200,7 +1218,7 @@ public class ImageLoader { b.recycle(); } } - if (blur && bitmapH < 100 && bitmapW < 100) { + if (blurType != 0 && bitmapH < 100 && bitmapW < 100) { if (image.getConfig() == Bitmap.Config.ARGB_8888) { Utilities.blurBitmap(image, 3, opts.inPurgeable ? 0 : 1, image.getWidth(), image.getHeight(), image.getRowBytes()); } @@ -1225,12 +1243,14 @@ public class ImageLoader { } } - private void onPostExecute(final BitmapDrawable bitmapDrawable) { + private void onPostExecute(final Drawable drawable) { AndroidUtilities.runOnUIThread(() -> { - BitmapDrawable toSet = null; - if (bitmapDrawable instanceof AnimatedFileDrawable) { - toSet = bitmapDrawable; - } else if (bitmapDrawable != null) { + Drawable toSet = null; + String decrementKey = null; + if (drawable instanceof AnimatedFileDrawable || drawable instanceof LottieDrawable) { + toSet = drawable; + } else if (drawable instanceof BitmapDrawable) { + BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; toSet = memCache.get(cacheImage.key); if (toSet == null) { memCache.put(cacheImage.key, bitmapDrawable); @@ -1239,9 +1259,14 @@ public class ImageLoader { Bitmap image = bitmapDrawable.getBitmap(); image.recycle(); } + if (toSet != null) { + incrementUseCount(cacheImage.key); + decrementKey = cacheImage.key; + } } - final BitmapDrawable toSetFinal = toSet; - imageLoadQueue.postRunnable(() -> cacheImage.setImageAndClear(toSetFinal)); + final Drawable toSetFinal = toSet; + final String decrementKetFinal = decrementKey; + imageLoadQueue.postRunnable(() -> cacheImage.setImageAndClear(toSetFinal, decrementKetFinal)); }); } @@ -1266,10 +1291,11 @@ public class ImageLoader { protected String filter; protected String ext; protected SecureDocument secureDocument; - protected Object location; + protected ImageLocation imageLocation; protected Object parentObject; protected int size; protected boolean animatedFile; + protected boolean lottieFile; protected int imageType; protected int currentAccount; @@ -1285,7 +1311,7 @@ public class ImageLoader { protected ArrayList imageReceiverArray = new ArrayList<>(); protected ArrayList keys = new ArrayList<>(); protected ArrayList filters = new ArrayList<>(); - protected ArrayList thumbs = new ArrayList<>(); + protected ArrayList imageTypes = new ArrayList<>(); public void addImageReceiver(ImageReceiver imageReceiver, String key, String filter, int type) { if (imageReceiverArray.contains(imageReceiver)) { @@ -1294,7 +1320,7 @@ public class ImageLoader { imageReceiverArray.add(imageReceiver); keys.add(key); filters.add(filter); - thumbs.add(type); + imageTypes.add(type); imageLoadingByTag.put(imageReceiver.getTag(type), this); } @@ -1303,7 +1329,7 @@ public class ImageLoader { if (index == -1) { return; } - if (thumbs.get(index) != type) { + if (imageTypes.get(index) != type) { index = imageReceiverArray.subList(index + 1, imageReceiverArray.size()).indexOf(imageReceiver); if (index == -1) { return; @@ -1321,7 +1347,7 @@ public class ImageLoader { imageReceiverArray.remove(a); keys.remove(a); filters.remove(a); - currentImageType = thumbs.remove(a); + currentImageType = imageTypes.remove(a); if (obj != null) { imageLoadingByTag.remove(obj.getTag(currentImageType)); } @@ -1333,16 +1359,16 @@ public class ImageLoader { imageLoadingByTag.remove(imageReceiverArray.get(a).getTag(currentImageType)); } imageReceiverArray.clear(); - if (location != null) { + if (imageLocation != null) { if (!forceLoadingImages.containsKey(key)) { - if (location instanceof TLRPC.FileLocation) { - FileLoader.getInstance(currentAccount).cancelLoadFile((TLRPC.FileLocation) location, ext); - } else if (location instanceof TLRPC.Document) { - FileLoader.getInstance(currentAccount).cancelLoadFile((TLRPC.Document) location); - } else if (location instanceof SecureDocument) { - FileLoader.getInstance(currentAccount).cancelLoadFile((SecureDocument) location); - } else if (location instanceof WebFile) { - FileLoader.getInstance(currentAccount).cancelLoadFile((WebFile) location); + if (imageLocation.location != null) { + FileLoader.getInstance(currentAccount).cancelLoadFile(imageLocation.location, ext); + } else if (imageLocation.document != null) { + FileLoader.getInstance(currentAccount).cancelLoadFile(imageLocation.document); + } else if (imageLocation.secureDocument != null) { + FileLoader.getInstance(currentAccount).cancelLoadFile(imageLocation.secureDocument); + } else if (imageLocation.webFile != null) { + FileLoader.getInstance(currentAccount).cancelLoadFile(imageLocation.webFile); } } } @@ -1374,7 +1400,7 @@ public class ImageLoader { } } - public void setImageAndClear(final BitmapDrawable image) { + public void setImageAndClear(final Drawable image, String decrementKey) { if (image != null) { final ArrayList finalImageReceiverArray = new ArrayList<>(imageReceiverArray); AndroidUtilities.runOnUIThread(() -> { @@ -1400,9 +1426,12 @@ public class ImageLoader { } else { for (int a = 0; a < finalImageReceiverArray.size(); a++) { ImageReceiver imgView = finalImageReceiverArray.get(a); - imgView.setImageBitmapByKey(image, key, imageType, false); + imgView.setImageBitmapByKey(image, key, imageTypes.get(a), false); } } + if (decrementKey != null) { + decrementUseCount(decrementKey); + } }); } for (int a = 0; a < imageReceiverArray.size(); a++) { @@ -1439,7 +1468,7 @@ public class ImageLoader { int memoryClass = ((ActivityManager) ApplicationLoader.applicationContext.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass(); int maxSize; - if (canForce8888 = memoryClass >= 256) { + if (canForce8888 = memoryClass >= 192) { maxSize = 30; } else { maxSize = 15; @@ -1910,7 +1939,7 @@ public class ImageLoader { return memCache.get(key); } - private void replaceImageInCacheInternal(final String oldKey, final String newKey, final TLObject newLocation) { + private void replaceImageInCacheInternal(final String oldKey, final String newKey, final ImageLocation newLocation) { ArrayList arr = memCache.getFilterKeys(oldKey); if (arr != null) { for (int a = 0; a < arr.size(); a++) { @@ -1926,7 +1955,7 @@ public class ImageLoader { } } - public void replaceImageInCache(final String oldKey, final String newKey, final TLObject newLocation, boolean post) { + public void replaceImageInCache(final String oldKey, final String newKey, final ImageLocation newLocation, boolean post) { if (post) { AndroidUtilities.runOnUIThread(() -> replaceImageInCacheInternal(oldKey, newKey, newLocation)); } else { @@ -1961,8 +1990,8 @@ public class ImageLoader { imageLoadQueue.postRunnable(() -> forceLoadingImages.remove(key)); } - private void createLoadOperationForImageReceiver(final ImageReceiver imageReceiver, final String key, final String url, final String ext, final Object imageLocation, final String filter, final int size, final int cacheType, final int imageType, final int thumb) { - if (imageReceiver == null || url == null || key == null) { + private void createLoadOperationForImageReceiver(final ImageReceiver imageReceiver, final String key, final String url, final String ext, final ImageLocation imageLocation, final String filter, final int size, final int cacheType, final int imageType, final int thumb) { + if (imageReceiver == null || url == null || key == null || imageLocation == null) { return; } int TAG = imageReceiver.getTag(imageType); @@ -2016,8 +2045,8 @@ public class ImageLoader { File cacheFile = null; boolean cacheFileExists = false; - if (imageLocation instanceof String) { - String location = (String) imageLocation; + if (imageLocation.path != null) { + String location = imageLocation.path; if (!location.startsWith("http") && !location.startsWith("athumb")) { onlyCache = true; if (location.startsWith("thumb://")) { @@ -2112,37 +2141,45 @@ public class ImageLoader { } if (thumb != 2) { - boolean isEncrypted = imageLocation instanceof TLRPC.TL_documentEncrypted || imageLocation instanceof TLRPC.TL_fileEncryptedLocation; + boolean isEncrypted = imageLocation.isEncrypted(); CacheImage img = new CacheImage(); - if (imageLocation instanceof WebFile && MessageObject.isGifDocument((WebFile) imageLocation) || - imageLocation instanceof TLRPC.Document && (MessageObject.isGifDocument((TLRPC.Document) imageLocation) || MessageObject.isRoundVideoDocument((TLRPC.Document) imageLocation))) { - img.animatedFile = true; - } else if (imageLocation instanceof String) { - String location = (String) imageLocation; - if (!location.startsWith("vthumb") && !location.startsWith("thumb")) { - String trueExt = getHttpUrlExtension(location, "jpg"); - if (trueExt.equals("mp4") || trueExt.equals("gif")) { - img.animatedFile = true; + if (!currentKeyQuality) { + if (MessageObject.isGifDocument(imageLocation.webFile) || MessageObject.isGifDocument(imageLocation.document) || MessageObject.isRoundVideoDocument(imageLocation.document)) { + img.animatedFile = true; + } else if (imageLocation.path != null) { + String location = imageLocation.path; + if (!location.startsWith("vthumb") && !location.startsWith("thumb")) { + String trueExt = getHttpUrlExtension(location, "jpg"); + if (trueExt.equals("mp4") || trueExt.equals("gif")) { + img.animatedFile = true; + } } } } if (cacheFile == null) { - if (imageLocation instanceof TLRPC.TL_photoStrippedSize) { + int fileSize = 0; + if (imageLocation.photoSize instanceof TLRPC.TL_photoStrippedSize) { onlyCache = true; - } else if (imageLocation instanceof SecureDocument) { - img.secureDocument = (SecureDocument) imageLocation; + } else if (imageLocation.secureDocument != null) { + img.secureDocument = imageLocation.secureDocument; onlyCache = img.secureDocument.secureFile.dc_id == Integer.MIN_VALUE; cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), url); - } else if (!VIDEO_FILTER.equals(filter) && (cacheType != 0 || size <= 0 || imageLocation instanceof String || isEncrypted)) { + } else if (!AUTOPLAY_FILTER.equals(filter) && (cacheType != 0 || size <= 0 || imageLocation.path != null || isEncrypted)) { cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), url); if (cacheFile.exists()) { cacheFileExists = true; } else if (cacheType == 2) { cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), url + ".enc"); } - } else if (imageLocation instanceof TLRPC.Document) { - TLRPC.Document document = (TLRPC.Document) imageLocation; + if (imageLocation.document != null) { + String name = FileLoader.getDocumentFileName(imageLocation.document); + if (name.startsWith("tg_secret_sticker") && name.endsWith("json")) { + img.lottieFile = true; + } + } + } else if (imageLocation.document != null) { + TLRPC.Document document = imageLocation.document; if (document instanceof TLRPC.TL_documentEncrypted) { cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), url); } else if (MessageObject.isVideoDocument(document)) { @@ -2150,25 +2187,32 @@ public class ImageLoader { } else { cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_DOCUMENT), url); } - if (VIDEO_FILTER.equals(filter)) { - img.animatedFile = true; - img.size = document.size; - onlyCache = true; - if (!cacheFile.exists()) { - cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), document.dc_id + "_" + document.id + ".temp"); + if (AUTOPLAY_FILTER.equals(filter) && !cacheFile.exists()) { + cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), document.dc_id + "_" + document.id + ".temp"); + } + if (BuildVars.DEBUG_PRIVATE_VERSION) { + String name = FileLoader.getDocumentFileName(document); + if (name.startsWith("tg_secret_sticker") && name.endsWith("json")) { + img.lottieFile = true; } } - } else if (imageLocation instanceof WebFile) { + fileSize = document.size; + } else if (imageLocation.webFile != null) { cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_DOCUMENT), url); } else { cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_IMAGE), url); } + if (AUTOPLAY_FILTER.equals(filter)) { + img.animatedFile = true; + img.size = fileSize; + onlyCache = true; + } } img.imageType = imageType; img.key = key; img.filter = filter; - img.location = imageLocation; + img.imageLocation = imageLocation; img.ext = ext; img.currentAccount = currentAccount; img.parentObject = parentObject; @@ -2178,7 +2222,7 @@ public class ImageLoader { img.addImageReceiver(imageReceiver, key, filter, imageType); if (onlyCache || cacheFileExists || cacheFile.exists()) { img.finalFilePath = cacheFile; - img.location = imageLocation; + img.imageLocation = imageLocation; img.cacheTask = new CacheOutTask(img); imageLoadingByKeys.put(key, img); if (thumb != 0) { @@ -2190,13 +2234,12 @@ public class ImageLoader { img.url = url; imageLoadingByUrl.put(url, img); - if (imageLocation instanceof String) { - String location = (String) imageLocation; - String file = Utilities.MD5(location); + if (imageLocation.path != null) { + String file = Utilities.MD5(imageLocation.path); File cacheDir = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE); img.tempFilePath = new File(cacheDir, file + "_temp.jpg"); img.finalFilePath = cacheFile; - if (location.startsWith("athumb")) { + if (imageLocation.path.startsWith("athumb")) { img.artworkTask = new ArtworkLoadTask(img); artworkTasks.add(img.artworkTask); runArtworkTasks(false); @@ -2206,26 +2249,18 @@ public class ImageLoader { runHttpTasks(false); } } else { - if (imageLocation instanceof TLRPC.FileLocation) { - TLRPC.FileLocation location = (TLRPC.FileLocation) imageLocation; + if (imageLocation.location != null) { int localCacheType = cacheType; - if (localCacheType == 0 && (size <= 0 || location.key != null)) { + if (localCacheType == 0 && (size <= 0 || imageLocation.key != null)) { localCacheType = 1; } - FileLoader.getInstance(currentAccount).loadFile(location, parentObject, ext, size, thumb != 0 ? 2 : 1, localCacheType); - } else if (imageLocation instanceof TLRPC.PhotoSize) { - TLRPC.PhotoSize photoSize = (TLRPC.PhotoSize) imageLocation; - int localCacheType = cacheType; - if (localCacheType == 0 && (size <= 0 || photoSize.location.key != null)) { - localCacheType = 1; - } - FileLoader.getInstance(currentAccount).loadFile(photoSize.location, parentObject, ext, size, thumb != 0 ? 2 : 1, localCacheType); - } else if (imageLocation instanceof TLRPC.Document) { - FileLoader.getInstance(currentAccount).loadFile((TLRPC.Document) imageLocation, parentObject, thumb != 0 ? 2 : 1, cacheType); - } else if (imageLocation instanceof SecureDocument) { - FileLoader.getInstance(currentAccount).loadFile((SecureDocument) imageLocation, thumb != 0 ? 2 : 1); - } else if (imageLocation instanceof WebFile) { - FileLoader.getInstance(currentAccount).loadFile((WebFile) imageLocation, thumb != 0 ? 2 : 1, cacheType); + FileLoader.getInstance(currentAccount).loadFile(imageLocation, parentObject, ext, thumb != 0 ? 2 : 1, localCacheType); + } else if (imageLocation.document != null) { + FileLoader.getInstance(currentAccount).loadFile(imageLocation.document, parentObject, thumb != 0 ? 2 : 1, cacheType); + } else if (imageLocation.secureDocument != null) { + FileLoader.getInstance(currentAccount).loadFile(imageLocation.secureDocument, thumb != 0 ? 2 : 1); + } else if (imageLocation.webFile != null) { + FileLoader.getInstance(currentAccount).loadFile(imageLocation.webFile, thumb != 0 ? 2 : 1, cacheType); } if (imageReceiver.isForceLoding()) { forceLoadingImages.put(img.key, 0); @@ -2284,15 +2319,19 @@ public class ImageLoader { boolean qualityThumb = false; Object parentObject = imageReceiver.getParentObject(); TLRPC.Document qualityDocument = imageReceiver.getQulityThumbDocument(); - Object thumbLocation = imageReceiver.getThumbLocation(); - Object mediaLocation = imageReceiver.getMediaLocation(); - Object imageLocation = imageReceiver.getImageLocation(); + ImageLocation thumbLocation = imageReceiver.getThumbLocation(); + String thumbFilter = imageReceiver.getThumbFilter(); + ImageLocation mediaLocation = imageReceiver.getMediaLocation(); + String mediaFilter = imageReceiver.getMediaFilter(); + ImageLocation imageLocation = imageReceiver.getImageLocation(); + String imageFilter = imageReceiver.getImageFilter(); if (imageLocation == null && imageReceiver.isNeedsQualityThumb() && imageReceiver.isCurrentKeyQuality()) { if (parentObject instanceof MessageObject) { - imageLocation = ((MessageObject) parentObject).getDocument(); + MessageObject messageObject = (MessageObject) parentObject; + imageLocation = ImageLocation.getForDocument(messageObject.getDocument()); qualityThumb = true; } else if (qualityDocument != null) { - imageLocation = qualityDocument; + imageLocation = ImageLocation.getForDocument(qualityDocument); qualityThumb = true; } } @@ -2310,7 +2349,7 @@ public class ImageLoader { } for (int a = 0; a < 2; a++) { - Object object; + ImageLocation object; if (a == 0) { object = imageLocation; } else { @@ -2319,67 +2358,47 @@ public class ImageLoader { if (object == null) { continue; } - String key = null; + String key = object.getKey(parentObject, mediaLocation != null ? mediaLocation : imageLocation); + if (key == null) { + continue; + } String url = null; - if (object instanceof String) { - String location = (String) object; - key = Utilities.MD5(location); - url = key + "." + getHttpUrlExtension(location, "jpg"); - } else if (object instanceof TLRPC.FileLocation) { - TLRPC.FileLocation location = (TLRPC.FileLocation) object; - key = location.volume_id + "_" + location.local_id; + if (object.path != null) { + url = key + "." + getHttpUrlExtension(object.path, "jpg"); + } else if (object.photoSize instanceof TLRPC.TL_photoStrippedSize) { url = key + "." + ext; - if (imageReceiver.getExt() != null || location.key != null || location.volume_id == Integer.MIN_VALUE && location.local_id < 0) { + } else if (object.location != null) { + url = key + "." + ext; + if (imageReceiver.getExt() != null || object.location.key != null || object.location.volume_id == Integer.MIN_VALUE && object.location.local_id < 0) { saveImageToCache = true; } - } else if (object instanceof TLRPC.TL_photoStrippedSize) { - TLRPC.TL_photoStrippedSize location = (TLRPC.TL_photoStrippedSize) object; - key = "stripped" + FileRefController.getKeyForParentObject(parentObject); + } else if (object.webFile != null) { + String defaultExt = FileLoader.getMimeTypePart(object.webFile.mime_type); + url = key + "." + getHttpUrlExtension(object.webFile.url, defaultExt); + } else if (object.secureDocument != null) { url = key + "." + ext; - } else if (object instanceof TLRPC.TL_photoSize) { - TLRPC.TL_photoSize photoSize = (TLRPC.TL_photoSize) object; - key = photoSize.location.volume_id + "_" + photoSize.location.local_id; - url = key + "." + ext; - if (imageReceiver.getExt() != null || photoSize.location.key != null || photoSize.location.volume_id == Integer.MIN_VALUE && photoSize.location.local_id < 0) { - saveImageToCache = true; + } else if (object.document != null) { + if (a == 0 && qualityThumb) { + key = "q_" + key; } - } else if (object instanceof WebFile) { - WebFile document = (WebFile) object; - String defaultExt = FileLoader.getMimeTypePart(document.mime_type); - key = Utilities.MD5(document.url); - url = key + "." + getHttpUrlExtension(document.url, defaultExt); - } else if (object instanceof SecureDocument) { - SecureDocument document = (SecureDocument) object; - key = document.secureFile.dc_id + "_" + document.secureFile.id; - url = key + "." + ext; - } else if (object instanceof TLRPC.Document) { - TLRPC.Document document = (TLRPC.Document) object; - if (document.id != 0 && document.dc_id != 0) { - if (a == 0 && qualityThumb) { - key = "q_" + document.dc_id + "_" + document.id; + String docExt = FileLoader.getDocumentFileName(object.document); + int idx; + if (docExt == null || (idx = docExt.lastIndexOf('.')) == -1) { + docExt = ""; + } else { + docExt = docExt.substring(idx); + } + if (docExt.length() <= 1) { + if ("video/mp4".equals(object.document.mime_type)) { + docExt = ".mp4"; + } else if ("video/x-matroska".equals(object.document.mime_type)) { + docExt = ".mkv"; } else { - key = document.dc_id + "_" + document.id; - } - - String docExt = FileLoader.getDocumentFileName(document); - int idx; - if (docExt == null || (idx = docExt.lastIndexOf('.')) == -1) { docExt = ""; - } else { - docExt = docExt.substring(idx); } - if (docExt.length() <= 1) { - if ("video/mp4".equals(document.mime_type)) { - docExt = ".mp4"; - } else if ("video/x-matroska".equals(document.mime_type)) { - docExt = ".mkv"; - } else { - docExt = ""; - } - } - url = key + docExt; - saveImageToCache = !MessageObject.isVideoDocument(document) && !MessageObject.isGifDocument(document) && !MessageObject.isRoundVideoDocument(document) && !MessageObject.canPreviewDocument(document); } + url = key + docExt; + saveImageToCache = !MessageObject.isVideoDocument(object.document) && !MessageObject.isGifDocument(object.document) && !MessageObject.isRoundVideoDocument(object.document) && !MessageObject.canPreviewDocument(object.document); } if (a == 0) { imageKey = key; @@ -2401,27 +2420,17 @@ public class ImageLoader { } } - if (thumbLocation instanceof String) { - String location = (String) thumbLocation; - thumbKey = Utilities.MD5(location); - thumbUrl = thumbKey + "." + getHttpUrlExtension(location, "jpg"); - } else if (thumbLocation instanceof TLRPC.FileLocation) { - TLRPC.FileLocation location = (TLRPC.FileLocation) thumbLocation; - thumbKey = location.volume_id + "_" + location.local_id; - thumbUrl = thumbKey + "." + ext; - } else if (thumbLocation instanceof TLRPC.TL_photoStrippedSize) { - TLRPC.TL_photoStrippedSize location = (TLRPC.TL_photoStrippedSize) thumbLocation; - thumbKey = "stripped" + FileRefController.getKeyForParentObject(parentObject); - thumbUrl = thumbKey + "." + ext; - } else if (thumbLocation instanceof TLRPC.TL_photoSize) { - TLRPC.TL_photoSize photoSize = (TLRPC.TL_photoSize) thumbLocation; - thumbKey = photoSize.location.volume_id + "_" + photoSize.location.local_id; - thumbUrl = thumbKey + "." + ext; + if (thumbLocation != null) { + thumbKey = thumbLocation.getKey(parentObject, mediaLocation != null ? mediaLocation : imageLocation); + if (thumbLocation.path != null) { + thumbUrl = thumbKey + "." + getHttpUrlExtension(thumbLocation.path, "jpg"); + } else if (thumbLocation.photoSize instanceof TLRPC.TL_photoStrippedSize) { + thumbUrl = thumbKey + "." + ext; + } else if (thumbLocation.location != null) { + thumbUrl = thumbKey + "." + ext; + } } - String mediaFilter = imageReceiver.getMediaFilter(); - String imageFilter = imageReceiver.getImageFilter(); - String thumbFilter = imageReceiver.getThumbFilter(); if (mediaKey != null && mediaFilter != null) { mediaKey += "@" + mediaFilter; } @@ -2432,7 +2441,7 @@ public class ImageLoader { thumbKey += "@" + thumbFilter; } - if (imageLocation instanceof String) { + if (imageLocation != null && imageLocation.path != null) { createLoadOperationForImageReceiver(imageReceiver, thumbKey, thumbUrl, ext, thumbLocation, thumbFilter, 0, 1, ImageReceiver.TYPE_THUMB, thumbSet ? 2 : 1); createLoadOperationForImageReceiver(imageReceiver, imageKey, imageUrl, ext, imageLocation, imageFilter, imageReceiver.getSize(), 1, ImageReceiver.TYPE_IMAGE, 0); } else if (mediaLocation != null) { @@ -2502,7 +2511,7 @@ public class ImageLoader { for (int a = 0; a < img.imageReceiverArray.size(); a++) { String key = img.keys.get(a); String filter = img.filters.get(a); - int imageType = img.thumbs.get(a); + int imageType = img.imageTypes.get(a); ImageReceiver imageReceiver = img.imageReceiverArray.get(a); CacheImage cacheImage = imageLoadingByKeys.get(key); if (cacheImage == null) { @@ -2511,7 +2520,7 @@ public class ImageLoader { cacheImage.currentAccount = img.currentAccount; cacheImage.finalFilePath = finalFile; cacheImage.key = key; - cacheImage.location = img.location; + cacheImage.imageLocation = img.imageLocation; cacheImage.imageType = imageType; cacheImage.ext = img.ext; cacheImage.encryptionKeyPath = img.encryptionKeyPath; @@ -2541,7 +2550,7 @@ public class ImageLoader { imageLoadQueue.postRunnable(() -> { CacheImage img = imageLoadingByUrl.get(location); if (img != null) { - img.setImageAndClear(null); + img.setImageAndClear(null, null); } }); } @@ -2851,9 +2860,9 @@ public class ImageLoader { } boolean check = photoSize != null; - TLRPC.TL_fileLocation location; - if (photoSize == null || !(photoSize.location instanceof TLRPC.TL_fileLocation)) { - location = new TLRPC.TL_fileLocation(); + TLRPC.TL_fileLocationToBeDeprecated location; + if (photoSize == null || !(photoSize.location instanceof TLRPC.TL_fileLocationToBeDeprecated)) { + location = new TLRPC.TL_fileLocationToBeDeprecated(); location.volume_id = Integer.MIN_VALUE; location.dc_id = Integer.MIN_VALUE; location.local_id = SharedConfig.getLastLocalId(); @@ -2875,7 +2884,7 @@ public class ImageLoader { photoSize.type = "w"; } } else { - location = (TLRPC.TL_fileLocation) photoSize.location; + location = (TLRPC.TL_fileLocationToBeDeprecated) photoSize.location; } String fileName = location.volume_id + "_" + location.local_id + ".jpg"; @@ -3000,11 +3009,9 @@ public class ImageLoader { } if (photoSize != null && photoSize.bytes != null && photoSize.bytes.length != 0) { if (photoSize.location == null || photoSize.location instanceof TLRPC.TL_fileLocationUnavailable) { - photoSize.location = new TLRPC.TL_fileLocation(); + photoSize.location = new TLRPC.TL_fileLocationToBeDeprecated(); photoSize.location.volume_id = Integer.MIN_VALUE; - photoSize.location.dc_id = Integer.MIN_VALUE; photoSize.location.local_id = SharedConfig.getLastLocalId(); - photoSize.location.file_reference = new byte[0]; } File file = FileLoader.getPathToAttach(photoSize, true); boolean isEncrypted = false; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLocation.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLocation.java new file mode 100644 index 000000000..65e1285f5 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLocation.java @@ -0,0 +1,286 @@ +package org.telegram.messenger; + +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; + +public class ImageLocation { + + public int dc_id; + public byte[] file_reference; + public byte[] key; + public byte[] iv; + public long access_hash; + public TLRPC.TL_fileLocationToBeDeprecated location; + + public String path; + + public SecureDocument secureDocument; + + public TLRPC.Document document; + + public TLRPC.PhotoSize photoSize; + public TLRPC.Photo photo; + public boolean photoPeerBig; + public TLRPC.InputPeer photoPeer; + public TLRPC.InputStickerSet stickerSet; + + public int currentSize; + + public long photoId; + public long documentId; + public String thumbSize; + + public WebFile webFile; + + public static ImageLocation getForPath(String path) { + if (path == null) { + return null; + } + ImageLocation imageLocation = new ImageLocation(); + imageLocation.path = path; + return imageLocation; + } + + public static ImageLocation getForSecureDocument(SecureDocument secureDocument) { + if (secureDocument == null) { + return null; + } + ImageLocation imageLocation = new ImageLocation(); + imageLocation.secureDocument = secureDocument; + return imageLocation; + } + + public static ImageLocation getForDocument(TLRPC.Document document) { + if (document == null) { + return null; + } + ImageLocation imageLocation = new ImageLocation(); + imageLocation.document = document; + imageLocation.key = document.key; + imageLocation.iv = document.iv; + imageLocation.currentSize = document.size; + return imageLocation; + } + + public static ImageLocation getForWebFile(WebFile webFile) { + if (webFile == null) { + return null; + } + ImageLocation imageLocation = new ImageLocation(); + imageLocation.webFile = webFile; + imageLocation.currentSize = webFile.size; + return imageLocation; + } + + public static ImageLocation getForObject(TLRPC.PhotoSize photoSize, TLObject object) { + if (object instanceof TLRPC.Photo) { + return getForPhoto(photoSize, (TLRPC.Photo) object); + } else if (object instanceof TLRPC.Document) { + return getForDocument(photoSize, (TLRPC.Document) object); + } + return null; + } + + public static ImageLocation getForPhoto(TLRPC.PhotoSize photoSize, TLRPC.Photo photo) { + if (photoSize instanceof TLRPC.TL_photoStrippedSize) { + ImageLocation imageLocation = new ImageLocation(); + imageLocation.photoSize = photoSize; + return imageLocation; + } else if (photoSize == null || photo == null) { + return null; + } + int dc_id; + if (photo.dc_id != 0) { + dc_id = photo.dc_id; + } else { + dc_id = photoSize.location.dc_id; + } + return getForPhoto(photoSize.location, photoSize.size, photo, null, null, false, dc_id, null, photoSize.type); + } + + public static ImageLocation getForUser(TLRPC.User user, boolean big) { + if (user == null || user.access_hash == 0 || user.photo == null) { + return null; + } + TLRPC.FileLocation fileLocation = big ? user.photo.photo_big : user.photo.photo_small; + if (fileLocation == null) { + return null; + } + TLRPC.TL_inputPeerUser inputPeer = new TLRPC.TL_inputPeerUser(); + inputPeer.user_id = user.id; + inputPeer.access_hash = user.access_hash; + int dc_id; + if (user.photo.dc_id != 0) { + dc_id = user.photo.dc_id; + } else { + dc_id = fileLocation.dc_id; + } + return getForPhoto(fileLocation, 0, null, null, inputPeer, big, dc_id, null, null); + } + + public static ImageLocation getForChat(TLRPC.Chat chat, boolean big) { + if (chat == null || chat.photo == null) { + return null; + } + TLRPC.FileLocation fileLocation = big ? chat.photo.photo_big : chat.photo.photo_small; + if (fileLocation == null) { + return null; + } + TLRPC.InputPeer inputPeer; + if (ChatObject.isChannel(chat)) { + if (chat.access_hash == 0) { + return null; + } + inputPeer = new TLRPC.TL_inputPeerChannel(); + inputPeer.channel_id = chat.id; + inputPeer.access_hash = chat.access_hash; + } else { + inputPeer = new TLRPC.TL_inputPeerChat(); + inputPeer.chat_id = chat.id; + } + int dc_id; + if (chat.photo.dc_id != 0) { + dc_id = chat.photo.dc_id; + } else { + dc_id = fileLocation.dc_id; + } + return getForPhoto(fileLocation, 0, null, null, inputPeer, big, dc_id, null, null); + } + + public static ImageLocation getForSticker(TLRPC.PhotoSize photoSize, TLRPC.Document sticker) { + if (photoSize instanceof TLRPC.TL_photoStrippedSize) { + ImageLocation imageLocation = new ImageLocation(); + imageLocation.photoSize = photoSize; + return imageLocation; + } else if (photoSize == null || sticker == null) { + return null; + } + TLRPC.InputStickerSet stickerSet = DataQuery.getInputStickerSet(sticker); + if (stickerSet == null) { + return null; + } + return getForPhoto(photoSize.location, photoSize.size, null, null, null, false, sticker.dc_id, stickerSet, photoSize.type); + } + + public static ImageLocation getForDocument(TLRPC.PhotoSize photoSize, TLRPC.Document document) { + if (photoSize instanceof TLRPC.TL_photoStrippedSize) { + ImageLocation imageLocation = new ImageLocation(); + imageLocation.photoSize = photoSize; + return imageLocation; + } else if (photoSize == null || document == null) { + return null; + } + return getForPhoto(photoSize.location, photoSize.size, null, document, null, false, document.dc_id, null, photoSize.type); + } + + public static ImageLocation getForLocal(TLRPC.FileLocation location) { + if (location == null) { + return null; + } + ImageLocation imageLocation = new ImageLocation(); + imageLocation.location = new TLRPC.TL_fileLocationToBeDeprecated(); + imageLocation.location.local_id = location.local_id; + imageLocation.location.volume_id = location.volume_id; + imageLocation.location.secret = location.secret; + imageLocation.location.dc_id = location.dc_id; + return imageLocation; + } + + private static ImageLocation getForPhoto(TLRPC.FileLocation location, int size, TLRPC.Photo photo, TLRPC.Document document, TLRPC.InputPeer photoPeer, boolean photoPeerBig, int dc_id, TLRPC.InputStickerSet stickerSet, String thumbSize) { + if (location == null || photo == null && photoPeer == null && stickerSet == null && document == null) { + return null; + } + ImageLocation imageLocation = new ImageLocation(); + imageLocation.dc_id = dc_id; + imageLocation.photo = photo; + imageLocation.currentSize = size; + imageLocation.photoPeer = photoPeer; + imageLocation.photoPeerBig = photoPeerBig; + imageLocation.stickerSet = stickerSet; + if (location instanceof TLRPC.TL_fileLocationToBeDeprecated) { + imageLocation.location = (TLRPC.TL_fileLocationToBeDeprecated) location; + if (photo != null) { + imageLocation.file_reference = photo.file_reference; + imageLocation.access_hash = photo.access_hash; + imageLocation.photoId = photo.id; + imageLocation.thumbSize = thumbSize; + } else if (document != null) { + imageLocation.file_reference = document.file_reference; + imageLocation.access_hash = document.access_hash; + imageLocation.documentId = document.id; + imageLocation.thumbSize = thumbSize; + } + } else { + imageLocation.location = new TLRPC.TL_fileLocationToBeDeprecated(); + imageLocation.location.local_id = location.local_id; + imageLocation.location.volume_id = location.volume_id; + imageLocation.location.secret = location.secret; + imageLocation.dc_id = location.dc_id; + imageLocation.file_reference = location.file_reference; + imageLocation.key = location.key; + imageLocation.iv = location.iv; + imageLocation.access_hash = location.secret; + } + return imageLocation; + } + + public static String getStippedKey(Object parentObject, Object fullObject) { + if (parentObject instanceof TLRPC.WebPage) { + if (fullObject instanceof TLRPC.Document) { + TLRPC.Document document = (TLRPC.Document) fullObject; + return "stripped" + FileRefController.getKeyForParentObject(parentObject) + "_" + document.id; + } else if (fullObject instanceof TLRPC.PhotoSize) { + TLRPC.PhotoSize size = (TLRPC.PhotoSize) fullObject; + if (size.location != null) { + return "stripped" + FileRefController.getKeyForParentObject(parentObject) + "_" + size.location.local_id + "_" + size.location.volume_id; + } else { + return "stripped" + FileRefController.getKeyForParentObject(parentObject); + } + } else if (fullObject instanceof TLRPC.FileLocation) { + TLRPC.FileLocation loc = (TLRPC.FileLocation) fullObject; + return "stripped" + FileRefController.getKeyForParentObject(parentObject) + "_" + loc.local_id + "_" + loc.volume_id; + } + } + return "stripped" + FileRefController.getKeyForParentObject(parentObject); + } + + public String getKey(Object parentObject, Object fullObject) { + if (secureDocument != null) { + return secureDocument.secureFile.dc_id + "_" + secureDocument.secureFile.id; + } else if (photoSize instanceof TLRPC.TL_photoStrippedSize) { + if (photoSize.bytes.length > 0) { + return getStippedKey(parentObject, fullObject); + } + } else if (location != null) { + return location.volume_id + "_" + location.local_id; + } else if (webFile != null) { + return Utilities.MD5(webFile.url); + } else if (document != null) { + if (document.id != 0 && document.dc_id != 0) { + return document.dc_id + "_" + document.id; + } + } else if (path != null) { + return Utilities.MD5(path); + } + return null; + } + + public boolean isEncrypted() { + return key != null; + } + + public int getSize() { + if (photoSize != null) { + return photoSize.size; + } else if (secureDocument != null) { + if (secureDocument.secureFile != null) { + return secureDocument.secureFile.size; + } + } else if (document != null) { + return document.size; + } else if (webFile != null) { + return webFile.size; + } + return currentSize; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index d02ceff2c..0ab58efa9 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java @@ -16,14 +16,14 @@ import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; -import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.view.View; -import org.telegram.tgnet.TLObject; +import com.airbnb.lottie.LottieDrawable; + import org.telegram.tgnet.TLRPC; import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.Components.RecyclableDrawable; @@ -85,13 +85,13 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } private class SetImageBackup { - public Object fileLocation; - public String filter; - public Drawable thumb; - public Object thumbLocation; + public ImageLocation imageLocation; + public String imageFilter; + public ImageLocation thumbLocation; public String thumbFilter; - public Object mediaLocation; + public ImageLocation mediaLocation; public String mediaFilter; + public Drawable thumb; public int size; public int cacheType; public Object parentObject; @@ -115,25 +115,25 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg private SetImageBackup setImageBackup; - private Object currentImageLocation; - private String currentImageKey; + private ImageLocation currentImageLocation; private String currentImageFilter; + private String currentImageKey; private int imageTag; private Drawable currentImageDrawable; private BitmapShader imageShader; private int imageOrientation; - private Object currentThumbLocation; - private String currentThumbKey; + private ImageLocation currentThumbLocation; private String currentThumbFilter; + private String currentThumbKey; private int thumbTag; private Drawable currentThumbDrawable; private BitmapShader thumbShader; private int thumbOrientation; - private Object currentMediaLocation; - private String currentMediaKey; + private ImageLocation currentMediaLocation; private String currentMediaFilter; + private String currentMediaKey; private int mediaTag; private Drawable currentMediaDrawable; private BitmapShader mediaShader; @@ -145,6 +145,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg private int currentSize; private int currentCacheType; private boolean allowStartAnimation = true; + private boolean useSharedAnimationQueue; private boolean allowDecodeSingleFrame; private boolean crossfadeWithOldImage; @@ -160,7 +161,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg private boolean invalidateAll; private int imageX, imageY, imageW, imageH; - private Rect drawRegion = new Rect(); + private float sideClip; + private RectF drawRegion = new RectF(); private boolean isVisible = true; private boolean isAspectFit; private boolean forcePreview; @@ -206,92 +208,51 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg return forceLoding; } - public void setImage(TLObject path, String filter, Drawable thumb, String ext, Object parentObject, int cacheType) { - setImage(path, filter, thumb, null, null, 0, ext, parentObject, cacheType); + public void setImage(ImageLocation imageLocation, String imageFilter, Drawable thumb, String ext, Object parentObject, int cacheType) { + setImage(imageLocation, imageFilter, null, null, thumb, 0, ext, parentObject, cacheType); } - public void setImage(TLObject path, String filter, Drawable thumb, int size, String ext, Object parentObject, int cacheType) { - setImage(path, filter, thumb, null, null, size, ext, parentObject, cacheType); + public void setImage(ImageLocation imageLocation, String imageFilter, Drawable thumb, int size, String ext, Object parentObject, int cacheType) { + setImage(imageLocation, imageFilter, null, null, thumb, size, ext, parentObject, cacheType); } - public void setImage(String httpUrl, String filter, Drawable thumb, String ext, int size) { - setImage(httpUrl, filter, thumb, null, null, size, ext, null, 1); + public void setImage(String imagePath, String imageFilter, Drawable thumb, String ext, int size) { + setImage(ImageLocation.getForPath(imagePath), imageFilter, null, null, thumb, size, ext, null, 1); } - public void setImage(TLObject fileLocation, String filter, TLObject thumbLocation, String thumbFilter, String ext, Object parentObject, int cacheType) { - setImage(fileLocation, filter, null, thumbLocation, thumbFilter, 0, ext, parentObject, cacheType); + public void setImage(ImageLocation imageLocation, String imageFilter, ImageLocation thumbLocation, String thumbFilter, String ext, Object parentObject, int cacheType) { + setImage(imageLocation, imageFilter, thumbLocation, thumbFilter, null, 0, ext, parentObject, cacheType); } - public void setImage(Object fileLocation, String filter, TLObject thumbLocation, String thumbFilter, int size, String ext, Object parentObject, int cacheType) { - setImage(fileLocation, filter, null, thumbLocation, thumbFilter, size, ext, parentObject, cacheType); + public void setImage(ImageLocation imageLocation, String imageFilter, ImageLocation thumbLocation, String thumbFilter, int size, String ext, Object parentObject, int cacheType) { + setImage(imageLocation, imageFilter, thumbLocation, thumbFilter, null, size, ext, parentObject, cacheType); } - public void setImage(Object fileLocation, String filter, Drawable thumb, Object thumbLocation, String thumbFilter, int size, String ext, Object parentObject, int cacheType) { - setImage(null, null, fileLocation, filter, thumb, thumbLocation, thumbFilter, size, ext, parentObject, cacheType); + public void setImage(ImageLocation fileLocation, String fileFilter, ImageLocation thumbLocation, String thumbFilter, Drawable thumb, int size, String ext, Object parentObject, int cacheType) { + setImage(null, null, fileLocation, fileFilter, thumbLocation, thumbFilter, thumb, size, ext, parentObject, cacheType); } - private String getLocationKey(Object fileLocation, Object parentObject) { - if (fileLocation instanceof SecureDocument) { - SecureDocument document = (SecureDocument) fileLocation; - return document.secureFile.dc_id + "_" + document.secureFile.id; - } else if (fileLocation instanceof TLRPC.FileLocation) { - TLRPC.FileLocation location = (TLRPC.FileLocation) fileLocation; - return location.volume_id + "_" + location.local_id; - } else if (fileLocation instanceof TLRPC.TL_photoStrippedSize) { - TLRPC.TL_photoStrippedSize location = (TLRPC.TL_photoStrippedSize) fileLocation; - if (location.bytes.length > 0) { - return "stripped" + FileRefController.getKeyForParentObject(parentObject); - } - } else if (fileLocation instanceof TLRPC.TL_photoSize || fileLocation instanceof TLRPC.TL_photoCachedSize) { - TLRPC.PhotoSize photoSize = (TLRPC.PhotoSize) fileLocation; - return photoSize.location.volume_id + "_" + photoSize.location.local_id; - } else if (fileLocation instanceof WebFile) { - WebFile location = (WebFile) fileLocation; - return Utilities.MD5(location.url); - } else if (fileLocation instanceof TLRPC.Document) { - TLRPC.Document location = (TLRPC.Document) fileLocation; - if (location.dc_id != 0) { - return location.dc_id + "_" + location.id; - } - } else if (fileLocation instanceof String) { - return Utilities.MD5((String) fileLocation); - } - return null; - } - - private boolean isInvalidLocation(Object fileLocation) { - return fileLocation != null && - !(fileLocation instanceof TLRPC.TL_fileLocation) - && !(fileLocation instanceof TLRPC.TL_fileEncryptedLocation) - && !(fileLocation instanceof TLRPC.TL_document) - && !(fileLocation instanceof WebFile) - && !(fileLocation instanceof TLRPC.TL_documentEncrypted) - && !(fileLocation instanceof TLRPC.PhotoSize) - && !(fileLocation instanceof SecureDocument) - && !(fileLocation instanceof String); - } - - public void setImage(Object mediaLocation, String mediaFilter, Object fileLocation, String imageFilter, Drawable thumb, Object thumbLocation, String thumbFilter, int size, String ext, Object parentObject, int cacheType) { + public void setImage(ImageLocation mediaLocation, String mediaFilter, ImageLocation imageLocation, String imageFilter, ImageLocation thumbLocation, String thumbFilter, Drawable thumb, int size, String ext, Object parentObject, int cacheType) { if (setImageBackup != null) { - setImageBackup.fileLocation = null; + setImageBackup.imageLocation = null; setImageBackup.thumbLocation = null; setImageBackup.mediaLocation = null; setImageBackup.thumb = null; } - if ((fileLocation == null && thumbLocation == null && mediaLocation == null) || isInvalidLocation(fileLocation) || isInvalidLocation(mediaLocation)) { + if (imageLocation == null && thumbLocation == null && mediaLocation == null) { for (int a = 0; a < 4; a++) { recycleBitmap(null, a); } currentImageLocation = null; - currentImageKey = null; currentImageFilter = null; + currentImageKey = null; currentMediaLocation = null; - currentMediaKey = null; currentMediaFilter = null; + currentMediaKey = null; currentThumbLocation = null; - currentThumbKey = null; currentThumbFilter = null; + currentThumbKey = null; currentMediaDrawable = null; mediaShader = null; @@ -320,12 +281,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } return; } - if (isInvalidLocation(thumbLocation)) { - thumbLocation = null; - } - String imageKey = getLocationKey(fileLocation, parentObject); - if (imageKey == null && fileLocation != null) { - fileLocation = null; + String imageKey = imageLocation != null ? imageLocation.getKey(parentObject, null) : null; + if (imageKey == null && imageLocation != null) { + imageLocation = null; } currentKeyQuality = false; if (imageKey == null && needsQualityThumb && (parentObject instanceof MessageObject || qulityThumbDocument != null)) { @@ -339,7 +297,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg imageKey += "@" + imageFilter; } - String mediaKey = getLocationKey(mediaLocation, parentObject); + String mediaKey = mediaLocation != null ? mediaLocation.getKey(parentObject, null) : null; if (mediaKey == null && mediaLocation != null) { mediaLocation = null; } @@ -356,7 +314,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } } - String thumbKey = getLocationKey(thumbLocation, parentObject); + String thumbKey = thumbLocation != null ? thumbLocation.getKey(parentObject, mediaLocation != null ? mediaLocation : imageLocation) : null; if (thumbKey != null && thumbFilter != null) { thumbKey += "@" + thumbFilter; } @@ -408,15 +366,15 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg crossfadeShader = null; } - currentImageLocation = fileLocation; - currentImageKey = imageKey; + currentImageLocation = imageLocation; currentImageFilter = imageFilter; + currentImageKey = imageKey; currentMediaLocation = mediaLocation; - currentMediaKey = mediaKey; currentMediaFilter = mediaFilter; + currentMediaKey = mediaKey; currentThumbLocation = thumbLocation; - currentThumbKey = thumbKey; currentThumbFilter = thumbFilter; + currentThumbKey = thumbKey; currentParentObject = parentObject; currentExt = ext; @@ -542,6 +500,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg if (bitmap instanceof AnimatedFileDrawable) { AnimatedFileDrawable fileDrawable = (AnimatedFileDrawable) bitmap; fileDrawable.setParentView(parentView); + fileDrawable.setUseSharedQueue(useSharedAnimationQueue); if (allowStartAnimation) { fileDrawable.start(); } @@ -559,20 +518,20 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg thumbShader = null; } currentMediaLocation = null; + currentMediaFilter = null; currentMediaDrawable = null; currentMediaKey = null; - currentMediaFilter = null; mediaShader = null; currentImageLocation = null; + currentImageFilter = null; currentImageDrawable = null; currentImageKey = null; - currentImageFilter = null; imageShader = null; currentThumbLocation = null; - currentThumbKey = null; currentThumbFilter = null; + currentThumbKey = null; currentKeyQuality = false; currentExt = null; @@ -581,7 +540,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg currentAlpha = 1; if (setImageBackup != null) { - setImageBackup.fileLocation = null; + setImageBackup.imageLocation = null; setImageBackup.thumbLocation = null; setImageBackup.mediaLocation = null; setImageBackup.thumb = null; @@ -618,11 +577,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } setImageBackup.mediaLocation = currentMediaLocation; setImageBackup.mediaFilter = currentMediaFilter; - setImageBackup.fileLocation = currentImageLocation; - setImageBackup.filter = currentImageFilter; - setImageBackup.thumb = staticThumbDrawable; + setImageBackup.imageLocation = currentImageLocation; + setImageBackup.imageFilter = currentImageFilter; setImageBackup.thumbLocation = currentThumbLocation; setImageBackup.thumbFilter = currentThumbFilter; + setImageBackup.thumb = staticThumbDrawable; setImageBackup.size = currentSize; setImageBackup.ext = currentExt; setImageBackup.cacheType = currentCacheType; @@ -634,8 +593,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg public boolean onAttachedToWindow() { NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didReplacedPhotoInMemCache); - if (setImageBackup != null && (setImageBackup.fileLocation != null || setImageBackup.thumbLocation != null || setImageBackup.mediaLocation != null || setImageBackup.thumb != null)) { - setImage(setImageBackup.mediaLocation, setImageBackup.mediaFilter, setImageBackup.fileLocation, setImageBackup.filter, setImageBackup.thumb, setImageBackup.thumbLocation, setImageBackup.thumbFilter, setImageBackup.size, setImageBackup.ext, setImageBackup.parentObject, setImageBackup.cacheType); + if (setImageBackup != null && (setImageBackup.imageLocation != null || setImageBackup.thumbLocation != null || setImageBackup.mediaLocation != null || setImageBackup.thumb != null)) { + setImage(setImageBackup.mediaLocation, setImageBackup.mediaFilter, setImageBackup.imageLocation, setImageBackup.imageFilter, setImageBackup.thumbLocation, setImageBackup.thumbFilter, setImageBackup.thumb, setImageBackup.size, setImageBackup.ext, setImageBackup.parentObject, setImageBackup.cacheType); return true; } return false; @@ -699,36 +658,65 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg bitmapH = bitmapDrawable.getBitmap().getHeight(); } } - float scaleW = bitmapW / (float) imageW; - float scaleH = bitmapH / (float) imageH; + float realImageW = imageW - sideClip * 2; + float realImageH = imageH - sideClip * 2; + float scaleW = imageW == 0 ? 1.0f : (bitmapW / realImageW); + float scaleH = imageH == 0 ? 1.0f : (bitmapH / realImageH); + if (shader != null) { - roundPaint.setShader(shader); - float scale = Math.min(scaleW, scaleH); - roundRect.set(imageX, imageY, imageX + imageW, imageY + imageH); - shaderMatrix.reset(); - if (Math.abs(scaleW - scaleH) > 0.0005f) { - if (bitmapW / scaleH > imageW) { - drawRegion.set(imageX - ((int) (bitmapW / scaleH) - imageW) / 2, imageY, imageX + ((int) (bitmapW / scaleH) + imageW) / 2, imageY + imageH); - } else { - drawRegion.set(imageX, imageY - ((int) (bitmapH / scaleW) - imageH) / 2, imageX + imageW, imageY + ((int) (bitmapH / scaleW) + imageH) / 2); + if (isAspectFit) { + float scale = Math.max(scaleW, scaleH); + bitmapW /= scale; + bitmapH /= scale; + drawRegion.set(imageX + (imageW - bitmapW) / 2, imageY + (imageH - bitmapH) / 2, imageX + (imageW + bitmapW) / 2, imageY + (imageH + bitmapH) / 2); + + if (isVisible) { + roundPaint.setShader(shader); + shaderMatrix.reset(); + shaderMatrix.setTranslate(drawRegion.left, drawRegion.top); + shaderMatrix.preScale(1.0f / scale, 1.0f / scale); + + shader.setLocalMatrix(shaderMatrix); + roundPaint.setAlpha(alpha); + roundRect.set(drawRegion); + canvas.drawRoundRect(roundRect, roundRadius, roundRadius, roundPaint); } } else { - drawRegion.set(imageX, imageY, imageX + imageW, imageY + imageH); - } - if (isVisible) { + roundPaint.setShader(shader); + float scale = 1.0f / Math.min(scaleW, scaleH); + roundRect.set(imageX + sideClip, imageY + sideClip, imageX + imageW - sideClip, imageY + imageH - sideClip); + shaderMatrix.reset(); if (Math.abs(scaleW - scaleH) > 0.0005f) { - int w = (int) Math.ceil(imageW * scale); - int h = (int) Math.ceil(imageH * scale); - bitmapRect.set((bitmapW - w) / 2, (bitmapH - h) / 2, (bitmapW + w) / 2, (bitmapH + h) / 2); - shaderMatrix.setRectToRect(bitmapRect, roundRect, Matrix.ScaleToFit.START); + if (bitmapW / scaleH > realImageW) { + bitmapW /= scaleH; + drawRegion.set(imageX - (bitmapW - realImageW) / 2, imageY, imageX + (bitmapW + realImageW) / 2, imageY + realImageH); + } else { + bitmapH /= scaleW; + drawRegion.set(imageX, imageY - (bitmapH - realImageH) / 2, imageX + realImageW, imageY + (bitmapH + realImageH) / 2); + } } else { - bitmapRect.set(0, 0, bitmapW, bitmapH); - shaderMatrix.setRectToRect(bitmapRect, roundRect, Matrix.ScaleToFit.FILL); + drawRegion.set(imageX, imageY, imageX + realImageW, imageY + realImageH); + } + if (isVisible) { + shaderMatrix.reset(); + shaderMatrix.setTranslate(drawRegion.left, drawRegion.top); + if (orientation == 90) { + shaderMatrix.preRotate(90); + shaderMatrix.preTranslate(0, -drawRegion.width()); + } else if (orientation == 180) { + shaderMatrix.preRotate(180); + shaderMatrix.preTranslate(-drawRegion.width(), -drawRegion.height()); + } else if (orientation == 270) { + shaderMatrix.preRotate(270); + shaderMatrix.preTranslate(-drawRegion.height(), 0); + } + shaderMatrix.preScale(scale, scale); + + shader.setLocalMatrix(shaderMatrix); + roundPaint.setAlpha(alpha); + canvas.drawRoundRect(roundRect, roundRadius, roundRadius, roundPaint); } - shader.setLocalMatrix(shaderMatrix); - roundPaint.setAlpha(alpha); - canvas.drawRoundRect(roundRect, roundRadius, roundRadius, roundPaint); } } else { if (isAspectFit) { @@ -736,8 +724,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg canvas.save(); bitmapW /= scale; bitmapH /= scale; - drawRegion.set(imageX + (imageW - bitmapW) / 2, imageY + (imageH - bitmapH) / 2, imageX + (imageW + bitmapW) / 2, imageY + (imageH + bitmapH) / 2); - bitmapDrawable.setBounds(drawRegion); + drawRegion.set(imageX + (imageW - bitmapW) / 2.0f, imageY + (imageH - bitmapH) / 2.0f, imageX + (imageW + bitmapW) / 2.0f, imageY + (imageH + bitmapH) / 2.0f); + bitmapDrawable.setBounds((int) drawRegion.left, (int) drawRegion.top, (int) drawRegion.right, (int) drawRegion.bottom); + if (bitmapDrawable instanceof AnimatedFileDrawable) { + ((AnimatedFileDrawable) bitmapDrawable).setActualDrawRect(drawRegion.left, drawRegion.top, drawRegion.width(), drawRegion.height()); + } if (isVisible) { try { bitmapDrawable.setAlpha(alpha); @@ -763,22 +754,22 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg if (bitmapW / scaleH > imageW) { bitmapW /= scaleH; - drawRegion.set(imageX - (bitmapW - imageW) / 2, imageY, imageX + (bitmapW + imageW) / 2, imageY + imageH); + drawRegion.set(imageX - (bitmapW - imageW) / 2.0f, imageY, imageX + (bitmapW + imageW) / 2.0f, imageY + imageH); } else { bitmapH /= scaleW; - drawRegion.set(imageX, imageY - (bitmapH - imageH) / 2, imageX + imageW, imageY + (bitmapH + imageH) / 2); + drawRegion.set(imageX, imageY - (bitmapH - imageH) / 2.0f, imageX + imageW, imageY + (bitmapH + imageH) / 2.0f); } if (bitmapDrawable instanceof AnimatedFileDrawable) { ((AnimatedFileDrawable) bitmapDrawable).setActualDrawRect(imageX, imageY, imageW, imageH); } if (orientation % 360 == 90 || orientation % 360 == 270) { - int width = (drawRegion.right - drawRegion.left) / 2; - int height = (drawRegion.bottom - drawRegion.top) / 2; - int centerX = (drawRegion.right + drawRegion.left) / 2; - int centerY = (drawRegion.top + drawRegion.bottom) / 2; - bitmapDrawable.setBounds(centerX - height, centerY - width, centerX + height, centerY + width); + float width = drawRegion.width() / 2; + float height = drawRegion.height() / 2; + float centerX = drawRegion.centerX(); + float centerY = drawRegion.centerY(); + bitmapDrawable.setBounds((int) (centerX - height), (int) (centerY - width), (int) (centerX + height), (int) (centerY + width)); } else { - bitmapDrawable.setBounds(drawRegion); + bitmapDrawable.setBounds((int) drawRegion.left, (int) drawRegion.top, (int) drawRegion.right, (int) drawRegion.bottom); } if (isVisible) { try { @@ -805,13 +796,13 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg ((AnimatedFileDrawable) bitmapDrawable).setActualDrawRect(imageX, imageY, imageW, imageH); } if (orientation % 360 == 90 || orientation % 360 == 270) { - int width = (drawRegion.right - drawRegion.left) / 2; - int height = (drawRegion.bottom - drawRegion.top) / 2; - int centerX = (drawRegion.right + drawRegion.left) / 2; - int centerY = (drawRegion.top + drawRegion.bottom) / 2; - bitmapDrawable.setBounds(centerX - height, centerY - width, centerX + height, centerY + width); + float width = drawRegion.width() / 2; + float height = drawRegion.height() / 2; + float centerX = drawRegion.centerX(); + float centerY = drawRegion.centerY(); + bitmapDrawable.setBounds((int) (centerX - height), (int) (centerY - width), (int) (centerX + height), (int) (centerY + width)); } else { - bitmapDrawable.setBounds(drawRegion); + bitmapDrawable.setBounds((int) drawRegion.left, (int) drawRegion.top, (int) drawRegion.right, (int) drawRegion.bottom); } if (isVisible) { try { @@ -828,14 +819,41 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } } else { drawRegion.set(imageX, imageY, imageX + imageW, imageY + imageH); - drawable.setBounds(drawRegion); + drawable.setBounds((int) drawRegion.left, (int) drawRegion.top, (int) drawRegion.right, (int) drawRegion.bottom); if (isVisible) { + if (drawable instanceof LottieDrawable) { + canvas.save(); + float tx = imageX; + float ty = imageY; + int bitmapWidth = getBitmapWidth(); + int bitmapHeight = getBitmapHeight(); + float scale; + if (bitmapWidth > imageW || bitmapHeight > imageH) { + scale = Math.min(imageW / (float) bitmapWidth, imageH / (float) bitmapHeight); + bitmapWidth *= scale; + bitmapHeight *= scale; + canvas.scale(scale, scale); + } else { + scale = 1.0f; + } + canvas.translate((imageX + (imageW - bitmapWidth) / 2) / scale, (imageY + (imageH - bitmapHeight) / 2) / scale); + if (parentView != null) { + if (invalidateAll) { + parentView.invalidate(); + } else { + parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); + } + } + } try { drawable.setAlpha(alpha); drawable.draw(canvas); } catch (Exception e) { FileLog.e(e); } + if (drawable instanceof LottieDrawable) { + canvas.restore(); + } } } } @@ -851,7 +869,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg ImageLoader.getInstance().removeImage(currentThumbKey); currentThumbKey = null; } - setImage(currentMediaLocation, currentMediaFilter, currentImageLocation, currentImageFilter, currentThumbDrawable, currentThumbLocation, currentThumbFilter, currentSize, currentExt, currentParentObject, currentCacheType); + setImage(currentMediaLocation, currentMediaFilter, currentImageLocation, currentImageFilter, currentThumbLocation, currentThumbFilter, currentThumbDrawable, currentSize, currentExt, currentParentObject, currentCacheType); } private void checkAlphaAnimation(boolean skip) { @@ -1059,6 +1077,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } public int getBitmapWidth() { + Drawable drawable = getDrawable(); + if (drawable instanceof LottieDrawable) { + return drawable.getIntrinsicWidth(); + } AnimatedFileDrawable animation = getAnimation(); if (animation != null) { return imageOrientation % 360 == 0 || imageOrientation % 360 == 180 ? animation.getIntrinsicWidth() : animation.getIntrinsicHeight(); @@ -1074,6 +1096,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } public int getBitmapHeight() { + Drawable drawable = getDrawable(); + if (drawable instanceof LottieDrawable) { + return drawable.getIntrinsicHeight(); + } AnimatedFileDrawable animation = getAnimation(); if (animation != null) { return imageOrientation % 360 == 0 || imageOrientation % 360 == 180 ? animation.getIntrinsicHeight() : animation.getIntrinsicWidth(); @@ -1165,6 +1191,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg imageH = height; } + public void setSideClip(float value) { + sideClip = value; + } + public float getCenterX() { return imageX + imageW / 2.0f; } @@ -1198,7 +1228,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } public float getImageAspectRatio() { - return imageOrientation % 180 != 0 ? drawRegion.height() / (float) drawRegion.width() : drawRegion.width() / (float) drawRegion.height(); + return imageOrientation % 180 != 0 ? drawRegion.height() / drawRegion.width() : drawRegion.width() / drawRegion.height(); } public String getExt() { @@ -1209,7 +1239,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg return x >= imageX && x <= imageX + imageW && y >= imageY && y <= imageY + imageH; } - public Rect getDrawRegion() { + public RectF getDrawRegion() { return drawRegion; } @@ -1217,42 +1247,42 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg return currentImageKey; } - public String getImageFilter() { - return currentImageFilter; - } - public String getMediaKey() { return currentMediaKey; } - public String getMediaFilter() { - return currentMediaFilter; - } - public String getThumbKey() { return currentThumbKey; } - public String getThumbFilter() { - return currentThumbFilter; - } - public int getSize() { return currentSize; } - public Object getMediaLocation() { + public ImageLocation getMediaLocation() { return currentMediaLocation; } - public Object getImageLocation() { + public ImageLocation getImageLocation() { return currentImageLocation; } - public Object getThumbLocation() { + public ImageLocation getThumbLocation() { return currentThumbLocation; } + public String getMediaFilter() { + return currentMediaFilter; + } + + public String getImageFilter() { + return currentImageFilter; + } + + public String getThumbFilter() { + return currentThumbFilter; + } + public int getCacheType() { return currentCacheType; } @@ -1329,6 +1359,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg allowDecodeSingleFrame = value; } + public void setUseSharedAnimationQueue(boolean value) { + useSharedAnimationQueue = value; + } + public boolean isAllowStartAnimation() { return allowStartAnimation; } @@ -1336,6 +1370,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg public void startAnimation() { AnimatedFileDrawable animation = getAnimation(); if (animation != null) { + animation.setUseSharedQueue(useSharedAnimationQueue); animation.start(); } } @@ -1394,27 +1429,28 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg return param; } - protected boolean setImageBitmapByKey(BitmapDrawable bitmap, String key, int type, boolean memCache) { - if (bitmap == null || key == null) { + protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, boolean memCache) { + if (drawable == null || key == null) { return false; } if (type == TYPE_IMAGE) { if (!key.equals(currentImageKey)) { return false; } - if (!(bitmap instanceof AnimatedFileDrawable)) { + if (!(drawable instanceof AnimatedFileDrawable)) { ImageLoader.getInstance().incrementUseCount(currentImageKey); } - currentImageDrawable = bitmap; - if (bitmap instanceof ExtendedBitmapDrawable) { - imageOrientation = ((ExtendedBitmapDrawable) bitmap).getOrientation(); + currentImageDrawable = drawable; + if (drawable instanceof ExtendedBitmapDrawable) { + imageOrientation = ((ExtendedBitmapDrawable) drawable).getOrientation(); } - if (roundRadius != 0 && bitmap instanceof BitmapDrawable) { - if (bitmap instanceof AnimatedFileDrawable) { - ((AnimatedFileDrawable) bitmap).setRoundRadius(roundRadius); + if (roundRadius != 0 && drawable instanceof BitmapDrawable) { + if (drawable instanceof AnimatedFileDrawable) { + AnimatedFileDrawable animatedFileDrawable = (AnimatedFileDrawable) drawable; + animatedFileDrawable.setRoundRadius(roundRadius); } else { - Bitmap object = bitmap.getBitmap(); - imageShader = new BitmapShader(object, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; + imageShader = new BitmapShader(bitmapDrawable.getBitmap(), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); } } else { imageShader = null; @@ -1437,16 +1473,17 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg if (!key.equals(currentMediaKey)) { return false; } - if (!(bitmap instanceof AnimatedFileDrawable)) { + if (!(drawable instanceof AnimatedFileDrawable)) { ImageLoader.getInstance().incrementUseCount(currentMediaKey); } - currentMediaDrawable = bitmap; - if (roundRadius != 0 && bitmap instanceof BitmapDrawable) { - if (bitmap instanceof AnimatedFileDrawable) { - ((AnimatedFileDrawable) bitmap).setRoundRadius(roundRadius); + currentMediaDrawable = drawable; + if (roundRadius != 0 && drawable instanceof BitmapDrawable) { + if (drawable instanceof AnimatedFileDrawable) { + AnimatedFileDrawable animatedFileDrawable = (AnimatedFileDrawable) drawable; + animatedFileDrawable.setRoundRadius(roundRadius); } else { - Bitmap object = bitmap.getBitmap(); - mediaShader = new BitmapShader(object, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; + mediaShader = new BitmapShader(bitmapDrawable.getBitmap(), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); } } else { mediaShader = null; @@ -1481,17 +1518,18 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } ImageLoader.getInstance().incrementUseCount(currentThumbKey); - currentThumbDrawable = bitmap; - if (bitmap instanceof ExtendedBitmapDrawable) { - thumbOrientation = ((ExtendedBitmapDrawable) bitmap).getOrientation(); + currentThumbDrawable = drawable; + if (drawable instanceof ExtendedBitmapDrawable) { + thumbOrientation = ((ExtendedBitmapDrawable) drawable).getOrientation(); } - if (roundRadius != 0 && bitmap instanceof BitmapDrawable) { - if (bitmap instanceof AnimatedFileDrawable) { - ((AnimatedFileDrawable) bitmap).setRoundRadius(roundRadius); + if (roundRadius != 0 && drawable instanceof BitmapDrawable) { + if (drawable instanceof AnimatedFileDrawable) { + AnimatedFileDrawable animatedFileDrawable = (AnimatedFileDrawable) drawable; + animatedFileDrawable.setRoundRadius(roundRadius); } else { - Bitmap object = bitmap.getBitmap(); - thumbShader = new BitmapShader(object, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; + thumbShader = new BitmapShader(bitmapDrawable.getBitmap(), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); } } else { thumbShader = null; @@ -1509,9 +1547,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg currentAlpha = 1.0f; } } - if (bitmap instanceof AnimatedFileDrawable) { - AnimatedFileDrawable fileDrawable = (AnimatedFileDrawable) bitmap; + if (drawable instanceof AnimatedFileDrawable) { + AnimatedFileDrawable fileDrawable = (AnimatedFileDrawable) drawable; fileDrawable.setParentView(parentView); + fileDrawable.setUseSharedQueue(useSharedAnimationQueue); if (allowStartAnimation) { fileDrawable.start(); } @@ -1588,23 +1627,23 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg String oldKey = (String) args[0]; if (currentMediaKey != null && currentMediaKey.equals(oldKey)) { currentMediaKey = (String) args[1]; - currentMediaLocation = args[2]; + currentMediaLocation = (ImageLocation) args[2]; if (setImageBackup != null) { - setImageBackup.mediaLocation = args[2]; + setImageBackup.mediaLocation = (ImageLocation) args[2]; } } if (currentImageKey != null && currentImageKey.equals(oldKey)) { currentImageKey = (String) args[1]; - currentImageLocation = args[2]; + currentImageLocation = (ImageLocation) args[2]; if (setImageBackup != null) { - setImageBackup.fileLocation = args[2]; + setImageBackup.imageLocation = (ImageLocation) args[2]; } } if (currentThumbKey != null && currentThumbKey.equals(oldKey)) { currentThumbKey = (String) args[1]; - currentThumbLocation = args[2]; + currentThumbLocation = (ImageLocation) args[2]; if (setImageBackup != null) { - setImageBackup.thumbLocation = args[2]; + setImageBackup.thumbLocation = (ImageLocation) args[2]; } } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java index 8ed50a750..06257627a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java @@ -77,6 +77,7 @@ public class LocaleController { private HashMap currencyValues; private HashMap translitChars; + private HashMap ruTranslitChars; private class TimeZoneChangedReceiver extends BroadcastReceiver { @Override @@ -1812,6 +1813,8 @@ public class LocaleController { if (localeInfo.hasBaseLang()) { TLRPC.TL_langpack_getDifference req = new TLRPC.TL_langpack_getDifference(); req.from_version = localeInfo.baseVersion; + req.lang_code = localeInfo.getBaseLangCode(); + req.lang_pack = ""; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (response != null) { AndroidUtilities.runOnUIThread(() -> saveRemoteLocaleStrings(localeInfo, (TLRPC.TL_langPackDifference) response, currentAccount)); @@ -1832,6 +1835,8 @@ public class LocaleController { if (localeInfo.version != 0 && !force) { TLRPC.TL_langpack_getDifference req = new TLRPC.TL_langpack_getDifference(); req.from_version = localeInfo.version; + req.lang_code = localeInfo.getLangCode(); + req.lang_pack = ""; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (response != null) { AndroidUtilities.runOnUIThread(() -> saveRemoteLocaleStrings(localeInfo, (TLRPC.TL_langPackDifference) response, currentAccount)); @@ -1853,15 +1858,57 @@ public class LocaleController { } public String getTranslitString(String src) { - return getTranslitString(src, false); + return getTranslitString(src, true, false); } public String getTranslitString(String src, boolean onlyEnglish) { + return getTranslitString(src, true, onlyEnglish); + } + + public String getTranslitString(String src, boolean ru, boolean onlyEnglish) { if (src == null) { return null; } + + if (ruTranslitChars == null) { + ruTranslitChars = new HashMap<>(33); + ruTranslitChars.put("а", "a"); + ruTranslitChars.put("б", "b"); + ruTranslitChars.put("в", "v"); + ruTranslitChars.put("г", "g"); + ruTranslitChars.put("д", "d"); + ruTranslitChars.put("е", "e"); + ruTranslitChars.put("ё", "yo"); + ruTranslitChars.put("ж", "zh"); + ruTranslitChars.put("з", "z"); + ruTranslitChars.put("и", "i"); + ruTranslitChars.put("й", "i"); + ruTranslitChars.put("к", "k"); + ruTranslitChars.put("л", "l"); + ruTranslitChars.put("м", "m"); + ruTranslitChars.put("н", "n"); + ruTranslitChars.put("о", "o"); + ruTranslitChars.put("п", "p"); + ruTranslitChars.put("р", "r"); + ruTranslitChars.put("с", "s"); + ruTranslitChars.put("т", "t"); + ruTranslitChars.put("у", "u"); + ruTranslitChars.put("ф", "f"); + ruTranslitChars.put("х", "h"); + ruTranslitChars.put("ц", "ts"); + ruTranslitChars.put("ч", "ch"); + ruTranslitChars.put("ш", "sh"); + ruTranslitChars.put("щ", "sch"); + ruTranslitChars.put("ы", "i"); + ruTranslitChars.put("ь", ""); + ruTranslitChars.put("ъ", ""); + ruTranslitChars.put("э", "e"); + ruTranslitChars.put("ю", "yu"); + ruTranslitChars.put("я", "ya"); + } + if (translitChars == null) { - translitChars = new HashMap<>(520); + translitChars = new HashMap<>(487); translitChars.put("ȼ", "c"); translitChars.put("ᶇ", "n"); translitChars.put("ɖ", "d"); @@ -1901,7 +1948,6 @@ public class LocaleController { translitChars.put("ɟ", "j"); translitChars.put("ẚ", "a"); translitChars.put("ɏ", "y"); - translitChars.put("л", "l"); translitChars.put("ʌ", "v"); translitChars.put("ꝓ", "p"); translitChars.put("fi", "fi"); @@ -1909,7 +1955,6 @@ public class LocaleController { translitChars.put("ḏ", "d"); translitChars.put("ᴌ", "l"); translitChars.put("ė", "e"); - translitChars.put("ё", "yo"); translitChars.put("ᴋ", "k"); translitChars.put("ċ", "c"); translitChars.put("ʁ", "r"); @@ -1950,7 +1995,6 @@ public class LocaleController { translitChars.put("ṩ", "s"); translitChars.put("ɽ", "r"); translitChars.put("ĝ", "g"); - translitChars.put("в", "v"); translitChars.put("ᴝ", "u"); translitChars.put("ḳ", "k"); translitChars.put("ꝫ", "et"); @@ -1961,7 +2005,6 @@ public class LocaleController { translitChars.put("ꜹ", "av"); translitChars.put("û", "u"); translitChars.put("æ", "ae"); - translitChars.put("и", "i"); translitChars.put("ă", "a"); translitChars.put("ǘ", "u"); translitChars.put("ꞅ", "s"); @@ -1989,7 +2032,6 @@ public class LocaleController { translitChars.put("ū", "u"); translitChars.put("ḃ", "b"); translitChars.put("ṗ", "p"); - translitChars.put("ь", ""); translitChars.put("å", "a"); translitChars.put("ɕ", "c"); translitChars.put("ọ", "o"); @@ -2007,7 +2049,6 @@ public class LocaleController { translitChars.put("ḓ", "d"); translitChars.put("ȇ", "e"); translitChars.put("ȕ", "u"); - translitChars.put("п", "p"); translitChars.put("ȵ", "n"); translitChars.put("ʠ", "q"); translitChars.put("ấ", "a"); @@ -2020,11 +2061,9 @@ public class LocaleController { translitChars.put("ṫ", "t"); translitChars.put("ꝗ", "q"); translitChars.put("ậ", "a"); - translitChars.put("н", "n"); translitChars.put("ʄ", "j"); translitChars.put("ƚ", "l"); translitChars.put("ᶂ", "f"); - translitChars.put("д", "d"); translitChars.put("ᵴ", "s"); translitChars.put("ꞃ", "r"); translitChars.put("ᶌ", "v"); @@ -2069,7 +2108,6 @@ public class LocaleController { translitChars.put("ď", "d"); translitChars.put("ᵯ", "m"); translitChars.put("ỵ", "y"); - translitChars.put("я", "ya"); translitChars.put("ŵ", "w"); translitChars.put("ề", "e"); translitChars.put("ứ", "u"); @@ -2078,13 +2116,11 @@ public class LocaleController { translitChars.put("ḍ", "d"); translitChars.put("ŭ", "u"); translitChars.put("ʝ", "j"); - translitChars.put("ж", "zh"); translitChars.put("ê", "e"); translitChars.put("ǚ", "u"); translitChars.put("ġ", "g"); translitChars.put("ṙ", "r"); translitChars.put("ƞ", "n"); - translitChars.put("ъ", ""); translitChars.put("ḗ", "e"); translitChars.put("ẝ", "s"); translitChars.put("ᶁ", "d"); @@ -2094,12 +2130,10 @@ public class LocaleController { translitChars.put("ợ", "o"); translitChars.put("ḿ", "m"); translitChars.put("ꜰ", "f"); - translitChars.put("а", "a"); translitChars.put("ẵ", "a"); translitChars.put("ꝏ", "oo"); translitChars.put("ᶆ", "m"); translitChars.put("ᵽ", "p"); - translitChars.put("ц", "ts"); translitChars.put("ữ", "u"); translitChars.put("ⱪ", "k"); translitChars.put("ḥ", "h"); @@ -2113,7 +2147,6 @@ public class LocaleController { translitChars.put("ᶎ", "z"); translitChars.put("ꝺ", "d"); translitChars.put("ᶈ", "p"); - translitChars.put("м", "m"); translitChars.put("ɫ", "l"); translitChars.put("ᴢ", "z"); translitChars.put("ɱ", "m"); @@ -2121,7 +2154,6 @@ public class LocaleController { translitChars.put("ṽ", "v"); translitChars.put("ũ", "u"); translitChars.put("ß", "ss"); - translitChars.put("т", "t"); translitChars.put("ĥ", "h"); translitChars.put("ᵵ", "t"); translitChars.put("ʐ", "z"); @@ -2131,7 +2163,6 @@ public class LocaleController { translitChars.put("ẙ", "y"); translitChars.put("ỳ", "y"); translitChars.put("ᴔ", "oe"); - translitChars.put("ы", "i"); translitChars.put("ₓ", "x"); translitChars.put("ȗ", "u"); translitChars.put("ⱼ", "j"); @@ -2150,12 +2181,10 @@ public class LocaleController { translitChars.put("ạ", "a"); translitChars.put("ḅ", "b"); translitChars.put("ụ", "u"); - translitChars.put("к", "k"); translitChars.put("ằ", "a"); translitChars.put("ᴛ", "t"); translitChars.put("ƴ", "y"); translitChars.put("ⱦ", "t"); - translitChars.put("з", "z"); translitChars.put("ⱡ", "l"); translitChars.put("ȷ", "j"); translitChars.put("ᵶ", "z"); @@ -2168,7 +2197,6 @@ public class LocaleController { translitChars.put("ȅ", "e"); translitChars.put("ȧ", "a"); translitChars.put("ẳ", "a"); - translitChars.put("щ", "sch"); translitChars.put("ɋ", "q"); translitChars.put("ṭ", "t"); translitChars.put("ꝸ", "um"); @@ -2215,14 +2243,12 @@ public class LocaleController { translitChars.put("ɳ", "n"); translitChars.put("ʛ", "g"); translitChars.put("ᴜ", "u"); - translitChars.put("ф", "f"); translitChars.put("ẩ", "a"); translitChars.put("ṅ", "n"); translitChars.put("ɨ", "i"); translitChars.put("ᴙ", "r"); translitChars.put("ǎ", "a"); translitChars.put("ſ", "s"); - translitChars.put("у", "u"); translitChars.put("ȫ", "o"); translitChars.put("ɿ", "r"); translitChars.put("ƭ", "t"); @@ -2245,7 +2271,6 @@ public class LocaleController { translitChars.put("ᴕ", "ou"); translitChars.put("ʈ", "t"); translitChars.put("ā", "a"); - translitChars.put("э", "e"); translitChars.put("ḙ", "e"); translitChars.put("ᴑ", "o"); translitChars.put("ç", "c"); @@ -2254,7 +2279,6 @@ public class LocaleController { translitChars.put("ų", "u"); translitChars.put("ả", "a"); translitChars.put("ǥ", "g"); - translitChars.put("р", "r"); translitChars.put("ꝁ", "k"); translitChars.put("ẕ", "z"); translitChars.put("ŝ", "s"); @@ -2263,7 +2287,6 @@ public class LocaleController { translitChars.put("ꝉ", "l"); translitChars.put("ꝼ", "f"); translitChars.put("ᶍ", "x"); - translitChars.put("х", "h"); translitChars.put("ǒ", "o"); translitChars.put("ę", "e"); translitChars.put("ổ", "o"); @@ -2276,7 +2299,6 @@ public class LocaleController { translitChars.put("ẅ", "w"); translitChars.put("ḑ", "d"); translitChars.put("ḹ", "l"); - translitChars.put("ч", "ch"); translitChars.put("œ", "oe"); translitChars.put("ᵳ", "r"); translitChars.put("ļ", "l"); @@ -2327,15 +2349,12 @@ public class LocaleController { translitChars.put("ử", "u"); translitChars.put("í", "i"); translitChars.put("ɔ", "o"); - translitChars.put("с", "s"); - translitChars.put("й", "i"); translitChars.put("ɺ", "r"); translitChars.put("ɢ", "g"); translitChars.put("ř", "r"); translitChars.put("ẖ", "h"); translitChars.put("ű", "u"); translitChars.put("ȍ", "o"); - translitChars.put("ш", "sh"); translitChars.put("ḻ", "l"); translitChars.put("ḣ", "h"); translitChars.put("ȶ", "t"); @@ -2343,7 +2362,6 @@ public class LocaleController { translitChars.put("ᶒ", "e"); translitChars.put("ì", "i"); translitChars.put("ẉ", "w"); - translitChars.put("б", "b"); translitChars.put("ē", "e"); translitChars.put("ᴇ", "e"); translitChars.put("ł", "l"); @@ -2362,17 +2380,14 @@ public class LocaleController { translitChars.put("ↄ", "c"); translitChars.put("ᶓ", "e"); translitChars.put("ɰ", "m"); - translitChars.put("е", "e"); translitChars.put("ᴡ", "w"); translitChars.put("ȏ", "o"); translitChars.put("č", "c"); translitChars.put("ǵ", "g"); translitChars.put("ĉ", "c"); - translitChars.put("ю", "yu"); translitChars.put("ᶗ", "o"); translitChars.put("ꝃ", "k"); translitChars.put("ꝙ", "q"); - translitChars.put("г", "g"); translitChars.put("ṑ", "o"); translitChars.put("ꜱ", "s"); translitChars.put("ṓ", "o"); @@ -2380,7 +2395,6 @@ public class LocaleController { translitChars.put("ő", "o"); translitChars.put("ꜩ", "tz"); translitChars.put("ẻ", "e"); - translitChars.put("о", "o"); } StringBuilder dst = new StringBuilder(src.length()); int len = src.length(); @@ -2393,6 +2407,9 @@ public class LocaleController { ch = lower; } String tch = translitChars.get(ch); + if (tch == null && ru) { + tch = ruTranslitChars.get(ch); + } if (tch != null) { if (onlyEnglish && upperCase) { if (tch.length() > 1) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocationSharingService.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocationSharingService.java index 8f28db6e9..c325d1964 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocationSharingService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocationSharingService.java @@ -13,8 +13,8 @@ import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.IBinder; -import android.support.v4.app.NotificationCompat; -import android.support.v4.app.NotificationManagerCompat; +import androidx.core.app.NotificationCompat; +import androidx.core.app.NotificationManagerCompat; import org.telegram.tgnet.TLRPC; import org.telegram.ui.LaunchActivity; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java index 45113b75a..740ef849a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java @@ -1166,7 +1166,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } if (event.sensor == proximitySensor) { if (BuildVars.LOGS_ENABLED) { - FileLog.d("proximity changed to " + event.values[0]); + FileLog.d("proximity changed to " + event.values[0] + " max value = " + proximitySensor.getMaximumRange()); } if (lastProximityValue == -100) { lastProximityValue = event.values[0]; @@ -1177,7 +1177,6 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, proximityTouched = isNearToSensor(event.values[0]); } } else if (event.sensor == accelerometerSensor) { - //0.98039215f final double alpha = lastTimestamp == 0 ? 0.98f : 1.0 / (1.0 + (event.timestamp - lastTimestamp) / 1000000000.0); final float alphaFast = 0.8f; lastTimestamp = event.timestamp; @@ -2082,6 +2081,188 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, return currentPlaybackSpeed; } + private void updateVideoState(MessageObject messageObject, int playCount[], boolean destroyAtEnd, boolean playWhenReady, int playbackState) { + if (videoPlayer == null) { + return; + } + if (playbackState != ExoPlayer.STATE_ENDED && playbackState != ExoPlayer.STATE_IDLE) { + try { + baseActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } catch (Exception e) { + FileLog.e(e); + } + } else { + try { + baseActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } catch (Exception e) { + FileLog.e(e); + } + } + if (playbackState == ExoPlayer.STATE_READY) { + playerWasReady = true; + if (playingMessageObject != null && (playingMessageObject.isVideo() || playingMessageObject.isRoundVideo())) { + AndroidUtilities.cancelRunOnUIThread(setLoadingRunnable); + FileLoader.getInstance(messageObject.currentAccount).removeLoadingVideo(playingMessageObject.getDocument(), true, false); + } + currentAspectRatioFrameLayoutReady = true; + } else if (playbackState == ExoPlayer.STATE_BUFFERING) { + if (playWhenReady && playingMessageObject != null && (playingMessageObject.isVideo() || playingMessageObject.isRoundVideo())) { + if (playerWasReady) { + setLoadingRunnable.run(); + } else { + AndroidUtilities.runOnUIThread(setLoadingRunnable, 1000); + } + } + } else if (videoPlayer.isPlaying() && playbackState == ExoPlayer.STATE_ENDED) { + if (playingMessageObject.isVideo() && !destroyAtEnd && (playCount == null || playCount[0] < 4)) { + videoPlayer.seekTo(0); + if (playCount != null) { + playCount[0]++; + } + } else { + cleanupPlayer(true, true, true, false); + } + } + } + + public void injectVideoPlayer(VideoPlayer player, MessageObject messageObject) { + if (player == null || messageObject == null) { + return; + } + FileLoader.getInstance(messageObject.currentAccount).setLoadingVideoForPlayer(messageObject.getDocument(), true); + playerWasReady = false; + boolean destroyAtEnd = true; + int[] playCount = null; + playlist.clear(); + shuffledPlaylist.clear(); + videoPlayer = player; + playingMessageObject = messageObject; + videoPlayer.setDelegate(new VideoPlayer.VideoPlayerDelegate() { + @Override + public void onStateChanged(boolean playWhenReady, int playbackState) { + updateVideoState(messageObject, playCount, destroyAtEnd, playWhenReady, playbackState); + } + + @Override + public void onError(Exception e) { + FileLog.e(e); + } + + @Override + public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) { + currentAspectRatioFrameLayoutRotation = unappliedRotationDegrees; + if (unappliedRotationDegrees == 90 || unappliedRotationDegrees == 270) { + int temp = width; + width = height; + height = temp; + } + currentAspectRatioFrameLayoutRatio = height == 0 ? 1 : (width * pixelWidthHeightRatio) / height; + + if (currentAspectRatioFrameLayout != null) { + currentAspectRatioFrameLayout.setAspectRatio(currentAspectRatioFrameLayoutRatio, currentAspectRatioFrameLayoutRotation); + } + } + + @Override + public void onRenderedFirstFrame() { + if (currentAspectRatioFrameLayout != null && !currentAspectRatioFrameLayout.isDrawingReady()) { + isDrawingWasReady = true; + currentAspectRatioFrameLayout.setDrawingReady(true); + currentTextureViewContainer.setTag(1); + } + } + + @Override + public boolean onSurfaceDestroyed(SurfaceTexture surfaceTexture) { + if (videoPlayer == null) { + return false; + } + if (pipSwitchingState == 2) { + if (currentAspectRatioFrameLayout != null) { + if (isDrawingWasReady) { + currentAspectRatioFrameLayout.setDrawingReady(true); + } + if (currentAspectRatioFrameLayout.getParent() == null) { + currentTextureViewContainer.addView(currentAspectRatioFrameLayout); + } + if (currentTextureView.getSurfaceTexture() != surfaceTexture) { + currentTextureView.setSurfaceTexture(surfaceTexture); + } + videoPlayer.setTextureView(currentTextureView); + } + pipSwitchingState = 0; + return true; + } else if (pipSwitchingState == 1) { + if (baseActivity != null) { + if (pipRoundVideoView == null) { + try { + pipRoundVideoView = new PipRoundVideoView(); + pipRoundVideoView.show(baseActivity, () -> cleanupPlayer(true, true)); + } catch (Exception e) { + pipRoundVideoView = null; + } + } + if (pipRoundVideoView != null) { + if (pipRoundVideoView.getTextureView().getSurfaceTexture() != surfaceTexture) { + pipRoundVideoView.getTextureView().setSurfaceTexture(surfaceTexture); + } + videoPlayer.setTextureView(pipRoundVideoView.getTextureView()); + } + } + pipSwitchingState = 0; + return true; + } else if (PhotoViewer.hasInstance() && PhotoViewer.getInstance().isInjectingVideoPlayer()) { + PhotoViewer.getInstance().injectVideoPlayerSurface(surfaceTexture); + return true; + } + return false; + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { + + } + }); + currentAspectRatioFrameLayoutReady = false; + if (currentTextureView != null) { + videoPlayer.setTextureView(currentTextureView); + } + + + + checkAudioFocus(messageObject); + setPlayerVolume(); + + isPaused = false; + lastProgress = 0; + playingMessageObject = messageObject; + if (!SharedConfig.raiseToSpeak) { + startRaiseToEarSensors(raiseChat); + } + startProgressTimer(playingMessageObject); + NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingDidStart, messageObject); + + /*try { + if (playingMessageObject.audioProgress != 0) { + long duration = videoPlayer.getDuration(); + if (duration == C.TIME_UNSET) { + duration = (long) playingMessageObject.getDuration() * 1000; + } + int seekTo = (int) (duration * playingMessageObject.audioProgress); + if (playingMessageObject.audioProgressMs != 0) { + seekTo = playingMessageObject.audioProgressMs; + playingMessageObject.audioProgressMs = 0; + } + videoPlayer.seekTo(seekTo); + } + } catch (Exception e2) { + playingMessageObject.audioProgress = 0; + playingMessageObject.audioProgressSec = 0; + NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.messagePlayingProgressDidChanged, playingMessageObject.getId(), 0); + FileLog.e(e2); + }*/ + } + public boolean playMessage(final MessageObject messageObject) { if (messageObject == null) { return false; @@ -2118,7 +2299,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } } final File cacheFile = file != null ? file : FileLoader.getPathToMessage(messageObject.messageOwner); - boolean canStream = SharedConfig.streamMedia && (messageObject.isMusic() || messageObject.isVideo() && messageObject.canStreamVideo()) && (int) messageObject.getDialogId() != 0; + boolean canStream = SharedConfig.streamMedia && (messageObject.isMusic() || messageObject.isRoundVideo() || messageObject.isVideo() && messageObject.canStreamVideo()) && (int) messageObject.getDialogId() != 0; if (cacheFile != null && cacheFile != file && !(exists = cacheFile.exists()) && !canStream) { FileLoader.getInstance(messageObject.currentAccount).loadFile(messageObject.getDocument(), messageObject, 0, 0); downloadingCurrentMessage = true; @@ -2158,9 +2339,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } boolean isVideo = messageObject.isVideo(); if (messageObject.isRoundVideo() || isVideo) { - if (isVideo) { - FileLoader.getInstance(messageObject.currentAccount).setLoadingVideoForPlayer(messageObject.getDocument(), true); - } + FileLoader.getInstance(messageObject.currentAccount).setLoadingVideoForPlayer(messageObject.getDocument(), true); playerWasReady = false; boolean destroyAtEnd = !isVideo || messageObject.messageOwner.to_id.channel_id == 0 && messageObject.audioProgress <= 0.1f; int[] playCount = isVideo && messageObject.getDuration() <= 30 ? new int[]{1} : null; @@ -2170,47 +2349,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, videoPlayer.setDelegate(new VideoPlayer.VideoPlayerDelegate() { @Override public void onStateChanged(boolean playWhenReady, int playbackState) { - if (videoPlayer == null) { - return; - } - if (playbackState != ExoPlayer.STATE_ENDED && playbackState != ExoPlayer.STATE_IDLE) { - try { - baseActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - } catch (Exception e) { - FileLog.e(e); - } - } else { - try { - baseActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - } catch (Exception e) { - FileLog.e(e); - } - } - if (playbackState == ExoPlayer.STATE_READY) { - playerWasReady = true; - if (playingMessageObject != null && playingMessageObject.isVideo()) { - AndroidUtilities.cancelRunOnUIThread(setLoadingRunnable); - FileLoader.getInstance(messageObject.currentAccount).removeLoadingVideo(playingMessageObject.getDocument(), true, false); - } - currentAspectRatioFrameLayoutReady = true; - } else if (playbackState == ExoPlayer.STATE_BUFFERING) { - if (playWhenReady && playingMessageObject != null && playingMessageObject.isVideo()) { - if (playerWasReady) { - setLoadingRunnable.run(); - } else { - AndroidUtilities.runOnUIThread(setLoadingRunnable, 1000); - } - } - } else if (videoPlayer.isPlaying() && playbackState == ExoPlayer.STATE_ENDED) { - if (playingMessageObject.isVideo() && !destroyAtEnd && (playCount == null || playCount[0] < 4)) { - videoPlayer.seekTo(0); - if (playCount != null) { - playCount[0]++; - } - } else { - cleanupPlayer(true, true, true, false); - } - } + updateVideoState(messageObject, playCount, destroyAtEnd, playWhenReady, playbackState); } @Override @@ -2355,7 +2494,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, audioPlayer.setDelegate(new VideoPlayer.VideoPlayerDelegate() { @Override public void onStateChanged(boolean playWhenReady, int playbackState) { - if (playbackState == ExoPlayer.STATE_ENDED) { + if (playbackState == ExoPlayer.STATE_ENDED || (playbackState == ExoPlayer.STATE_IDLE || playbackState == ExoPlayer.STATE_BUFFERING) && playWhenReady && messageObject.audioProgress >= 0.999f) { if (!playlist.isEmpty() && playlist.size() > 1) { playNextMessageWithoutOrder(true); } else { @@ -2663,7 +2802,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, return; } - audioRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, recordBufferSize * 10); + audioRecorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, 16000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, recordBufferSize * 10); recordStartTime = System.currentTimeMillis(); recordTimeCount = 0; samplesCount = 0; @@ -3791,13 +3930,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, outputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat); outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate > 0 ? bitrate : 921600); outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, framerate != 0 ? framerate : 25); - outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10); - /*if (Build.VERSION.SDK_INT >= 21) { - outputFormat.setInteger(MediaFormat.KEY_PROFILE, MediaCodecInfo.CodecProfileLevel.AVCProfileHigh); - if (Build.VERSION.SDK_INT >= 23) { - outputFormat.setInteger(MediaFormat.KEY_LEVEL, MediaCodecInfo.CodecProfileLevel.AVCLevel5); - } - }*/ + outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2); if (Build.VERSION.SDK_INT < 18) { outputFormat.setInteger("stride", resultWidth + 32); outputFormat.setInteger("slice-height", resultHeight); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index f55d90144..ede4c836e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -68,12 +68,14 @@ public class MessageObject { public long localGroupId; public long localSentGroupId; public boolean localChannel; + public boolean localEdit; public TLRPC.Message messageOwner; public CharSequence messageText; public CharSequence linkDescription; public CharSequence caption; public MessageObject replyMessageObject; public int type = 1000; + private boolean animatedHackedSticker; private int isRoundVideoCached; public long eventId; public int contentType; @@ -87,6 +89,8 @@ public class MessageObject { public int audioProgressSec; public int audioPlayerDuration; public boolean isDateObject; + public TLObject photoThumbsObject; + public TLObject photoThumbsObject2; public ArrayList photoThumbs; public ArrayList photoThumbs2; public VideoEditedInfo videoEditedInfo; @@ -126,8 +130,10 @@ public class MessageObject { public float textXOffset; public int linesCount; + private int emojiOnlyCount; private boolean layoutCreated; private int generatedWithMinSize; + private float generatedWithDensity; public static Pattern urlPattern; public static Pattern instagramUrlPattern; @@ -310,7 +316,7 @@ public class MessageObject { public int leftSpanOffset; public boolean edge; public int flags; - public float siblingHeights[]; + public float[] siblingHeights; public void set(int minX, int maxX, int minY, int maxY, int w, float h, int flags) { this.minX = (byte) minX; @@ -355,7 +361,7 @@ public class MessageObject { } } - private float multiHeight(float array[], int start, int end) { + private float multiHeight(float[] array, int start, int end) { float sum = 0; for (int a = start; a < end; a++) { sum += array[a]; @@ -554,7 +560,7 @@ public class MessageObject { } } } else { - float croppedRatios[] = new float[posArray.size()]; + float[] croppedRatios = new float[posArray.size()]; for (int a = 0; a < count; a++) { if (averageAspectRatio > 1.1f) { croppedRatios[a] = Math.max(1.0f, posArray.get(a).aspectRatio); @@ -715,7 +721,7 @@ public class MessageObject { public ArrayList textLayoutBlocks; - public MessageObject(int accountNum, TLRPC.Message message, String formattedMessage, String name, String userName, boolean localMessage, boolean isChannel) { + public MessageObject(int accountNum, TLRPC.Message message, String formattedMessage, String name, String userName, boolean localMessage, boolean isChannel, boolean edit) { localType = localMessage ? 2 : 1; currentAccount = accountNum; localName = name; @@ -723,6 +729,7 @@ public class MessageObject { messageText = formattedMessage; messageOwner = message; localChannel = isChannel; + localEdit = edit; } public MessageObject(int accountNum, TLRPC.Message message, AbstractMap users, boolean generateLayout) { @@ -1164,6 +1171,24 @@ public class MessageObject { } else { messageText = message.message; } + + /* + Дописывать нужно в следующих случаях: TODO + - любое сообщение от скам-пользователя или скам-бота + - пересланное сообщение от скам-пользователя или скам-бота + - сообщение via скам-бот + - любое сообщение в скам-канале + - пересланное сообщение из скам-канала + - сообщение от админа в скам-супергруппе + - закрепленное сообщение в скам-супергруппе + + if (messageText == null || messageText.length() == 0) { + messageText = LocaleController.getString("ScamMessage", R.string.ScamMessage); + } else { + messageText = messageText + "\n\n" + LocaleController.getString("ScamMessage", R.string.ScamMessage); + } + */ + if (messageText == null) { messageText = ""; } @@ -1190,31 +1215,7 @@ public class MessageObject { } int[] emojiOnly = SharedConfig.allowBigEmoji ? new int[1] : null; messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false, emojiOnly); - if (emojiOnly != null && emojiOnly[0] >= 1 && emojiOnly[0] <= 3) { - TextPaint emojiPaint; - int size; - switch (emojiOnly[0]) { - case 1: - emojiPaint = Theme.chat_msgTextPaintOneEmoji; - size = AndroidUtilities.dp(32); - break; - case 2: - emojiPaint = Theme.chat_msgTextPaintTwoEmoji; - size = AndroidUtilities.dp(28); - break; - case 3: - default: - emojiPaint = Theme.chat_msgTextPaintThreeEmoji; - size = AndroidUtilities.dp(24); - break; - } - Emoji.EmojiSpan[] spans = ((Spannable) messageText).getSpans(0, messageText.length(), Emoji.EmojiSpan.class); - if (spans != null && spans.length > 0) { - for (int a = 0; a < spans.length; a++) { - spans[a].replaceFontMetrics(emojiPaint.getFontMetricsInt(), size); - } - } - } + checkEmojiOnly(emojiOnly); generateLayout(fromUser); } layoutCreated = generateLayout; @@ -1239,6 +1240,41 @@ public class MessageObject { } } + public void checkForScam() { + + } + + private void checkEmojiOnly(int[] emojiOnly) { + if (emojiOnly != null && emojiOnly[0] >= 1 && emojiOnly[0] <= 3) { + TextPaint emojiPaint; + int size; + switch (emojiOnly[0]) { + case 1: + emojiPaint = Theme.chat_msgTextPaintOneEmoji; + size = AndroidUtilities.dp(32); + emojiOnlyCount = 1; + break; + case 2: + emojiPaint = Theme.chat_msgTextPaintTwoEmoji; + size = AndroidUtilities.dp(28); + emojiOnlyCount = 2; + break; + case 3: + default: + emojiPaint = Theme.chat_msgTextPaintThreeEmoji; + size = AndroidUtilities.dp(24); + emojiOnlyCount = 3; + break; + } + Emoji.EmojiSpan[] spans = ((Spannable) messageText).getSpans(0, messageText.length(), Emoji.EmojiSpan.class); + if (spans != null && spans.length > 0) { + for (int a = 0; a < spans.length; a++) { + spans[a].replaceFontMetrics(emojiPaint.getFontMetricsInt(), size); + } + } + } + } + public MessageObject(int accountNum, TLRPC.TL_channelAdminLogEvent event, ArrayList messageObjects, HashMap> messagesByDays, TLRPC.Chat chat, int[] mid) { TLRPC.User fromUser = null; if (event.user_id > 0) { @@ -1269,7 +1305,7 @@ public class MessageObject { } } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangePhoto) { messageOwner = new TLRPC.TL_messageService(); - if (event.action.new_photo instanceof TLRPC.TL_chatPhotoEmpty) { + if (event.action.new_photo instanceof TLRPC.TL_photoEmpty) { messageOwner.action = new TLRPC.TL_messageActionChatDeletePhoto(); if (chat.megagroup) { messageText = replaceWithLink(LocaleController.getString("EventLogRemovedWGroupPhoto", R.string.EventLogRemovedWGroupPhoto), "un1", fromUser); @@ -1278,18 +1314,7 @@ public class MessageObject { } } else { messageOwner.action = new TLRPC.TL_messageActionChatEditPhoto(); - messageOwner.action.photo = new TLRPC.TL_photo(); - messageOwner.action.photo.file_reference = new byte[0]; - TLRPC.TL_photoSize photoSize = new TLRPC.TL_photoSize(); - photoSize.location = event.action.new_photo.photo_small; - photoSize.type = "s"; - photoSize.w = photoSize.h = 80; - messageOwner.action.photo.sizes.add(photoSize); - photoSize = new TLRPC.TL_photoSize(); - photoSize.location = event.action.new_photo.photo_big; - photoSize.type = "m"; - photoSize.w = photoSize.h = 640; - messageOwner.action.photo.sizes.add(photoSize); + messageOwner.action.photo = event.action.new_photo; if (chat.megagroup) { messageText = replaceWithLink(LocaleController.getString("EventLogEditedGroupPhoto", R.string.EventLogEditedGroupPhoto), "un1", fromUser); @@ -1822,31 +1847,7 @@ public class MessageObject { } int[] emojiOnly = SharedConfig.allowBigEmoji ? new int[1] : null; messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false, emojiOnly); - if (emojiOnly != null && emojiOnly[0] >= 1 && emojiOnly[0] <= 3) { - TextPaint emojiPaint; - int size; - switch (emojiOnly[0]) { - case 1: - emojiPaint = Theme.chat_msgTextPaintOneEmoji; - size = AndroidUtilities.dp(32); - break; - case 2: - emojiPaint = Theme.chat_msgTextPaintTwoEmoji; - size = AndroidUtilities.dp(28); - break; - case 3: - default: - emojiPaint = Theme.chat_msgTextPaintThreeEmoji; - size = AndroidUtilities.dp(24); - break; - } - Emoji.EmojiSpan[] spans = ((Spannable) messageText).getSpans(0, messageText.length(), Emoji.EmojiSpan.class); - if (spans != null && spans.length > 0) { - for (int a = 0; a < spans.length; a++) { - spans[a].replaceFontMetrics(emojiPaint.getFontMetricsInt(), size); - } - } - } + checkEmojiOnly(emojiOnly); if (mediaController.isPlayingMessage(this)) { MessageObject player = mediaController.getPlayingMessageObject(); audioProgress = player.audioProgress; @@ -1900,7 +1901,9 @@ public class MessageObject { } else { paint = Theme.chat_msgTextPaint; } - messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + int[] emojiOnly = SharedConfig.allowBigEmoji ? new int[1] : null; + messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false, emojiOnly); + checkEmojiOnly(emojiOnly); generateLayout(fromUser); } @@ -1973,7 +1976,7 @@ public class MessageObject { messageText = replaceWithLink(LocaleController.getString("ActionPinnedVoice", R.string.ActionPinnedVoice), "un1", fromUser != null ? fromUser : chat); } else if (replyMessageObject.isRoundVideo()) { messageText = replaceWithLink(LocaleController.getString("ActionPinnedRound", R.string.ActionPinnedRound), "un1", fromUser != null ? fromUser : chat); - } else if (replyMessageObject.isSticker()) { + } else if (replyMessageObject.isSticker() || replyMessageObject.isAnimatedSticker()) { messageText = replaceWithLink(LocaleController.getString("ActionPinnedSticker", R.string.ActionPinnedSticker), "un1", fromUser != null ? fromUser : chat); } else if (replyMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { messageText = replaceWithLink(LocaleController.getString("ActionPinnedFile", R.string.ActionPinnedFile), "un1", fromUser != null ? fromUser : chat); @@ -2128,8 +2131,11 @@ public class MessageObject { } public ArrayList getWebPagePhotos(ArrayList array, ArrayList blocksToSearch) { - TLRPC.WebPage webPage = messageOwner.media.webpage; ArrayList messageObjects = array == null ? new ArrayList<>() : array; + if (messageOwner.media == null || messageOwner.media.webpage == null) { + return messageObjects; + } + TLRPC.WebPage webPage = messageOwner.media.webpage; if (webPage.cached_page == null) { return messageObjects; } @@ -2256,7 +2262,10 @@ public class MessageObject { if (messageOwner.media.document != null && messageOwner.media.document.mime_type != null) { if (isGifDocument(messageOwner.media.document)) { type = 8; - } else if (messageOwner.media.document.mime_type.equals("image/webp") && isSticker()) { + } else if (isSticker()) { + type = 13; + } else if (isAnimatedSticker()) { + animatedHackedSticker = true; type = 13; } else { type = 9; @@ -2304,7 +2313,7 @@ public class MessageObject { } if (layoutCreated) { int newMinSize = AndroidUtilities.isTablet() ? AndroidUtilities.getMinTabletSide() : AndroidUtilities.displaySize.x; - if (Math.abs(generatedWithMinSize - newMinSize) > AndroidUtilities.dp(52)) { + if (Math.abs(generatedWithMinSize - newMinSize) > AndroidUtilities.dp(52) || generatedWithDensity != AndroidUtilities.density) { layoutCreated = false; } } @@ -2320,7 +2329,9 @@ public class MessageObject { } else { paint = Theme.chat_msgTextPaint; } - messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + int[] emojiOnly = SharedConfig.allowBigEmoji ? new int[1] : null; + messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false, emojiOnly); + checkEmojiOnly(emojiOnly); generateLayout(fromUser); return true; } @@ -2360,7 +2371,7 @@ public class MessageObject { } public static boolean isGifDocument(TLRPC.Document document) { - return document != null && !document.thumbs.isEmpty() && document.mime_type != null && (document.mime_type.equals("image/gif") || isNewGifDocument(document)); + return document != null /*&& !document.thumbs.isEmpty()*/ && document.mime_type != null && (document.mime_type.equals("image/gif") || isNewGifDocument(document)); } public static boolean isDocumentHasThumb(TLRPC.Document document) { @@ -2379,7 +2390,7 @@ public class MessageObject { public static boolean canPreviewDocument(TLRPC.Document document) { if (document != null && document.mime_type != null) { String mime = document.mime_type.toLowerCase(); - if (isDocumentHasThumb(document) && mime != null && (mime.equals("image/png") || mime.equals("image/jpg") || mime.equals("image/jpeg"))) { + if (isDocumentHasThumb(document) && (mime.equals("image/png") || mime.equals("image/jpg") || mime.equals("image/jpeg"))) { for (int a = 0; a < document.attributes.size(); a++) { TLRPC.DocumentAttribute attribute = document.attributes.get(a); if (attribute instanceof TLRPC.TL_documentAttributeImageSize) { @@ -2387,6 +2398,11 @@ public class MessageObject { return size.w < 6000 && size.h < 6000; } } + } else if (BuildVars.DEBUG_PRIVATE_VERSION) { + String fileName = FileLoader.getDocumentFileName(document); + if (fileName.startsWith("tg_secret_sticker") && fileName.endsWith("json")) { + return true; + } } } return false; @@ -2457,13 +2473,14 @@ public class MessageObject { public void generateThumbs(boolean update) { if (messageOwner instanceof TLRPC.TL_messageService) { if (messageOwner.action instanceof TLRPC.TL_messageActionChatEditPhoto) { + TLRPC.Photo photo = messageOwner.action.photo; if (!update) { - photoThumbs = new ArrayList<>(messageOwner.action.photo.sizes); + photoThumbs = new ArrayList<>(photo.sizes); } else if (photoThumbs != null && !photoThumbs.isEmpty()) { for (int a = 0; a < photoThumbs.size(); a++) { TLRPC.PhotoSize photoObject = photoThumbs.get(a); - for (int b = 0; b < messageOwner.action.photo.sizes.size(); b++) { - TLRPC.PhotoSize size = messageOwner.action.photo.sizes.get(b); + for (int b = 0; b < photo.sizes.size(); b++) { + TLRPC.PhotoSize size = photo.sizes.get(b); if (size instanceof TLRPC.TL_photoSizeEmpty) { continue; } @@ -2474,19 +2491,28 @@ public class MessageObject { } } } + if (photo.dc_id != 0) { + for (int a = 0, N = photoThumbs.size(); a < N; a++) { + TLRPC.FileLocation location = photoThumbs.get(a).location; + location.dc_id = photo.dc_id; + location.file_reference = photo.file_reference; + } + } + photoThumbsObject = messageOwner.action.photo; } } else if (messageOwner.media != null && !(messageOwner.media instanceof TLRPC.TL_messageMediaEmpty)) { if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { - if (!update || photoThumbs != null && photoThumbs.size() != messageOwner.media.photo.sizes.size()) { - photoThumbs = new ArrayList<>(messageOwner.media.photo.sizes); + TLRPC.Photo photo = messageOwner.media.photo; + if (!update || photoThumbs != null && photoThumbs.size() != photo.sizes.size()) { + photoThumbs = new ArrayList<>(photo.sizes); } else if (photoThumbs != null && !photoThumbs.isEmpty()) { for (int a = 0; a < photoThumbs.size(); a++) { TLRPC.PhotoSize photoObject = photoThumbs.get(a); if (photoObject == null) { continue; } - for (int b = 0; b < messageOwner.media.photo.sizes.size(); b++) { - TLRPC.PhotoSize size = messageOwner.media.photo.sizes.get(b); + for (int b = 0; b < photo.sizes.size(); b++) { + TLRPC.PhotoSize size = photo.sizes.get(b); if (size == null || size instanceof TLRPC.TL_photoSizeEmpty) { continue; } @@ -2497,6 +2523,7 @@ public class MessageObject { } } } + photoThumbsObject = messageOwner.media.photo; } else if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { TLRPC.Document document = messageOwner.media.document; if (isDocumentHasThumb(document)) { @@ -2506,6 +2533,7 @@ public class MessageObject { } else if (photoThumbs != null && !photoThumbs.isEmpty()) { updatePhotoSizeLocations(photoThumbs, document.thumbs); } + photoThumbsObject = document; } } else if (messageOwner.media instanceof TLRPC.TL_messageMediaGame) { TLRPC.Document document = messageOwner.media.game.document; @@ -2517,6 +2545,7 @@ public class MessageObject { } else if (photoThumbs != null && !photoThumbs.isEmpty()) { updatePhotoSizeLocations(photoThumbs, document.thumbs); } + photoThumbsObject = document; } } TLRPC.Photo photo = messageOwner.media.game.photo; @@ -2526,10 +2555,13 @@ public class MessageObject { } else if (!photoThumbs2.isEmpty()) { updatePhotoSizeLocations(photoThumbs2, photo.sizes); } + photoThumbsObject2 = photo; } if (photoThumbs == null && photoThumbs2 != null) { photoThumbs = photoThumbs2; photoThumbs2 = null; + photoThumbsObject = photoThumbsObject2; + photoThumbsObject2 = null; } } else if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) { TLRPC.Photo photo = messageOwner.media.webpage.photo; @@ -2540,6 +2572,7 @@ public class MessageObject { } else if (!photoThumbs.isEmpty()) { updatePhotoSizeLocations(photoThumbs, photo.sizes); } + photoThumbsObject = photo; } else if (document != null) { if (isDocumentHasThumb(document)) { if (!update) { @@ -2548,6 +2581,7 @@ public class MessageObject { } else if (photoThumbs != null && !photoThumbs.isEmpty()) { updatePhotoSizeLocations(photoThumbs, document.thumbs); } + photoThumbsObject = document; } } } @@ -3121,6 +3155,7 @@ public class MessageObject { } else { generatedWithMinSize = AndroidUtilities.isTablet() ? AndroidUtilities.getMinTabletSide() : AndroidUtilities.displaySize.x; } + generatedWithDensity = AndroidUtilities.density; if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageOwner.media.webpage != null && "telegram_background".equals(messageOwner.media.webpage.type)) { try { Uri uri = Uri.parse(messageOwner.media.webpage.url); @@ -3245,6 +3280,23 @@ public class MessageObject { block.textLayout = textLayout; block.textYOffset = 0; block.charactersOffset = 0; + if (emojiOnlyCount != 0) { + switch (emojiOnlyCount) { + case 1: + textHeight -= AndroidUtilities.dp(5.3f); + block.textYOffset -= AndroidUtilities.dp(5.3f); + break; + case 2: + textHeight -= AndroidUtilities.dp(4.5f); + block.textYOffset -= AndroidUtilities.dp(4.5f); + break; + case 3: + textHeight -= AndroidUtilities.dp(4.2f); + block.textYOffset -= AndroidUtilities.dp(4.2f); + break; + } + + } block.height = textHeight; } else { int startCharacter = textLayout.getLineStart(linesOffset); @@ -3309,6 +3361,9 @@ public class MessageObject { } int linesMaxWidth = (int) Math.ceil(lastLine); + if (linesMaxWidth > maxWidth + 80) { + linesMaxWidth = maxWidth; + } int lastLineWidthWithLeft; int linesMaxWidthWithLeft; @@ -3473,6 +3528,8 @@ public class MessageObject { TLRPC.Document document; if (message.media instanceof TLRPC.TL_messageMediaWebPage) { document = message.media.webpage.document; + } else if (message.media instanceof TLRPC.TL_messageMediaGame) { + document = message.media.game.document; } else { document = message.media != null ? message.media.document : null; } @@ -3580,7 +3637,7 @@ public class MessageObject { public boolean canStreamVideo() { TLRPC.Document document = getDocument(); - if (document == null) { + if (document == null || document instanceof TLRPC.TL_documentEncrypted) { return false; } if (SharedConfig.streamAllVideo) { @@ -3670,13 +3727,23 @@ public class MessageObject { for (int a = 0; a < document.attributes.size(); a++) { TLRPC.DocumentAttribute attribute = document.attributes.get(a); if (attribute instanceof TLRPC.TL_documentAttributeSticker) { - return true; + return "image/webp".equals(document.mime_type); } } } return false; } + public static boolean isAnimatedStickerDocument(TLRPC.Document document) { + if (SharedConfig.showAnimatedStickers && document != null) { + String fileName = FileLoader.getDocumentFileName(document); + if (fileName.startsWith("tg_secret_sticker") && fileName.endsWith("json")) { + return true; + } + } + return false; + } + public static boolean isMaskDocument(TLRPC.Document document) { if (document != null) { for (int a = 0; a < document.attributes.size(); a++) { @@ -3764,18 +3831,33 @@ public class MessageObject { } public TLRPC.Document getDocument() { - if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) { - return messageOwner.media.webpage.document; - } else if (messageOwner.media instanceof TLRPC.TL_messageMediaGame) { - return messageOwner.media.game.document; + return getDocument(messageOwner); + } + + public static TLRPC.Document getDocument(TLRPC.Message message) { + if (message.media instanceof TLRPC.TL_messageMediaWebPage) { + return message.media.webpage.document; + } else if (message.media instanceof TLRPC.TL_messageMediaGame) { + return message.media.game.document; } - return messageOwner.media != null ? messageOwner.media.document : null; + return message.media != null ? message.media.document : null; + } + + public static TLRPC.Photo getPhoto(TLRPC.Message message) { + if (message.media instanceof TLRPC.TL_messageMediaWebPage) { + return message.media.webpage.photo; + } + return message.media != null ? message.media.photo : null; } public static boolean isStickerMessage(TLRPC.Message message) { return message.media != null && isStickerDocument(message.media.document); } + public static boolean isAnimatedStickerMessage(TLRPC.Message message) { + return message.media != null && isAnimatedStickerDocument(message.media.document); + } + public static boolean isLocationMessage(TLRPC.Message message) { return message.media instanceof TLRPC.TL_messageMediaGeo || message.media instanceof TLRPC.TL_messageMediaGeoLive || message.media instanceof TLRPC.TL_messageMediaVenue; } @@ -3792,6 +3874,9 @@ public class MessageObject { } public static boolean isGifMessage(TLRPC.Message message) { + if (message.media instanceof TLRPC.TL_messageMediaWebPage) { + return isGifDocument(message.media.webpage.document); + } return message.media != null && isGifDocument(message.media.document); } @@ -3989,11 +4074,18 @@ public class MessageObject { public boolean isSticker() { if (type != 1000) { - return type == 13; + return type == 13 && !animatedHackedSticker; } return isStickerMessage(messageOwner); } + public boolean isAnimatedSticker() { + if (type != 1000) { + return type == 13; + } + return isAnimatedStickerMessage(messageOwner); + } + public boolean isLocation() { return isLocationMessage(messageOwner); } @@ -4014,6 +4106,10 @@ public class MessageObject { return isVideoMessage(messageOwner); } + public boolean isPhoto() { + return isPhoto(messageOwner); + } + public boolean isLiveLocation() { return isLiveLocationMessage(messageOwner); } @@ -4179,6 +4275,8 @@ public class MessageObject { chat = MessagesController.getInstance(currentAccount).getChat(messageOwner.fwd_from.channel_id); } else if (messageOwner.fwd_from != null && messageOwner.fwd_from.from_id != 0) { user = MessagesController.getInstance(currentAccount).getUser(messageOwner.fwd_from.from_id); + } else if (messageOwner.fwd_from != null && messageOwner.fwd_from.from_name != null) { + return messageOwner.fwd_from.from_name; } else if (messageOwner.from_id < 0) { chat = MessagesController.getInstance(currentAccount).getChat(-messageOwner.from_id); } else if (messageOwner.from_id == 0 && messageOwner.to_id.channel_id != 0) { @@ -4237,13 +4335,17 @@ public class MessageObject { return canEditMessage(currentAccount, messageOwner, chat); } + public boolean canForwardMessage() { + return !(messageOwner instanceof TLRPC.TL_message_secret) && !needDrawBluredPreview() && !isLiveLocation() && type != 16; + } + public boolean canEditMedia() { if (isSecretMedia()) { return false; } else if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { return true; } else if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { - return !isVoice() && !isSticker() && !isRoundVideo(); + return !isVoice() && !isSticker() && !isAnimatedSticker() && !isRoundVideo(); } return false; } @@ -4345,6 +4447,8 @@ public class MessageObject { if (user != null) { return UserObject.getUserName(user); } + } else if (messageOwner.fwd_from.from_name != null) { + return messageOwner.fwd_from.from_name; } } return null; @@ -4455,4 +4559,8 @@ public class MessageObject { } } } + + public boolean equals(MessageObject obj) { + return getId() == obj.getId() && getDialogId() == obj.getDialogId(); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index 3f53876b9..fcc86f59a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -48,7 +48,7 @@ import java.util.Locale; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; -import android.support.v4.app.NotificationManagerCompat; +import androidx.core.app.NotificationManagerCompat; public class MessagesController implements NotificationCenter.NotificationCenterDelegate { @@ -62,20 +62,21 @@ public class MessagesController implements NotificationCenter.NotificationCenter private SparseArray exportedChats = new SparseArray<>(); public ArrayList hintDialogs = new ArrayList<>(); - public ArrayList dialogs = new ArrayList<>(); - public ArrayList dialogsForward = new ArrayList<>(); - public ArrayList dialogsServerOnly = new ArrayList<>(); - public ArrayList dialogsCanAddUsers = new ArrayList<>(); - public ArrayList dialogsChannelsOnly = new ArrayList<>(); - public ArrayList dialogsUsersOnly = new ArrayList<>(); - public ArrayList dialogsGroupsOnly = new ArrayList<>(); + private SparseArray> dialogsByFolder = new SparseArray<>(); + protected ArrayList allDialogs = new ArrayList<>(); + public ArrayList dialogsForward = new ArrayList<>(); + public ArrayList dialogsServerOnly = new ArrayList<>(); + public ArrayList dialogsCanAddUsers = new ArrayList<>(); + public ArrayList dialogsChannelsOnly = new ArrayList<>(); + public ArrayList dialogsUsersOnly = new ArrayList<>(); + public ArrayList dialogsGroupsOnly = new ArrayList<>(); public int unreadUnmutedDialogs; - public int nextDialogsCacheOffset; public ConcurrentHashMap dialogs_read_inbox_max = new ConcurrentHashMap<>(100, 1.0f, 2); public ConcurrentHashMap dialogs_read_outbox_max = new ConcurrentHashMap<>(100, 1.0f, 2); - public LongSparseArray dialogs_dict = new LongSparseArray<>(); + public LongSparseArray dialogs_dict = new LongSparseArray<>(); public LongSparseArray dialogMessage = new LongSparseArray<>(); public LongSparseArray dialogMessagesByRandomIds = new LongSparseArray<>(); + public LongSparseArray deletedHistory = new LongSparseArray<>(); public SparseArray dialogMessagesByIds = new SparseArray<>(); public ConcurrentHashMap> printingUsers = new ConcurrentHashMap<>(20, 1.0f, 2); public LongSparseArray printingStrings = new LongSparseArray<>(); @@ -84,6 +85,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter public ConcurrentHashMap onlinePrivacy = new ConcurrentHashMap<>(20, 1.0f, 2); private int lastPrintingStringCount; + private boolean dialogsInTransaction; + private LongSparseArray loadingPeerSettings = new LongSparseArray<>(); private ArrayList createdDialogIds = new ArrayList<>(); @@ -95,8 +98,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter private SparseIntArray shortPollOnlines = new SparseIntArray(); private SparseIntArray needShortPollOnlines = new SparseIntArray(); - private LongSparseArray deletingDialogs = new LongSparseArray<>(); - private LongSparseArray clearingHistoryDialogs = new LongSparseArray<>(); + private LongSparseArray deletingDialogs = new LongSparseArray<>(); + private LongSparseArray clearingHistoryDialogs = new LongSparseArray<>(); public boolean loadingBlockedUsers = false; public SparseIntArray blockedUsers = new SparseIntArray(); @@ -112,6 +115,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter private SparseBooleanArray gettingDifferenceChannels = new SparseBooleanArray(); private SparseBooleanArray gettingUnknownChannels = new SparseBooleanArray(); + private LongSparseArray gettingUnknownDialogs = new LongSparseArray<>(); private SparseBooleanArray checkingLastMessagesDialogs = new SparseBooleanArray(); private ArrayList updatesQueueSeq = new ArrayList<>(); @@ -120,7 +124,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter private long updatesStartWaitTimeSeq; private long updatesStartWaitTimePts; private long updatesStartWaitTimeQts; - private SparseArray fullUsers = new SparseArray<>(); + private SparseArray fullUsers = new SparseArray<>(); private ArrayList loadingFullUsers = new ArrayList<>(); private ArrayList loadedFullUsers = new ArrayList<>(); private ArrayList loadingFullChats = new ArrayList<>(); @@ -146,11 +150,14 @@ public class MessagesController implements NotificationCenter.NotificationCenter private int currentDeletingTaskChannelId; private Runnable currentDeleteTaskRunnable; + public boolean dialogsLoaded; + private SparseIntArray nextDialogsCacheOffset = new SparseIntArray(); + private SparseBooleanArray loadingDialogs = new SparseBooleanArray(); + private SparseBooleanArray dialogsEndReached = new SparseBooleanArray(); + private SparseBooleanArray serverDialogsEndReached = new SparseBooleanArray(); + private boolean loadingUnreadDialogs; - public boolean loadingDialogs; private boolean migratingDialogs; - public boolean dialogsEndReached; - public boolean serverDialogsEndReached; public boolean gettingDifference; private boolean getDifferenceFirstSync = true; public boolean updatingState; @@ -160,6 +167,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter private boolean resetingDialogs; private TLRPC.TL_messages_peerDialogs resetDialogsPinned; private TLRPC.messages_Dialogs resetDialogsAll; + private SparseIntArray loadingPinnedDialogs = new SparseIntArray(); private int loadingNotificationSettings; private boolean loadingNotificationSignUpSettings; @@ -167,7 +175,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter private int nextProxyInfoCheckTime; private boolean checkingProxyInfo; private int checkingProxyInfoRequestId; - private TLRPC.TL_dialog proxyDialog; + private TLRPC.Dialog proxyDialog; private boolean isLeftProxyChannel; private long proxyDialogId; private String proxyDialogAddress; @@ -218,6 +226,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter public int callConnectTimeout; public int callPacketTimeout; public int maxPinnedDialogsCount; + public int maxFolderPinnedDialogsCount; public int mapProvider; public int availableMapProviders; public String mapKey; @@ -262,6 +271,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter public static final int UPDATE_MASK_CHAT = 8192; //public static final int UPDATE_MASK_CHAT_ADMINS = 16384; public static final int UPDATE_MASK_MESSAGE_TEXT = 32768; + public static final int UPDATE_MASK_CHECK = 65536; + public static final int UPDATE_MASK_REORDER = 131072; public static final int UPDATE_MASK_ALL = UPDATE_MASK_AVATAR | UPDATE_MASK_STATUS | UPDATE_MASK_NAME | UPDATE_MASK_CHAT_AVATAR | UPDATE_MASK_CHAT_NAME | UPDATE_MASK_CHAT_MEMBERS | UPDATE_MASK_USER_PRINT | UPDATE_MASK_USER_PHONE | UPDATE_MASK_READ_DIALOG_MESSAGE | UPDATE_MASK_PHONE; private class ReadTask { @@ -277,10 +288,14 @@ public class MessagesController implements NotificationCenter.NotificationCenter public TLRPC.SendMessageAction action; } - private final Comparator dialogComparator = new Comparator() { + private final Comparator dialogComparator = new Comparator() { @Override - public int compare(TLRPC.TL_dialog dialog1, TLRPC.TL_dialog dialog2) { - if (!dialog1.pinned && dialog2.pinned) { + public int compare(TLRPC.Dialog dialog1, TLRPC.Dialog dialog2) { + if (dialog1 instanceof TLRPC.TL_dialogFolder && !(dialog2 instanceof TLRPC.TL_dialogFolder)) { + return -1; + } else if (!(dialog1 instanceof TLRPC.TL_dialogFolder) && dialog2 instanceof TLRPC.TL_dialogFolder) { + return 1; + } else if (!dialog1.pinned && dialog2.pinned) { return 1; } else if (dialog1.pinned && !dialog2.pinned) { return -1; @@ -406,6 +421,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter callConnectTimeout = mainPreferences.getInt("callConnectTimeout", 30000); callPacketTimeout = mainPreferences.getInt("callPacketTimeout", 10000); maxPinnedDialogsCount = mainPreferences.getInt("maxPinnedDialogsCount", 5); + maxFolderPinnedDialogsCount = mainPreferences.getInt("maxFolderPinnedDialogsCount", 100); maxMessageLength = mainPreferences.getInt("maxMessageLength", 4096); maxCaptionLength = mainPreferences.getInt("maxCaptionLength", 1024); mapProvider = mainPreferences.getInt("mapProvider", 0); @@ -457,6 +473,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter callConnectTimeout = config.call_connect_timeout_ms; callPacketTimeout = config.call_packet_timeout_ms; maxPinnedDialogsCount = config.pinned_dialogs_count_max; + maxFolderPinnedDialogsCount = config.pinned_infolder_count_max; maxMessageLength = config.message_length_max; maxCaptionLength = config.caption_length_max; defaultP2pContacts = config.default_p2p_contacts; @@ -531,6 +548,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter editor.putInt("callPacketTimeout", callPacketTimeout); editor.putString("linkPrefix", linkPrefix); editor.putInt("maxPinnedDialogsCount", maxPinnedDialogsCount); + editor.putInt("maxFolderPinnedDialogsCount", maxFolderPinnedDialogsCount); editor.putInt("maxMessageLength", maxMessageLength); editor.putInt("maxCaptionLength", maxCaptionLength); editor.putBoolean("defaultP2pContacts", defaultP2pContacts); @@ -571,6 +589,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter user = new TLRPC.TL_userForeign_old2(); user.phone = "42777"; user.id = 777000; + user.verified = true; user.first_name = "Telegram"; user.last_name = "Notifications"; user.status = null; @@ -734,7 +753,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (image != null) { String newKey = image.location.volume_id + "_" + image.location.local_id + "@100_100"; String oldKey = Utilities.MD5(path.getAbsolutePath()) + "@100_100"; - ImageLoader.getInstance().replaceImageInCache(oldKey, newKey, image.location, false); + ImageLoader.getInstance().replaceImageInCache(oldKey, newKey, ImageLocation.getForDocument(image, wallPaper.document), false); } NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.wallpapersNeedReload, wallPaper.id); } @@ -757,7 +776,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter obj.messageOwner.id = newMsgId; obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; } - TLRPC.TL_dialog dialog = dialogs_dict.get(did); + TLRPC.Dialog dialog = dialogs_dict.get(did); if (dialog != null && dialog.top_message == msgId) { dialog.top_message = newMsgId; NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); @@ -796,16 +815,17 @@ public class MessagesController implements NotificationCenter.NotificationCenter editor = emojiPreferences.edit(); editor.putLong("lastGifLoadTime", 0).putLong("lastStickersLoadTime", 0).putLong("lastStickersLoadTimeMask", 0).putLong("lastStickersLoadTimeFavs", 0).commit(); editor = mainPreferences.edit(); - editor.remove("gifhint").remove("soundHint").remove("dcDomainName").remove("webFileDatacenterId").commit(); + editor.remove("archivehint").remove("archivehint_l").remove("gifhint").remove("soundHint").remove("dcDomainName").remove("webFileDatacenterId").commit(); reloadingWebpages.clear(); reloadingWebpagesPending.clear(); dialogs_dict.clear(); dialogs_read_inbox_max.clear(); + loadingPinnedDialogs.clear(); dialogs_read_outbox_max.clear(); exportedChats.clear(); fullUsers.clear(); - dialogs.clear(); + dialogsByFolder.clear(); unreadUnmutedDialogs = 0; joiningToChannels.clear(); migratedChats.clear(); @@ -814,6 +834,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter pollsToCheckSize = 0; dialogsServerOnly.clear(); dialogsForward.clear(); + allDialogs.clear(); dialogsCanAddUsers.clear(); dialogsChannelsOnly.clear(); dialogsGroupsOnly.clear(); @@ -826,6 +847,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter objectsByUsernames.clear(); chats.clear(); dialogMessage.clear(); + deletedHistory.clear(); printingUsers.clear(); printingStrings.clear(); printingStringsTypes.clear(); @@ -834,7 +856,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter deletingDialogs.clear(); clearingHistoryDialogs.clear(); lastPrintingStringCount = 0; - nextDialogsCacheOffset = 0; Utilities.stageQueue.postRunnable(() -> { readTasks.clear(); @@ -843,6 +864,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter updatesQueuePts.clear(); updatesQueueQts.clear(); gettingUnknownChannels.clear(); + gettingUnknownDialogs.clear(); updatesStartWaitTimeSeq = 0; updatesStartWaitTimePts = 0; updatesStartWaitTimeQts = 0; @@ -863,6 +885,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter loadedFullParticipants.clear(); loadedFullChats.clear(); + dialogsLoaded = false; + nextDialogsCacheOffset.clear(); + loadingDialogs.clear(); + dialogsEndReached.clear(); + serverDialogsEndReached.clear(); + checkingTosUpdate = false; nextTosCheckTime = 0; nextProxyInfoCheckTime = 0; @@ -873,9 +901,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter currentDeletingTaskMids = null; currentDeletingTaskChannelId = 0; gettingNewDeleteTask = false; - loadingDialogs = false; - dialogsEndReached = false; - serverDialogsEndReached = false; loadingBlockedUsers = false; firstGettingTask = false; updatingState = false; @@ -1261,7 +1286,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } - public TLRPC.TL_userFull getUserFull(int uid) { + public TLRPC.UserFull getUserFull(int uid) { return fullUsers.get(uid); } @@ -1278,7 +1303,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter loadedFullChats.clear(); } - private void reloadDialogsReadValue(ArrayList dialogs, long did) { + private void reloadDialogsReadValue(ArrayList dialogs, long did) { if (did == 0 && (dialogs == null || dialogs.isEmpty())) { return; } @@ -1310,22 +1335,14 @@ public class MessagesController implements NotificationCenter.NotificationCenter TLRPC.TL_messages_peerDialogs res = (TLRPC.TL_messages_peerDialogs) response; ArrayList arrayList = new ArrayList<>(); for (int a = 0; a < res.dialogs.size(); a++) { - TLRPC.TL_dialog dialog = res.dialogs.get(a); + TLRPC.Dialog dialog = res.dialogs.get(a); if (dialog.read_inbox_max_id == 0) { dialog.read_inbox_max_id = 1; } if (dialog.read_outbox_max_id == 0) { dialog.read_outbox_max_id = 1; } - if (dialog.id == 0 && dialog.peer != null) { - if (dialog.peer.user_id != 0) { - dialog.id = dialog.peer.user_id; - } else if (dialog.peer.chat_id != 0) { - dialog.id = -dialog.peer.chat_id; - } else if (dialog.peer.channel_id != 0) { - dialog.id = -dialog.peer.channel_id; - } - } + DialogObject.initDialog(dialog); Integer value = dialogs_read_inbox_max.get(dialog.id); if (value == null) { @@ -1527,7 +1544,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (error == null) { - TLRPC.TL_userFull userFull = (TLRPC.TL_userFull) response; + TLRPC.UserFull userFull = (TLRPC.UserFull) response; MessagesStorage.getInstance(currentAccount).updateUserInfo(userFull, false); AndroidUtilities.runOnUIThread(() -> { @@ -2468,15 +2485,80 @@ public class MessagesController implements NotificationCenter.NotificationCenter }); } - public void deleteDialog(final long did, final int onlyHistory) { - deleteDialog(did, true, onlyHistory, 0); + public ArrayList getAllDialogs() { + return allDialogs; } - private void deleteDialog(final long did, final boolean first, final int onlyHistory, final int max_id) { - int lower_part = (int) did; - int high_id = (int) (did >> 32); - int max_id_delete = max_id; + public boolean isDialogsEndReached(int folderId) { + return dialogsEndReached.get(folderId); + } + public boolean isLoadingDialogs(int folderId) { + return loadingDialogs.get(folderId); + } + + public boolean isServerDialogsEndReached(int folderId) { + return serverDialogsEndReached.get(folderId); + } + + public boolean hasHiddenArchive() { + return SharedConfig.archiveHidden && dialogs_dict.get(DialogObject.makeFolderDialogId(1)) != null; + } + + public ArrayList getDialogs(int folderId) { + ArrayList dialogs = dialogsByFolder.get(folderId); + if (dialogs == null) { + return new ArrayList<>(); + } + return dialogs; + } + + private void removeDialog(TLRPC.Dialog dialog) { + if (dialog == null) { + return; + } + long did = dialog.id; + if (dialogsServerOnly.remove(dialog) && DialogObject.isChannel(dialog)) { + Utilities.stageQueue.postRunnable(() -> { + channelsPts.delete(-(int) did); + shortPollChannels.delete(-(int) did); + needShortPollChannels.delete(-(int) did); + shortPollOnlines.delete(-(int) did); + needShortPollOnlines.delete(-(int) did); + }); + } + allDialogs.remove(dialog); + dialogsCanAddUsers.remove(dialog); + dialogsChannelsOnly.remove(dialog); + dialogsGroupsOnly.remove(dialog); + dialogsUsersOnly.remove(dialog); + dialogsForward.remove(dialog); + dialogs_dict.remove(did); + dialogs_read_inbox_max.remove(did); + dialogs_read_outbox_max.remove(did); + + ArrayList dialogs = dialogsByFolder.get(dialog.folder_id); + if (dialogs != null) { + dialogs.remove(dialog); + } + } + + public void deleteDialog(final long did, final int onlyHistory) { + deleteDialog(did, onlyHistory, false); + } + + public void deleteDialog(final long did, final int onlyHistory, boolean revoke) { + deleteDialog(did, true, onlyHistory, 0, revoke, null, 0); + } + + public void setDialogsInTransaction(boolean transaction) { + dialogsInTransaction = transaction; + if (!transaction) { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload, true); + } + } + + protected void deleteDialog(final long did, final boolean first, final int onlyHistory, final int max_id, boolean revoke, TLRPC.InputPeer peer, final long taskId) { if (onlyHistory == 2) { MessagesStorage.getInstance(currentAccount).deleteDialog(did, onlyHistory); return; @@ -2484,14 +2566,19 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (onlyHistory == 0 || onlyHistory == 3) { DataQuery.getInstance(currentAccount).uninstallShortcut(did); } + int lower_part = (int) did; + int high_id = (int) (did >> 32); + int max_id_delete = max_id; if (first) { boolean isProxyDialog = false; MessagesStorage.getInstance(currentAccount).deleteDialog(did, onlyHistory); - TLRPC.TL_dialog dialog = dialogs_dict.get(did); + TLRPC.Dialog dialog = dialogs_dict.get(did); if (dialog != null) { if (max_id_delete == 0) { max_id_delete = Math.max(0, dialog.top_message); + max_id_delete = Math.max(max_id_delete, dialog.read_inbox_max_id); + max_id_delete = Math.max(max_id_delete, dialog.read_outbox_max_id); } if (onlyHistory == 0 || onlyHistory == 3) { if (isProxyDialog = (proxyDialog != null && proxyDialog.id == did)) { @@ -2504,25 +2591,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter } sortDialogs(null); } else { - dialogs.remove(dialog); - if (dialogsServerOnly.remove(dialog) && DialogObject.isChannel(dialog)) { - Utilities.stageQueue.postRunnable(() -> { - channelsPts.delete(-(int) did); - shortPollChannels.delete(-(int) did); - needShortPollChannels.delete(-(int) did); - shortPollOnlines.delete(-(int) did); - needShortPollOnlines.delete(-(int) did); - }); + removeDialog(dialog); + int offset = nextDialogsCacheOffset.get(dialog.folder_id, 0); + if (offset > 0) { + nextDialogsCacheOffset.put(dialog.folder_id, offset - 1); } - dialogsCanAddUsers.remove(dialog); - dialogsChannelsOnly.remove(dialog); - dialogsGroupsOnly.remove(dialog); - dialogsUsersOnly.remove(dialog); - dialogsForward.remove(dialog); - dialogs_dict.remove(did); - dialogs_read_inbox_max.remove(did); - dialogs_read_outbox_max.remove(did); - nextDialogsCacheOffset--; } } else { dialog.unread_count = 0; @@ -2576,11 +2649,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } } - if (isProxyDialog) { - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload, true); - } else { - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.removeAllMessagesFromDialog, did, false); + if (!dialogsInTransaction) { + if (isProxyDialog) { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload, true); + } else { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.removeAllMessagesFromDialog, did, false); + } } MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> NotificationsController.getInstance(currentAccount).removeNotificationsForDialog(did))); } @@ -2590,12 +2665,46 @@ public class MessagesController implements NotificationCenter.NotificationCenter } if (lower_part != 0) { - TLRPC.InputPeer peer = getInputPeer(lower_part); + if (peer == null) { + peer = getInputPeer(lower_part); + } if (peer == null) { return; } + + final long newTaskId; + if (!(peer instanceof TLRPC.TL_inputPeerChannel) || onlyHistory != 0) { + if (max_id_delete > 0 && max_id_delete != Integer.MAX_VALUE) { + deletedHistory.put(did, max_id_delete); + } + + if (taskId == 0) { + NativeByteBuffer data = null; + try { + data = new NativeByteBuffer(4 + 8 + 4 + 4 + 4 + 4 + peer.getObjectSize()); + data.writeInt32(13); + data.writeInt64(did); + data.writeBool(first); + data.writeInt32(onlyHistory); + data.writeInt32(max_id_delete); + data.writeBool(revoke); + peer.serializeToStream(data); + } catch (Exception e) { + FileLog.e(e); + } + newTaskId = MessagesStorage.getInstance(currentAccount).createPendingTask(data); + } else { + newTaskId = taskId; + } + } else { + newTaskId = taskId; + } + if (peer instanceof TLRPC.TL_inputPeerChannel) { if (onlyHistory == 0) { + if (newTaskId != 0) { + MessagesStorage.getInstance(currentAccount).removePendingTask(newTaskId); + } return; } TLRPC.TL_channels_deleteHistory req = new TLRPC.TL_channels_deleteHistory(); @@ -2604,21 +2713,30 @@ public class MessagesController implements NotificationCenter.NotificationCenter req.channel.access_hash = peer.access_hash; req.max_id = max_id_delete > 0 ? max_id_delete : Integer.MAX_VALUE; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - + if (newTaskId != 0) { + MessagesStorage.getInstance(currentAccount).removePendingTask(newTaskId); + } + AndroidUtilities.runOnUIThread(() -> deletedHistory.remove(did)); }, ConnectionsManager.RequestFlagInvokeAfter); } else { TLRPC.TL_messages_deleteHistory req = new TLRPC.TL_messages_deleteHistory(); req.peer = peer; req.max_id = (onlyHistory == 0 ? Integer.MAX_VALUE : max_id_delete); req.just_clear = onlyHistory != 0; + req.revoke = revoke; final int max_id_delete_final = max_id_delete; + final TLRPC.InputPeer peerFinal = peer; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + if (newTaskId != 0) { + MessagesStorage.getInstance(currentAccount).removePendingTask(newTaskId); + } if (error == null) { TLRPC.TL_messages_affectedHistory res = (TLRPC.TL_messages_affectedHistory) response; if (res.offset > 0) { - deleteDialog(did, false, onlyHistory, max_id_delete_final); + deleteDialog(did, false, onlyHistory, max_id_delete_final, revoke, peerFinal, 0); } processNewDifferenceParams(-1, res.pts, -1, res.pts_count); + MessagesStorage.getInstance(currentAccount).onDeleteQueryComplete(did); } }, ConnectionsManager.RequestFlagInvokeAfter); } @@ -2632,7 +2750,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } public void saveGif(Object parentObject, TLRPC.Document document) { - if (parentObject == null || document == null || !MessageObject.isGifDocument(document)) { + if (parentObject == null || !MessageObject.isGifDocument(document)) { return; } TLRPC.TL_messages_saveGif req = new TLRPC.TL_messages_saveGif(); @@ -2718,7 +2836,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter MessagesStorage.getInstance(currentAccount).loadUserInfo(user, force, classGuid); } - public void processUserInfo(TLRPC.User user, final TLRPC.TL_userFull info, final boolean fromCache, boolean force, final MessageObject pinnedMessageObject, int classGuid) { + public void processUserInfo(TLRPC.User user, final TLRPC.UserFull info, final boolean fromCache, boolean force, final MessageObject pinnedMessageObject, int classGuid) { if (fromCache) { loadFullUser(user, classGuid, force); } @@ -2813,7 +2931,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter req.id = channelViewsToSend.valueAt(a); req.increment = a == 0; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - if (error == null) { + if (response != null) { TLRPC.Vector vector = (TLRPC.Vector) response; final SparseArray channelViews = new SparseArray<>(); SparseIntArray array = channelViews.get(key); @@ -3136,6 +3254,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter proxyDialog = res2.dialogs.get(0); proxyDialog.id = did; + proxyDialog.folder_id = 0; if (DialogObject.isChannel(proxyDialog)) { channelsPts.put(-(int) proxyDialog.id, proxyDialog.pts); } @@ -3176,8 +3295,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (proxyDialog.id < 0) { TLRPC.Chat chat = getChat(-(int) proxyDialog.id); if (chat == null || chat.left || chat.kicked || chat.restricted) { - dialogs_dict.remove(proxyDialog.id); - dialogs.remove(proxyDialog); + removeDialog(proxyDialog); } } proxyDialog = null; @@ -3205,8 +3323,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (proxyDialog.id < 0) { TLRPC.Chat chat = getChat(-(int) proxyDialog.id); if (chat == null || chat.left || chat.kicked || chat.restricted) { - dialogs_dict.remove(proxyDialog.id); - dialogs.remove(proxyDialog); + removeDialog(proxyDialog); } } proxyDialog = null; @@ -3236,8 +3353,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (proxyDialog.id < 0) { TLRPC.Chat chat = getChat(-(int) proxyDialog.id); if (chat == null || chat.left || chat.kicked || chat.restricted) { - dialogs_dict.remove(proxyDialog.id); - dialogs.remove(proxyDialog); + removeDialog(proxyDialog); } } proxyDialog = null; @@ -3474,6 +3590,21 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } + protected void removeDeletedMessagesFromArray(final long dialog_id, ArrayList messages) { + int maxDeletedId = deletedHistory.get(dialog_id, 0); + if (maxDeletedId == 0) { + return; + } + for (int a = 0, N = messages.size(); a < N; a++) { + TLRPC.Message message = messages.get(a); + if (message.id <= maxDeletedId) { + messages.remove(a); + a--; + N--; + } + } + } + public void loadMessages(final long dialog_id, final int count, final int max_id, final int offset_date, boolean fromCache, int midDate, final int classGuid, final int load_type, final int last_message_id, final boolean isChannel, final int loadIndex) { loadMessages(dialog_id, count, max_id, offset_date, fromCache, midDate, classGuid, load_type, last_message_id, isChannel, loadIndex, 0, 0, 0, false, 0); } @@ -3501,7 +3632,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (response != null) { TLRPC.TL_messages_peerDialogs res = (TLRPC.TL_messages_peerDialogs) response; if (!res.dialogs.isEmpty()) { - TLRPC.TL_dialog dialog = res.dialogs.get(0); + TLRPC.Dialog dialog = res.dialogs.get(0); if (dialog.top_message != 0) { TLRPC.TL_messages_dialogs dialogs = new TLRPC.TL_messages_dialogs(); @@ -3543,6 +3674,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter int reqId = ConnectionsManager.getInstance(currentAccount).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); } @@ -3773,50 +3905,222 @@ public class MessagesController implements NotificationCenter.NotificationCenter }); } - public void loadDialogs(final int offset, final int count, boolean fromCache) { - if (loadingDialogs || resetingDialogs) { + private TLRPC.TL_dialogFolder ensureFolderDialogExists(int folderId, boolean[] folderCreated) { + if (folderId == 0) { + return null; + } + long folderDialogId = DialogObject.makeFolderDialogId(folderId); + TLRPC.Dialog dialog = dialogs_dict.get(folderDialogId); + if (dialog instanceof TLRPC.TL_dialogFolder) { + if (folderCreated != null) { + folderCreated[0] = false; + } + return (TLRPC.TL_dialogFolder) dialog; + } + if (folderCreated != null) { + folderCreated[0] = true; + } + TLRPC.TL_dialogFolder dialogFolder = new TLRPC.TL_dialogFolder(); + dialogFolder.id = folderDialogId; + dialogFolder.peer = new TLRPC.TL_peerUser(); + dialogFolder.folder = new TLRPC.TL_folder(); + dialogFolder.folder.id = folderId; + dialogFolder.folder.title = LocaleController.getString("ArchivedChats", R.string.ArchivedChats); + dialogFolder.pinned = true; + + int maxPinnedNum = 0; + for (int a = 0; a < allDialogs.size(); a++) { + TLRPC.Dialog d = allDialogs.get(a); + if (!d.pinned) { + break; + } + maxPinnedNum = Math.max(d.pinnedNum, maxPinnedNum); + } + dialogFolder.pinnedNum = maxPinnedNum + 1; + + TLRPC.TL_messages_dialogs dialogs = new TLRPC.TL_messages_dialogs(); + dialogs.dialogs.add(dialogFolder); + MessagesStorage.getInstance(currentAccount).putDialogs(dialogs, 1); + + dialogs_dict.put(folderDialogId, dialogFolder); + allDialogs.add(0, dialogFolder); + return dialogFolder; + } + + private void removeFolder(int folderId) { + long dialogId = DialogObject.makeFolderDialogId(folderId); + TLRPC.Dialog dialog = dialogs_dict.get(dialogId); + if (dialog == null) { return; } - loadingDialogs = true; + dialogs_dict.remove(dialogId); + allDialogs.remove(dialog); + sortDialogs(null); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.folderBecomeEmpty, folderId); + } + + protected void onFolderEmpty(int folderId) { + int[] dialogsLoadOffset = UserConfig.getInstance(currentAccount).getDialogLoadOffsets(folderId); + if (dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetId] == Integer.MAX_VALUE) { + removeFolder(folderId); + } else { + loadDialogs(folderId, 0, 10, false, () -> removeFolder(folderId)); + } + } + + public void checkIfFolderEmpty(int folderId) { + if (folderId == 0) { + return; + } + MessagesStorage.getInstance(currentAccount).checkIfFolderEmpty(folderId); + } + + public int addDialogToFolder(long dialogId, int folderId, int pinnedNum, long taskId) { + ArrayList arrayList = new ArrayList<>(1); + arrayList.add(dialogId); + return addDialogToFolder(arrayList, folderId, pinnedNum, null, taskId); + } + + public int addDialogToFolder(ArrayList dialogIds, int folderId, int pinnedNum, ArrayList peers, long taskId) { + TLRPC.TL_folders_editPeerFolders req = new TLRPC.TL_folders_editPeerFolders(); + boolean[] folderCreated = null; + + final long newTaskId; + if (taskId == 0) { + boolean added = false; + int selfUserId = UserConfig.getInstance(currentAccount).getClientUserId(); + int size = 0; + for (int a = 0, N = dialogIds.size(); a < N; a++) { + long dialogId = dialogIds.get(a); + if (!DialogObject.isPeerDialogId(dialogId) && !DialogObject.isSecretDialogId(dialogId)) { + continue; + } + if (folderId == 1 && (dialogId == selfUserId || dialogId == 777000)) { + continue; + } + TLRPC.Dialog dialog = dialogs_dict.get(dialogId); + if (dialog == null) { + continue; + } + added = true; + dialog.folder_id = folderId; + if (pinnedNum > 0) { + dialog.pinned = true; + dialog.pinnedNum = pinnedNum; + } else { + dialog.pinned = false; + dialog.pinnedNum = 0; + } + if (folderCreated == null) { + folderCreated = new boolean[1]; + ensureFolderDialogExists(folderId, folderCreated); + } + if (DialogObject.isSecretDialogId(dialogId)) { + MessagesStorage.getInstance(currentAccount).setDialogsFolderId(null, null, dialogId, folderId); + } else { + TLRPC.TL_inputFolderPeer folderPeer = new TLRPC.TL_inputFolderPeer(); + folderPeer.folder_id = folderId; + folderPeer.peer = getInputPeer((int) dialogId); + req.folder_peers.add(folderPeer); + size += folderPeer.getObjectSize(); + } + } + if (!added) { + return 0; + } + sortDialogs(null); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); + + if (size != 0) { + NativeByteBuffer data = null; + try { + data = new NativeByteBuffer(4 + 4 + 4 + size); + data.writeInt32(17); + data.writeInt32(folderId); + data.writeInt32(req.folder_peers.size()); + for (int a = 0, N = req.folder_peers.size(); a < N; a++) { + req.folder_peers.get(a).serializeToStream(data); + } + } catch (Exception e) { + FileLog.e(e); + } + newTaskId = MessagesStorage.getInstance(currentAccount).createPendingTask(data); + } else { + newTaskId = 0; + } + } else { + req.folder_peers = peers; + newTaskId = taskId; + } + if (!req.folder_peers.isEmpty()) { + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + if (error == null) { + processUpdates((TLRPC.Updates) response, false); + } + if (newTaskId != 0) { + MessagesStorage.getInstance(currentAccount).removePendingTask(newTaskId); + } + }); + MessagesStorage.getInstance(currentAccount).setDialogsFolderId(null, req.folder_peers, 0, folderId); + } + return folderCreated == null ? 0 : (folderCreated[0] ? 2 : 1); + } + + public void loadDialogs(final int folderId, final int offset, final int count, boolean fromCache) { + loadDialogs(folderId, offset, count, fromCache, null); + } + + public void loadDialogs(final int folderId, final int offset, final int count, boolean fromCache, Runnable onEmptyCallback) { + if (loadingDialogs.get(folderId) || resetingDialogs) { + return; + } + loadingDialogs.put(folderId, true); NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); if (BuildVars.LOGS_ENABLED) { - FileLog.d("load cacheOffset = " + offset + " count = " + count + " cache = " + fromCache); + FileLog.d("folderId = " + folderId + " load cacheOffset = " + offset + " count = " + count + " cache = " + fromCache); } if (fromCache) { - MessagesStorage.getInstance(currentAccount).getDialogs(offset == 0 ? 0 : nextDialogsCacheOffset, count); + MessagesStorage.getInstance(currentAccount).getDialogs(folderId, offset == 0 ? 0 : nextDialogsCacheOffset.get(folderId, 0), count); } else { TLRPC.TL_messages_getDialogs req = new TLRPC.TL_messages_getDialogs(); req.limit = count; req.exclude_pinned = true; - if (UserConfig.getInstance(currentAccount).dialogsLoadOffsetId != -1) { - if (UserConfig.getInstance(currentAccount).dialogsLoadOffsetId == Integer.MAX_VALUE) { - dialogsEndReached = true; - serverDialogsEndReached = true; - loadingDialogs = false; + if (folderId != 0) { + req.flags |= 2; + req.folder_id = folderId; + } + int[] dialogsLoadOffset = UserConfig.getInstance(currentAccount).getDialogLoadOffsets(folderId); + if (dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetId] != -1) { + if (dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetId] == Integer.MAX_VALUE) { + dialogsEndReached.put(folderId, true); + serverDialogsEndReached.put(folderId, true); + loadingDialogs.put(folderId, false); NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); return; } - req.offset_id = UserConfig.getInstance(currentAccount).dialogsLoadOffsetId; - req.offset_date = UserConfig.getInstance(currentAccount).dialogsLoadOffsetDate; + req.offset_id = dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetId]; + req.offset_date = dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetDate]; if (req.offset_id == 0) { req.offset_peer = new TLRPC.TL_inputPeerEmpty(); } else { - if (UserConfig.getInstance(currentAccount).dialogsLoadOffsetChannelId != 0) { + if (dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetChannelId] != 0) { req.offset_peer = new TLRPC.TL_inputPeerChannel(); - req.offset_peer.channel_id = UserConfig.getInstance(currentAccount).dialogsLoadOffsetChannelId; - } else if (UserConfig.getInstance(currentAccount).dialogsLoadOffsetUserId != 0) { + req.offset_peer.channel_id = dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetChannelId]; + } else if (dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetUserId] != 0) { req.offset_peer = new TLRPC.TL_inputPeerUser(); - req.offset_peer.user_id = UserConfig.getInstance(currentAccount).dialogsLoadOffsetUserId; + req.offset_peer.user_id = dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetUserId]; } else { req.offset_peer = new TLRPC.TL_inputPeerChat(); - req.offset_peer.chat_id = UserConfig.getInstance(currentAccount).dialogsLoadOffsetChatId; + req.offset_peer.chat_id = dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetChatId]; } - req.offset_peer.access_hash = UserConfig.getInstance(currentAccount).dialogsLoadOffsetAccess; + req.offset_peer.access_hash = ((long) dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetAccess_1]) | ((long) dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetAccess_1] << 32); } } else { boolean found = false; + ArrayList dialogs = getDialogs(folderId); for (int a = dialogs.size() - 1; a >= 0; a--) { - TLRPC.TL_dialog dialog = dialogs.get(a); + TLRPC.Dialog dialog = dialogs.get(a); if (dialog.pinned) { continue; } @@ -3848,7 +4152,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (error == null) { final TLRPC.messages_Dialogs dialogsRes = (TLRPC.messages_Dialogs) response; - processLoadedDialogs(dialogsRes, null, 0, count, 0, false, false, false); + processLoadedDialogs(dialogsRes, null, folderId, 0, count, 0, false, false, false); + if (onEmptyCallback != null && dialogsRes.dialogs.isEmpty()) { + AndroidUtilities.runOnUIThread(onEmptyCallback); + } } }); } @@ -3976,16 +4283,119 @@ public class MessagesController implements NotificationCenter.NotificationCenter resetDialogs(true, MessagesStorage.getInstance(currentAccount).getLastSeqValue(), MessagesStorage.getInstance(currentAccount).getLastPtsValue(), MessagesStorage.getInstance(currentAccount).getLastDateValue(), MessagesStorage.getInstance(currentAccount).getLastQtsValue()); } + protected void loadUnknownDialog(final TLRPC.InputPeer peer, final long taskId) { + if (peer == null) { + return; + } + long dialogId = DialogObject.getPeerDialogId(peer); + if (gettingUnknownDialogs.indexOfKey(dialogId) >= 0) { + return; + } + gettingUnknownDialogs.put(dialogId, true); + + TLRPC.TL_messages_getPeerDialogs req = new TLRPC.TL_messages_getPeerDialogs(); + TLRPC.TL_inputDialogPeer inputDialogPeer = new TLRPC.TL_inputDialogPeer(); + inputDialogPeer.peer = peer; + req.peers.add(inputDialogPeer); + final long newTaskId; + if (taskId == 0) { + NativeByteBuffer data = null; + try { + data = new NativeByteBuffer(4 + peer.getObjectSize()); + data.writeInt32(15); + peer.serializeToStream(data); + } catch (Exception e) { + FileLog.e(e); + } + newTaskId = MessagesStorage.getInstance(currentAccount).createPendingTask(data); + } else { + newTaskId = taskId; + } + 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.TL_dialog dialog = (TLRPC.TL_dialog) res.dialogs.get(0); + TLRPC.TL_messages_dialogs dialogs = new TLRPC.TL_messages_dialogs(); + dialogs.dialogs.addAll(res.dialogs); + dialogs.messages.addAll(res.messages); + dialogs.users.addAll(res.users); + dialogs.chats.addAll(res.chats); + processLoadedDialogs(dialogs, null, dialog.folder_id, 0, 1, DIALOGS_LOAD_TYPE_UNKNOWN, false, false, false); + } + } + if (newTaskId != 0) { + MessagesStorage.getInstance(currentAccount).removePendingTask(newTaskId); + } + gettingUnknownDialogs.delete(dialogId); + }); + } + + private void fetchFolderInLoadedPinnedDialogs(TLRPC.TL_messages_peerDialogs res) { + for (int a = 0, N = res.dialogs.size(); a < N; a++) { + TLRPC.Dialog dialog = res.dialogs.get(a); + if (dialog instanceof TLRPC.TL_dialogFolder) { + TLRPC.TL_dialogFolder dialogFolder = (TLRPC.TL_dialogFolder) dialog; + long folderTopDialogId = DialogObject.getPeerDialogId(dialog.peer); + for (int b = 0, N2 = res.messages.size(); b < N2; b++) { + TLRPC.Message message = res.messages.get(b); + long messageDialogId = MessageObject.getDialogId(message); + if (folderTopDialogId == messageDialogId && dialog.top_message == message.id) { + TLRPC.TL_dialog newDialog = new TLRPC.TL_dialog(); + newDialog.peer = dialog.peer; + newDialog.top_message = dialog.top_message; + newDialog.folder_id = dialogFolder.folder.id; + newDialog.flags |= 16; + res.dialogs.add(newDialog); + + TLRPC.InputPeer inputPeer; + if (dialog.peer instanceof TLRPC.TL_peerChannel) { + inputPeer = new TLRPC.TL_inputPeerChannel(); + inputPeer.channel_id = dialog.peer.channel_id; + for (int c = 0, N3 = res.chats.size(); c < N3; c++) { + TLRPC.Chat chat = res.chats.get(c); + if (chat.id == inputPeer.channel_id) { + inputPeer.access_hash = chat.access_hash; + break; + } + } + } else if (dialog.peer instanceof TLRPC.TL_peerChat) { + inputPeer = new TLRPC.TL_inputPeerChat(); + inputPeer.chat_id = dialog.peer.chat_id; + } else { + inputPeer = new TLRPC.TL_inputPeerUser(); + inputPeer.user_id = dialog.peer.user_id; + for (int c = 0, N3 = res.users.size(); c < N3; c++) { + TLRPC.User user = res.users.get(c); + if (user.id == inputPeer.user_id) { + inputPeer.access_hash = user.access_hash; + break; + } + } + } + loadUnknownDialog(inputPeer, 0); + break; + } + } + } + } + } + private void resetDialogs(boolean query, final int seq, final int newPts, final int date, final int qts) { if (query) { if (resetingDialogs) { return; } + UserConfig.getInstance(currentAccount).setPinnedDialogsLoaded(1, false); resetingDialogs = true; TLRPC.TL_messages_getPinnedDialogs req = new TLRPC.TL_messages_getPinnedDialogs(); ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (response != null) { resetDialogsPinned = (TLRPC.TL_messages_peerDialogs) response; + for (int a = 0; a < resetDialogsPinned.dialogs.size(); a++) { + TLRPC.Dialog d = resetDialogsPinned.dialogs.get(a); + d.pinned = true; + } resetDialogs(false, seq, newPts, date, qts); } }); @@ -4002,12 +4412,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter } else if (resetDialogsPinned != null && resetDialogsAll != null) { int messagesCount = resetDialogsAll.messages.size(); int dialogsCount = resetDialogsAll.dialogs.size(); + fetchFolderInLoadedPinnedDialogs(resetDialogsPinned); resetDialogsAll.dialogs.addAll(resetDialogsPinned.dialogs); resetDialogsAll.messages.addAll(resetDialogsPinned.messages); resetDialogsAll.users.addAll(resetDialogsPinned.users); resetDialogsAll.chats.addAll(resetDialogsPinned.chats); - final LongSparseArray new_dialogs_dict = new LongSparseArray<>(); + final LongSparseArray new_dialogs_dict = new LongSparseArray<>(); final LongSparseArray new_dialogMessage = new LongSparseArray<>(); final SparseArray usersDict = new SparseArray<>(); final SparseArray chatsDict = new SparseArray<>(); @@ -4048,16 +4459,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter } for (int a = 0; a < resetDialogsAll.dialogs.size(); a++) { - TLRPC.TL_dialog d = resetDialogsAll.dialogs.get(a); - if (d.id == 0 && d.peer != null) { - if (d.peer.user_id != 0) { - d.id = d.peer.user_id; - } else if (d.peer.chat_id != 0) { - d.id = -d.peer.chat_id; - } else if (d.peer.channel_id != 0) { - d.id = -d.peer.channel_id; - } - } + TLRPC.Dialog d = resetDialogsAll.dialogs.get(a); + DialogObject.initDialog(d); if (d.id == 0) { continue; } @@ -4125,7 +4528,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } - protected void completeDialogsReset(final TLRPC.messages_Dialogs dialogsRes, final int messagesCount, final int seq, final int newPts, final int date, final int qts, final LongSparseArray new_dialogs_dict, final LongSparseArray new_dialogMessage, final TLRPC.Message lastMessage) { + protected void completeDialogsReset(final TLRPC.messages_Dialogs dialogsRes, final int messagesCount, final int seq, final int newPts, final int date, final int qts, final LongSparseArray new_dialogs_dict, final LongSparseArray new_dialogMessage, final TLRPC.Message lastMessage) { Utilities.stageQueue.postRunnable(() -> { gettingDifference = false; MessagesStorage.getInstance(currentAccount).setLastPtsValue(newPts); @@ -4143,9 +4546,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter putUsers(dialogsRes.users, false); putChats(dialogsRes.chats, false); - for (int a = 0; a < dialogs.size(); a++) { - TLRPC.TL_dialog oldDialog = dialogs.get(a); - if ((int) oldDialog.id != 0) { + for (int a = 0; a < allDialogs.size(); a++) { + TLRPC.Dialog oldDialog = allDialogs.get(a); + if (!DialogObject.isSecretDialogId(oldDialog.id)) { dialogs_dict.remove(oldDialog.id); MessageObject messageObject = dialogMessage.get(oldDialog.id); dialogMessage.remove(oldDialog.id); @@ -4160,7 +4563,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter for (int a = 0; a < new_dialogs_dict.size(); a++) { long key = new_dialogs_dict.keyAt(a); - TLRPC.TL_dialog value = new_dialogs_dict.valueAt(a); + TLRPC.Dialog value = new_dialogs_dict.valueAt(a); if (value.draft instanceof TLRPC.TL_draftMessage) { DataQuery.getInstance(currentAccount).saveDraft(value.id, value.draft, null, false); } @@ -4175,16 +4578,21 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } - dialogs.clear(); + allDialogs.clear(); for (int a = 0, size = dialogs_dict.size(); a < size; a++) { - dialogs.add(dialogs_dict.valueAt(a)); + allDialogs.add(dialogs_dict.valueAt(a)); } sortDialogs(null); - dialogsEndReached = true; - serverDialogsEndReached = false; + dialogsEndReached.put(0, true); + serverDialogsEndReached.put(0, false); - if (UserConfig.getInstance(currentAccount).totalDialogsLoadCount < 400 && UserConfig.getInstance(currentAccount).dialogsLoadOffsetId != -1 && UserConfig.getInstance(currentAccount).dialogsLoadOffsetId != Integer.MAX_VALUE) { - loadDialogs(0, 100, false); + dialogsEndReached.put(1, true); + serverDialogsEndReached.put(1, false); + + int totalDialogsLoadCount = UserConfig.getInstance(currentAccount).getTotalDialogsCount(0); + int[] dialogsLoadOffset = UserConfig.getInstance(currentAccount).getDialogLoadOffsets(0); + if (totalDialogsLoadCount < 400 && dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetId] != -1 && dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetId] != Integer.MAX_VALUE) { + loadDialogs(0, 100, 0, false); } NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); }); @@ -4226,7 +4634,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> { try { int offsetId; - UserConfig.getInstance(currentAccount).totalDialogsLoadCount += dialogsRes.dialogs.size(); + int totalDialogsLoadCount = UserConfig.getInstance(currentAccount).getTotalDialogsCount(0); + UserConfig.getInstance(currentAccount).setTotalDialogsCount(0, totalDialogsLoadCount + dialogsRes.dialogs.size()); TLRPC.Message lastMessage = null; for (int a = 0; a < dialogsRes.messages.size(); a++) { TLRPC.Message message = dialogsRes.messages.get(a); @@ -4246,36 +4655,37 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (BuildVars.LOGS_ENABLED) { FileLog.d("migrate stop due to not 100 dialogs"); } - UserConfig.getInstance(currentAccount).dialogsLoadOffsetId = Integer.MAX_VALUE; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetDate = UserConfig.getInstance(currentAccount).migrateOffsetDate; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetUserId = UserConfig.getInstance(currentAccount).migrateOffsetUserId; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChatId = UserConfig.getInstance(currentAccount).migrateOffsetChatId; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChannelId = UserConfig.getInstance(currentAccount).migrateOffsetChannelId; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetAccess = UserConfig.getInstance(currentAccount).migrateOffsetAccess; + for (int i = 0; i < 2; i++) { + UserConfig.getInstance(currentAccount).setDialogsLoadOffset(i, + Integer.MAX_VALUE, + UserConfig.getInstance(currentAccount).migrateOffsetDate, + UserConfig.getInstance(currentAccount).migrateOffsetUserId, + UserConfig.getInstance(currentAccount).migrateOffsetChatId, + UserConfig.getInstance(currentAccount).migrateOffsetChannelId, + UserConfig.getInstance(currentAccount).migrateOffsetAccess); + } offsetId = -1; } StringBuilder dids = new StringBuilder(dialogsRes.dialogs.size() * 12); - LongSparseArray dialogHashMap = new LongSparseArray<>(); + LongSparseArray dialogHashMap = new LongSparseArray<>(); for (int a = 0; a < dialogsRes.dialogs.size(); a++) { - TLRPC.TL_dialog dialog = dialogsRes.dialogs.get(a); - if (dialog.peer.channel_id != 0) { - dialog.id = -dialog.peer.channel_id; - } else if (dialog.peer.chat_id != 0) { - dialog.id = -dialog.peer.chat_id; - } else { - dialog.id = dialog.peer.user_id; - } + TLRPC.Dialog dialog = dialogsRes.dialogs.get(a); + DialogObject.initDialog(dialog); if (dids.length() > 0) { dids.append(","); } dids.append(dialog.id); dialogHashMap.put(dialog.id, dialog); } - SQLiteCursor cursor = MessagesStorage.getInstance(currentAccount).getDatabase().queryFinalized(String.format(Locale.US, "SELECT did FROM dialogs WHERE did IN (%s)", dids.toString())); + SQLiteCursor cursor = MessagesStorage.getInstance(currentAccount).getDatabase().queryFinalized(String.format(Locale.US, "SELECT did, folder_id FROM dialogs WHERE did IN (%s)", dids.toString())); while (cursor.next()) { long did = cursor.longValue(0); - TLRPC.TL_dialog dialog = dialogHashMap.get(did); + int folder_id = cursor.intValue(1); + TLRPC.Dialog dialog = dialogHashMap.get(did); + if (dialog.folder_id != folder_id) { + continue; + } dialogHashMap.remove(did); if (dialog != null) { dialogsRes.dialogs.remove(dialog); @@ -4304,12 +4714,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter TLRPC.Message message = dialogsRes.messages.get(a); if (message.date < date) { if (offset != -1) { - UserConfig.getInstance(currentAccount).dialogsLoadOffsetId = UserConfig.getInstance(currentAccount).migrateOffsetId; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetDate = UserConfig.getInstance(currentAccount).migrateOffsetDate; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetUserId = UserConfig.getInstance(currentAccount).migrateOffsetUserId; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChatId = UserConfig.getInstance(currentAccount).migrateOffsetChatId; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChannelId = UserConfig.getInstance(currentAccount).migrateOffsetChannelId; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetAccess = UserConfig.getInstance(currentAccount).migrateOffsetAccess; + for (int i = 0; i < 2; i++) { + UserConfig.getInstance(currentAccount).setDialogsLoadOffset(i, + UserConfig.getInstance(currentAccount).migrateOffsetId, + UserConfig.getInstance(currentAccount).migrateOffsetDate, + UserConfig.getInstance(currentAccount).migrateOffsetUserId, + UserConfig.getInstance(currentAccount).migrateOffsetChatId, + UserConfig.getInstance(currentAccount).migrateOffsetChannelId, + UserConfig.getInstance(currentAccount).migrateOffsetAccess); + } offsetId = -1; if (BuildVars.LOGS_ENABLED) { FileLog.d("migrate stop due to reached loaded dialogs " + LocaleController.getInstance().formatterStats.format((long) date * 1000)); @@ -4318,7 +4731,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialogsRes.messages.remove(a); a--; long did = MessageObject.getDialogId(message); - TLRPC.TL_dialog dialog = dialogHashMap.get(did); + TLRPC.Dialog dialog = dialogHashMap.get(did); dialogHashMap.remove(did); if (dialog != null) { dialogsRes.dialogs.remove(dialog); @@ -4326,12 +4739,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } if (lastMessage != null && lastMessage.date < date && offset != -1) { - UserConfig.getInstance(currentAccount).dialogsLoadOffsetId = UserConfig.getInstance(currentAccount).migrateOffsetId; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetDate = UserConfig.getInstance(currentAccount).migrateOffsetDate; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetUserId = UserConfig.getInstance(currentAccount).migrateOffsetUserId; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChatId = UserConfig.getInstance(currentAccount).migrateOffsetChatId; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChannelId = UserConfig.getInstance(currentAccount).migrateOffsetChannelId; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetAccess = UserConfig.getInstance(currentAccount).migrateOffsetAccess; + for (int i = 0; i < 2; i++) { + UserConfig.getInstance(currentAccount).setDialogsLoadOffset(i, + UserConfig.getInstance(currentAccount).migrateOffsetId, + UserConfig.getInstance(currentAccount).migrateOffsetDate, + UserConfig.getInstance(currentAccount).migrateOffsetUserId, + UserConfig.getInstance(currentAccount).migrateOffsetChatId, + UserConfig.getInstance(currentAccount).migrateOffsetChannelId, + UserConfig.getInstance(currentAccount).migrateOffsetAccess); + } offsetId = -1; if (BuildVars.LOGS_ENABLED) { FileLog.d("migrate stop due to reached loaded dialogs " + LocaleController.getInstance().formatterStats.format((long) date * 1000)); @@ -4376,7 +4792,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } - processLoadedDialogs(dialogsRes, null, offsetId, 0, 0, false, true, false); + processLoadedDialogs(dialogsRes, null, 0, offsetId, 0, 0, false, true, false); } catch (Exception e) { FileLog.e(e); AndroidUtilities.runOnUIThread(() -> migratingDialogs = false); @@ -4388,7 +4804,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter }); } - public void processLoadedDialogs(final TLRPC.messages_Dialogs dialogsRes, final ArrayList encChats, final int offset, final int count, final int loadType, final boolean resetEnd, final boolean migrate, final boolean fromCache) { + private int DIALOGS_LOAD_TYPE_CACHE = 1; + private int DIALOGS_LOAD_TYPE_CHANNEL = 2; + private int DIALOGS_LOAD_TYPE_UNKNOWN = 3; + + public void processLoadedDialogs(final TLRPC.messages_Dialogs dialogsRes, final ArrayList encChats, final int folderId, final int offset, final int count, final int loadType, final boolean resetEnd, final boolean migrate, final boolean fromCache) { Utilities.stageQueue.postRunnable(() -> { if (!firstGettingTask) { getNewDeleteTask(null, 0); @@ -4396,27 +4816,28 @@ public class MessagesController implements NotificationCenter.NotificationCenter } if (BuildVars.LOGS_ENABLED) { - FileLog.d("loaded loadType " + loadType + " count " + dialogsRes.dialogs.size()); + FileLog.d("loaded folderId " + folderId + " loadType " + loadType + " count " + dialogsRes.dialogs.size()); } - if (loadType == 1 && dialogsRes.dialogs.size() == 0) { + int[] dialogsLoadOffset = UserConfig.getInstance(currentAccount).getDialogLoadOffsets(folderId); + if (loadType == DIALOGS_LOAD_TYPE_CACHE && dialogsRes.dialogs.size() == 0) { AndroidUtilities.runOnUIThread(() -> { putUsers(dialogsRes.users, true); - loadingDialogs = false; + loadingDialogs.put(folderId, false); if (resetEnd) { - dialogsEndReached = false; - serverDialogsEndReached = false; - } else if (UserConfig.getInstance(currentAccount).dialogsLoadOffsetId == Integer.MAX_VALUE) { - dialogsEndReached = true; - serverDialogsEndReached = true; + dialogsEndReached.put(folderId, false); + serverDialogsEndReached.put(folderId, false); + } else if (dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetId] == Integer.MAX_VALUE) { + dialogsEndReached.put(folderId, true); + serverDialogsEndReached.put(folderId, true); } else { - loadDialogs(0, count, false); + loadDialogs(folderId, 0, count, false); } NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); }); return; } - final LongSparseArray new_dialogs_dict = new LongSparseArray<>(); + final LongSparseArray new_dialogs_dict = new LongSparseArray<>(); final SparseArray enc_chats_dict; final LongSparseArray new_dialogMessage = new LongSparseArray<>(); final SparseArray usersDict = new SparseArray<>(); @@ -4439,8 +4860,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter } else { enc_chats_dict = null; } - if (loadType == 1) { - nextDialogsCacheOffset = offset + count; + if (loadType == DIALOGS_LOAD_TYPE_CACHE) { + nextDialogsCacheOffset.put(folderId, offset + count); } TLRPC.Message lastMessage = null; @@ -4467,63 +4888,70 @@ public class MessagesController implements NotificationCenter.NotificationCenter new_dialogMessage.put(messageObject.getDialogId(), messageObject); } - if (!fromCache && !migrate && UserConfig.getInstance(currentAccount).dialogsLoadOffsetId != -1 && loadType == 0) { - if (lastMessage != null && lastMessage.id != UserConfig.getInstance(currentAccount).dialogsLoadOffsetId) { - UserConfig.getInstance(currentAccount).totalDialogsLoadCount += dialogsRes.dialogs.size(); - UserConfig.getInstance(currentAccount).dialogsLoadOffsetId = lastMessage.id; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetDate = lastMessage.date; + if (!fromCache && !migrate && dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetId] != -1 && loadType == 0) { + int totalDialogsLoadCount = UserConfig.getInstance(currentAccount).getTotalDialogsCount(folderId); + int dialogsLoadOffsetId; + int dialogsLoadOffsetDate = 0; + int dialogsLoadOffsetChannelId = 0; + int dialogsLoadOffsetChatId = 0; + int dialogsLoadOffsetUserId = 0; + long dialogsLoadOffsetAccess = 0; + if (lastMessage != null && lastMessage.id != dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetId]) { + totalDialogsLoadCount += dialogsRes.dialogs.size(); + dialogsLoadOffsetId = lastMessage.id; + dialogsLoadOffsetDate = lastMessage.date; if (lastMessage.to_id.channel_id != 0) { - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChannelId = lastMessage.to_id.channel_id; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChatId = 0; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetUserId = 0; + dialogsLoadOffsetChannelId = lastMessage.to_id.channel_id; + dialogsLoadOffsetChatId = 0; + dialogsLoadOffsetUserId = 0; for (int a = 0; a < dialogsRes.chats.size(); a++) { TLRPC.Chat chat = dialogsRes.chats.get(a); - if (chat.id == UserConfig.getInstance(currentAccount).dialogsLoadOffsetChannelId) { - UserConfig.getInstance(currentAccount).dialogsLoadOffsetAccess = chat.access_hash; + if (chat.id == dialogsLoadOffsetChannelId) { + dialogsLoadOffsetAccess = chat.access_hash; break; } } } else if (lastMessage.to_id.chat_id != 0) { - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChatId = lastMessage.to_id.chat_id; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChannelId = 0; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetUserId = 0; + dialogsLoadOffsetChatId = lastMessage.to_id.chat_id; + dialogsLoadOffsetChannelId = 0; + dialogsLoadOffsetUserId = 0; for (int a = 0; a < dialogsRes.chats.size(); a++) { TLRPC.Chat chat = dialogsRes.chats.get(a); - if (chat.id == UserConfig.getInstance(currentAccount).dialogsLoadOffsetChatId) { - UserConfig.getInstance(currentAccount).dialogsLoadOffsetAccess = chat.access_hash; + if (chat.id == dialogsLoadOffsetChatId) { + dialogsLoadOffsetAccess = chat.access_hash; break; } } } else if (lastMessage.to_id.user_id != 0) { - UserConfig.getInstance(currentAccount).dialogsLoadOffsetUserId = lastMessage.to_id.user_id; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChatId = 0; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChannelId = 0; + dialogsLoadOffsetUserId = lastMessage.to_id.user_id; + dialogsLoadOffsetChatId = 0; + dialogsLoadOffsetChannelId = 0; for (int a = 0; a < dialogsRes.users.size(); a++) { TLRPC.User user = dialogsRes.users.get(a); - if (user.id == UserConfig.getInstance(currentAccount).dialogsLoadOffsetUserId) { - UserConfig.getInstance(currentAccount).dialogsLoadOffsetAccess = user.access_hash; + if (user.id == dialogsLoadOffsetUserId) { + dialogsLoadOffsetAccess = user.access_hash; break; } } } } else { - UserConfig.getInstance(currentAccount).dialogsLoadOffsetId = Integer.MAX_VALUE; + dialogsLoadOffsetId = Integer.MAX_VALUE; } + UserConfig.getInstance(currentAccount).setDialogsLoadOffset(folderId, + dialogsLoadOffsetId, + dialogsLoadOffsetDate, + dialogsLoadOffsetUserId, + dialogsLoadOffsetChatId, + dialogsLoadOffsetChannelId, + dialogsLoadOffsetAccess); + UserConfig.getInstance(currentAccount).setTotalDialogsCount(folderId, totalDialogsLoadCount); UserConfig.getInstance(currentAccount).saveConfig(false); } - final ArrayList dialogsToReload = new ArrayList<>(); + final ArrayList dialogsToReload = new ArrayList<>(); for (int a = 0; a < dialogsRes.dialogs.size(); a++) { - TLRPC.TL_dialog d = dialogsRes.dialogs.get(a); - if (d.id == 0 && d.peer != null) { - if (d.peer.user_id != 0) { - d.id = d.peer.user_id; - } else if (d.peer.chat_id != 0) { - d.id = -d.peer.chat_id; - } else if (d.peer.channel_id != 0) { - d.id = -d.peer.channel_id; - } - } + TLRPC.Dialog d = dialogsRes.dialogs.get(a); + DialogObject.initDialog(d); if (d.id == 0) { continue; } @@ -4563,7 +4991,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } new_dialogs_dict.put(d.id, d); - if (allowCheck && loadType == 1 && (d.read_outbox_max_id == 0 || d.read_inbox_max_id == 0) && d.top_message != 0) { + if (allowCheck && loadType == DIALOGS_LOAD_TYPE_CACHE && (d.read_outbox_max_id == 0 || d.read_inbox_max_id == 0) && d.top_message != 0) { dialogsToReload.add(d); } @@ -4580,7 +5008,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialogs_read_outbox_max.put(d.id, Math.max(value, d.read_outbox_max_id)); } - if (loadType != 1) { + if (loadType != DIALOGS_LOAD_TYPE_CACHE) { ImageLoader.saveMessagesThumbs(dialogsRes.messages); for (int a = 0; a < dialogsRes.messages.size(); a++) { @@ -4608,21 +5036,21 @@ public class MessagesController implements NotificationCenter.NotificationCenter } MessagesStorage.getInstance(currentAccount).putDialogs(dialogsRes, 0); } - if (loadType == 2) { + if (loadType == DIALOGS_LOAD_TYPE_CHANNEL) { TLRPC.Chat chat = dialogsRes.chats.get(0); getChannelDifference(chat.id); checkChannelInviter(chat.id); } AndroidUtilities.runOnUIThread(() -> { - if (loadType != 1) { + if (loadType != DIALOGS_LOAD_TYPE_CACHE) { applyDialogsNotificationsSettings(dialogsRes.dialogs); if (!UserConfig.getInstance(currentAccount).draftsLoaded) { DataQuery.getInstance(currentAccount).loadDrafts(); } } - putUsers(dialogsRes.users, loadType == 1); - putChats(dialogsRes.chats, loadType == 1); + putUsers(dialogsRes.users, loadType == DIALOGS_LOAD_TYPE_CACHE); + putChats(dialogsRes.chats, loadType == DIALOGS_LOAD_TYPE_CACHE); if (encChats != null) { for (int a = 0; a < encChats.size(); a++) { TLRPC.EncryptedChat encryptedChat = encChats.get(a); @@ -4632,22 +5060,35 @@ public class MessagesController implements NotificationCenter.NotificationCenter putEncryptedChat(encryptedChat, true); } } - if (!migrate) { - loadingDialogs = false; + if (!migrate && loadType != DIALOGS_LOAD_TYPE_UNKNOWN && loadType != DIALOGS_LOAD_TYPE_CHANNEL) { + loadingDialogs.put(folderId, false); } boolean added = false; + dialogsLoaded = true; - int lastDialogDate = migrate && !dialogs.isEmpty() ? dialogs.get(dialogs.size() - 1).last_message_date : 0; + int archivedDialogsCount = 0; + int lastDialogDate = migrate && !allDialogs.isEmpty() ? allDialogs.get(allDialogs.size() - 1).last_message_date : 0; for (int a = 0; a < new_dialogs_dict.size(); a++) { long key = new_dialogs_dict.keyAt(a); - TLRPC.TL_dialog value = new_dialogs_dict.valueAt(a); + TLRPC.Dialog value = new_dialogs_dict.valueAt(a); + TLRPC.Dialog currentDialog; + if (loadType != DIALOGS_LOAD_TYPE_UNKNOWN) { + currentDialog = dialogs_dict.get(key); + } else { + currentDialog = null; + } + if (migrate && currentDialog != null) { + currentDialog.folder_id = value.folder_id; + } if (migrate && lastDialogDate != 0 && value.last_message_date < lastDialogDate) { continue; } - TLRPC.TL_dialog currentDialog = dialogs_dict.get(key); - if (loadType != 1 && value.draft instanceof TLRPC.TL_draftMessage) { + if (loadType != DIALOGS_LOAD_TYPE_CACHE && value.draft instanceof TLRPC.TL_draftMessage) { DataQuery.getInstance(currentAccount).saveDraft(value.id, value.draft, null, false); } + if (value.folder_id != folderId) { + archivedDialogsCount++; + } if (currentDialog == null) { added = true; dialogs_dict.put(key, value); @@ -4660,7 +5101,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } } else { - if (loadType != 1) { + if (loadType != DIALOGS_LOAD_TYPE_CACHE) { currentDialog.notify_settings = value.notify_settings; } currentDialog.pinned = value.pinned; @@ -4704,22 +5145,31 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } - dialogs.clear(); + allDialogs.clear(); for (int a = 0, size = dialogs_dict.size(); a < size; a++) { - dialogs.add(dialogs_dict.valueAt(a)); + allDialogs.add(dialogs_dict.valueAt(a)); } sortDialogs(migrate ? chatsDict : null); - if (loadType != 2) { + if (loadType != DIALOGS_LOAD_TYPE_CHANNEL && loadType != DIALOGS_LOAD_TYPE_UNKNOWN) { if (!migrate) { - dialogsEndReached = (dialogsRes.dialogs.size() == 0 || dialogsRes.dialogs.size() != count) && loadType == 0; + dialogsEndReached.put(folderId, (dialogsRes.dialogs.size() == 0 || dialogsRes.dialogs.size() != count) && loadType == 0); + if (archivedDialogsCount > 0 && archivedDialogsCount < 20 && folderId == 0) { + dialogsEndReached.put(1, true); + int[] dialogsLoadOffsetArchived = UserConfig.getInstance(currentAccount).getDialogLoadOffsets(folderId); + if (dialogsLoadOffsetArchived[UserConfig.i_dialogsLoadOffsetId] == Integer.MAX_VALUE) { + serverDialogsEndReached.put(1, true); + } + } if (!fromCache) { - serverDialogsEndReached = (dialogsRes.dialogs.size() == 0 || dialogsRes.dialogs.size() != count) && loadType == 0; + serverDialogsEndReached.put(folderId, (dialogsRes.dialogs.size() == 0 || dialogsRes.dialogs.size() != count) && loadType == 0); } } } - if (!fromCache && !migrate && UserConfig.getInstance(currentAccount).totalDialogsLoadCount < 400 && UserConfig.getInstance(currentAccount).dialogsLoadOffsetId != -1 && UserConfig.getInstance(currentAccount).dialogsLoadOffsetId != Integer.MAX_VALUE) { - loadDialogs(0, 100, false); + int totalDialogsLoadCount = UserConfig.getInstance(currentAccount).getTotalDialogsCount(folderId); + int[] dialogsLoadOffset2 = UserConfig.getInstance(currentAccount).getDialogLoadOffsets(folderId); + if (!fromCache && !migrate && totalDialogsLoadCount < 400 && dialogsLoadOffset2[UserConfig.i_dialogsLoadOffsetId] != -1 && dialogsLoadOffset2[UserConfig.i_dialogsLoadOffsetId] != Integer.MAX_VALUE) { + loadDialogs(0, 100, folderId, false); } NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); @@ -4730,8 +5180,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.needReloadRecentDialogsSearch); } else { generateUpdateMessage(); - if (!added && loadType == 1) { - loadDialogs(0, count, false); + if (!added && loadType == DIALOGS_LOAD_TYPE_CACHE) { + loadDialogs(folderId, 0, count, false); } } migrateDialogs(UserConfig.getInstance(currentAccount).migrateOffsetId, UserConfig.getInstance(currentAccount).migrateOffsetDate, UserConfig.getInstance(currentAccount).migrateOffsetUserId, UserConfig.getInstance(currentAccount).migrateOffsetChatId, UserConfig.getInstance(currentAccount).migrateOffsetChannelId, UserConfig.getInstance(currentAccount).migrateOffsetAccess); @@ -4751,7 +5201,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter int currentValue2 = notificationsPreferences.getInt("notifyuntil_" + dialog_id, 0); SharedPreferences.Editor editor = notificationsPreferences.edit(); boolean updated = false; - TLRPC.TL_dialog dialog = dialogs_dict.get(dialog_id); + TLRPC.Dialog dialog = dialogs_dict.get(dialog_id); if (dialog != null) { dialog.notify_settings = notify_settings; } @@ -4810,10 +5260,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } - private void applyDialogsNotificationsSettings(ArrayList dialogs) { + private void applyDialogsNotificationsSettings(ArrayList dialogs) { SharedPreferences.Editor editor = null; for (int a = 0; a < dialogs.size(); a++) { - TLRPC.TL_dialog dialog = dialogs.get(a); + TLRPC.Dialog dialog = dialogs.get(a); if (dialog.peer != null && dialog.notify_settings instanceof TLRPC.TL_peerNotifySettings) { if (editor == null) { editor = notificationsPreferences.edit(); @@ -4881,7 +5331,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (dialogsToUpdate != null) { for (int a = 0; a < dialogsToUpdate.size(); a++) { long dialogId = dialogsToUpdate.keyAt(a); - TLRPC.TL_dialog currentDialog = dialogs_dict.get(dialogId); + TLRPC.Dialog currentDialog = dialogs_dict.get(dialogId); if (currentDialog != null) { int prevCount = currentDialog.unread_count; currentDialog.unread_count = dialogsToUpdate.valueAt(a); @@ -4896,7 +5346,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (dialogsMentionsToUpdate != null) { for (int a = 0; a < dialogsMentionsToUpdate.size(); a++) { long dialogId = dialogsMentionsToUpdate.keyAt(a); - TLRPC.TL_dialog currentDialog = dialogs_dict.get(dialogId); + TLRPC.Dialog currentDialog = dialogs_dict.get(dialogId); if (currentDialog != null) { currentDialog.unread_mentions_count = dialogsMentionsToUpdate.valueAt(a); if (createdDialogMainThreadIds.contains(currentDialog.id)) { @@ -4912,14 +5362,14 @@ public class MessagesController implements NotificationCenter.NotificationCenter }); } - protected void checkLastDialogMessage(final TLRPC.TL_dialog dialog, final TLRPC.InputPeer peer, long taskId) { + protected void checkLastDialogMessage(final TLRPC.Dialog dialog, final TLRPC.InputPeer peer, long taskId) { final int lower_id = (int) dialog.id; if (lower_id == 0 || checkingLastMessagesDialogs.indexOfKey(lower_id) >= 0) { return; } TLRPC.TL_messages_getHistory req = new TLRPC.TL_messages_getHistory(); req.peer = peer == null ? getInputPeer(lower_id) : peer; - if (req.peer == null || req.peer instanceof TLRPC.TL_inputPeerChannel) { + if (req.peer == null) { return; } req.limit = 1; @@ -4929,8 +5379,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (taskId == 0) { NativeByteBuffer data = null; try { - data = new NativeByteBuffer(48 + req.peer.getObjectSize()); - data.writeInt32(10); + data = new NativeByteBuffer(60 + req.peer.getObjectSize()); + data.writeInt32(14); data.writeInt64(dialog.id); data.writeInt32(dialog.top_message); data.writeInt32(dialog.read_inbox_max_id); @@ -4943,6 +5393,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter data.writeInt32(dialog.pinnedNum); data.writeInt32(dialog.unread_mentions_count); data.writeBool(dialog.unread_mark); + data.writeInt32(dialog.folder_id); peer.serializeToStream(data); } catch (Exception e) { FileLog.e(e); @@ -4955,10 +5406,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (response != null) { TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; + removeDeletedMessagesFromArray(lower_id, res.messages); if (!res.messages.isEmpty()) { TLRPC.TL_messages_dialogs dialogs = new TLRPC.TL_messages_dialogs(); TLRPC.Message newMessage = res.messages.get(0); - TLRPC.TL_dialog newDialog = new TLRPC.TL_dialog(); + TLRPC.Dialog newDialog = new TLRPC.TL_dialog(); newDialog.flags = dialog.flags; newDialog.top_message = newMessage.id; newDialog.last_message_date = newMessage.date; @@ -4971,6 +5423,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter newDialog.read_outbox_max_id = dialog.read_outbox_max_id; newDialog.pinned = dialog.pinned; newDialog.pinnedNum = dialog.pinnedNum; + newDialog.folder_id = dialog.folder_id; newMessage.dialog_id = newDialog.id = dialog.id; dialogs.users.addAll(res.users); dialogs.chats.addAll(res.chats); @@ -4981,7 +5434,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter MessagesStorage.getInstance(currentAccount).putMessages(res.messages, true, true, false, DownloadController.getInstance(currentAccount).getAutodownloadMask(), true); } else { AndroidUtilities.runOnUIThread(() -> { - TLRPC.TL_dialog currentDialog = dialogs_dict.get(dialog.id); + TLRPC.Dialog currentDialog = dialogs_dict.get(dialog.id); if (currentDialog != null && currentDialog.top_message == 0) { deleteDialog(dialog.id, 3); } @@ -4997,7 +5450,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter public void processDialogsUpdate(final TLRPC.messages_Dialogs dialogsRes, ArrayList encChats) { Utilities.stageQueue.postRunnable(() -> { - final LongSparseArray new_dialogs_dict = new LongSparseArray<>(); + final LongSparseArray new_dialogs_dict = new LongSparseArray<>(); final LongSparseArray new_dialogMessage = new LongSparseArray<>(); final SparseArray usersDict = new SparseArray<>(dialogsRes.users.size()); final SparseArray chatsDict = new SparseArray<>(dialogsRes.chats.size()); @@ -5031,16 +5484,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter new_dialogMessage.put(messageObject.getDialogId(), messageObject); } for (int a = 0; a < dialogsRes.dialogs.size(); a++) { - TLRPC.TL_dialog d = dialogsRes.dialogs.get(a); - if (d.id == 0) { - if (d.peer.user_id != 0) { - d.id = d.peer.user_id; - } else if (d.peer.chat_id != 0) { - d.id = -d.peer.chat_id; - } else if (d.peer.channel_id != 0) { - d.id = -d.peer.channel_id; - } - } + TLRPC.Dialog d = dialogsRes.dialogs.get(a); + DialogObject.initDialog(d); if (proxyDialogId == 0 || proxyDialogId != d.id) { if (DialogObject.isChannel(d)) { TLRPC.Chat chat = chatsDict.get(-(int) d.id); @@ -5082,10 +5527,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter for (int a = 0; a < new_dialogs_dict.size(); a++) { long key = new_dialogs_dict.keyAt(a); - TLRPC.TL_dialog value = new_dialogs_dict.valueAt(a); - TLRPC.TL_dialog currentDialog = dialogs_dict.get(key); + TLRPC.Dialog value = new_dialogs_dict.valueAt(a); + TLRPC.Dialog currentDialog = dialogs_dict.get(key); if (currentDialog == null) { - nextDialogsCacheOffset++; + int offset = nextDialogsCacheOffset.get(value.folder_id, 0) + 1; + nextDialogsCacheOffset.put(value.folder_id, offset); dialogs_dict.put(key, value); MessageObject messageObject = new_dialogMessage.get(value.id); dialogMessage.put(key, messageObject); @@ -5145,9 +5591,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } - dialogs.clear(); + allDialogs.clear(); for (int a = 0, size = dialogs_dict.size(); a < size; a++) { - dialogs.add(dialogs_dict.valueAt(a)); + allDialogs.add(dialogs_dict.valueAt(a)); } sortDialogs(null); NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); @@ -5421,6 +5867,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter int high_id = (int) (dialogId >> 32); boolean createReadTask; + boolean countMessages = NotificationsController.getInstance(currentAccount).showBadgeMessages; if (lower_part != 0) { if (maxPositiveId == 0 || high_id == 1) { return; @@ -5444,7 +5891,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter MessagesStorage.getInstance(currentAccount).processPendingRead(dialogId, maxMessageId, minMessageId, maxDate, isChannel); MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> { - TLRPC.TL_dialog dialog = dialogs_dict.get(dialogId); + TLRPC.Dialog dialog = dialogs_dict.get(dialogId); if (dialog != null) { int prevCount = dialog.unread_count; if (countDiff == 0 || maxPositiveId >= dialog.top_message) { @@ -5455,6 +5902,25 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialog.unread_count = dialog.top_message - maxPositiveId; } } + if (dialog.folder_id != 0) { + TLRPC.Dialog folder = dialogs_dict.get(DialogObject.makeFolderDialogId(dialog.folder_id)); + if (folder != null) { + if (countMessages) { + if (isDialogMuted(dialog.id)) { + folder.unread_count -= (prevCount - dialog.unread_count); + } else { + folder.unread_mentions_count -= (prevCount - dialog.unread_count); + } + } else if (dialog.unread_count == 0) { + if (isDialogMuted(dialog.id)) { + folder.unread_count--; + } else { + folder.unread_mentions_count--; + } + } + } + } + if ((prevCount != 0 || dialog.unread_mark) && dialog.unread_count == 0 && !isDialogMuted(dialogId)) { unreadUnmutedDialogs--; } @@ -5488,7 +5954,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter MessagesStorage.getInstance(currentAccount).processPendingRead(dialogId, maxPositiveId, maxNegativeId, maxDate, false); MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> { NotificationsController.getInstance(currentAccount).processReadMessages(null, dialogId, maxDate, 0, popup); - TLRPC.TL_dialog dialog = dialogs_dict.get(dialogId); + TLRPC.Dialog dialog = dialogs_dict.get(dialogId); if (dialog != null) { int prevCount = dialog.unread_count; if (countDiff == 0 || maxNegativeId <= dialog.top_message) { @@ -5499,6 +5965,24 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialog.unread_count = maxNegativeId - dialog.top_message; } } + if (dialog.folder_id != 0) { + TLRPC.Dialog folder = dialogs_dict.get(DialogObject.makeFolderDialogId(dialog.folder_id)); + if (folder != null) { + if (countMessages) { + if (isDialogMuted(dialog.id)) { + folder.unread_count -= (prevCount - dialog.unread_count); + } else { + folder.unread_mentions_count -= (prevCount - dialog.unread_count); + } + } else if (dialog.unread_count == 0) { + if (isDialogMuted(dialog.id)) { + folder.unread_count--; + } else { + folder.unread_mentions_count--; + } + } + } + } if ((prevCount != 0 || dialog.unread_mark) && dialog.unread_count == 0 && !isDialogMuted(dialogId)) { unreadUnmutedDialogs--; } @@ -5923,10 +6407,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter } public void deleteUserFromChat(final int chat_id, final TLRPC.User user, final TLRPC.ChatFull info) { - deleteUserFromChat(chat_id, user, info, false); + deleteUserFromChat(chat_id, user, info, false, false); } - public void deleteUserFromChat(final int chat_id, final TLRPC.User user, final TLRPC.ChatFull info, boolean forceDelete) { + public void deleteUserFromChat(final int chat_id, final TLRPC.User user, final TLRPC.ChatFull info, boolean forceDelete, boolean revoke) { if (user == null) { return; } @@ -5971,10 +6455,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter req.user_id = getInputUser(user); request = req; } + if (user.id == UserConfig.getInstance(currentAccount).getClientUserId()) { + deleteDialog(-chat_id, 0, revoke); + } ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> { - if (user.id == UserConfig.getInstance(currentAccount).getClientUserId()) { - AndroidUtilities.runOnUIThread(() -> deleteDialog(-chat_id, 0)); - } if (error != null) { return; } @@ -6094,7 +6578,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter src.renameTo(destFile); String oldKey = smallSize.volume_id + "_" + smallSize.local_id + "@50_50"; String newKey = small.location.volume_id + "_" + small.location.local_id + "@50_50"; - ImageLoader.getInstance().replaceImageInCache(oldKey, newKey, small.location, true); + ImageLoader.getInstance().replaceImageInCache(oldKey, newKey, ImageLocation.getForPhoto(small, photo), true); } TLRPC.PhotoSize big = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, 800); if (big != null && bigSize != null) { @@ -6444,12 +6928,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (response != null) { TLRPC.TL_messages_peerDialogs res = (TLRPC.TL_messages_peerDialogs) response; if (!res.dialogs.isEmpty() && !res.chats.isEmpty()) { + TLRPC.TL_dialog dialog = (TLRPC.TL_dialog) res.dialogs.get(0); TLRPC.TL_messages_dialogs dialogs = new TLRPC.TL_messages_dialogs(); dialogs.dialogs.addAll(res.dialogs); dialogs.messages.addAll(res.messages); dialogs.users.addAll(res.users); dialogs.chats.addAll(res.chats); - processLoadedDialogs(dialogs, null, 0, 1, 2, false, false, false); + processLoadedDialogs(dialogs, null, dialog.folder_id, 0, 1, DIALOGS_LOAD_TYPE_CHANNEL, false, false, false); } } if (newTaskId != 0) { @@ -6486,8 +6971,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter } public static boolean isSupportUser(TLRPC.User user) { - return user != null && (user.support || user.id / 1000 == 777 || user.id == 333000 || - user.id == 4240000 || user.id == 4240000 || user.id == 4244000 || + return user != null && (user.support || user.id == 777000 || + user.id == 333000 || user.id == 4240000 || user.id == 4244000 || user.id == 4245000 || user.id == 4246000 || user.id == 410000 || user.id == 420000 || user.id == 431000 || user.id == 431415000 || user.id == 434000 || user.id == 4243000 || user.id == 439000 || @@ -7006,23 +7491,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter }); } - public boolean canPinDialog(boolean secret) { - int count = 0; - for (int a = 0; a < dialogs.size(); a++) { - TLRPC.TL_dialog dialog = dialogs.get(a); - int lower_id = (int) dialog.id; - if (secret && lower_id != 0 || !secret && lower_id == 0) { - continue; - } - if (dialog.pinned) { - count++; - } - } - return count < maxPinnedDialogsCount; - } - public void markDialogAsUnread(long did, TLRPC.InputPeer peer, long taskId) { - TLRPC.TL_dialog dialog = dialogs_dict.get(did); + TLRPC.Dialog dialog = dialogs_dict.get(did); if (dialog != null) { dialog.unread_mark = true; if (dialog.unread_count == 0 && !isDialogMuted(did)) { @@ -7095,7 +7565,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter did = 0; } MessagesStorage.getInstance(currentAccount).setDialogUnread(did, true); - TLRPC.TL_dialog dialog = dialogs_dict.get(did); + TLRPC.Dialog dialog = dialogs_dict.get(did); if (dialog != null && !dialog.unread_mark) { dialog.unread_mark = true; if (dialog.unread_count == 0 && !isDialogMuted(did)) { @@ -7112,17 +7582,78 @@ public class MessagesController implements NotificationCenter.NotificationCenter })); } + public void reorderPinnedDialogs(int folderId, ArrayList order, long taskId) { + TLRPC.TL_messages_reorderPinnedDialogs req = new TLRPC.TL_messages_reorderPinnedDialogs(); + req.folder_id = folderId; + req.force = true; + + final long newTaskId; + if (taskId == 0) { + ArrayList dialogs = getDialogs(folderId); + if (dialogs.isEmpty()) { + return; + } + + int size = 0; + for (int a = 0, N = dialogs.size(); a < N; a++) { + TLRPC.Dialog dialog = dialogs.get(a); + if (dialog instanceof TLRPC.TL_dialogFolder) { + continue; + } + if (!dialog.pinned) { + break; + } + MessagesStorage.getInstance(currentAccount).setDialogPinned(dialog.id, dialog.pinnedNum); + if ((int) dialog.id != 0) { + TLRPC.InputPeer inputPeer = getInputPeer((int) dialogs.get(a).id); + TLRPC.TL_inputDialogPeer inputDialogPeer = new TLRPC.TL_inputDialogPeer(); + inputDialogPeer.peer = inputPeer; + req.order.add(inputDialogPeer); + size += inputDialogPeer.getObjectSize(); + } + } + + NativeByteBuffer data = null; + try { + data = new NativeByteBuffer(4 + 4 + 4 + size); + data.writeInt32(16); + data.writeInt32(folderId); + data.writeInt32(req.order.size()); + for (int a = 0, N = req.order.size(); a < N; a++) { + req.order.get(a).serializeToStream(data); + } + } catch (Exception e) { + FileLog.e(e); + } + newTaskId = MessagesStorage.getInstance(currentAccount).createPendingTask(data); + } else { + req.order = order; + newTaskId = taskId; + } + + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + if (newTaskId != 0) { + MessagesStorage.getInstance(currentAccount).removePendingTask(newTaskId); + } + }); + } + public boolean pinDialog(long did, boolean pin, TLRPC.InputPeer peer, long taskId) { int lower_id = (int) did; - TLRPC.TL_dialog dialog = dialogs_dict.get(did); + TLRPC.Dialog dialog = dialogs_dict.get(did); if (dialog == null || dialog.pinned == pin) { return dialog != null; } + int folderId = dialog.folder_id; + ArrayList dialogs = getDialogs(folderId); dialog.pinned = pin; if (pin) { int maxPinnedNum = 0; for (int a = 0; a < dialogs.size(); a++) { - TLRPC.TL_dialog d = dialogs.get(a); + TLRPC.Dialog d = dialogs.get(a); + if (d instanceof TLRPC.TL_dialogFolder) { + continue; + } if (!d.pinned) { break; } @@ -7133,7 +7664,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialog.pinnedNum = 0; } sortDialogs(null); - if (!pin && dialogs.get(dialogs.size() - 1) == dialog && !dialogsEndReached) { + if (!pin && dialogs.get(dialogs.size() - 1) == dialog && !dialogsEndReached.get(folderId)) { dialogs.remove(dialogs.size() - 1); } NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); @@ -7179,14 +7710,18 @@ public class MessagesController implements NotificationCenter.NotificationCenter return true; } - public void loadPinnedDialogs(final long newDialogId, final ArrayList order) { - if (UserConfig.getInstance(currentAccount).pinnedDialogsLoaded) { + public void loadPinnedDialogs(final int folderId, final long newDialogId, final ArrayList order) { + if (loadingPinnedDialogs.indexOfKey(folderId) >= 0 || UserConfig.getInstance(currentAccount).isPinnedDialogsLoaded(folderId)) { return; } + loadingPinnedDialogs.put(folderId, 1); TLRPC.TL_messages_getPinnedDialogs req = new TLRPC.TL_messages_getPinnedDialogs(); + req.folder_id = folderId; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (response != null) { final TLRPC.TL_messages_peerDialogs res = (TLRPC.TL_messages_peerDialogs) response; + ArrayList newPinnedDialogs = new ArrayList<>(res.dialogs); + fetchFolderInLoadedPinnedDialogs(res); final TLRPC.TL_messages_dialogs toCache = new TLRPC.TL_messages_dialogs(); toCache.users.addAll(res.users); toCache.chats.addAll(res.chats); @@ -7196,7 +7731,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter final LongSparseArray new_dialogMessage = new LongSparseArray<>(); final SparseArray usersDict = new SparseArray<>(); final SparseArray chatsDict = new SparseArray<>(); - final ArrayList newPinnedOrder = new ArrayList<>(); for (int a = 0; a < res.users.size(); a++) { TLRPC.User u = res.users.get(a); @@ -7223,18 +7757,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, false); new_dialogMessage.put(messageObject.getDialogId(), messageObject); } - for (int a = 0; a < res.dialogs.size(); a++) { - TLRPC.TL_dialog d = res.dialogs.get(a); - if (d.id == 0) { - if (d.peer.user_id != 0) { - d.id = d.peer.user_id; - } else if (d.peer.chat_id != 0) { - d.id = -d.peer.chat_id; - } else if (d.peer.channel_id != 0) { - d.id = -d.peer.channel_id; - } - } - newPinnedOrder.add(d.id); + boolean firstIsFolder = !newPinnedDialogs.isEmpty() && newPinnedDialogs.get(0) instanceof TLRPC.TL_dialogFolder; + for (int a = 0, N = newPinnedDialogs.size(); a < N; a++) { + TLRPC.Dialog d = newPinnedDialogs.get(a); + d.pinned = true; + DialogObject.initDialog(d); if (DialogObject.isChannel(d)) { TLRPC.Chat chat = chatsDict.get(-(int) d.id); if (chat != null && chat.left) { @@ -7267,70 +7794,49 @@ public class MessagesController implements NotificationCenter.NotificationCenter } MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> { - applyDialogsNotificationsSettings(res.dialogs); + loadingPinnedDialogs.delete(folderId); + applyDialogsNotificationsSettings(newPinnedDialogs); boolean changed = false; boolean added = false; int maxPinnedNum = 0; - LongSparseArray oldPinnedDialogNums = new LongSparseArray<>(); - ArrayList oldPinnedOrder = new ArrayList<>(); + + ArrayList dialogs = getDialogs(folderId); + + int pinnedNum = firstIsFolder ? 1 : 0; for (int a = 0; a < dialogs.size(); a++) { - TLRPC.TL_dialog dialog = dialogs.get(a); + TLRPC.Dialog dialog = dialogs.get(a); + if (dialog instanceof TLRPC.TL_dialogFolder) { + continue; + } if ((int) dialog.id == 0) { + if (pinnedNum < newPinnedDialogs.size()) { + newPinnedDialogs.add(pinnedNum, dialog); + } else { + newPinnedDialogs.add(dialog); + } + pinnedNum++; continue; } if (!dialog.pinned) { break; } maxPinnedNum = Math.max(dialog.pinnedNum, maxPinnedNum); - oldPinnedDialogNums.put(dialog.id, dialog.pinnedNum); - oldPinnedOrder.add(dialog.id); dialog.pinned = false; dialog.pinnedNum = 0; changed = true; + pinnedNum++; } ArrayList pinnedDialogs = new ArrayList<>(); - ArrayList orderArrayList = order != null ? order : newPinnedOrder; - if (orderArrayList.size() < oldPinnedOrder.size()) { - orderArrayList.add(0L); - } - while (oldPinnedOrder.size() < orderArrayList.size()) { - oldPinnedOrder.add(0, 0L); - } - if (!res.dialogs.isEmpty()) { + if (!newPinnedDialogs.isEmpty()) { putUsers(res.users, false); putChats(res.chats, false); - for (int a = 0; a < res.dialogs.size(); a++) { - TLRPC.TL_dialog dialog = res.dialogs.get(a); - if (newDialogId != 0) { - Integer oldNum = oldPinnedDialogNums.get(dialog.id); - if (oldNum != null) { - dialog.pinnedNum = oldNum; - } - } else { - int oldIdx = oldPinnedOrder.indexOf(dialog.id); - int newIdx = orderArrayList.indexOf(dialog.id); - if (oldIdx != -1 && newIdx != -1) { - if (oldIdx == newIdx) { - Integer oldNum = oldPinnedDialogNums.get(dialog.id); - if (oldNum != null) { - dialog.pinnedNum = oldNum; - } - } else { - long oldDid = oldPinnedOrder.get(newIdx); - Integer oldNum = oldPinnedDialogNums.get(oldDid); - if (oldNum != null) { - dialog.pinnedNum = oldNum; - } - } - } - } - if (dialog.pinnedNum == 0) { - dialog.pinnedNum = (res.dialogs.size() - a) + maxPinnedNum; - } - pinnedDialogs.add(dialog.id); - TLRPC.TL_dialog d = dialogs_dict.get(dialog.id); + for (int a = 0, N = newPinnedDialogs.size(); a < N; a++) { + TLRPC.Dialog dialog = newPinnedDialogs.get(a); + dialog.pinnedNum = (N - a) + maxPinnedNum; + pinnedDialogs.add(dialog.id); + TLRPC.Dialog d = dialogs_dict.get(dialog.id); if (d != null) { d.pinned = true; d.pinnedNum = dialog.pinnedNum; @@ -7353,17 +7859,17 @@ public class MessagesController implements NotificationCenter.NotificationCenter } if (changed) { if (added) { - dialogs.clear(); + allDialogs.clear(); for (int a = 0, size = dialogs_dict.size(); a < size; a++) { - dialogs.add(dialogs_dict.valueAt(a)); + allDialogs.add(dialogs_dict.valueAt(a)); } } sortDialogs(null); NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); } - MessagesStorage.getInstance(currentAccount).unpinAllDialogsExceptNew(pinnedDialogs); + MessagesStorage.getInstance(currentAccount).unpinAllDialogsExceptNew(pinnedDialogs, folderId); MessagesStorage.getInstance(currentAccount).putDialogs(toCache, 1); - UserConfig.getInstance(currentAccount).pinnedDialogsLoaded = true; + UserConfig.getInstance(currentAccount).setPinnedDialogsLoaded(folderId, true); UserConfig.getInstance(currentAccount).saveConfig(false); })); } @@ -7472,7 +7978,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter private int getUpdateType(TLRPC.Update update) { if (update instanceof TLRPC.TL_updateNewMessage || update instanceof TLRPC.TL_updateReadMessagesContents || update instanceof TLRPC.TL_updateReadHistoryInbox || update instanceof TLRPC.TL_updateReadHistoryOutbox || update instanceof TLRPC.TL_updateDeleteMessages || update instanceof TLRPC.TL_updateWebPage || - update instanceof TLRPC.TL_updateEditMessage) { + update instanceof TLRPC.TL_updateEditMessage || update instanceof TLRPC.TL_updateFolderPeers) { return 0; } else if (update instanceof TLRPC.TL_updateNewEncryptedMessage) { return 1; @@ -7509,6 +8015,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter return ((TLRPC.TL_updateReadMessagesContents) update).pts; } else if (update instanceof TLRPC.TL_updateChannelTooLong) { return ((TLRPC.TL_updateChannelTooLong) update).pts; + } else if (update instanceof TLRPC.TL_updateFolderPeers) { + return ((TLRPC.TL_updateFolderPeers) update).pts; } else { return 0; } @@ -7537,6 +8045,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter return ((TLRPC.TL_updateEditChannelMessage) update).pts_count; } else if (update instanceof TLRPC.TL_updateReadMessagesContents) { return ((TLRPC.TL_updateReadMessagesContents) update).pts_count; + } else if (update instanceof TLRPC.TL_updateFolderPeers) { + return ((TLRPC.TL_updateFolderPeers) update).pts_count; } else { return 0; } @@ -8645,6 +9155,14 @@ public class MessagesController implements NotificationCenter.NotificationCenter updatesOnMainThread = new ArrayList<>(); } updatesOnMainThread.add(baseUpdate); + } else if (baseUpdate instanceof TLRPC.TL_updateFolderPeers) { + if (updatesOnMainThread == null) { + updatesOnMainThread = new ArrayList<>(); + } + updatesOnMainThread.add(baseUpdate); + + TLRPC.TL_updateFolderPeers update = (TLRPC.TL_updateFolderPeers) baseUpdate; + MessagesStorage.getInstance(currentAccount).setDialogsFolderId(update.folder_peers, null, 0, 0); } else if (baseUpdate instanceof TLRPC.TL_updatePrivacy) { if (updatesOnMainThread == null) { updatesOnMainThread = new ArrayList<>(); @@ -9011,7 +9529,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter final ArrayList updatesOnMainThreadFinal = updatesOnMainThread; AndroidUtilities.runOnUIThread(() -> { int updateMask = interfaceUpdateMaskFinal; - boolean hasDraftUpdates = false; + boolean forceDialogsUpdate = false; if (updatesOnMainThreadFinal != null) { ArrayList dbUsers = new ArrayList<>(); @@ -9045,7 +9563,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter currentUser.id = update.user_id; currentUser.status = update.status; } - final TLRPC.User toDbUser = new TLRPC.TL_user(); //TODO remove + final TLRPC.User toDbUser = new TLRPC.TL_user(); toDbUser.id = update.user_id; toDbUser.status = update.status; dbUsersStatus.add(toDbUser); @@ -9068,40 +9586,34 @@ public class MessagesController implements NotificationCenter.NotificationCenter } currentUser.username = update.username; } - final TLRPC.User toDbUser = new TLRPC.TL_user(); //TODO remove + final TLRPC.User toDbUser = new TLRPC.TL_user(); toDbUser.id = update.user_id; toDbUser.first_name = update.first_name; toDbUser.last_name = update.last_name; toDbUser.username = update.username; dbUsers.add(toDbUser); } else if (baseUpdate instanceof TLRPC.TL_updateDialogPinned) { - TLRPC.TL_updateDialogPinned updateDialogPinned = (TLRPC.TL_updateDialogPinned) baseUpdate; + TLRPC.TL_updateDialogPinned update = (TLRPC.TL_updateDialogPinned) baseUpdate; long did; - if (updateDialogPinned.peer instanceof TLRPC.TL_dialogPeer) { - TLRPC.Peer peer = ((TLRPC.TL_dialogPeer) updateDialogPinned.peer).peer; - if (peer instanceof TLRPC.TL_peerUser) { - did = peer.user_id; - } else if (peer instanceof TLRPC.TL_peerChat) { - did = -peer.chat_id; - } else { - did = -peer.channel_id; - } + if (update.peer instanceof TLRPC.TL_dialogPeer) { + TLRPC.TL_dialogPeer dialogPeer = (TLRPC.TL_dialogPeer) update.peer; + did = DialogObject.getPeerDialogId(dialogPeer.peer); } else { did = 0; } - if (!pinDialog(did, updateDialogPinned.pinned, null, -1)) { - UserConfig.getInstance(currentAccount).pinnedDialogsLoaded = false; + if (!pinDialog(did, update.pinned, null, -1)) { + UserConfig.getInstance(currentAccount).setPinnedDialogsLoaded(update.folder_id, false); UserConfig.getInstance(currentAccount).saveConfig(false); - loadPinnedDialogs(did, null); + loadPinnedDialogs(update.folder_id, did, null); } } else if (baseUpdate instanceof TLRPC.TL_updatePinnedDialogs) { TLRPC.TL_updatePinnedDialogs update = (TLRPC.TL_updatePinnedDialogs) baseUpdate; - UserConfig.getInstance(currentAccount).pinnedDialogsLoaded = false; + UserConfig.getInstance(currentAccount).setPinnedDialogsLoaded(update.folder_id, false); UserConfig.getInstance(currentAccount).saveConfig(false); ArrayList order; if ((update.flags & 1) != 0) { order = new ArrayList<>(); - ArrayList peers = ((TLRPC.TL_updatePinnedDialogs) baseUpdate).order; + ArrayList peers = update.order; for (int b = 0, size2 = peers.size(); b < size2; b++) { long did; TLRPC.DialogPeer dialogPeer = peers.get(b); @@ -9122,14 +9634,28 @@ public class MessagesController implements NotificationCenter.NotificationCenter } else { order = null; } - loadPinnedDialogs(0, order); + loadPinnedDialogs(update.folder_id, 0, order); + } else if (baseUpdate instanceof TLRPC.TL_updateFolderPeers) { + TLRPC.TL_updateFolderPeers update = (TLRPC.TL_updateFolderPeers) baseUpdate; + for (int b = 0, size2 = update.folder_peers.size(); b < size2; b++) { + TLRPC.TL_folderPeer folderPeer = update.folder_peers.get(b); + long dialogId = DialogObject.getPeerDialogId(folderPeer.peer); + TLRPC.Dialog dialog = dialogs_dict.get(dialogId); + if (dialog == null) { + continue; + } + //TODO folder + dialog.folder_id = folderPeer.folder_id; + ensureFolderDialogExists(folderPeer.folder_id, null); + } + forceDialogsUpdate = true; } else if (baseUpdate instanceof TLRPC.TL_updateUserPhoto) { TLRPC.TL_updateUserPhoto update = (TLRPC.TL_updateUserPhoto) baseUpdate; final TLRPC.User currentUser = getUser(update.user_id); if (currentUser != null) { currentUser.photo = update.photo; } - final TLRPC.User toDbUser = new TLRPC.TL_user(); //TODO remove + final TLRPC.User toDbUser = new TLRPC.TL_user(); toDbUser.id = update.user_id; toDbUser.photo = update.photo; dbUsers.add(toDbUser); @@ -9140,7 +9666,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter currentUser.phone = update.phone; Utilities.phoneBookQueue.postRunnable(() -> ContactsController.getInstance(currentAccount).addContactToPhoneBook(currentUser, true)); } - final TLRPC.User toDbUser = new TLRPC.TL_user(); //TODO remove + final TLRPC.User toDbUser = new TLRPC.TL_user(); toDbUser.id = update.user_id; toDbUser.phone = update.phone; dbUsers.add(toDbUser); @@ -9161,7 +9687,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } else { dialog_id = -notifyPeer.peer.channel_id; } - TLRPC.TL_dialog dialog = dialogs_dict.get(dialog_id); + TLRPC.Dialog dialog = dialogs_dict.get(dialog_id); if (dialog != null) { dialog.notify_settings = update.notify_settings; } @@ -9248,7 +9774,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } else if (baseUpdate instanceof TLRPC.TL_updateChannel) { final TLRPC.TL_updateChannel update = (TLRPC.TL_updateChannel) baseUpdate; - TLRPC.TL_dialog dialog = dialogs_dict.get(-(long) update.channel_id); + TLRPC.Dialog dialog = dialogs_dict.get(-(long) update.channel_id); TLRPC.Chat chat = getChat(update.channel_id); if (chat != null) { if (dialog == null && chat instanceof TLRPC.TL_channel && !chat.left) { @@ -9293,7 +9819,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter editor2.putLong("lastStickersLoadTime", 0).commit(); } else if (baseUpdate instanceof TLRPC.TL_updateDraftMessage) { TLRPC.TL_updateDraftMessage update = (TLRPC.TL_updateDraftMessage) baseUpdate; - hasDraftUpdates = true; + forceDialogsUpdate = true; long did; TLRPC.Peer peer = ((TLRPC.TL_updateDraftMessage) baseUpdate).peer; if (peer.user_id != 0) { @@ -9389,7 +9915,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter did = 0; } MessagesStorage.getInstance(currentAccount).setDialogUnread(did, update.unread); - TLRPC.TL_dialog dialog = dialogs_dict.get(did); + TLRPC.Dialog dialog = dialogs_dict.get(did); if (dialog != null && dialog.unread_mark != update.unread) { dialog.unread_mark = update.unread; if (dialog.unread_count == 0 && !isDialogMuted(did)) { @@ -9456,7 +9982,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter updateInterfaceWithMessages(key, value); } updateDialogs = true; - } else if (hasDraftUpdates) { + } else if (forceDialogsUpdate) { sortDialogs(null); updateDialogs = true; } @@ -9528,7 +10054,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter for (int b = 0, size = markAsReadMessagesInboxFinal.size(); b < size; b++) { int key = markAsReadMessagesInboxFinal.keyAt(b); int messageId = (int) markAsReadMessagesInboxFinal.valueAt(b); - TLRPC.TL_dialog dialog = dialogs_dict.get((long) key); + TLRPC.Dialog dialog = dialogs_dict.get((long) key); if (dialog != null && dialog.top_message > 0 && dialog.top_message <= messageId) { MessageObject obj = dialogMessage.get(dialog.id); if (obj != null && !obj.isOut()) { @@ -9547,7 +10073,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter for (int b = 0, size = markAsReadMessagesOutboxFinal.size(); b < size; b++) { int key = markAsReadMessagesOutboxFinal.keyAt(b); int messageId = (int) markAsReadMessagesOutboxFinal.valueAt(b); - TLRPC.TL_dialog dialog = dialogs_dict.get((long) key); + TLRPC.Dialog dialog = dialogs_dict.get((long) key); if (dialog != null && dialog.top_message > 0 && dialog.top_message <= messageId) { MessageObject obj = dialogMessage.get(dialog.id); if (obj != null && obj.isOut()) { @@ -9564,7 +10090,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter int value = markAsReadEncryptedFinal.valueAt(a); NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messagesReadEncrypted, key, value); long dialog_id = (long) (key) << 32; - TLRPC.TL_dialog dialog = dialogs_dict.get(dialog_id); + TLRPC.Dialog dialog = dialogs_dict.get(dialog_id); if (dialog != null) { MessageObject message = dialogMessage.get(dialog_id); if (message != null && message.messageOwner.date <= value) { @@ -9761,10 +10287,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (lastMessage == null) { return; } - TLRPC.TL_dialog dialog = dialogs_dict.get(uid); + TLRPC.TL_dialog dialog = (TLRPC.TL_dialog) dialogs_dict.get(uid); if (lastMessage.messageOwner.action instanceof TLRPC.TL_messageActionChatMigrateTo) { if (dialog != null) { - dialogs.remove(dialog); + allDialogs.remove(dialog); dialogsServerOnly.remove(dialog); dialogsCanAddUsers.remove(dialog); dialogsChannelsOnly.remove(dialog); @@ -9774,8 +10300,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialogs_dict.remove(dialog.id); dialogs_read_inbox_max.remove(dialog.id); dialogs_read_outbox_max.remove(dialog.id); - nextDialogsCacheOffset--; + int offset = nextDialogsCacheOffset.get(dialog.folder_id, 0); + if (offset > 0) { + nextDialogsCacheOffset.put(dialog.folder_id, offset - 1); + } dialogMessage.remove(dialog.id); + ArrayList dialogs = dialogsByFolder.get(dialog.folder_id); + if (dialogs != null) { + dialogs.remove(dialog); + } MessageObject object = dialogMessagesByIds.get(dialog.top_message); dialogMessagesByIds.remove(dialog.top_message); if (object != null && object.messageOwner.random_id != 0) { @@ -9803,7 +10336,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialog.last_message_date = lastMessage.messageOwner.date; dialog.flags = ChatObject.isChannel(chat) ? 1 : 0; dialogs_dict.put(uid, dialog); - dialogs.add(dialog); + allDialogs.add(dialog); dialogMessage.put(uid, lastMessage); if (lastMessage.messageOwner.to_id.channel_id == 0) { dialogMessagesByIds.put(lastMessage.getId(), lastMessage); @@ -9811,10 +10344,35 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialogMessagesByRandomIds.put(lastMessage.messageOwner.random_id, lastMessage); } } - nextDialogsCacheOffset++; changed = true; + + //int offset = nextDialogsCacheOffset.get(dialog.folder_id, 0) + 1; + //nextDialogsCacheOffset.put(dialog.folder_id, offset); + + TLRPC.Dialog dialogFinal = dialog; + MessagesStorage.getInstance(currentAccount).getDialogFolderId(uid, param -> { + if (param != -1) { + if (param != 0) { + dialogFinal.folder_id = param; + sortDialogs(null); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload, true); + } + } else { + int lowerId = (int) uid; + if (lowerId != 0) { + loadUnknownDialog(getInputPeer(lowerId), 0); + } + } + }); } } else { + if (dialog.folder_id == 1 && !isDialogMuted(dialog.id)) { + dialog.folder_id = 0; + dialog.pinned = false; + dialog.pinnedNum = 0; + MessagesStorage.getInstance(currentAccount).setDialogsFolderId(null, null, dialog.id, 0); + changed = true; + } if ((dialog.top_message > 0 && lastMessage.getId() > 0 && lastMessage.getId() > dialog.top_message) || (dialog.top_message < 0 && lastMessage.getId() < 0 && lastMessage.getId() < dialog.top_message) || dialogMessage.indexOfKey(uid) < 0 || dialog.top_message < 0 || dialog.last_message_date <= lastMessage.messageOwner.date) { @@ -9848,7 +10406,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } public void addDialogAction(long did, boolean clean) { - TLRPC.TL_dialog dialog = dialogs_dict.get(did); + TLRPC.Dialog dialog = dialogs_dict.get(did); if (dialog == null) { return; } @@ -9856,14 +10414,14 @@ public class MessagesController implements NotificationCenter.NotificationCenter clearingHistoryDialogs.put(did, dialog); } else { deletingDialogs.put(did, dialog); - dialogs.remove(dialog); + allDialogs.remove(dialog); sortDialogs(null); } NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload, true); } public void removeDialogAction(long did, boolean clean, boolean apply) { - TLRPC.TL_dialog dialog = dialogs_dict.get(did); + TLRPC.Dialog dialog = dialogs_dict.get(did); if (dialog == null) { return; } @@ -9872,7 +10430,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } else { deletingDialogs.remove(did); if (!apply) { - dialogs.add(dialog); + allDialogs.add(dialog); sortDialogs(null); } } @@ -9892,10 +10450,16 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialogsGroupsOnly.clear(); dialogsUsersOnly.clear(); dialogsForward.clear(); + for (int a = 0; a < dialogsByFolder.size(); a++) { + ArrayList arrayList = dialogsByFolder.get(a); + if (arrayList != null) { + arrayList.clear(); + } + } unreadUnmutedDialogs = 0; boolean selfAdded = false; int selfId = UserConfig.getInstance(currentAccount).getClientUserId(); - Collections.sort(dialogs, dialogComparator); + Collections.sort(allDialogs, dialogComparator); isLeftProxyChannel = true; if (proxyDialog != null && proxyDialog.id < 0) { TLRPC.Chat chat = getChat(-(int) proxyDialog.id); @@ -9903,58 +10467,66 @@ public class MessagesController implements NotificationCenter.NotificationCenter isLeftProxyChannel = false; } } - for (int a = 0; a < dialogs.size(); a++) { - TLRPC.TL_dialog d = dialogs.get(a); + boolean countMessages = NotificationsController.getInstance(currentAccount).showBadgeMessages; + for (int a = 0, N = allDialogs.size(); a < N; a++) { + TLRPC.Dialog d = allDialogs.get(a); int high_id = (int) (d.id >> 32); int lower_id = (int) d.id; - if (lower_id == selfId) { - dialogsForward.add(0, d); - selfAdded = true; - } else { - dialogsForward.add(d); - } - if (lower_id != 0 && high_id != 1) { - dialogsServerOnly.add(d); - if (DialogObject.isChannel(d)) { - TLRPC.Chat chat = getChat(-lower_id); - if (chat != null && (chat.megagroup && (chat.admin_rights != null && (chat.admin_rights.post_messages || chat.admin_rights.add_admins)) || chat.creator)) { - dialogsCanAddUsers.add(d); - } - if (chat != null && chat.megagroup) { - dialogsGroupsOnly.add(d); - } else { - dialogsChannelsOnly.add(d); - } - } else if (lower_id < 0) { - if (chatsDict != null) { - TLRPC.Chat chat = chatsDict.get(-lower_id); - if (chat != null && chat.migrated_to != null) { - dialogs.remove(a); - a--; - continue; - } - } - dialogsCanAddUsers.add(d); - dialogsGroupsOnly.add(d); - } else if (lower_id > 0) { - dialogsUsersOnly.add(d); + if (d instanceof TLRPC.TL_dialog) { + if (lower_id == selfId) { + dialogsForward.add(0, d); + selfAdded = true; + } else { + dialogsForward.add(d); + } + if (lower_id != 0 && high_id != 1) { + dialogsServerOnly.add(d); + if (DialogObject.isChannel(d)) { + TLRPC.Chat chat = getChat(-lower_id); + if (chat != null && (chat.megagroup && (chat.admin_rights != null && (chat.admin_rights.post_messages || chat.admin_rights.add_admins)) || chat.creator)) { + dialogsCanAddUsers.add(d); + } + if (chat != null && chat.megagroup) { + dialogsGroupsOnly.add(d); + } else { + dialogsChannelsOnly.add(d); + } + } else if (lower_id < 0) { + if (chatsDict != null) { + TLRPC.Chat chat = chatsDict.get(-lower_id); + if (chat != null && chat.migrated_to != null) { + allDialogs.remove(a); + a--; + N--; + continue; + } + } + dialogsCanAddUsers.add(d); + dialogsGroupsOnly.add(d); + } else if (lower_id > 0) { + dialogsUsersOnly.add(d); + } } - } - if (proxyDialog != null && d.id == proxyDialog.id && isLeftProxyChannel) { - dialogs.remove(a); - a--; } if ((d.unread_count != 0 || d.unread_mark) && !isDialogMuted(d.id)) { unreadUnmutedDialogs++; } + if (proxyDialog != null && d.id == proxyDialog.id && isLeftProxyChannel) { + allDialogs.remove(a); + a--; + N--; + continue; + } + addDialogToItsFolder(-1, d, countMessages); } if (proxyDialog != null && isLeftProxyChannel) { - dialogs.add(0, proxyDialog); + allDialogs.add(0, proxyDialog); + addDialogToItsFolder(-2, proxyDialog, countMessages); } if (!selfAdded) { TLRPC.User user = UserConfig.getInstance(currentAccount).getCurrentUser(); if (user != null) { - TLRPC.TL_dialog dialog = new TLRPC.TL_dialog(); + TLRPC.Dialog dialog = new TLRPC.TL_dialog(); dialog.id = user.id; dialog.notify_settings = new TLRPC.TL_peerNotifySettings(); dialog.peer = new TLRPC.TL_peerUser(); @@ -9962,6 +10534,58 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialogsForward.add(0, dialog); } } + for (int a = 0; a < dialogsByFolder.size(); a++) { + int folderId = dialogsByFolder.keyAt(a); + ArrayList dialogs = dialogsByFolder.valueAt(a); + if (dialogs.isEmpty()) { + dialogsByFolder.remove(folderId); + } + } + } + + private void addDialogToItsFolder(int index, TLRPC.Dialog dialog, boolean countMessages) { + int folderId; + if (dialog instanceof TLRPC.TL_dialogFolder) { + folderId = 0; + dialog.unread_count = 0; + dialog.unread_mentions_count = 0; + } else { + folderId = dialog.folder_id; + } + ArrayList dialogs = dialogsByFolder.get(folderId); + if (dialogs == null) { + dialogs = new ArrayList<>(); + dialogsByFolder.put(folderId, dialogs); + } + if (folderId != 0 && dialog.unread_count != 0) { + TLRPC.Dialog folder = dialogs_dict.get(DialogObject.makeFolderDialogId(folderId)); + if (folder != null) { + if (countMessages) { + if (isDialogMuted(dialog.id)) { + folder.unread_count += dialog.unread_count; + } else { + folder.unread_mentions_count += dialog.unread_count; + } + } else { + if (isDialogMuted(dialog.id)) { + folder.unread_count++; + } else { + folder.unread_mentions_count++; + } + } + } + } + if (index == -1) { + dialogs.add(dialog); + } else if (index == -2) { + if (dialogs.isEmpty() || !(dialogs.get(0) instanceof TLRPC.TL_dialogFolder)) { + dialogs.add(0, dialog); + } else { + dialogs.add(1, dialog); + } + } else { + dialogs.add(index, dialog); + } } private static String getRestrictionReason(String reason) { @@ -10128,7 +10752,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (fragment.getParentActivity() == null) { return; } - final AlertDialog progressDialog[] = new AlertDialog[] {new AlertDialog(fragment.getParentActivity(), 3)}; + final AlertDialog[] progressDialog = new AlertDialog[]{new AlertDialog(fragment.getParentActivity(), 3)}; TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); req.username = username; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index 86349b165..4653f16cc 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -41,6 +41,10 @@ public class MessagesStorage { void run(int param); } + public interface BooleanCallback { + void run(boolean param); + } + private DispatchQueue storageQueue = new DispatchQueue("storageQueue"); private SQLiteDatabase database; private File cacheFile; @@ -64,8 +68,8 @@ public class MessagesStorage { private CountDownLatch openSync = new CountDownLatch(1); private int currentAccount; - private static volatile MessagesStorage Instance[] = new MessagesStorage[UserConfig.MAX_ACCOUNT_COUNT]; - private final static int LAST_DB_VERSION = 56; + private static volatile MessagesStorage[] Instance = new MessagesStorage[UserConfig.MAX_ACCOUNT_COUNT]; + private final static int LAST_DB_VERSION = 60; public static MessagesStorage getInstance(int num) { MessagesStorage localInstance = Instance[num]; @@ -161,7 +165,7 @@ public class MessagesStorage { public MessagesStorage(int instance) { currentAccount = instance; //storageQueue.setPriority(Thread.MAX_PRIORITY); - storageQueue.postRunnable(() -> openDatabase(true)); + storageQueue.postRunnable(() -> openDatabase(1)); } public SQLiteDatabase getDatabase() { @@ -186,7 +190,7 @@ public class MessagesStorage { return size; } - public void openDatabase(boolean first) { + public void openDatabase(int openTries) { File filesDir = ApplicationLoader.getFilesDirFixed(); if (currentAccount != 0) { filesDir = new File(filesDir, "account" + currentAccount + "/"); @@ -206,6 +210,7 @@ public class MessagesStorage { database.executeFast("PRAGMA secure_delete = ON").stepThis().dispose(); database.executeFast("PRAGMA temp_store = 1").stepThis().dispose(); database.executeFast("PRAGMA journal_mode = WAL").stepThis().dispose(); + if (createTable) { if (BuildVars.LOGS_ENABLED) { FileLog.d("create new database"); @@ -231,12 +236,13 @@ public class MessagesStorage { database.executeFast("CREATE TABLE user_phones_v7(key TEXT, phone TEXT, sphone TEXT, deleted INTEGER, PRIMARY KEY (key, phone))").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS sphone_deleted_idx_user_phones ON user_phones_v7(sphone, deleted);").stepThis().dispose(); - database.executeFast("CREATE TABLE dialogs(did INTEGER PRIMARY KEY, date INTEGER, unread_count INTEGER, last_mid INTEGER, inbox_max INTEGER, outbox_max INTEGER, last_mid_i INTEGER, unread_count_i INTEGER, pts INTEGER, date_i INTEGER, pinned INTEGER, flags INTEGER)").stepThis().dispose(); + database.executeFast("CREATE TABLE dialogs(did INTEGER PRIMARY KEY, date INTEGER, unread_count INTEGER, last_mid INTEGER, inbox_max INTEGER, outbox_max INTEGER, last_mid_i INTEGER, unread_count_i INTEGER, pts INTEGER, date_i INTEGER, pinned INTEGER, flags INTEGER, folder_id INTEGER, data BLOB)").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS date_idx_dialogs ON dialogs(date);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS last_mid_idx_dialogs ON dialogs(last_mid);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS unread_count_idx_dialogs ON dialogs(unread_count);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS last_mid_i_idx_dialogs ON dialogs(last_mid_i);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS unread_count_i_idx_dialogs ON dialogs(unread_count_i);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS folder_id_idx_dialogs ON dialogs(folder_id);").stepThis().dispose(); database.executeFast("CREATE TABLE randoms(random_id INTEGER, mid INTEGER, PRIMARY KEY (random_id, mid))").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS mid_idx_randoms ON randoms(mid);").stepThis().dispose(); @@ -295,6 +301,10 @@ public class MessagesStorage { database.executeFast("CREATE TABLE requested_holes(uid INTEGER, seq_out_start INTEGER, seq_out_end INTEGER, PRIMARY KEY (uid, seq_out_start, seq_out_end));").stepThis().dispose(); database.executeFast("CREATE TABLE sharing_locations(uid INTEGER PRIMARY KEY, mid INTEGER, date INTEGER, period INTEGER, message BLOB);").stepThis().dispose(); + database.executeFast("CREATE TABLE emoji_keywords_v2(lang TEXT, keyword TEXT, emoji TEXT, PRIMARY KEY(lang, keyword, emoji));").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS emoji_keywords_v2_keyword ON emoji_keywords_v2(keyword);").stepThis().dispose(); + database.executeFast("CREATE TABLE emoji_keywords_info_v2(lang TEXT PRIMARY KEY, alias TEXT, version INTEGER, date INTEGER);").stepThis().dispose(); + database.executeFast("CREATE TABLE wallpapers2(uid INTEGER PRIMARY KEY, data BLOB, num INTEGER)").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS wallpapers_num ON wallpapers2(num);").stepThis().dispose(); @@ -352,17 +362,19 @@ public class MessagesStorage { } } catch (Exception e) { FileLog.e(e); - if (first && e.getMessage().contains("malformed")) { - cleanupInternal(); - UserConfig.getInstance(currentAccount).dialogsLoadOffsetId = 0; - UserConfig.getInstance(currentAccount).totalDialogsLoadCount = 0; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetDate = 0; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetUserId = 0; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChatId = 0; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChannelId = 0; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetAccess = 0; - UserConfig.getInstance(currentAccount).saveConfig(false); - openDatabase(false); + + if (openTries < 3 && e.getMessage().contains("malformed")) { + if (openTries == 2) { + cleanupInternal(true); + for (int a = 0; a < 2; a++) { + UserConfig.getInstance(currentAccount).setDialogsLoadOffset(a, 0, 0, 0, 0, 0, 0); + UserConfig.getInstance(currentAccount).setTotalDialogsCount(a, 0); + } + UserConfig.getInstance(currentAccount).saveConfig(false); + } else { + cleanupInternal(false); + } + openDatabase(openTries == 1 ? 2 : 3); } } loadUnreadMessages(); @@ -753,7 +765,29 @@ public class MessagesStorage { database.executeFast("CREATE TABLE IF NOT EXISTS wallpapers2(uid INTEGER PRIMARY KEY, data BLOB, num INTEGER)").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS wallpapers_num ON wallpapers2(num);").stepThis().dispose(); database.executeFast("PRAGMA user_version = 56").stepThis().dispose(); - //version = 56; + version = 56; + } + if (version == 56 || version == 57) { + database.executeFast("CREATE TABLE IF NOT EXISTS emoji_keywords_v2(lang TEXT, keyword TEXT, emoji TEXT, PRIMARY KEY(lang, keyword, emoji));").stepThis().dispose(); + database.executeFast("CREATE TABLE IF NOT EXISTS emoji_keywords_info_v2(lang TEXT PRIMARY KEY, alias TEXT, version INTEGER);").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 58").stepThis().dispose(); + version = 58; + } + if (version == 58) { + database.executeFast("CREATE INDEX IF NOT EXISTS emoji_keywords_v2_keyword ON emoji_keywords_v2(keyword);").stepThis().dispose(); + database.executeFast("ALTER TABLE emoji_keywords_info_v2 ADD COLUMN date INTEGER default 0").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 59").stepThis().dispose(); + version = 59; + } + if (version == 59) { + database.executeFast("ALTER TABLE dialogs ADD COLUMN folder_id INTEGER default 0").stepThis().dispose(); + database.executeFast("ALTER TABLE dialogs ADD COLUMN data BLOB default NULL").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS folder_id_idx_dialogs ON dialogs(folder_id);").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 60").stepThis().dispose(); + version = 60; + } + if (version == 60) { + } } catch (Exception e) { FileLog.e(e); @@ -761,7 +795,7 @@ public class MessagesStorage { }); } - private void cleanupInternal() { + private void cleanupInternal(boolean deleteFiles) { lastDateValue = 0; lastSeqValue = 0; lastPtsValue = 0; @@ -779,17 +813,19 @@ public class MessagesStorage { database.close(); database = null; } - if (cacheFile != null) { - cacheFile.delete(); - cacheFile = null; - } - if (walCacheFile != null) { - walCacheFile.delete(); - walCacheFile = null; - } - if (shmCacheFile != null) { - shmCacheFile.delete(); - shmCacheFile = null; + if (deleteFiles) { + if (cacheFile != null) { + cacheFile.delete(); + cacheFile = null; + } + if (walCacheFile != null) { + walCacheFile.delete(); + walCacheFile = null; + } + if (shmCacheFile != null) { + shmCacheFile.delete(); + shmCacheFile = null; + } } } @@ -798,8 +834,8 @@ public class MessagesStorage { storageQueue.cleanupQueue(); } storageQueue.postRunnable(() -> { - cleanupInternal(); - openDatabase(false); + cleanupInternal(true); + openDatabase(1); if (isLogin) { Utilities.stageQueue.postRunnable(() -> MessagesController.getInstance(currentAccount).getDifference()); } @@ -934,8 +970,9 @@ public class MessagesStorage { case 2: case 5: case 8: - case 10: { - final TLRPC.TL_dialog dialog = new TLRPC.TL_dialog(); + case 10: + case 14: { + final TLRPC.Dialog dialog = new TLRPC.TL_dialog(); dialog.id = data.readInt64(false); dialog.top_message = data.readInt32(false); dialog.read_inbox_max_id = data.readInt32(false); @@ -954,6 +991,9 @@ public class MessagesStorage { if (type >= 10) { dialog.unread_mark = data.readBool(false); } + if (type >= 14) { + dialog.folder_id = data.readInt32(false); + } final TLRPC.InputPeer peer = TLRPC.InputPeer.TLdeserialize(data, data.readInt32(false), false); AndroidUtilities.runOnUIThread(() -> MessagesController.getInstance(currentAccount).checkLastDialogMessage(dialog, peer, taskId)); break; @@ -1024,6 +1064,43 @@ public class MessagesStorage { AndroidUtilities.runOnUIThread(() -> MessagesController.getInstance(currentAccount).saveWallpaperToServer(null, wallPaperId, accessHash, isBlurred, isMotion, backgroundColor, intesity, install, taskId)); break; } + case 13: { + final long did = data.readInt64(false); + final boolean first = data.readBool(false); + final int onlyHistory = data.readInt32(false); + final int maxIdDelete = data.readInt32(false); + final boolean revoke = data.readBool(false); + TLRPC.InputPeer inputPeer = TLRPC.InputPeer.TLdeserialize(data, data.readInt32(false), false); + AndroidUtilities.runOnUIThread(() -> MessagesController.getInstance(currentAccount).deleteDialog(did, first, onlyHistory, maxIdDelete, revoke, inputPeer, taskId)); + break; + } + case 15: { + TLRPC.InputPeer inputPeer = TLRPC.InputPeer.TLdeserialize(data, data.readInt32(false), false); + Utilities.stageQueue.postRunnable(() -> MessagesController.getInstance(currentAccount).loadUnknownDialog(inputPeer, taskId)); + break; + } + case 16: { + final int folderId = data.readInt32(false); + int count = data.readInt32(false); + ArrayList peers = new ArrayList<>(); + for (int a = 0; a < count; a++) { + TLRPC.InputDialogPeer inputPeer = TLRPC.InputDialogPeer.TLdeserialize(data, data.readInt32(false), false); + peers.add(inputPeer); + } + AndroidUtilities.runOnUIThread(() -> MessagesController.getInstance(currentAccount).reorderPinnedDialogs(folderId, peers, taskId)); + break; + } + case 17: { + final int folderId = data.readInt32(false); + int count = data.readInt32(false); + ArrayList peers = new ArrayList<>(); + for (int a = 0; a < count; a++) { + TLRPC.TL_inputFolderPeer inputPeer = TLRPC.TL_inputFolderPeer.TLdeserialize(data, data.readInt32(false), false); + peers.add(inputPeer); + } + AndroidUtilities.runOnUIThread(() -> MessagesController.getInstance(currentAccount).addDialogToFolder(null, folderId, -1, peers, taskId)); + break; + } } data.reuse(); } @@ -1136,6 +1213,81 @@ public class MessagesStorage { }); } + private class ReadDialog { + public int lastMid; + public int date; + public int unreadCount; + } + + public void readAllDialogs() { + storageQueue.postRunnable(() -> { + try { + ArrayList usersToLoad = new ArrayList<>(); + ArrayList chatsToLoad = new ArrayList<>(); + ArrayList encryptedChatIds = new ArrayList<>(); + + final LongSparseArray dialogs = new LongSparseArray<>(); + SQLiteCursor cursor = database.queryFinalized("SELECT did, last_mid, unread_count, date FROM dialogs WHERE unread_count != 0"); + while (cursor.next()) { + long did = cursor.longValue(0); + if (DialogObject.isFolderDialogId(did)) { + continue; + } + ReadDialog dialog = new ReadDialog(); + dialog.lastMid = cursor.intValue(1); + dialog.unreadCount = cursor.intValue(2); + dialog.date = cursor.intValue(3); + + dialogs.put(did, dialog); + int lower_id = (int) did; + int high_id = (int) (did >> 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); + } + } + } + cursor.dispose(); + + final ArrayList users = new ArrayList<>(); + final ArrayList chats = new ArrayList<>(); + final ArrayList encryptedChats = new ArrayList<>(); + if (!encryptedChatIds.isEmpty()) { + getEncryptedChatsInternal(TextUtils.join(",", encryptedChatIds), encryptedChats, usersToLoad); + } + if (!usersToLoad.isEmpty()) { + getUsersInternal(TextUtils.join(",", usersToLoad), users); + } + if (!chatsToLoad.isEmpty()) { + getChatsInternal(TextUtils.join(",", chatsToLoad), chats); + } + AndroidUtilities.runOnUIThread(() -> { + MessagesController.getInstance(currentAccount).putUsers(users, true); + MessagesController.getInstance(currentAccount).putChats(chats, true); + MessagesController.getInstance(currentAccount).putEncryptedChats(encryptedChats, true); + for (int a = 0; a < dialogs.size(); a++) { + long did = dialogs.keyAt(a); + ReadDialog dialog = dialogs.valueAt(a); + MessagesController.getInstance(currentAccount).markDialogAsRead(did, dialog.lastMid, dialog.lastMid, dialog.date, false, dialog.unreadCount, true); + } + }); + } catch (Exception e) { + FileLog.e(e); + } + }); + } + + public void loadUnreadMessages() { storageQueue.postRunnable(() -> { try { @@ -1153,6 +1305,9 @@ public class MessagesStorage { int mutedUntil = (int) (flags >> 32); if (cursor.isNull(2) || !muted || mutedUntil != 0 && mutedUntil < currentTime) { long did = cursor.longValue(0); + if (DialogObject.isFolderDialogId(did)) { + continue; + } int count = cursor.intValue(1); pushDialogs.put(did, count); if (ids.length() != 0) { @@ -1271,7 +1426,7 @@ public class MessagesStorage { String userName = cursor.isNull(7) ? null : cursor.stringValue(7); int flags = cursor.intValue(8); - pushMessages.add(new MessageObject(currentAccount, message, messageText, name, userName, (flags & 1) != 0, (flags & 2) != 0)); + pushMessages.add(new MessageObject(currentAccount, message, messageText, name, userName, (flags & 1) != 0, (flags & 2) != 0, false)); addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad); } } @@ -1783,7 +1938,7 @@ public class MessagesStorage { return; } - database.executeFast("UPDATE dialogs SET unread_count = 0 WHERE did = " + did).stepThis().dispose(); + database.executeFast("UPDATE dialogs SET unread_count = 0, unread_count_i = 0 WHERE did = " + did).stepThis().dispose(); database.executeFast("DELETE FROM messages WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM bot_keyboard WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM media_counts_v2 WHERE uid = " + did).stepThis().dispose(); @@ -1798,6 +1953,16 @@ public class MessagesStorage { }); } + public void onDeleteQueryComplete(final long did) { + storageQueue.postRunnable(() -> { + try { + database.executeFast("DELETE FROM media_counts_v2 WHERE uid = " + did).stepThis().dispose(); + } catch (Exception e) { + FileLog.e(e); + } + }); + } + public void getDialogPhotos(final int did, final int count, final long max_id, final int classGuid) { storageQueue.postRunnable(() -> { try { @@ -1848,7 +2013,7 @@ public class MessagesStorage { }); } - public void resetDialogs(final TLRPC.messages_Dialogs dialogsRes, final int messagesCount, final int seq, final int newPts, final int date, final int qts, final LongSparseArray new_dialogs_dict, final LongSparseArray new_dialogMessage, final TLRPC.Message lastMessage, final int dialogsCount) { + public void resetDialogs(final TLRPC.messages_Dialogs dialogsRes, final int messagesCount, final int seq, final int newPts, final int date, final int qts, final LongSparseArray new_dialogs_dict, final LongSparseArray new_dialogMessage, final TLRPC.Message lastMessage, final int dialogsCount) { storageQueue.postRunnable(() -> { try { int maxPinnedNum = 0; @@ -1861,7 +2026,7 @@ public class MessagesStorage { ArrayList orderArrayList = new ArrayList<>(); for (int a = dialogsCount; a < dialogsRes.dialogs.size(); a++) { - TLRPC.TL_dialog dialog = dialogsRes.dialogs.get(a); + TLRPC.Dialog dialog = dialogsRes.dialogs.get(a); orderArrayList.add(dialog.id); } @@ -1906,7 +2071,10 @@ public class MessagesStorage { database.commitTransaction(); for (int a = 0; a < totalPinnedCount; a++) { - TLRPC.TL_dialog dialog = dialogsRes.dialogs.get(dialogsCount + a); + TLRPC.Dialog dialog = dialogsRes.dialogs.get(dialogsCount + a); + if (dialog instanceof TLRPC.TL_dialog && !dialog.pinned) { + continue; + } int oldIdx = oldPinnedOrder.indexOf(dialog.id); int newIdx = orderArrayList.indexOf(dialog.id); if (oldIdx != -1 && newIdx != -1) { @@ -1931,46 +2099,61 @@ public class MessagesStorage { putDialogsInternal(dialogsRes, 0); saveDiffParamsInternal(seq, newPts, date, qts); - if (lastMessage != null && lastMessage.id != UserConfig.getInstance(currentAccount).dialogsLoadOffsetId) { - UserConfig.getInstance(currentAccount).totalDialogsLoadCount = dialogsRes.dialogs.size(); - UserConfig.getInstance(currentAccount).dialogsLoadOffsetId = lastMessage.id; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetDate = lastMessage.date; - if (lastMessage.to_id.channel_id != 0) { - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChannelId = lastMessage.to_id.channel_id; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChatId = 0; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetUserId = 0; - for (int a = 0; a < dialogsRes.chats.size(); a++) { - TLRPC.Chat chat = dialogsRes.chats.get(a); - if (chat.id == UserConfig.getInstance(currentAccount).dialogsLoadOffsetChannelId) { - UserConfig.getInstance(currentAccount).dialogsLoadOffsetAccess = chat.access_hash; - break; - } - } - } else if (lastMessage.to_id.chat_id != 0) { - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChatId = lastMessage.to_id.chat_id; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChannelId = 0; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetUserId = 0; - for (int a = 0; a < dialogsRes.chats.size(); a++) { - TLRPC.Chat chat = dialogsRes.chats.get(a); - if (chat.id == UserConfig.getInstance(currentAccount).dialogsLoadOffsetChatId) { - UserConfig.getInstance(currentAccount).dialogsLoadOffsetAccess = chat.access_hash; - break; - } - } - } else if (lastMessage.to_id.user_id != 0) { - UserConfig.getInstance(currentAccount).dialogsLoadOffsetUserId = lastMessage.to_id.user_id; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChatId = 0; - UserConfig.getInstance(currentAccount).dialogsLoadOffsetChannelId = 0; - for (int a = 0; a < dialogsRes.users.size(); a++) { - TLRPC.User user = dialogsRes.users.get(a); - if (user.id == UserConfig.getInstance(currentAccount).dialogsLoadOffsetUserId) { - UserConfig.getInstance(currentAccount).dialogsLoadOffsetAccess = user.access_hash; - break; - } + int totalDialogsLoadCount = UserConfig.getInstance(currentAccount).getTotalDialogsCount(0); + int[] dialogsLoadOffset = UserConfig.getInstance(currentAccount).getDialogLoadOffsets(0); + int dialogsLoadOffsetId; + int dialogsLoadOffsetDate; + int dialogsLoadOffsetChannelId = 0; + int dialogsLoadOffsetChatId = 0; + int dialogsLoadOffsetUserId = 0; + long dialogsLoadOffsetAccess = 0; + + totalDialogsLoadCount += dialogsRes.dialogs.size(); + dialogsLoadOffsetId = lastMessage.id; + dialogsLoadOffsetDate = lastMessage.date; + if (lastMessage.to_id.channel_id != 0) { + dialogsLoadOffsetChannelId = lastMessage.to_id.channel_id; + dialogsLoadOffsetChatId = 0; + dialogsLoadOffsetUserId = 0; + for (int a = 0; a < dialogsRes.chats.size(); a++) { + TLRPC.Chat chat = dialogsRes.chats.get(a); + if (chat.id == dialogsLoadOffsetChannelId) { + dialogsLoadOffsetAccess = chat.access_hash; + break; } } - } else { - UserConfig.getInstance(currentAccount).dialogsLoadOffsetId = Integer.MAX_VALUE; + } else if (lastMessage.to_id.chat_id != 0) { + dialogsLoadOffsetChatId = lastMessage.to_id.chat_id; + dialogsLoadOffsetChannelId = 0; + dialogsLoadOffsetUserId = 0; + for (int a = 0; a < dialogsRes.chats.size(); a++) { + TLRPC.Chat chat = dialogsRes.chats.get(a); + if (chat.id == dialogsLoadOffsetChatId) { + dialogsLoadOffsetAccess = chat.access_hash; + break; + } + } + } else if (lastMessage.to_id.user_id != 0) { + dialogsLoadOffsetUserId = lastMessage.to_id.user_id; + dialogsLoadOffsetChatId = 0; + dialogsLoadOffsetChannelId = 0; + for (int a = 0; a < dialogsRes.users.size(); a++) { + TLRPC.User user = dialogsRes.users.get(a); + if (user.id == dialogsLoadOffsetUserId) { + dialogsLoadOffsetAccess = user.access_hash; + break; + } + } + } + for (int a = 0; a < 2; a++) { + UserConfig.getInstance(currentAccount).setDialogsLoadOffset(a, + dialogsLoadOffsetId, + dialogsLoadOffsetDate, + dialogsLoadOffsetUserId, + dialogsLoadOffsetChatId, + dialogsLoadOffsetChannelId, + dialogsLoadOffsetAccess); + UserConfig.getInstance(currentAccount).setTotalDialogsCount(a, totalDialogsLoadCount); } UserConfig.getInstance(currentAccount).saveConfig(false); MessagesController.getInstance(currentAccount).completeDialogsReset(dialogsRes, messagesCount, seq, newPts, date, qts, new_dialogs_dict, new_dialogMessage, lastMessage); @@ -2683,13 +2866,13 @@ public class MessagesStorage { } storageQueue.postRunnable(() -> { MessageObject pinnedMessageObject = null; - TLRPC.TL_userFull info = null; + TLRPC.UserFull info = null; try { SQLiteCursor cursor = database.queryFinalized("SELECT info, pinned FROM user_settings WHERE uid = " + user.id); if (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { - info = TLRPC.TL_userFull.TLdeserialize(data, data.readInt32(false), false); + info = TLRPC.UserFull.TLdeserialize(data, data.readInt32(false), false); data.reuse(); info.pinned_msg_id = cursor.intValue(1); } @@ -2706,7 +2889,7 @@ public class MessagesStorage { }); } - public void updateUserInfo(final TLRPC.TL_userFull info, final boolean ifExist) { + public void updateUserInfo(final TLRPC.UserFull info, final boolean ifExist) { storageQueue.postRunnable(() -> { try { if (ifExist) { @@ -2761,35 +2944,17 @@ public class MessagesStorage { data.reuse(); if (info instanceof TLRPC.TL_channelFull) { - cursor = database.queryFinalized("SELECT date, pts, last_mid, inbox_max, outbox_max, pinned, unread_count_i, flags FROM dialogs WHERE did = " + (-info.id)); + cursor = database.queryFinalized("SELECT inbox_max, outbox_max FROM dialogs WHERE did = " + (-info.id)); if (cursor.next()) { - int inbox_max = cursor.intValue(3); + int inbox_max = cursor.intValue(0); if (inbox_max < info.read_inbox_max_id) { - /*int inbox_diff = info.read_inbox_max_id - inbox_max; - if (inbox_diff < info.unread_count) { - info.unread_count = inbox_diff; - }*/ - int dialog_date = cursor.intValue(0); - int pts = cursor.intValue(1); - long last_mid = cursor.longValue(2); - int outbox_max = cursor.intValue(4); - int pinned = cursor.intValue(5); - int mentions = cursor.intValue(6); - int flags = cursor.intValue(7); + int outbox_max = cursor.intValue(1); - state = database.executeFast("REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); - state.bindLong(1, -info.id); - state.bindInteger(2, dialog_date); - state.bindInteger(3, info.unread_count); - state.bindLong(4, last_mid); - state.bindInteger(5, info.read_inbox_max_id); - state.bindInteger(6, Math.max(outbox_max, info.read_outbox_max_id)); - state.bindLong(7, 0); - state.bindInteger(8, mentions); - state.bindInteger(9, pts); - state.bindInteger(10, 0); - state.bindInteger(11, pinned); - state.bindInteger(12, flags); + state = database.executeFast("UPDATE dialogs SET unread_count = ?, inbox_max = ?, outbox_max = ? WHERE did = ?"); + state.bindInteger(1, info.unread_count); + state.bindInteger(2, info.read_inbox_max_id); + state.bindInteger(3, Math.max(outbox_max, info.read_outbox_max_id)); + state.bindLong(4, -info.id); state.step(); state.dispose(); } @@ -2806,21 +2971,21 @@ public class MessagesStorage { storageQueue.postRunnable(() -> { try { SQLiteCursor cursor = database.queryFinalized("SELECT info, pinned FROM user_settings WHERE uid = " + userId); - TLRPC.TL_userFull info = null; + TLRPC.UserFull info = null; if (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { - info = TLRPC.TL_userFull.TLdeserialize(data, data.readInt32(false), false); + info = TLRPC.UserFull.TLdeserialize(data, data.readInt32(false), false); data.reuse(); info.pinned_msg_id = cursor.intValue(1); } } cursor.dispose(); - if (info instanceof TLRPC.TL_userFull) { + if (info instanceof TLRPC.UserFull) { info.pinned_msg_id = messageId; info.flags |= 64; - final TLRPC.TL_userFull finalInfo = info; + final TLRPC.UserFull finalInfo = info; AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.userInfoDidLoad, userId, finalInfo, null)); SQLitePreparedStatement state = database.executeFast("REPLACE INTO user_settings VALUES(?, ?, ?)"); @@ -2979,7 +3144,7 @@ public class MessagesStorage { public boolean isMigratedChat(final int chat_id) { final CountDownLatch countDownLatch = new CountDownLatch(1); - final boolean result[] = new boolean[1]; + final boolean[] result = new boolean[1]; storageQueue.postRunnable(() -> { try { SQLiteCursor cursor = database.queryFinalized("SELECT info FROM chat_settings_v2 WHERE uid = " + chat_id); @@ -4520,7 +4685,7 @@ public class MessagesStorage { public boolean isDialogHasMessages(final long did) { final CountDownLatch countDownLatch = new CountDownLatch(1); - final boolean result[] = new boolean[1]; + final boolean[] result = new boolean[1]; storageQueue.postRunnable(() -> { try { SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT mid FROM messages WHERE uid = %d LIMIT 1", did)); @@ -4542,7 +4707,7 @@ public class MessagesStorage { public boolean hasAuthMessage(final int date) { final CountDownLatch countDownLatch = new CountDownLatch(1); - final boolean result[] = new boolean[1]; + final boolean[] result = new boolean[1]; storageQueue.postRunnable(() -> { try { SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT mid FROM messages WHERE uid = 777000 AND date = %d AND mid < 0 LIMIT 1", date)); @@ -4587,7 +4752,7 @@ public class MessagesStorage { }); } - public void putEncryptedChat(final TLRPC.EncryptedChat chat, final TLRPC.User user, final TLRPC.TL_dialog dialog) { + public void putEncryptedChat(final TLRPC.EncryptedChat chat, final TLRPC.User user, final TLRPC.Dialog dialog) { if (chat == null) { return; } @@ -4644,7 +4809,7 @@ public class MessagesStorage { data4.reuse(); data5.reuse(); if (dialog != null) { - state = database.executeFast("REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + state = database.executeFast("REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); state.bindLong(1, dialog.id); state.bindInteger(2, dialog.last_message_date); state.bindInteger(3, dialog.unread_count); @@ -4657,6 +4822,8 @@ public class MessagesStorage { state.bindInteger(10, 0); state.bindInteger(11, dialog.pinnedNum); state.bindInteger(12, dialog.flags); + state.bindInteger(13, dialog.folder_id); + state.bindNull(14); state.step(); state.dispose(); } @@ -5022,9 +5189,10 @@ public class MessagesStorage { if (messageMedia.document != null) { downloadObject.object = messageMedia.document; } else if (messageMedia.photo != null) { - downloadObject.object = FileLoader.getClosestPhotoSizeWithSize(messageMedia.photo.sizes, AndroidUtilities.getPhotoSize()); + downloadObject.object = messageMedia.photo; } downloadObject.secret = messageMedia.ttl_seconds != 0; + downloadObject.forceCache = (messageMedia.flags & 0x80000000) != 0; } objects.add(downloadObject); } @@ -5142,13 +5310,13 @@ public class MessagesStorage { final long did = -channel_id; int pinned = 0; - SQLiteCursor cursor = database.queryFinalized("SELECT pts, pinned FROM dialogs WHERE did = " + did); + SQLiteCursor cursor = database.queryFinalized("SELECT pinned FROM dialogs WHERE did = " + did); if (!cursor.next()) { if (newDialogType != 0) { checkInvite = true; } } else { - pinned = cursor.intValue(1); + pinned = cursor.intValue(0); } cursor.dispose(); @@ -5165,20 +5333,12 @@ public class MessagesStorage { dialogs.chats.addAll(difference.chats); dialogs.users.addAll(difference.users); dialogs.messages.addAll(difference.messages); - TLRPC.TL_dialog dialog = new TLRPC.TL_dialog(); + TLRPC.Dialog dialog = difference.dialog; dialog.id = did; dialog.flags = 1; - dialog.peer = new TLRPC.TL_peerChannel(); - dialog.peer.channel_id = channel_id; - dialog.top_message = difference.top_message; - dialog.read_inbox_max_id = difference.read_inbox_max_id; - dialog.read_outbox_max_id = difference.read_outbox_max_id; - dialog.unread_count = difference.unread_count; - dialog.unread_mentions_count = difference.unread_mentions_count; dialog.notify_settings = null; dialog.pinned = pinned != 0; dialog.pinnedNum = pinned; - dialog.pts = difference.pts; dialogs.dialogs.add(dialog); putDialogsInternal(dialogs, 0); @@ -5440,7 +5600,7 @@ public class MessagesStorage { if (updateDialog) { TLRPC.Message lastMessage = messagesMap.get(message.dialog_id); - if (lastMessage == null || message.date > lastMessage.date || message.id > 0 && lastMessage.id > 0 && message.id > lastMessage.id || message.id < 0 && lastMessage.id < 0 && message.id < lastMessage.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); } } @@ -5501,43 +5661,48 @@ public class MessagesStorage { data.reuse(); if (downloadMask != 0 && (message.to_id.channel_id == 0 || message.post) && message.date >= ConnectionsManager.getInstance(currentAccount).getCurrentTime() - 60 * 60 && DownloadController.getInstance(currentAccount).canDownloadMedia(message) == 1) { - if (message.media instanceof TLRPC.TL_messageMediaPhoto || message.media instanceof TLRPC.TL_messageMediaDocument) { + 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 = message.media.document.id; + id = document.id; type = DownloadController.AUTODOWNLOAD_TYPE_AUDIO; object = new TLRPC.TL_messageMediaDocument(); - object.document = message.media.document; + object.document = document; object.flags |= 1; } else if (MessageObject.isStickerMessage(message)) { - id = message.media.document.id; + id = document.id; type = DownloadController.AUTODOWNLOAD_TYPE_PHOTO; object = new TLRPC.TL_messageMediaDocument(); - object.document = message.media.document; + object.document = document; object.flags |= 1; - } else if (message.media instanceof TLRPC.TL_messageMediaPhoto) { - TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(message.media.photo.sizes, AndroidUtilities.getPhotoSize()); - if (photoSize != null) { - id = message.media.photo.id; - type = DownloadController.AUTODOWNLOAD_TYPE_PHOTO; - object = new TLRPC.TL_messageMediaPhoto(); - object.photo = message.media.photo; - object.flags |= 1; - } - } else if (MessageObject.isVideoMessage(message) || MessageObject.isRoundVideoMessage(message)) { - id = message.media.document.id; + } 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 = message.media.document; + object.document = document; object.flags |= 1; - } else if (message.media instanceof TLRPC.TL_messageMediaDocument && !MessageObject.isMusicMessage(message) && !MessageObject.isGifDocument(message.media.document)) { - id = message.media.document.id; + } else if (document != null) { + id = document.id; type = DownloadController.AUTODOWNLOAD_TYPE_DOCUMENT; object = new TLRPC.TL_messageMediaDocument(); - object.document = message.media.document; + 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; + 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) { @@ -5570,7 +5735,8 @@ public class MessagesStorage { state_download.dispose(); state_webpage.dispose(); - state_messages = database.executeFast("REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + 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); @@ -5584,26 +5750,17 @@ public class MessagesStorage { channelId = message.to_id.channel_id; } - SQLiteCursor cursor = database.queryFinalized("SELECT date, unread_count, pts, last_mid, inbox_max, outbox_max, pinned, unread_count_i, flags FROM dialogs WHERE did = " + key); + 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 pts = channelId != 0 ? 1 : 0; - int inbox_max = 0; - int outbox_max = 0; - int pinned = 0; int old_mentions_count = 0; - int flags = 0; - if (cursor.next()) { + boolean exists; + if (exists = cursor.next()) { dialog_date = cursor.intValue(0); old_unread_count = Math.max(0, cursor.intValue(1)); - pts = cursor.intValue(2); - last_mid = cursor.intValue(3); - inbox_max = cursor.intValue(4); - outbox_max = cursor.intValue(5); - pinned = cursor.intValue(6); - old_mentions_count = Math.max(0, cursor.intValue(7)); - flags = cursor.intValue(8); + last_mid = cursor.intValue(2); + old_mentions_count = Math.max(0, cursor.intValue(3)); } else if (channelId != 0) { MessagesController.getInstance(currentAccount).checkChannelInviter(channelId); } @@ -5632,26 +5789,35 @@ public class MessagesStorage { messageId |= ((long) channelId) << 32; } - state_messages.requery(); - state_messages.bindLong(1, key); - if (message != null && (!doNotUpdateDialogDate || dialog_date == 0)) { - state_messages.bindInteger(2, message.date); + 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_messages.bindInteger(2, dialog_date); + 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_messages.bindInteger(3, old_unread_count + unread_count); - state_messages.bindLong(4, messageId); - state_messages.bindInteger(5, inbox_max); - state_messages.bindInteger(6, outbox_max); - state_messages.bindLong(7, 0); - state_messages.bindInteger(8, old_mentions_count + mentions_count); - state_messages.bindInteger(9, pts); - state_messages.bindInteger(10, 0); - state_messages.bindInteger(11, pinned); - state_messages.bindInteger(12, flags); - state_messages.step(); } - state_messages.dispose(); + state_dialogs_update.dispose(); + state_dialogs_replace.dispose(); if (mediaCounts != null) { state_randoms = database.executeFast("REPLACE INTO media_counts_v2 VALUES(?, ?, ?, ?)"); @@ -6104,6 +6270,14 @@ public class MessagesStorage { }); } + protected void deletePushMessages(long dialogId, final ArrayList messages) { + try { + database.executeFast(String.format(Locale.US, "DELETE FROM unread_push_messages WHERE uid = %d AND mid IN(%s)", dialogId, TextUtils.join(",", messages))).stepThis().dispose(); + } catch (Exception e) { + FileLog.e(e); + } + } + private ArrayList markMessagesAsDeletedInternal(final ArrayList messages, int channelId) { try { String ids; @@ -6337,10 +6511,27 @@ public class MessagesStorage { ArrayList usersToLoad = new ArrayList<>(); ArrayList chatsToLoad = new ArrayList<>(); ArrayList encryptedToLoad = new ArrayList<>(); - SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT d.did, d.last_mid, d.unread_count, d.date, m.data, m.read_state, m.mid, m.send_state, m.date, d.pts, d.inbox_max, d.outbox_max, d.pinned, d.unread_count_i, d.flags FROM dialogs as d LEFT JOIN messages as m ON d.last_mid = m.mid WHERE d.did IN(%s)", ids)); + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT d.did, d.last_mid, d.unread_count, d.date, m.data, m.read_state, m.mid, m.send_state, m.date, d.pts, d.inbox_max, d.outbox_max, d.pinned, d.unread_count_i, d.flags, d.folder_id, d.data FROM dialogs as d LEFT JOIN messages as m ON d.last_mid = m.mid WHERE d.did IN(%s)", ids)); while (cursor.next()) { - TLRPC.TL_dialog dialog = new TLRPC.TL_dialog(); - dialog.id = cursor.longValue(0); + long dialogId = cursor.longValue(0); + TLRPC.Dialog dialog; + if (DialogObject.isFolderDialogId(dialogId)) { + TLRPC.TL_dialogFolder dialogFolder = new TLRPC.TL_dialogFolder(); + if (!cursor.isNull(16)) { + NativeByteBuffer data = cursor.byteBufferValue(16); + if (data != null) { + dialogFolder.folder = TLRPC.TL_folder.TLdeserialize(data, data.readInt32(false), false); + } else { + dialogFolder.folder = new TLRPC.TL_folder(); + dialogFolder.folder.id = cursor.intValue(15); + } + data.reuse(); + } + dialog = dialogFolder; + } else { + dialog = new TLRPC.TL_dialog(); + } + dialog.id = dialogId; dialog.top_message = cursor.intValue(1); dialog.read_inbox_max_id = cursor.intValue(10); dialog.read_outbox_max_id = cursor.intValue(11); @@ -6353,6 +6544,7 @@ public class MessagesStorage { dialog.pinned = dialog.pinnedNum != 0; int dialog_flags = cursor.intValue(14); dialog.unread_mark = (dialog_flags & 1) != 0; + dialog.folder_id = cursor.intValue(15); dialogs.dialogs.add(dialog); @@ -6771,7 +6963,7 @@ public class MessagesStorage { } } - public void replaceMessageIfExists(final TLRPC.Message message) { + public void replaceMessageIfExists(final TLRPC.Message message, int currentAccount, ArrayList users, ArrayList chats, boolean broadcast) { if (message == null) { return; } @@ -6845,6 +7037,22 @@ public class MessagesStorage { state2.dispose(); database.commitTransaction(); + if (broadcast) { + HashMap userHashMap = new HashMap<>(); + HashMap chatHashMap = new HashMap<>(); + for (int a = 0; a < users.size(); a++) { + TLRPC.User user = users.get(a); + userHashMap.put(user.id, user); + } + for (int a = 0; a < chats.size(); a++) { + TLRPC.Chat chat = chats.get(a); + chatHashMap.put(chat.id, chat); + } + MessageObject messageObject = new MessageObject(currentAccount, message, userHashMap, chatHashMap, true); + ArrayList arrayList = new ArrayList<>(); + arrayList.add(messageObject); + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.replaceMessagesObjects, messageObject.getDialogId(), arrayList)); + } } catch (Exception e) { FileLog.e(e); } @@ -6952,26 +7160,41 @@ public class MessagesStorage { int mentions = 0; int flags = 0; SQLiteCursor cursor = database.queryFinalized("SELECT pinned, unread_count_i, flags FROM dialogs WHERE did = " + dialog_id); - if (cursor.next()) { + boolean exist; + if (exist = cursor.next()) { pinned = cursor.intValue(0); mentions = cursor.intValue(1); flags = cursor.intValue(2); } cursor.dispose(); - SQLitePreparedStatement 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); + 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(); } @@ -7149,7 +7372,7 @@ public class MessagesStorage { } } - public void getDialogs(final int offset, final int count) { + public void getDialogs(final int folderId, final int offset, final int count) { storageQueue.postRunnable(() -> { TLRPC.messages_Dialogs dialogs = new TLRPC.TL_messages_dialogs(); ArrayList encryptedChats = new ArrayList<>(); @@ -7160,115 +7383,151 @@ public class MessagesStorage { ArrayList encryptedToLoad = new ArrayList<>(); ArrayList replyMessages = new ArrayList<>(); LongSparseArray replyMessageOwners = new LongSparseArray<>(); - SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT d.did, d.last_mid, d.unread_count, d.date, m.data, m.read_state, m.mid, m.send_state, s.flags, m.date, d.pts, d.inbox_max, d.outbox_max, m.replydata, d.pinned, d.unread_count_i, d.flags FROM dialogs as d LEFT JOIN messages as m ON d.last_mid = m.mid LEFT JOIN dialog_settings as s ON d.did = s.did ORDER BY d.pinned DESC, d.date DESC LIMIT %d,%d", offset, count)); - while (cursor.next()) { - TLRPC.TL_dialog dialog = new TLRPC.TL_dialog(); - dialog.id = cursor.longValue(0); - dialog.top_message = cursor.intValue(1); - dialog.unread_count = cursor.intValue(2); - dialog.last_message_date = cursor.intValue(3); - dialog.pts = cursor.intValue(10); - dialog.flags = dialog.pts == 0 || (int) dialog.id > 0 ? 0 : 1; - dialog.read_inbox_max_id = cursor.intValue(11); - dialog.read_outbox_max_id = cursor.intValue(12); - dialog.pinnedNum = cursor.intValue(14); - dialog.pinned = dialog.pinnedNum != 0; - dialog.unread_mentions_count = cursor.intValue(15); - int dialog_flags = cursor.intValue(16); - dialog.unread_mark = (dialog_flags & 1) != 0; - long flags = cursor.longValue(8); - int low_flags = (int) flags; - dialog.notify_settings = new TLRPC.TL_peerNotifySettings(); - if ((low_flags & 1) != 0) { - dialog.notify_settings.mute_until = (int) (flags >> 32); - if (dialog.notify_settings.mute_until == 0) { - dialog.notify_settings.mute_until = Integer.MAX_VALUE; - } + ArrayList foldersToLoad = new ArrayList<>(2); + foldersToLoad.add(folderId); + for (int a = 0; a < foldersToLoad.size(); a++) { + int fid = foldersToLoad.get(a); + int off; + int cnt; + if (a == 0) { + off = offset; + cnt = count; + } else { + off = 0; + cnt = 50; } - dialogs.dialogs.add(dialog); - NativeByteBuffer data = cursor.byteBufferValue(4); - if (data != null) { - TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); - message.readAttachPath(data, UserConfig.getInstance(currentAccount).clientUserId); - data.reuse(); - if (message != null) { - MessageObject.setUnreadFlags(message, cursor.intValue(5)); - message.id = cursor.intValue(6); - int date = cursor.intValue(9); - if (date != 0) { - dialog.last_message_date = date; - } - message.send_state = cursor.intValue(7); - message.dialog_id = dialog.id; - dialogs.messages.add(message); - - addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad); - - try { - if (message.reply_to_msg_id != 0 && ( - message.action instanceof TLRPC.TL_messageActionPinMessage || - message.action instanceof TLRPC.TL_messageActionPaymentSent || - message.action instanceof TLRPC.TL_messageActionGameScore)) { - if (!cursor.isNull(13)) { - data = cursor.byteBufferValue(13); - if (data != null) { - message.replyMessage = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); - message.replyMessage.readAttachPath(data, UserConfig.getInstance(currentAccount).clientUserId); - 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) { - 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); - } - replyMessageOwners.put(dialog.id, message); - } + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT d.did, d.last_mid, d.unread_count, d.date, m.data, m.read_state, m.mid, m.send_state, s.flags, m.date, d.pts, d.inbox_max, d.outbox_max, m.replydata, d.pinned, d.unread_count_i, d.flags, d.folder_id, d.data FROM dialogs as d LEFT JOIN messages as m ON d.last_mid = m.mid LEFT JOIN dialog_settings as s ON d.did = s.did WHERE d.folder_id = %d ORDER BY d.pinned DESC, d.date DESC LIMIT %d,%d", fid, off, cnt)); + while (cursor.next()) { + long dialogId = cursor.longValue(0); + TLRPC.Dialog dialog; + if (DialogObject.isFolderDialogId(dialogId)) { + TLRPC.TL_dialogFolder dialogFolder = new TLRPC.TL_dialogFolder(); + if (!cursor.isNull(18)) { + NativeByteBuffer data = cursor.byteBufferValue(18); + if (data != null) { + dialogFolder.folder = TLRPC.TL_folder.TLdeserialize(data, data.readInt32(false), false); + } else { + dialogFolder.folder = new TLRPC.TL_folder(); + dialogFolder.folder.id = (int) dialogId; } - } catch (Exception e) { - FileLog.e(e); + data.reuse(); } - } - } - - 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); + dialog = dialogFolder; + if (a == 0) { + foldersToLoad.add(dialogFolder.folder.id); } } else { - if (lower_id > 0) { - if (!usersToLoad.contains(lower_id)) { - usersToLoad.add(lower_id); + dialog = new TLRPC.TL_dialog(); + } + dialog.id = dialogId; + dialog.top_message = cursor.intValue(1); + dialog.unread_count = cursor.intValue(2); + dialog.last_message_date = cursor.intValue(3); + dialog.pts = cursor.intValue(10); + dialog.flags = dialog.pts == 0 || (int) dialog.id > 0 ? 0 : 1; + dialog.read_inbox_max_id = cursor.intValue(11); + dialog.read_outbox_max_id = cursor.intValue(12); + dialog.pinnedNum = cursor.intValue(14); + dialog.pinned = dialog.pinnedNum != 0; + dialog.unread_mentions_count = cursor.intValue(15); + int dialog_flags = cursor.intValue(16); + dialog.unread_mark = (dialog_flags & 1) != 0; + long flags = cursor.longValue(8); + int low_flags = (int) flags; + dialog.notify_settings = new TLRPC.TL_peerNotifySettings(); + if ((low_flags & 1) != 0) { + dialog.notify_settings.mute_until = (int) (flags >> 32); + if (dialog.notify_settings.mute_until == 0) { + dialog.notify_settings.mute_until = Integer.MAX_VALUE; + } + } + dialog.folder_id = cursor.intValue(17); + dialogs.dialogs.add(dialog); + + NativeByteBuffer data = cursor.byteBufferValue(4); + if (data != null) { + TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + message.readAttachPath(data, UserConfig.getInstance(currentAccount).clientUserId); + data.reuse(); + if (message != null) { + MessageObject.setUnreadFlags(message, cursor.intValue(5)); + message.id = cursor.intValue(6); + int date = cursor.intValue(9); + if (date != 0) { + dialog.last_message_date = date; } - } else { - if (!chatsToLoad.contains(-lower_id)) { - chatsToLoad.add(-lower_id); + message.send_state = cursor.intValue(7); + message.dialog_id = dialog.id; + dialogs.messages.add(message); + + addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad); + + try { + if (message.reply_to_msg_id != 0 && ( + message.action instanceof TLRPC.TL_messageActionPinMessage || + message.action instanceof TLRPC.TL_messageActionPaymentSent || + message.action instanceof TLRPC.TL_messageActionGameScore)) { + if (!cursor.isNull(13)) { + data = cursor.byteBufferValue(13); + if (data != null) { + message.replyMessage = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); + message.replyMessage.readAttachPath(data, UserConfig.getInstance(currentAccount).clientUserId); + 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) { + 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); + } + replyMessageOwners.put(dialog.id, message); + } + } + } catch (Exception e) { + FileLog.e(e); } } } - } else { - if (!encryptedToLoad.contains(high_id)) { - encryptedToLoad.add(high_id); + + 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); + } + } else { + if (lower_id > 0) { + if (!usersToLoad.contains(lower_id)) { + usersToLoad.add(lower_id); + } + } else { + if (!chatsToLoad.contains(-lower_id)) { + chatsToLoad.add(-lower_id); + } + } + } + } else { + if (!encryptedToLoad.contains(high_id)) { + encryptedToLoad.add(high_id); + } } } + cursor.dispose(); } - cursor.dispose(); if (!replyMessages.isEmpty()) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid, date, uid FROM messages WHERE mid IN(%s)", TextUtils.join(",", replyMessages))); + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid, date, uid FROM messages WHERE mid IN(%s)", TextUtils.join(",", replyMessages))); while (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { @@ -7303,14 +7562,14 @@ public class MessagesStorage { if (!usersToLoad.isEmpty()) { getUsersInternal(TextUtils.join(",", usersToLoad), dialogs.users); } - MessagesController.getInstance(currentAccount).processLoadedDialogs(dialogs, encryptedChats, offset, count, 1, false, false, true); + MessagesController.getInstance(currentAccount).processLoadedDialogs(dialogs, encryptedChats, folderId, offset, count, 1, false, false, true); } catch (Exception e) { dialogs.dialogs.clear(); dialogs.users.clear(); dialogs.chats.clear(); encryptedChats.clear(); FileLog.e(e); - MessagesController.getInstance(currentAccount).processLoadedDialogs(dialogs, encryptedChats, 0, 100, 1, true, false, true); + MessagesController.getInstance(currentAccount).processLoadedDialogs(dialogs, encryptedChats, folderId, 0, 100, 1, true, false, true); } }); } @@ -7343,7 +7602,7 @@ public class MessagesStorage { if (!dialogs.dialogs.isEmpty()) { SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?)"); - SQLitePreparedStatement state_dialogs = database.executeFast("REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + SQLitePreparedStatement state_dialogs = database.executeFast("REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); SQLitePreparedStatement state_media = database.executeFast("REPLACE INTO media_v2 VALUES(?, ?, ?, ?, ?)"); SQLitePreparedStatement state_settings = database.executeFast("REPLACE INTO dialog_settings VALUES(?, ?)"); SQLitePreparedStatement state_holes = database.executeFast("REPLACE INTO messages_holes VALUES(?, ?, ?)"); @@ -7351,17 +7610,9 @@ public class MessagesStorage { SQLitePreparedStatement state_polls = null; for (int a = 0; a < dialogs.dialogs.size(); a++) { - TLRPC.TL_dialog dialog = dialogs.dialogs.get(a); + TLRPC.Dialog dialog = dialogs.dialogs.get(a); - if (dialog.id == 0) { - if (dialog.peer.user_id != 0) { - dialog.id = dialog.peer.user_id; - } else if (dialog.peer.chat_id != 0) { - dialog.id = -dialog.peer.chat_id; - } else { - dialog.id = -dialog.peer.channel_id; - } - } + DialogObject.initDialog(dialog); if (check == 1) { SQLiteCursor cursor = database.queryFinalized("SELECT did FROM dialogs WHERE did = " + dialog.id); boolean exists = cursor.next(); @@ -7435,7 +7686,7 @@ public class MessagesStorage { } long topMessage = dialog.top_message; - if (dialog.peer.channel_id != 0) { + if (dialog.peer != null && dialog.peer.channel_id != 0) { topMessage |= ((long) dialog.peer.channel_id) << 32; } @@ -7456,7 +7707,21 @@ public class MessagesStorage { flags |= 1; } state_dialogs.bindInteger(12, flags); + state_dialogs.bindInteger(13, dialog.folder_id); + NativeByteBuffer data; + if (dialog instanceof TLRPC.TL_dialogFolder) { + TLRPC.TL_dialogFolder dialogFolder = (TLRPC.TL_dialogFolder) dialog; + data = new NativeByteBuffer(dialogFolder.folder.getObjectSize()); + dialogFolder.folder.serializeToStream(data); + state_dialogs.bindByteBuffer(14, data); + } else { + data = null; + state_dialogs.bindNull(14); + } state_dialogs.step(); + if (data != null) { + data.reuse(); + } if (dialog.notify_settings != null) { state_settings.requery(); @@ -7485,14 +7750,91 @@ public class MessagesStorage { } } - public void unpinAllDialogsExceptNew(final ArrayList dids) { + public void getDialogFolderId(long dialogId, IntCallback callback) { + storageQueue.postRunnable(() -> { + try { + int folderId; + SQLiteCursor cursor = database.queryFinalized("SELECT folder_id FROM dialogs WHERE did = ?", dialogId); + if (cursor.next()) { + folderId = cursor.intValue(0); + } else { + folderId = -1; + } + cursor.dispose(); + AndroidUtilities.runOnUIThread(() -> callback.run(folderId)); + } catch (Exception e) { + FileLog.e(e); + } + }); + } + + public void setDialogsFolderId(final ArrayList peers, ArrayList inputPeers, long dialogId, int folderId) { + if (peers == null && inputPeers == null && dialogId == 0) { + return; + } + storageQueue.postRunnable(() -> { + try { + database.beginTransaction(); + SQLitePreparedStatement state = database.executeFast("UPDATE dialogs SET folder_id = ? 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.step(); + } + } else if (inputPeers != null) { + for (int a = 0, N = inputPeers.size(); a < N; a++) { + TLRPC.TL_inputFolderPeer folderPeer = inputPeers.get(a); + long did = DialogObject.getPeerDialogId(folderPeer.peer); + state.requery(); + state.bindInteger(1, folderPeer.folder_id); + state.bindLong(2, did); + state.step(); + } + } else { + state.requery(); + state.bindInteger(1, folderId); + state.bindLong(2, dialogId); + state.step(); + } + state.dispose(); + database.commitTransaction(); + checkIfFolderEmptyInternal(1); + } catch (Exception e) { + FileLog.e(e); + } + }); + } + + private void checkIfFolderEmptyInternal(int folderId) { + try { + SQLiteCursor cursor = database.queryFinalized("SELECT did FROM dialogs WHERE folder_id = ?", folderId); + if (!cursor.next()) { + AndroidUtilities.runOnUIThread(() -> MessagesController.getInstance(currentAccount).onFolderEmpty(folderId)); + database.executeFast("DELETE FROM dialogs WHERE did = " + DialogObject.makeFolderDialogId(folderId)).stepThis().dispose(); + } + cursor.dispose(); + } catch (Exception e) { + FileLog.e(e); + } + } + + public void checkIfFolderEmpty(int folderId) { + storageQueue.postRunnable(() -> checkIfFolderEmptyInternal(folderId)); + } + + public void unpinAllDialogsExceptNew(final ArrayList dids, int folderId) { storageQueue.postRunnable(() -> { try { ArrayList unpinnedDialogs = new ArrayList<>(); - SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT did FROM dialogs WHERE pinned != 0 AND did NOT IN (%s)", TextUtils.join(",", dids))); + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT did, folder_id FROM dialogs WHERE pinned != 0 AND did NOT IN (%s)", TextUtils.join(",", dids))); while (cursor.next()) { long did = cursor.longValue(0); - if ((int) did != 0) { + int fid = cursor.intValue(1); + if (fid == folderId && (int) did != 0 && !DialogObject.isFolderDialogId(did)) { unpinnedDialogs.add(cursor.longValue(0)); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MusicBrowserService.java b/TMessagesProj/src/main/java/org/telegram/messenger/MusicBrowserService.java index a0e1b5a17..879219d2c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MusicBrowserService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MusicBrowserService.java @@ -276,7 +276,7 @@ public class MusicBrowserService extends MediaBrowserService implements Notifica TLRPC.User user = users.get(did); if (user != null) { builder.setTitle(ContactsController.formatName(user.first_name, user.last_name)); - if (user.photo != null && user.photo.photo_small instanceof TLRPC.TL_fileLocation) { + if (user.photo != null && !(user.photo.photo_small instanceof TLRPC.TL_fileLocationUnavailable)) { avatar = user.photo.photo_small; } } else { @@ -286,7 +286,7 @@ public class MusicBrowserService extends MediaBrowserService implements Notifica TLRPC.Chat chat = chats.get(-did); if (chat != null) { builder.setTitle(chat.title); - if (chat.photo != null && chat.photo.photo_small instanceof TLRPC.TL_fileLocation) { + if (chat.photo != null && !(chat.photo.photo_small instanceof TLRPC.TL_fileLocationUnavailable)) { avatar = chat.photo.photo_small; } } else { @@ -470,7 +470,7 @@ public class MusicBrowserService extends MediaBrowserService implements Notifica long position = PlaybackState.PLAYBACK_POSITION_UNKNOWN; MessageObject playingMessageObject = MediaController.getInstance().getPlayingMessageObject(); if (playingMessageObject != null) { - position = playingMessageObject.audioProgressSec * 1000; + position = playingMessageObject.audioProgressSec * 1000L; } PlaybackState.Builder stateBuilder = new PlaybackState.Builder().setActions(getAvailableActions()); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java b/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java index dd60e202b..ddf50af7d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java @@ -30,7 +30,7 @@ import android.media.session.MediaSession; import android.media.session.PlaybackState; import android.os.Build; import android.os.IBinder; -import android.support.v4.app.NotificationCompat; +import androidx.core.app.NotificationCompat; import android.text.TextUtils; import android.view.View; import android.widget.RemoteViews; @@ -49,6 +49,7 @@ public class MusicPlayerService extends Service implements NotificationCenter.No public static final String NOTIFY_PAUSE = "org.telegram.android.musicplayer.pause"; public static final String NOTIFY_PLAY = "org.telegram.android.musicplayer.play"; public static final String NOTIFY_NEXT = "org.telegram.android.musicplayer.next"; + public static final String NOTIFY_SEEK = "org.telegram.android.musicplayer.seek"; private static final int ID_NOTIFICATION = 5; @@ -128,6 +129,15 @@ public class MusicPlayerService extends Service implements NotificationCenter.No MediaController.getInstance().playPreviousMessage(); } + @Override + public void onSeekTo(long pos) { + MessageObject object = MediaController.getInstance().getPlayingMessageObject(); + if (object != null) { + MediaController.getInstance().seekToProgress(object, pos / 1000 / (float) object.getDuration()); + updatePlaybackState(pos); + } + } + @Override public void onStop() { //stopSelf(); @@ -214,6 +224,7 @@ public class MusicPlayerService extends Service implements NotificationCenter.No String artworkUrl = messageObject.getArtworkUrl(true); String artworkUrlBig = messageObject.getArtworkUrl(false); + long duration = messageObject.getDuration() * 1000; Bitmap albumArt = audioInfo != null ? audioInfo.getSmallCover() : null; Bitmap fullAlbumArt = audioInfo != null ? audioInfo.getCover() : null; @@ -239,6 +250,7 @@ public class MusicPlayerService extends Service implements NotificationCenter.No PendingIntent pendingStop = PendingIntent.getService(getApplicationContext(), 0, new Intent(this, getClass()).setAction(getPackageName() + ".STOP_PLAYER"), PendingIntent.FLAG_CANCEL_CURRENT); PendingIntent pendingPlaypause = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(isPlaying ? NOTIFY_PAUSE : NOTIFY_PLAY).setComponent(new ComponentName(this, MusicPlayerReceiver.class)), PendingIntent.FLAG_CANCEL_CURRENT); PendingIntent pendingNext = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_NEXT).setComponent(new ComponentName(this, MusicPlayerReceiver.class)), PendingIntent.FLAG_CANCEL_CURRENT); + PendingIntent pendingSeek = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_SEEK).setComponent(new ComponentName(this, MusicPlayerReceiver.class)), PendingIntent.FLAG_CANCEL_CURRENT); Notification.Builder bldr = new Notification.Builder(this); bldr.setSmallIcon(R.drawable.player) @@ -273,7 +285,7 @@ public class MusicPlayerService extends Service implements NotificationCenter.No playbackState.setState(isPlaying ? PlaybackState.STATE_PLAYING : PlaybackState.STATE_PAUSED, MediaController.getInstance().getPlayingMessageObject().audioProgressSec * 1000L, isPlaying ? 1 : 0) - .setActions(PlaybackState.ACTION_PLAY_PAUSE | PlaybackState.ACTION_PLAY | PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_SKIP_TO_PREVIOUS | PlaybackState.ACTION_SKIP_TO_NEXT); + .setActions(PlaybackState.ACTION_PLAY_PAUSE | PlaybackState.ACTION_PLAY | PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_SEEK_TO | PlaybackState.ACTION_SKIP_TO_PREVIOUS | PlaybackState.ACTION_SKIP_TO_NEXT); bldr.addAction(new Notification.Action.Builder(R.drawable.ic_action_previous, "", pendingPrev).build()) .addAction(new Notification.Action.Builder(isPlaying ? R.drawable.ic_action_pause : R.drawable.ic_action_play, "", pendingPlaypause).build()) .addAction(new Notification.Action.Builder(R.drawable.ic_action_next, "", pendingNext).build()); @@ -283,6 +295,7 @@ public class MusicPlayerService extends Service implements NotificationCenter.No MediaMetadata.Builder meta = new MediaMetadata.Builder() .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, fullAlbumArt) .putString(MediaMetadata.METADATA_KEY_ALBUM_ARTIST, authorName) + .putLong(MediaMetadata.METADATA_KEY_DURATION, duration) .putString(MediaMetadata.METADATA_KEY_TITLE, songName) .putString(MediaMetadata.METADATA_KEY_ALBUM, audioInfo != null ? audioInfo.getAlbum() : null); @@ -445,6 +458,22 @@ public class MusicPlayerService extends Service implements NotificationCenter.No } } + private void updatePlaybackState(long seekTo) { + if (Build.VERSION.SDK_INT < 21) { + return; + } + boolean isPlaying = !MediaController.getInstance().isMessagePaused(); + if (MediaController.getInstance().isDownloadingCurrentMessage()) { + playbackState.setState(PlaybackState.STATE_BUFFERING, 0, 1).setActions(0); + } else { + playbackState.setState(isPlaying ? PlaybackState.STATE_PLAYING : PlaybackState.STATE_PAUSED, + seekTo, + isPlaying ? 1 : 0) + .setActions(PlaybackState.ACTION_PLAY_PAUSE | PlaybackState.ACTION_PLAY | PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_SEEK_TO | PlaybackState.ACTION_SKIP_TO_PREVIOUS | PlaybackState.ACTION_SKIP_TO_NEXT); + } + mediaSession.setPlaybackState(playbackState.build()); + } + public void setListeners(RemoteViews view) { PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_PREVIOUS), PendingIntent.FLAG_UPDATE_CURRENT); view.setOnClickPendingIntent(R.id.player_previous, pendingIntent); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java index fdec7152d..1997cfc0d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java @@ -8,7 +8,7 @@ package org.telegram.messenger; -import android.support.annotation.UiThread; +import androidx.annotation.UiThread; import android.util.SparseArray; import java.util.ArrayList; @@ -42,6 +42,7 @@ public class NotificationCenter { public static final int messagesReadEncrypted = totalEvents++; public static final int encryptedChatCreated = totalEvents++; public static final int dialogPhotosLoaded = totalEvents++; + public static final int folderBecomeEmpty = totalEvents++; public static final int removeAllMessagesFromDialog = totalEvents++; public static final int notificationsSettingsUpdated = totalEvents++; public static final int blockedUsersDidLoad = totalEvents++; @@ -132,6 +133,8 @@ public class NotificationCenter { public static final int needDeleteDialog = totalEvents++; + public static final int newEmojiSuggestionsAvailable = totalEvents++; + //global public static final int pushMessagesUpdated = totalEvents++; public static final int stopEncodingService = totalEvents++; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationImageProvider.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationImageProvider.java index ad47edd42..950e93895 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationImageProvider.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationImageProvider.java @@ -6,8 +6,8 @@ import android.content.UriMatcher; import android.database.Cursor; import android.net.Uri; import android.os.ParcelFileDescriptor; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.text.TextUtils; import java.io.File; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java index 3656f5c65..a03f177b4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java @@ -39,12 +39,12 @@ import android.os.Build; import android.os.PowerManager; import android.os.SystemClock; import android.provider.Settings; -import android.support.v4.app.NotificationCompat; -import android.support.v4.app.NotificationManagerCompat; -import android.support.v4.app.Person; -import android.support.v4.app.RemoteInput; -import android.support.v4.content.FileProvider; -import android.support.v4.graphics.drawable.IconCompat; +import androidx.core.app.NotificationCompat; +import androidx.core.app.NotificationManagerCompat; +import androidx.core.app.Person; +import androidx.core.app.RemoteInput; +import androidx.core.content.FileProvider; +import androidx.core.graphics.drawable.IconCompat; import android.text.TextUtils; import android.util.LongSparseArray; import android.util.SparseArray; @@ -128,7 +128,7 @@ public class NotificationsController { } private int currentAccount; - private static volatile NotificationsController Instance[] = new NotificationsController[UserConfig.MAX_ACCOUNT_COUNT]; + private static volatile NotificationsController[] Instance = new NotificationsController[UserConfig.MAX_ACCOUNT_COUNT]; public static NotificationsController getInstance(int num) { NotificationsController localInstance = Instance[num]; @@ -592,6 +592,7 @@ public class NotificationsController { final ArrayList popupArrayAdd = new ArrayList<>(0); notificationsQueue.postRunnable(() -> { boolean added = false; + boolean edited = false; LongSparseArray settingsCache = new LongSparseArray<>(); SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); @@ -600,6 +601,9 @@ public class NotificationsController { for (int a = 0; a < messageObjects.size(); a++) { MessageObject messageObject = messageObjects.get(a); + if (messageObject.messageOwner != null && messageObject.messageOwner.silent && (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionContactSignUp || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserJoined)) { + continue; + } long mid = messageObject.getId(); long random_id = messageObject.isFcmMessage() ? messageObject.messageOwner.random_id : 0; long dialog_id = messageObject.getDialogId(); @@ -627,9 +631,15 @@ public class NotificationsController { pushMessages.set(idxOld, messageObject); popup = addToPopupMessages(popupArrayAdd, messageObject, lower_id, dialog_id, isChannel, preferences); } + if (isFcm && (edited = messageObject.localEdit)) { + MessagesStorage.getInstance(currentAccount).putPushMessage(messageObject); + } } continue; } + if (edited) { + continue; + } if (isFcm) { MessagesStorage.getInstance(currentAccount).putPushMessage(messageObject); } @@ -652,7 +662,6 @@ public class NotificationsController { } added = true; - boolean isChat = lower_id < 0; int index = settingsCache.indexOfKey(dialog_id); boolean value; @@ -708,48 +717,53 @@ public class NotificationsController { } }); } - if (added && isFcm) { - long dialog_id = messageObjects.get(0).getDialogId(); - int old_unread_count = total_unread_count; - - int notifyOverride = getNotifyOverride(preferences, dialog_id); - boolean canAddValue; - if (notifyOverride == -1) { - canAddValue = isGlobalNotificationsEnabled(dialog_id); - } else { - canAddValue = notifyOverride != 2; - } - - Integer currentCount = pushDialogs.get(dialog_id); - Integer newCount = currentCount != null ? currentCount + 1 : 1; - - if (notifyCheck && !canAddValue) { - Integer override = pushDialogsOverrideMention.get(dialog_id); - if (override != null && override != 0) { - canAddValue = true; - newCount = override; - } - } - - if (canAddValue) { - if (currentCount != null) { - total_unread_count -= currentCount; - } - total_unread_count += newCount; - pushDialogs.put(dialog_id, newCount); - } - if (old_unread_count != total_unread_count) { + if (isFcm) { + if (edited) { delayedPushMessages.clear(); showOrUpdateNotification(notifyCheck); - final int pushDialogsCount = pushDialogs.size(); - AndroidUtilities.runOnUIThread(() -> { - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.notificationsCountUpdated, currentAccount); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsUnreadCounterChanged, pushDialogsCount); - }); - } - notifyCheck = false; - if (showBadgeNumber) { - setBadge(getTotalAllUnreadCount()); + } else if (added) { + long dialog_id = messageObjects.get(0).getDialogId(); + int old_unread_count = total_unread_count; + + int notifyOverride = getNotifyOverride(preferences, dialog_id); + boolean canAddValue; + if (notifyOverride == -1) { + canAddValue = isGlobalNotificationsEnabled(dialog_id); + } else { + canAddValue = notifyOverride != 2; + } + + Integer currentCount = pushDialogs.get(dialog_id); + Integer newCount = currentCount != null ? currentCount + 1 : 1; + + if (notifyCheck && !canAddValue) { + Integer override = pushDialogsOverrideMention.get(dialog_id); + if (override != null && override != 0) { + canAddValue = true; + newCount = override; + } + } + + if (canAddValue) { + if (currentCount != null) { + total_unread_count -= currentCount; + } + total_unread_count += newCount; + pushDialogs.put(dialog_id, newCount); + } + if (old_unread_count != total_unread_count) { + delayedPushMessages.clear(); + showOrUpdateNotification(notifyCheck); + final int pushDialogsCount = pushDialogs.size(); + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.notificationsCountUpdated, currentAccount); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsUnreadCounterChanged, pushDialogsCount); + }); + } + notifyCheck = false; + if (showBadgeNumber) { + setBadge(getTotalAllUnreadCount()); + } } } if (countDownLatch != null) { @@ -872,6 +886,9 @@ public class NotificationsController { if (messages != null) { for (int a = 0; a < messages.size(); a++) { TLRPC.Message message = messages.get(a); + if (message != null && message.silent && (message.action instanceof TLRPC.TL_messageActionContactSignUp || message.action instanceof TLRPC.TL_messageActionUserJoined)) { + continue; + } long mid = message.id; if (message.to_id.channel_id != 0) { mid |= ((long) message.to_id.channel_id) << 32; @@ -1027,8 +1044,8 @@ public class NotificationsController { if (controller.showBadgeMessages) { if (controller.showBadgeMuted) { try { - for (int i = 0, N = MessagesController.getInstance(a).dialogs.size(); i < N; i++) { - TLRPC.TL_dialog dialog = MessagesController.getInstance(a).dialogs.get(i); + for (int i = 0, N = MessagesController.getInstance(a).allDialogs.size(); i < N; i++) { + TLRPC.Dialog dialog = MessagesController.getInstance(a).allDialogs.get(i); if (dialog.unread_count != 0) { count += dialog.unread_count; } @@ -1042,8 +1059,8 @@ public class NotificationsController { } else { if (controller.showBadgeMuted) { try { - for (int i = 0, N = MessagesController.getInstance(a).dialogs.size(); i < N; i++) { - TLRPC.TL_dialog dialog = MessagesController.getInstance(a).dialogs.get(i); + for (int i = 0, N = MessagesController.getInstance(a).allDialogs.size(); i < N; i++) { + TLRPC.Dialog dialog = MessagesController.getInstance(a).allDialogs.get(i); if (dialog.unread_count != 0) { count++; } @@ -1073,7 +1090,7 @@ public class NotificationsController { NotificationBadge.applyCount(count); } - private String getShortStringForMessage(MessageObject messageObject, String[] userName, boolean preview[]) { + private String getShortStringForMessage(MessageObject messageObject, String[] userName, boolean[] preview) { if (AndroidUtilities.needShowPasscode(false) || SharedConfig.isWaitingForPasscodeEnter) { return LocaleController.getString("YouHaveNewMessage", R.string.YouHaveNewMessage); } @@ -1313,9 +1330,11 @@ public class NotificationsController { } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { return LocaleController.formatString("NotificationActionPinnedGeoLive", R.string.NotificationActionPinnedGeoLive, name, chat.title); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { - return LocaleController.formatString("NotificationActionPinnedContact", R.string.NotificationActionPinnedContact, name, chat.title); + TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) object.messageOwner.media; + return LocaleController.formatString("NotificationActionPinnedContact2", R.string.NotificationActionPinnedContact2, name, chat.title, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { - return LocaleController.formatString("NotificationActionPinnedPoll", R.string.NotificationActionPinnedPoll, name, chat.title); + TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; + return LocaleController.formatString("NotificationActionPinnedPoll2", R.string.NotificationActionPinnedPoll2, name, chat.title, mediaPoll.poll.question); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83D\uDDBC " + object.messageOwner.message; @@ -1379,9 +1398,11 @@ public class NotificationsController { } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { return LocaleController.formatString("NotificationActionPinnedGeoLiveChannel", R.string.NotificationActionPinnedGeoLiveChannel, chat.title); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { - return LocaleController.formatString("NotificationActionPinnedContactChannel", R.string.NotificationActionPinnedContactChannel, chat.title); + TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) object.messageOwner.media; + return LocaleController.formatString("NotificationActionPinnedContactChannel2", R.string.NotificationActionPinnedContactChannel2, chat.title, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { - return LocaleController.formatString("NotificationActionPinnedPollChannel", R.string.NotificationActionPinnedPollChannel, chat.title); + TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; + return LocaleController.formatString("NotificationActionPinnedPollChannel2", R.string.NotificationActionPinnedPollChannel2, chat.title, mediaPoll.poll.question); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83D\uDDBC " + object.messageOwner.message; @@ -1475,7 +1496,7 @@ public class NotificationsController { return null; } - private String getStringForMessage(MessageObject messageObject, boolean shortMessage, boolean text[], boolean preview[]) { + private String getStringForMessage(MessageObject messageObject, boolean shortMessage, boolean[] text, boolean[] preview) { if (AndroidUtilities.needShowPasscode(false) || SharedConfig.isWaitingForPasscodeEnter) { return LocaleController.getString("YouHaveNewMessage", R.string.YouHaveNewMessage); } @@ -1618,9 +1639,11 @@ public class NotificationsController { } else if (messageObject.isMusic()) { msg = LocaleController.formatString("NotificationMessageMusic", R.string.NotificationMessageMusic, name); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { - msg = LocaleController.formatString("NotificationMessageContact", R.string.NotificationMessageContact, name); + TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) messageObject.messageOwner.media; + msg = LocaleController.formatString("NotificationMessageContact2", R.string.NotificationMessageContact2, name, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { - msg = LocaleController.formatString("NotificationMessagePoll", R.string.NotificationMessagePoll, name); + TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) messageObject.messageOwner.media; + msg = LocaleController.formatString("NotificationMessagePoll2", R.string.NotificationMessagePoll2, name, mediaPoll.poll.question); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { msg = LocaleController.formatString("NotificationMessageMap", R.string.NotificationMessageMap, name); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { @@ -1779,9 +1802,11 @@ public class NotificationsController { } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { msg = LocaleController.formatString("NotificationActionPinnedGeoLive", R.string.NotificationActionPinnedGeoLive, name, chat.title); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { - msg = LocaleController.formatString("NotificationActionPinnedContact", R.string.NotificationActionPinnedContact, name, chat.title); + TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) messageObject.messageOwner.media; + msg = LocaleController.formatString("NotificationActionPinnedContact2", R.string.NotificationActionPinnedContact2, name, chat.title, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { - msg = LocaleController.formatString("NotificationActionPinnedPoll", R.string.NotificationActionPinnedPoll, name, chat.title); + TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; + msg = LocaleController.formatString("NotificationActionPinnedPoll2", R.string.NotificationActionPinnedPoll2, name, chat.title, mediaPoll.poll.question); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83D\uDDBC " + object.messageOwner.message; @@ -1845,9 +1870,11 @@ public class NotificationsController { } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { msg = LocaleController.formatString("NotificationActionPinnedGeoLiveChannel", R.string.NotificationActionPinnedGeoLiveChannel, chat.title); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { - msg = LocaleController.formatString("NotificationActionPinnedContactChannel", R.string.NotificationActionPinnedContactChannel, chat.title); + TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) messageObject.messageOwner.media; + msg = LocaleController.formatString("NotificationActionPinnedContactChannel2", R.string.NotificationActionPinnedContactChannel2, chat.title, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { - msg = LocaleController.formatString("NotificationActionPinnedPollChannel", R.string.NotificationActionPinnedPollChannel, chat.title); + TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; + msg = LocaleController.formatString("NotificationActionPinnedPollChannel2", R.string.NotificationActionPinnedPollChannel2, chat.title, mediaPoll.poll.question); } else if (object.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) { if (Build.VERSION.SDK_INT >= 19 && !TextUtils.isEmpty(object.messageOwner.message)) { String message = "\uD83D\uDDBC " + object.messageOwner.message; @@ -1900,9 +1927,11 @@ public class NotificationsController { } else if (messageObject.isMusic()) { msg = LocaleController.formatString("ChannelMessageMusic", R.string.ChannelMessageMusic, name); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { - msg = LocaleController.formatString("ChannelMessageContact", R.string.ChannelMessageContact, name); + TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) messageObject.messageOwner.media; + msg = LocaleController.formatString("ChannelMessageContact2", R.string.ChannelMessageContact2, name, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { - msg = LocaleController.formatString("ChannelMessagePoll", R.string.ChannelMessagePoll, name); + TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) messageObject.messageOwner.media; + msg = LocaleController.formatString("ChannelMessagePoll2", R.string.ChannelMessagePoll2, name, mediaPoll.poll.question); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { msg = LocaleController.formatString("ChannelMessageMap", R.string.ChannelMessageMap, name); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { @@ -1957,9 +1986,11 @@ public class NotificationsController { } else if (messageObject.isMusic()) { msg = LocaleController.formatString("NotificationMessageGroupMusic", R.string.NotificationMessageGroupMusic, name, chat.title); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaContact) { - msg = LocaleController.formatString("NotificationMessageGroupContact", R.string.NotificationMessageGroupContact, name, chat.title); + TLRPC.TL_messageMediaContact mediaContact = (TLRPC.TL_messageMediaContact) messageObject.messageOwner.media; + msg = LocaleController.formatString("NotificationMessageGroupContact2", R.string.NotificationMessageGroupContact2, name, chat.title, ContactsController.formatName(mediaContact.first_name, mediaContact.last_name)); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { - msg = LocaleController.formatString("NotificationMessageGroupPoll", R.string.NotificationMessageGroupPoll, name, chat.title); + TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) messageObject.messageOwner.media; + msg = LocaleController.formatString("NotificationMessageGroupPoll2", R.string.NotificationMessageGroupPoll2, name, chat.title, mediaPoll.poll.question); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { msg = LocaleController.formatString("NotificationMessageGroupGame", R.string.NotificationMessageGroupGame, name, chat.title, messageObject.messageOwner.media.game.title); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { @@ -2037,6 +2068,21 @@ public class NotificationsController { return notifyOverride; } + public void showNotifications() { + notificationsQueue.postRunnable(() -> showOrUpdateNotification(false)); + } + + public void hideNotifications() { + notificationsQueue.postRunnable(() -> { + notificationManager.cancel(notificationId); + lastWearNotifiedMessageId.clear(); + for (int a = 0; a < wearNotificationsIds.size(); a++) { + notificationManager.cancel(wearNotificationsIds.valueAt(a)); + } + wearNotificationsIds.clear(); + }); + } + private void dismissNotification() { try { notificationManager.cancel(notificationId); @@ -2053,7 +2099,7 @@ public class NotificationsController { JSONObject o = new JSONObject(); o.put("id", UserConfig.getInstance(currentAccount).getClientUserId()); o.put("cancel_all", true); - WearDataLayerListenerService.sendMessageToWatch("/notify", o.toString().getBytes("UTF-8"), "remote_notifications"); + WearDataLayerListenerService.sendMessageToWatch("/notify", o.toString().getBytes(), "remote_notifications"); } catch (JSONException ignore) { } } @@ -2297,7 +2343,7 @@ public class NotificationsController { } private void showOrUpdateNotification(boolean notifyAboutLast) { - if (!UserConfig.getInstance(currentAccount).isClientActivated() || pushMessages.isEmpty()) { + if (!UserConfig.getInstance(currentAccount).isClientActivated() || pushMessages.isEmpty() || !SharedConfig.showNotificationsForAllAccounts && currentAccount != UserConfig.selectedAccount) { dismissNotification(); return; } @@ -2385,7 +2431,6 @@ public class NotificationsController { String defaultPath = Settings.System.DEFAULT_NOTIFICATION_URI.getPath(); - // boolean inAppSounds = preferences.getBoolean("EnableInAppSounds", true); boolean inAppVibrate = preferences.getBoolean("EnableInAppVibrate", true); boolean inAppPreview = preferences.getBoolean("EnableInAppPreview", true); @@ -2474,9 +2519,9 @@ public class NotificationsController { FileLog.e(e); } } - // + Uri configSound = null; - long configVibrationPattern[] = null; + long[] configVibrationPattern = null; int configImportance = 0; if (Build.VERSION.SDK_INT >= 26) { if (needVibrate == 2) { @@ -2592,9 +2637,9 @@ public class NotificationsController { .setGroupSummary(true) .setShowWhen(true) .setWhen(((long) lastMessageObject.messageOwner.date) * 1000) - .setColor(0xff2ca5e0); + .setColor(0xff11acfa); - long vibrationPattern[] = null; + long[] vibrationPattern = null; int importance = 0; Uri sound = null; @@ -2608,7 +2653,7 @@ public class NotificationsController { boolean hasNewMessages = false; if (pushMessages.size() == 1) { MessageObject messageObject = pushMessages.get(0); - boolean text[] = new boolean[1]; + boolean[] text = new boolean[1]; String message = lastMessage = getStringForMessage(messageObject, false, text, null); silent = messageObject.messageOwner.silent ? 1 : 0; if (message == null) { @@ -2632,7 +2677,7 @@ public class NotificationsController { NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); inboxStyle.setBigContentTitle(name); int count = Math.min(10, pushMessages.size()); - boolean text[] = new boolean[1]; + boolean[] text = new boolean[1]; for (int i = 0; i < count; i++) { MessageObject messageObject = pushMessages.get(i); String message = getStringForMessage(messageObject, false, text, null); @@ -2683,8 +2728,8 @@ public class NotificationsController { mBuilder.setLargeIcon(bitmap); } } - } catch (Throwable e) { - //ignore + } catch (Throwable ignore) { + } } } @@ -2737,6 +2782,13 @@ public class NotificationsController { if (choosenSoundPath.equals(defaultPath)) { mBuilder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI, AudioManager.STREAM_NOTIFICATION); } else { + if (Build.VERSION.SDK_INT >= 24 && choosenSoundPath.startsWith("file://") && !AndroidUtilities.isInternalUri(Uri.parse(choosenSoundPath))) { + Uri uri = FileProvider.getUriForFile(ApplicationLoader.applicationContext, BuildConfig.APPLICATION_ID + ".provider", new File(choosenSoundPath.replace("file://", ""))); + ApplicationLoader.applicationContext.grantUriPermission("com.android.systemui", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); + mBuilder.setSound(uri, AudioManager.STREAM_NOTIFICATION); + } else { + mBuilder.setSound(Uri.parse(choosenSoundPath), AudioManager.STREAM_NOTIFICATION); + } mBuilder.setSound(Uri.parse(choosenSoundPath), AudioManager.STREAM_NOTIFICATION); } } @@ -2988,30 +3040,9 @@ public class NotificationsController { } } - NotificationCompat.CarExtender.UnreadConversation.Builder unreadConvBuilder = new NotificationCompat.CarExtender.UnreadConversation.Builder(name).setLatestTimestamp((long) max_date * 1000); - - Intent msgHeardIntent = new Intent(ApplicationLoader.applicationContext, AutoMessageHeardReceiver.class); - msgHeardIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - msgHeardIntent.setAction("org.telegram.messenger.ACTION_MESSAGE_HEARD"); - msgHeardIntent.putExtra("dialog_id", dialog_id); - msgHeardIntent.putExtra("max_id", max_id); - msgHeardIntent.putExtra("currentAccount", currentAccount); - PendingIntent msgHeardPendingIntent = PendingIntent.getBroadcast(ApplicationLoader.applicationContext, internalId, msgHeardIntent, PendingIntent.FLAG_UPDATE_CURRENT); - unreadConvBuilder.setReadPendingIntent(msgHeardPendingIntent); - NotificationCompat.Action wearReplyAction = null; if ((!isChannel || isSupergroup) && canReply && !SharedConfig.isWaitingForPasscodeEnter) { - Intent msgReplyIntent = new Intent(ApplicationLoader.applicationContext, AutoMessageReplyReceiver.class); - msgReplyIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - msgReplyIntent.setAction("org.telegram.messenger.ACTION_MESSAGE_REPLY"); - msgReplyIntent.putExtra("dialog_id", dialog_id); - msgReplyIntent.putExtra("max_id", max_id); - msgReplyIntent.putExtra("currentAccount", currentAccount); - PendingIntent msgReplyPendingIntent = PendingIntent.getBroadcast(ApplicationLoader.applicationContext, internalId, msgReplyIntent, PendingIntent.FLAG_UPDATE_CURRENT); - RemoteInput remoteInputAuto = new RemoteInput.Builder(EXTRA_VOICE_REPLY).setLabel(LocaleController.getString("Reply", R.string.Reply)).build(); - unreadConvBuilder.setReplyAction(msgReplyPendingIntent, remoteInputAuto); - Intent replyIntent = new Intent(ApplicationLoader.applicationContext, WearReplyReceiver.class); replyIntent.putExtra("dialog_id", dialog_id); replyIntent.putExtra("max_id", max_id); @@ -3024,24 +3055,35 @@ public class NotificationsController { } else { replyToString = LocaleController.formatString("ReplyToUser", R.string.ReplyToUser, name); } - wearReplyAction = new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon, replyToString, replyPendingIntent).setAllowGeneratedReplies(true).addRemoteInput(remoteInputWear).build(); + wearReplyAction = new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon, replyToString, replyPendingIntent) + .setAllowGeneratedReplies(true) + .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY) + .addRemoteInput(remoteInputWear) + .setShowsUserInterface(false) + .build(); } Integer count = pushDialogs.get(dialog_id); if (count == null) { count = 0; } - String conversationName = String.format("%1$s (%2$s)", name, LocaleController.formatPluralString("NewMessages", Math.max(count, messageObjects.size()))); - - NotificationCompat.MessagingStyle messagingStyle = new NotificationCompat.MessagingStyle(""); - messagingStyle.setConversationTitle(conversationName); - if (!isChannel && lowerId < 0) { - messagingStyle.setGroupConversation(true); + int n = Math.max(count, messageObjects.size()); + String conversationName; + if (n <= 1 || Build.VERSION.SDK_INT >= 28) { + conversationName = name; + } else { + conversationName = String.format("%1$s (%2$d)", name, n); } + NotificationCompat.MessagingStyle messagingStyle = new NotificationCompat.MessagingStyle(""); + if (Build.VERSION.SDK_INT < 28 || lowerId < 0 && !isChannel) { + messagingStyle.setConversationTitle(conversationName); + } + messagingStyle.setGroupConversation(Build.VERSION.SDK_INT < 28 || !isChannel && lowerId < 0); + StringBuilder text = new StringBuilder(); - String senderName[] = new String[1]; - boolean preview[] = new boolean[1]; + String[] senderName = new String[1]; + boolean[] preview = new boolean[1]; ArrayList rows = null; int rowsMid = 0; JSONArray serializedMsgs = null; @@ -3066,7 +3108,7 @@ public class NotificationsController { text.append(message); } - unreadConvBuilder.addMessage(message); + //unreadConvBuilder.addMessage(message); long uid; if (lowerId > 0) { @@ -3082,6 +3124,7 @@ public class NotificationsController { if (person == null) { Person.Builder personBuilder = new Person.Builder().setName(senderName[0] == null ? "" : senderName[0]); if (preview[0] && lowerId != 0 && Build.VERSION.SDK_INT >= 28) { + File avatar = null; if (lowerId > 0 || isChannel) { avatar = avatalFile; @@ -3098,27 +3141,7 @@ public class NotificationsController { avatar = FileLoader.getPathToAttach(sender.photo.photo_small, true); } } - if (avatar != null) { - try { - Bitmap bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(avatar), (decoder, info, src) -> decoder.setPostProcessor((canvas) -> { - Path path = new Path(); - path.setFillType(Path.FillType.INVERSE_EVEN_ODD); - int width = canvas.getWidth(); - int height = canvas.getHeight(); - path.addRoundRect(0, 0, width, height, width / 2, width / 2, Path.Direction.CW); - Paint paint = new Paint(); - paint.setAntiAlias(true); - paint.setColor(Color.TRANSPARENT); - paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); - canvas.drawPath(path, paint); - return PixelFormat.TRANSLUCENT; - })); - IconCompat icon = IconCompat.createWithBitmap(bitmap); - personBuilder.setIcon(icon); - } catch (Throwable ignore) { - - } - } + loadRoundAvatar(avatar, personBuilder); } person = personBuilder.build(); personCache.put(uid, person); @@ -3230,8 +3253,17 @@ public class NotificationsController { if (wearReplyAction != null) { wearableExtender.addAction(wearReplyAction); } + Intent msgHeardIntent = new Intent(ApplicationLoader.applicationContext, AutoMessageHeardReceiver.class); + msgHeardIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); + msgHeardIntent.setAction("org.telegram.messenger.ACTION_MESSAGE_HEARD"); + msgHeardIntent.putExtra("dialog_id", dialog_id); + msgHeardIntent.putExtra("max_id", max_id); + msgHeardIntent.putExtra("currentAccount", currentAccount); PendingIntent readPendingIntent = PendingIntent.getBroadcast(ApplicationLoader.applicationContext, internalId, msgHeardIntent, PendingIntent.FLAG_UPDATE_CURRENT); - NotificationCompat.Action readAction = new NotificationCompat.Action.Builder(R.drawable.menu_read, LocaleController.getString("MarkAsRead", R.string.MarkAsRead), readPendingIntent).build(); + NotificationCompat.Action readAction = new NotificationCompat.Action.Builder(R.drawable.menu_read, LocaleController.getString("MarkAsRead", R.string.MarkAsRead), readPendingIntent) + .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ) + .setShowsUserInterface(false) + .build(); String dismissalID; if (lowerId != 0) { @@ -3262,7 +3294,7 @@ public class NotificationsController { .setContentText(text.toString()) .setAutoCancel(true) .setNumber(messageObjects.size()) - .setColor(0xff2ca5e0) + .setColor(0xff11acfa) .setGroupSummary(false) .setWhen(date) .setShowWhen(true) @@ -3271,7 +3303,6 @@ public class NotificationsController { .setContentIntent(contentIntent) .extend(wearableExtender) .setSortKey("" + (Long.MAX_VALUE - date)) - .extend(new NotificationCompat.CarExtender().setUnreadConversation(unreadConvBuilder.build())) .setCategory(NotificationCompat.CATEGORY_MESSAGE); if (useSummaryNotification) { @@ -3380,12 +3411,37 @@ public class NotificationsController { JSONObject s = new JSONObject(); s.put("id", UserConfig.getInstance(currentAccount).getClientUserId()); s.put("n", serializedNotifications); - WearDataLayerListenerService.sendMessageToWatch("/notify", s.toString().getBytes("UTF-8"), "remote_notifications"); + WearDataLayerListenerService.sendMessageToWatch("/notify", s.toString().getBytes(), "remote_notifications"); } catch (Exception ignore) { } } } + @TargetApi(Build.VERSION_CODES.P) + private void loadRoundAvatar(File avatar, Person.Builder personBuilder) { + if (avatar != null) { + try { + Bitmap bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(avatar), (decoder, info, src) -> decoder.setPostProcessor((canvas) -> { + Path path = new Path(); + path.setFillType(Path.FillType.INVERSE_EVEN_ODD); + int width = canvas.getWidth(); + int height = canvas.getHeight(); + path.addRoundRect(0, 0, width, height, width / 2, width / 2, Path.Direction.CW); + Paint paint = new Paint(); + paint.setAntiAlias(true); + paint.setColor(Color.TRANSPARENT); + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); + canvas.drawPath(path, paint); + return PixelFormat.TRANSLUCENT; + })); + IconCompat icon = IconCompat.createWithBitmap(bitmap); + personBuilder.setIcon(icon); + } catch (Throwable ignore) { + + } + } + } + public void playOutChatSound() { if (!inChatSoundEnabled || MediaController.getInstance().isRecordingAudio()) { return; @@ -3432,6 +3488,58 @@ public class NotificationsController { }); } + public static final int SETTING_MUTE_HOUR = 0; + public static final int SETTING_MUTE_8_HOURS = 1; + public static final int SETTING_MUTE_2_DAYS = 2; + public static final int SETTING_MUTE_FOREVER = 3; + public static final int SETTING_MUTE_UNMUTE = 4; + + public void setDialogNotificationsSettings(long dialog_id, int setting) { + SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); + SharedPreferences.Editor editor = preferences.edit(); + TLRPC.Dialog dialog = MessagesController.getInstance(UserConfig.selectedAccount).dialogs_dict.get(dialog_id); + if (setting == SETTING_MUTE_UNMUTE) { + boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialog_id); + if (defaultEnabled) { + editor.remove("notify2_" + dialog_id); + } else { + editor.putInt("notify2_" + dialog_id, 0); + } + MessagesStorage.getInstance(currentAccount).setDialogFlags(dialog_id, 0); + if (dialog != null) { + dialog.notify_settings = new TLRPC.TL_peerNotifySettings(); + } + } else { + int untilTime = ConnectionsManager.getInstance(UserConfig.selectedAccount).getCurrentTime(); + if (setting == SETTING_MUTE_HOUR) { + untilTime += 60 * 60; + } else if (setting == SETTING_MUTE_8_HOURS) { + untilTime += 60 * 60 * 8; + } else if (setting == SETTING_MUTE_2_DAYS) { + untilTime += 60 * 60 * 48; + } else if (setting == SETTING_MUTE_FOREVER) { + untilTime = Integer.MAX_VALUE; + } + long flags; + if (setting == SETTING_MUTE_FOREVER) { + editor.putInt("notify2_" + dialog_id, 2); + flags = 1; + } else { + editor.putInt("notify2_" + dialog_id, 3); + editor.putInt("notifyuntil_" + dialog_id, untilTime); + flags = ((long) untilTime << 32) | 1; + } + NotificationsController.getInstance(UserConfig.selectedAccount).removeNotificationsForDialog(dialog_id); + MessagesStorage.getInstance(UserConfig.selectedAccount).setDialogFlags(dialog_id, flags); + if (dialog != null) { + dialog.notify_settings = new TLRPC.TL_peerNotifySettings(); + dialog.notify_settings.mute_until = untilTime; + } + } + editor.commit(); + updateServerNotificationsSettings(dialog_id); + } + public void updateServerNotificationsSettings(long dialog_id) { NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.notificationsSettingsUpdated); if ((int) dialog_id == 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java index 2fbb38a42..9bd30989b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java @@ -187,7 +187,7 @@ public class SecretChatHelper { user = usersDict.get(user_id); } newChat.user_id = user_id; - final TLRPC.TL_dialog dialog = new TLRPC.TL_dialog(); + final TLRPC.Dialog dialog = new TLRPC.TL_dialog(); dialog.id = dialog_id; dialog.unread_count = 0; dialog.top_message = 0; @@ -195,14 +195,14 @@ public class SecretChatHelper { MessagesController.getInstance(currentAccount).putEncryptedChat(newChat, false); AndroidUtilities.runOnUIThread(() -> { MessagesController.getInstance(currentAccount).dialogs_dict.put(dialog.id, dialog); - MessagesController.getInstance(currentAccount).dialogs.add(dialog); + MessagesController.getInstance(currentAccount).allDialogs.add(dialog); MessagesController.getInstance(currentAccount).sortDialogs(null); NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); }); MessagesStorage.getInstance(currentAccount).putEncryptedChat(newChat, user, dialog); acceptSecretChat(newChat); } else if (newChat instanceof TLRPC.TL_encryptedChat) { - if (existingChat != null && existingChat instanceof TLRPC.TL_encryptedChatWaiting && (existingChat.auth_key == null || existingChat.auth_key.length == 1)) { + if (existingChat instanceof TLRPC.TL_encryptedChatWaiting && (existingChat.auth_key == null || existingChat.auth_key.length == 1)) { newChat.a_or_b = existingChat.a_or_b; newChat.user_id = existingChat.user_id; processAcceptedSecretChat(newChat); @@ -482,7 +482,7 @@ public class SecretChatHelper { File cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName + ".jpg"); File cacheFile2 = FileLoader.getPathToAttach(size); cacheFile.renameTo(cacheFile2); - ImageLoader.getInstance().replaceImageInCache(fileName, fileName2, size.location, true); + ImageLoader.getInstance().replaceImageInCache(fileName, fileName2, ImageLocation.getForPhoto(size, newMsg.media.photo), true); ArrayList arr = new ArrayList<>(); arr.add(newMsg); MessagesStorage.getInstance(currentAccount).putMessages(arr, false, true, false, 0); @@ -1076,7 +1076,7 @@ public class SecretChatHelper { } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionFlushHistory) { final long did = ((long) chat.id) << 32; AndroidUtilities.runOnUIThread(() -> { - TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(did); + TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(did); if (dialog != null) { dialog.unread_count = 0; MessagesController.getInstance(currentAccount).dialogMessage.remove(dialog.id); @@ -1868,13 +1868,13 @@ public class SecretChatHelper { chat.seq_out = 1; chat.a_or_b = salt; MessagesController.getInstance(currentAccount).putEncryptedChat(chat, false); - TLRPC.TL_dialog dialog = new TLRPC.TL_dialog(); - dialog.id = ((long) chat.id) << 32; + TLRPC.Dialog dialog = new TLRPC.TL_dialog(); + dialog.id = DialogObject.makeSecretDialogId(chat.id); dialog.unread_count = 0; dialog.top_message = 0; dialog.last_message_date = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); MessagesController.getInstance(currentAccount).dialogs_dict.put(dialog.id, dialog); - MessagesController.getInstance(currentAccount).dialogs.add(dialog); + MessagesController.getInstance(currentAccount).allDialogs.add(dialog); MessagesController.getInstance(currentAccount).sortDialogs(null); MessagesStorage.getInstance(currentAccount).putEncryptedChat(chat, user, dialog); NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogsNeedReload); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index e6bf13056..a9faafdaa 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -25,8 +25,8 @@ import android.os.Build; import android.os.Bundle; import android.os.SystemClock; import android.provider.MediaStore; -import android.support.annotation.UiThread; -import android.support.v13.view.inputmethod.InputContentInfoCompat; +import androidx.annotation.UiThread; +import androidx.core.view.inputmethod.InputContentInfoCompat; import android.text.TextUtils; import android.util.Base64; import android.util.LongSparseArray; @@ -34,17 +34,6 @@ import android.util.SparseArray; import android.webkit.MimeTypeMap; import android.widget.Toast; -import com.coremedia.iso.IsoFile; -import com.coremedia.iso.boxes.Box; -import com.coremedia.iso.boxes.MediaBox; -import com.coremedia.iso.boxes.MediaHeaderBox; -import com.coremedia.iso.boxes.SampleSizeBox; -import com.coremedia.iso.boxes.TimeToSampleBox; -import com.coremedia.iso.boxes.TrackBox; -import com.coremedia.iso.boxes.TrackHeaderBox; -import com.googlecode.mp4parser.util.Matrix; -import com.googlecode.mp4parser.util.Path; - import org.telegram.messenger.audioinfo.AudioInfo; import org.telegram.messenger.support.SparseLongArray; import org.telegram.tgnet.ConnectionsManager; @@ -57,6 +46,7 @@ import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.PaymentFormActivity; import java.io.File; @@ -66,7 +56,6 @@ import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Locale; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; @@ -278,7 +267,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter public TLObject sendEncryptedRequest; public int type; public String originalPath; - public TLRPC.FileLocation location; + public TLRPC.PhotoSize photoSize; + public TLObject locationParent; public String httpLocation; public MessageObject obj; public TLRPC.EncryptedChat encryptedChat; @@ -287,7 +277,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter public TLRPC.InputMedia inputUploadMedia; - public ArrayList locations; + public ArrayList locations; public ArrayList httpLocations; public ArrayList videoEditedInfos; public ArrayList messageObjects; @@ -457,7 +447,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } else if (message.type == 1) { if (media.file == null) { media.file = file; - if (media.thumb == null && message.location != null) { + if (media.thumb == null && message.photoSize != null && message.photoSize.location != null) { performSendDelayedMessage(message); } else { performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject); @@ -470,7 +460,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } else if (message.type == 2) { if (media.file == null) { media.file = file; - if (media.thumb == null && message.location != null) { + if (media.thumb == null && message.photoSize != null && message.photoSize.location != null) { performSendDelayedMessage(message); } else { performSendMessageRequest(message.sendRequest, message.obj, message.originalPath, null, message.parentObject); @@ -489,9 +479,9 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter media.file = file; MessageObject messageObject = (MessageObject) message.extraHashMap.get(location + "_i"); int index = message.messageObjects.indexOf(messageObject); - message.location = (TLRPC.FileLocation) message.extraHashMap.get(location + "_t"); + message.photoSize = (TLRPC.PhotoSize) message.extraHashMap.get(location + "_t"); stopVideoService(message.messageObjects.get(index).messageOwner.attachPath); - if (media.thumb == null && message.location != null) { + if (media.thumb == null && message.photoSize != null) { message.performMediaUpload = true; performSendDelayedMessage(message, index); } else { @@ -519,7 +509,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter req.files.set(index, encryptedFile); if (inputEncryptedFile.id == 1) { MessageObject messageObject = (MessageObject) message.extraHashMap.get(location + "_i"); - message.location = (TLRPC.FileLocation) message.extraHashMap.get(location + "_t"); + message.photoSize = (TLRPC.PhotoSize) message.extraHashMap.get(location + "_t"); stopVideoService(message.messageObjects.get(index).messageOwner.attachPath); } decryptedMessage = req.messages.get(index); @@ -580,7 +570,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter DelayedMessage message = arr.get(a); if (message.type == 4) { int index = message.messageObjects.indexOf(messageObject); - message.location = (TLRPC.FileLocation) message.extraHashMap.get(messageObject.messageOwner.attachPath + "_t"); + message.photoSize = (TLRPC.PhotoSize) message.extraHashMap.get(messageObject.messageOwner.attachPath + "_t"); message.performMediaUpload = true; performSendDelayedMessage(message, index); arr.remove(a); @@ -707,7 +697,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter messages.add(messageObject.messageOwner); MessagesStorage.getInstance(currentAccount).putMessages(messages, false, true, false, 0); NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.updateMessageMedia, messageObject.messageOwner); - message.location = photo.sizes.get(photo.sizes.size() - 1).location; + message.photoSize = photo.sizes.get(photo.sizes.size() - 1); + message.locationParent = photo; message.httpLocation = null; if (message.type == 4) { message.performMediaUpload = true; @@ -745,7 +736,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter message.httpLocation = null; message.obj.messageOwner.attachPath = cacheFile.toString(); if (!document.thumbs.isEmpty()) { - message.location = document.thumbs.get(0).location; + message.photoSize = document.thumbs.get(0); + message.locationParent = document; } ArrayList messages = new ArrayList<>(); messages.add(messageObject.messageOwner); @@ -1226,6 +1218,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter newMsg.fwd_from.channel_id = msgObj.messageOwner.fwd_from.channel_id; newMsg.fwd_from.channel_post = msgObj.messageOwner.fwd_from.channel_post; newMsg.fwd_from.post_author = msgObj.messageOwner.fwd_from.post_author; + newMsg.fwd_from.from_name = msgObj.messageOwner.fwd_from.from_name; newMsg.flags = TLRPC.MESSAGE_FLAG_FWD; } else if (!forwardFromSaved) { //if (!toMyself || !msgObj.isOutOwner()) newMsg.fwd_from = new TLRPC.TL_messageFwdHeader(); @@ -1671,7 +1664,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter if (path != null && path.length() > 0 && path.startsWith("http")) { delayedMessage.httpLocation = path; } else { - delayedMessage.location = photo.sizes.get(photo.sizes.size() - 1).location; + delayedMessage.photoSize = photo.sizes.get(photo.sizes.size() - 1); + delayedMessage.locationParent = photo; } } else if (type == 3) { TLRPC.TL_inputMediaUploadedDocument uploadedDocument = new TLRPC.TL_inputMediaUploadedDocument(); @@ -1706,7 +1700,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter delayedMessage.inputUploadMedia = uploadedDocument; delayedMessage.performMediaUpload = performMediaUpload; if (!document.thumbs.isEmpty()) { - delayedMessage.location = document.thumbs.get(0).location; + delayedMessage.photoSize = document.thumbs.get(0); + delayedMessage.locationParent = document; } delayedMessage.videoEditedInfo = videoEditedInfo; } else if (type == 7) { @@ -1747,7 +1742,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter delayedMessage.type = 2; delayedMessage.obj = messageObject; if (!document.thumbs.isEmpty()) { - delayedMessage.location = document.thumbs.get(0).location; + delayedMessage.photoSize = document.thumbs.get(0); + delayedMessage.locationParent = document; } delayedMessage.parentObject = parentObject; delayedMessage.inputUploadMedia = uploadedDocument; @@ -2616,7 +2612,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter delayedMessage.encryptedChat = encryptedChat; } delayedMessage.performMediaUpload = false; - delayedMessage.location = null; + delayedMessage.photoSize = null; delayedMessage.videoEditedInfo = null; delayedMessage.httpLocation = null; if (isFinalGroupMedia) { @@ -2768,7 +2764,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter if (path != null && path.length() > 0 && path.startsWith("http")) { delayedMessage.httpLocation = path; } else { - delayedMessage.location = photo.sizes.get(photo.sizes.size() - 1).location; + delayedMessage.photoSize = photo.sizes.get(photo.sizes.size() - 1); + delayedMessage.locationParent = photo; } } else if (type == 3) { TLRPC.TL_inputMediaUploadedDocument uploadedDocument = new TLRPC.TL_inputMediaUploadedDocument(); @@ -2808,7 +2805,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter delayedMessage.inputUploadMedia = uploadedDocument; delayedMessage.performMediaUpload = performMediaUpload; if (!document.thumbs.isEmpty()) { - delayedMessage.location = document.thumbs.get(0).location; + delayedMessage.photoSize = document.thumbs.get(0); + delayedMessage.locationParent = document; } delayedMessage.videoEditedInfo = videoEditedInfo; } else if (type == 6) { @@ -2870,7 +2868,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter delayedMessage.type = 2; delayedMessage.obj = newMsgObj; if (!document.thumbs.isEmpty()) { - delayedMessage.location = document.thumbs.get(0).location; + delayedMessage.photoSize = document.thumbs.get(0); + delayedMessage.locationParent = document; } delayedMessage.parentObject = parentObject; delayedMessage.inputUploadMedia = uploadedMedia; @@ -2948,7 +2947,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } delayedMessage.messageObjects.add(newMsgObj); delayedMessage.parentObjects.add(parentObject); - delayedMessage.locations.add(delayedMessage.location); + delayedMessage.locations.add(delayedMessage.photoSize); delayedMessage.videoEditedInfos.add(delayedMessage.videoEditedInfo); delayedMessage.httpLocations.add(delayedMessage.httpLocation); delayedMessage.inputMedias.add(delayedMessage.inputUploadMedia); @@ -3094,7 +3093,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter if (!TextUtils.isEmpty(path) && path.startsWith("http")) { delayedMessage.httpLocation = path; } else { - delayedMessage.location = photo.sizes.get(photo.sizes.size() - 1).location; + delayedMessage.photoSize = photo.sizes.get(photo.sizes.size() - 1); + delayedMessage.locationParent = photo; } if (groupId == 0) { performSendDelayedMessage(delayedMessage); @@ -3318,6 +3318,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter TLRPC.TL_messages_sendInlineBotResult reqSend = new TLRPC.TL_messages_sendInlineBotResult(); reqSend.peer = sendToPeer; reqSend.random_id = newMsg.random_id; + reqSend.hide_via = !params.containsKey("bot"); if (newMsg.reply_to_msg_id != 0) { reqSend.flags |= 1; reqSend.reply_to_msg_id = newMsg.reply_to_msg_id; @@ -3383,20 +3384,20 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter ImageLoader.getInstance().loadHttpFile(message.httpLocation, "file", currentAccount); } else { if (message.sendRequest != null) { - String location = FileLoader.getPathToAttach(message.location).toString(); + String location = FileLoader.getPathToAttach(message.photoSize).toString(); putToDelayedMessages(location, message); FileLoader.getInstance(currentAccount).uploadFile(location, false, true, ConnectionsManager.FileTypePhoto); } else { - String location = FileLoader.getPathToAttach(message.location).toString(); - if (message.sendEncryptedRequest != null && message.location.dc_id != 0) { + String location = FileLoader.getPathToAttach(message.photoSize).toString(); + if (message.sendEncryptedRequest != null && message.photoSize.location.dc_id != 0) { File file = new File(location); if (!file.exists()) { - location = FileLoader.getPathToAttach(message.location, true).toString(); + location = FileLoader.getPathToAttach(message.photoSize, true).toString(); file = new File(location); } if (!file.exists()) { - putToDelayedMessages(FileLoader.getAttachFileName(message.location), message); - FileLoader.getInstance(currentAccount).loadFile(message.location, message.parentObject, "jpg", 0, 2, 0); + putToDelayedMessages(FileLoader.getAttachFileName(message.photoSize), message); + FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForObject(message.photoSize, message.locationParent), message.parentObject, "jpg", 2, 0); return; } } @@ -3458,7 +3459,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter FileLoader.getInstance(currentAccount).uploadFile(location, false, false, ConnectionsManager.FileTypeVideo); } } else { - String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.location.volume_id + "_" + message.location.local_id + ".jpg"; + String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.photoSize.location.volume_id + "_" + message.photoSize.location.local_id + ".jpg"; putToDelayedMessages(location, message); FileLoader.getInstance(currentAccount).uploadFile(location, false, true, ConnectionsManager.FileTypePhoto); } @@ -3502,8 +3503,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter String location = message.obj.messageOwner.attachPath; putToDelayedMessages(location, message); FileLoader.getInstance(currentAccount).uploadFile(location, message.sendRequest == null, false, ConnectionsManager.FileTypeFile); - } else if (media.thumb == null && message.location != null) { - String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.location.volume_id + "_" + message.location.local_id + ".jpg"; + } else if (media.thumb == null && message.photoSize != null) { + String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.photoSize.location.volume_id + "_" + message.photoSize.location.local_id + ".jpg"; putToDelayedMessages(location, message); FileLoader.getInstance(currentAccount).uploadFile(location, false, true, ConnectionsManager.FileTypePhoto); } @@ -3543,8 +3544,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter putToDelayedMessages(location, message); message.extraHashMap.put(messageObject, location); message.extraHashMap.put(location + "_i", messageObject); - if (message.location != null) { - message.extraHashMap.put(location + "_t", message.location); + if (message.photoSize != null) { + message.extraHashMap.put(location + "_t", message.photoSize); } MediaController.getInstance().scheduleVideoConvert(messageObject); } else { @@ -3561,8 +3562,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter message.extraHashMap.put(messageObject, documentLocation); message.extraHashMap.put(documentLocation, media); message.extraHashMap.put(documentLocation + "_i", messageObject); - if (message.location != null) { - message.extraHashMap.put(documentLocation + "_t", message.location); + if (message.photoSize != null) { + message.extraHashMap.put(documentLocation + "_t", message.photoSize); } if (messageObject.videoEditedInfo != null && messageObject.videoEditedInfo.needConvert()) { FileLoader.getInstance(currentAccount).uploadFile(documentLocation, false, false, document.size, ConnectionsManager.FileTypeVideo); @@ -3570,7 +3571,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter FileLoader.getInstance(currentAccount).uploadFile(documentLocation, false, false, ConnectionsManager.FileTypeVideo); } } else { - String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.location.volume_id + "_" + message.location.local_id + ".jpg"; + String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.photoSize.location.volume_id + "_" + message.photoSize.location.local_id + ".jpg"; putToDelayedMessages(location, message); message.extraHashMap.put(location + "_o", documentLocation); message.extraHashMap.put(messageObject, location); @@ -3583,8 +3584,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter message.extraHashMap.put(messageObject, documentLocation); message.extraHashMap.put(documentLocation, request.files.get(index)); message.extraHashMap.put(documentLocation + "_i", messageObject); - if (message.location != null) { - message.extraHashMap.put(documentLocation + "_t", message.location); + if (message.photoSize != null) { + message.extraHashMap.put(documentLocation + "_t", message.photoSize); } if (messageObject.videoEditedInfo != null && messageObject.videoEditedInfo.needConvert()) { FileLoader.getInstance(currentAccount).uploadFile(documentLocation, true, false, document.size, ConnectionsManager.FileTypeVideo); @@ -3594,7 +3595,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } } message.videoEditedInfo = null; - message.location = null; + message.photoSize = null; } else { if (message.httpLocation != null) { putToDelayedMessages(message.httpLocation, message); @@ -3611,12 +3612,12 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter TLRPC.TL_messages_sendEncryptedMultiMedia request = (TLRPC.TL_messages_sendEncryptedMultiMedia) message.sendEncryptedRequest; inputMedia = request.files.get(index); } - String location = FileLoader.getPathToAttach(message.location).toString(); + String location = FileLoader.getPathToAttach(message.photoSize).toString(); putToDelayedMessages(location, message); message.extraHashMap.put(location, inputMedia); message.extraHashMap.put(messageObject, location); FileLoader.getInstance(currentAccount).uploadFile(location, message.sendEncryptedRequest != null, true, ConnectionsManager.FileTypePhoto); - message.location = null; + message.photoSize = null; } } message.performMediaUpload = false; @@ -3793,7 +3794,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } delayedMessage.videoEditedInfo = delayedMessage.videoEditedInfos.get(a); delayedMessage.httpLocation = delayedMessage.httpLocations.get(a); - delayedMessage.location = delayedMessage.locations.get(a); + delayedMessage.photoSize = delayedMessage.locations.get(a); delayedMessage.performMediaUpload = true; performSendDelayedMessage(delayedMessage, a); } @@ -4169,6 +4170,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter if (newMsg.media != null) { TLRPC.PhotoSize strippedOld = null; TLRPC.PhotoSize strippedNew = null; + TLObject photoObject = null; if (newMsg.media.photo != null) { strippedOld = FileLoader.getClosestPhotoSizeWithSize(newMsg.media.photo.sizes, 40); if (sentMessage != null && sentMessage.media != null && sentMessage.media.photo != null) { @@ -4176,6 +4178,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } else { strippedNew = strippedOld; } + photoObject = newMsg.media.photo; } else if (newMsg.media.document != null) { strippedOld = FileLoader.getClosestPhotoSizeWithSize(newMsg.media.document.thumbs, 40); if (sentMessage != null && sentMessage.media != null && sentMessage.media.document != null) { @@ -4183,6 +4186,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } else { strippedNew = strippedOld; } + photoObject = newMsg.media.document; } else if (newMsg.media.webpage != null) { if (newMsg.media.webpage.photo != null) { strippedOld = FileLoader.getClosestPhotoSizeWithSize(newMsg.media.webpage.photo.sizes, 40); @@ -4191,6 +4195,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } else { strippedNew = strippedOld; } + photoObject = newMsg.media.webpage.photo; } else if (newMsg.media.webpage.document != null) { strippedOld = FileLoader.getClosestPhotoSizeWithSize(newMsg.media.webpage.document.thumbs, 40); if (sentMessage != null && sentMessage.media != null && sentMessage.media.webpage != null && sentMessage.media.webpage.document != null) { @@ -4198,6 +4203,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } else { strippedNew = strippedOld; } + photoObject = newMsg.media.webpage.document; } } if (strippedNew instanceof TLRPC.TL_photoStrippedSize && strippedOld instanceof TLRPC.TL_photoStrippedSize) { @@ -4208,7 +4214,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } else { newKey = "stripped" + "message" + newMsgId + "_" + newMsgObj.getChannelId(); } - ImageLoader.getInstance().replaceImageInCache(oldKey, newKey, strippedNew, post); + ImageLoader.getInstance().replaceImageInCache(oldKey, newKey, ImageLocation.getForObject(strippedNew, photoObject), post); } } if (sentMessage == null) { @@ -4246,7 +4252,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter cacheFile2 = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName2 + ".jpg"); } cacheFile.renameTo(cacheFile2); - ImageLoader.getInstance().replaceImageInCache(fileName, fileName2, size.location, post); + ImageLoader.getInstance().replaceImageInCache(fileName, fileName2, ImageLocation.getForPhoto(size, sentMessage.media.photo), post); size2.location = size.location; size2.size = size.size; break; @@ -4280,7 +4286,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter File cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName + ".jpg"); File cacheFile2 = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName2 + ".jpg"); cacheFile.renameTo(cacheFile2); - ImageLoader.getInstance().replaceImageInCache(fileName, fileName2, size.location, post); + ImageLoader.getInstance().replaceImageInCache(fileName, fileName2, ImageLocation.getForDocument(size, sentMessage.media.document), post); size2.location = size.location; size2.size = size.size; } @@ -4824,21 +4830,24 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter TLRPC.TL_document document = null; TLRPC.TL_photo photo = null; TLRPC.TL_game game = null; - if (result instanceof TLRPC.TL_botInlineMediaResult) { - if (result.type.equals("game")) { - if ((int) dialog_id == 0) { - return; //doesn't work in secret chats for now - } - game = new TLRPC.TL_game(); - game.title = result.title; - game.description = result.description; - game.short_name = result.id; - game.photo = result.photo; - if (result.document instanceof TLRPC.TL_document) { - game.document = result.document; - game.flags |= 1; - } - } else if (result.document != null) { + if ("game".equals(result.type)) { + if ((int) dialog_id == 0) { + return; //doesn't work in secret chats for now + } + game = new TLRPC.TL_game(); + game.title = result.title; + game.description = result.description; + game.short_name = result.id; + game.photo = result.photo; + if (game.photo == null) { + game.photo = new TLRPC.TL_photoEmpty(); + } + if (result.document instanceof TLRPC.TL_document) { + game.document = result.document; + game.flags |= 1; + } + } else if (result instanceof TLRPC.TL_botInlineMediaResult) { + if (result.document != null) { if (result.document instanceof TLRPC.TL_document) { document = (TLRPC.TL_document) result.document; } @@ -4847,189 +4856,187 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter photo = (TLRPC.TL_photo) result.photo; } } - } else { - if (result.content != null) { - File f = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.MD5(result.content.url) + "." + ImageLoader.getHttpUrlExtension(result.content.url, "file")); - if (f.exists()) { - finalPath = f.getAbsolutePath(); - } else { - finalPath = result.content.url; - } - switch (result.type) { - case "audio": - case "voice": - case "file": - case "video": - case "sticker": - case "gif": { - document = new TLRPC.TL_document(); - document.id = 0; - document.size = 0; - document.dc_id = 0; - document.mime_type = result.content.mime_type; - document.file_reference = new byte[0]; - document.date = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); - TLRPC.TL_documentAttributeFilename fileName = new TLRPC.TL_documentAttributeFilename(); - document.attributes.add(fileName); + } else if (result.content != null) { + File f = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.MD5(result.content.url) + "." + ImageLoader.getHttpUrlExtension(result.content.url, "file")); + if (f.exists()) { + finalPath = f.getAbsolutePath(); + } else { + finalPath = result.content.url; + } + switch (result.type) { + case "audio": + case "voice": + case "file": + case "video": + case "sticker": + case "gif": { + document = new TLRPC.TL_document(); + document.id = 0; + document.size = 0; + document.dc_id = 0; + document.mime_type = result.content.mime_type; + document.file_reference = new byte[0]; + document.date = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); + TLRPC.TL_documentAttributeFilename fileName = new TLRPC.TL_documentAttributeFilename(); + document.attributes.add(fileName); - switch (result.type) { - case "gif": { - fileName.file_name = "animation.gif"; + switch (result.type) { + case "gif": { + fileName.file_name = "animation.gif"; + if (finalPath.endsWith("mp4")) { + document.mime_type = "video/mp4"; + document.attributes.add(new TLRPC.TL_documentAttributeAnimated()); + } else { + document.mime_type = "image/gif"; + } + try { + int side = isEncrypted ? 90 : 320; + Bitmap bitmap; if (finalPath.endsWith("mp4")) { - document.mime_type = "video/mp4"; - document.attributes.add(new TLRPC.TL_documentAttributeAnimated()); + bitmap = ThumbnailUtils.createVideoThumbnail(finalPath, MediaStore.Video.Thumbnails.MINI_KIND); } else { - document.mime_type = "image/gif"; + bitmap = ImageLoader.loadBitmap(finalPath, null, side, side, true); } - try { - int side = isEncrypted ? 90 : 320; - Bitmap bitmap; - if (finalPath.endsWith("mp4")) { - bitmap = ThumbnailUtils.createVideoThumbnail(finalPath, MediaStore.Video.Thumbnails.MINI_KIND); - } else { - bitmap = ImageLoader.loadBitmap(finalPath, null, side, side, true); + if (bitmap != null) { + TLRPC.PhotoSize thumb = ImageLoader.scaleAndSaveImage(bitmap, side, side, side > 90 ? 80 : 55, false); + if (thumb != null) { + document.thumbs.add(thumb); + document.flags |= 1; } + bitmap.recycle(); + } + } catch (Throwable e) { + FileLog.e(e); + } + break; + } + case "voice": { + TLRPC.TL_documentAttributeAudio audio = new TLRPC.TL_documentAttributeAudio(); + audio.duration = MessageObject.getInlineResultDuration(result); + audio.voice = true; + fileName.file_name = "audio.ogg"; + document.attributes.add(audio); + + break; + } + case "audio": { + TLRPC.TL_documentAttributeAudio audio = new TLRPC.TL_documentAttributeAudio(); + audio.duration = MessageObject.getInlineResultDuration(result); + audio.title = result.title; + audio.flags |= 1; + if (result.description != null) { + audio.performer = result.description; + audio.flags |= 2; + } + fileName.file_name = "audio.mp3"; + document.attributes.add(audio); + + break; + } + case "file": { + int idx = result.content.mime_type.lastIndexOf('/'); + if (idx != -1) { + fileName.file_name = "file." + result.content.mime_type.substring(idx + 1); + } else { + fileName.file_name = "file"; + } + break; + } + case "video": { + fileName.file_name = "video.mp4"; + TLRPC.TL_documentAttributeVideo attributeVideo = new TLRPC.TL_documentAttributeVideo(); + int wh[] = MessageObject.getInlineResultWidthAndHeight(result); + attributeVideo.w = wh[0]; + attributeVideo.h = wh[1]; + attributeVideo.duration = MessageObject.getInlineResultDuration(result); + attributeVideo.supports_streaming = true; + document.attributes.add(attributeVideo); + try { + if (result.thumb != null) { + String thumbPath = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.MD5(result.thumb.url) + "." + ImageLoader.getHttpUrlExtension(result.thumb.url, "jpg")).getAbsolutePath(); + Bitmap bitmap = ImageLoader.loadBitmap(thumbPath, null, 90, 90, true); if (bitmap != null) { - TLRPC.PhotoSize thumb = ImageLoader.scaleAndSaveImage(bitmap, side, side, side > 90 ? 70 : 55, false); + TLRPC.PhotoSize thumb = ImageLoader.scaleAndSaveImage(bitmap, 90, 90, 55, false); if (thumb != null) { document.thumbs.add(thumb); document.flags |= 1; } bitmap.recycle(); } - } catch (Throwable e) { - FileLog.e(e); } - break; - } - case "voice": { - TLRPC.TL_documentAttributeAudio audio = new TLRPC.TL_documentAttributeAudio(); - audio.duration = MessageObject.getInlineResultDuration(result); - audio.voice = true; - fileName.file_name = "audio.ogg"; - document.attributes.add(audio); - - break; - } - case "audio": { - TLRPC.TL_documentAttributeAudio audio = new TLRPC.TL_documentAttributeAudio(); - audio.duration = MessageObject.getInlineResultDuration(result); - audio.title = result.title; - audio.flags |= 1; - if (result.description != null) { - audio.performer = result.description; - audio.flags |= 2; - } - fileName.file_name = "audio.mp3"; - document.attributes.add(audio); - - break; - } - case "file": { - int idx = result.content.mime_type.lastIndexOf('/'); - if (idx != -1) { - fileName.file_name = "file." + result.content.mime_type.substring(idx + 1); - } else { - fileName.file_name = "file"; - } - break; - } - case "video": { - fileName.file_name = "video.mp4"; - TLRPC.TL_documentAttributeVideo attributeVideo = new TLRPC.TL_documentAttributeVideo(); - int wh[] = MessageObject.getInlineResultWidthAndHeight(result); - attributeVideo.w = wh[0]; - attributeVideo.h = wh[1]; - attributeVideo.duration = MessageObject.getInlineResultDuration(result); - attributeVideo.supports_streaming = true; - document.attributes.add(attributeVideo); - try { - if (result.thumb != null) { - String thumbPath = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.MD5(result.thumb.url) + "." + ImageLoader.getHttpUrlExtension(result.thumb.url, "jpg")).getAbsolutePath(); - Bitmap bitmap = ImageLoader.loadBitmap(thumbPath, null, 90, 90, true); - if (bitmap != null) { - TLRPC.PhotoSize thumb = ImageLoader.scaleAndSaveImage(bitmap, 90, 90, 55, false); - if (thumb != null) { - document.thumbs.add(thumb); - document.flags |= 1; - } - bitmap.recycle(); - } - } - } catch (Throwable e) { - FileLog.e(e); - } - break; - } - case "sticker": { - TLRPC.TL_documentAttributeSticker attributeSticker = new TLRPC.TL_documentAttributeSticker(); - attributeSticker.alt = ""; - attributeSticker.stickerset = new TLRPC.TL_inputStickerSetEmpty(); - document.attributes.add(attributeSticker); - TLRPC.TL_documentAttributeImageSize attributeImageSize = new TLRPC.TL_documentAttributeImageSize(); - int wh[] = MessageObject.getInlineResultWidthAndHeight(result); - attributeImageSize.w = wh[0]; - attributeImageSize.h = wh[1]; - document.attributes.add(attributeImageSize); - fileName.file_name = "sticker.webp"; - try { - if (result.thumb != null) { - String thumbPath = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.MD5(result.thumb.url) + "." + ImageLoader.getHttpUrlExtension(result.thumb.url, "webp")).getAbsolutePath(); - Bitmap bitmap = ImageLoader.loadBitmap(thumbPath, null, 90, 90, true); - if (bitmap != null) { - TLRPC.PhotoSize thumb = ImageLoader.scaleAndSaveImage(bitmap, 90, 90, 55, false); - if (thumb != null) { - document.thumbs.add(thumb); - document.flags |= 1; - } - bitmap.recycle(); - } - } - } catch (Throwable e) { - FileLog.e(e); - } - break; + } catch (Throwable e) { + FileLog.e(e); } + break; } - if (fileName.file_name == null) { - fileName.file_name = "file"; - } - if (document.mime_type == null) { - document.mime_type = "application/octet-stream"; - } - if (document.thumbs.isEmpty()) { - TLRPC.PhotoSize thumb = new TLRPC.TL_photoSize(); + case "sticker": { + TLRPC.TL_documentAttributeSticker attributeSticker = new TLRPC.TL_documentAttributeSticker(); + attributeSticker.alt = ""; + attributeSticker.stickerset = new TLRPC.TL_inputStickerSetEmpty(); + document.attributes.add(attributeSticker); + TLRPC.TL_documentAttributeImageSize attributeImageSize = new TLRPC.TL_documentAttributeImageSize(); int wh[] = MessageObject.getInlineResultWidthAndHeight(result); - thumb.w = wh[0]; - thumb.h = wh[1]; - thumb.size = 0; - thumb.location = new TLRPC.TL_fileLocationUnavailable(); - thumb.type = "x"; + attributeImageSize.w = wh[0]; + attributeImageSize.h = wh[1]; + document.attributes.add(attributeImageSize); + fileName.file_name = "sticker.webp"; + try { + if (result.thumb != null) { + String thumbPath = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.MD5(result.thumb.url) + "." + ImageLoader.getHttpUrlExtension(result.thumb.url, "webp")).getAbsolutePath(); + Bitmap bitmap = ImageLoader.loadBitmap(thumbPath, null, 90, 90, true); + if (bitmap != null) { + TLRPC.PhotoSize thumb = ImageLoader.scaleAndSaveImage(bitmap, 90, 90, 55, false); + if (thumb != null) { + document.thumbs.add(thumb); + document.flags |= 1; + } + bitmap.recycle(); + } + } + } catch (Throwable e) { + FileLog.e(e); + } + break; + } + } + if (fileName.file_name == null) { + fileName.file_name = "file"; + } + if (document.mime_type == null) { + document.mime_type = "application/octet-stream"; + } + if (document.thumbs.isEmpty()) { + TLRPC.PhotoSize thumb = new TLRPC.TL_photoSize(); + int wh[] = MessageObject.getInlineResultWidthAndHeight(result); + thumb.w = wh[0]; + thumb.h = wh[1]; + thumb.size = 0; + thumb.location = new TLRPC.TL_fileLocationUnavailable(); + thumb.type = "x"; - document.thumbs.add(thumb); - document.flags |= 1; - } - break; + document.thumbs.add(thumb); + document.flags |= 1; } - case "photo": { - if (f.exists()) { - photo = SendMessagesHelper.getInstance(currentAccount).generatePhotoSizes(finalPath, null); - } - if (photo == null) { - photo = new TLRPC.TL_photo(); - photo.date = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); - photo.file_reference = new byte[0]; - TLRPC.TL_photoSize photoSize = new TLRPC.TL_photoSize(); - int wh[] = MessageObject.getInlineResultWidthAndHeight(result); - photoSize.w = wh[0]; - photoSize.h = wh[1]; - photoSize.size = 1; - photoSize.location = new TLRPC.TL_fileLocationUnavailable(); - photoSize.type = "x"; - photo.sizes.add(photoSize); - } - break; + break; + } + case "photo": { + if (f.exists()) { + photo = SendMessagesHelper.getInstance(currentAccount).generatePhotoSizes(finalPath, null); } + if (photo == null) { + photo = new TLRPC.TL_photo(); + photo.date = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); + photo.file_reference = new byte[0]; + TLRPC.TL_photoSize photoSize = new TLRPC.TL_photoSize(); + int wh[] = MessageObject.getInlineResultWidthAndHeight(result); + photoSize.w = wh[0]; + photoSize.h = wh[1]; + photoSize.size = 1; + photoSize.location = new TLRPC.TL_fileLocationUnavailable(); + photoSize.type = "x"; + photo.sizes.add(photoSize); + } + break; } } } @@ -5174,12 +5181,104 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter thumb = ThumbnailUtils.createVideoThumbnail(path, MediaStore.Video.Thumbnails.MINI_KIND); } int side = isEncrypted ? 90 : 320; - document.thumbs.set(0, ImageLoader.scaleAndSaveImage(photoSize, thumb, side, side, side > 90 ? 70 : 55, false)); + document.thumbs.set(0, ImageLoader.scaleAndSaveImage(photoSize, thumb, side, side, side > 90 ? 80 : 55, false)); } } } } + private static String getKeyForPhotoSize(TLRPC.PhotoSize photoSize, Bitmap[] bitmap, boolean blur) { + if (photoSize == null) { + return null; + } + int maxPhotoWidth; + int photoWidth; + int photoHeight; + if (AndroidUtilities.isTablet()) { + maxPhotoWidth = photoWidth = (int) (AndroidUtilities.getMinTabletSide() * 0.7f); + } else { + if (photoSize.w >= photoSize.h) { + maxPhotoWidth = photoWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(64); + } else { + maxPhotoWidth = photoWidth = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f); + } + } + + photoHeight = photoWidth + AndroidUtilities.dp(100); + + if (photoWidth > AndroidUtilities.getPhotoSize()) { + photoWidth = AndroidUtilities.getPhotoSize(); + } + if (photoHeight > AndroidUtilities.getPhotoSize()) { + photoHeight = AndroidUtilities.getPhotoSize(); + } + + float scale = (float) photoSize.w / (float) photoWidth; + int w = (int) (photoSize.w / scale); + int h = (int) (photoSize.h / scale); + if (w == 0) { + w = AndroidUtilities.dp(150); + } + if (h == 0) { + h = AndroidUtilities.dp(150); + } + if (h > photoHeight) { + float scale2 = h; + h = photoHeight; + scale2 /= h; + w = (int) (w / scale2); + } else if (h < AndroidUtilities.dp(120)) { + h = AndroidUtilities.dp(120); + float hScale = (float) photoSize.h / h; + if (photoSize.w / hScale < photoWidth) { + w = (int) (photoSize.w / hScale); + } + } + + if (bitmap != null) { + try { + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inJustDecodeBounds = true; + File file = FileLoader.getPathToAttach(photoSize); + + FileInputStream is = new FileInputStream(file); + BitmapFactory.decodeStream(is, null, opts); + is.close(); + + float photoW = opts.outWidth; + float photoH = opts.outHeight; + float scaleFactor = Math.max(photoW / w, photoH / h); + if (scaleFactor < 1) { + scaleFactor = 1; + } + opts.inJustDecodeBounds = false; + opts.inSampleSize = (int) scaleFactor; + opts.inPreferredConfig = Bitmap.Config.RGB_565; + if (Build.VERSION.SDK_INT >= 21) { + is = new FileInputStream(file); + 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);*/ + } + } catch (Throwable ignore) { + + } + } + + return String.format(Locale.US, blur ? "%d_%d@%d_%d_b" : "%d_%d@%d_%d", photoSize.location.volume_id, photoSize.location.local_id, (int) (w / AndroidUtilities.density), (int) (h / AndroidUtilities.density)); + } + @UiThread public static void prepareSendingMedia(final ArrayList media, final long dialog_id, final MessageObject reply_to_msg, final InputContentInfoCompat inputContent, final boolean forceDocument, final boolean groupPhotos, final MessageObject editingMessageObject) { if (media.isEmpty()) { @@ -5343,7 +5442,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter bitmap = ImageLoader.loadBitmap(thumbFile.getAbsolutePath(), null, side, side, true); } if (bitmap != null) { - TLRPC.PhotoSize thumb = ImageLoader.scaleAndSaveImage(bitmap, side, side, side > 90 ? 70 : 55, isEncrypted); + TLRPC.PhotoSize thumb = ImageLoader.scaleAndSaveImage(bitmap, side, side, side > 90 ? 80 : 55, isEncrypted); if (thumb != null) { document.thumbs.add(thumb); document.flags |= 1; @@ -5492,10 +5591,11 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter if (thumb == null) { thumb = ThumbnailUtils.createVideoThumbnail(info.path, MediaStore.Video.Thumbnails.MINI_KIND); } - int side = isEncrypted || info.ttl != 0 ? 90 : 320; - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(thumb, side, side, side > 90 ? 70 : 55, isEncrypted); - if (thumb != null && size != null) { - thumb = null; + TLRPC.PhotoSize size = null; + if (thumb != null) { + int side = isEncrypted || info.ttl != 0 ? 90 : Math.max(thumb.getWidth(), thumb.getHeight()); + size = ImageLoader.scaleAndSaveImage(thumb, side, side, side > 90 ? 80 : 55, isEncrypted); + thumbKey = getKeyForPhotoSize(size, null, true); } document = new TLRPC.TL_document(); document.file_reference = new byte[0]; @@ -5701,85 +5801,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter if (!groupPhotos || media.size() == 1) { TLRPC.PhotoSize currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(photoFinal.sizes, AndroidUtilities.getPhotoSize()); if (currentPhotoObject != null) { - int maxPhotoWidth; - int photoWidth; - int photoHeight; - if (AndroidUtilities.isTablet()) { - maxPhotoWidth = photoWidth = (int) (AndroidUtilities.getMinTabletSide() * 0.7f); - } else { - if (currentPhotoObject.w >= currentPhotoObject.h) { - maxPhotoWidth = photoWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(64); - } else { - maxPhotoWidth = photoWidth = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f); - } - } - - photoHeight = photoWidth + AndroidUtilities.dp(100); - - if (photoWidth > AndroidUtilities.getPhotoSize()) { - photoWidth = AndroidUtilities.getPhotoSize(); - } - if (photoHeight > AndroidUtilities.getPhotoSize()) { - photoHeight = AndroidUtilities.getPhotoSize(); - } - - float scale = (float) currentPhotoObject.w / (float) photoWidth; - int w = (int) (currentPhotoObject.w / scale); - int h = (int) (currentPhotoObject.h / scale); - if (w == 0) { - w = AndroidUtilities.dp(150); - } - if (h == 0) { - h = AndroidUtilities.dp(150); - } - if (h > photoHeight) { - float scale2 = h; - h = photoHeight; - scale2 /= h; - w = (int) (w / scale2); - } else if (h < AndroidUtilities.dp(120)) { - h = AndroidUtilities.dp(120); - float hScale = (float) currentPhotoObject.h / h; - if (currentPhotoObject.w / hScale < photoWidth) { - w = (int) (currentPhotoObject.w / hScale); - } - } - keyFinal[0] = String.format(Locale.US, "%d_%d@%d_%d", currentPhotoObject.location.volume_id, currentPhotoObject.location.local_id, (int) (w / AndroidUtilities.density), (int) (h / AndroidUtilities.density)); - - BitmapFactory.Options opts = new BitmapFactory.Options(); - opts.inJustDecodeBounds = true; - File file = FileLoader.getPathToAttach(currentPhotoObject); - - FileInputStream is = new FileInputStream(file); - BitmapFactory.decodeStream(is, null, opts); - is.close(); - - float photoW = opts.outWidth; - float photoH = opts.outHeight; - float scaleFactor = Math.max(photoW / w, photoH / h); - if (scaleFactor < 1) { - scaleFactor = 1; - } - opts.inJustDecodeBounds = false; - opts.inSampleSize = (int) scaleFactor; - opts.inPreferredConfig = Bitmap.Config.RGB_565; - if (Build.VERSION.SDK_INT >= 21) { - is = new FileInputStream(file); - bitmapFinal[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);*/ - } + keyFinal[0] = getKeyForPhotoSize(currentPhotoObject, bitmapFinal, false); } } } catch (Exception e) { @@ -5932,137 +5954,29 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter if (bitmap == null) { return null; } - - int width = bitmap.getWidth(); - int height = bitmap.getHeight(); - int max = Math.max(width, height); - float size = 320; - if (max > size) { - float scale = size / max; - int w = Math.round(scale * width); - int h = Math.round(scale * height); - Bitmap scaled = Bitmaps.createScaledBitmap(bitmap, w, h, true); - if (scaled != bitmap) { - bitmap.recycle(); - bitmap = scaled; - } - } return bitmap; } private static VideoEditedInfo createCompressionSettings(String videoPath) { - TrackHeaderBox trackHeaderBox = null; - int originalBitrate = 0; - int bitrate = 0; - float videoDuration = 0.0f; - long videoFramesSize = 0; - long audioFramesSize = 0; - int videoFramerate = 25; - try { - IsoFile isoFile = new IsoFile(videoPath); - List boxes = Path.getPaths(isoFile, "/moov/trak/"); + int[] params = new int[AnimatedFileDrawable.PARAM_NUM_COUNT]; + AnimatedFileDrawable.getVideoInfo(videoPath, params); - Box boxTest = Path.getPath(isoFile, "/moov/trak/mdia/minf/stbl/stsd/mp4a/"); - if (boxTest == null) { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("video hasn't mp4a atom"); - } + if (params[AnimatedFileDrawable.PARAM_NUM_IS_AVC] == 0) { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("video hasn't avc1 atom"); } - - boxTest = Path.getPath(isoFile, "/moov/trak/mdia/minf/stbl/stsd/avc1/"); - if (boxTest == null) { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("video hasn't avc1 atom"); - } - return null; - } - - for (int b = 0; b < boxes.size(); b++) { - Box box = boxes.get(b); - TrackBox trackBox = (TrackBox) box; - long sampleSizes = 0; - long trackBitrate = 0; - MediaBox mediaBox = null; - MediaHeaderBox mediaHeaderBox = null; - try { - mediaBox = trackBox.getMediaBox(); - mediaHeaderBox = mediaBox.getMediaHeaderBox(); - SampleSizeBox sampleSizeBox = mediaBox.getMediaInformationBox().getSampleTableBox().getSampleSizeBox(); - long[] sizes = sampleSizeBox.getSampleSizes(); - for (int a = 0; a < sizes.length; a++) { - sampleSizes += sizes[a]; - } - if (videoDuration == 0) { - videoDuration = (float) mediaHeaderBox.getDuration() / (float) mediaHeaderBox.getTimescale(); - if (videoDuration == 0) { - MediaPlayer player = null; - try { - player = new MediaPlayer(); - player.setDataSource(videoPath); - player.prepare(); - videoDuration = player.getDuration() / 1000.0f; - if (videoDuration < 0) { - videoDuration = 0; - } - } catch (Throwable ignore) { - - } finally { - try { - if (player != null) { - player.release(); - } - } catch (Throwable ignore) { - - } - } - } - } - if (videoDuration != 0) { - trackBitrate = (int) (sampleSizes * 8 / videoDuration); - } else { - trackBitrate = 400000; - } - } catch (Exception e) { - FileLog.e(e); - } - TrackHeaderBox headerBox = trackBox.getTrackHeaderBox(); - if (headerBox.getWidth() != 0 && headerBox.getHeight() != 0) { - if (trackHeaderBox == null || trackHeaderBox.getWidth() < headerBox.getWidth() || trackHeaderBox.getHeight() < headerBox.getHeight()) { - trackHeaderBox = headerBox; - originalBitrate = bitrate = (int) (trackBitrate / 100000 * 100000); - if (bitrate > 900000) { - bitrate = 900000; - } - videoFramesSize += sampleSizes; - - if (mediaBox != null && mediaHeaderBox != null) { - TimeToSampleBox timeToSampleBox = mediaBox.getMediaInformationBox().getSampleTableBox().getTimeToSampleBox(); - if (timeToSampleBox != null) { - List entries = timeToSampleBox.getEntries(); - long delta = 0; - int size = Math.min(entries.size(), 11); - for (int a = 1; a < size; a++) { - delta += entries.get(a).getDelta(); - } - if (delta != 0) { - videoFramerate = (int) ((double) mediaHeaderBox.getTimescale() / (delta / (size - 1))); - } - } - } - } - } else { - audioFramesSize += sampleSizes; - } - } - } catch (Exception e) { - FileLog.e(e); return null; } - if (trackHeaderBox == null) { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("video hasn't trackHeaderBox atom"); - } - return null; + + int originalBitrate = params[AnimatedFileDrawable.PARAM_NUM_BITRATE]; + int bitrate = params[AnimatedFileDrawable.PARAM_NUM_BITRATE]; + float videoDuration = params[AnimatedFileDrawable.PARAM_NUM_DURATION]; + long videoFramesSize = params[AnimatedFileDrawable.PARAM_NUM_VIDEO_FRAME_SIZE]; + long audioFramesSize = params[AnimatedFileDrawable.PARAM_NUM_AUDIO_FRAME_SIZE]; + int videoFramerate = params[AnimatedFileDrawable.PARAM_NUM_FRAMERATE]; + + if (bitrate > 900000) { + bitrate = 900000; } if (Build.VERSION.SDK_INT < 18) { @@ -6099,7 +6013,6 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter return null; } } - videoDuration *= 1000; VideoEditedInfo videoEditedInfo = new VideoEditedInfo(); videoEditedInfo.startTime = -1; @@ -6108,19 +6021,9 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter videoEditedInfo.originalPath = videoPath; videoEditedInfo.framerate = videoFramerate; videoEditedInfo.estimatedDuration = (long) Math.ceil(videoDuration); - videoEditedInfo.resultWidth = videoEditedInfo.originalWidth = (int) trackHeaderBox.getWidth(); - videoEditedInfo.resultHeight = videoEditedInfo.originalHeight = (int) trackHeaderBox.getHeight(); - - Matrix matrix = trackHeaderBox.getMatrix(); - if (matrix.equals(Matrix.ROTATE_90)) { - videoEditedInfo.rotationValue = 90; - } else if (matrix.equals(Matrix.ROTATE_180)) { - videoEditedInfo.rotationValue = 180; - } else if (matrix.equals(Matrix.ROTATE_270)) { - videoEditedInfo.rotationValue = 270; - } else { - videoEditedInfo.rotationValue = 0; - } + videoEditedInfo.resultWidth = videoEditedInfo.originalWidth = params[AnimatedFileDrawable.PARAM_NUM_WIDTH]; + videoEditedInfo.resultHeight = videoEditedInfo.originalHeight = params[AnimatedFileDrawable.PARAM_NUM_HEIGHT]; + videoEditedInfo.rotationValue = params[AnimatedFileDrawable.PARAM_NUM_ROTATION]; SharedPreferences preferences = MessagesController.getGlobalMainSettings(); int selectedCompression = preferences.getInt("compress_video2", 1); @@ -6236,7 +6139,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter thumb = ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Video.Thumbnails.MINI_KIND); } int side = isEncrypted || ttl != 0 ? 90 : 320; - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(thumb, side, side, side > 90 ? 70 : 55, isEncrypted); + TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(thumb, side, side, side > 90 ? 80 : 55, isEncrypted); if (thumb != null && size != null) { if (isRound) { if (isEncrypted) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index 86c52685a..0c5734016 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -31,6 +31,8 @@ public class SharedConfig { public static byte[] pushAuthKey; public static byte[] pushAuthKeyId; + public static long directShareHash; + public static boolean saveIncomingPhotos; public static String passcodeHash = ""; public static long passcodeRetryInMs; @@ -72,15 +74,21 @@ public class SharedConfig { public static boolean streamAllVideo = false; public static boolean streamMkv = false; public static boolean saveStreamMedia = true; + public static boolean showAnimatedStickers = BuildVars.DEBUG_VERSION; public static boolean sortContactsByName; public static boolean shuffleMusic; public static boolean playOrderReversed; public static boolean hasCameraCache; + public static boolean showNotificationsForAllAccounts = true; public static int repeatMode; public static boolean allowBigEmoji; public static boolean useSystemEmoji; public static int fontSize = AndroidUtilities.dp(16); + public static boolean drawDialogIcons; + public static boolean useThreeLinesLayout; + public static boolean archiveHidden; + static { loadConfig(); } @@ -220,7 +228,7 @@ public class SharedConfig { groupPhotosEnabled = preferences.getBoolean("groupPhotosEnabled", true); repeatMode = preferences.getInt("repeatMode", 0); fontSize = preferences.getInt("fons_size", AndroidUtilities.isTablet() ? 18 : 16); - allowBigEmoji = preferences.getBoolean("allowBigEmoji", false); + allowBigEmoji = preferences.getBoolean("allowBigEmoji", true); useSystemEmoji = preferences.getBoolean("useSystemEmoji", false); streamMedia = preferences.getBoolean("streamMedia", true); saveStreamMedia = preferences.getBoolean("saveStreamMedia", true); @@ -229,6 +237,12 @@ public class SharedConfig { suggestStickers = preferences.getInt("suggestStickers", 0); sortContactsByName = preferences.getBoolean("sortContactsByName", false); noSoundHintShowed = preferences.getBoolean("noSoundHintShowed", false); + directShareHash = preferences.getLong("directShareHash", 0); + useThreeLinesLayout = preferences.getBoolean("useThreeLinesLayout", false); + archiveHidden = preferences.getBoolean("archiveHidden", false); + + preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); + showNotificationsForAllAccounts = preferences.getBoolean("AllAccounts", true); configLoaded = true; } @@ -394,6 +408,23 @@ public class SharedConfig { editor.commit(); } + public static void setUseThreeLinesLayout(boolean value) { + useThreeLinesLayout = value; + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putBoolean("useThreeLinesLayout", useThreeLinesLayout); + editor.commit(); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.dialogsNeedReload, true); + } + + public static void toggleArchiveHidden() { + archiveHidden = !archiveHidden; + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putBoolean("archiveHidden", archiveHidden); + editor.commit(); + } + public static void toggleAutoplayVideo() { autoplayVideo = !autoplayVideo; SharedPreferences preferences = MessagesController.getGlobalMainSettings(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TgChooserTargetService.java b/TMessagesProj/src/main/java/org/telegram/messenger/TgChooserTargetService.java index fc8c0c41f..dabe33915 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TgChooserTargetService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TgChooserTargetService.java @@ -9,6 +9,7 @@ package org.telegram.messenger; import android.annotation.TargetApi; +import android.app.Activity; import android.content.ComponentName; import android.content.IntentFilter; import android.content.SharedPreferences; @@ -105,6 +106,9 @@ public class TgChooserTargetService extends ChooserTargetService { } catch (Exception e) { FileLog.e(e); } + SharedConfig.directShareHash = Utilities.random.nextLong(); + ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).edit().putLong("directShareHash", SharedConfig.directShareHash).commit(); + for (int a = 0; a < dialogs.size(); a++) { Bundle extras = new Bundle(); Icon icon = null; @@ -116,6 +120,7 @@ public class TgChooserTargetService extends ChooserTargetService { if (user.id == id) { if (!user.bot) { extras.putLong("dialogId", (long) id); + extras.putLong("hash", SharedConfig.directShareHash); if (user.photo != null && user.photo.photo_small != null) { icon = createRoundBitmap(FileLoader.getPathToAttach(user.photo.photo_small, true)); } @@ -130,6 +135,7 @@ public class TgChooserTargetService extends ChooserTargetService { if (chat.id == -id) { if (!ChatObject.isNotInChat(chat) && (!ChatObject.isChannel(chat) || chat.megagroup)) { extras.putLong("dialogId", (long) id); + extras.putLong("hash", SharedConfig.directShareHash); if (chat.photo != null && chat.photo.photo_small != null) { icon = createRoundBitmap(FileLoader.getPathToAttach(chat.photo.photo_small, true)); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java index 1a6297b67..6231fd7a6 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java @@ -36,25 +36,19 @@ public class UserConfig { public int lastContactsSyncTime; public int lastHintsSyncTime; public boolean draftsLoaded; - public boolean pinnedDialogsLoaded = true; public boolean unreadDialogsLoaded = true; public TLRPC.TL_account_tmpPassword tmpPassword; public int ratingLoadTime; public int botRatingLoadTime; public boolean contactsReimported; + public boolean hasValidDialogLoadIds; public int migrateOffsetId = -1; public int migrateOffsetDate = -1; public int migrateOffsetUserId = -1; public int migrateOffsetChatId = -1; public int migrateOffsetChannelId = -1; public long migrateOffsetAccess = -1; - public int totalDialogsLoadCount = 0; - public int dialogsLoadOffsetId = 0; - public int dialogsLoadOffsetDate = 0; - public int dialogsLoadOffsetUserId = 0; - public int dialogsLoadOffsetChatId = 0; - public int dialogsLoadOffsetChannelId = 0; - public long dialogsLoadOffsetAccess = 0; + public boolean notificationsSettingsLoaded; public boolean notificationsSignUpSettingsLoaded; public boolean syncContacts = true; @@ -117,13 +111,7 @@ public class UserConfig { public void saveConfig(boolean withFile, File oldFile) { synchronized (sync) { try { - SharedPreferences preferences; - if (currentAccount == 0) { - preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE); - } else { - preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfig" + currentAccount, Context.MODE_PRIVATE); - } - SharedPreferences.Editor editor = preferences.edit(); + SharedPreferences.Editor editor = getPreferences().edit(); if (currentAccount == 0) { editor.putInt("selectedAccount", selectedAccount); } @@ -135,7 +123,6 @@ public class UserConfig { editor.putInt("lastContactsSyncTime", lastContactsSyncTime); editor.putInt("lastHintsSyncTime", lastHintsSyncTime); editor.putBoolean("draftsLoaded", draftsLoaded); - editor.putBoolean("pinnedDialogsLoaded", pinnedDialogsLoaded); editor.putBoolean("unreadDialogsLoaded", unreadDialogsLoaded); editor.putInt("ratingLoadTime", ratingLoadTime); editor.putInt("botRatingLoadTime", botRatingLoadTime); @@ -147,14 +134,15 @@ public class UserConfig { editor.putBoolean("notificationsSettingsLoaded3", notificationsSettingsLoaded); editor.putBoolean("notificationsSignUpSettingsLoaded", notificationsSignUpSettingsLoaded); editor.putLong("autoDownloadConfigLoadTime", autoDownloadConfigLoadTime); + editor.putBoolean("hasValidDialogLoadIds", hasValidDialogLoadIds); - editor.putInt("3migrateOffsetId", migrateOffsetId); + editor.putInt("6migrateOffsetId", migrateOffsetId); if (migrateOffsetId != -1) { - editor.putInt("3migrateOffsetDate", migrateOffsetDate); - editor.putInt("3migrateOffsetUserId", migrateOffsetUserId); - editor.putInt("3migrateOffsetChatId", migrateOffsetChatId); - editor.putInt("3migrateOffsetChannelId", migrateOffsetChannelId); - editor.putLong("3migrateOffsetAccess", migrateOffsetAccess); + editor.putInt("6migrateOffsetDate", migrateOffsetDate); + editor.putInt("6migrateOffsetUserId", migrateOffsetUserId); + editor.putInt("6migrateOffsetChatId", migrateOffsetChatId); + editor.putInt("6migrateOffsetChannelId", migrateOffsetChannelId); + editor.putLong("6migrateOffsetAccess", migrateOffsetAccess); } if (unacceptedTermsOfService != null) { @@ -190,14 +178,6 @@ public class UserConfig { } } - editor.putInt("2totalDialogsLoadCount", totalDialogsLoadCount); - editor.putInt("2dialogsLoadOffsetId", dialogsLoadOffsetId); - editor.putInt("2dialogsLoadOffsetDate", dialogsLoadOffsetDate); - editor.putInt("2dialogsLoadOffsetUserId", dialogsLoadOffsetUserId); - editor.putInt("2dialogsLoadOffsetChatId", dialogsLoadOffsetChatId); - editor.putInt("2dialogsLoadOffsetChannelId", dialogsLoadOffsetChannelId); - editor.putLong("2dialogsLoadOffsetAccess", dialogsLoadOffsetAccess); - SharedConfig.saveConfig(); if (tmpPassword != null) { @@ -268,12 +248,9 @@ public class UserConfig { if (configLoaded) { return; } - SharedPreferences preferences; + SharedPreferences preferences = getPreferences(); if (currentAccount == 0) { - preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE); selectedAccount = preferences.getInt("selectedAccount", 0); - } else { - preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfig" + currentAccount, Context.MODE_PRIVATE); } registeredForPush = preferences.getBoolean("registeredForPush", false); lastSendMessageId = preferences.getInt("lastSendMessageId", -210000); @@ -283,7 +260,6 @@ public class UserConfig { lastContactsSyncTime = preferences.getInt("lastContactsSyncTime", (int) (System.currentTimeMillis() / 1000) - 23 * 60 * 60); lastHintsSyncTime = preferences.getInt("lastHintsSyncTime", (int) (System.currentTimeMillis() / 1000) - 25 * 60 * 60); draftsLoaded = preferences.getBoolean("draftsLoaded", false); - pinnedDialogsLoaded = preferences.getBoolean("pinnedDialogsLoaded", false); unreadDialogsLoaded = preferences.getBoolean("unreadDialogsLoaded", false); contactsReimported = preferences.getBoolean("contactsReimported", false); ratingLoadTime = preferences.getInt("ratingLoadTime", 0); @@ -295,6 +271,7 @@ public class UserConfig { notificationsSettingsLoaded = preferences.getBoolean("notificationsSettingsLoaded3", false); notificationsSignUpSettingsLoaded = preferences.getBoolean("notificationsSignUpSettingsLoaded", false); autoDownloadConfigLoadTime = preferences.getLong("autoDownloadConfigLoadTime", 0); + hasValidDialogLoadIds = preferences.contains("2dialogsLoadOffsetId") || preferences.getBoolean("hasValidDialogLoadIds", false); try { String terms = preferences.getString("terms", null); @@ -342,23 +319,15 @@ public class UserConfig { } } - migrateOffsetId = preferences.getInt("3migrateOffsetId", 0); + migrateOffsetId = preferences.getInt("6migrateOffsetId", 0); if (migrateOffsetId != -1) { - migrateOffsetDate = preferences.getInt("3migrateOffsetDate", 0); - migrateOffsetUserId = preferences.getInt("3migrateOffsetUserId", 0); - migrateOffsetChatId = preferences.getInt("3migrateOffsetChatId", 0); - migrateOffsetChannelId = preferences.getInt("3migrateOffsetChannelId", 0); - migrateOffsetAccess = preferences.getLong("3migrateOffsetAccess", 0); + migrateOffsetDate = preferences.getInt("6migrateOffsetDate", 0); + migrateOffsetUserId = preferences.getInt("6migrateOffsetUserId", 0); + migrateOffsetChatId = preferences.getInt("6migrateOffsetChatId", 0); + migrateOffsetChannelId = preferences.getInt("6migrateOffsetChannelId", 0); + migrateOffsetAccess = preferences.getLong("6migrateOffsetAccess", 0); } - dialogsLoadOffsetId = preferences.getInt("2dialogsLoadOffsetId", -1); - totalDialogsLoadCount = preferences.getInt("2totalDialogsLoadCount", 0); - dialogsLoadOffsetDate = preferences.getInt("2dialogsLoadOffsetDate", -1); - dialogsLoadOffsetUserId = preferences.getInt("2dialogsLoadOffsetUserId", -1); - dialogsLoadOffsetChatId = preferences.getInt("2dialogsLoadOffsetChatId", -1); - dialogsLoadOffsetChannelId = preferences.getInt("2dialogsLoadOffsetChannelId", -1); - dialogsLoadOffsetAccess = preferences.getLong("2dialogsLoadOffsetAccess", -1); - String string = preferences.getString("tmpPassword", null); if (string != null) { byte[] bytes = Base64.decode(string, Base64.DEFAULT); @@ -414,7 +383,17 @@ public class UserConfig { } } + private SharedPreferences getPreferences() { + if (currentAccount == 0) { + return ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE); + } else { + return ApplicationLoader.applicationContext.getSharedPreferences("userconfig" + currentAccount, Context.MODE_PRIVATE); + } + } + public void clearConfig() { + getPreferences().edit().clear().commit(); + currentUser = null; clientUserId = 0; registeredForPush = false; @@ -430,21 +409,14 @@ public class UserConfig { migrateOffsetChatId = -1; migrateOffsetChannelId = -1; migrateOffsetAccess = -1; - dialogsLoadOffsetId = 0; - totalDialogsLoadCount = 0; - dialogsLoadOffsetDate = 0; - dialogsLoadOffsetUserId = 0; - dialogsLoadOffsetChatId = 0; - dialogsLoadOffsetChannelId = 0; - dialogsLoadOffsetAccess = 0; ratingLoadTime = 0; botRatingLoadTime = 0; draftsLoaded = true; contactsReimported = true; syncContacts = true; suggestContacts = true; - pinnedDialogsLoaded = false; unreadDialogsLoaded = true; + hasValidDialogLoadIds = true; unacceptedTermsOfService = null; pendingAppUpdate = null; hasSecureData = false; @@ -464,4 +436,51 @@ public class UserConfig { } saveConfig(true); } + + public boolean isPinnedDialogsLoaded(int folderId) { + return getPreferences().getBoolean("2pinnedDialogsLoaded" + folderId, false); + } + + public void setPinnedDialogsLoaded(int folderId, boolean loaded) { + getPreferences().edit().putBoolean("2pinnedDialogsLoaded" + folderId, loaded).commit(); + } + + public static final int i_dialogsLoadOffsetId = 0; + public static final int i_dialogsLoadOffsetDate = 1; + public static final int i_dialogsLoadOffsetUserId = 2; + public static final int i_dialogsLoadOffsetChatId = 3; + public static final int i_dialogsLoadOffsetChannelId = 4; + public static final int i_dialogsLoadOffsetAccess_1 = 5; + public static final int i_dialogsLoadOffsetAccess_2 = 6; + + public int getTotalDialogsCount(int folderId) { + return getPreferences().getInt("2totalDialogsLoadCount" + (folderId == 0 ? "" : folderId), 0); + } + + public void setTotalDialogsCount(int folderId, int totalDialogsLoadCount) { + getPreferences().edit().putInt("2totalDialogsLoadCount" + (folderId == 0 ? "" : folderId), totalDialogsLoadCount).commit(); + } + + public int[] getDialogLoadOffsets(int folderId) { + SharedPreferences preferences = getPreferences(); + int dialogsLoadOffsetId = preferences.getInt("2dialogsLoadOffsetId" + (folderId == 0 ? "" : folderId), hasValidDialogLoadIds ? 0 : -1); + int dialogsLoadOffsetDate = preferences.getInt("2dialogsLoadOffsetDate" + (folderId == 0 ? "" : folderId), hasValidDialogLoadIds ? 0 : -1); + int dialogsLoadOffsetUserId = preferences.getInt("2dialogsLoadOffsetUserId" + (folderId == 0 ? "" : folderId), hasValidDialogLoadIds ? 0 : -1); + int dialogsLoadOffsetChatId = preferences.getInt("2dialogsLoadOffsetChatId" + (folderId == 0 ? "" : folderId), hasValidDialogLoadIds ? 0 : -1); + int dialogsLoadOffsetChannelId = preferences.getInt("2dialogsLoadOffsetChannelId" + (folderId == 0 ? "" : folderId), hasValidDialogLoadIds ? 0 : -1); + long dialogsLoadOffsetAccess = preferences.getLong("2dialogsLoadOffsetAccess" + (folderId == 0 ? "" : folderId), hasValidDialogLoadIds ? 0 : -1); + return new int[]{dialogsLoadOffsetId, dialogsLoadOffsetDate, dialogsLoadOffsetUserId, dialogsLoadOffsetChatId, dialogsLoadOffsetChannelId, (int) dialogsLoadOffsetAccess, (int) (dialogsLoadOffsetAccess >> 32)}; + } + + public void setDialogsLoadOffset(int folderId, int dialogsLoadOffsetId, int dialogsLoadOffsetDate, int dialogsLoadOffsetUserId, int dialogsLoadOffsetChatId, int dialogsLoadOffsetChannelId, long dialogsLoadOffsetAccess) { + SharedPreferences.Editor editor = getPreferences().edit(); + editor.putInt("2dialogsLoadOffsetId" + (folderId == 0 ? "" : folderId), dialogsLoadOffsetId); + editor.putInt("2dialogsLoadOffsetDate" + (folderId == 0 ? "" : folderId), dialogsLoadOffsetDate); + editor.putInt("2dialogsLoadOffsetUserId" + (folderId == 0 ? "" : folderId), dialogsLoadOffsetUserId); + editor.putInt("2dialogsLoadOffsetChatId" + (folderId == 0 ? "" : folderId), dialogsLoadOffsetChatId); + editor.putInt("2dialogsLoadOffsetChannelId" + (folderId == 0 ? "" : folderId), dialogsLoadOffsetChannelId); + editor.putLong("2dialogsLoadOffsetAccess" + (folderId == 0 ? "" : folderId), dialogsLoadOffsetAccess); + editor.putBoolean("hasValidDialogLoadIds", true); + editor.commit(); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java index e4bc26060..ce3c5c035 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java @@ -11,8 +11,8 @@ package org.telegram.messenger; import android.app.Service; import android.content.Intent; import android.os.IBinder; -import android.support.v4.app.NotificationCompat; -import android.support.v4.app.NotificationManagerCompat; +import androidx.core.app.NotificationCompat; +import androidx.core.app.NotificationManagerCompat; public class VideoEncodingService extends Service implements NotificationCenter.NotificationCenterDelegate { @@ -32,6 +32,7 @@ public class VideoEncodingService extends Service implements NotificationCenter. public void onDestroy() { stopForeground(true); + NotificationManagerCompat.from(ApplicationLoader.applicationContext).cancel(4); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.stopEncodingService); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.FileUploadProgressChanged); if (BuildVars.LOGS_ENABLED) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/WearDataLayerListenerService.java b/TMessagesProj/src/main/java/org/telegram/messenger/WearDataLayerListenerService.java index 2e85eddd6..06b02dc8d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/WearDataLayerListenerService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/WearDataLayerListenerService.java @@ -1,6 +1,6 @@ package org.telegram.messenger; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.text.TextUtils; import com.google.android.gms.common.api.GoogleApiClient; @@ -104,7 +104,7 @@ public class WearDataLayerListenerService extends WearableListenerService { @Override public void run() { NotificationCenter.getInstance(currentAccount).addObserver(listener, NotificationCenter.fileDidLoad); - FileLoader.getInstance(currentAccount).loadFile(user.photo.photo_small, user, null, 0, 1, 1); + FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForUser(user, false), user, null, 1, 1); } }); try { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/WearReplyReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/WearReplyReceiver.java index 7a8eeff8b..9412c42d2 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/WearReplyReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/WearReplyReceiver.java @@ -12,7 +12,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.support.v4.app.RemoteInput; +import androidx.core.app.RemoteInput; public class WearReplyReceiver extends BroadcastReceiver { 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 2617a3dd3..97bd03115 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java @@ -168,7 +168,7 @@ public class Browser { openUrl(context, Uri.parse(url), allowCustom, tryTelegraph); } - public static void openUrl(final Context context, final Uri uri, final boolean allowCustom, boolean tryTelegraph) { + public static void openUrl(final Context context, Uri uri, final boolean allowCustom, boolean tryTelegraph) { if (context == null || uri == null) { return; } @@ -181,6 +181,7 @@ public class Browser { if (host.equals("telegra.ph") || uri.toString().toLowerCase().contains("telegram.org/faq")) { final AlertDialog progressDialog[] = new AlertDialog[] {new AlertDialog(context, 3)}; + Uri finalUri = uri; TLRPC.TL_messages_getWebPagePreview req = new TLRPC.TL_messages_getWebPagePreview(); req.message = uri.toString(); final int reqId = ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { @@ -195,12 +196,12 @@ public class Browser { if (response instanceof TLRPC.TL_messageMediaWebPage) { TLRPC.TL_messageMediaWebPage webPage = (TLRPC.TL_messageMediaWebPage) response; if (webPage.webpage instanceof TLRPC.TL_webPage && webPage.webpage.cached_page != null) { - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.openArticle, webPage.webpage, uri.toString()); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.openArticle, webPage.webpage, finalUri.toString()); ok = true; } } if (!ok) { - openUrl(context, uri, allowCustom, false); + openUrl(context, finalUri, allowCustom, false); } })); AndroidUtilities.runOnUIThread(() -> { @@ -222,6 +223,13 @@ public class Browser { } try { String scheme = uri.getScheme() != null ? uri.getScheme().toLowerCase() : ""; + if ("http".equals(scheme) || "https".equals(scheme)) { + try { + uri = uri.normalizeScheme(); + } catch (Exception e) { + FileLog.e(e); + } + } if (allowCustom && SharedConfig.customTabs && !internalUri && !scheme.equals("tel")) { String browserPackageNames[] = null; try { @@ -310,6 +318,9 @@ public class Browser { } public static boolean isPassportUrl(String url) { + if (url == null) { + return false; + } try { url = url.toLowerCase(); if (url.startsWith("tg:passport") || url.startsWith("tg://passport") || url.startsWith("tg:secureid") || url.contains("resolve") && url.contains("domain=telegrampassport")) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java index c08405e3d..f48a31de8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java @@ -8,7 +8,6 @@ package org.telegram.messenger.camera; -import android.annotation.SuppressLint; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -58,7 +57,7 @@ public class CameraController implements MediaRecorder.OnInfoListener { protected ArrayList availableFlashModes = new ArrayList<>(); private MediaRecorder recorder; private String recordedFile; - protected ArrayList cameraInfos; + protected volatile ArrayList cameraInfos; private VideoTakeCallback onVideoTakeCallback; private boolean cameraInitied; private boolean loadingCameras; @@ -85,7 +84,7 @@ public class CameraController implements MediaRecorder.OnInfoListener { } public CameraController() { - threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, new LinkedBlockingQueue()); + threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); } public void cancelOnInitRunnable(final Runnable onInitRunnable) { @@ -100,153 +99,141 @@ public class CameraController implements MediaRecorder.OnInfoListener { return; } loadingCameras = true; - threadPool.execute(new Runnable() { - @Override - public void run() { - try { - if (cameraInfos == null) { - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - String cache = preferences.getString("cameraCache", null); - Comparator comparator = new Comparator() { - @Override - public int compare(Size o1, Size o2) { - if (o1.mWidth < o2.mWidth) { - return 1; - } else if (o1.mWidth > o2.mWidth) { - return -1; - } else { - if (o1.mHeight < o2.mHeight) { - return 1; - } else if (o1.mHeight > o2.mHeight) { - return -1; - } - return 0; - } - } - }; - ArrayList result = new ArrayList<>(); - if (cache != null) { - SerializedData serializedData = new SerializedData(Base64.decode(cache, Base64.DEFAULT)); - int count = serializedData.readInt32(false); - for (int a = 0; a < count; a++) { - CameraInfo cameraInfo = new CameraInfo(serializedData.readInt32(false), serializedData.readInt32(false)); - int pCount = serializedData.readInt32(false); - for (int b = 0; b < pCount; b++) { - cameraInfo.previewSizes.add(new Size(serializedData.readInt32(false), serializedData.readInt32(false))); - } - pCount = serializedData.readInt32(false); - for (int b = 0; b < pCount; b++) { - cameraInfo.pictureSizes.add(new Size(serializedData.readInt32(false), serializedData.readInt32(false))); - } - result.add(cameraInfo); - - Collections.sort(cameraInfo.previewSizes, comparator); - Collections.sort(cameraInfo.pictureSizes, comparator); - } - serializedData.cleanup(); + threadPool.execute(() -> { + try { + if (cameraInfos == null) { + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + String cache = preferences.getString("cameraCache", null); + Comparator comparator = (o1, o2) -> { + if (o1.mWidth < o2.mWidth) { + return 1; + } else if (o1.mWidth > o2.mWidth) { + return -1; } else { - int count = Camera.getNumberOfCameras(); - Camera.CameraInfo info = new Camera.CameraInfo(); - - int bufferSize = 4; - for (int cameraId = 0; cameraId < count; cameraId++) { - Camera.getCameraInfo(cameraId, info); - CameraInfo cameraInfo = new CameraInfo(cameraId, info.facing); - - if (ApplicationLoader.mainInterfacePaused && ApplicationLoader.externalInterfacePaused) { - throw new RuntimeException("app paused"); - } - Camera camera = Camera.open(cameraInfo.getCameraId()); - Camera.Parameters params = camera.getParameters(); - - List list = params.getSupportedPreviewSizes(); - for (int a = 0; a < list.size(); a++) { - Camera.Size size = list.get(a); - if (size.width == 1280 && size.height != 720) { - continue; - } - if (size.height < 2160 && size.width < 2160) { - cameraInfo.previewSizes.add(new Size(size.width, size.height)); - if (BuildVars.LOGS_ENABLED) { - FileLog.d("preview size = " + size.width + " " + size.height); - } - } - } - - list = params.getSupportedPictureSizes(); - for (int a = 0; a < list.size(); a++) { - Camera.Size size = list.get(a); - if (size.width == 1280 && size.height != 720) { - continue; - } - if (!"samsung".equals(Build.MANUFACTURER) || !"jflteuc".equals(Build.PRODUCT) || size.width < 2048) { - cameraInfo.pictureSizes.add(new Size(size.width, size.height)); - if (BuildVars.LOGS_ENABLED) { - FileLog.d("picture size = " + size.width + " " + size.height); - } - } - } - - camera.release(); - result.add(cameraInfo); - - Collections.sort(cameraInfo.previewSizes, comparator); - Collections.sort(cameraInfo.pictureSizes, comparator); - - bufferSize += 4 + 4 + 8 * (cameraInfo.previewSizes.size() + cameraInfo.pictureSizes.size()); + if (o1.mHeight < o2.mHeight) { + return 1; + } else if (o1.mHeight > o2.mHeight) { + return -1; } - - SerializedData serializedData = new SerializedData(bufferSize); - serializedData.writeInt32(result.size()); - for (int a = 0; a < count; a++) { - CameraInfo cameraInfo = result.get(a); - serializedData.writeInt32(cameraInfo.cameraId); - serializedData.writeInt32(cameraInfo.frontCamera); - - int pCount = cameraInfo.previewSizes.size(); - serializedData.writeInt32(pCount); - for (int b = 0; b < pCount; b++) { - Size size = cameraInfo.previewSizes.get(b); - serializedData.writeInt32(size.mWidth); - serializedData.writeInt32(size.mHeight); - } - pCount = cameraInfo.pictureSizes.size(); - serializedData.writeInt32(pCount); - for (int b = 0; b < pCount; b++) { - Size size = cameraInfo.pictureSizes.get(b); - serializedData.writeInt32(size.mWidth); - serializedData.writeInt32(size.mHeight); - } - } - preferences.edit().putString("cameraCache", Base64.encodeToString(serializedData.toByteArray(), Base64.DEFAULT)).commit(); - serializedData.cleanup(); + return 0; } - cameraInfos = result; + }; + ArrayList result = new ArrayList<>(); + if (cache != null) { + SerializedData serializedData = new SerializedData(Base64.decode(cache, Base64.DEFAULT)); + int count = serializedData.readInt32(false); + for (int a = 0; a < count; a++) { + CameraInfo cameraInfo = new CameraInfo(serializedData.readInt32(false), serializedData.readInt32(false)); + int pCount = serializedData.readInt32(false); + for (int b = 0; b < pCount; b++) { + cameraInfo.previewSizes.add(new Size(serializedData.readInt32(false), serializedData.readInt32(false))); + } + pCount = serializedData.readInt32(false); + for (int b = 0; b < pCount; b++) { + cameraInfo.pictureSizes.add(new Size(serializedData.readInt32(false), serializedData.readInt32(false))); + } + result.add(cameraInfo); + + Collections.sort(cameraInfo.previewSizes, comparator); + Collections.sort(cameraInfo.pictureSizes, comparator); + } + serializedData.cleanup(); + } else { + int count = Camera.getNumberOfCameras(); + Camera.CameraInfo info = new Camera.CameraInfo(); + + int bufferSize = 4; + for (int cameraId = 0; cameraId < count; cameraId++) { + Camera.getCameraInfo(cameraId, info); + CameraInfo cameraInfo = new CameraInfo(cameraId, info.facing); + + if (ApplicationLoader.mainInterfacePaused && ApplicationLoader.externalInterfacePaused) { + throw new RuntimeException("app paused"); + } + Camera camera = Camera.open(cameraInfo.getCameraId()); + Camera.Parameters params = camera.getParameters(); + + List list = params.getSupportedPreviewSizes(); + for (int a = 0; a < list.size(); a++) { + Camera.Size size = list.get(a); + if (size.width == 1280 && size.height != 720) { + continue; + } + if (size.height < 2160 && size.width < 2160) { + cameraInfo.previewSizes.add(new Size(size.width, size.height)); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("preview size = " + size.width + " " + size.height); + } + } + } + + list = params.getSupportedPictureSizes(); + for (int a = 0; a < list.size(); a++) { + Camera.Size size = list.get(a); + if (size.width == 1280 && size.height != 720) { + continue; + } + if (!"samsung".equals(Build.MANUFACTURER) || !"jflteuc".equals(Build.PRODUCT) || size.width < 2048) { + cameraInfo.pictureSizes.add(new Size(size.width, size.height)); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("picture size = " + size.width + " " + size.height); + } + } + } + + camera.release(); + result.add(cameraInfo); + + Collections.sort(cameraInfo.previewSizes, comparator); + Collections.sort(cameraInfo.pictureSizes, comparator); + + bufferSize += 4 + 4 + 8 * (cameraInfo.previewSizes.size() + cameraInfo.pictureSizes.size()); + } + + SerializedData serializedData = new SerializedData(bufferSize); + serializedData.writeInt32(result.size()); + for (int a = 0; a < count; a++) { + CameraInfo cameraInfo = result.get(a); + serializedData.writeInt32(cameraInfo.cameraId); + serializedData.writeInt32(cameraInfo.frontCamera); + + int pCount = cameraInfo.previewSizes.size(); + serializedData.writeInt32(pCount); + for (int b = 0; b < pCount; b++) { + Size size = cameraInfo.previewSizes.get(b); + serializedData.writeInt32(size.mWidth); + serializedData.writeInt32(size.mHeight); + } + pCount = cameraInfo.pictureSizes.size(); + serializedData.writeInt32(pCount); + for (int b = 0; b < pCount; b++) { + Size size = cameraInfo.pictureSizes.get(b); + serializedData.writeInt32(size.mWidth); + serializedData.writeInt32(size.mHeight); + } + } + preferences.edit().putString("cameraCache", Base64.encodeToString(serializedData.toByteArray(), Base64.DEFAULT)).commit(); + serializedData.cleanup(); } - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - loadingCameras = false; - cameraInitied = true; - if (!onFinishCameraInitRunnables.isEmpty()) { - for (int a = 0; a < onFinishCameraInitRunnables.size(); a++) { - onFinishCameraInitRunnables.get(a).run(); - } - onFinishCameraInitRunnables.clear(); - } - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.cameraInitied); - } - }); - } catch (Exception e) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - onFinishCameraInitRunnables.clear(); - loadingCameras = false; - cameraInitied = false; - } - }); + cameraInfos = result; } + AndroidUtilities.runOnUIThread(() -> { + loadingCameras = false; + cameraInitied = true; + if (!onFinishCameraInitRunnables.isEmpty()) { + for (int a = 0; a < onFinishCameraInitRunnables.size(); a++) { + onFinishCameraInitRunnables.get(a).run(); + } + onFinishCameraInitRunnables.clear(); + } + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.cameraInitied); + }); + } catch (Exception e) { + AndroidUtilities.runOnUIThread(() -> { + onFinishCameraInitRunnables.clear(); + loadingCameras = false; + cameraInitied = false; + }); } }); } @@ -257,32 +244,29 @@ public class CameraController implements MediaRecorder.OnInfoListener { public void close(final CameraSession session, final CountDownLatch countDownLatch, final Runnable beforeDestroyRunnable) { session.destroy(); - threadPool.execute(new Runnable() { - @Override - public void run() { - if (beforeDestroyRunnable != null) { - beforeDestroyRunnable.run(); - } - if (session.cameraInfo.camera == null) { - return; - } - try { - session.cameraInfo.camera.stopPreview(); - session.cameraInfo.camera.setPreviewCallbackWithBuffer(null); - } catch (Exception e) { - FileLog.e(e); - } - try { - session.cameraInfo.camera.release(); - } catch (Exception e) { - FileLog.e(e); - } - session.cameraInfo.camera = null; - if (countDownLatch != null) { - countDownLatch.countDown(); - } - } - }); + threadPool.execute(() -> { + if (beforeDestroyRunnable != null) { + beforeDestroyRunnable.run(); + } + if (session.cameraInfo.camera == null) { + return; + } + try { + session.cameraInfo.camera.stopPreview(); + session.cameraInfo.camera.setPreviewCallbackWithBuffer(null); + } catch (Exception e) { + FileLog.e(e); + } + try { + session.cameraInfo.camera.release(); + } catch (Exception e) { + FileLog.e(e); + } + session.cameraInfo.camera = null; + if (countDownLatch != null) { + countDownLatch.countDown(); + } + }); if (countDownLatch != null) { try { countDownLatch.await(); @@ -398,67 +382,64 @@ public class CameraController implements MediaRecorder.OnInfoListener { final boolean flipFront = session.isFlipFront(); Camera camera = info.camera; try { - camera.takePicture(null, null, new Camera.PictureCallback() { - @Override - public void onPictureTaken(byte[] data, Camera camera) { - Bitmap bitmap = null; - int size = (int) (AndroidUtilities.getPhotoSize() / AndroidUtilities.density); - String key = String.format(Locale.US, "%s@%d_%d", Utilities.MD5(path.getAbsolutePath()), size, size); - try { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeByteArray(data, 0, data.length, options); - float scaleFactor = Math.max((float) options.outWidth / AndroidUtilities.getPhotoSize(), (float) options.outHeight / AndroidUtilities.getPhotoSize()); - if (scaleFactor < 1) { - scaleFactor = 1; - } - options.inJustDecodeBounds = false; - options.inSampleSize = (int) scaleFactor; - options.inPurgeable = true; - bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options); - } catch (Throwable e) { - FileLog.e(e); + camera.takePicture(null, null, (data, camera1) -> { + Bitmap bitmap = null; + int size = (int) (AndroidUtilities.getPhotoSize() / AndroidUtilities.density); + String key = String.format(Locale.US, "%s@%d_%d", Utilities.MD5(path.getAbsolutePath()), size, size); + try { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeByteArray(data, 0, data.length, options); + float scaleFactor = Math.max((float) options.outWidth / AndroidUtilities.getPhotoSize(), (float) options.outHeight / AndroidUtilities.getPhotoSize()); + if (scaleFactor < 1) { + scaleFactor = 1; } - try { - if (info.frontCamera != 0 && flipFront) { - try { - Matrix matrix = new Matrix(); - matrix.setRotate(getOrientation(data)); - matrix.postScale(-1, 1); - Bitmap scaled = Bitmaps.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false); - if (scaled != bitmap) { - bitmap.recycle(); - } - FileOutputStream outputStream = new FileOutputStream(path); - scaled.compress(Bitmap.CompressFormat.JPEG, 80, outputStream); - outputStream.flush(); - outputStream.getFD().sync(); - outputStream.close(); - if (scaled != null) { - ImageLoader.getInstance().putImageToCache(new BitmapDrawable(scaled), key); - } - if (callback != null) { - callback.run(); - } - return; - } catch (Throwable e) { - FileLog.e(e); + options.inJustDecodeBounds = false; + options.inSampleSize = (int) scaleFactor; + options.inPurgeable = true; + bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options); + } catch (Throwable e) { + FileLog.e(e); + } + try { + if (info.frontCamera != 0 && flipFront) { + try { + Matrix matrix = new Matrix(); + matrix.setRotate(getOrientation(data)); + matrix.postScale(-1, 1); + Bitmap scaled = Bitmaps.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); + if (scaled != bitmap) { + bitmap.recycle(); } + FileOutputStream outputStream = new FileOutputStream(path); + scaled.compress(Bitmap.CompressFormat.JPEG, 80, outputStream); + outputStream.flush(); + outputStream.getFD().sync(); + outputStream.close(); + if (scaled != null) { + ImageLoader.getInstance().putImageToCache(new BitmapDrawable(scaled), key); + } + if (callback != null) { + callback.run(); + } + return; + } catch (Throwable e) { + FileLog.e(e); } - FileOutputStream outputStream = new FileOutputStream(path); - outputStream.write(data); - outputStream.flush(); - outputStream.getFD().sync(); - outputStream.close(); - if (bitmap != null) { - ImageLoader.getInstance().putImageToCache(new BitmapDrawable(bitmap), key); - } - } catch (Exception e) { - FileLog.e(e); } - if (callback != null) { - callback.run(); + FileOutputStream outputStream = new FileOutputStream(path); + outputStream.write(data); + outputStream.flush(); + outputStream.getFD().sync(); + outputStream.close(); + if (bitmap != null) { + ImageLoader.getInstance().putImageToCache(new BitmapDrawable(bitmap), key); } + } catch (Exception e) { + FileLog.e(e); + } + if (callback != null) { + callback.run(); } }); return true; @@ -472,23 +453,19 @@ public class CameraController implements MediaRecorder.OnInfoListener { if (session == null) { return; } - threadPool.execute(new Runnable() { - @SuppressLint("NewApi") - @Override - public void run() { - Camera camera = session.cameraInfo.camera; - try { - if (camera == null) { - camera = session.cameraInfo.camera = Camera.open(session.cameraInfo.cameraId); - } - camera.startPreview(); - } catch (Exception e) { - session.cameraInfo.camera = null; - if (camera != null) { - camera.release(); - } - FileLog.e(e); + threadPool.execute(() -> { + Camera camera = session.cameraInfo.camera; + try { + if (camera == null) { + camera = session.cameraInfo.camera = Camera.open(session.cameraInfo.cameraId); } + camera.startPreview(); + } catch (Exception e) { + session.cameraInfo.camera = null; + if (camera != null) { + camera.release(); + } + FileLog.e(e); } }); } @@ -497,23 +474,19 @@ public class CameraController implements MediaRecorder.OnInfoListener { if (session == null) { return; } - threadPool.execute(new Runnable() { - @SuppressLint("NewApi") - @Override - public void run() { - Camera camera = session.cameraInfo.camera; - try { - if (camera == null) { - camera = session.cameraInfo.camera = Camera.open(session.cameraInfo.cameraId); - } - camera.stopPreview(); - } catch (Exception e) { - session.cameraInfo.camera = null; - if (camera != null) { - camera.release(); - } - FileLog.e(e); + threadPool.execute(() -> { + Camera camera = session.cameraInfo.camera; + try { + if (camera == null) { + camera = session.cameraInfo.camera = Camera.open(session.cameraInfo.cameraId); } + camera.stopPreview(); + } catch (Exception e) { + session.cameraInfo.camera = null; + if (camera != null) { + camera.release(); + } + FileLog.e(e); } }); } @@ -525,39 +498,35 @@ public class CameraController implements MediaRecorder.OnInfoListener { } return; } - threadPool.execute(new Runnable() { - @SuppressLint("NewApi") - @Override - public void run() { - Camera camera = session.cameraInfo.camera; - try { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("start creating round camera session"); - } - if (camera == null) { - camera = session.cameraInfo.camera = Camera.open(session.cameraInfo.cameraId); - } - Camera.Parameters params = camera.getParameters(); - - session.configureRoundCamera(); - if (configureCallback != null) { - configureCallback.run(); - } - camera.setPreviewTexture(texture); - camera.startPreview(); - if (callback != null) { - AndroidUtilities.runOnUIThread(callback); - } - if (BuildVars.LOGS_ENABLED) { - FileLog.d("round camera session created"); - } - } catch (Exception e) { - session.cameraInfo.camera = null; - if (camera != null) { - camera.release(); - } - FileLog.e(e); + threadPool.execute(() -> { + Camera camera = session.cameraInfo.camera; + try { + if (BuildVars.LOGS_ENABLED) { + FileLog.d("start creating round camera session"); } + if (camera == null) { + camera = session.cameraInfo.camera = Camera.open(session.cameraInfo.cameraId); + } + Camera.Parameters params = camera.getParameters(); + + session.configureRoundCamera(); + if (configureCallback != null) { + configureCallback.run(); + } + camera.setPreviewTexture(texture); + camera.startPreview(); + if (callback != null) { + AndroidUtilities.runOnUIThread(callback); + } + if (BuildVars.LOGS_ENABLED) { + FileLog.d("round camera session created"); + } + } catch (Exception e) { + session.cameraInfo.camera = null; + if (camera != null) { + camera.release(); + } + FileLog.e(e); } }); } @@ -566,46 +535,42 @@ public class CameraController implements MediaRecorder.OnInfoListener { if (session == null || texture == null) { return; } - threadPool.execute(new Runnable() { - @SuppressLint("NewApi") - @Override - public void run() { - Camera camera = session.cameraInfo.camera; - try { - if (camera == null) { - camera = session.cameraInfo.camera = Camera.open(session.cameraInfo.cameraId); - } - Camera.Parameters params = camera.getParameters(); - List rawFlashModes = params.getSupportedFlashModes(); - - availableFlashModes.clear(); - if (rawFlashModes != null) { - for (int a = 0; a < rawFlashModes.size(); a++) { - String rawFlashMode = rawFlashModes.get(a); - if (rawFlashMode.equals(Camera.Parameters.FLASH_MODE_OFF) || rawFlashMode.equals(Camera.Parameters.FLASH_MODE_ON) || rawFlashMode.equals(Camera.Parameters.FLASH_MODE_AUTO)) { - availableFlashModes.add(rawFlashMode); - } - } - session.checkFlashMode(availableFlashModes.get(0)); - } - - if (prestartCallback != null) { - prestartCallback.run(); - } - - session.configurePhotoCamera(); - camera.setPreviewTexture(texture); - camera.startPreview(); - if (callback != null) { - AndroidUtilities.runOnUIThread(callback); - } - } catch (Exception e) { - session.cameraInfo.camera = null; - if (camera != null) { - camera.release(); - } - FileLog.e(e); + threadPool.execute(() -> { + Camera camera = session.cameraInfo.camera; + try { + if (camera == null) { + camera = session.cameraInfo.camera = Camera.open(session.cameraInfo.cameraId); } + Camera.Parameters params = camera.getParameters(); + List rawFlashModes = params.getSupportedFlashModes(); + + availableFlashModes.clear(); + if (rawFlashModes != null) { + for (int a = 0; a < rawFlashModes.size(); a++) { + String rawFlashMode = rawFlashModes.get(a); + if (rawFlashMode.equals(Camera.Parameters.FLASH_MODE_OFF) || rawFlashMode.equals(Camera.Parameters.FLASH_MODE_ON) || rawFlashMode.equals(Camera.Parameters.FLASH_MODE_AUTO)) { + availableFlashModes.add(rawFlashMode); + } + } + session.checkFlashMode(availableFlashModes.get(0)); + } + + if (prestartCallback != null) { + prestartCallback.run(); + } + + session.configurePhotoCamera(); + camera.setPreviewTexture(texture); + camera.startPreview(); + if (callback != null) { + AndroidUtilities.runOnUIThread(callback); + } + } catch (Exception e) { + session.cameraInfo.camera = null; + if (camera != null) { + camera.release(); + } + FileLog.e(e); } }); } @@ -617,53 +582,50 @@ public class CameraController implements MediaRecorder.OnInfoListener { final CameraInfo info = session.cameraInfo; final Camera camera = info.camera; - threadPool.execute(new Runnable() { - @Override - public void run() { - try { - if (camera != null) { - try { - Camera.Parameters params = camera.getParameters(); - params.setFlashMode(session.getCurrentFlashMode().equals(Camera.Parameters.FLASH_MODE_ON) ? Camera.Parameters.FLASH_MODE_TORCH : Camera.Parameters.FLASH_MODE_OFF); - camera.setParameters(params); - } catch (Exception e) { - FileLog.e(e); - } - camera.unlock(); - //camera.stopPreview(); - try { - recorder = new MediaRecorder(); - recorder.setCamera(camera); - recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); - recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); - session.configureRecorder(1, recorder); - recorder.setOutputFile(path.getAbsolutePath()); - recorder.setMaxFileSize(1024 * 1024 * 1024); - recorder.setVideoFrameRate(30); - recorder.setMaxDuration(0); - org.telegram.messenger.camera.Size pictureSize; - pictureSize = new Size(16, 9); - pictureSize = CameraController.chooseOptimalSize(info.getPictureSizes(), 720, 480, pictureSize); - recorder.setVideoEncodingBitRate(900000 * 2); - recorder.setVideoSize(pictureSize.getWidth(), pictureSize.getHeight()); - recorder.setOnInfoListener(CameraController.this); - recorder.prepare(); - recorder.start(); - - onVideoTakeCallback = callback; - recordedFile = path.getAbsolutePath(); - if (onVideoStartRecord != null) { - AndroidUtilities.runOnUIThread(onVideoStartRecord); - } - } catch (Exception e) { - recorder.release(); - recorder = null; - FileLog.e(e); - } + threadPool.execute(() -> { + try { + if (camera != null) { + try { + Camera.Parameters params = camera.getParameters(); + params.setFlashMode(session.getCurrentFlashMode().equals(Camera.Parameters.FLASH_MODE_ON) ? Camera.Parameters.FLASH_MODE_TORCH : Camera.Parameters.FLASH_MODE_OFF); + camera.setParameters(params); + } catch (Exception e) { + FileLog.e(e); + } + camera.unlock(); + //camera.stopPreview(); + try { + recorder = new MediaRecorder(); + recorder.setCamera(camera); + recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); + recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); + session.configureRecorder(1, recorder); + recorder.setOutputFile(path.getAbsolutePath()); + recorder.setMaxFileSize(1024 * 1024 * 1024); + recorder.setVideoFrameRate(30); + recorder.setMaxDuration(0); + Size pictureSize; + pictureSize = new Size(16, 9); + pictureSize = CameraController.chooseOptimalSize(info.getPictureSizes(), 720, 480, pictureSize); + recorder.setVideoEncodingBitRate(900000 * 2); + recorder.setVideoSize(pictureSize.getWidth(), pictureSize.getHeight()); + recorder.setOnInfoListener(CameraController.this); + recorder.prepare(); + recorder.start(); + + onVideoTakeCallback = callback; + recordedFile = path.getAbsolutePath(); + if (onVideoStartRecord != null) { + AndroidUtilities.runOnUIThread(onVideoStartRecord); + } + } catch (Exception e) { + recorder.release(); + recorder = null; + FileLog.e(e); } - } catch (Exception e) { - FileLog.e(e); } + } catch (Exception e) { + FileLog.e(e); } }); } @@ -694,23 +656,20 @@ public class CameraController implements MediaRecorder.OnInfoListener { final File cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); try { FileOutputStream stream = new FileOutputStream(cacheFile); - bitmap.compress(Bitmap.CompressFormat.JPEG, 55, stream); + bitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream); } catch (Throwable e) { FileLog.e(e); } SharedConfig.saveConfig(); final long durationFinal = duration; - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (onVideoTakeCallback != null) { - String path = cacheFile.getAbsolutePath(); - if (bitmap != null) { - ImageLoader.getInstance().putImageToCache(new BitmapDrawable(bitmap), Utilities.MD5(path)); - } - onVideoTakeCallback.onFinishVideoRecording(path, durationFinal); - onVideoTakeCallback = null; + AndroidUtilities.runOnUIThread(() -> { + if (onVideoTakeCallback != null) { + String path = cacheFile.getAbsolutePath(); + if (bitmap != null) { + ImageLoader.getInstance().putImageToCache(new BitmapDrawable(bitmap), Utilities.MD5(path)); } + onVideoTakeCallback.onFinishVideoRecording(path, durationFinal); + onVideoTakeCallback = null; } }); } @@ -731,63 +690,57 @@ public class CameraController implements MediaRecorder.OnInfoListener { } public void stopVideoRecording(final CameraSession session, final boolean abandon) { - threadPool.execute(new Runnable() { - @Override - public void run() { - try { - CameraInfo info = session.cameraInfo; - final Camera camera = info.camera; - if (camera != null && recorder != null) { - MediaRecorder tempRecorder = recorder; - recorder = null; - try { - tempRecorder.stop(); - } catch (Exception e) { - FileLog.e(e); - } - try { - tempRecorder.release(); - } catch (Exception e) { - FileLog.e(e); - } - try { - camera.reconnect(); - camera.startPreview(); - } catch (Exception e) { - FileLog.e(e); - } - try { - session.stopVideoRecording(); - } catch (Exception e) { - FileLog.e(e); - } + threadPool.execute(() -> { + try { + CameraInfo info = session.cameraInfo; + final Camera camera = info.camera; + if (camera != null && recorder != null) { + MediaRecorder tempRecorder = recorder; + recorder = null; + try { + tempRecorder.stop(); + } catch (Exception e) { + FileLog.e(e); } + try { + tempRecorder.release(); + } catch (Exception e) { + FileLog.e(e); + } + try { + camera.reconnect(); + camera.startPreview(); + } catch (Exception e) { + FileLog.e(e); + } + try { + session.stopVideoRecording(); + } catch (Exception e) { + FileLog.e(e); + } + } + try { + Camera.Parameters params = camera.getParameters(); + params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); + camera.setParameters(params); + } catch (Exception e) { + FileLog.e(e); + } + threadPool.execute(() -> { try { Camera.Parameters params = camera.getParameters(); - params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); + params.setFlashMode(session.getCurrentFlashMode()); camera.setParameters(params); } catch (Exception e) { FileLog.e(e); } - threadPool.execute(new Runnable() { - @Override - public void run() { - try { - Camera.Parameters params = camera.getParameters(); - params.setFlashMode(session.getCurrentFlashMode()); - camera.setParameters(params); - } catch (Exception e) { - FileLog.e(e); - } - } - }); - if (!abandon && onVideoTakeCallback != null) { - finishRecordingVideo(); - } else { - onVideoTakeCallback = null; - } - } catch (Exception ignore) { + }); + if (!abandon && onVideoTakeCallback != null) { + finishRecordingVideo(); + } else { + onVideoTakeCallback = null; } + } catch (Exception ignore) { } }); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/EncryptedFileDataSource.java b/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/EncryptedFileDataSource.java index 7dc7df1dc..752650f4c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/EncryptedFileDataSource.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/EncryptedFileDataSource.java @@ -9,7 +9,7 @@ package org.telegram.messenger.secretmedia; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.upstream.BaseDataSource; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSource.java b/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSource.java index 337f4322b..1e421d780 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSource.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/secretmedia/ExtendedDefaultDataSource.java @@ -10,7 +10,7 @@ package org.telegram.messenger.secretmedia; import android.content.Context; import android.net.Uri; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.upstream.AssetDataSource; import com.google.android.exoplayer2.upstream.ContentDataSource; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/JobIntentService.java b/TMessagesProj/src/main/java/org/telegram/messenger/support/JobIntentService.java index c3b767463..e25d61c75 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/JobIntentService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/support/JobIntentService.java @@ -29,9 +29,9 @@ import android.os.AsyncTask; import android.os.Build; import android.os.IBinder; import android.os.PowerManager; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.RequiresApi; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; import android.util.Log; import java.util.ArrayList; @@ -436,7 +436,7 @@ public abstract class JobIntentService extends Service { } /** - * Call this to enqueue work for your subclass of {@link android.support.v4.app.JobIntentService}. This will + * Call this to enqueue work for your subclass of {@link androidx.core.app.JobIntentService}. This will * either directly start the service (when running on pre-O platforms) or enqueue work * for it as a job (when running on O and later). In either case, a wake lock will be * held for you to ensure you continue running. The work you enqueue will ultimately diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsClient.java b/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsClient.java index 8c568e548..666c0a2b1 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsClient.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsClient.java @@ -27,7 +27,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.text.TextUtils; import java.util.ArrayList; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsIntent.java b/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsIntent.java index 28f40db3d..6aa5b161f 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsIntent.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsIntent.java @@ -24,13 +24,13 @@ import android.graphics.Bitmap; import android.graphics.Color; import android.net.Uri; import android.os.Bundle; -import android.support.annotation.AnimRes; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.ActivityOptionsCompat; -import android.support.v4.app.BundleCompat; -import android.support.v4.content.ContextCompat; +import androidx.annotation.AnimRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.app.ActivityOptionsCompat; +import androidx.core.app.BundleCompat; +import androidx.core.content.ContextCompat; import android.view.View; import android.widget.RemoteViews; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsService.java b/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsService.java index e3d4afb6f..9217ee09d 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsService.java @@ -23,8 +23,8 @@ import android.os.Bundle; import android.os.IBinder; import android.os.IBinder.DeathRecipient; import android.os.RemoteException; -import android.support.annotation.IntDef; -import android.support.v4.util.ArrayMap; +import androidx.annotation.IntDef; +import androidx.collection.ArrayMap; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsSession.java b/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsSession.java index c0de1c0cf..454746c09 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsSession.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsSession.java @@ -23,8 +23,8 @@ import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.view.View; import android.widget.RemoteViews; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsSessionToken.java b/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsSessionToken.java index 668a01320..cf2d99410 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsSessionToken.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/support/customtabs/CustomTabsSessionToken.java @@ -20,7 +20,7 @@ import android.content.Intent; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; -import android.support.v4.app.BundleCompat; +import androidx.core.app.BundleCompat; import android.util.Log; /** diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/fingerprint/FingerprintManagerCompat.java b/TMessagesProj/src/main/java/org/telegram/messenger/support/fingerprint/FingerprintManagerCompat.java index 13b15f4ac..3eccd2aa5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/fingerprint/FingerprintManagerCompat.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/support/fingerprint/FingerprintManagerCompat.java @@ -19,9 +19,9 @@ package org.telegram.messenger.support.fingerprint; import android.content.Context; import android.os.Build; import android.os.Handler; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.os.CancellationSignal; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.os.CancellationSignal; import java.security.Signature; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/PositionMap.java b/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/PositionMap.java deleted file mode 100644 index 529a348fe..000000000 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/PositionMap.java +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.telegram.messenger.support.widget; - -import java.util.ArrayList; - -/** - * Like a SparseArray, but with the ability to offset key ranges for bulk insertions/deletions. - */ -class PositionMap implements Cloneable { - private static final Object DELETED = new Object(); - private boolean mGarbage = false; - - private int[] mKeys; - private Object[] mValues; - private int mSize; - - /** - * Creates a new SparseArray containing no mappings. - */ - PositionMap() { - this(10); - } - - /** - * Creates a new PositionMap containing no mappings that will not - * require any additional memory allocation to store the specified - * number of mappings. If you supply an initial capacity of 0, the - * sparse array will be initialized with a light-weight representation - * not requiring any additional array allocations. - */ - PositionMap(int initialCapacity) { - if (initialCapacity == 0) { - mKeys = ContainerHelpers.EMPTY_INTS; - mValues = ContainerHelpers.EMPTY_OBJECTS; - } else { - initialCapacity = idealIntArraySize(initialCapacity); - mKeys = new int[initialCapacity]; - mValues = new Object[initialCapacity]; - } - mSize = 0; - } - - @Override - @SuppressWarnings("unchecked") - public PositionMap clone() { - PositionMap clone = null; - try { - clone = (PositionMap) super.clone(); - clone.mKeys = mKeys.clone(); - clone.mValues = mValues.clone(); - } catch (CloneNotSupportedException cnse) { - /* ignore */ - } - return clone; - } - - /** - * Gets the Object mapped from the specified key, or null - * if no such mapping has been made. - */ - public E get(int key) { - return get(key, null); - } - - /** - * Gets the Object mapped from the specified key, or the specified Object - * if no such mapping has been made. - */ - @SuppressWarnings("unchecked") - public E get(int key, E valueIfKeyNotFound) { - int i = ContainerHelpers.binarySearch(mKeys, mSize, key); - - if (i < 0 || mValues[i] == DELETED) { - return valueIfKeyNotFound; - } else { - return (E) mValues[i]; - } - } - - /** - * Removes the mapping from the specified key, if there was any. - */ - public void delete(int key) { - int i = ContainerHelpers.binarySearch(mKeys, mSize, key); - - if (i >= 0) { - if (mValues[i] != DELETED) { - mValues[i] = DELETED; - mGarbage = true; - } - } - } - - /** - * Alias for {@link #delete(int)}. - */ - public void remove(int key) { - delete(key); - } - - /** - * Removes the mapping at the specified index. - */ - public void removeAt(int index) { - if (mValues[index] != DELETED) { - mValues[index] = DELETED; - mGarbage = true; - } - } - - /** - * Remove a range of mappings as a batch. - * - * @param index Index to begin at - * @param size Number of mappings to remove - */ - public void removeAtRange(int index, int size) { - final int end = Math.min(mSize, index + size); - for (int i = index; i < end; i++) { - removeAt(i); - } - } - - public void insertKeyRange(int keyStart, int count) { - - } - - public void removeKeyRange(ArrayList removedItems, int keyStart, int count) { - - } - - private void gc() { - // Log.e("SparseArray", "gc start with " + mSize); - - int n = mSize; - int o = 0; - int[] keys = mKeys; - Object[] values = mValues; - - for (int i = 0; i < n; i++) { - Object val = values[i]; - - if (val != DELETED) { - if (i != o) { - keys[o] = keys[i]; - values[o] = val; - values[i] = null; - } - - o++; - } - } - - mGarbage = false; - mSize = o; - - // Log.e("SparseArray", "gc end with " + mSize); - } - - /** - * Adds a mapping from the specified key to the specified value, - * replacing the previous mapping from the specified key if there - * was one. - */ - public void put(int key, E value) { - int i = ContainerHelpers.binarySearch(mKeys, mSize, key); - - if (i >= 0) { - mValues[i] = value; - } else { - i = ~i; - - if (i < mSize && mValues[i] == DELETED) { - mKeys[i] = key; - mValues[i] = value; - return; - } - - if (mGarbage && mSize >= mKeys.length) { - gc(); - - // Search again because indices may have changed. - i = ~ContainerHelpers.binarySearch(mKeys, mSize, key); - } - - if (mSize >= mKeys.length) { - int n = idealIntArraySize(mSize + 1); - - int[] nkeys = new int[n]; - Object[] nvalues = new Object[n]; - - // Log.e("SparseArray", "grow " + mKeys.length + " to " + n); - System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length); - System.arraycopy(mValues, 0, nvalues, 0, mValues.length); - - mKeys = nkeys; - mValues = nvalues; - } - - if (mSize - i != 0) { - // Log.e("SparseArray", "move " + (mSize - i)); - System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i); - System.arraycopy(mValues, i, mValues, i + 1, mSize - i); - } - - mKeys[i] = key; - mValues[i] = value; - mSize++; - } - } - - /** - * Returns the number of key-value mappings that this SparseArray - * currently stores. - */ - public int size() { - if (mGarbage) { - gc(); - } - - return mSize; - } - - /** - * Given an index in the range 0...size()-1, returns - * the key from the indexth key-value mapping that this - * SparseArray stores. - */ - public int keyAt(int index) { - if (mGarbage) { - gc(); - } - - return mKeys[index]; - } - - /** - * Given an index in the range 0...size()-1, returns - * the value from the indexth key-value mapping that this - * SparseArray stores. - */ - @SuppressWarnings("unchecked") - public E valueAt(int index) { - if (mGarbage) { - gc(); - } - - return (E) mValues[index]; - } - - /** - * Given an index in the range 0...size()-1, sets a new - * value for the indexth key-value mapping that this - * SparseArray stores. - */ - public void setValueAt(int index, E value) { - if (mGarbage) { - gc(); - } - - mValues[index] = value; - } - - /** - * Returns the index for which {@link #keyAt} would return the - * specified key, or a negative number if the specified - * key is not mapped. - */ - public int indexOfKey(int key) { - if (mGarbage) { - gc(); - } - - return ContainerHelpers.binarySearch(mKeys, mSize, key); - } - - /** - * Returns an index for which {@link #valueAt} would return the - * specified key, or a negative number if no keys map to the - * specified value. - *

    Beware that this is a linear search, unlike lookups by key, - * and that multiple keys can map to the same value and this will - * find only one of them. - *

    Note also that unlike most collections' {@code indexOf} methods, - * this method compares values using {@code ==} rather than {@code equals}. - */ - public int indexOfValue(E value) { - if (mGarbage) { - gc(); - } - - for (int i = 0; i < mSize; i++) { - if (mValues[i] == value) { - return i; - } - } - - return -1; - } - - /** - * Removes all key-value mappings from this SparseArray. - */ - public void clear() { - int n = mSize; - Object[] values = mValues; - - for (int i = 0; i < n; i++) { - values[i] = null; - } - - mSize = 0; - mGarbage = false; - } - - /** - * Puts a key/value pair into the array, optimizing for the case where - * the key is greater than all existing keys in the array. - */ - public void append(int key, E value) { - if (mSize != 0 && key <= mKeys[mSize - 1]) { - put(key, value); - return; - } - - if (mGarbage && mSize >= mKeys.length) { - gc(); - } - - int pos = mSize; - if (pos >= mKeys.length) { - int n = idealIntArraySize(pos + 1); - - int[] nkeys = new int[n]; - Object[] nvalues = new Object[n]; - - // Log.e("SparseArray", "grow " + mKeys.length + " to " + n); - System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length); - System.arraycopy(mValues, 0, nvalues, 0, mValues.length); - - mKeys = nkeys; - mValues = nvalues; - } - - mKeys[pos] = key; - mValues[pos] = value; - mSize = pos + 1; - } - - /** - * {@inheritDoc} - * - *

    This implementation composes a string by iterating over its mappings. If - * this map contains itself as a value, the string "(this Map)" - * will appear in its place. - */ - @Override - public String toString() { - if (size() <= 0) { - return "{}"; - } - - StringBuilder buffer = new StringBuilder(mSize * 28); - buffer.append('{'); - for (int i = 0; i < mSize; i++) { - if (i > 0) { - buffer.append(", "); - } - int key = keyAt(i); - buffer.append(key); - buffer.append('='); - Object value = valueAt(i); - if (value != this) { - buffer.append(value); - } else { - buffer.append("(this Map)"); - } - } - buffer.append('}'); - return buffer.toString(); - } - - static int idealByteArraySize(int need) { - for (int i = 4; i < 32; i++) { - if (need <= (1 << i) - 12) { - return (1 << i) - 12; - } - } - - return need; - } - - static int idealBooleanArraySize(int need) { - return idealByteArraySize(need); - } - - static int idealShortArraySize(int need) { - return idealByteArraySize(need * 2) / 2; - } - - static int idealCharArraySize(int need) { - return idealByteArraySize(need * 2) / 2; - } - - static int idealIntArraySize(int need) { - return idealByteArraySize(need * 4) / 4; - } - - static int idealFloatArraySize(int need) { - return idealByteArraySize(need * 4) / 4; - } - - static int idealObjectArraySize(int need) { - return idealByteArraySize(need * 4) / 4; - } - - static int idealLongArraySize(int need) { - return idealByteArraySize(need * 8) / 8; - } - - static class ContainerHelpers { - static final boolean[] EMPTY_BOOLEANS = new boolean[0]; - static final int[] EMPTY_INTS = new int[0]; - static final long[] EMPTY_LONGS = new long[0]; - static final Object[] EMPTY_OBJECTS = new Object[0]; - - // This is Arrays.binarySearch(), but doesn't do any argument validation. - static int binarySearch(int[] array, int size, int value) { - int lo = 0; - int hi = size - 1; - - while (lo <= hi) { - final int mid = (lo + hi) >>> 1; - final int midVal = array[mid]; - - if (midVal < value) { - lo = mid + 1; - } else if (midVal > value) { - hi = mid - 1; - } else { - return mid; // value found - } - } - return ~lo; // value not present - } - } - -} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/helper/ItemTouchUIUtilImpl.java b/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/helper/ItemTouchUIUtilImpl.java deleted file mode 100644 index 05a39a4a2..000000000 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/helper/ItemTouchUIUtilImpl.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.telegram.messenger.support.widget.helper; - -import android.graphics.Canvas; -import android.support.v4.view.ViewCompat; -import org.telegram.messenger.support.widget.RecyclerView; -import android.view.View; - -/** - * Package private class to keep implementations. Putting them inside ItemTouchUIUtil makes them - * public API, which is not desired in this case. - */ -class ItemTouchUIUtilImpl { - static class Api21Impl extends BaseImpl { - @Override - public void onDraw(Canvas c, RecyclerView recyclerView, View view, - float dX, float dY, int actionState, boolean isCurrentlyActive) { - if (isCurrentlyActive) { - Object originalElevation = view.getTag(); - if (originalElevation == null) { - originalElevation = ViewCompat.getElevation(view); - float newElevation = 1f + findMaxElevation(recyclerView, view); - ViewCompat.setElevation(view, newElevation); - view.setTag(originalElevation); - } - } - super.onDraw(c, recyclerView, view, dX, dY, actionState, isCurrentlyActive); - } - - private float findMaxElevation(RecyclerView recyclerView, View itemView) { - final int childCount = recyclerView.getChildCount(); - float max = 0; - for (int i = 0; i < childCount; i++) { - final View child = recyclerView.getChildAt(i); - if (child == itemView) { - continue; - } - final float elevation = ViewCompat.getElevation(child); - if (elevation > max) { - max = elevation; - } - } - return max; - } - - @Override - public void clearView(View view) { - final Object tag = view.getTag(); - if (tag != null && tag instanceof Float) { - ViewCompat.setElevation(view, (Float) tag); - } - view.setTag(null); - super.clearView(view); - } - } - - static class BaseImpl implements ItemTouchUIUtil { - - @Override - public void clearView(View view) { - view.setTranslationX(0f); - view.setTranslationY(0f); - } - - @Override - public void onSelected(View view) { - - } - - @Override - public void onDraw(Canvas c, RecyclerView recyclerView, View view, - float dX, float dY, int actionState, boolean isCurrentlyActive) { - view.setTranslationX(dX); - view.setTranslationY(dY); - } - - @Override - public void onDrawOver(Canvas c, RecyclerView recyclerView, - View view, float dX, float dY, int actionState, boolean isCurrentlyActive) { - - } - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/MP4Builder.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/MP4Builder.java index 4487bbe8d..c39d396d8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/MP4Builder.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/MP4Builder.java @@ -61,6 +61,7 @@ public class MP4Builder { private HashMap track2SampleSizes = new HashMap<>(); private ByteBuffer sizeBuffer = null; private boolean splitMdat; + private boolean wasFirstVideoFrame; public MP4Builder createMovie(Mp4Movie mp4Movie, boolean split) throws Exception { currentMp4Movie = mp4Movie; @@ -102,6 +103,34 @@ public class MP4Builder { writeNewMdat = false; } + /*if (writeLength && !wasFirstVideoFrame) { + wasFirstVideoFrame = true; + byte[] buff = new byte[bufferInfo.size]; + byteBuf.position(bufferInfo.offset); + byteBuf.limit(bufferInfo.offset + bufferInfo.size); + byteBuf.get(buff); + + ByteBuffer nativeBuffer = ByteBuffer.allocateDirect(bufferInfo.size); + nativeBuffer.position(4); + int indexOfNal = -1; + int totalLen = 0; + for (int a = 0, N = buff.length - 3; a < N; a++) { + if (buff[a] == 0 && buff[a + 1] == 0 && buff[a + 2] == 0 && buff[a + 3] == 1 || a == N - 1) { + if (indexOfNal != -1) { + int len = a - indexOfNal - 4; + nativeBuffer.put(buff, indexOfNal, len); + totalLen += len; + } + indexOfNal = a; + } + } + nativeBuffer.position(0); + nativeBuffer.putInt(totalLen); + bufferInfo.offset = 0; + bufferInfo.size = totalLen + 4; + byteBuf = nativeBuffer; + }*/ + mdat.setContentSize(mdat.getContentSize() + bufferInfo.size); wroteSinceLastMdat += bufferInfo.size; @@ -116,17 +145,20 @@ public class MP4Builder { } currentMp4Movie.addSample(trackIndex, dataOffset, bufferInfo); - byteBuf.position(bufferInfo.offset + (!writeLength ? 0 : 4)); - byteBuf.limit(bufferInfo.offset + bufferInfo.size); if (writeLength) { sizeBuffer.position(0); sizeBuffer.putInt(bufferInfo.size - 4); sizeBuffer.position(0); fc.write(sizeBuffer); - } + byteBuf.position(bufferInfo.offset + 4); + } else { + byteBuf.position(bufferInfo.offset); + } + byteBuf.limit(bufferInfo.offset + bufferInfo.size); fc.write(byteBuf); + dataOffset += bufferInfo.size; if (flush) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/voip/AudioRecordJNI.java b/TMessagesProj/src/main/java/org/telegram/messenger/voip/AudioRecordJNI.java index cc6bce24f..e3d8523b4 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/voip/AudioRecordJNI.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/voip/AudioRecordJNI.java @@ -19,7 +19,6 @@ import android.os.Build; import android.text.TextUtils; import org.telegram.messenger.BuildVars; -import org.telegram.messenger.FileLog; import java.nio.ByteBuffer; import java.util.regex.Pattern; @@ -67,14 +66,10 @@ public class AudioRecordJNI { if(agc!=null) agc.setEnabled(false); }else{ - if (BuildVars.LOGS_ENABLED) { - FileLog.w("AutomaticGainControl is not available on this device :("); - } + VLog.w("AutomaticGainControl is not available on this device :("); } }catch(Throwable x){ - if (BuildVars.LOGS_ENABLED) { - FileLog.e("error creating AutomaticGainControl", x); - } + VLog.e("error creating AutomaticGainControl", x); } try{ if(NoiseSuppressor.isAvailable()){ @@ -82,14 +77,10 @@ public class AudioRecordJNI { if(ns!=null) ns.setEnabled(VoIPServerConfig.getBoolean("use_system_ns", true) && isGoodAudioEffect(ns)); }else{ - if (BuildVars.LOGS_ENABLED) { - FileLog.w("NoiseSuppressor is not available on this device :("); - } + VLog.w("NoiseSuppressor is not available on this device :("); } }catch(Throwable x){ - if (BuildVars.LOGS_ENABLED) { - FileLog.e("error creating NoiseSuppressor", x); - } + VLog.e("error creating NoiseSuppressor", x); } try{ if(AcousticEchoCanceler.isAvailable()){ @@ -97,14 +88,10 @@ public class AudioRecordJNI { if(aec!=null) aec.setEnabled(VoIPServerConfig.getBoolean("use_system_aec", true) && isGoodAudioEffect(aec)); }else{ - if (BuildVars.LOGS_ENABLED) { - FileLog.w("AcousticEchoCanceler is not available on this device"); - } + VLog.w("AcousticEchoCanceler is not available on this device"); } }catch(Throwable x){ - if (BuildVars.LOGS_ENABLED) { - FileLog.e("error creating AcousticEchoCanceler", x); - } + VLog.e("error creating AcousticEchoCanceler", x); } } @@ -117,14 +104,12 @@ public class AudioRecordJNI { audioRecord.release(); }catch(Exception ignore){} } - if (BuildVars.LOGS_ENABLED) { - FileLog.d("Trying to initialize AudioRecord with source=" + source + " and sample rate=" + sampleRate); - } + VLog.i("Trying to initialize AudioRecord with source=" + source + " and sample rate=" + sampleRate); int size = getBufferSize(bufferSize, 48000); try{ audioRecord=new AudioRecord(source, sampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, size); }catch(Exception x){ - FileLog.e("AudioRecord init failed!", x); + VLog.e("AudioRecord init failed!", x); } needResampling=sampleRate!=48000; return audioRecord!=null && audioRecord.getState()==AudioRecord.STATE_INITIALIZED; @@ -143,7 +128,7 @@ public class AudioRecordJNI { try{ thread.join(); }catch(InterruptedException e){ - FileLog.e(e); + VLog.e(e); } thread = null; } @@ -179,9 +164,7 @@ public class AudioRecordJNI { } return true; }catch(Exception x){ - if (BuildVars.LOGS_ENABLED) { - FileLog.e("Error initializing AudioRecord", x); - } + VLog.e("Error initializing AudioRecord", x); } return false; } @@ -209,11 +192,10 @@ public class AudioRecordJNI { } nativeCallback(buffer); } catch (Exception e) { - FileLog.e(e); + VLog.e(e); } } - if(BuildVars.LOGS_ENABLED) - FileLog.d("audiorecord thread exits"); + VLog.i("audiorecord thread exits"); } }); thread.start(); @@ -235,7 +217,7 @@ public class AudioRecordJNI { try{ return Pattern.compile(r); }catch(Exception x){ - FileLog.e(x); + VLog.e(x); return null; } } @@ -243,7 +225,7 @@ public class AudioRecordJNI { private static boolean isGoodAudioEffect(AudioEffect effect){ Pattern globalImpl=makeNonEmptyRegex("adsp_good_impls"), globalName=makeNonEmptyRegex("adsp_good_names"); AudioEffect.Descriptor desc=effect.getDescriptor(); - FileLog.d(effect.getClass().getSimpleName()+": implementor="+desc.implementor+", name="+desc.name); + VLog.d(effect.getClass().getSimpleName()+": implementor="+desc.implementor+", name="+desc.name); if(globalImpl!=null && globalImpl.matcher(desc.implementor).find()){ return true; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/voip/AudioTrackJNI.java b/TMessagesProj/src/main/java/org/telegram/messenger/voip/AudioTrackJNI.java index 8df4e425b..8b1dc7d5e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/voip/AudioTrackJNI.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/voip/AudioTrackJNI.java @@ -2,16 +2,7 @@ package org.telegram.messenger.voip; import android.media.AudioFormat; import android.media.AudioManager; -import android.media.AudioRecord; import android.media.AudioTrack; -import android.media.MediaRecorder; -import android.media.audiofx.AutomaticGainControl; -import android.media.audiofx.NoiseSuppressor; -import android.os.Build; -import android.util.Log; - -import org.telegram.messenger.BuildVars; -import org.telegram.messenger.FileLog; import java.nio.ByteBuffer; @@ -44,13 +35,12 @@ public class AudioTrackJNI{ this.bufferSize = bufferSize; audioTrack=new AudioTrack(AudioManager.STREAM_VOICE_CALL, 48000, channels==1 ? AudioFormat.CHANNEL_OUT_MONO : AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, size, AudioTrack.MODE_STREAM); if(audioTrack.getState()!=AudioTrack.STATE_INITIALIZED){ + VLog.w("Error initializing AudioTrack with 48k, trying 44.1k with resampling"); try{ audioTrack.release(); }catch(Throwable ignore){} size=getBufferSize(bufferSize*6, 44100); - if (BuildVars.LOGS_ENABLED) { - FileLog.d("buffer size: " + size); - } + VLog.d("buffer size: " + size); audioTrack=new AudioTrack(AudioManager.STREAM_VOICE_CALL, 44100, channels==1 ? AudioFormat.CHANNEL_OUT_MONO : AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, size, AudioTrack.MODE_STREAM); needResampling=true; } @@ -73,7 +63,7 @@ public class AudioTrackJNI{ try{ thread.join(); }catch(InterruptedException e){ - FileLog.e(e); + VLog.e(e); } thread=null; } @@ -102,9 +92,7 @@ public class AudioTrackJNI{ try{ audioTrack.play(); }catch(Exception x){ - if (BuildVars.LOGS_ENABLED) { - FileLog.e("error starting AudioTrack", x); - } + VLog.e("error starting AudioTrack", x); return; } ByteBuffer tmp48=needResampling ? ByteBuffer.allocateDirect(960*2) : null; @@ -128,10 +116,10 @@ public class AudioTrackJNI{ break; } } catch (Exception e) { - FileLog.e(e); + VLog.e(e); } } - Log.i("tg-voip", "audiotrack thread exits"); + VLog.i("audiotrack thread exits"); } }); thread.start(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/voip/CallNotificationSoundProvider.java b/TMessagesProj/src/main/java/org/telegram/messenger/voip/CallNotificationSoundProvider.java index e2940fdb4..3cf7e5e76 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/voip/CallNotificationSoundProvider.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/voip/CallNotificationSoundProvider.java @@ -5,8 +5,8 @@ import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.ParcelFileDescriptor; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import org.telegram.messenger.ApplicationLoader; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/voip/VLog.java b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VLog.java new file mode 100644 index 000000000..b4f52561e --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VLog.java @@ -0,0 +1,31 @@ +package org.telegram.messenger.voip; + +import android.text.TextUtils; + +import java.io.PrintWriter; +import java.io.StringWriter; + +class VLog{ + public native static void v(String msg); + public native static void d(String msg); + public native static void i(String msg); + public native static void w(String msg); + public native static void e(String msg); + + public static void e(Throwable x){ + e(null, x); + } + + public static void e(String msg, Throwable x){ + StringWriter sw=new StringWriter(); + if(!TextUtils.isEmpty(msg)){ + sw.append(msg); + sw.append(": "); + } + PrintWriter pw=new PrintWriter(sw); + x.printStackTrace(pw); + String[] lines=sw.toString().split("\n"); + for(String line:lines) + e(line); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPBaseService.java b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPBaseService.java index 58dfdb691..ad5d44ad4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPBaseService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPBaseService.java @@ -1046,7 +1046,7 @@ public abstract class VoIPBaseService extends Service implements SensorEventList NotificationChannel existingChannel=nm.getNotificationChannel("incoming_calls2"+chanIndex); boolean needCreate=true; if(existingChannel!=null){ - if(existingChannel.getImportance()= Build.VERSION_CODES.JELLY_BEAN_MR1) { builder.setShowWhen(false); @@ -1409,7 +1409,7 @@ public abstract class VoIPBaseService extends Service implements SensorEventList PhoneAccountHandle handle=new PhoneAccountHandle(new ComponentName(this, TelegramConnectionService.class), ""+self.id); PhoneAccount account=new PhoneAccount.Builder(handle, ContactsController.formatName(self.first_name, self.last_name)) .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED) - .setIcon(Icon.createWithResource(this, R.drawable.ic_launcher)) + .setIcon(Icon.createWithResource(this, R.drawable.ic_launcher_dr)) .setHighlightColor(0xff2ca5e0) .addSupportedUriScheme("sip") .build(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java index b9cb105df..cb8f12618 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java @@ -14,19 +14,15 @@ import android.app.Activity; import android.app.KeyguardManager; import android.app.Notification; import android.app.PendingIntent; -import android.content.ComponentName; import android.content.Intent; import android.content.SharedPreferences; -import android.graphics.drawable.Icon; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.IBinder; -import android.support.annotation.Nullable; -import android.support.v4.app.NotificationManagerCompat; -import android.telecom.Connection; -import android.telecom.PhoneAccount; -import android.telecom.PhoneAccountHandle; +import androidx.annotation.Nullable; +import androidx.core.app.NotificationManagerCompat; + import android.telecom.TelecomManager; import android.text.TextUtils; import android.view.KeyEvent; @@ -34,7 +30,6 @@ import android.widget.Toast; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; -import org.telegram.messenger.BuildConfig; import org.telegram.messenger.BuildVars; import org.telegram.messenger.ContactsController; import org.telegram.messenger.FileLog; @@ -44,7 +39,6 @@ import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.NotificationsController; import org.telegram.messenger.R; -import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.messenger.XiaomiUtilities; import org.telegram.tgnet.ConnectionsManager; @@ -992,10 +986,7 @@ public class VoIPService extends VoIPBaseService{ controller.setConfig(MessagesController.getInstance(currentAccount).callPacketTimeout / 1000.0, MessagesController.getInstance(currentAccount).callConnectTimeout / 1000.0, convertDataSavingMode(preferences.getInt("VoipDataSaving", VoIPHelper.getDataSavingDefault())), call.id); controller.setEncryptionKey(authKey, isOutgoing); - TLRPC.TL_phoneConnection[] endpoints = new TLRPC.TL_phoneConnection[1 + call.alternative_connections.size()]; - endpoints[0] = call.connection; - for (int i = 0; i < call.alternative_connections.size(); i++) - endpoints[i + 1] = call.alternative_connections.get(i); + TLRPC.TL_phoneConnection[] endpoints=call.connections.toArray(new TLRPC.TL_phoneConnection[call.connections.size()]); SharedPreferences prefs=MessagesController.getGlobalMainSettings(); diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java index 411f532e5..12d72f633 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java @@ -42,8 +42,8 @@ import java.net.URLConnection; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; -import java.util.HashMap; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; public class ConnectionsManager { @@ -102,12 +102,7 @@ public class ConnectionsManager { } } - private static ThreadLocal> dnsCache = new ThreadLocal>() { - @Override - protected HashMap initialValue() { - return new HashMap<>(); - } - }; + private static ConcurrentHashMap dnsCache = new ConcurrentHashMap<>(); private static int lastClassGuid = 1; @@ -492,70 +487,14 @@ public class ConnectionsManager { AndroidUtilities.runOnUIThread(() -> NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needShowAlert, 3)); } - public static String getHostByName(String domain, final int currentAccount) { - HashMap cache = dnsCache.get(); - ResolvedDomain resolvedDomain = cache.get(domain); + public static void getHostByName(String hostName, long address) { + ResolvedDomain resolvedDomain = dnsCache.get(hostName); if (resolvedDomain != null && SystemClock.elapsedRealtime() - resolvedDomain.ttl < 5 * 60 * 1000) { - return resolvedDomain.getAddress(); + native_onHostNameResolved(hostName, address, resolvedDomain.getAddress()); + } else { + ResolveHostByNameTask task = new ResolveHostByNameTask(address, hostName); + task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null); } - - ByteArrayOutputStream outbuf = null; - InputStream httpConnectionStream = null; - try { - URL downloadUrl = new URL("https://www.google.com/resolve?name=" + domain + "&type=A"); - URLConnection httpConnection = downloadUrl.openConnection(); - httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.38 (KHTML, like Gecko) Version/10.0 Mobile/14A5297c Safari/602.1"); - httpConnection.addRequestProperty("Host", "dns.google.com"); - httpConnection.setConnectTimeout(1000); - httpConnection.setReadTimeout(2000); - httpConnection.connect(); - httpConnectionStream = httpConnection.getInputStream(); - - outbuf = new ByteArrayOutputStream(); - - byte[] data = new byte[1024 * 32]; - while (true) { - int read = httpConnectionStream.read(data); - if (read > 0) { - outbuf.write(data, 0, read); - } else if (read == -1) { - break; - } else { - break; - } - } - - JSONObject jsonObject = new JSONObject(new String(outbuf.toByteArray())); - JSONArray array = jsonObject.getJSONArray("Answer"); - int len = array.length(); - if (len > 0) { - ArrayList addresses = new ArrayList<>(len); - for (int a = 0; a < len; a++) { - addresses.add(array.getJSONObject(a).getString("data")); - } - ResolvedDomain newResolvedDomain = new ResolvedDomain(addresses, SystemClock.elapsedRealtime()); - cache.put(domain, newResolvedDomain); - return newResolvedDomain.getAddress(); - } - } catch (Throwable e) { - FileLog.e(e); - } finally { - try { - if (httpConnectionStream != null) { - httpConnectionStream.close(); - } - } catch (Throwable e) { - FileLog.e(e); - } - try { - if (outbuf != null) { - outbuf.close(); - } - } catch (Exception ignore) { - - } - } - return ""; } public static void onBytesReceived(int amount, int networkType, final int currentAccount) { @@ -635,7 +574,10 @@ public class ConnectionsManager { public static native void native_setPushConnectionEnabled(int currentAccount, boolean value); public static native void native_applyDnsConfig(int currentAccount, long address, String phone); public static native long native_checkProxy(int currentAccount, String address, int port, String username, String password, String secret, RequestTimeDelegate requestTimeDelegate); + public static native void native_onHostNameResolved(String host, long address, String ip); + + //void onHostNameResolved(JNIEnv *env, jclass c, jlong address, jstring ip) public static int generateClassGuid() { return lastClassGuid++; } @@ -725,6 +667,95 @@ public class ConnectionsManager { return false; } + private static class ResolveHostByNameTask extends AsyncTask { + + private long currentAddress; + private String currentHostName; + + public ResolveHostByNameTask(long address, String hostName) { + super(); + currentAddress = address; + currentHostName = hostName; + } + + protected String doInBackground(Void... voids) { + ByteArrayOutputStream outbuf = null; + InputStream httpConnectionStream = null; + boolean done = false; + try { + URL downloadUrl = new URL("https://www.google.com/resolve?name=" + currentHostName + "&type=A"); + URLConnection httpConnection = downloadUrl.openConnection(); + httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.38 (KHTML, like Gecko) Version/10.0 Mobile/14A5297c Safari/602.1"); + httpConnection.addRequestProperty("Host", "dns.google.com"); + httpConnection.setConnectTimeout(1000); + httpConnection.setReadTimeout(2000); + httpConnection.connect(); + httpConnectionStream = httpConnection.getInputStream(); + + outbuf = new ByteArrayOutputStream(); + + byte[] data = new byte[1024 * 32]; + while (true) { + int read = httpConnectionStream.read(data); + if (read > 0) { + outbuf.write(data, 0, read); + } else if (read == -1) { + break; + } else { + break; + } + } + + JSONObject jsonObject = new JSONObject(new String(outbuf.toByteArray())); + if (jsonObject.has("Answer")) { + JSONArray array = jsonObject.getJSONArray("Answer"); + int len = array.length(); + if (len > 0) { + ArrayList addresses = new ArrayList<>(len); + for (int a = 0; a < len; a++) { + addresses.add(array.getJSONObject(a).getString("data")); + } + ResolvedDomain newResolvedDomain = new ResolvedDomain(addresses, SystemClock.elapsedRealtime()); + dnsCache.put(currentHostName, newResolvedDomain); + return newResolvedDomain.getAddress(); + } + } + done = true; + } catch (Throwable e) { + FileLog.e(e); + } finally { + try { + if (httpConnectionStream != null) { + httpConnectionStream.close(); + } + } catch (Throwable e) { + FileLog.e(e); + } + try { + if (outbuf != null) { + outbuf.close(); + } + } catch (Exception ignore) { + + } + } + if (!done) { + try { + InetAddress address = InetAddress.getByName(currentHostName); + return address.getHostAddress(); + } catch (Exception e) { + FileLog.e(e); + } + } + return ""; + } + + @Override + protected void onPostExecute(final String result) { + native_onHostNameResolved(currentHostName, currentAddress, result); + } + } + private static class DnsTxtLoadTask extends AsyncTask { private int currentAccount; @@ -781,7 +812,7 @@ public class ConnectionsManager { } } - JSONObject jsonObject = new JSONObject(new String(outbuf.toByteArray(), "UTF-8")); + JSONObject jsonObject = new JSONObject(new String(outbuf.toByteArray())); JSONArray array = jsonObject.getJSONArray("Answer"); len = array.length(); ArrayList arrayList = new ArrayList<>(len); diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index 76f7ca7d8..c38551bfc 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -59,7 +59,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 = 96; + public static final int LAYER = 99; public static class TL_chatBannedRights extends TLObject { public static int constructor = 0x9f120418; @@ -240,53 +240,76 @@ public class TLRPC { } public static abstract class ChatPhoto extends TLObject { - public FileLocation photo_small; - public FileLocation photo_big; - public static ChatPhoto TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - ChatPhoto result = null; - switch (constructor) { - case 0x37c1011c: - result = new TL_chatPhotoEmpty(); - break; - case 0x6153276a: - result = new TL_chatPhoto(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in ChatPhoto", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } + public FileLocation photo_small; + public FileLocation photo_big; + public int dc_id; - public static class TL_chatPhotoEmpty extends ChatPhoto { - public static int constructor = 0x37c1011c; + public static ChatPhoto TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + ChatPhoto result = null; + switch (constructor) { + case 0x37c1011c: + result = new TL_chatPhotoEmpty(); + break; + case 0x6153276a: + result = new TL_chatPhoto_layer97(); + break; + case 0x475cdbd5: + result = new TL_chatPhoto(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in ChatPhoto", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_chatPhotoEmpty extends ChatPhoto { + public static int constructor = 0x37c1011c; - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } - public static class TL_chatPhoto extends ChatPhoto { - public static int constructor = 0x6153276a; + public static class TL_chatPhoto_layer97 extends TL_chatPhoto { + public static int constructor = 0x6153276a; - public void readParams(AbstractSerializedData stream, boolean exception) { - photo_small = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); - photo_big = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); - } + public void readParams(AbstractSerializedData stream, boolean exception) { + photo_small = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + photo_big = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - photo_small.serializeToStream(stream); - photo_big.serializeToStream(stream); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + photo_small.serializeToStream(stream); + photo_big.serializeToStream(stream); + } + } + + public static class TL_chatPhoto extends ChatPhoto { + public static int constructor = 0x475cdbd5; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + photo_small = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + photo_big = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + dc_id = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + photo_small.serializeToStream(stream); + photo_big.serializeToStream(stream); + stream.writeInt32(dc_id); + } + } public static class TL_help_termsOfService extends TLObject { public static int constructor = 0x780a0310; @@ -509,6 +532,62 @@ public class TLRPC { } } + public static class TL_emojiKeywordsDifference extends TLObject { + public static int constructor = 0x5cc761bd; + + public String lang_code; + public int from_version; + public int version; + public ArrayList keywords = new ArrayList<>(); + + public static TL_emojiKeywordsDifference TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_emojiKeywordsDifference.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_emojiKeywordsDifference", constructor)); + } else { + return null; + } + } + TL_emojiKeywordsDifference result = new TL_emojiKeywordsDifference(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + lang_code = stream.readString(exception); + from_version = stream.readInt32(exception); + version = 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++) { + EmojiKeyword object = EmojiKeyword.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + keywords.add(object); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(lang_code); + stream.writeInt32(from_version); + stream.writeInt32(version); + stream.writeInt32(0x1cb5c415); + int count = keywords.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + keywords.get(a).serializeToStream(stream); + } + } + } + public static abstract class messages_SentEncryptedMessage extends TLObject { public int date; public EncryptedFile file; @@ -1657,57 +1736,57 @@ public class TLRPC { } } - public static abstract class DialogPeer extends TLObject { + public static abstract class DialogPeer extends TLObject { - public static DialogPeer TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - DialogPeer result = null; - switch (constructor) { - case 0xe56dbf05: - result = new TL_dialogPeer(); - break; - case 0xda429411: - result = new TL_dialogPeerFeed(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in DialogPeer", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } + public static DialogPeer TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + DialogPeer result = null; + switch (constructor) { + case 0xe56dbf05: + result = new TL_dialogPeer(); + break; + case 0x514519e2: + result = new TL_dialogPeerFolder(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in DialogPeer", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } - public static class TL_dialogPeer extends DialogPeer { - public static int constructor = 0xe56dbf05; + public static class TL_dialogPeer extends DialogPeer { + public static int constructor = 0xe56dbf05; - public Peer peer; + public Peer peer; - public void readParams(AbstractSerializedData stream, boolean exception) { - peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - } + public void readParams(AbstractSerializedData stream, boolean exception) { + peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + } + } - public static class TL_dialogPeerFeed extends DialogPeer { - public static int constructor = 0xda429411; + public static class TL_dialogPeerFolder extends DialogPeer { + public static int constructor = 0x514519e2; - public int feed_id; + public int folder_id; - public void readParams(AbstractSerializedData stream, boolean exception) { - feed_id = stream.readInt32(exception); - } + public void readParams(AbstractSerializedData stream, boolean exception) { + folder_id = stream.readInt32(exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(feed_id); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(folder_id); + } + } public static class TL_auth_authorization extends TLObject { public static int constructor = 0xcd050916; @@ -1989,6 +2068,56 @@ public class TLRPC { } } + public static class TL_folder extends TLObject { + public static int constructor = 0xff544e65; + + public int flags; + public boolean autofill_new_broadcasts; + public boolean autofill_public_groups; + public boolean autofill_new_correspondents; + public int id; + public String title; + public ChatPhoto photo; + + public static TL_folder TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_folder.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_folder", constructor)); + } else { + return null; + } + } + TL_folder result = new TL_folder(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + autofill_new_broadcasts = (flags & 1) != 0; + autofill_public_groups = (flags & 2) != 0; + autofill_new_correspondents = (flags & 4) != 0; + id = stream.readInt32(exception); + title = stream.readString(exception); + if ((flags & 8) != 0) { + photo = ChatPhoto.TLdeserialize(stream, stream.readInt32(exception), exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = autofill_new_broadcasts ? (flags | 1) : (flags &~ 1); + flags = autofill_public_groups ? (flags | 2) : (flags &~ 2); + flags = autofill_new_correspondents ? (flags | 4) : (flags &~ 4); + stream.writeInt32(flags); + stream.writeInt32(id); + stream.writeString(title); + if ((flags & 8) != 0) { + photo.serializeToStream(stream); + } + } + } + public static abstract class messages_Messages extends TLObject { public ArrayList messages = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); @@ -3377,6 +3506,12 @@ public class TLRPC { case 0x3d662b7b: result = new TL_privacyKeyPhoneCall(); break; + case 0x69ec56a3: + result = new TL_privacyKeyForwards(); + break; + case 0x96151fed: + result = new TL_privacyKeyProfilePhoto(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in PrivacyKey", constructor)); @@ -3419,6 +3554,24 @@ public class TLRPC { public static int constructor = 0x3d662b7b; + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_privacyKeyForwards extends PrivacyKey { + public static int constructor = 0x69ec56a3; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_privacyKeyProfilePhoto extends PrivacyKey { + public static int constructor = 0x96151fed; + + public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); } @@ -3564,104 +3717,105 @@ public class TLRPC { } } - public static abstract class ChatInvite extends TLObject { - public int flags; - public boolean channel; - public boolean broadcast; - public boolean isPublic; - public boolean megagroup; - public String title; - public ChatPhoto photo; - public int participants_count; - public ArrayList participants = new ArrayList<>(); - public Chat chat; + public static abstract class ChatInvite extends TLObject { - public static ChatInvite TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - ChatInvite result = null; - switch (constructor) { - case 0xdb74f558: - result = new TL_chatInvite(); - break; - case 0x5a686d7c: - result = new TL_chatInviteAlready(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in ChatInvite", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } + public int flags; + public boolean channel; + public boolean broadcast; + public boolean isPublic; + public boolean megagroup; + public String title; + public Photo photo; + public int participants_count; + public ArrayList participants = new ArrayList<>(); + public Chat chat; - public static class TL_chatInvite extends ChatInvite { - public static int constructor = 0xdb74f558; + public static ChatInvite TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + ChatInvite result = null; + switch (constructor) { + case 0xdfc2f58e: + result = new TL_chatInvite(); + break; + case 0x5a686d7c: + result = new TL_chatInviteAlready(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in ChatInvite", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_chatInvite extends ChatInvite { + public static int constructor = 0xdfc2f58e; - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - channel = (flags & 1) != 0; - broadcast = (flags & 2) != 0; - isPublic = (flags & 4) != 0; - megagroup = (flags & 8) != 0; - title = stream.readString(exception); - photo = ChatPhoto.TLdeserialize(stream, stream.readInt32(exception), exception); - participants_count = stream.readInt32(exception); - if ((flags & 16) != 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++) { - User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - participants.add(object); - } - } - } + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + channel = (flags & 1) != 0; + broadcast = (flags & 2) != 0; + isPublic = (flags & 4) != 0; + megagroup = (flags & 8) != 0; + title = stream.readString(exception); + photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + participants_count = stream.readInt32(exception); + if ((flags & 16) != 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++) { + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + participants.add(object); + } + } + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = channel ? (flags | 1) : (flags &~ 1); - flags = broadcast ? (flags | 2) : (flags &~ 2); - flags = isPublic ? (flags | 4) : (flags &~ 4); - flags = megagroup ? (flags | 8) : (flags &~ 8); - stream.writeInt32(flags); - stream.writeString(title); - photo.serializeToStream(stream); - stream.writeInt32(participants_count); - if ((flags & 16) != 0) { - stream.writeInt32(0x1cb5c415); - int count = participants.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - participants.get(a).serializeToStream(stream); - } - } - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = channel ? (flags | 1) : (flags &~ 1); + flags = broadcast ? (flags | 2) : (flags &~ 2); + flags = isPublic ? (flags | 4) : (flags &~ 4); + flags = megagroup ? (flags | 8) : (flags &~ 8); + stream.writeInt32(flags); + stream.writeString(title); + photo.serializeToStream(stream); + stream.writeInt32(participants_count); + if ((flags & 16) != 0) { + stream.writeInt32(0x1cb5c415); + int count = participants.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + participants.get(a).serializeToStream(stream); + } + } + } + } - public static class TL_chatInviteAlready extends ChatInvite { - public static int constructor = 0x5a686d7c; + public static class TL_chatInviteAlready extends ChatInvite { + public static int constructor = 0x5a686d7c; - public void readParams(AbstractSerializedData stream, boolean exception) { - chat = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); - } + public void readParams(AbstractSerializedData stream, boolean exception) { + chat = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - chat.serializeToStream(stream); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + chat.serializeToStream(stream); + } + } public static class TL_inputGroupCall extends TLObject { public static int constructor = 0xd8aa840f; @@ -4417,57 +4571,57 @@ public class TLRPC { } } - public static abstract class InputDialogPeer extends TLObject { + public static abstract class InputDialogPeer extends TLObject { - public static InputDialogPeer TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - InputDialogPeer result = null; - switch (constructor) { - case 0xfcaafeb7: - result = new TL_inputDialogPeer(); - break; - case 0x2c38b8cf: - result = new TL_inputDialogPeerFeed(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in InputDialogPeer", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } + public static InputDialogPeer TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + InputDialogPeer result = null; + switch (constructor) { + case 0xfcaafeb7: + result = new TL_inputDialogPeer(); + break; + case 0x64600527: + result = new TL_inputDialogPeerFolder(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in InputDialogPeer", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } - public static class TL_inputDialogPeer extends InputDialogPeer { - public static int constructor = 0xfcaafeb7; + public static class TL_inputDialogPeer extends InputDialogPeer { + public static int constructor = 0xfcaafeb7; - public InputPeer peer; + public InputPeer peer; - public void readParams(AbstractSerializedData stream, boolean exception) { - peer = InputPeer.TLdeserialize(stream, stream.readInt32(exception), exception); - } + public void readParams(AbstractSerializedData stream, boolean exception) { + peer = InputPeer.TLdeserialize(stream, stream.readInt32(exception), exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + } + } - public static class TL_inputDialogPeerFeed extends InputDialogPeer { - public static int constructor = 0x2c38b8cf; + public static class TL_inputDialogPeerFolder extends InputDialogPeer { + public static int constructor = 0x64600527; - public int feed_id; + public int folder_id; - public void readParams(AbstractSerializedData stream, boolean exception) { - feed_id = stream.readInt32(exception); - } + public void readParams(AbstractSerializedData stream, boolean exception) { + folder_id = stream.readInt32(exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(feed_id); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(folder_id); + } + } public static abstract class FoundGif extends TLObject { public String url; @@ -7122,6 +7276,12 @@ public class TLRPC { case 0xfabadc5f: result = new TL_inputPrivacyKeyPhoneCall(); break; + case 0xa4dd4c08: + result = new TL_inputPrivacyKeyForwards(); + break; + case 0x5719bacc: + result = new TL_inputPrivacyKeyProfilePhoto(); + break; case 0xdb9e70d2: result = new TL_inputPrivacyKeyPhoneP2P(); break; @@ -7163,6 +7323,24 @@ public class TLRPC { } } + public static class TL_inputPrivacyKeyForwards extends InputPrivacyKey { + public static int constructor = 0xa4dd4c08; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_inputPrivacyKeyProfilePhoto extends InputPrivacyKey { + public static int constructor = 0x5719bacc; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class TL_inputPrivacyKeyPhoneP2P extends InputPrivacyKey { public static int constructor = 0xdb9e70d2; @@ -7328,6 +7506,7 @@ public class TLRPC { public int pinned_msg_id; public int kicked_count; public int unread_important_count; + public int folder_id; public boolean can_set_stickers; public boolean hidden_prehistory; public boolean can_view_stats; @@ -7336,11 +7515,15 @@ public class TLRPC { public StickerSet stickerset; public int available_min_id; public int call_msg_id; + public int pts; public static ChatFull TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { ChatFull result = null; switch (constructor) { case 0x1c87a71a: + result = new TL_channelFull_layer98(); + break; + case 0x3648977: result = new TL_channelFull(); break; case 0x2e02a614: @@ -7361,9 +7544,12 @@ public class TLRPC { case 0x9e341ddf: result = new TL_channelFull_layer48(); break; - case 0x22a235da: + case 0x1b7c9db3: result = new TL_chatFull(); break; + case 0x22a235da: + result = new TL_chatFull_layer98(); + break; case 0xedd2a791: result = new TL_chatFull_layer92(); break; @@ -7388,6 +7574,135 @@ public class TLRPC { } public static class TL_channelFull extends ChatFull { + public static int constructor = 0x3648977; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + can_view_participants = (flags & 8) != 0; + can_set_username = (flags & 64) != 0; + can_set_stickers = (flags & 128) != 0; + hidden_prehistory = (flags & 1024) != 0; + can_view_stats = (flags & 4096) != 0; + id = stream.readInt32(exception); + about = stream.readString(exception); + if ((flags & 1) != 0) { + participants_count = stream.readInt32(exception); + } + if ((flags & 2) != 0) { + admins_count = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + kicked_count = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + banned_count = stream.readInt32(exception); + } + if ((flags & 8192) != 0) { + online_count = stream.readInt32(exception); + } + read_inbox_max_id = stream.readInt32(exception); + read_outbox_max_id = stream.readInt32(exception); + unread_count = stream.readInt32(exception); + chat_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); + exported_invite = ExportedChatInvite.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++) { + BotInfo object = BotInfo.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + bot_info.add(object); + } + if ((flags & 16) != 0) { + migrated_from_chat_id = stream.readInt32(exception); + } + if ((flags & 16) != 0) { + migrated_from_max_id = stream.readInt32(exception); + } + if ((flags & 32) != 0) { + pinned_msg_id = stream.readInt32(exception); + } + if ((flags & 256) != 0) { + stickerset = StickerSet.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 512) != 0) { + available_min_id = stream.readInt32(exception); + } + if ((flags & 2048) != 0) { + folder_id = stream.readInt32(exception); + } + pts = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = can_view_participants ? (flags | 8) : (flags &~ 8); + flags = can_set_username ? (flags | 64) : (flags &~ 64); + flags = can_set_stickers ? (flags | 128) : (flags &~ 128); + flags = hidden_prehistory ? (flags | 1024) : (flags &~ 1024); + flags = can_view_stats ? (flags | 4096) : (flags &~ 4096); + stream.writeInt32(flags); + stream.writeInt32(id); + stream.writeString(about); + if ((flags & 1) != 0) { + stream.writeInt32(participants_count); + } + if ((flags & 2) != 0) { + stream.writeInt32(admins_count); + } + if ((flags & 4) != 0) { + stream.writeInt32(kicked_count); + } + if ((flags & 4) != 0) { + stream.writeInt32(banned_count); + } + if ((flags & 8192) != 0) { + stream.writeInt32(online_count); + } + stream.writeInt32(read_inbox_max_id); + stream.writeInt32(read_outbox_max_id); + stream.writeInt32(unread_count); + chat_photo.serializeToStream(stream); + notify_settings.serializeToStream(stream); + exported_invite.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = bot_info.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + bot_info.get(a).serializeToStream(stream); + } + if ((flags & 16) != 0) { + stream.writeInt32(migrated_from_chat_id); + } + if ((flags & 16) != 0) { + stream.writeInt32(migrated_from_max_id); + } + if ((flags & 32) != 0) { + stream.writeInt32(pinned_msg_id); + } + if ((flags & 256) != 0) { + stickerset.serializeToStream(stream); + } + if ((flags & 512) != 0) { + stream.writeInt32(available_min_id); + } + if ((flags & 2048) != 0) { + stream.writeInt32(folder_id); + } + stream.writeInt32(pts); + } + } + + public static class TL_channelFull_layer98 extends TL_channelFull { public static int constructor = 0x1c87a71a; @@ -7889,6 +8204,75 @@ public class TLRPC { } public static class TL_chatFull extends ChatFull { + public static int constructor = 0x1b7c9db3; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + can_set_username = (flags & 128) != 0; + id = stream.readInt32(exception); + about = stream.readString(exception); + participants = ChatParticipants.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 4) != 0) { + chat_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + } + notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); + exported_invite = ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 8) != 0) { + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + BotInfo object = BotInfo.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + bot_info.add(object); + } + } + if ((flags & 64) != 0) { + pinned_msg_id = stream.readInt32(exception); + } + if ((flags & 2048) != 0) { + folder_id = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = can_set_username ? (flags | 128) : (flags &~ 128); + stream.writeInt32(flags); + stream.writeInt32(id); + stream.writeString(about); + participants.serializeToStream(stream); + if ((flags & 4) != 0) { + chat_photo.serializeToStream(stream); + } + notify_settings.serializeToStream(stream); + exported_invite.serializeToStream(stream); + if ((flags & 8) != 0) { + stream.writeInt32(0x1cb5c415); + int count = bot_info.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + bot_info.get(a).serializeToStream(stream); + } + } + if ((flags & 64) != 0) { + stream.writeInt32(pinned_msg_id); + } + if ((flags & 2048) != 0) { + stream.writeInt32(folder_id); + } + } + } + + public static class TL_chatFull_layer98 extends TL_chatFull { public static int constructor = 0x22a235da; @@ -10904,80 +11288,64 @@ public class TLRPC { } } - public static abstract class InputFileLocation extends TLObject { - public long id; - public long access_hash; - public long volume_id; - public int local_id; - public long secret; - public byte[] file_reference; + public static abstract class InputFileLocation extends TLObject { - public static InputFileLocation TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - InputFileLocation result = null; - switch (constructor) { - case 0xcbc7ee28: - result = new TL_inputSecureFileLocation(); - break; - case 0xf5235d55: - result = new TL_inputEncryptedFileLocation(); - break; - case 0x196683d9: + public long id; + public long access_hash; + public byte[] file_reference; + public String thumb_size; + public int flags; + public boolean big; + public InputPeer peer; + public long volume_id; + public int local_id; + public InputStickerSet stickerset; + public long secret; + + public static InputFileLocation TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + InputFileLocation result = null; + switch (constructor) { + case 0x40181ffe: + result = new TL_inputPhotoFileLocation(); + break; + case 0xbad07584: result = new TL_inputDocumentFileLocation(); break; - case 0xdfdaabe1: - result = new TL_inputFileLocation(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in InputFileLocation", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } + case 0x27d69997: + result = new TL_inputPeerPhotoFileLocation(); + break; + case 0xf5235d55: + result = new TL_inputEncryptedFileLocation(); + break; + case 0xdbaeae9: + result = new TL_inputStickerSetThumb(); + break; + case 0xdfdaabe1: + result = new TL_inputFileLocation(); + break; + case 0xcbc7ee28: + result = new TL_inputSecureFileLocation(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in InputFileLocation", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } - public static class TL_inputSecureFileLocation extends InputFileLocation { - public static int constructor = 0xcbc7ee28; - - - 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 class TL_inputEncryptedFileLocation extends InputFileLocation { - public static int constructor = 0xf5235d55; - - - 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 class TL_inputDocumentFileLocation extends InputFileLocation { - public static int constructor = 0x196683d9; + public static class TL_inputPhotoFileLocation extends InputFileLocation { + public static int constructor = 0x40181ffe; public void readParams(AbstractSerializedData stream, boolean exception) { id = stream.readInt64(exception); access_hash = stream.readInt64(exception); file_reference = stream.readByteArray(exception); + thumb_size = stream.readString(exception); } public void serializeToStream(AbstractSerializedData stream) { @@ -10985,28 +11353,121 @@ public class TLRPC { stream.writeInt64(id); stream.writeInt64(access_hash); stream.writeByteArray(file_reference); + stream.writeString(thumb_size); } } - public static class TL_inputFileLocation extends InputFileLocation { - public static int constructor = 0xdfdaabe1; + public static class TL_inputDocumentFileLocation extends InputFileLocation { + public static int constructor = 0xbad07584; - public void readParams(AbstractSerializedData stream, boolean exception) { - volume_id = stream.readInt64(exception); - local_id = stream.readInt32(exception); - secret = stream.readInt64(exception); - file_reference = stream.readByteArray(exception); - } + public void readParams(AbstractSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + file_reference = stream.readByteArray(exception); + thumb_size = stream.readString(exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(volume_id); - stream.writeInt32(local_id); - stream.writeInt64(secret); - stream.writeByteArray(file_reference); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeByteArray(file_reference); + stream.writeString(thumb_size); + } + } + + public static class TL_inputPeerPhotoFileLocation extends InputFileLocation { + public static int constructor = 0x27d69997; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + big = (flags & 1) != 0; + peer = InputPeer.TLdeserialize(stream, stream.readInt32(exception), exception); + volume_id = stream.readInt64(exception); + local_id = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = big ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + peer.serializeToStream(stream); + stream.writeInt64(volume_id); + stream.writeInt32(local_id); + } + } + + public static class TL_inputEncryptedFileLocation extends InputFileLocation { + public static int constructor = 0xf5235d55; + + + 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 class TL_inputStickerSetThumb extends InputFileLocation { + public static int constructor = 0xdbaeae9; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + stickerset = InputStickerSet.TLdeserialize(stream, stream.readInt32(exception), exception); + volume_id = stream.readInt64(exception); + local_id = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stickerset.serializeToStream(stream); + stream.writeInt64(volume_id); + stream.writeInt32(local_id); + } + } + + public static class TL_inputFileLocation extends InputFileLocation { + public static int constructor = 0xdfdaabe1; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + volume_id = stream.readInt64(exception); + local_id = stream.readInt32(exception); + secret = stream.readInt64(exception); + file_reference = stream.readByteArray(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(volume_id); + stream.writeInt32(local_id); + stream.writeInt64(secret); + stream.writeByteArray(file_reference); + } + } + + public static class TL_inputSecureFileLocation extends InputFileLocation { + public static int constructor = 0xcbc7ee28; + + + 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 class TL_photos_photo extends TLObject { public static int constructor = 0x20212ca8; @@ -11114,41 +11575,42 @@ public class TLRPC { } public static abstract class PhoneCall extends TLObject { + + public int flags; + public boolean p2p_allowed; public long id; public long access_hash; public int date; public int admin_id; public int participant_id; - public byte[] g_b; - public TL_phoneCallProtocol protocol; - public int flags; - public boolean p2p_allowed; public byte[] g_a_or_b; public long key_fingerprint; - public TL_phoneConnection connection; - public ArrayList alternative_connections = new ArrayList<>(); + public TL_phoneCallProtocol protocol; + public ArrayList connections = new ArrayList<>(); public int start_date; - public byte[] g_a_hash; - public int receive_date; public boolean need_rating; public boolean need_debug; + public boolean video; public PhoneCallDiscardReason reason; public int duration; + public byte[] g_a_hash; + public byte[] g_b; + public int receive_date; public static PhoneCall TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { PhoneCall result = null; switch (constructor) { - case 0x6d003d3f: - result = new TL_phoneCallAccepted(); - break; - case 0xe6f9ddf3: - result = new TL_phoneCall(); - break; - case 0x83761ce4: + case 0x87eabb53: result = new TL_phoneCallRequested(); break; - case 0xffe6ab67: - result = new TL_phoneCall_layer86(); + case 0x8742ae7f: + result = new TL_phoneCall(); + break; + case 0x5366c915: + result = new TL_phoneCallEmpty(); + break; + case 0x997c454a: + result = new TL_phoneCallAccepted(); break; case 0x1b8f4ad1: result = new TL_phoneCallWaiting(); @@ -11156,9 +11618,6 @@ public class TLRPC { case 0x50ca4de1: result = new TL_phoneCallDiscarded(); break; - case 0x5366c915: - result = new TL_phoneCallEmpty(); - break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in PhoneCall", constructor)); @@ -11170,34 +11629,38 @@ public class TLRPC { } } - public static class TL_phoneCallAccepted extends PhoneCall { - public static int constructor = 0x6d003d3f; + public static class TL_phoneCallRequested extends PhoneCall { + public static int constructor = 0x87eabb53; public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + video = (flags & 32) != 0; id = stream.readInt64(exception); access_hash = stream.readInt64(exception); date = stream.readInt32(exception); admin_id = stream.readInt32(exception); participant_id = stream.readInt32(exception); - g_b = stream.readByteArray(exception); + g_a_hash = stream.readByteArray(exception); protocol = TL_phoneCallProtocol.TLdeserialize(stream, stream.readInt32(exception), exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + flags = video ? (flags | 32) : (flags &~ 32); + stream.writeInt32(flags); stream.writeInt64(id); stream.writeInt64(access_hash); stream.writeInt32(date); stream.writeInt32(admin_id); stream.writeInt32(participant_id); - stream.writeByteArray(g_b); + stream.writeByteArray(g_a_hash); protocol.serializeToStream(stream); } } public static class TL_phoneCall extends PhoneCall { - public static int constructor = 0xe6f9ddf3; + public static int constructor = 0x8742ae7f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -11211,7 +11674,6 @@ public class TLRPC { g_a_or_b = stream.readByteArray(exception); key_fingerprint = stream.readInt64(exception); protocol = TL_phoneCallProtocol.TLdeserialize(stream, stream.readInt32(exception), exception); - connection = TL_phoneConnection.TLdeserialize(stream, stream.readInt32(exception), exception); int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { if (exception) { @@ -11225,7 +11687,7 @@ public class TLRPC { if (object == null) { return; } - alternative_connections.add(object); + connections.add(object); } start_date = stream.readInt32(exception); } @@ -11242,93 +11704,57 @@ public class TLRPC { stream.writeByteArray(g_a_or_b); stream.writeInt64(key_fingerprint); protocol.serializeToStream(stream); - connection.serializeToStream(stream); stream.writeInt32(0x1cb5c415); - int count = alternative_connections.size(); + int count = connections.size(); stream.writeInt32(count); for (int a = 0; a < count; a++) { - alternative_connections.get(a).serializeToStream(stream); + connections.get(a).serializeToStream(stream); } stream.writeInt32(start_date); } } - public static class TL_phoneCallRequested extends PhoneCall { - public static int constructor = 0x83761ce4; + public static class TL_phoneCallEmpty extends PhoneCall { + public static int constructor = 0x5366c915; public void readParams(AbstractSerializedData stream, boolean exception) { id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - date = stream.readInt32(exception); - admin_id = stream.readInt32(exception); - participant_id = stream.readInt32(exception); - g_a_hash = stream.readByteArray(exception); - protocol = TL_phoneCallProtocol.TLdeserialize(stream, stream.readInt32(exception), exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeInt32(date); - stream.writeInt32(admin_id); - stream.writeInt32(participant_id); - stream.writeByteArray(g_a_hash); - protocol.serializeToStream(stream); } } - public static class TL_phoneCall_layer86 extends TL_phoneCall { - public static int constructor = 0xffe6ab67; + public static class TL_phoneCallAccepted extends PhoneCall { + public static int constructor = 0x997c454a; public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + video = (flags & 32) != 0; id = stream.readInt64(exception); access_hash = stream.readInt64(exception); date = stream.readInt32(exception); admin_id = stream.readInt32(exception); participant_id = stream.readInt32(exception); - g_a_or_b = stream.readByteArray(exception); - key_fingerprint = stream.readInt64(exception); + g_b = stream.readByteArray(exception); protocol = TL_phoneCallProtocol.TLdeserialize(stream, stream.readInt32(exception), exception); - connection = TL_phoneConnection.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++) { - TL_phoneConnection object = TL_phoneConnection.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - alternative_connections.add(object); - } - start_date = stream.readInt32(exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + flags = video ? (flags | 32) : (flags &~ 32); + stream.writeInt32(flags); stream.writeInt64(id); stream.writeInt64(access_hash); stream.writeInt32(date); stream.writeInt32(admin_id); stream.writeInt32(participant_id); - stream.writeByteArray(g_a_or_b); - stream.writeInt64(key_fingerprint); + stream.writeByteArray(g_b); protocol.serializeToStream(stream); - connection.serializeToStream(stream); - stream.writeInt32(0x1cb5c415); - int count = alternative_connections.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - alternative_connections.get(a).serializeToStream(stream); - } - stream.writeInt32(start_date); } } @@ -11338,6 +11764,7 @@ public class TLRPC { public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); + video = (flags & 32) != 0; id = stream.readInt64(exception); access_hash = stream.readInt64(exception); date = stream.readInt32(exception); @@ -11351,6 +11778,7 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + flags = video ? (flags | 32) : (flags &~ 32); stream.writeInt32(flags); stream.writeInt64(id); stream.writeInt64(access_hash); @@ -11372,6 +11800,7 @@ public class TLRPC { flags = stream.readInt32(exception); need_rating = (flags & 4) != 0; need_debug = (flags & 8) != 0; + video = (flags & 32) != 0; id = stream.readInt64(exception); if ((flags & 1) != 0) { reason = PhoneCallDiscardReason.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -11385,6 +11814,7 @@ public class TLRPC { stream.writeInt32(constructor); flags = need_rating ? (flags | 4) : (flags &~ 4); flags = need_debug ? (flags | 8) : (flags &~ 8); + flags = video ? (flags | 32) : (flags &~ 32); stream.writeInt32(flags); stream.writeInt64(id); if ((flags & 1) != 0) { @@ -11396,20 +11826,6 @@ public class TLRPC { } } - public static class TL_phoneCallEmpty extends PhoneCall { - public static int constructor = 0x5366c915; - - - public void readParams(AbstractSerializedData stream, boolean exception) { - id = stream.readInt64(exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(id); - } - } - public static abstract class User extends TLObject { public int id; public String first_name; @@ -11432,6 +11848,7 @@ public class TLRPC { public boolean min; public boolean bot_inline_geo; public boolean support; + public boolean scam; public int bot_info_version; public String restriction_reason; public String bot_inline_placeholder; @@ -11570,6 +11987,7 @@ public class TLRPC { 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); @@ -11620,6 +12038,7 @@ public class TLRPC { 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) { @@ -12451,6 +12870,7 @@ public class TLRPC { public long total_amount; public long game_id; public int score; + public boolean video; public static MessageAction TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { MessageAction result = null; @@ -12904,33 +13324,35 @@ public class TLRPC { } } - public static class TL_messageActionPhoneCall extends MessageAction { - public static int constructor = 0x80e11a7f; + public static class TL_messageActionPhoneCall extends MessageAction { + public static int constructor = 0x80e11a7f; - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - call_id = stream.readInt64(exception); - if ((flags & 1) != 0) { - reason = PhoneCallDiscardReason.TLdeserialize(stream, stream.readInt32(exception), exception); - } - if ((flags & 2) != 0) { - duration = stream.readInt32(exception); - } - } + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + video = (flags & 4) != 0; + call_id = stream.readInt64(exception); + if ((flags & 1) != 0) { + reason = PhoneCallDiscardReason.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 2) != 0) { + duration = stream.readInt32(exception); + } + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - stream.writeInt64(call_id); - if ((flags & 1) != 0) { - reason.serializeToStream(stream); - } - if ((flags & 2) != 0) { - stream.writeInt32(duration); - } - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = video ? (flags | 4) : (flags &~ 4); + stream.writeInt32(flags); + stream.writeInt64(call_id); + if ((flags & 1) != 0) { + reason.serializeToStream(stream); + } + if ((flags & 2) != 0) { + stream.writeInt32(duration); + } + } + } public static class TL_messageActionChatEditTitle extends MessageAction { public static int constructor = 0xb5a1ce5a; @@ -14293,6 +14715,37 @@ public class TLRPC { } } + public static class TL_folderPeer extends TLObject { + public static int constructor = 0xe9baa668; + + public Peer peer; + public int folder_id; + + public static TL_folderPeer TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_folderPeer.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_folderPeer", constructor)); + } else { + return null; + } + } + TL_folderPeer result = new TL_folderPeer(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + folder_id = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(folder_id); + } + } + public static abstract class SecureValueType extends TLObject { public static SecureValueType TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { @@ -15028,6 +15481,7 @@ public class TLRPC { public int mid; //custom public int groupId; //custom public PhotoSize thumb; //custom + public TLObject thumbObject; //custom public static PageBlock TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { PageBlock result = null; @@ -17247,7 +17701,7 @@ public class TLRPC { case 0x2f2f21bf: result = new TL_updateReadHistoryOutbox(); break; - case 0x19d27f3c: + case 0x6e6fe51c: result = new TL_updateDialogPinned(); break; case 0x12b9417b: @@ -17265,6 +17719,9 @@ public class TLRPC { case 0x43ae3dec: result = new TL_updateStickerSets(); break; + case 0x19360dc0: + result = new TL_updateFolderPeers(); + break; case 0x1f2b0afd: result = new TL_updateNewMessage(); break; @@ -17349,13 +17806,13 @@ public class TLRPC { case 0xab0f6b1e: result = new TL_updatePhoneCall(); break; - case 0xea4cb65b: + case 0xfa0f3ca2: result = new TL_updatePinnedDialogs(); break; case 0x9a422c20: result = new TL_updateRecentStickers(); break; - case 0x9961fd5c: + case 0x9c974fdf: result = new TL_updateReadHistoryInbox(); break; case 0x9d2e67c5: @@ -17400,7 +17857,7 @@ public class TLRPC { case 0xbb2d201: result = new TL_updateStickerSetsOrder(); break; - case 0x4214f37f: + case 0x330b5424: result = new TL_updateReadChannelInbox(); break; case 0x68c13933: @@ -17547,15 +18004,19 @@ public class TLRPC { } public static class TL_updateDialogPinned extends Update { - public static int constructor = 0x19d27f3c; + public static int constructor = 0x6e6fe51c; public int flags; public boolean pinned; + public int folder_id; public DialogPeer peer; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); pinned = (flags & 1) != 0; + if ((flags & 2) != 0) { + folder_id = stream.readInt32(exception); + } peer = DialogPeer.TLdeserialize(stream, stream.readInt32(exception), exception); } @@ -17563,6 +18024,9 @@ public class TLRPC { stream.writeInt32(constructor); flags = pinned ? (flags | 1) : (flags &~ 1); stream.writeInt32(flags); + if ((flags & 2) != 0) { + stream.writeInt32(folder_id); + } peer.serializeToStream(stream); } } @@ -17648,6 +18112,46 @@ public class TLRPC { } } + public static class TL_updateFolderPeers extends Update { + public static int constructor = 0x19360dc0; + + public ArrayList folder_peers = new ArrayList<>(); + public int pts; + public int pts_count; + + public void readParams(AbstractSerializedData stream, boolean exception) { + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TL_folderPeer object = TL_folderPeer.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + folder_peers.add(object); + } + pts = stream.readInt32(exception); + pts_count = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(0x1cb5c415); + int count = folder_peers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + folder_peers.get(a).serializeToStream(stream); + } + stream.writeInt32(pts); + stream.writeInt32(pts_count); + } + } + public static class TL_updateNewMessage extends Update { public static int constructor = 0x1f2b0afd; @@ -18278,13 +18782,17 @@ public class TLRPC { } public static class TL_updatePinnedDialogs extends Update { - public static int constructor = 0xea4cb65b; + public static int constructor = 0xfa0f3ca2; public int flags; + public int folder_id; public ArrayList order = new ArrayList<>(); public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); + if ((flags & 2) != 0) { + folder_id = stream.readInt32(exception); + } if ((flags & 1) != 0) { int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -18307,6 +18815,9 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); stream.writeInt32(flags); + if ((flags & 2) != 0) { + stream.writeInt32(folder_id); + } if ((flags & 1) != 0) { stream.writeInt32(0x1cb5c415); int count = order.size(); @@ -18328,24 +18839,37 @@ public class TLRPC { } public static class TL_updateReadHistoryInbox extends Update { - public static int constructor = 0x9961fd5c; + public static int constructor = 0x9c974fdf; + public int flags; + public int folder_id; public Peer peer; public int max_id; + public int still_unread_count; public int pts; public int pts_count; public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + if ((flags & 1) != 0) { + folder_id = stream.readInt32(exception); + } peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); max_id = stream.readInt32(exception); + still_unread_count = stream.readInt32(exception); pts = stream.readInt32(exception); pts_count = stream.readInt32(exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeInt32(folder_id); + } peer.serializeToStream(stream); stream.writeInt32(max_id); + stream.writeInt32(still_unread_count); stream.writeInt32(pts); stream.writeInt32(pts_count); } @@ -18653,20 +19177,36 @@ public class TLRPC { } public static class TL_updateReadChannelInbox extends Update { - public static int constructor = 0x4214f37f; + public static int constructor = 0x330b5424; + public int flags; + public int folder_id; public int channel_id; public int max_id; + public int still_unread_count; + public int pts; public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + if ((flags & 1) != 0) { + folder_id = stream.readInt32(exception); + } channel_id = stream.readInt32(exception); max_id = stream.readInt32(exception); + still_unread_count = stream.readInt32(exception); + pts = stream.readInt32(exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeInt32(folder_id); + } stream.writeInt32(channel_id); stream.writeInt32(max_id); + stream.writeInt32(still_unread_count); + stream.writeInt32(pts); } } @@ -19365,76 +19905,101 @@ public class TLRPC { } } - public static abstract class UserProfilePhoto extends TLObject { - public long photo_id; - public FileLocation photo_small; - public FileLocation photo_big; + public static abstract class UserProfilePhoto extends TLObject { - public static UserProfilePhoto TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - UserProfilePhoto result = null; - switch (constructor) { - case 0x4f11bae1: - result = new TL_userProfilePhotoEmpty(); - break; - case 0xd559d8c8: + public long photo_id; + public FileLocation photo_small; + public FileLocation photo_big; + public int dc_id; + + public static UserProfilePhoto TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + UserProfilePhoto result = null; + switch (constructor) { + case 0xecd75d8c: result = new TL_userProfilePhoto(); - break; - case 0x990d1493: - result = new TL_userProfilePhoto_old(); break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in UserProfilePhoto", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } + case 0x4f11bae1: + result = new TL_userProfilePhotoEmpty(); + break; + case 0xd559d8c8: + result = new TL_userProfilePhoto_layer97(); + break; + case 0x990d1493: + result = new TL_userProfilePhoto_old(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in UserProfilePhoto", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } - public static class TL_userProfilePhotoEmpty extends UserProfilePhoto { - public static int constructor = 0x4f11bae1; + public static class TL_userProfilePhoto extends UserProfilePhoto { + public static int constructor = 0xecd75d8c; - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - } - } + public void readParams(AbstractSerializedData stream, boolean exception) { + photo_id = stream.readInt64(exception); + photo_small = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + photo_big = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + dc_id = stream.readInt32(exception); + } - public static class TL_userProfilePhoto extends UserProfilePhoto { + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(photo_id); + photo_small.serializeToStream(stream); + photo_big.serializeToStream(stream); + stream.writeInt32(dc_id); + } + } + + public static class TL_userProfilePhotoEmpty extends UserProfilePhoto { + public static int constructor = 0x4f11bae1; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_userProfilePhoto_layer97 extends TL_userProfilePhoto { public static int constructor = 0xd559d8c8; - public void readParams(AbstractSerializedData stream, boolean exception) { - photo_id = stream.readInt64(exception); - photo_small = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); - photo_big = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(photo_id); - photo_small.serializeToStream(stream); - photo_big.serializeToStream(stream); - } - } - - public static class TL_userProfilePhoto_old extends TL_userProfilePhoto { - public static int constructor = 0x990d1493; - - - public void readParams(AbstractSerializedData stream, boolean exception) { - photo_small = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); - photo_big = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); - } + public void readParams(AbstractSerializedData stream, boolean exception) { + photo_id = stream.readInt64(exception); + photo_small = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + photo_big = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + } public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - photo_small.serializeToStream(stream); - photo_big.serializeToStream(stream); - } - } + stream.writeInt32(constructor); + stream.writeInt64(photo_id); + photo_small.serializeToStream(stream); + photo_big.serializeToStream(stream); + } + } + + public static class TL_userProfilePhoto_old extends TL_userProfilePhoto { + public static int constructor = 0x990d1493; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + photo_small = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + photo_big = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + photo_small.serializeToStream(stream); + photo_big.serializeToStream(stream); + } + } public static abstract class MessageEntity extends TLObject { public int offset; @@ -19749,278 +20314,330 @@ public class TLRPC { } } - public static abstract class Photo extends TLObject { - public int flags; - public boolean has_stickers; - public long id; - public long access_hash; - public byte[] file_reference; - public int user_id; - public int date; - public String caption; - public GeoPoint geo; - public ArrayList sizes = new ArrayList<>(); + public static abstract class Photo extends TLObject { - public static Photo TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - Photo result = null; - switch (constructor) { - case 0x22b56751: - result = new TL_photo_old(); - break; - case 0x9c477dd8: - result = new TL_photo(); - break; - case 0xc3838076: - result = new TL_photo_old2(); - break; - case 0xcded42fe: - result = new TL_photo_layer55(); - break; - case 0x9288dd29: - result = new TL_photo_layer82(); - break; - case 0x2331b22d: - result = new TL_photoEmpty(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in Photo", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } + public int flags; + public boolean has_stickers; + public long id; + public long access_hash; + public byte[] file_reference; + public int date; + public ArrayList sizes = new ArrayList<>(); + public int dc_id; + public int user_id; + public GeoPoint geo; + public String caption; - public static class TL_photo_old extends TL_photo { - public static int constructor = 0x22b56751; + public static Photo TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + Photo result = null; + switch (constructor) { + case 0x9c477dd8: + result = new TL_photo_layer97(); + break; + case 0xcded42fe: + result = new TL_photo_layer55(); + break; + case 0xc3838076: + result = new TL_photo_old2(); + break; + case 0x2331b22d: + result = new TL_photoEmpty(); + break; + case 0x22b56751: + result = new TL_photo_old(); + break; + case 0xd07504a5: + result = new TL_photo(); + break; + case 0x9288dd29: + result = new TL_photo_layer82(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in Photo", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_photo_layer97 extends TL_photo { + public static int constructor = 0x9c477dd8; - public void readParams(AbstractSerializedData stream, boolean exception) { - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - user_id = stream.readInt32(exception); - date = stream.readInt32(exception); - caption = stream.readString(exception); - geo = GeoPoint.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++) { - PhotoSize object = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - sizes.add(object); - } - } + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + has_stickers = (flags & 1) != 0; + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + file_reference = stream.readByteArray(exception); + date = 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++) { + PhotoSize object = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + sizes.add(object); + } + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeInt32(user_id); - stream.writeInt32(date); - stream.writeString(caption); - geo.serializeToStream(stream); - stream.writeInt32(0x1cb5c415); - int count = sizes.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - sizes.get(a).serializeToStream(stream); - } - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = has_stickers ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeByteArray(file_reference); + stream.writeInt32(date); + stream.writeInt32(0x1cb5c415); + int count = sizes.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + sizes.get(a).serializeToStream(stream); + } + } + } - public static class TL_photo extends Photo { - public static int constructor = 0x9c477dd8; + public static class TL_photo_layer55 extends TL_photo { + public static int constructor = 0xcded42fe; - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - has_stickers = (flags & 1) != 0; - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - file_reference = stream.readByteArray(exception); - date = 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++) { - PhotoSize object = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - sizes.add(object); - } - } + public void readParams(AbstractSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + date = 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++) { + PhotoSize object = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + sizes.add(object); + } + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = has_stickers ? (flags | 1) : (flags &~ 1); - stream.writeInt32(flags); - stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeByteArray(file_reference); - stream.writeInt32(date); - stream.writeInt32(0x1cb5c415); - int count = sizes.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - sizes.get(a).serializeToStream(stream); - } - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeInt32(date); + stream.writeInt32(0x1cb5c415); + int count = sizes.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + sizes.get(a).serializeToStream(stream); + } + } + } - public static class TL_photo_old2 extends TL_photo { - public static int constructor = 0xc3838076; + public static class TL_photo_old2 extends TL_photo { + public static int constructor = 0xc3838076; - public void readParams(AbstractSerializedData stream, boolean exception) { - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - user_id = stream.readInt32(exception); - date = stream.readInt32(exception); - geo = GeoPoint.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++) { - PhotoSize object = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - sizes.add(object); - } - } + public void readParams(AbstractSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + user_id = stream.readInt32(exception); + date = stream.readInt32(exception); + geo = GeoPoint.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++) { + PhotoSize object = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + sizes.add(object); + } + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeInt32(user_id); - stream.writeInt32(date); - geo.serializeToStream(stream); - stream.writeInt32(0x1cb5c415); - int count = sizes.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - sizes.get(a).serializeToStream(stream); - } - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeInt32(user_id); + stream.writeInt32(date); + geo.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = sizes.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + sizes.get(a).serializeToStream(stream); + } + } + } - public static class TL_photo_layer55 extends TL_photo { - public static int constructor = 0xcded42fe; + public static class TL_photoEmpty extends Photo { + public static int constructor = 0x2331b22d; - public void readParams(AbstractSerializedData stream, boolean exception) { - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - date = 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++) { - PhotoSize object = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - sizes.add(object); - } - } + public void readParams(AbstractSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeInt32(date); - stream.writeInt32(0x1cb5c415); - int count = sizes.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - sizes.get(a).serializeToStream(stream); - } - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + } + } - public static class TL_photo_layer82 extends TL_photo { - public static int constructor = 0x9288dd29; + public static class TL_photo_old extends TL_photo { + public static int constructor = 0x22b56751; - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - has_stickers = (flags & 1) != 0; - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - date = 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++) { - PhotoSize object = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - sizes.add(object); - } - } + public void readParams(AbstractSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + user_id = stream.readInt32(exception); + date = stream.readInt32(exception); + caption = stream.readString(exception); + geo = GeoPoint.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++) { + PhotoSize object = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + sizes.add(object); + } + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = has_stickers ? (flags | 1) : (flags &~ 1); - stream.writeInt32(flags); - stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeInt32(date); - stream.writeInt32(0x1cb5c415); - int count = sizes.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - sizes.get(a).serializeToStream(stream); - } - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeInt32(user_id); + stream.writeInt32(date); + stream.writeString(caption); + geo.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = sizes.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + sizes.get(a).serializeToStream(stream); + } + } + } - public static class TL_photoEmpty extends Photo { - public static int constructor = 0x2331b22d; + public static class TL_photo extends Photo { + public static int constructor = 0xd07504a5; - public void readParams(AbstractSerializedData stream, boolean exception) { - id = stream.readInt64(exception); - } + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + has_stickers = (flags & 1) != 0; + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + file_reference = stream.readByteArray(exception); + date = 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++) { + PhotoSize object = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + sizes.add(object); + } + dc_id = stream.readInt32(exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(id); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = has_stickers ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeByteArray(file_reference); + stream.writeInt32(date); + stream.writeInt32(0x1cb5c415); + int count = sizes.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + sizes.get(a).serializeToStream(stream); + } + stream.writeInt32(dc_id); + } + } + + public static class TL_photo_layer82 extends TL_photo { + public static int constructor = 0x9288dd29; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + has_stickers = (flags & 1) != 0; + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + date = 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++) { + PhotoSize object = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + sizes.add(object); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = has_stickers ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeInt32(date); + stream.writeInt32(0x1cb5c415); + int count = sizes.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + sizes.get(a).serializeToStream(stream); + } + } + } public static class TL_encryptedChatRequested_old extends TL_encryptedChatRequested { public static int constructor = 0xfda9a7b7; @@ -20347,7 +20964,7 @@ public class TLRPC { } public static class TL_config extends TLObject { - public static int constructor = 0xe6ca25f6; + public static int constructor = 0x330b4067; public int flags; public boolean phonecalls_enabled; @@ -20384,6 +21001,7 @@ public class TLRPC { public int channels_read_media_period; public int tmp_sessions; public int pinned_dialogs_count_max; + public int pinned_infolder_count_max; public int call_receive_timeout_ms; public int call_ring_timeout_ms; public int call_connect_timeout_ms; @@ -20466,6 +21084,7 @@ public class TLRPC { tmp_sessions = stream.readInt32(exception); } pinned_dialogs_count_max = stream.readInt32(exception); + pinned_infolder_count_max = stream.readInt32(exception); call_receive_timeout_ms = stream.readInt32(exception); call_ring_timeout_ms = stream.readInt32(exception); call_connect_timeout_ms = stream.readInt32(exception); @@ -20544,6 +21163,7 @@ public class TLRPC { stream.writeInt32(tmp_sessions); } stream.writeInt32(pinned_dialogs_count_max); + stream.writeInt32(pinned_infolder_count_max); stream.writeInt32(call_receive_timeout_ms); stream.writeInt32(call_ring_timeout_ms); stream.writeInt32(call_connect_timeout_ms); @@ -21151,6 +21771,37 @@ public class TLRPC { } } + public static class TL_inputFolderPeer extends TLObject { + public static int constructor = 0xfbd2c296; + + public InputPeer peer; + public int folder_id; + + public static TL_inputFolderPeer TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_inputFolderPeer.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_inputFolderPeer", constructor)); + } else { + return null; + } + } + TL_inputFolderPeer result = new TL_inputFolderPeer(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + peer = InputPeer.TLdeserialize(stream, stream.readInt32(exception), exception); + folder_id = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(folder_id); + } + } + public static class TL_phoneConnection extends TLObject { public static int constructor = 0x9d4c17c0; @@ -21311,6 +21962,34 @@ public class TLRPC { } } + public static class TL_emojiLanguage extends TLObject { + public static int constructor = 0xb3fb5361; + + public String lang_code; + + public static TL_emojiLanguage TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_emojiLanguage.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_emojiLanguage", constructor)); + } else { + return null; + } + } + TL_emojiLanguage result = new TL_emojiLanguage(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + lang_code = stream.readString(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(lang_code); + } + } + public static class TL_messages_foundGifs extends TLObject { public static int constructor = 0x450a1c0a; @@ -21370,13 +22049,10 @@ public class TLRPC { public ArrayList other_updates = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); public ArrayList users = new ArrayList<>(); - public int top_message; - public int read_inbox_max_id; - public int read_outbox_max_id; - public int unread_count; - public int unread_mentions_count; + public Dialog dialog; public ArrayList messages = new ArrayList<>(); + public static updates_ChannelDifference TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { updates_ChannelDifference result = null; switch (constructor) { @@ -21386,9 +22062,9 @@ public class TLRPC { case 0x2064674e: result = new TL_updates_channelDifference(); break; - case 0x6a9d7b35: - result = new TL_updates_channelDifferenceTooLong(); - break; + case 0xa4bcc6fe: + result = new TL_updates_channelDifferenceTooLong(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in updates_ChannelDifference", constructor)); @@ -21532,102 +22208,92 @@ public class TLRPC { } } - public static class TL_updates_channelDifferenceTooLong extends updates_ChannelDifference { - public static int constructor = 0x6a9d7b35; + public static class TL_updates_channelDifferenceTooLong extends updates_ChannelDifference { + public static int constructor = 0xa4bcc6fe; - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - isFinal = (flags & 1) != 0; - pts = stream.readInt32(exception); - if ((flags & 2) != 0) { - timeout = stream.readInt32(exception); - } - top_message = stream.readInt32(exception); - read_inbox_max_id = stream.readInt32(exception); - read_outbox_max_id = stream.readInt32(exception); - unread_count = stream.readInt32(exception); - unread_mentions_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++) { - Message object = Message.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - messages.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - chats.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - users.add(object); - } - } + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + isFinal = (flags & 1) != 0; + if ((flags & 2) != 0) { + timeout = stream.readInt32(exception); + } + dialog = Dialog.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++) { + Message object = Message.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + messages.add(object); + } + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); + } + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); + } + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = isFinal ? (flags | 1) : (flags &~ 1); - stream.writeInt32(flags); - stream.writeInt32(pts); - if ((flags & 2) != 0) { - stream.writeInt32(timeout); - } - stream.writeInt32(top_message); - stream.writeInt32(read_inbox_max_id); - stream.writeInt32(read_outbox_max_id); - stream.writeInt32(unread_count); - stream.writeInt32(unread_mentions_count); - stream.writeInt32(0x1cb5c415); - int count = messages.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - messages.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = chats.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - chats.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = users.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - users.get(a).serializeToStream(stream); - } - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = isFinal ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + if ((flags & 2) != 0) { + stream.writeInt32(timeout); + } + dialog.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = messages.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + messages.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = chats.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + chats.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); + } + } + } public static abstract class ChannelMessagesFilter extends TLObject { public int flags; @@ -23478,6 +24144,94 @@ public class TLRPC { } } + public static abstract class EmojiKeyword extends TLObject { + + public static EmojiKeyword TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + EmojiKeyword result = null; + switch (constructor) { + case 0x236df622: + result = new TL_emojiKeywordDeleted(); + break; + case 0xd5b3b9f9: + result = new TL_emojiKeyword(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in EmojiKeyword", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_emojiKeywordDeleted extends EmojiKeyword { + public static int constructor = 0x236df622; + + public String keyword; + public ArrayList emoticons = new ArrayList<>(); + + public void readParams(AbstractSerializedData stream, boolean exception) { + keyword = stream.readString(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + emoticons.add(stream.readString(exception)); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(keyword); + stream.writeInt32(0x1cb5c415); + int count = emoticons.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeString(emoticons.get(a)); + } + } + } + + public static class TL_emojiKeyword extends EmojiKeyword { + public static int constructor = 0xd5b3b9f9; + + public String keyword; + public ArrayList emoticons = new ArrayList<>(); + + public void readParams(AbstractSerializedData stream, boolean exception) { + keyword = stream.readString(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + emoticons.add(stream.readString(exception)); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(keyword); + stream.writeInt32(0x1cb5c415); + int count = emoticons.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeString(emoticons.get(a)); + } + } + } + public static class TL_account_autoDownloadSettings extends TLObject { public static int constructor = 0x63cacf26; @@ -23762,8 +24516,8 @@ public class TLRPC { public InputStickerSet prev_stickerset; public InputStickerSet new_stickerset; public ChannelParticipant participant; - public ChatPhoto prev_photo; - public ChatPhoto new_photo; + public Photo prev_photo; + public Photo new_photo; public static ChannelAdminLogEventAction TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { ChannelAdminLogEventAction result = null; @@ -23813,9 +24567,9 @@ public class TLRPC { case 0x6a4afc38: result = new TL_channelAdminLogEventActionChangeUsername(); break; - case 0xb82f55c3: - result = new TL_channelAdminLogEventActionChangePhoto(); - break; + case 0x434bd2af: + result = new TL_channelAdminLogEventActionChangePhoto(); + break; case 0xe6d83d7e: result = new TL_channelAdminLogEventActionParticipantToggleBan(); break; @@ -24060,21 +24814,21 @@ public class TLRPC { } } - public static class TL_channelAdminLogEventActionChangePhoto extends ChannelAdminLogEventAction { - public static int constructor = 0xb82f55c3; + public static class TL_channelAdminLogEventActionChangePhoto extends ChannelAdminLogEventAction { + public static int constructor = 0x434bd2af; - public void readParams(AbstractSerializedData stream, boolean exception) { - prev_photo = ChatPhoto.TLdeserialize(stream, stream.readInt32(exception), exception); - new_photo = ChatPhoto.TLdeserialize(stream, stream.readInt32(exception), exception); - } + public void readParams(AbstractSerializedData stream, boolean exception) { + prev_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + new_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - prev_photo.serializeToStream(stream); - new_photo.serializeToStream(stream); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + prev_photo.serializeToStream(stream); + new_photo.serializeToStream(stream); + } + } public static class TL_channelAdminLogEventActionParticipantToggleBan extends ChannelAdminLogEventAction { public static int constructor = 0xe6d83d7e; @@ -24329,6 +25083,7 @@ public class TLRPC { public String username; public String restriction_reason; public boolean min; + public boolean scam; public boolean explicit_content; public TL_channelAdminRights_layer92 admin_rights_layer92; public TL_channelBannedRights_layer92 banned_rights_layer92; @@ -24832,6 +25587,7 @@ public class TLRPC { restricted = (flags & 512) != 0; signatures = (flags & 2048) != 0; min = (flags & 4096) != 0; + scam = (flags & 524288) != 0; id = stream.readInt32(exception); if ((flags & 8192) != 0) { access_hash = stream.readInt64(exception); @@ -24870,6 +25626,7 @@ public class TLRPC { flags = restricted ? (flags | 512) : (flags &~ 512); flags = signatures ? (flags | 2048) : (flags &~ 2048); flags = min ? (flags | 4096) : (flags &~ 4096); + flags = scam ? (flags | 524288) : (flags &~ 524288); stream.writeInt32(flags); stream.writeInt32(id); if ((flags & 8192) != 0) { @@ -25190,132 +25947,237 @@ public class TLRPC { } } - public static abstract class StickerSet extends TLObject { + public static abstract class StickerSet extends TLObject { - public int flags; - public boolean installed; - public boolean archived; - public boolean official; - public boolean masks; - public int installed_date; - public long id; - public long access_hash; - public String title; - public String short_name; - public int count; - public int hash; + public int flags; + public boolean installed; + public boolean archived; + public boolean official; + public boolean masks; + public long id; + public long access_hash; + public String title; + public String short_name; + public int count; + public int hash; + public int installed_date; + public PhotoSize thumb; + public int thumb_dc_id; - public static StickerSet TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - StickerSet result = null; - switch (constructor) { - case 0xa7a43b17: - result = new TL_stickerSet_old(); - break; - case 0x5585a139: - result = new TL_stickerSet(); - break; - case 0xcd303b41: - result = new TL_stickerSet_layer75(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in StickerSet", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } + public static StickerSet TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + StickerSet result = null; + switch (constructor) { + case 0xa7a43b17: + result = new TL_stickerSet_old(); + break; + case 0x5585a139: + result = new TL_stickerSet_layer96(); + break; + case 0x6a90bcb7: + result = new TL_stickerSet_layer97(); + break; + case 0xeeb46f27: + result = new TL_stickerSet(); + break; + case 0xcd303b41: + result = new TL_stickerSet_layer75(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in StickerSet", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } - public static class TL_stickerSet_old extends TL_stickerSet { - public static int constructor = 0xa7a43b17; + public static class TL_stickerSet_old extends TL_stickerSet { + public static int constructor = 0xa7a43b17; - public void readParams(AbstractSerializedData stream, boolean exception) { - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - title = stream.readString(exception); - short_name = stream.readString(exception); - } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeString(title); - stream.writeString(short_name); - } - } + public void readParams(AbstractSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + title = stream.readString(exception); + short_name = stream.readString(exception); + } - public static class TL_stickerSet extends StickerSet { - public static int constructor = 0x5585a139; + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeString(title); + stream.writeString(short_name); + } + } - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - archived = (flags & 2) != 0; - official = (flags & 4) != 0; - masks = (flags & 8) != 0; - if ((flags & 1) != 0) { - installed_date = stream.readInt32(exception); - } - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - title = stream.readString(exception); - short_name = stream.readString(exception); - count = stream.readInt32(exception); - hash = stream.readInt32(exception); - } + public static class TL_stickerSet_layer96 extends TL_stickerSet { + public static int constructor = 0x5585a139; - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = archived ? (flags | 2) : (flags &~ 2); - flags = official ? (flags | 4) : (flags &~ 4); - flags = masks ? (flags | 8) : (flags &~ 8); - stream.writeInt32(flags); - if ((flags & 1) != 0) { - stream.writeInt32(installed_date); - } - stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeString(title); - stream.writeString(short_name); - stream.writeInt32(count); - stream.writeInt32(hash); - } - } - public static class TL_stickerSet_layer75 extends TL_stickerSet { - public static int constructor = 0xcd303b41; + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + archived = (flags & 2) != 0; + official = (flags & 4) != 0; + masks = (flags & 8) != 0; + if ((flags & 1) != 0) { + installed_date = stream.readInt32(exception); + } + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + title = stream.readString(exception); + short_name = stream.readString(exception); + count = stream.readInt32(exception); + hash = stream.readInt32(exception); + } - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - installed = (flags & 1) != 0; - archived = (flags & 2) != 0; - official = (flags & 4) != 0; - masks = (flags & 8) != 0; - id = stream.readInt64(exception); - access_hash = stream.readInt64(exception); - title = stream.readString(exception); - short_name = stream.readString(exception); - count = stream.readInt32(exception); - hash = stream.readInt32(exception); - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = archived ? (flags | 2) : (flags &~ 2); + flags = official ? (flags | 4) : (flags &~ 4); + flags = masks ? (flags | 8) : (flags &~ 8); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeInt32(installed_date); + } + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeString(title); + stream.writeString(short_name); + stream.writeInt32(count); + stream.writeInt32(hash); + } + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = installed ? (flags | 1) : (flags &~ 1); - flags = archived ? (flags | 2) : (flags &~ 2); - flags = official ? (flags | 4) : (flags &~ 4); - flags = masks ? (flags | 8) : (flags &~ 8); - stream.writeInt32(flags); - stream.writeInt64(id); - stream.writeInt64(access_hash); - stream.writeString(title); - stream.writeString(short_name); - stream.writeInt32(count); - stream.writeInt32(hash); - } - } + public static class TL_stickerSet_layer97 extends TL_stickerSet { + public static int constructor = 0x6a90bcb7; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + archived = (flags & 2) != 0; + official = (flags & 4) != 0; + masks = (flags & 8) != 0; + if ((flags & 1) != 0) { + installed_date = stream.readInt32(exception); + } + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + title = stream.readString(exception); + short_name = stream.readString(exception); + if ((flags & 16) != 0) { + thumb = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + } + count = stream.readInt32(exception); + hash = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = archived ? (flags | 2) : (flags &~ 2); + flags = official ? (flags | 4) : (flags &~ 4); + flags = masks ? (flags | 8) : (flags &~ 8); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeInt32(installed_date); + } + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeString(title); + stream.writeString(short_name); + if ((flags & 16) != 0) { + thumb.serializeToStream(stream); + } + stream.writeInt32(count); + stream.writeInt32(hash); + } + } + + public static class TL_stickerSet extends StickerSet { + public static int constructor = 0xeeb46f27; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + archived = (flags & 2) != 0; + official = (flags & 4) != 0; + masks = (flags & 8) != 0; + if ((flags & 1) != 0) { + installed_date = stream.readInt32(exception); + } + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + title = stream.readString(exception); + short_name = stream.readString(exception); + if ((flags & 16) != 0) { + thumb = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 16) != 0) { + thumb_dc_id = stream.readInt32(exception); + } + count = stream.readInt32(exception); + hash = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = archived ? (flags | 2) : (flags &~ 2); + flags = official ? (flags | 4) : (flags &~ 4); + flags = masks ? (flags | 8) : (flags &~ 8); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeInt32(installed_date); + } + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeString(title); + stream.writeString(short_name); + if ((flags & 16) != 0) { + thumb.serializeToStream(stream); + } + if ((flags & 16) != 0) { + stream.writeInt32(thumb_dc_id); + } + stream.writeInt32(count); + stream.writeInt32(hash); + } + } + + public static class TL_stickerSet_layer75 extends TL_stickerSet { + public static int constructor = 0xcd303b41; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + installed = (flags & 1) != 0; + archived = (flags & 2) != 0; + official = (flags & 4) != 0; + masks = (flags & 8) != 0; + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + title = stream.readString(exception); + short_name = stream.readString(exception); + count = stream.readInt32(exception); + hash = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = installed ? (flags | 1) : (flags &~ 1); + flags = archived ? (flags | 2) : (flags &~ 2); + flags = official ? (flags | 4) : (flags &~ 4); + flags = masks ? (flags | 8) : (flags &~ 8); + stream.writeInt32(flags); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeString(title); + stream.writeString(short_name); + stream.writeInt32(count); + stream.writeInt32(hash); + } + } public static abstract class storage_FileType extends TLObject { @@ -25867,283 +26729,366 @@ public class TLRPC { } } - public static abstract class MessageFwdHeader extends TLObject { - public int flags; - public int from_id; - public int date; - public int channel_id; - public int channel_post; - public String post_author; - public Peer saved_from_peer; - public int saved_from_msg_id; + public static abstract class MessageFwdHeader extends TLObject { - public static MessageFwdHeader TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - MessageFwdHeader result = null; - switch (constructor) { - case 0xfadff4ac: - result = new TL_messageFwdHeader_layer72(); - break; - case 0x559ebe6d: - result = new TL_messageFwdHeader(); - break; - case 0xc786ddcb: - result = new TL_messageFwdHeader_layer68(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in MessageFwdHeader", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } + public int flags; + public int from_id; + public String from_name; + public int date; + public int channel_id; + public int channel_post; + public String post_author; + public Peer saved_from_peer; + public int saved_from_msg_id; - public static class TL_messageFwdHeader_layer72 extends TL_messageFwdHeader { - public static int constructor = 0xfadff4ac; + public static MessageFwdHeader TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + MessageFwdHeader result = null; + switch (constructor) { + case 0xc786ddcb: + result = new TL_messageFwdHeader_layer68(); + break; + case 0xec338270: + result = new TL_messageFwdHeader(); + break; + case 0xfadff4ac: + result = new TL_messageFwdHeader_layer72(); + break; + case 0x559ebe6d: + result = new TL_messageFwdHeader_layer96(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in MessageFwdHeader", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_messageFwdHeader_layer68 extends TL_messageFwdHeader { + public static int constructor = 0xc786ddcb; - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - if ((flags & 1) != 0) { - from_id = stream.readInt32(exception); - } - date = stream.readInt32(exception); - if ((flags & 2) != 0) { - channel_id = stream.readInt32(exception); - } - if ((flags & 4) != 0) { - channel_post = stream.readInt32(exception); - } - if ((flags & 8) != 0) { - post_author = stream.readString(exception); - } - } + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + if ((flags & 1) != 0) { + from_id = stream.readInt32(exception); + } + date = stream.readInt32(exception); + if ((flags & 2) != 0) { + channel_id = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + channel_post = stream.readInt32(exception); + } + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - if ((flags & 1) != 0) { - stream.writeInt32(from_id); - } - stream.writeInt32(date); - if ((flags & 2) != 0) { - stream.writeInt32(channel_id); - } - if ((flags & 4) != 0) { - stream.writeInt32(channel_post); - } - if ((flags & 8) != 0) { - stream.writeString(post_author); - } - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeInt32(from_id); + } + stream.writeInt32(date); + if ((flags & 2) != 0) { + stream.writeInt32(channel_id); + } + if ((flags & 4) != 0) { + stream.writeInt32(channel_post); + } + } + } - public static class TL_messageFwdHeader extends MessageFwdHeader { - public static int constructor = 0x559ebe6d; + public static class TL_messageFwdHeader extends MessageFwdHeader { + public static int constructor = 0xec338270; - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - if ((flags & 1) != 0) { - from_id = stream.readInt32(exception); - } - date = stream.readInt32(exception); - if ((flags & 2) != 0) { - channel_id = stream.readInt32(exception); - } - if ((flags & 4) != 0) { - channel_post = stream.readInt32(exception); - } - if ((flags & 8) != 0) { - post_author = stream.readString(exception); - } - if ((flags & 16) != 0) { - saved_from_peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - } - if ((flags & 16) != 0) { - saved_from_msg_id = stream.readInt32(exception); - } - } + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + if ((flags & 1) != 0) { + from_id = stream.readInt32(exception); + } + if ((flags & 32) != 0) { + from_name = stream.readString(exception); + } + date = stream.readInt32(exception); + if ((flags & 2) != 0) { + channel_id = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + channel_post = stream.readInt32(exception); + } + if ((flags & 8) != 0) { + post_author = stream.readString(exception); + } + if ((flags & 16) != 0) { + saved_from_peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 16) != 0) { + saved_from_msg_id = stream.readInt32(exception); + } + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - if ((flags & 1) != 0) { - stream.writeInt32(from_id); - } - stream.writeInt32(date); - if ((flags & 2) != 0) { - stream.writeInt32(channel_id); - } - if ((flags & 4) != 0) { - stream.writeInt32(channel_post); - } - if ((flags & 8) != 0) { - stream.writeString(post_author); - } - if ((flags & 16) != 0) { - saved_from_peer.serializeToStream(stream); - } - if ((flags & 16) != 0) { - stream.writeInt32(saved_from_msg_id); - } - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeInt32(from_id); + } + if ((flags & 32) != 0) { + stream.writeString(from_name); + } + stream.writeInt32(date); + if ((flags & 2) != 0) { + stream.writeInt32(channel_id); + } + if ((flags & 4) != 0) { + stream.writeInt32(channel_post); + } + if ((flags & 8) != 0) { + stream.writeString(post_author); + } + if ((flags & 16) != 0) { + saved_from_peer.serializeToStream(stream); + } + if ((flags & 16) != 0) { + stream.writeInt32(saved_from_msg_id); + } + } + } - public static class TL_messageFwdHeader_layer68 extends TL_messageFwdHeader { - public static int constructor = 0xc786ddcb; + public static class TL_messageFwdHeader_layer72 extends TL_messageFwdHeader { + public static int constructor = 0xfadff4ac; - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - if ((flags & 1) != 0) { - from_id = stream.readInt32(exception); - } - date = stream.readInt32(exception); - if ((flags & 2) != 0) { - channel_id = stream.readInt32(exception); - } - if ((flags & 4) != 0) { - channel_post = stream.readInt32(exception); - } - } + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + if ((flags & 1) != 0) { + from_id = stream.readInt32(exception); + } + date = stream.readInt32(exception); + if ((flags & 2) != 0) { + channel_id = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + channel_post = stream.readInt32(exception); + } + if ((flags & 8) != 0) { + post_author = stream.readString(exception); + } + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - if ((flags & 1) != 0) { - stream.writeInt32(from_id); - } - stream.writeInt32(date); - if ((flags & 2) != 0) { - stream.writeInt32(channel_id); - } - if ((flags & 4) != 0) { - stream.writeInt32(channel_post); - } - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeInt32(from_id); + } + stream.writeInt32(date); + if ((flags & 2) != 0) { + stream.writeInt32(channel_id); + } + if ((flags & 4) != 0) { + stream.writeInt32(channel_post); + } + if ((flags & 8) != 0) { + stream.writeString(post_author); + } + } + } - public static abstract class FileLocation extends TLObject { - public int dc_id; - public long volume_id; - public int local_id; - public long secret; - public byte[] file_reference; - public byte[] key; - public byte[] iv; - - public static FileLocation TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - FileLocation result = null; - switch (constructor) { - case 0x7c596b46: - result = new TL_fileLocationUnavailable(); - break; - case 0x91d11eb: - result = new TL_fileLocation(); - break; - case 0x53d69076: - result = new TL_fileLocation_layer82(); - break; - case 0x55555554: - result = new TL_fileEncryptedLocation(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in FileLocation", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_fileLocationUnavailable extends FileLocation { - public static int constructor = 0x7c596b46; + public static class TL_messageFwdHeader_layer96 extends TL_messageFwdHeader { + public static int constructor = 0x559ebe6d; - public void readParams(AbstractSerializedData stream, boolean exception) { - volume_id = stream.readInt64(exception); - local_id = stream.readInt32(exception); - secret = stream.readInt64(exception); - } + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + if ((flags & 1) != 0) { + from_id = stream.readInt32(exception); + } + date = stream.readInt32(exception); + if ((flags & 2) != 0) { + channel_id = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + channel_post = stream.readInt32(exception); + } + if ((flags & 8) != 0) { + post_author = stream.readString(exception); + } + if ((flags & 16) != 0) { + saved_from_peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 16) != 0) { + saved_from_msg_id = stream.readInt32(exception); + } + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(volume_id); - stream.writeInt32(local_id); - stream.writeInt64(secret); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeInt32(from_id); + } + stream.writeInt32(date); + if ((flags & 2) != 0) { + stream.writeInt32(channel_id); + } + if ((flags & 4) != 0) { + stream.writeInt32(channel_post); + } + if ((flags & 8) != 0) { + stream.writeString(post_author); + } + if ((flags & 16) != 0) { + saved_from_peer.serializeToStream(stream); + } + if ((flags & 16) != 0) { + stream.writeInt32(saved_from_msg_id); + } + } + } - public static class TL_fileLocation extends FileLocation { - public static int constructor = 0x91d11eb; + public static abstract class FileLocation extends TLObject { + + public int dc_id; + public long volume_id; + public int local_id; + public long secret; + public byte[] file_reference; + public byte[] key; + public byte[] iv; + + public static FileLocation TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + FileLocation result = null; + switch (constructor) { + case 0x7c596b46: + result = new TL_fileLocationUnavailable(); + break; + case 0x53d69076: + result = new TL_fileLocation_layer82(); + break; + case 0x91d11eb: + result = new TL_fileLocation_layer97(); + break; + case 0xbc7fc6cd: + result = new TL_fileLocationToBeDeprecated(); + break; + case 0x55555554: + result = new TL_fileEncryptedLocation(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in FileLocation", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_fileLocationUnavailable extends FileLocation { + public static int constructor = 0x7c596b46; - public void readParams(AbstractSerializedData stream, boolean exception) { - dc_id = stream.readInt32(exception); - volume_id = stream.readInt64(exception); - local_id = stream.readInt32(exception); - secret = stream.readInt64(exception); - file_reference = stream.readByteArray(exception); - } + public void readParams(AbstractSerializedData stream, boolean exception) { + volume_id = stream.readInt64(exception); + local_id = stream.readInt32(exception); + secret = stream.readInt64(exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(dc_id); - stream.writeInt64(volume_id); - stream.writeInt32(local_id); - stream.writeInt64(secret); - stream.writeByteArray(file_reference); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(volume_id); + stream.writeInt32(local_id); + stream.writeInt64(secret); + } + } - public static class TL_fileLocation_layer82 extends TL_fileLocation { - public static int constructor = 0x53d69076; + public static class TL_fileLocation_layer82 extends TL_fileLocation_layer97 { + public static int constructor = 0x53d69076; - public void readParams(AbstractSerializedData stream, boolean exception) { - dc_id = stream.readInt32(exception); - volume_id = stream.readInt64(exception); - local_id = stream.readInt32(exception); - secret = stream.readInt64(exception); - } + public void readParams(AbstractSerializedData stream, boolean exception) { + dc_id = stream.readInt32(exception); + volume_id = stream.readInt64(exception); + local_id = stream.readInt32(exception); + secret = stream.readInt64(exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(dc_id); - stream.writeInt64(volume_id); - stream.writeInt32(local_id); - stream.writeInt64(secret); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(dc_id); + stream.writeInt64(volume_id); + stream.writeInt32(local_id); + stream.writeInt64(secret); + } + } - public static class TL_fileEncryptedLocation extends FileLocation { - public static int constructor = 0x55555554; + public static class TL_fileLocation_layer97 extends FileLocation { + public static int constructor = 0x91d11eb; - public void readParams(AbstractSerializedData stream, boolean exception) { - dc_id = stream.readInt32(exception); - volume_id = stream.readInt64(exception); - local_id = stream.readInt32(exception); - secret = stream.readInt64(exception); - key = stream.readByteArray(exception); - iv = stream.readByteArray(exception); - } + public void readParams(AbstractSerializedData stream, boolean exception) { + dc_id = stream.readInt32(exception); + volume_id = stream.readInt64(exception); + local_id = stream.readInt32(exception); + secret = stream.readInt64(exception); + file_reference = stream.readByteArray(exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(dc_id); - stream.writeInt64(volume_id); - stream.writeInt32(local_id); - stream.writeInt64(secret); - stream.writeByteArray(key); - stream.writeByteArray(iv); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(dc_id); + stream.writeInt64(volume_id); + stream.writeInt32(local_id); + stream.writeInt64(secret); + stream.writeByteArray(file_reference); + } + } + + public static class TL_fileLocationToBeDeprecated extends FileLocation { + public static int constructor = 0xbc7fc6cd; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + volume_id = stream.readInt64(exception); + local_id = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(volume_id); + stream.writeInt32(local_id); + } + } + + public static class TL_fileEncryptedLocation extends FileLocation { + public static int constructor = 0x55555554; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + dc_id = stream.readInt32(exception); + volume_id = stream.readInt64(exception); + local_id = stream.readInt32(exception); + secret = stream.readInt64(exception); + key = stream.readByteArray(exception); + iv = stream.readByteArray(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(dc_id); + stream.writeInt64(volume_id); + stream.writeInt32(local_id); + stream.writeInt64(secret); + stream.writeByteArray(key); + stream.writeByteArray(iv); + } + } public static abstract class messages_SavedGifs extends TLObject { public int hash; @@ -26569,8 +27514,7 @@ public class TLRPC { } } - public static class TL_userFull extends TLObject { - public static int constructor = 0x8ea4a881; + public static abstract class UserFull extends TLObject { public int flags; public boolean blocked; @@ -26585,19 +27529,91 @@ public class TLRPC { public BotInfo bot_info; public int pinned_msg_id; public int common_chats_count; + public int folder_id; - public static TL_userFull TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_userFull.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_userFull", constructor)); - } else { - return null; - } + public static UserFull TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + UserFull result = null; + switch (constructor) { + case 0x745559cc: + result = new TL_userFull(); + break; + case 0x8ea4a881: + result = new TL_userFull_layer98(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in UserFull", constructor)); + } + if (result != null) { + result.readParams(stream, exception); } - TL_userFull result = new TL_userFull(); - result.readParams(stream, exception); return result; } + } + + public static class TL_userFull extends UserFull { + public static int constructor = 0x745559cc; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + blocked = (flags & 1) != 0; + phone_calls_available = (flags & 16) != 0; + phone_calls_private = (flags & 32) != 0; + can_pin_message = (flags & 128) != 0; + user = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 2) != 0) { + about = stream.readString(exception); + } + link = TL_contacts_link.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 4) != 0) { + profile_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + } + notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 8) != 0) { + bot_info = BotInfo.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 64) != 0) { + pinned_msg_id = stream.readInt32(exception); + } + common_chats_count = stream.readInt32(exception); + if ((flags & 2048) != 0) { + folder_id = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = blocked ? (flags | 1) : (flags &~ 1); + flags = phone_calls_available ? (flags | 16) : (flags &~ 16); + flags = phone_calls_private ? (flags | 32) : (flags &~ 32); + flags = can_pin_message ? (flags | 128) : (flags &~ 128); + stream.writeInt32(flags); + user.serializeToStream(stream); + if ((flags & 2) != 0) { + stream.writeString(about); + } + link.serializeToStream(stream); + if ((flags & 4) != 0) { + profile_photo.serializeToStream(stream); + } + notify_settings.serializeToStream(stream); + if ((flags & 8) != 0) { + bot_info.serializeToStream(stream); + } + if ((flags & 64) != 0) { + stream.writeInt32(pinned_msg_id); + } + stream.writeInt32(common_chats_count); + if ((flags & 2048) != 0) { + stream.writeInt32(folder_id); + } + } + } + + public static class TL_userFull_layer98 extends TL_userFull { + public static int constructor = 0x8ea4a881; + public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -28070,6 +29086,34 @@ public class TLRPC { } } + public static class TL_emojiURL extends TLObject { + public static int constructor = 0xa575739d; + + public String url; + + public static TL_emojiURL TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_emojiURL.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_emojiURL", constructor)); + } else { + return null; + } + } + TL_emojiURL result = new TL_emojiURL(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + url = stream.readString(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(url); + } + } + public static class TL_decryptedMessageLayer extends TLObject { public static int constructor = 0x1be31789; @@ -28265,7 +29309,7 @@ public class TLRPC { public static class TL_messages_peerDialogs extends TLObject { public static int constructor = 0x3371c354; - public ArrayList dialogs = new ArrayList<>(); + public ArrayList

    dialogs = new ArrayList<>(); public ArrayList messages = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); public ArrayList users = new ArrayList<>(); @@ -28294,7 +29338,7 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - TL_dialog object = TL_dialog.TLdeserialize(stream, stream.readInt32(exception), exception); + Dialog object = Dialog.TLdeserialize(stream, stream.readInt32(exception), exception); if (object == null) { return; } @@ -28412,7 +29456,7 @@ public class TLRPC { public static abstract class messages_Dialogs extends TLObject { public int count; - public ArrayList dialogs = new ArrayList<>(); + public ArrayList dialogs = new ArrayList<>(); public ArrayList messages = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); public ArrayList users = new ArrayList<>(); @@ -28453,7 +29497,7 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - TL_dialog object = TL_dialog.TLdeserialize(stream, stream.readInt32(exception), exception); + Dialog object = Dialog.TLdeserialize(stream, stream.readInt32(exception), exception); if (object == null) { return; } @@ -28549,7 +29593,7 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - TL_dialog object = TL_dialog.TLdeserialize(stream, stream.readInt32(exception), exception); + Dialog object = Dialog.TLdeserialize(stream, stream.readInt32(exception), exception); if (object == null) { return; } @@ -29090,7 +30134,7 @@ public class TLRPC { public InputUser id; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_userFull.TLdeserialize(stream, constructor, exception); + return UserFull.TLdeserialize(stream, constructor, exception); } public void serializeToStream(AbstractSerializedData stream) { @@ -29345,10 +30389,11 @@ public class TLRPC { } public static class TL_messages_getDialogs extends TLObject { - public static int constructor = 0xb098aee6; + public static int constructor = 0xa0ee3b73; public int flags; public boolean exclude_pinned; + public int folder_id; public int offset_date; public int offset_id; public InputPeer offset_peer; @@ -29363,6 +30408,9 @@ public class TLRPC { stream.writeInt32(constructor); flags = exclude_pinned ? (flags | 1) : (flags &~ 1); stream.writeInt32(flags); + if ((flags & 2) != 0) { + stream.writeInt32(folder_id); + } stream.writeInt32(offset_date); stream.writeInt32(offset_id); offset_peer.serializeToStream(stream); @@ -29551,26 +30599,28 @@ public class TLRPC { } } - public static class TL_messages_deleteHistory extends TLObject { - public static int constructor = 0x1c015b09; + public static class TL_messages_deleteHistory extends TLObject { + public static int constructor = 0x1c015b09; - public int flags; - public boolean just_clear; - public InputPeer peer; - public int max_id; + public int flags; + public boolean just_clear; + public boolean revoke; + public InputPeer peer; + public int max_id; - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_messages_affectedHistory.TLdeserialize(stream, constructor, exception); - } + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_messages_affectedHistory.TLdeserialize(stream, constructor, exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = just_clear ? (flags | 1) : (flags &~ 1); - stream.writeInt32(flags); - peer.serializeToStream(stream); - stream.writeInt32(max_id); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = just_clear ? (flags | 1) : (flags &~ 1); + flags = revoke ? (flags | 2) : (flags &~ 2); + stream.writeInt32(flags); + peer.serializeToStream(stream); + stream.writeInt32(max_id); + } + } public static class TL_channels_togglePreHistoryHidden extends TLObject { public static int constructor = 0xeabbb94c; @@ -32220,42 +33270,46 @@ public class TLRPC { } } - public static class TL_messages_reorderPinnedDialogs extends TLObject { - public static int constructor = 0x5b51d63f; + public static class TL_messages_reorderPinnedDialogs extends TLObject { + public static int constructor = 0x3b1adf37; - public int flags; - public boolean force; - public ArrayList order = new ArrayList<>(); + public int flags; + public boolean force; + public int folder_id; + public ArrayList order = new ArrayList<>(); - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Bool.TLdeserialize(stream, constructor, exception); - } + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Bool.TLdeserialize(stream, constructor, exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = force ? (flags | 1) : (flags &~ 1); - stream.writeInt32(flags); - stream.writeInt32(0x1cb5c415); - int count = order.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - order.get(a).serializeToStream(stream); - } - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = force ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + stream.writeInt32(folder_id); + stream.writeInt32(0x1cb5c415); + int count = order.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + order.get(a).serializeToStream(stream); + } + } + } - public static class TL_messages_getPinnedDialogs extends TLObject { - public static int constructor = 0xe254d64e; + public static class TL_messages_getPinnedDialogs extends TLObject { + public static int constructor = 0xd6b94df2; + public int folder_id; - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_messages_peerDialogs.TLdeserialize(stream, constructor, exception); - } + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_messages_peerDialogs.TLdeserialize(stream, constructor, exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(folder_id); + } + } public static class TL_messages_uploadMedia extends TLObject { public static int constructor = 0x519bc2b1; @@ -32509,8 +33563,10 @@ public class TLRPC { } public static class TL_messages_getStatsURL extends TLObject { - public static int constructor = 0xebd58cb3; + public static int constructor = 0x812c2ae6; + public int flags; + public boolean dark; public InputPeer peer; public String params; @@ -32520,6 +33576,8 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + flags = dark ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); peer.serializeToStream(stream); stream.writeString(params); } @@ -32559,6 +33617,82 @@ public class TLRPC { } } + public static class TL_messages_getEmojiKeywords extends TLObject { + public static int constructor = 0x35a0e062; + + public String lang_code; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_emojiKeywordsDifference.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(lang_code); + } + } + + public static class TL_messages_getEmojiKeywordsDifference extends TLObject { + public static int constructor = 0x1508b6af; + + public String lang_code; + public int from_version; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_emojiKeywordsDifference.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(lang_code); + stream.writeInt32(from_version); + } + } + + public static class TL_messages_getEmojiKeywordsLanguages extends TLObject { + public static int constructor = 0x4e9963b2; + + public ArrayList lang_codes = new ArrayList<>(); + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + Vector vector = new Vector(); + int size = stream.readInt32(exception); + for (int a = 0; a < size; a++) { + TL_emojiLanguage object = TL_emojiLanguage.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return vector; + } + vector.objects.add(object); + } + return vector; + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(0x1cb5c415); + int count = lang_codes.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeString(lang_codes.get(a)); + } + } + } + + public static class TL_messages_getEmojiURL extends TLObject { + public static int constructor = 0xd5b10c26; + + public String lang_code; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_emojiURL.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(lang_code); + } + } + public static class TL_help_getAppChangelog extends TLObject { public static int constructor = 0x9010ef6f; @@ -33298,151 +34432,163 @@ public class TLRPC { } } - public static class TL_phone_getCallConfig extends TLObject { - public static int constructor = 0x55451fa9; + public static class TL_phone_getCallConfig extends TLObject { + public static int constructor = 0x55451fa9; - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_dataJSON.TLdeserialize(stream, constructor, exception); - } + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_dataJSON.TLdeserialize(stream, constructor, exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } - public static class TL_phone_requestCall extends TLObject { - public static int constructor = 0x5b95b3d4; + public static class TL_phone_requestCall extends TLObject { + public static int constructor = 0x42ff96ed; - public InputUser user_id; - public int random_id; - public byte[] g_a_hash; - public TL_phoneCallProtocol protocol; + public int flags; + public boolean video; + public InputUser user_id; + public int random_id; + public byte[] g_a_hash; + public TL_phoneCallProtocol protocol; - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_phone_phoneCall.TLdeserialize(stream, constructor, exception); - } + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_phone_phoneCall.TLdeserialize(stream, constructor, exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - user_id.serializeToStream(stream); - stream.writeInt32(random_id); - stream.writeByteArray(g_a_hash); - protocol.serializeToStream(stream); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = video ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + user_id.serializeToStream(stream); + stream.writeInt32(random_id); + stream.writeByteArray(g_a_hash); + protocol.serializeToStream(stream); + } + } - public static class TL_phone_acceptCall extends TLObject { - public static int constructor = 0x3bd2b4a0; + public static class TL_phone_acceptCall extends TLObject { + public static int constructor = 0x3bd2b4a0; - public TL_inputPhoneCall peer; - public byte[] g_b; - public TL_phoneCallProtocol protocol; + public TL_inputPhoneCall peer; + public byte[] g_b; + public TL_phoneCallProtocol protocol; - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_phone_phoneCall.TLdeserialize(stream, constructor, exception); - } + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_phone_phoneCall.TLdeserialize(stream, constructor, exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - stream.writeByteArray(g_b); - protocol.serializeToStream(stream); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeByteArray(g_b); + protocol.serializeToStream(stream); + } + } - public static class TL_phone_confirmCall extends TLObject { - public static int constructor = 0x2efe1722; + public static class TL_phone_confirmCall extends TLObject { + public static int constructor = 0x2efe1722; - public TL_inputPhoneCall peer; - public byte[] g_a; - public long key_fingerprint; - public TL_phoneCallProtocol protocol; + public TL_inputPhoneCall peer; + public byte[] g_a; + public long key_fingerprint; + public TL_phoneCallProtocol protocol; - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_phone_phoneCall.TLdeserialize(stream, constructor, exception); - } + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_phone_phoneCall.TLdeserialize(stream, constructor, exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - stream.writeByteArray(g_a); - stream.writeInt64(key_fingerprint); - protocol.serializeToStream(stream); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeByteArray(g_a); + stream.writeInt64(key_fingerprint); + protocol.serializeToStream(stream); + } + } - public static class TL_phone_receivedCall extends TLObject { - public static int constructor = 0x17d54f61; + public static class TL_phone_receivedCall extends TLObject { + public static int constructor = 0x17d54f61; - public TL_inputPhoneCall peer; + public TL_inputPhoneCall peer; - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Bool.TLdeserialize(stream, constructor, exception); - } + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Bool.TLdeserialize(stream, constructor, exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + } + } - public static class TL_phone_discardCall extends TLObject { - public static int constructor = 0x78d413a6; + public static class TL_phone_discardCall extends TLObject { + public static int constructor = 0xb2cbc1c0; - public TL_inputPhoneCall peer; - public int duration; - public PhoneCallDiscardReason reason; - public long connection_id; + public int flags; + public boolean video; + public TL_inputPhoneCall peer; + public int duration; + public PhoneCallDiscardReason reason; + public long connection_id; - 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); - peer.serializeToStream(stream); - stream.writeInt32(duration); - reason.serializeToStream(stream); - stream.writeInt64(connection_id); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = video ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + peer.serializeToStream(stream); + stream.writeInt32(duration); + reason.serializeToStream(stream); + stream.writeInt64(connection_id); + } + } - public static class TL_phone_setCallRating extends TLObject { - public static int constructor = 0x1c536a34; + public static class TL_phone_setCallRating extends TLObject { + public static int constructor = 0x59ead627; - public TL_inputPhoneCall peer; - public int rating; - public String comment; + public int flags; + public boolean user_initiative; + public TL_inputPhoneCall peer; + public int rating; + public String comment; - 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); - peer.serializeToStream(stream); - stream.writeInt32(rating); - stream.writeString(comment); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = user_initiative ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + peer.serializeToStream(stream); + stream.writeInt32(rating); + stream.writeString(comment); + } + } - public static class TL_phone_saveCallDebug extends TLObject { - public static int constructor = 0x277add7e; + public static class TL_phone_saveCallDebug extends TLObject { + public static int constructor = 0x277add7e; - public TL_inputPhoneCall peer; - public TL_dataJSON debug; + public TL_inputPhoneCall peer; + public TL_dataJSON debug; - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Bool.TLdeserialize(stream, constructor, exception); - } + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Bool.TLdeserialize(stream, constructor, exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - debug.serializeToStream(stream); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + debug.serializeToStream(stream); + } + } public static class TL_phone_createGroupCall extends TLObject { public static int constructor = 0x8504e5b6; @@ -33814,20 +34960,24 @@ public class TLRPC { } } - public static class TL_langpack_getDifference extends TLObject { - public static int constructor = 0xb2e4d7d; + public static class TL_langpack_getDifference extends TLObject { + public static int constructor = 0xcd984aa5; - public int from_version; + public String lang_pack; + public String lang_code; + public int from_version; - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_langPackDifference.TLdeserialize(stream, constructor, exception); - } + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_langPackDifference.TLdeserialize(stream, constructor, exception); + } - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(from_version); - } - } + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(lang_pack); + stream.writeString(lang_code); + stream.writeInt32(from_version); + } + } public static class TL_langpack_getLanguages extends TLObject { public static int constructor = 0x800fd57d; @@ -33868,6 +35018,41 @@ public class TLRPC { } } + public static class TL_folders_editPeerFolders extends TLObject { + public static int constructor = 0x6847d0ab; + + public ArrayList folder_peers = 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); + stream.writeInt32(0x1cb5c415); + int count = folder_peers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + folder_peers.get(a).serializeToStream(stream); + } + } + } + + public static class TL_folders_deleteFolder extends TLObject { + public static int constructor = 0x1c295881; + + public int folder_id; + + 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(folder_id); + } + } + //manually created //RichText start @@ -36072,77 +37257,129 @@ public class TLRPC { //Message end //TL_dialog start - public static class TL_dialog extends TLObject { - public static int constructor = 0xe4def5db; + public static abstract class Dialog extends TLObject { - public int flags; - public boolean pinned; - public boolean unread_mark; - public Peer peer; - public int top_message; - public int read_inbox_max_id; - public int read_outbox_max_id; - public int unread_count; - public int unread_mentions_count; - public PeerNotifySettings notify_settings; - public int pts; - public DraftMessage draft; - public int last_message_date; //custom - public long id; //custom - public int pinnedNum; //custom + public int flags; + public boolean pinned; + public boolean unread_mark; + public Peer peer; + public int top_message; + public int read_inbox_max_id; + public int read_outbox_max_id; + public int unread_count; + public int unread_mentions_count; + public PeerNotifySettings notify_settings; + public int pts; + public DraftMessage draft; + public int folder_id; + public int last_message_date; //custom + public long id; //custom + public int pinnedNum; //custom - public static TL_dialog TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_dialog.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_dialog", constructor)); - } else { - return null; - } - } - TL_dialog result = new TL_dialog(); - result.readParams(stream, exception); - return result; - } + public static Dialog TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + Dialog result = null; + switch (constructor) { + case 0x2c171f72: + result = new TL_dialog(); + break; + case 0x71bd134c: + result = new TL_dialogFolder(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in Dialog", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - pinned = (flags & 4) != 0; - unread_mark = (flags & 8) != 0; - peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - top_message = stream.readInt32(exception); - read_inbox_max_id = stream.readInt32(exception); - read_outbox_max_id = stream.readInt32(exception); - unread_count = stream.readInt32(exception); - unread_mentions_count = stream.readInt32(exception); - notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); - if ((flags & 1) != 0) { - pts = stream.readInt32(exception); - } - if ((flags & 2) != 0) { - draft = DraftMessage.TLdeserialize(stream, stream.readInt32(exception), exception); - } - } + public static class TL_dialog extends Dialog { + public static int constructor = 0x2c171f72; - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = pinned ? (flags | 4) : (flags &~ 4); - flags = unread_mark ? (flags | 8) : (flags &~ 8); - stream.writeInt32(flags); - peer.serializeToStream(stream); - stream.writeInt32(top_message); - stream.writeInt32(read_inbox_max_id); - stream.writeInt32(read_outbox_max_id); - stream.writeInt32(unread_count); - stream.writeInt32(unread_mentions_count); - notify_settings.serializeToStream(stream); - if ((flags & 1) != 0) { - stream.writeInt32(pts); - } - if ((flags & 2) != 0) { - draft.serializeToStream(stream); - } - } - } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + pinned = (flags & 4) != 0; + unread_mark = (flags & 8) != 0; + peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + top_message = stream.readInt32(exception); + read_inbox_max_id = stream.readInt32(exception); + read_outbox_max_id = stream.readInt32(exception); + unread_count = stream.readInt32(exception); + unread_mentions_count = stream.readInt32(exception); + notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 1) != 0) { + pts = stream.readInt32(exception); + } + if ((flags & 2) != 0) { + draft = DraftMessage.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 16) != 0) { + folder_id = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = pinned ? (flags | 4) : (flags &~ 4); + flags = unread_mark ? (flags | 8) : (flags &~ 8); + stream.writeInt32(flags); + peer.serializeToStream(stream); + stream.writeInt32(top_message); + stream.writeInt32(read_inbox_max_id); + stream.writeInt32(read_outbox_max_id); + stream.writeInt32(unread_count); + stream.writeInt32(unread_mentions_count); + notify_settings.serializeToStream(stream); + if ((flags & 1) != 0) { + stream.writeInt32(pts); + } + if ((flags & 2) != 0) { + draft.serializeToStream(stream); + } + if ((flags & 16) != 0) { + stream.writeInt32(folder_id); + } + } + } + + public static class TL_dialogFolder extends Dialog { + public static int constructor = 0x71bd134c; + + public TL_folder folder; + public int unread_muted_peers_count; + public int unread_unmuted_peers_count; + public int unread_muted_messages_count; + public int unread_unmuted_messages_count; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + pinned = (flags & 4) != 0; + folder = TL_folder.TLdeserialize(stream, stream.readInt32(exception), exception); + peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + top_message = stream.readInt32(exception); + unread_muted_peers_count = stream.readInt32(exception); + unread_unmuted_peers_count = stream.readInt32(exception); + unread_muted_messages_count = stream.readInt32(exception); + unread_unmuted_messages_count = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = pinned ? (flags | 4) : (flags &~ 4); + stream.writeInt32(flags); + folder.serializeToStream(stream); + peer.serializeToStream(stream); + stream.writeInt32(top_message); + stream.writeInt32(unread_muted_peers_count); + stream.writeInt32(unread_unmuted_peers_count); + stream.writeInt32(unread_muted_messages_count); + stream.writeInt32(unread_unmuted_messages_count); + } + } //TL_dialog end //ChatParticipant start diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java index 4105621b9..f5bb64ecd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java @@ -32,6 +32,7 @@ import android.widget.ImageView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BuildVars; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; import org.telegram.ui.Components.FireworksEffect; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.SnowflakesEffect; @@ -56,6 +57,7 @@ public class ActionBar extends FrameLayout { private View actionModeTop; private ActionBarMenu menu; private ActionBarMenu actionMode; + private boolean ignoreLayoutRequest; private boolean occupyStatusBar = Build.VERSION.SDK_INT >= 21; private boolean actionModeVisible; private boolean addToContainer = true; @@ -63,6 +65,10 @@ public class ActionBar extends FrameLayout { private boolean interceptTouches = true; private int extraHeight; private AnimatorSet actionModeAnimation; + private View actionModeExtraView; + private View actionModeTranslationView; + private View actionModeShowingView; + private View[] actionModeHidingViews; private boolean supportsHolidayImage; private SnowflakesEffect snowflakesEffect; @@ -92,6 +98,9 @@ public class ActionBar extends FrameLayout { public ActionBar(Context context) { super(context); setOnClickListener(v -> { + if (isSearchFieldVisible()) { + return; + } if (titleActionRunnable != null) { titleActionRunnable.run(); } @@ -120,6 +129,7 @@ public class ActionBar extends FrameLayout { actionBarMenuOnItemClick.onItemClick(-1); } }); + backButtonImageView.setContentDescription(LocaleController.getString("AccDescrGoBack", R.string.AccDescrGoBack)); } public void setBackButtonDrawable(Drawable drawable) { @@ -136,6 +146,12 @@ public class ActionBar extends FrameLayout { } } + public void setBackButtonContentDescription(CharSequence description) { + if (backButtonImageView != null) { + backButtonImageView.setContentDescription(description); + } + } + public void setSupportsHolidayImage(boolean value) { supportsHolidayImage = value; if (supportsHolidayImage) { @@ -296,9 +312,9 @@ public class ActionBar extends FrameLayout { subtitleTextView.setTextColor(color); } - public void setPopupItemsColor(int color) { + public void setPopupItemsColor(int color, boolean icon) { if (menu != null) { - menu.setPopupItemsColor(color); + menu.setPopupItemsColor(color, icon); } } @@ -388,14 +404,35 @@ public class ActionBar extends FrameLayout { } public void showActionMode() { + showActionMode(null, null, null, null, null, 0); + } + + public void showActionMode(View extraView, View showingView, View[] hidingViews, boolean[] hideView, View translationView, int translation) { if (actionMode == null || actionModeVisible) { return; } actionModeVisible = true; ArrayList animators = new ArrayList<>(); - animators.add(ObjectAnimator.ofFloat(actionMode, "alpha", 0.0f, 1.0f)); + animators.add(ObjectAnimator.ofFloat(actionMode, View.ALPHA, 0.0f, 1.0f)); + if (hidingViews != null) { + for (int a = 0; a < hidingViews.length; a++) { + if (hidingViews[a] != null) { + animators.add(ObjectAnimator.ofFloat(hidingViews[a], View.ALPHA, 1.0f, 0.0f)); + } + } + } + if (showingView != null) { + animators.add(ObjectAnimator.ofFloat(showingView, View.ALPHA, 0.0f, 1.0f)); + } + if (translationView != null) { + animators.add(ObjectAnimator.ofFloat(translationView, View.TRANSLATION_Y, translation)); + actionModeTranslationView = translationView; + } + actionModeExtraView = extraView; + actionModeShowingView = showingView; + actionModeHidingViews = hidingViews; if (occupyStatusBar && actionModeTop != null) { - animators.add(ObjectAnimator.ofFloat(actionModeTop, "alpha", 0.0f, 1.0f)); + animators.add(ObjectAnimator.ofFloat(actionModeTop, View.ALPHA, 0.0f, 1.0f)); } if (actionModeAnimation != null) { actionModeAnimation.cancel(); @@ -425,6 +462,15 @@ public class ActionBar extends FrameLayout { if (menu != null) { menu.setVisibility(INVISIBLE); } + if (actionModeHidingViews != null) { + for (int a = 0; a < actionModeHidingViews.length; a++) { + if (actionModeHidingViews[a] != null) { + if (hideView == null || a >= hideView.length || hideView[a]) { + actionModeHidingViews[a].setVisibility(INVISIBLE); + } + } + } + } } } @@ -449,11 +495,27 @@ public class ActionBar extends FrameLayout { if (actionMode == null || !actionModeVisible) { return; } + actionMode.hideAllPopupMenus(); actionModeVisible = false; ArrayList animators = new ArrayList<>(); - animators.add(ObjectAnimator.ofFloat(actionMode, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(actionMode, View.ALPHA, 0.0f)); + if (actionModeHidingViews != null) { + for (int a = 0; a < actionModeHidingViews.length; a++) { + if (actionModeHidingViews != null) { + actionModeHidingViews[a].setVisibility(VISIBLE); + animators.add(ObjectAnimator.ofFloat(actionModeHidingViews[a], View.ALPHA, 1.0f)); + } + } + } + if (actionModeTranslationView != null) { + animators.add(ObjectAnimator.ofFloat(actionModeTranslationView, View.TRANSLATION_Y, 0.0f)); + actionModeTranslationView = null; + } + if (actionModeShowingView != null) { + animators.add(ObjectAnimator.ofFloat(actionModeShowingView, View.ALPHA, 0.0f)); + } if (occupyStatusBar && actionModeTop != null) { - animators.add(ObjectAnimator.ofFloat(actionModeTop, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(actionModeTop, View.ALPHA, 0.0f)); } if (actionModeAnimation != null) { actionModeAnimation.cancel(); @@ -470,6 +532,9 @@ public class ActionBar extends FrameLayout { if (occupyStatusBar && actionModeTop != null) { actionModeTop.setVisibility(INVISIBLE); } + if (actionModeExtraView != null) { + actionModeExtraView.setVisibility(INVISIBLE); + } } } @@ -545,8 +610,10 @@ public class ActionBar extends FrameLayout { subtitleTextView.setVisibility(visible ? INVISIBLE : VISIBLE); } Drawable drawable = backButtonImageView.getDrawable(); - if (drawable != null && drawable instanceof MenuDrawable) { - ((MenuDrawable) drawable).setRotation(visible ? 1 : 0, true); + if (drawable instanceof MenuDrawable) { + MenuDrawable menuDrawable = (MenuDrawable) drawable; + menuDrawable.setRotateToBack(true); + menuDrawable.setRotation(visible ? 1 : 0, true); } } @@ -595,6 +662,14 @@ public class ActionBar extends FrameLayout { } } + @Override + public void requestLayout() { + if (ignoreLayoutRequest) { + return; + } + super.requestLayout(); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); @@ -602,6 +677,16 @@ public class ActionBar extends FrameLayout { int actionBarHeight = getCurrentActionBarHeight(); int actionBarHeightSpec = MeasureSpec.makeMeasureSpec(actionBarHeight, MeasureSpec.EXACTLY); + ignoreLayoutRequest = true; + if (actionModeTop != null) { + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) actionModeTop.getLayoutParams(); + layoutParams.height = AndroidUtilities.statusBarHeight; + } + if (actionMode != null) { + actionMode.setPadding(0, occupyStatusBar ? AndroidUtilities.statusBarHeight : 0, 0, 0); + } + ignoreLayoutRequest = false; + setMeasuredDimension(width, actionBarHeight + (occupyStatusBar ? AndroidUtilities.statusBarHeight : 0) + extraHeight); int textLeft; @@ -738,6 +823,9 @@ public class ActionBar extends FrameLayout { } public void onMenuButtonPressed() { + if (isActionModeShowed()) { + return; + } if (menu != null) { menu.onMenuButtonPressed(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java index ebd5203aa..6d1523301 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java @@ -24,7 +24,7 @@ import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Build; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.KeyEvent; @@ -164,8 +164,8 @@ public class ActionBarLayout extends FrameLayout { private boolean beginTrackingSent; private boolean transitionAnimationInProgress; private boolean transitionAnimationPreviewMode; - private int animateStartColors[][] = new int[2][]; - private int animateEndColors[][] = new int[2][]; + private int[][] animateStartColors = new int[2][]; + private int[][] animateEndColors = new int[2][]; private ThemeDescription[][] themeAnimatorDescriptions = new ThemeDescription[2][]; private ThemeDescription.ThemeDescriptionDelegate[] themeAnimatorDelegate = new ThemeDescription.ThemeDescriptionDelegate[2]; private AnimatorSet themeAnimatorSet; @@ -369,6 +369,9 @@ public class ActionBarLayout extends FrameLayout { private void onSlideAnimationEnd(final boolean backAnimation) { if (!backAnimation) { + if (fragmentsStack.size() < 2) { + return; + } BaseFragment lastFragment = fragmentsStack.get(fragmentsStack.size() - 1); lastFragment.onPause(); lastFragment.onFragmentDestroy(); @@ -474,7 +477,12 @@ public class ActionBarLayout extends FrameLayout { int dy = Math.abs((int) ev.getY() - startedTrackingY); velocityTracker.addMovement(ev); if (maybeStartTracking && !startedTracking && dx >= AndroidUtilities.getPixelsInCM(0.4f, true) && Math.abs(dx) / 3 > dy) { - prepareForMoving(ev); + BaseFragment currentFragment = fragmentsStack.get(fragmentsStack.size() - 1); + if (currentFragment.canBeginSlide()) { + prepareForMoving(ev); + } else { + maybeStartTracking = false; + } } else if (startedTracking) { if (!beginTrackingSent) { if (parentActivity.getCurrentFocus() != null) { @@ -561,7 +569,7 @@ public class ActionBarLayout extends FrameLayout { if (transitionAnimationPreviewMode || startedTracking || checkTransitionAnimation() || fragmentsStack.isEmpty()) { return; } - if (currentActionBar != null && currentActionBar.isSearchFieldVisible) { + if (!currentActionBar.isActionModeShowed() && currentActionBar != null && currentActionBar.isSearchFieldVisible) { currentActionBar.closeSearchField(); return; } @@ -731,6 +739,10 @@ public class ActionBarLayout extends FrameLayout { delayedOpenAnimationRunnable = null; } + public boolean isInPreviewMode() { + return inPreviewMode || transitionAnimationPreviewMode; + } + public boolean presentFragment(final BaseFragment fragment, final boolean removeLast, boolean forceWithoutAnimation, boolean check, final boolean preview) { if (checkTransitionAnimation() || delegate != null && check && !delegate.needPresentFragment(fragment, removeLast, forceWithoutAnimation, this) || !fragment.onFragmentCreate()) { return false; @@ -1038,39 +1050,43 @@ public class ActionBarLayout extends FrameLayout { LinearLayoutContainer temp = containerView; containerView = containerViewBack; containerViewBack = temp; - containerView.setVisibility(View.VISIBLE); previousFragment.setParentLayout(this); View fragmentView = previousFragment.fragmentView; if (fragmentView == null) { fragmentView = previousFragment.createView(parentActivity); } - if (previousFragment.actionBar != null && previousFragment.actionBar.getAddToContainer()) { - if (removeActionBarExtraHeight) { - previousFragment.actionBar.setOccupyStatusBar(false); - } - ViewGroup parent = (ViewGroup) previousFragment.actionBar.getParent(); - if (parent != null) { - parent.removeView(previousFragment.actionBar); - } - containerView.addView(previousFragment.actionBar); - previousFragment.actionBar.setTitleOverlayText(titleOverlayText, titleOverlayTextId, overlayAction); - } - ViewGroup parent = (ViewGroup) fragmentView.getParent(); - if (parent != null) { - previousFragment.onRemoveFromParent(); - try { - parent.removeView(fragmentView); - } catch (Exception ignore) { + if (!inPreviewMode) { + containerView.setVisibility(View.VISIBLE); + if (previousFragment.actionBar != null && previousFragment.actionBar.getAddToContainer()) { + if (removeActionBarExtraHeight) { + previousFragment.actionBar.setOccupyStatusBar(false); + } + ViewGroup parent = (ViewGroup) previousFragment.actionBar.getParent(); + if (parent != null) { + parent.removeView(previousFragment.actionBar); + } + containerView.addView(previousFragment.actionBar); + previousFragment.actionBar.setTitleOverlayText(titleOverlayText, titleOverlayTextId, overlayAction); } + ViewGroup parent = (ViewGroup) fragmentView.getParent(); + if (parent != null) { + previousFragment.onRemoveFromParent(); + try { + parent.removeView(fragmentView); + } catch (Exception e) { + FileLog.e(e); + } + } + containerView.addView(fragmentView); + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) fragmentView.getLayoutParams(); + layoutParams.width = LayoutHelper.MATCH_PARENT; + layoutParams.height = LayoutHelper.MATCH_PARENT; + layoutParams.topMargin = layoutParams.bottomMargin = layoutParams.rightMargin = layoutParams.leftMargin = 0; + fragmentView.setLayoutParams(layoutParams); } - containerView.addView(fragmentView); - LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) fragmentView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.topMargin = layoutParams.bottomMargin = layoutParams.rightMargin = layoutParams.leftMargin = 0; - fragmentView.setLayoutParams(layoutParams); + previousFragment.onTransitionAnimationStart(true, true); currentFragment.onTransitionAnimationStart(false, false); previousFragment.onResume(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java index e8460b357..3316d8af6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java @@ -52,7 +52,7 @@ public class ActionBarMenu extends LinearLayout { } public ActionBarMenuItem addItem(int id, Drawable drawable) { - return addItem(id, 0, isActionMode ? parentActionBar.itemsActionModeBackgroundColor : parentActionBar.itemsBackgroundColor, drawable, AndroidUtilities.dp(48)); + return addItem(id, 0, isActionMode ? parentActionBar.itemsActionModeBackgroundColor : parentActionBar.itemsBackgroundColor, drawable, AndroidUtilities.dp(48), null); } public ActionBarMenuItem addItem(int id, int icon) { @@ -60,14 +60,18 @@ public class ActionBarMenu extends LinearLayout { } public ActionBarMenuItem addItem(int id, int icon, int backgroundColor) { - return addItem(id, icon, backgroundColor, null, AndroidUtilities.dp(48)); + return addItem(id, icon, backgroundColor, null, AndroidUtilities.dp(48), null); } public ActionBarMenuItem addItemWithWidth(int id, int icon, int width) { - return addItem(id, icon, isActionMode ? parentActionBar.itemsActionModeBackgroundColor : parentActionBar.itemsBackgroundColor, null, width); + return addItem(id, icon, isActionMode ? parentActionBar.itemsActionModeBackgroundColor : parentActionBar.itemsBackgroundColor, null, width, null); } - public ActionBarMenuItem addItem(int id, int icon, int backgroundColor, Drawable drawable, int width) { + public ActionBarMenuItem addItemWithWidth(int id, int icon, int width, CharSequence title) { + return addItem(id, icon, isActionMode ? parentActionBar.itemsActionModeBackgroundColor : parentActionBar.itemsBackgroundColor, null, width, title); + } + + public ActionBarMenuItem addItem(int id, int icon, int backgroundColor, Drawable drawable, int width, CharSequence title) { ActionBarMenuItem menuItem = new ActionBarMenuItem(getContext(), this, backgroundColor, isActionMode ? parentActionBar.itemsActionModeColor : parentActionBar.itemsColor); menuItem.setTag(id); if (drawable != null) { @@ -88,6 +92,9 @@ public class ActionBarMenu extends LinearLayout { onItemClick((Integer) view.getTag()); } }); + if (title != null) { + menuItem.setContentDescription(title); + } return menuItem; } @@ -101,13 +108,13 @@ public class ActionBarMenu extends LinearLayout { } } - protected void setPopupItemsColor(int color) { + protected void setPopupItemsColor(int color, boolean icon) { int count = getChildCount(); for (int a = 0; a < count; a++) { View view = getChildAt(a); if (view instanceof ActionBarMenuItem) { ActionBarMenuItem item = (ActionBarMenuItem) view; - item.setPopupItemsColor(color); + item.setPopupItemsColor(color, icon); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java index dd5e23970..0460411cf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java @@ -26,25 +26,22 @@ import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.DecelerateInterpolator; import android.view.inputmethod.EditorInfo; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.PopupWindow; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; import org.telegram.ui.Components.CloseProgressDrawable2; import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.LayoutHelper; -import java.lang.reflect.Method; - public class ActionBarMenuItem extends FrameLayout { public static class ActionBarMenuItemSearchListener { @@ -99,7 +96,6 @@ public class ActionBarMenuItem extends FrameLayout { private boolean processedPopupClick; private boolean layoutInScreen; private boolean animationEnabled = true; - private static Method layoutInScreenMethod; private boolean ignoreOnTextChange; private CloseProgressDrawable2 progressDrawable; private int additionalOffset; @@ -311,6 +307,38 @@ public class ActionBarMenuItem extends FrameLayout { return textView; } + public ActionBarMenuSubItem addSubItem(int id, int icon, CharSequence text) { + createPopupLayout(); + + ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getContext()); + cell.setTextAndIcon(text, icon); + cell.setMinimumWidth(AndroidUtilities.dp(196)); + cell.setTag(id); + popupLayout.addView(cell); + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) cell.getLayoutParams(); + if (LocaleController.isRTL) { + layoutParams.gravity = Gravity.RIGHT; + } + layoutParams.width = LayoutHelper.MATCH_PARENT; + layoutParams.height = AndroidUtilities.dp(48); + cell.setLayoutParams(layoutParams); + cell.setOnClickListener(view -> { + if (popupWindow != null && popupWindow.isShowing()) { + if (processedPopupClick) { + return; + } + processedPopupClick = true; + popupWindow.dismiss(allowCloseAnimation); + } + if (parentMenu != null) { + parentMenu.onItemClick((Integer) view.getTag()); + } else if (delegate != null) { + delegate.onItemClick((Integer) view.getTag()); + } + }); + return cell; + } + public void redrawPopup(int color) { if (popupLayout != null) { popupLayout.backgroundDrawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); @@ -318,7 +346,7 @@ public class ActionBarMenuItem extends FrameLayout { } } - public void setPopupItemsColor(int color) { + public void setPopupItemsColor(int color, boolean icon) { if (popupLayout == null) { return; } @@ -327,6 +355,12 @@ public class ActionBarMenuItem extends FrameLayout { View child = popupLayout.linearLayout.getChildAt(a); if (child instanceof TextView) { ((TextView) child).setTextColor(color); + } else if (child instanceof ActionBarMenuSubItem) { + if (icon) { + ((ActionBarMenuSubItem) child).setIconColor(color); + } else { + ((ActionBarMenuSubItem) child).setTextColor(color); + } } } } @@ -340,7 +374,7 @@ public class ActionBarMenuItem extends FrameLayout { } public void toggleSubMenu() { - if (popupLayout == null) { + if (popupLayout == null || parentMenu != null && parentMenu.isActionMode && parentMenu.parentActionBar != null && !parentMenu.parentActionBar.isActionModeShowed()) { return; } if (showMenuRunnable != null) { @@ -364,15 +398,7 @@ public class ActionBarMenuItem extends FrameLayout { popupWindow.setOutsideTouchable(true); popupWindow.setClippingEnabled(true); if (layoutInScreen) { - try { - if (layoutInScreenMethod == null) { - layoutInScreenMethod = PopupWindow.class.getDeclaredMethod("setLayoutInScreenEnabled", boolean.class); - layoutInScreenMethod.setAccessible(true); - } - layoutInScreenMethod.invoke(popupWindow, true); - } catch (Exception e) { - FileLog.e(e); - } + popupWindow.setLayoutInScreen(true); } popupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); @@ -409,13 +435,13 @@ public class ActionBarMenuItem extends FrameLayout { } if (searchContainer.getVisibility() == VISIBLE) { if (listener == null || listener != null && listener.canCollapseSearch()) { + if (openKeyboard) { + AndroidUtilities.hideKeyboard(searchField); + } searchField.setText(""); searchContainer.setVisibility(GONE); searchField.clearFocus(); setVisibility(VISIBLE); - if (openKeyboard) { - AndroidUtilities.hideKeyboard(searchField); - } if (listener != null) { listener.onSearchCollapse(); } @@ -459,6 +485,7 @@ public class ActionBarMenuItem extends FrameLayout { return; } searchField.setHint(hint); + setContentDescription(hint); } public void setSearchFieldText(CharSequence text, boolean animated) { @@ -695,6 +722,7 @@ public class ActionBarMenuItem extends FrameLayout { searchField.requestFocus(); AndroidUtilities.showKeyboard(searchField); }); + clearButton.setContentDescription(LocaleController.getString("ClearButton", R.string.ClearButton)); searchContainer.addView(clearButton, LayoutHelper.createFrame(48, LayoutHelper.MATCH_PARENT, Gravity.CENTER_VERTICAL | Gravity.RIGHT)); } isSearchField = value; @@ -772,10 +800,10 @@ public class ActionBarMenuItem extends FrameLayout { int offsetY; if (parentMenu != null) { - offsetY = -parentMenu.parentActionBar.getMeasuredHeight() + parentMenu.getTop(); + offsetY = -parentMenu.parentActionBar.getMeasuredHeight() + parentMenu.getTop() + parentMenu.getPaddingTop(); } else { float scaleY = getScaleY(); - offsetY = -(int) (getMeasuredHeight() * scaleY - getTranslationY() / scaleY) + additionalOffset; + offsetY = -(int) (getMeasuredHeight() * scaleY - (subMenuOpenSide != 2 ? getTranslationY() : 0) / scaleY) + additionalOffset; } offsetY += yOffset; @@ -811,13 +839,20 @@ public class ActionBarMenuItem extends FrameLayout { popupWindow.update(parent, getLeft() + getMeasuredWidth() - popupLayout.getMeasuredWidth(), offsetY, -1, -1); } } - } else { + } else if (subMenuOpenSide == 1) { if (show) { popupWindow.showAsDropDown(this, -AndroidUtilities.dp(8), offsetY); } if (update) { popupWindow.update(this, -AndroidUtilities.dp(8), offsetY, -1, -1); } + } else { + if (show) { + popupWindow.showAsDropDown(this, getMeasuredWidth() - popupLayout.getMeasuredWidth(), offsetY); + } + if (update) { + popupWindow.update(this, getMeasuredWidth() - popupLayout.getMeasuredWidth(), offsetY, -1, -1); + } } } } @@ -849,4 +884,10 @@ public class ActionBarMenuItem extends FrameLayout { view.setVisibility(VISIBLE); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.ImageButton"); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java new file mode 100644 index 000000000..f594f0c04 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java @@ -0,0 +1,81 @@ +package org.telegram.ui.ActionBar; + +import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.ui.Components.LayoutHelper; + +public class ActionBarMenuSubItem extends FrameLayout { + + private TextView textView; + private ImageView imageView; + + public ActionBarMenuSubItem(Context context) { + super(context); + + setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_dialogButtonSelector), 2)); + setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); + + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.CENTER); + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarDefaultSubmenuItemIcon), PorterDuff.Mode.MULTIPLY)); + addView(imageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 40, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT))); + + textView = new TextView(context); + textView.setLines(1); + textView.setSingleLine(true); + textView.setGravity(Gravity.CENTER_HORIZONTAL); + textView.setEllipsize(TextUtils.TruncateAt.END); + textView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), View.MeasureSpec.EXACTLY)); + } + + public void setTextAndIcon(CharSequence text, int icon) { + textView.setText(text); + if (icon != 0) { + imageView.setImageResource(icon); + imageView.setVisibility(VISIBLE); + textView.setPadding(LocaleController.isRTL ? 0 : AndroidUtilities.dp(43), 0, LocaleController.isRTL ? AndroidUtilities.dp(43) : 0, 0); + } else { + imageView.setVisibility(INVISIBLE); + textView.setPadding(0, 0, 0, 0); + } + } + + public void setColors(int text, int icon) { + textView.setTextColor(text); + imageView.setColorFilter(new PorterDuffColorFilter(icon, PorterDuff.Mode.MULTIPLY)); + } + + public void setTextColor(int color) { + textView.setTextColor(color); + } + + public void setIconColor(int color) { + imageView.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); + } + + public void setIcon(int resId) { + imageView.setImageResource(resId); + } + + public void setText(String text) { + textView.setText(text); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java index c520bac35..77f7c0ad7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java @@ -19,7 +19,7 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; import android.os.Build; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; @@ -36,15 +36,18 @@ import org.telegram.messenger.R; import org.telegram.ui.Components.LayoutHelper; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.HashMap; public class ActionBarPopupWindow extends PopupWindow { + private static Method layoutInScreenMethod; private static final Field superListenerField; private static final boolean allowAnimation = Build.VERSION.SDK_INT >= 18; private static DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(); private AnimatorSet windowAnimatorSet; private boolean animationEnabled = allowAnimation; + private int dismissAnimationDuration = 150; static { Field f = null; try { @@ -86,7 +89,7 @@ public class ActionBarPopupWindow extends PopupWindow { public ActionBarPopupWindowLayout(Context context) { super(context); - backgroundDrawable = getResources().getDrawable(R.drawable.popup_fixed).mutate(); + backgroundDrawable = getResources().getDrawable(R.drawable.popup_fixed_alert2).mutate(); backgroundDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground), PorterDuff.Mode.MULTIPLY)); setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8)); @@ -283,6 +286,19 @@ public class ActionBarPopupWindow extends PopupWindow { animationEnabled = value; } + @SuppressWarnings("PrivateAPI") + public void setLayoutInScreen(boolean value) { + try { + if (layoutInScreenMethod == null) { + layoutInScreenMethod = PopupWindow.class.getDeclaredMethod("setLayoutInScreenEnabled", boolean.class); + layoutInScreenMethod.setAccessible(true); + } + layoutInScreenMethod.invoke(this, true); + } catch (Exception e) { + FileLog.e(e); + } + } + private void init() { if (superListenerField != null) { try { @@ -294,6 +310,10 @@ public class ActionBarPopupWindow extends PopupWindow { } } + public void setDismissAnimationDuration(int value) { + dismissAnimationDuration = value; + } + private void unregisterListener() { if (mSuperScrollListener != null && mViewTreeObserver != null) { if (mViewTreeObserver.isAlive()) { @@ -418,7 +438,7 @@ public class ActionBarPopupWindow extends PopupWindow { windowAnimatorSet.playTogether( ObjectAnimator.ofFloat(content, "translationY", AndroidUtilities.dp(content.showedFromBotton ? 5 : -5)), ObjectAnimator.ofFloat(content, "alpha", 0.0f)); - windowAnimatorSet.setDuration(150); + windowAnimatorSet.setDuration(dismissAnimationDuration); windowAnimatorSet.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { 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 e45671347..8e232d8e6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java @@ -60,9 +60,9 @@ public class AlertDialog extends Dialog implements Drawable.Callback { private ScrollView contentScrollView; private LinearLayout scrollContainer; private ViewTreeObserver.OnScrollChangedListener onScrollChangedListener; - private BitmapDrawable shadow[] = new BitmapDrawable[2]; - private boolean shadowVisibility[] = new boolean[2]; - private AnimatorSet shadowAnimation[] = new AnimatorSet[2]; + private BitmapDrawable[] shadow = new BitmapDrawable[2]; + private boolean[] shadowVisibility = new boolean[2]; + private AnimatorSet[] shadowAnimation = new AnimatorSet[2]; private int customViewOffset = 20; private OnCancelListener onCancelListener; @@ -541,7 +541,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback { if (LocaleController.isRTL) { child.layout(getPaddingLeft(), getPaddingTop(), getPaddingLeft() + child.getMeasuredWidth(), getPaddingTop() + child.getMeasuredHeight()); } else { - child.layout(width - getPaddingRight() - child.getMeasuredWidth(), getPaddingTop(), width - getPaddingRight() + child.getMeasuredWidth(), getPaddingTop() + child.getMeasuredHeight()); + child.layout(width - getPaddingRight() - child.getMeasuredWidth(), getPaddingTop(), width - getPaddingRight(), getPaddingTop() + child.getMeasuredHeight()); } } else if (tag == Dialog.BUTTON_NEGATIVE) { if (LocaleController.isRTL) { @@ -616,6 +616,12 @@ public class AlertDialog extends Dialog implements Drawable.Callback { super.setEnabled(enabled); setAlpha(enabled ? 1.0f : 0.5f); } + + @Override + public void setTextColor(int color) { + super.setTextColor(color); + setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(color)); + } }; textView.setMinWidth(AndroidUtilities.dp(64)); textView.setTag(Dialog.BUTTON_POSITIVE); @@ -626,7 +632,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback { // textView.setLines(1); // textView.setSingleLine(true); //TODO textView.setText(positiveButtonText.toString().toUpperCase()); - textView.setBackgroundDrawable(Theme.getRoundRectSelectorDrawable()); + textView.setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(getThemeColor(Theme.key_dialogButton))); textView.setPadding(AndroidUtilities.dp(10), 0, AndroidUtilities.dp(10), 0); buttonsLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 36, Gravity.TOP | Gravity.RIGHT)); textView.setOnClickListener(v -> { @@ -646,6 +652,12 @@ public class AlertDialog extends Dialog implements Drawable.Callback { super.setEnabled(enabled); setAlpha(enabled ? 1.0f : 0.5f); } + + @Override + public void setTextColor(int color) { + super.setTextColor(color); + setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(color)); + } }; textView.setMinWidth(AndroidUtilities.dp(64)); textView.setTag(Dialog.BUTTON_NEGATIVE); @@ -656,7 +668,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback { textView.setEllipsize(TextUtils.TruncateAt.END); textView.setSingleLine(true); textView.setText(negativeButtonText.toString().toUpperCase()); - textView.setBackgroundDrawable(Theme.getRoundRectSelectorDrawable()); + textView.setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(getThemeColor(Theme.key_dialogButton))); textView.setPadding(AndroidUtilities.dp(10), 0, AndroidUtilities.dp(10), 0); buttonsLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 36, Gravity.TOP | Gravity.RIGHT)); textView.setOnClickListener(v -> { @@ -676,6 +688,12 @@ public class AlertDialog extends Dialog implements Drawable.Callback { super.setEnabled(enabled); setAlpha(enabled ? 1.0f : 0.5f); } + + @Override + public void setTextColor(int color) { + super.setTextColor(color); + setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(color)); + } }; textView.setMinWidth(AndroidUtilities.dp(64)); textView.setTag(Dialog.BUTTON_NEUTRAL); @@ -686,7 +704,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback { textView.setEllipsize(TextUtils.TruncateAt.END); textView.setSingleLine(true); textView.setText(neutralButtonText.toString().toUpperCase()); - textView.setBackgroundDrawable(Theme.getRoundRectSelectorDrawable()); + textView.setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(getThemeColor(Theme.key_dialogButton))); textView.setPadding(AndroidUtilities.dp(10), 0, AndroidUtilities.dp(10), 0); buttonsLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 36, Gravity.TOP | Gravity.LEFT)); textView.setOnClickListener(v -> { @@ -729,6 +747,9 @@ public class AlertDialog extends Dialog implements Drawable.Callback { } else { params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE; } + if (Build.VERSION.SDK_INT >= 28) { + params.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT; + } window.setAttributes(params); } @@ -841,7 +862,11 @@ public class AlertDialog extends Dialog implements Drawable.Callback { if (cancelDialog != null) { cancelDialog.dismiss(); } - super.dismiss(); + try { + super.dismiss(); + } catch (Throwable ignore) { + + } } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BackDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BackDrawable.java index e6e1c25bf..50a32ab04 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BackDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BackDrawable.java @@ -21,7 +21,7 @@ import org.telegram.messenger.AndroidUtilities; public class BackDrawable extends Drawable { private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); - private boolean reverseAngle = false; + private boolean reverseAngle; private long lastFrameTime; private boolean animationInProgress; private float finalRotation; 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 53e67912f..6e5e4b1f0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java @@ -15,11 +15,20 @@ import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Bundle; +import android.text.TextUtils; import android.view.Menu; import android.view.View; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityManager; +import org.telegram.messenger.AccountInstance; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.ContactsController; +import org.telegram.messenger.DataQuery; import org.telegram.messenger.FileLog; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.NotificationsController; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.ConnectionsManager; @@ -289,6 +298,13 @@ public class BaseFragment { return null; } + protected void setParentActivityTitle(CharSequence title) { + Activity activity = getParentActivity(); + if (activity != null) { + activity.setTitle(title); + } + } + public void startActivityForResult(final Intent intent, final int requestCode) { if (parentLayout != null) { parentLayout.startActivityForResult(intent, requestCode); @@ -311,6 +327,10 @@ public class BaseFragment { return true; } + public boolean canBeginSlide() { + return true; + } + public void onBeginSlide() { try { if (visibleDialog != null && visibleDialog.isShowing()) { @@ -334,7 +354,16 @@ public class BaseFragment { } protected void onBecomeFullyVisible() { - + AccessibilityManager mgr = (AccessibilityManager) ApplicationLoader.applicationContext.getSystemService(Context.ACCESSIBILITY_SERVICE); + if (mgr.isEnabled()) { + ActionBar actionBar = getActionBar(); + if (actionBar != null) { + String title = actionBar.getTitle(); + if (!TextUtils.isEmpty(title)) { + setParentActivityTitle(title); + } + } + } } protected void onBecomeFullyHidden() { @@ -406,4 +435,36 @@ public class BaseFragment { public ThemeDescription[] getThemeDescriptions() { return new ThemeDescription[0]; } + + protected AccountInstance getAccountInstance() { + return AccountInstance.getInstance(currentAccount); + } + + protected MessagesController getMessagesController() { + return getAccountInstance().getMessagesController(); + } + + protected ContactsController getContactsController() { + return getAccountInstance().getContactsController(); + } + + protected DataQuery getDataQuery() { + return getAccountInstance().getDataQuery(); + } + + protected ConnectionsManager getConnectionsManager() { + return getAccountInstance().getConnectionsManager(); + } + + protected NotificationsController getNotificationsController() { + return getAccountInstance().getNotificationsController(); + } + + public NotificationCenter getNotificationCenter() { + return getAccountInstance().getNotificationCenter(); + } + + public UserConfig getUserConfig() { + return getAccountInstance().getUserConfig(); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java index 4e588884c..0b878ea0b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java @@ -23,9 +23,9 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; -import android.support.v4.view.NestedScrollingParent; -import android.support.v4.view.NestedScrollingParentHelper; -import android.support.v4.view.ViewCompat; +import androidx.core.view.NestedScrollingParent; +import androidx.core.view.NestedScrollingParentHelper; +import androidx.core.view.ViewCompat; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; @@ -37,8 +37,6 @@ import android.view.ViewGroup; import android.view.Window; import android.view.WindowInsets; import android.view.WindowManager; -import android.view.animation.AccelerateInterpolator; -import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -48,6 +46,7 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; import java.util.ArrayList; @@ -76,7 +75,7 @@ public class BottomSheet extends Dialog { private View customView; private CharSequence title; protected boolean fullWidth; - protected boolean fullscreen; + protected boolean isFullscreen; protected ColorDrawable backDrawable = new ColorDrawable(0xff000000); private boolean allowCustomAnimation = true; @@ -89,18 +88,17 @@ public class BottomSheet extends Dialog { private boolean focusable; + private boolean dimBehind = true; + private boolean allowNestedScroll = true; private Drawable shadowDrawable; - protected static int backgroundPaddingTop; - protected static int backgroundPaddingLeft; + protected int backgroundPaddingTop; + protected int backgroundPaddingLeft; private boolean applyTopPadding = true; private boolean applyBottomPadding = true; - private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(); - private AccelerateInterpolator accelerateInterpolator = new AccelerateInterpolator(); - private ArrayList itemViews = new ArrayList<>(); private Runnable dismissRunnable = this::dismiss; @@ -213,7 +211,7 @@ public class BottomSheet extends Dialog { currentAnimation = new AnimatorSet(); currentAnimation.playTogether(ObjectAnimator.ofFloat(containerView, "translationY", 0)); currentAnimation.setDuration((int) (150 * (translationY / AndroidUtilities.getPixelsInCM(0.8f, false)))); - currentAnimation.setInterpolator(new DecelerateInterpolator()); + currentAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT); currentAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -477,12 +475,12 @@ public class BottomSheet extends Dialog { super(context); setBackgroundDrawable(Theme.getSelectorDrawable(false)); - setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); + //setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); imageView = new ImageView(context); imageView.setScaleType(ImageView.ScaleType.CENTER); imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogIcon), PorterDuff.Mode.MULTIPLY)); - addView(imageView, LayoutHelper.createFrame(24, 24, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT))); + addView(imageView, LayoutHelper.createFrame(56, 48, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT))); textView = new TextView(context); textView.setLines(1); @@ -520,10 +518,10 @@ public class BottomSheet extends Dialog { if (icon != 0) { imageView.setImageResource(icon); imageView.setVisibility(VISIBLE); - textView.setPadding(LocaleController.isRTL ? 0 : AndroidUtilities.dp(56), 0, LocaleController.isRTL ? AndroidUtilities.dp(56) : 0, 0); + textView.setPadding(AndroidUtilities.dp(LocaleController.isRTL ? 16 : 72), 0, AndroidUtilities.dp(LocaleController.isRTL ? 72 : 16), 0); } else { imageView.setVisibility(INVISIBLE); - textView.setPadding(0, 0, 0, 0); + textView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); } } } @@ -540,7 +538,7 @@ public class BottomSheet extends Dialog { } } - public BottomSheet(Context context, boolean needFocus) { + public BottomSheet(Context context, boolean needFocus, int backgroundType) { super(context, R.style.TransparentDialog); if (Build.VERSION.SDK_INT >= 21) { @@ -550,7 +548,11 @@ public class BottomSheet extends Dialog { touchSlop = vc.getScaledTouchSlop(); Rect padding = new Rect(); - shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow).mutate(); + if (backgroundType == 0) { + shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow).mutate(); + } else if (backgroundType == 1) { + shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow_round).mutate(); + } shadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); shadowDrawable.getPadding(padding); backgroundPaddingLeft = padding.left; @@ -606,9 +608,6 @@ public class BottomSheet extends Dialog { containerView.setBackgroundDrawable(shadowDrawable); containerView.setPadding(backgroundPaddingLeft, (applyTopPadding ? AndroidUtilities.dp(8) : 0) + backgroundPaddingTop - 1, backgroundPaddingLeft, (applyBottomPadding ? AndroidUtilities.dp(8) : 0)); } - if (Build.VERSION.SDK_INT >= 21) { - containerView.setFitsSystemWindows(true); - } containerView.setVisibility(View.INVISIBLE); container.addView(containerView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM)); @@ -660,7 +659,7 @@ public class BottomSheet extends Dialog { if (!focusable) { params.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; } - if (fullscreen) { + if (isFullscreen) { if (Build.VERSION.SDK_INT >= 21) { params.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | @@ -669,6 +668,9 @@ public class BottomSheet extends Dialog { params.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN; } params.height = ViewGroup.LayoutParams.MATCH_PARENT; + if (Build.VERSION.SDK_INT >= 28) { + params.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + } window.setAttributes(params); } @@ -690,7 +692,7 @@ public class BottomSheet extends Dialog { cancelSheetAnimation(); containerView.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x + backgroundPaddingLeft * 2, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.y, View.MeasureSpec.AT_MOST)); if (showWithoutAnimation) { - backDrawable.setAlpha(51); + backDrawable.setAlpha(dimBehind ? 51 : 0); containerView.setTranslationY(0); return; } @@ -786,10 +788,10 @@ public class BottomSheet extends Dialog { AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether( ObjectAnimator.ofFloat(containerView, "translationY", 0), - ObjectAnimator.ofInt(backDrawable, "alpha", 51)); - animatorSet.setDuration(200); + ObjectAnimator.ofInt(backDrawable, "alpha", dimBehind ? 51 : 0)); + animatorSet.setDuration(400); animatorSet.setStartDelay(20); - animatorSet.setInterpolator(new DecelerateInterpolator()); + animatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); animatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -832,6 +834,10 @@ public class BottomSheet extends Dialog { return tag; } + public void setDimBehind(boolean value) { + dimBehind = value; + } + public void setItemText(int item, CharSequence text) { if (item < 0 || item >= itemViews.size()) { return; @@ -849,6 +855,12 @@ public class BottomSheet extends Dialog { cell.imageView.setColorFilter(new PorterDuffColorFilter(icon, PorterDuff.Mode.MULTIPLY)); } + public void setItems(CharSequence[] i, int[] icons, final OnClickListener listener) { + items = i; + itemIcons = icons; + onClickListener = listener; + } + public void setTitleColor(int color) { if (titleView == null) { return; @@ -872,7 +884,7 @@ public class BottomSheet extends Dialog { ObjectAnimator.ofInt(backDrawable, "alpha", 0) ); animatorSet.setDuration(180); - animatorSet.setInterpolator(new AccelerateInterpolator()); + animatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT); animatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -925,7 +937,7 @@ public class BottomSheet extends Dialog { } else { animatorSet.setDuration(180); } - animatorSet.setInterpolator(new AccelerateInterpolator()); + animatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT); animatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -973,12 +985,16 @@ public class BottomSheet extends Dialog { private BottomSheet bottomSheet; + public Builder(Context context, boolean needFocus, int backgroundType) { + bottomSheet = new BottomSheet(context, needFocus, backgroundType); + } + public Builder(Context context) { - bottomSheet = new BottomSheet(context, false); + bottomSheet = new BottomSheet(context, false, 0); } public Builder(Context context, boolean needFocus) { - bottomSheet = new BottomSheet(context, needFocus); + bottomSheet = new BottomSheet(context, needFocus, 0); } public Builder setItems(CharSequence[] items, final OnClickListener onClickListener) { @@ -1008,6 +1024,11 @@ public class BottomSheet extends Dialog { return bottomSheet; } + public BottomSheet setDimBehind(boolean value) { + bottomSheet.dimBehind = value; + return bottomSheet; + } + public BottomSheet show() { bottomSheet.show(); return bottomSheet; @@ -1048,7 +1069,7 @@ public class BottomSheet extends Dialog { } public BottomSheet setUseFullscreen(boolean value) { - bottomSheet.fullscreen = value; + bottomSheet.isFullscreen = value; return bottomSheet; } } @@ -1060,6 +1081,13 @@ public class BottomSheet extends Dialog { return 0; } + protected int getRightInset() { + if (lastInsets != null && Build.VERSION.SDK_INT >= 21) { + return lastInsets.getSystemWindowInsetRight(); + } + return 0; + } + public void onConfigurationChanged(android.content.res.Configuration newConfig) { } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java index d6ad6c9d7..bdbda5b4a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java @@ -20,13 +20,15 @@ import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; -import android.support.annotation.Keep; +import androidx.annotation.Keep; +import android.view.DisplayCutout; import android.view.Gravity; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewGroup; import android.view.WindowInsets; +import android.view.accessibility.AccessibilityEvent; import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; import android.widget.ListView; @@ -57,6 +59,11 @@ public class DrawerLayoutContainer extends FrameLayout { private int paddingTop; private Paint scrimPaint = new Paint(); + private Paint backgroundPaint = new Paint(); + + private int behindKeyboardColor; + + private boolean hasCutout; private Object lastInsets; private boolean inLayout; @@ -80,10 +87,18 @@ public class DrawerLayoutContainer extends FrameLayout { setFitsSystemWindows(true); setOnApplyWindowInsetsListener((v, insets) -> { final DrawerLayoutContainer drawerLayout = (DrawerLayoutContainer) v; + if (AndroidUtilities.statusBarHeight != insets.getSystemWindowInsetTop()) { + drawerLayout.requestLayout(); + } AndroidUtilities.statusBarHeight = insets.getSystemWindowInsetTop(); lastInsets = insets; drawerLayout.setWillNotDraw(insets.getSystemWindowInsetTop() <= 0 && getBackground() == null); - drawerLayout.requestLayout(); + + if (Build.VERSION.SDK_INT >= 28) { + DisplayCutout cutout = insets.getDisplayCutout(); + hasCutout = cutout != null && cutout.getBoundingRects().size() != 0; + } + invalidate(); return insets.consumeSystemWindowInsets(); }); setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); @@ -220,6 +235,15 @@ public class DrawerLayoutContainer extends FrameLayout { ((ListView) drawerLayout).setSelectionFromTop(0, 0); } } + if (Build.VERSION.SDK_INT >= 19) { + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + if (child != drawerLayout) { + child.setImportantForAccessibility(opened ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); + } + } + } + sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); } private void setScrimOpacity(float value) { @@ -300,7 +324,7 @@ public class DrawerLayoutContainer extends FrameLayout { float dx = (int) (ev.getX() - startedTrackingX); float dy = Math.abs((int) ev.getY() - startedTrackingY); velocityTracker.addMovement(ev); - if (maybeStartTracking && !startedTracking && (dx > 0 && dx / 3.0f > Math.abs(dy) && Math.abs(dx) >= AndroidUtilities.getPixelsInCM(0.2f, true) || dx < 0 && Math.abs(dx) >= Math.abs(dy) && Math.abs(dx) >= AndroidUtilities.getPixelsInCM(0.4f, true))) { + if (maybeStartTracking && !startedTracking && (dx > 0 && dx / 3.0f > Math.abs(dy) && Math.abs(dx) >= AndroidUtilities.getPixelsInCM(0.2f, true) || drawerOpened && dx < 0 && Math.abs(dx) >= Math.abs(dy) && Math.abs(dx) >= AndroidUtilities.getPixelsInCM(0.4f, true))) { prepareForDrawerOpen(ev); startedTrackingX = (int) ev.getX(); requestDisallowInterceptTouchEvent(true); @@ -372,7 +396,7 @@ public class DrawerLayoutContainer extends FrameLayout { if (drawerLayout != child) { child.layout(lp.leftMargin, lp.topMargin + getPaddingTop(), lp.leftMargin + child.getMeasuredWidth(), lp.topMargin + child.getMeasuredHeight() + getPaddingTop()); } else { - child.layout(-child.getMeasuredWidth(), lp.topMargin + getPaddingTop(), 0, lp.topMargin + child.getMeasuredHeight() + + getPaddingTop()); + child.layout(-child.getMeasuredWidth(), lp.topMargin + getPaddingTop(), 0, lp.topMargin + child.getMeasuredHeight() + +getPaddingTop()); } } else { try { @@ -458,6 +482,11 @@ public class DrawerLayoutContainer extends FrameLayout { } } + public void setBehindKeyboardColor(int color) { + behindKeyboardColor = color; + invalidate(); + } + @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { if (!allowDrawContent) { @@ -480,7 +509,7 @@ public class DrawerLayoutContainer extends FrameLayout { continue; } - final int vright = v.getRight(); + final int vright = (int) v.getX() + v.getMeasuredWidth(); if (vright > clipLeft) { clipLeft = vright; } @@ -508,8 +537,41 @@ public class DrawerLayoutContainer extends FrameLayout { return result; } + @Override + protected void onDraw(Canvas canvas) { + if (Build.VERSION.SDK_INT >= 21 && lastInsets != null) { + WindowInsets insets = (WindowInsets) lastInsets; + + int bottomInset = insets.getSystemWindowInsetBottom(); + if (bottomInset > 0) { + backgroundPaint.setColor(behindKeyboardColor); + canvas.drawRect(0, getMeasuredHeight() - bottomInset, getMeasuredWidth(), getMeasuredHeight(), backgroundPaint); + } + + if (hasCutout) { + backgroundPaint.setColor(0xff000000); + int left = insets.getSystemWindowInsetLeft(); + if (left != 0) { + canvas.drawRect(0, 0, left, getMeasuredHeight(), backgroundPaint); + } + int right = insets.getSystemWindowInsetRight(); + if (right != 0) { + canvas.drawRect(right, 0, getMeasuredWidth(), getMeasuredHeight(), backgroundPaint); + } + } + } + } + @Override public boolean hasOverlappingRendering() { return false; } + + @Override + public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) { + if (drawerOpened && child != drawerLayout) { + return false; + } + return super.onRequestSendAccessibilityEvent(child, event); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/MenuDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/MenuDrawable.java index b44ec4116..7ab821aa6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/MenuDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/MenuDrawable.java @@ -20,20 +20,24 @@ import org.telegram.messenger.AndroidUtilities; public class MenuDrawable extends Drawable { private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); - private boolean reverseAngle = false; + private boolean reverseAngle; private long lastFrameTime; private boolean animationInProgress; private float finalRotation; private float currentRotation; private int currentAnimationTime; + private boolean rotateToBack = true; private DecelerateInterpolator interpolator = new DecelerateInterpolator(); public MenuDrawable() { super(); - paint.setColor(0xffffffff); paint.setStrokeWidth(AndroidUtilities.dp(2)); } + public void setRotateToBack(boolean value) { + rotateToBack = value; + } + public void setRotation(float rotation, boolean animated) { lastFrameTime = 0; if (currentRotation == 1) { @@ -79,12 +83,29 @@ public class MenuDrawable extends Drawable { canvas.save(); canvas.translate(getIntrinsicWidth() / 2, getIntrinsicHeight() / 2); - canvas.rotate(currentRotation * (reverseAngle ? -180 : 180)); - canvas.drawLine(-AndroidUtilities.dp(9), 0, AndroidUtilities.dp(9) - AndroidUtilities.dp(3.0f) * currentRotation, 0, paint); - float endYDiff = AndroidUtilities.dp(5) * (1 - Math.abs(currentRotation)) - AndroidUtilities.dp(0.5f) * Math.abs(currentRotation); - float endXDiff = AndroidUtilities.dp(9) - AndroidUtilities.dp(2.5f) * Math.abs(currentRotation); - float startYDiff = AndroidUtilities.dp(5) + AndroidUtilities.dp(2.0f) * Math.abs(currentRotation); - float startXDiff = -AndroidUtilities.dp(9) + AndroidUtilities.dp(7.5f) * Math.abs(currentRotation); + float endYDiff; + float endXDiff; + float startYDiff; + float startXDiff; + int color1 = Theme.getColor(Theme.key_actionBarDefaultIcon); + if (rotateToBack) { + canvas.rotate(currentRotation * (reverseAngle ? -180 : 180)); + paint.setColor(color1); + canvas.drawLine(-AndroidUtilities.dp(9), 0, AndroidUtilities.dp(9) - AndroidUtilities.dp(3.0f) * currentRotation, 0, paint); + endYDiff = AndroidUtilities.dp(5) * (1 - Math.abs(currentRotation)) - AndroidUtilities.dp(0.5f) * Math.abs(currentRotation); + endXDiff = AndroidUtilities.dp(9) - AndroidUtilities.dp(2.5f) * Math.abs(currentRotation); + startYDiff = AndroidUtilities.dp(5) + AndroidUtilities.dp(2.0f) * Math.abs(currentRotation); + startXDiff = -AndroidUtilities.dp(9) + AndroidUtilities.dp(7.5f) * Math.abs(currentRotation); + } else { + canvas.rotate(currentRotation * (reverseAngle ? -225 : 135)); + int color2 = Theme.getColor(Theme.key_actionBarActionModeDefaultIcon); + paint.setColor(AndroidUtilities.getOffsetColor(color1, color2, currentRotation, 1.0f)); + canvas.drawLine(-AndroidUtilities.dp(9) + AndroidUtilities.dp(1) * currentRotation, 0, AndroidUtilities.dp(9) - AndroidUtilities.dp(1) * currentRotation, 0, paint); + endYDiff = AndroidUtilities.dp(5) * (1 - Math.abs(currentRotation)) - AndroidUtilities.dp(0.5f) * Math.abs(currentRotation); + endXDiff = AndroidUtilities.dp(9) - AndroidUtilities.dp(9) * Math.abs(currentRotation); + startYDiff = AndroidUtilities.dp(5) + AndroidUtilities.dp(3.0f) * Math.abs(currentRotation); + startXDiff = -AndroidUtilities.dp(9) + AndroidUtilities.dp(9) * Math.abs(currentRotation); + } canvas.drawLine(startXDiff, -startYDiff, endXDiff, -endYDiff, paint); canvas.drawLine(startXDiff, startYDiff, endXDiff, endYDiff, paint); canvas.restore(); @@ -97,7 +118,7 @@ public class MenuDrawable extends Drawable { @Override public void setColorFilter(ColorFilter cf) { - paint.setColorFilter(cf); + } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java index db7383339..b97f37ca6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java @@ -24,6 +24,7 @@ import android.text.TextPaint; import android.text.TextUtils; import android.view.Gravity; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import org.telegram.messenger.AndroidUtilities; @@ -65,6 +66,7 @@ public class SimpleTextView extends View implements Drawable.Callback { public SimpleTextView(Context context) { super(context); textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); } public void setTextColor(int color) { @@ -252,6 +254,10 @@ public class SimpleTextView extends View implements Drawable.Callback { } } + public Drawable getRightDrawable() { + return rightDrawable; + } + public void setRightDrawable(Drawable drawable) { if (rightDrawable == drawable) { return; @@ -268,12 +274,17 @@ public class SimpleTextView extends View implements Drawable.Callback { } } + public void setSideDrawablesColor(int color) { + Theme.setDrawableColor(rightDrawable, color); + Theme.setDrawableColor(leftDrawable, color); + } + public boolean setText(CharSequence value) { return setText(value, false); } public boolean setText(CharSequence value, boolean force) { - if (text == null && value == null || !force && text != null && value != null && text.equals(value)) { + if (text == null && value == null || !force && text != null && text.equals(value)) { return false; } text = value; @@ -387,7 +398,7 @@ public class SimpleTextView extends View implements Drawable.Callback { if (offsetX + textOffsetX != 0 || offsetY != 0 || scrollingOffset != 0) { canvas.restore(); } - if (scrollNonFitText && textDoesNotFit) { + if (scrollNonFitText && (textDoesNotFit || scrollingOffset != 0)) { if (scrollingOffset < AndroidUtilities.dp(10)) { fadeDrawable.setAlpha((int) (255 * (scrollingOffset / AndroidUtilities.dp(10)))); } else if (scrollingOffset > totalWidth + AndroidUtilities.dp(DIST_BETWEEN_SCROLLING_TEXT) - AndroidUtilities.dp(10)) { @@ -419,7 +430,7 @@ public class SimpleTextView extends View implements Drawable.Callback { } private void updateScrollAnimation() { - if (!scrollNonFitText || !textDoesNotFit) { + if (!scrollNonFitText || !textDoesNotFit && scrollingOffset == 0) { return; } long newUpdateTime = SystemClock.uptimeMillis(); @@ -463,4 +474,12 @@ public class SimpleTextView extends View implements Drawable.Callback { public boolean hasOverlappingRendering() { return false; } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setVisibleToUser(true); + info.setClassName("android.widget.TextView"); + info.setText(text); + } } 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 a4e553d93..303f24a74 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -45,6 +45,13 @@ import android.text.TextPaint; import android.text.TextUtils; import android.util.StateSet; +import com.airbnb.lottie.LottieCompositionFactory; +import com.airbnb.lottie.LottieDrawable; +import com.airbnb.lottie.LottieProperty; +import com.airbnb.lottie.SimpleColorFilter; +import com.airbnb.lottie.model.KeyPath; +import com.airbnb.lottie.value.LottieValueCallback; + import org.json.JSONArray; import org.json.JSONObject; import org.telegram.messenger.AndroidUtilities; @@ -60,6 +67,7 @@ import org.telegram.messenger.SharedConfig; import org.telegram.messenger.Utilities; import org.telegram.messenger.time.SunDate; import org.telegram.ui.Components.CombinedDrawable; +import org.telegram.ui.Components.ScamDrawable; import org.telegram.ui.Components.ThemeEditorView; import java.io.File; @@ -330,25 +338,36 @@ public class Theme { public static TextPaint dialogs_namePaint; public static TextPaint dialogs_nameEncryptedPaint; public static TextPaint dialogs_messagePaint; + public static TextPaint dialogs_messageNamePaint; public static TextPaint dialogs_messagePrintingPaint; public static TextPaint dialogs_timePaint; public static TextPaint dialogs_countTextPaint; + public static TextPaint dialogs_archiveTextPaint; public static TextPaint dialogs_onlinePaint; public static TextPaint dialogs_offlinePaint; public static Drawable dialogs_checkDrawable; public static Drawable dialogs_halfCheckDrawable; public static Drawable dialogs_clockDrawable; public static Drawable dialogs_errorDrawable; + public static Drawable dialogs_reorderDrawable; public static Drawable dialogs_lockDrawable; public static Drawable dialogs_groupDrawable; public static Drawable dialogs_broadcastDrawable; public static Drawable dialogs_botDrawable; public static Drawable dialogs_muteDrawable; public static Drawable dialogs_verifiedDrawable; + public static ScamDrawable dialogs_scamDrawable; public static Drawable dialogs_verifiedCheckDrawable; public static Drawable dialogs_pinnedDrawable; public static Drawable dialogs_mentionDrawable; public static Drawable dialogs_holidayDrawable; + public static LottieDrawable dialogs_archiveAvatarDrawable; + public static Drawable dialogs_archiveDrawable; + public static Drawable dialogs_unarchiveDrawable; + public static Drawable dialogs_pinArchiveDrawable; + public static Drawable dialogs_unpinArchiveDrawable; + public static boolean dialogs_archiveDrawableRecolored; + public static boolean dialogs_archiveAvatarDrawableRecolored; private static int dialogs_holidayDrawableOffsetX; private static int dialogs_holidayDrawableOffsetY; private static long lastHolidayCheckTime; @@ -530,7 +549,14 @@ public class Theme { public static final String key_dialogCameraIcon = "dialogCameraIcon"; public static final String key_dialog_inlineProgressBackground = "dialog_inlineProgressBackground"; public static final String key_dialog_inlineProgress = "dialog_inlineProgress"; - + public static final String key_dialogSearchBackground = "dialogSearchBackground"; + public static final String key_dialogSearchHint = "dialogSearchHint"; + public static final String key_dialogSearchIcon = "dialogSearchIcon"; + public static final String key_dialogSearchText = "dialogSearchText"; + public static final String key_dialogFloatingButton = "dialogFloatingButton"; + public static final String key_dialogFloatingButtonPressed = "dialogFloatingButtonPressed"; + public static final String key_dialogFloatingIcon = "dialogFloatingIcon"; + public static final String key_dialogShadowLine = "dialogShadowLine"; public static final String key_windowBackgroundWhite = "windowBackgroundWhite"; public static final String key_windowBackgroundUnchecked = "windowBackgroundUnchecked"; @@ -621,6 +647,8 @@ public class Theme { public static final String key_avatar_text = "avatar_text"; public static final String key_avatar_backgroundSaved = "avatar_backgroundSaved"; + public static final String key_avatar_backgroundArchived = "avatar_backgroundArchived"; + public static final String key_avatar_backgroundArchivedHidden = "avatar_backgroundArchivedHidden"; public static final String key_avatar_backgroundRed = "avatar_backgroundRed"; public static final String key_avatar_backgroundOrange = "avatar_backgroundOrange"; public static final String key_avatar_backgroundViolet = "avatar_backgroundViolet"; @@ -660,19 +688,38 @@ public class Theme { public static final String key_actionBarDefaultSearch = "actionBarDefaultSearch"; public static final String key_actionBarDefaultSearchPlaceholder = "actionBarDefaultSearchPlaceholder"; public static final String key_actionBarDefaultSubmenuItem = "actionBarDefaultSubmenuItem"; + public static final String key_actionBarDefaultSubmenuItemIcon = "actionBarDefaultSubmenuItemIcon"; public static final String key_actionBarDefaultSubmenuBackground = "actionBarDefaultSubmenuBackground"; + + public static final String key_actionBarDefaultArchived = "actionBarDefaultArchived"; + public static final String key_actionBarDefaultArchivedSelector = "actionBarDefaultArchivedSelector"; + public static final String key_actionBarDefaultArchivedIcon = "actionBarDefaultArchivedIcon"; + public static final String key_actionBarDefaultArchivedTitle = "actionBarDefaultArchivedTitle"; + public static final String key_actionBarDefaultArchivedSearch = "actionBarDefaultArchivedSearch"; + public static final String key_actionBarDefaultArchivedSearchPlaceholder = "actionBarDefaultSearchArchivedPlaceholder"; + 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"; public static final String key_chats_unreadCounterText = "chats_unreadCounterText"; public static final String key_chats_name = "chats_name"; + public static final String key_chats_nameArchived = "chats_nameArchived"; public static final String key_chats_secretName = "chats_secretName"; public static final String key_chats_secretIcon = "chats_secretIcon"; public static final String key_chats_nameIcon = "chats_nameIcon"; public static final String key_chats_pinnedIcon = "chats_pinnedIcon"; + public static final String key_chats_archiveBackground = "chats_archiveBackground"; + public static final String key_chats_archivePinBackground = "chats_archivePinBackground"; + public static final String key_chats_archiveIcon = "chats_archiveIcon"; + public static final String key_chats_archiveText = "chats_archiveText"; public static final String key_chats_message = "chats_message"; + public static final String key_chats_messageArchived = "chats_messageArchived"; + public static final String key_chats_message_threeLines = "chats_message_threeLines"; public static final String key_chats_draft = "chats_draft"; public static final String key_chats_nameMessage = "chats_nameMessage"; + public static final String key_chats_nameMessageArchived = "chats_nameMessageArchived"; + public static final String key_chats_nameMessage_threeLines = "chats_nameMessage_threeLines"; + public static final String key_chats_nameMessageArchived_threeLines = "chats_nameMessageArchived_threeLines"; public static final String key_chats_attachMessage = "chats_attachMessage"; public static final String key_chats_actionMessage = "chats_actionMessage"; public static final String key_chats_date = "chats_date"; @@ -709,6 +756,8 @@ public class Theme { public static final String key_chat_attachCameraIcon4 = "chat_attachCameraIcon4"; public static final String key_chat_attachCameraIcon5 = "chat_attachCameraIcon5"; public static final String key_chat_attachCameraIcon6 = "chat_attachCameraIcon6"; + public static final String key_chat_attachMediaBanBackground = "chat_attachMediaBanBackground"; + public static final String key_chat_attachMediaBanText = "chat_attachMediaBanText"; public static final String key_chat_attachGalleryBackground = "chat_attachGalleryBackground"; //public static final String key_chat_attachGalleryBackgroundPressed = "chat_attachGalleryBackgroundPressed"; @@ -946,24 +995,26 @@ public class Theme { public static final String key_chat_emojiPanelBadgeBackground = "chat_emojiPanelBadgeBackground"; public static final String key_chat_emojiPanelBadgeText = "chat_emojiPanelBadgeText"; public static final String key_chat_emojiSearchBackground = "chat_emojiSearchBackground"; + public static final String key_chat_emojiSearchIcon = "chat_emojiSearchIcon"; public static final String key_chat_emojiPanelShadowLine = "chat_emojiPanelShadowLine"; public static final String key_chat_emojiPanelEmptyText = "chat_emojiPanelEmptyText"; public static final String key_chat_emojiPanelIcon = "chat_emojiPanelIcon"; + public static final String key_chat_emojiBottomPanelIcon = "chat_emojiBottomPanelIcon"; public static final String key_chat_emojiPanelIconSelected = "chat_emojiPanelIconSelected"; public static final String key_chat_emojiPanelStickerPackSelector = "chat_emojiPanelStickerPackSelector"; - public static final String key_chat_emojiPanelIconSelector = "chat_emojiPanelIconSelector"; + public static final String key_chat_emojiPanelStickerPackSelectorLine = "chat_emojiPanelStickerPackSelectorLine"; public static final String key_chat_emojiPanelBackspace = "chat_emojiPanelBackspace"; public static final String key_chat_emojiPanelMasksIcon = "chat_emojiPanelMasksIcon"; public static final String key_chat_emojiPanelMasksIconSelected = "chat_emojiPanelMasksIconSelected"; public static final String key_chat_emojiPanelTrendingTitle = "chat_emojiPanelTrendingTitle"; public static final String key_chat_emojiPanelStickerSetName = "chat_emojiPanelStickerSetName"; + public static final String key_chat_emojiPanelStickerSetNameHighlight = "chat_emojiPanelStickerSetNameHighlight"; public static final String key_chat_emojiPanelStickerSetNameIcon = "chat_emojiPanelStickerSetNameIcon"; public static final String key_chat_emojiPanelTrendingDescription = "chat_emojiPanelTrendingDescription"; public static final String key_chat_botKeyboardButtonText = "chat_botKeyboardButtonText"; public static final String key_chat_botKeyboardButtonBackground = "chat_botKeyboardButtonBackground"; public static final String key_chat_botKeyboardButtonBackgroundPressed = "chat_botKeyboardButtonBackgroundPressed"; public static final String key_chat_emojiPanelNewTrending = "chat_emojiPanelNewTrending"; - public static final String key_chat_editDoneIcon = "chat_editDoneIcon"; public static final String key_chat_messagePanelVoicePressed = "chat_messagePanelVoicePressed"; public static final String key_chat_messagePanelVoiceBackground = "chat_messagePanelVoiceBackground"; public static final String key_chat_messagePanelVoiceShadow = "chat_messagePanelVoiceShadow"; @@ -1004,6 +1055,7 @@ public class Theme { public static final String key_sharedMedia_linkPlaceholder = "sharedMedia_linkPlaceholder"; public static final String key_sharedMedia_linkPlaceholderText = "sharedMedia_linkPlaceholderText"; public static final String key_sharedMedia_photoPlaceholder = "sharedMedia_photoPlaceholder"; + public static final String key_sharedMedia_actionMode = "sharedMedia_actionMode"; public static final String key_featuredStickers_addedIcon = "featuredStickers_addedIcon"; public static final String key_featuredStickers_buttonProgress = "featuredStickers_buttonProgress"; @@ -1068,6 +1120,9 @@ public class Theme { public static final String key_undo_cancelColor = "undo_cancelColor"; public static final String key_undo_infoColor = "undo_infoColor"; + public static final String key_sheet_scrollUp = "key_sheet_scrollUp"; + public static final String key_sheet_other = "key_sheet_other"; + //ununsed public static final String key_chat_outBroadcast = "chat_outBroadcast"; public static final String key_chat_mediaBroadcast = "chat_mediaBroadcast"; @@ -1109,7 +1164,7 @@ public class Theme { defaultColors.put(key_dialogTextGray3, 0xff999999); defaultColors.put(key_dialogTextGray4, 0xffb3b3b3); defaultColors.put(key_dialogTextHint, 0xff979797); - defaultColors.put(key_dialogIcon, 0xff8a8a8a); + defaultColors.put(key_dialogIcon, 0xff676b70); defaultColors.put(key_dialogRedIcon, 0xffe14d4d); defaultColors.put(key_dialogGrayLine, 0xffd2d2d2); defaultColors.put(key_dialogTopBackground, 0xff6fb2e5); @@ -1127,13 +1182,21 @@ public class Theme { defaultColors.put(key_dialogButton, 0xff4991cc); defaultColors.put(key_dialogButtonSelector, 0x0f000000); defaultColors.put(key_dialogScrollGlow, 0xfff5f6f7); - defaultColors.put(key_dialogRoundCheckBox, 0xff3ec1f9); + defaultColors.put(key_dialogRoundCheckBox, 0xff4cb4f5); defaultColors.put(key_dialogRoundCheckBoxCheck, 0xffffffff); defaultColors.put(key_dialogBadgeBackground, 0xff3ec1f9); defaultColors.put(key_dialogBadgeText, 0xffffffff); defaultColors.put(key_dialogCameraIcon, 0xffffffff); defaultColors.put(key_dialog_inlineProgressBackground, 0xf6f0f2f5); defaultColors.put(key_dialog_inlineProgress, 0xff6b7378); + defaultColors.put(key_dialogSearchBackground, 0xfff2f4f5); + defaultColors.put(key_dialogSearchHint, 0xff98a0a7); + defaultColors.put(key_dialogSearchIcon, 0xffa1a8af); + defaultColors.put(key_dialogSearchText, 0xff222222); + defaultColors.put(key_dialogFloatingButton, 0xff4cb4f5); + defaultColors.put(key_dialogFloatingButtonPressed, 0xff4cb4f5); + defaultColors.put(key_dialogFloatingIcon, 0xffffffff); + defaultColors.put(key_dialogShadowLine, 0x12000000); defaultColors.put(key_windowBackgroundWhite, 0xffffffff); defaultColors.put(key_windowBackgroundUnchecked, 0xff9da7b1); @@ -1213,6 +1276,8 @@ public class Theme { defaultColors.put(key_avatar_text, 0xffffffff); defaultColors.put(key_avatar_backgroundSaved, 0xff66bffa); + defaultColors.put(key_avatar_backgroundArchived, 0xffa9b6c1); + defaultColors.put(key_avatar_backgroundArchivedHidden, 0xffc6c9cc); defaultColors.put(key_avatar_backgroundRed, 0xffe56555); defaultColors.put(key_avatar_backgroundOrange, 0xfff28c48); defaultColors.put(key_avatar_backgroundViolet, 0xff8e85ee); @@ -1232,15 +1297,15 @@ public class Theme { defaultColors.put(key_avatar_nameInMessageOrange, 0xffd87b29); defaultColors.put(key_avatar_nameInMessageViolet, 0xff4e92cc); defaultColors.put(key_avatar_nameInMessageGreen, 0xff50b232); - defaultColors.put(key_avatar_nameInMessageCyan, 0xff42b1a8); + defaultColors.put(key_avatar_nameInMessageCyan, 0xff379eb8); defaultColors.put(key_avatar_nameInMessageBlue, 0xff4e92cc); defaultColors.put(key_avatar_nameInMessagePink, 0xff4e92cc); defaultColors.put(key_actionBarDefault, 0xff527da3); defaultColors.put(key_actionBarDefaultIcon, 0xffffffff); defaultColors.put(key_actionBarActionModeDefault, 0xffffffff); - defaultColors.put(key_actionBarActionModeDefaultTop, 0x99000000); - defaultColors.put(key_actionBarActionModeDefaultIcon, 0xff737373); + defaultColors.put(key_actionBarActionModeDefaultTop, 0x10000000); + defaultColors.put(key_actionBarActionModeDefaultIcon, 0xff676a6f); defaultColors.put(key_actionBarDefaultTitle, 0xffffffff); defaultColors.put(key_actionBarDefaultSubtitle, 0xffd5e8f7); defaultColors.put(key_actionBarDefaultSelector, 0xff406d94); @@ -1248,24 +1313,42 @@ public class Theme { defaultColors.put(key_actionBarDefaultSearch, 0xffffffff); defaultColors.put(key_actionBarDefaultSearchPlaceholder, 0x88ffffff); defaultColors.put(key_actionBarDefaultSubmenuItem, 0xff222222); + defaultColors.put(key_actionBarDefaultSubmenuItemIcon, 0xff676b70); defaultColors.put(key_actionBarDefaultSubmenuBackground, 0xffffffff); defaultColors.put(key_actionBarActionModeDefaultSelector, 0xfff0f0f0); - defaultColors.put(key_chats_onlineCircle, 0xff32a9e6); + defaultColors.put(key_actionBarDefaultArchived, 0xff6f7a87); + defaultColors.put(key_actionBarDefaultArchivedSelector, 0xff5e6772); + defaultColors.put(key_actionBarDefaultArchivedIcon, 0xffffffff); + defaultColors.put(key_actionBarDefaultArchivedTitle, 0xffffffff); + defaultColors.put(key_actionBarDefaultArchivedSearch, 0xffffffff); + defaultColors.put(key_actionBarDefaultArchivedSearchPlaceholder, 0x88ffffff); + + defaultColors.put(key_chats_onlineCircle, 0xff4bcb1c); defaultColors.put(key_chats_unreadCounter, 0xff4ecc5e); - defaultColors.put(key_chats_unreadCounterMuted, 0xffc7c7c7); + defaultColors.put(key_chats_unreadCounterMuted, 0xffc6c9cc); defaultColors.put(key_chats_unreadCounterText, 0xffffffff); + defaultColors.put(key_chats_archiveBackground, 0xff66a9e0); + defaultColors.put(key_chats_archivePinBackground, 0xff9faab3); + defaultColors.put(key_chats_archiveIcon, 0xffffffff); + defaultColors.put(key_chats_archiveText, 0xffffffff); defaultColors.put(key_chats_name, 0xff222222); + defaultColors.put(key_chats_nameArchived, 0xff525252); defaultColors.put(key_chats_secretName, 0xff00a60e); defaultColors.put(key_chats_secretIcon, 0xff19b126); defaultColors.put(key_chats_nameIcon, 0xff242424); defaultColors.put(key_chats_pinnedIcon, 0xffa8a8a8); - defaultColors.put(key_chats_message, 0xff8f8f8f); + defaultColors.put(key_chats_message, 0xff8b8d8f); + defaultColors.put(key_chats_messageArchived, 0xff919191); + defaultColors.put(key_chats_message_threeLines, 0xff8e9091); defaultColors.put(key_chats_draft, 0xffdd4b39); - defaultColors.put(key_chats_nameMessage, 0xff4d83b3); - defaultColors.put(key_chats_attachMessage, 0xff4d83b3); - defaultColors.put(key_chats_actionMessage, 0xff4d83b3); - defaultColors.put(key_chats_date, 0xff999999); + defaultColors.put(key_chats_nameMessage, 0xff3c7eb0); + defaultColors.put(key_chats_nameMessageArchived, 0xff8b8d8f); + defaultColors.put(key_chats_nameMessage_threeLines, 0xff424449); + defaultColors.put(key_chats_nameMessageArchived_threeLines, 0xff5e5e5e); + defaultColors.put(key_chats_attachMessage, 0xff3c7eb0); + defaultColors.put(key_chats_actionMessage, 0xff3c7eb0); + defaultColors.put(key_chats_date, 0xff95999C); defaultColors.put(key_chats_pinnedOverlay, 0x08000000); defaultColors.put(key_chats_tabletSelectedOverlay, 0x0f000000); defaultColors.put(key_chats_sentCheck, 0xff46aa36); @@ -1274,7 +1357,7 @@ public class Theme { defaultColors.put(key_chats_sentErrorIcon, 0xffffffff); defaultColors.put(key_chats_verifiedBackground, 0xff33a8e6); defaultColors.put(key_chats_verifiedCheck, 0xffffffff); - defaultColors.put(key_chats_muteIcon, 0xffa8a8a8); + defaultColors.put(key_chats_muteIcon, 0xffbdc1c4); defaultColors.put(key_chats_mentionIcon, 0xffffffff); defaultColors.put(key_chats_menuBackground, 0xffffffff); defaultColors.put(key_chats_menuItemText, 0xff444444); @@ -1298,6 +1381,8 @@ public class Theme { defaultColors.put(key_chat_attachCameraIcon4, 0xffb455e0); defaultColors.put(key_chat_attachCameraIcon5, 0xff61d061); defaultColors.put(key_chat_attachCameraIcon6, 0xfffec125); + defaultColors.put(key_chat_attachMediaBanBackground, 0xff464646); + defaultColors.put(key_chat_attachMediaBanText, 0xffffffff); defaultColors.put(key_chat_attachGalleryBackground, 0xffa47ad9); //defaultColors.put(key_chat_attachGalleryBackgroundPressed, 0xffa47ad9); @@ -1332,15 +1417,15 @@ public class Theme { defaultColors.put(key_chat_lockIcon, 0xffffffff); defaultColors.put(key_chat_muteIcon, 0xffb1cce3); defaultColors.put(key_chat_inBubble, 0xffffffff); - defaultColors.put(key_chat_inBubbleSelected, 0xffe2f8ff); + defaultColors.put(key_chat_inBubbleSelected, 0xffecf7fd); defaultColors.put(key_chat_inBubbleShadow, 0xff1d3753); defaultColors.put(key_chat_outBubble, 0xffefffde); - defaultColors.put(key_chat_outBubbleSelected, 0xffd4f5bc); + defaultColors.put(key_chat_outBubbleSelected, 0xffd9f7c5); defaultColors.put(key_chat_outBubbleShadow, 0xff1e750c); defaultColors.put(key_chat_inMediaIcon, 0xffffffff); - defaultColors.put(key_chat_inMediaIconSelected, 0xffe2f8ff); + defaultColors.put(key_chat_inMediaIconSelected, 0xffeff8fe); defaultColors.put(key_chat_outMediaIcon, 0xffefffde); - defaultColors.put(key_chat_outMediaIconSelected, 0xffd4f5bc); + defaultColors.put(key_chat_outMediaIconSelected, 0xffe1f8cf); defaultColors.put(key_chat_messageTextIn, 0xff000000); defaultColors.put(key_chat_messageTextOut, 0xff000000); defaultColors.put(key_chat_messageLinkIn, 0xff2678b6); @@ -1373,7 +1458,7 @@ public class Theme { defaultColors.put(key_chat_inInstantSelected, 0xff3079b5); defaultColors.put(key_chat_sentError, 0xffdb3535); defaultColors.put(key_chat_sentErrorIcon, 0xffffffff); - defaultColors.put(key_chat_selectedBackground, 0x6633b5e5); + defaultColors.put(key_chat_selectedBackground, 0x280a90f0); defaultColors.put(key_chat_previewDurationText, 0xffffffff); defaultColors.put(key_chat_previewGameText, 0xffffffff); defaultColors.put(key_chat_inPreviewInstantText, 0xff3a8ccf); @@ -1415,8 +1500,8 @@ public class Theme { defaultColors.put(key_chat_mediaProgress, 0xffffffff); defaultColors.put(key_chat_inAudioProgress, 0xffffffff); defaultColors.put(key_chat_outAudioProgress, 0xffefffde); - defaultColors.put(key_chat_inAudioSelectedProgress, 0xffe2f8ff); - defaultColors.put(key_chat_outAudioSelectedProgress, 0xffd4f5bc); + defaultColors.put(key_chat_inAudioSelectedProgress, 0xffeff8fe); + defaultColors.put(key_chat_outAudioSelectedProgress, 0xffe1f8cf); defaultColors.put(key_chat_mediaTimeText, 0xffffffff); defaultColors.put(key_chat_inTimeText, 0xffa1aab3); defaultColors.put(key_chat_outTimeText, 0xff70b15c); @@ -1469,21 +1554,24 @@ public class Theme { defaultColors.put(key_chat_mediaInfoText, 0xffffffff); defaultColors.put(key_chat_linkSelectBackground, 0x3362a9e3); defaultColors.put(key_chat_textSelectBackground, 0x6662a9e3); - defaultColors.put(key_chat_emojiPanelBackground, 0xfff5f6f7); + defaultColors.put(key_chat_emojiPanelBackground, 0xfff0f2f5); defaultColors.put(key_chat_emojiPanelBadgeBackground, 0xff4da6ea); defaultColors.put(key_chat_emojiPanelBadgeText, 0xffffffff); - defaultColors.put(key_chat_emojiSearchBackground, 0xffe7ebed); - defaultColors.put(key_chat_emojiPanelShadowLine, 0xffe2e5e7); - defaultColors.put(key_chat_emojiPanelEmptyText, 0xffa8a8a8); - defaultColors.put(key_chat_emojiPanelIcon, 0xffa8a8a8); - defaultColors.put(key_chat_emojiPanelIconSelected, 0xff2b96e2); + defaultColors.put(key_chat_emojiSearchBackground, 0xffe5e9ee); + defaultColors.put(key_chat_emojiSearchIcon, 0xff94a1af); + defaultColors.put(key_chat_emojiPanelShadowLine, 0x12000000); + defaultColors.put(key_chat_emojiPanelEmptyText, 0xff949ba1); + defaultColors.put(key_chat_emojiPanelIcon, 0xff9da4ab); + defaultColors.put(key_chat_emojiBottomPanelIcon, 0xff8c9197); + defaultColors.put(key_chat_emojiPanelIconSelected, 0xff2b97e2); defaultColors.put(key_chat_emojiPanelStickerPackSelector, 0xffe2e5e7); - defaultColors.put(key_chat_emojiPanelIconSelector, 0xff2b96e2); - defaultColors.put(key_chat_emojiPanelBackspace, 0xffa8a8a8); + defaultColors.put(key_chat_emojiPanelStickerPackSelectorLine, 0xff56abf0); + defaultColors.put(key_chat_emojiPanelBackspace, 0xff8c9197); defaultColors.put(key_chat_emojiPanelMasksIcon, 0xffffffff); defaultColors.put(key_chat_emojiPanelMasksIconSelected, 0xff62bfe8); defaultColors.put(key_chat_emojiPanelTrendingTitle, 0xff222222); - defaultColors.put(key_chat_emojiPanelStickerSetName, 0xff838c96); + defaultColors.put(key_chat_emojiPanelStickerSetName, 0xff828b94); + defaultColors.put(key_chat_emojiPanelStickerSetNameHighlight, 0xff278ddb); defaultColors.put(key_chat_emojiPanelStickerSetNameIcon, 0xffb1b6bc); defaultColors.put(key_chat_emojiPanelTrendingDescription, 0xff8a8a8a); defaultColors.put(key_chat_botKeyboardButtonText, 0xff36474f); @@ -1492,7 +1580,6 @@ public class Theme { defaultColors.put(key_chat_unreadMessagesStartArrowIcon, 0xffa2b5c7); defaultColors.put(key_chat_unreadMessagesStartText, 0xff5695cc); defaultColors.put(key_chat_unreadMessagesStartBackground, 0xffffffff); - defaultColors.put(key_chat_editDoneIcon, 0xff51bdf3); defaultColors.put(key_chat_inFileIcon, 0xffa2b5c7); defaultColors.put(key_chat_inFileSelectedIcon, 0xff87b6c5); defaultColors.put(key_chat_outFileIcon, 0xff85bf78); @@ -1507,21 +1594,21 @@ public class Theme { defaultColors.put(key_chat_outContactIcon, 0xffefffde); defaultColors.put(key_chat_outBroadcast, 0xff46aa36); defaultColors.put(key_chat_mediaBroadcast, 0xffffffff); - defaultColors.put(key_chat_searchPanelIcons, 0xff5da5dc); - defaultColors.put(key_chat_searchPanelText, 0xff4e9ad4); + defaultColors.put(key_chat_searchPanelIcons, 0xff676a6f); + defaultColors.put(key_chat_searchPanelText, 0xff676a6f); defaultColors.put(key_chat_secretChatStatusText, 0xff7f7f7f); defaultColors.put(key_chat_fieldOverlayText, 0xff3a8ccf); defaultColors.put(key_chat_stickersHintPanel, 0xffffffff); defaultColors.put(key_chat_replyPanelIcons, 0xff57a8e6); - defaultColors.put(key_chat_replyPanelClose, 0xffa8a8a8); + defaultColors.put(key_chat_replyPanelClose, 0xff8e959b); defaultColors.put(key_chat_replyPanelName, 0xff3a8ccf); defaultColors.put(key_chat_replyPanelMessage, 0xff222222); defaultColors.put(key_chat_replyPanelLine, 0xffe8e8e8); defaultColors.put(key_chat_messagePanelBackground, 0xffffffff); defaultColors.put(key_chat_messagePanelText, 0xff000000); - defaultColors.put(key_chat_messagePanelHint, 0xffb2b2b2); + defaultColors.put(key_chat_messagePanelHint, 0xffa4acb3); defaultColors.put(key_chat_messagePanelShadow, 0xff000000); - defaultColors.put(key_chat_messagePanelIcons, 0xffa8a8a8); + defaultColors.put(key_chat_messagePanelIcons, 0xff8e959b); defaultColors.put(key_chat_recordedVoicePlayPause, 0xffffffff); defaultColors.put(key_chat_recordedVoicePlayPausePressed, 0xffd9eafb); defaultColors.put(key_chat_recordedVoiceDot, 0xffda564d); @@ -1539,7 +1626,7 @@ public class Theme { defaultColors.put(key_chat_gifSaveHintBackground, 0xcc111111); defaultColors.put(key_chat_goDownButton, 0xffffffff); defaultColors.put(key_chat_goDownButtonShadow, 0xff000000); - defaultColors.put(key_chat_goDownButtonIcon, 0xffa8a8a8); + defaultColors.put(key_chat_goDownButtonIcon, 0xff8e959b); defaultColors.put(key_chat_goDownButtonCounter, 0xffffffff); defaultColors.put(key_chat_goDownButtonCounterBackground, 0xff4da2e8); defaultColors.put(key_chat_messagePanelCancelInlineBot, 0xffadadad); @@ -1584,7 +1671,7 @@ public class Theme { defaultColors.put(key_profile_title, 0xffffffff); defaultColors.put(key_player_actionBar, 0xffffffff); - defaultColors.put(key_player_actionBarSelector, 0x2f000000); + defaultColors.put(key_player_actionBarSelector, 0x0f000000); defaultColors.put(key_player_actionBarTitle, 0xff2f3438); defaultColors.put(key_player_actionBarTop, 0x99000000); defaultColors.put(key_player_actionBarSubtitle, 0xff8a8a8a); @@ -1599,6 +1686,9 @@ public class Theme { defaultColors.put(key_player_button, 0xff333333); defaultColors.put(key_player_buttonActive, 0xff4ca8ea); + defaultColors.put(key_sheet_scrollUp, 0xffe1e4e8); + defaultColors.put(key_sheet_other, 0xffc9cdd3); + defaultColors.put(key_files_folderIcon, 0xff999999); defaultColors.put(key_files_folderIconBackground, 0xfff0f0f0); defaultColors.put(key_files_iconText, 0xffffffff); @@ -1642,13 +1732,14 @@ public class Theme { defaultColors.put(key_sharedMedia_startStopLoadIcon, 0xff36a2ee); defaultColors.put(key_sharedMedia_linkPlaceholder, 0xfff0f3f5); defaultColors.put(key_sharedMedia_linkPlaceholderText, 0xffb7bec3); - defaultColors.put(key_sharedMedia_photoPlaceholder, 0xfff5f5f5); + defaultColors.put(key_sharedMedia_photoPlaceholder, 0xffedf3f7); + defaultColors.put(key_sharedMedia_actionMode, 0xff4687b3); defaultColors.put(key_checkbox, 0xff5ec245); defaultColors.put(key_checkboxCheck, 0xffffffff); defaultColors.put(key_stickers_menu, 0xffb6bdc5); - defaultColors.put(key_stickers_menuSelector, 0x2f000000); + defaultColors.put(key_stickers_menuSelector, 0x0f000000); defaultColors.put(key_changephoneinfo_image, 0xffa8a8a8); defaultColors.put(key_changephoneinfo_changeText, 0xff4d83b3); @@ -1723,6 +1814,40 @@ public class Theme { fallbackKeys.put(key_contextProgressOuter4, key_contextProgressOuter1); fallbackKeys.put(key_switchTrackBlueSelector, key_listSelector); fallbackKeys.put(key_switchTrackBlueSelectorChecked, key_listSelector); + fallbackKeys.put(key_chat_emojiBottomPanelIcon, key_chat_emojiPanelIcon); + fallbackKeys.put(key_chat_emojiSearchIcon, key_chat_emojiPanelIcon); + fallbackKeys.put(key_chat_emojiPanelStickerSetNameHighlight, key_windowBackgroundWhiteBlueText4); + fallbackKeys.put(key_chat_emojiPanelStickerPackSelectorLine, key_chat_emojiPanelIconSelected); + fallbackKeys.put(key_sharedMedia_actionMode, key_actionBarDefault); + fallbackKeys.put(key_sheet_scrollUp, key_chat_emojiPanelStickerPackSelector); + fallbackKeys.put(key_sheet_other, key_player_actionBarItems); + fallbackKeys.put(key_dialogSearchBackground, key_chat_emojiPanelStickerPackSelector); + fallbackKeys.put(key_dialogSearchHint, key_chat_emojiPanelIcon); + fallbackKeys.put(key_dialogSearchIcon, key_chat_emojiPanelIcon); + fallbackKeys.put(key_dialogSearchText, key_windowBackgroundWhiteBlackText); + fallbackKeys.put(key_dialogFloatingButton, key_dialogRoundCheckBox); + fallbackKeys.put(key_dialogFloatingButtonPressed, key_dialogRoundCheckBox); + fallbackKeys.put(key_dialogFloatingIcon, key_dialogRoundCheckBoxCheck); + fallbackKeys.put(key_dialogShadowLine, key_chat_emojiPanelShadowLine); + fallbackKeys.put(key_actionBarDefaultArchived, key_actionBarDefault); + fallbackKeys.put(key_actionBarDefaultArchivedSelector, key_actionBarDefaultSelector); + fallbackKeys.put(key_actionBarDefaultArchivedIcon, key_actionBarDefaultIcon); + fallbackKeys.put(key_actionBarDefaultArchivedTitle, key_actionBarDefaultTitle); + fallbackKeys.put(key_actionBarDefaultArchivedSearch, key_actionBarDefaultSearch); + fallbackKeys.put(key_actionBarDefaultArchivedSearchPlaceholder, key_actionBarDefaultSearchPlaceholder); + fallbackKeys.put(key_chats_message_threeLines, key_chats_message); + fallbackKeys.put(key_chats_nameMessage_threeLines, key_chats_nameMessage); + fallbackKeys.put(key_chats_nameArchived, key_chats_name); + fallbackKeys.put(key_chats_nameMessageArchived, key_chats_nameMessage); + fallbackKeys.put(key_chats_nameMessageArchived_threeLines, key_chats_nameMessage); + fallbackKeys.put(key_chats_messageArchived, key_chats_message); + fallbackKeys.put(key_avatar_backgroundArchived, key_chats_unreadCounterMuted); + fallbackKeys.put(key_avatar_backgroundArchivedHidden, key_chats_unreadCounterMuted); + fallbackKeys.put(key_chats_archiveBackground, key_chats_actionBackground); + fallbackKeys.put(key_chats_archivePinBackground, key_chats_unreadCounterMuted); + fallbackKeys.put(key_chats_archiveIcon, key_chats_actionIcon); + fallbackKeys.put(key_chats_archiveText, key_chats_actionIcon); + fallbackKeys.put(key_actionBarDefaultSubmenuItemIcon, key_dialogIcon); themes = new ArrayList<>(); otherThemes = new ArrayList<>(); @@ -2139,18 +2264,18 @@ public class Theme { return stateListDrawable; } - public static Drawable getRoundRectSelectorDrawable() { + public static Drawable getRoundRectSelectorDrawable(int color) { if (Build.VERSION.SDK_INT >= 21) { Drawable maskDrawable = createRoundRectDrawable(AndroidUtilities.dp(3), 0xffffffff); ColorStateList colorStateList = new ColorStateList( new int[][]{StateSet.WILD_CARD}, - new int[]{getColor(key_dialogButtonSelector)} + new int[]{(color & 0x00ffffff) | 0x19000000} ); return new RippleDrawable(colorStateList, null, maskDrawable); } else { StateListDrawable stateListDrawable = new StateListDrawable(); - stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, createRoundRectDrawable(AndroidUtilities.dp(3), getColor(key_dialogButtonSelector))); - stateListDrawable.addState(new int[]{android.R.attr.state_selected}, createRoundRectDrawable(AndroidUtilities.dp(3), getColor(key_dialogButtonSelector))); + stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, createRoundRectDrawable(AndroidUtilities.dp(3), (color & 0x00ffffff) | 0x19000000)); + stateListDrawable.addState(new int[]{android.R.attr.state_selected}, createRoundRectDrawable(AndroidUtilities.dp(3), (color & 0x00ffffff) | 0x19000000)); stateListDrawable.addState(StateSet.WILD_CARD, new ColorDrawable(0x00000000)); return stateListDrawable; } @@ -2203,13 +2328,23 @@ public class Theme { Drawable drawable; if (Build.VERSION.SDK_INT >= 21) { Drawable maskDrawable = null; - if (maskType == 1) { + if (maskType == 1 && Build.VERSION.SDK_INT >= 23) { + maskDrawable = null; + } else if (maskType == 1 || maskType == 3 || maskType == 4) { maskPaint.setColor(0xffffffff); maskDrawable = new Drawable() { @Override public void draw(Canvas canvas) { android.graphics.Rect bounds = getBounds(); - canvas.drawCircle(bounds.centerX(), bounds.centerY(), AndroidUtilities.dp(18), maskPaint); + int rad; + if (maskType == 1) { + rad = AndroidUtilities.dp(20); + } else if (maskType == 3) { + rad = (Math.max(bounds.width(), bounds.height()) / 2); + } else { + rad = (int) Math.ceil(Math.sqrt((bounds.left - bounds.centerX()) * (bounds.left - bounds.centerX()) + (bounds.top - bounds.centerY()) * (bounds.top - bounds.centerY()))); + } + canvas.drawCircle(bounds.centerX(), bounds.centerY(), rad, maskPaint); } @Override @@ -2234,7 +2369,11 @@ public class Theme { new int[][]{StateSet.WILD_CARD}, new int[]{color} ); - return new RippleDrawable(colorStateList, null, maskDrawable); + RippleDrawable rippleDrawable = new RippleDrawable(colorStateList, null, maskDrawable); + if (maskType == 1 && Build.VERSION.SDK_INT >= 23) { + rippleDrawable.setRadius(AndroidUtilities.dp(20)); + } + return rippleDrawable; } else { StateListDrawable stateListDrawable = new StateListDrawable(); stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(color)); @@ -2525,7 +2664,7 @@ public class Theme { if (autoNightScheduleByLocation) { int day = calendar.get(Calendar.DAY_OF_MONTH); if (autoNightLastSunCheckDay != day && autoNightLocationLatitude != 10000 && autoNightLocationLongitude != 10000) { - int t[] = SunDate.calculateSunriseSunset(Theme.autoNightLocationLatitude, Theme.autoNightLocationLongitude); + int[] t = SunDate.calculateSunriseSunset(Theme.autoNightLocationLatitude, Theme.autoNightLocationLongitude); autoNightSunriseTime = t[0]; autoNightSunsetTime = t[1]; autoNightLastSunCheckDay = day; @@ -2710,7 +2849,7 @@ public class Theme { for (int a = 0; a < read; a++) { if (bytes[a] == '\n') { int len = a - start + 1; - String line = new String(bytes, start, len - 1, "UTF-8"); + String line = new String(bytes, start, len - 1); if (line.startsWith("WPS")) { themedWallpaperFileOffset = currentPosition + len; finished = true; @@ -2778,7 +2917,32 @@ public class Theme { Resources resources = context.getResources(); avatar_broadcastDrawable = resources.getDrawable(R.drawable.broadcast_w); - avatar_savedDrawable = resources.getDrawable(R.drawable.bookmark_large); + avatar_savedDrawable = resources.getDrawable(R.drawable.chats_saved); + + dialogs_archiveAvatarDrawable = new LottieDrawable(); + dialogs_archiveAvatarDrawable.setComposition(LottieCompositionFactory.fromRawResSync(context, R.raw.chats_archiveavatar).getValue()); + if (Build.VERSION.SDK_INT == 24) { + dialogs_archiveDrawable = resources.getDrawable(R.drawable.chats_archive); + dialogs_unarchiveDrawable = resources.getDrawable(R.drawable.chats_unarchive); + dialogs_pinArchiveDrawable = resources.getDrawable(R.drawable.chats_archive_hide); + dialogs_unpinArchiveDrawable = resources.getDrawable(R.drawable.chats_archive_show); + } else { + LottieDrawable lottie_dialogs_archiveDrawable = new LottieDrawable(); + lottie_dialogs_archiveDrawable.setComposition(LottieCompositionFactory.fromRawResSync(context, R.raw.chats_archive).getValue()); + dialogs_archiveDrawable = lottie_dialogs_archiveDrawable; + + LottieDrawable lottie_dialogs_unarchiveDrawable = new LottieDrawable(); + lottie_dialogs_unarchiveDrawable.setComposition(LottieCompositionFactory.fromRawResSync(context, R.raw.chats_unarchive).getValue()); + dialogs_unarchiveDrawable = lottie_dialogs_unarchiveDrawable; + + LottieDrawable lottie_dialogs_pinArchiveDrawable = new LottieDrawable(); + lottie_dialogs_pinArchiveDrawable.setComposition(LottieCompositionFactory.fromRawResSync(context, R.raw.chats_hide).getValue()); + dialogs_pinArchiveDrawable = lottie_dialogs_pinArchiveDrawable; + + LottieDrawable lottie_dialogs_unpinArchiveDrawable = new LottieDrawable(); + lottie_dialogs_unpinArchiveDrawable.setComposition(LottieCompositionFactory.fromRawResSync(context, R.raw.chats_unhide).getValue()); + dialogs_unpinArchiveDrawable = lottie_dialogs_unpinArchiveDrawable; + } applyCommonTheme(); } @@ -2793,6 +2957,58 @@ public class Theme { setDrawableColorByKey(avatar_broadcastDrawable, key_avatar_text); setDrawableColorByKey(avatar_savedDrawable, key_avatar_text); + + dialogs_archiveAvatarDrawable.addValueCallback(new KeyPath("**"), LottieProperty.COLOR_FILTER, (LottieValueCallback) null); + dialogs_archiveAvatarDrawable.addValueCallback(new KeyPath("Arrow1", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(getColor(key_avatar_backgroundArchived)))); + dialogs_archiveAvatarDrawable.addValueCallback(new KeyPath("Arrow2", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(getColor(key_avatar_backgroundArchived)))); + dialogs_archiveAvatarDrawable.addValueCallback(new KeyPath("Box2", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(getColor(key_avatar_text)))); + dialogs_archiveAvatarDrawable.addValueCallback(new KeyPath("Box1", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(getColor(key_avatar_text)))); + dialogs_archiveAvatarDrawableRecolored = false; + + /* + fallbackKeys.put(key_chats_archiveIcon, key_chats_actionIcon); + fallbackKeys.put(key_chats_archiveText, key_chats_actionIcon); + */ + + if (dialogs_pinArchiveDrawable instanceof LottieDrawable) { + LottieDrawable lottieDrawable = (LottieDrawable) dialogs_pinArchiveDrawable; + lottieDrawable.addValueCallback(new KeyPath("**"), LottieProperty.COLOR_FILTER, (LottieValueCallback) null); + lottieDrawable.addValueCallback(new KeyPath("Arrow", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(getColor(key_chats_archiveIcon)))); + lottieDrawable.addValueCallback(new KeyPath("Line", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(getColor(key_chats_archiveIcon)))); + } else { + setDrawableColorByKey(dialogs_pinArchiveDrawable, key_chats_archiveIcon); + } + + if (dialogs_unpinArchiveDrawable instanceof LottieDrawable) { + LottieDrawable lottieDrawable = (LottieDrawable) dialogs_unpinArchiveDrawable; + lottieDrawable.addValueCallback(new KeyPath("**"), LottieProperty.COLOR_FILTER, (LottieValueCallback) null); + lottieDrawable.addValueCallback(new KeyPath("Arrow", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(getColor(key_chats_archiveIcon)))); + lottieDrawable.addValueCallback(new KeyPath("Line", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(getColor(key_chats_archiveIcon)))); + } else { + setDrawableColorByKey(dialogs_unpinArchiveDrawable, key_chats_archiveIcon); + } + + if (dialogs_archiveDrawable instanceof LottieDrawable) { + LottieDrawable lottieDrawable = (LottieDrawable) dialogs_archiveDrawable; + lottieDrawable.addValueCallback(new KeyPath("**"), LottieProperty.COLOR_FILTER, (LottieValueCallback) null); + lottieDrawable.addValueCallback(new KeyPath("Arrow", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(getColor(key_chats_archiveBackground)))); + lottieDrawable.addValueCallback(new KeyPath("Box2", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(getColor(key_chats_archiveIcon)))); + lottieDrawable.addValueCallback(new KeyPath("Box1", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(getColor(key_chats_archiveIcon)))); + dialogs_archiveDrawableRecolored = false; + } else { + setDrawableColorByKey(dialogs_archiveDrawable, key_chats_archiveIcon); + } + + if (dialogs_unarchiveDrawable instanceof LottieDrawable) { + LottieDrawable lottieDrawable = (LottieDrawable) dialogs_unarchiveDrawable; + lottieDrawable.addValueCallback(new KeyPath("**"), LottieProperty.COLOR_FILTER, (LottieValueCallback) null); + lottieDrawable.addValueCallback(new KeyPath("Arrow1", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(getColor(key_chats_archiveIcon)))); + lottieDrawable.addValueCallback(new KeyPath("Arrow2", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(getColor(key_chats_archivePinBackground)))); + lottieDrawable.addValueCallback(new KeyPath("Box2", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(getColor(key_chats_archiveIcon)))); + lottieDrawable.addValueCallback(new KeyPath("Box1", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(getColor(key_chats_archiveIcon)))); + } else { + setDrawableColorByKey(dialogs_unarchiveDrawable, key_chats_archiveIcon); + } } public static void createDialogsResources(Context context) { @@ -2805,15 +3021,19 @@ public class Theme { dialogs_nameEncryptedPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); dialogs_nameEncryptedPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); dialogs_messagePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); + dialogs_messageNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); + dialogs_messageNamePaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); dialogs_messagePrintingPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); dialogs_timePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); dialogs_countTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); dialogs_countTextPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + dialogs_archiveTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); + dialogs_archiveTextPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); dialogs_onlinePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); dialogs_offlinePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); dialogs_tabletSeletedPaint = new Paint(); - dialogs_pinnedPaint = new Paint(); + dialogs_pinnedPaint = new Paint(Paint.ANTI_ALIAS_FLAG); dialogs_onlineCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG); dialogs_countPaint = new Paint(Paint.ANTI_ALIAS_FLAG); dialogs_countGrayPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -2824,10 +3044,12 @@ public class Theme { 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); + dialogs_reorderDrawable = resources.getDrawable(R.drawable.list_reorder); dialogs_groupDrawable = resources.getDrawable(R.drawable.list_group); dialogs_broadcastDrawable = resources.getDrawable(R.drawable.list_broadcast); dialogs_muteDrawable = resources.getDrawable(R.drawable.list_mute).mutate(); dialogs_verifiedDrawable = resources.getDrawable(R.drawable.verified_area); + dialogs_scamDrawable = new ScamDrawable(11); dialogs_verifiedCheckDrawable = resources.getDrawable(R.drawable.verified_check); dialogs_mentionDrawable = resources.getDrawable(R.drawable.mentionchatslist); dialogs_botDrawable = resources.getDrawable(R.drawable.list_bot); @@ -2837,12 +3059,10 @@ public class Theme { applyDialogsTheme(); } - dialogs_namePaint.setTextSize(AndroidUtilities.dp(17)); - dialogs_nameEncryptedPaint.setTextSize(AndroidUtilities.dp(17)); - dialogs_messagePaint.setTextSize(AndroidUtilities.dp(16)); - dialogs_messagePrintingPaint.setTextSize(AndroidUtilities.dp(16)); + dialogs_messageNamePaint.setTextSize(AndroidUtilities.dp(14)); dialogs_timePaint.setTextSize(AndroidUtilities.dp(13)); dialogs_countTextPaint.setTextSize(AndroidUtilities.dp(13)); + dialogs_archiveTextPaint.setTextSize(AndroidUtilities.dp(13)); dialogs_onlinePaint.setTextSize(AndroidUtilities.dp(16)); dialogs_offlinePaint.setTextSize(AndroidUtilities.dp(16)); } @@ -2854,10 +3074,12 @@ public class Theme { dialogs_namePaint.setColor(getColor(key_chats_name)); dialogs_nameEncryptedPaint.setColor(getColor(key_chats_secretName)); dialogs_messagePaint.setColor(dialogs_messagePaint.linkColor = getColor(key_chats_message)); + dialogs_messageNamePaint.setColor(dialogs_messageNamePaint.linkColor = getColor(key_chats_nameMessage_threeLines)); dialogs_tabletSeletedPaint.setColor(getColor(key_chats_tabletSelectedOverlay)); dialogs_pinnedPaint.setColor(getColor(key_chats_pinnedOverlay)); dialogs_timePaint.setColor(getColor(key_chats_date)); dialogs_countTextPaint.setColor(getColor(key_chats_unreadCounterText)); + dialogs_archiveTextPaint.setColor(getColor(key_chats_archiveText)); dialogs_messagePrintingPaint.setColor(getColor(key_chats_actionMessage)); dialogs_countPaint.setColor(getColor(key_chats_unreadCounter)); dialogs_countGrayPaint.setColor(getColor(key_chats_unreadCounterMuted)); @@ -2874,11 +3096,13 @@ public class Theme { setDrawableColorByKey(dialogs_broadcastDrawable, key_chats_nameIcon); setDrawableColorByKey(dialogs_botDrawable, key_chats_nameIcon); setDrawableColorByKey(dialogs_pinnedDrawable, key_chats_pinnedIcon); + setDrawableColorByKey(dialogs_reorderDrawable, key_chats_pinnedIcon); setDrawableColorByKey(dialogs_muteDrawable, key_chats_muteIcon); setDrawableColorByKey(dialogs_mentionDrawable, key_chats_mentionIcon); setDrawableColorByKey(dialogs_verifiedDrawable, key_chats_verifiedBackground); setDrawableColorByKey(dialogs_verifiedCheckDrawable, key_chats_verifiedCheck); setDrawableColorByKey(dialogs_holidayDrawable, key_actionBarDefaultTitle); + setDrawableColorByKey(dialogs_scamDrawable, key_chats_draft); } public static void destroyResources() { @@ -2889,6 +3113,24 @@ public class Theme { } } + public static void reloadAllResources(Context context) { + destroyResources(); + if (chat_msgInDrawable != null) { + chat_msgInDrawable = null; + currentColor = 0; + currentSelectedColor = 0; + createChatResources(context, false); + } + if (dialogs_namePaint != null) { + dialogs_namePaint = null; + createDialogsResources(context); + } + if (profile_verifiedDrawable != null) { + profile_verifiedDrawable = null; + createProfileResources(context); + } + } + public static void createChatResources(Context context, boolean fontsOnly) { synchronized (sync) { if (chat_msgTextPaint == null) { @@ -2950,7 +3192,7 @@ public class Theme { chat_instantViewPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); chat_instantViewRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG); chat_instantViewRectPaint.setStyle(Paint.Style.STROKE); - chat_replyLinePaint = new Paint(); + chat_replyLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); chat_msgErrorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); chat_statusPaint = new Paint(Paint.ANTI_ALIAS_FLAG); chat_statusRecordPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -3012,10 +3254,10 @@ public class Theme { chat_lockIconDrawable = resources.getDrawable(R.drawable.ic_lock_header); chat_msgBroadcastDrawable = resources.getDrawable(R.drawable.broadcast3).mutate(); chat_msgBroadcastMediaDrawable = resources.getDrawable(R.drawable.broadcast3).mutate(); - chat_msgInCallDrawable = resources.getDrawable(R.drawable.ic_call_white_24dp).mutate(); - chat_msgInCallSelectedDrawable = resources.getDrawable(R.drawable.ic_call_white_24dp).mutate(); - chat_msgOutCallDrawable = resources.getDrawable(R.drawable.ic_call_white_24dp).mutate(); - chat_msgOutCallSelectedDrawable = resources.getDrawable(R.drawable.ic_call_white_24dp).mutate(); + chat_msgInCallDrawable = resources.getDrawable(R.drawable.ic_call).mutate(); + chat_msgInCallSelectedDrawable = resources.getDrawable(R.drawable.ic_call).mutate(); + chat_msgOutCallDrawable = resources.getDrawable(R.drawable.ic_call).mutate(); + chat_msgOutCallSelectedDrawable = resources.getDrawable(R.drawable.ic_call).mutate(); chat_msgCallUpRedDrawable = resources.getDrawable(R.drawable.ic_call_made_green_18dp).mutate(); chat_msgCallUpGreenDrawable = resources.getDrawable(R.drawable.ic_call_made_green_18dp).mutate(); chat_msgCallDownRedDrawable = resources.getDrawable(R.drawable.ic_call_received_green_18dp).mutate(); @@ -3615,6 +3857,8 @@ public class Theme { } if (drawable instanceof ShapeDrawable) { ((ShapeDrawable) drawable).getPaint().setColor(color); + } else if (drawable instanceof ScamDrawable) { + ((ScamDrawable) drawable).setColor(color); } else { drawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); } @@ -3718,7 +3962,7 @@ public class Theme { private static void calcBackgroundColor(Drawable drawable, int save) { if (save != 2) { - int result[] = AndroidUtilities.calcDrawableColor(drawable); + int[] result = AndroidUtilities.calcDrawableColor(drawable); serviceMessageColor = serviceMessageColorBackup = result[0]; serviceSelectedMessageColor = serviceSelectedMessageColorBackup = result[1]; serviceMessage2Color = result[2]; 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 7c182fadd..5f3751214 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeDescription.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeDescription.java @@ -13,6 +13,7 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.RippleDrawable; import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.StateListDrawable; @@ -26,6 +27,13 @@ import android.widget.ImageView; import android.widget.ScrollView; import android.widget.TextView; +import com.airbnb.lottie.LottieAnimationView; +import com.airbnb.lottie.LottieDrawable; +import com.airbnb.lottie.LottieProperty; +import com.airbnb.lottie.SimpleColorFilter; +import com.airbnb.lottie.model.KeyPath; +import com.airbnb.lottie.value.LottieValueCallback; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLog; import org.telegram.ui.Components.AvatarDrawable; @@ -42,10 +50,12 @@ import org.telegram.ui.Components.GroupCreateCheckBox; import org.telegram.ui.Components.GroupCreateSpan; import org.telegram.ui.Components.LetterDrawable; import org.telegram.ui.Components.LineProgressView; +import org.telegram.ui.Components.MessageBackgroundDrawable; import org.telegram.ui.Components.NumberTextView; import org.telegram.ui.Components.RadialProgressView; import org.telegram.ui.Components.RadioButton; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.ScamDrawable; import org.telegram.ui.Components.SeekBarView; import org.telegram.ui.Components.TypefaceSpan; @@ -53,6 +63,8 @@ import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; +import androidx.viewpager.widget.ViewPager; + public class ThemeDescription { public static int FLAG_BACKGROUND = 0x00000001; @@ -93,6 +105,7 @@ public class ThemeDescription { private Drawable[] drawablesToUpdate; private Class[] listClasses; private String currentKey; + private String lottieLayerName; private ThemeDescriptionDelegate delegate; private int previousColor; private boolean[] previousIsDefault = new boolean[1]; @@ -136,6 +149,18 @@ public class ThemeDescription { } } + public ThemeDescription(View view, int flags, Class[] classes, LottieDrawable[] drawables, String layerName, String key) { + currentKey = key; + lottieLayerName = layerName; + drawablesToUpdate = drawables; + viewToInvalidate = view; + changeFlags = flags; + listClasses = classes; + if (viewToInvalidate instanceof EditTextEmoji) { + viewToInvalidate = ((EditTextEmoji) viewToInvalidate).getEditText(); + } + } + public ThemeDescription(View view, int flags, Class[] classes, String[] classesFields, Paint[] paint, Drawable[] drawables, ThemeDescriptionDelegate themeDescriptionDelegate, String key) { currentKey = key; paintToUpdate = paint; @@ -152,6 +177,20 @@ public class ThemeDescription { } } + public ThemeDescription(View view, int flags, Class[] classes, String[] classesFields, String layerName, String key) { + currentKey = key; + lottieLayerName = layerName; + viewToInvalidate = view; + changeFlags = flags; + listClasses = classes; + listClassesFieldName = classesFields; + cachedFields = new HashMap<>(); + notFoundCachedFields = new HashMap<>(); + if (viewToInvalidate instanceof EditTextEmoji) { + viewToInvalidate = ((EditTextEmoji) viewToInvalidate).getEditText(); + } + } + public ThemeDescriptionDelegate setDelegateDisabled() { ThemeDescriptionDelegate oldDelegate = delegate; delegate = null; @@ -191,7 +230,13 @@ public class ThemeDescription { if (drawablesToUpdate[a] == null) { continue; } - if (drawablesToUpdate[a] instanceof CombinedDrawable) { + if (drawablesToUpdate[a] instanceof ScamDrawable) { + ((ScamDrawable) drawablesToUpdate[a]).setColor(color); + } else if (drawablesToUpdate[a] instanceof LottieDrawable) { + if (lottieLayerName != null) { + ((LottieDrawable) drawablesToUpdate[a]).addValueCallback(new KeyPath(lottieLayerName, "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(color))); + } + } else if (drawablesToUpdate[a] instanceof CombinedDrawable) { if ((changeFlags & FLAG_BACKGROUNDFILTER) != 0) { ((CombinedDrawable) drawablesToUpdate[a]).getBackground().setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); } else { @@ -207,7 +252,12 @@ public class ThemeDescription { if (viewToInvalidate != null && listClasses == null && listClassesFieldName == null) { if ((changeFlags & FLAG_CHECKTAG) == 0 || checkTag(currentKey, viewToInvalidate)) { if ((changeFlags & FLAG_BACKGROUND) != 0) { - viewToInvalidate.setBackgroundColor(color); + Drawable background = viewToInvalidate.getBackground(); + if (background instanceof MessageBackgroundDrawable) { + ((MessageBackgroundDrawable) background).setColor(color); + } else { + viewToInvalidate.setBackgroundColor(color); + } } if ((changeFlags & FLAG_BACKGROUNDFILTER) != 0) { if ((changeFlags & FLAG_PROGRESSBAR) != 0) { @@ -268,7 +318,7 @@ public class ThemeDescription { ((ActionBar) viewToInvalidate).setSearchTextColor(color, false); } if ((changeFlags & FLAG_AB_SUBMENUITEM) != 0) { - ((ActionBar) viewToInvalidate).setPopupItemsColor(color); + ((ActionBar) viewToInvalidate).setPopupItemsColor(color, (changeFlags & FLAG_IMAGECOLOR) != 0); } if ((changeFlags & FLAG_AB_SUBMENUBACKGROUND) != 0) { ((ActionBar) viewToInvalidate).setPopupBackgroundColor(color); @@ -340,6 +390,9 @@ public class ThemeDescription { } } else if (viewToInvalidate instanceof BackupImageView) { //((BackupImageView) viewToInvalidate).setResourceImageColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); + } else if (viewToInvalidate instanceof SimpleTextView) { + SimpleTextView textView = (SimpleTextView) viewToInvalidate; + textView.setSideDrawablesColor(color); } } } @@ -348,6 +401,11 @@ public class ThemeDescription { AndroidUtilities.setScrollViewEdgeEffectColor((ScrollView) viewToInvalidate, color); } } + if (viewToInvalidate instanceof ViewPager) { + if ((changeFlags & FLAG_LISTGLOWCOLOR) != 0) { + AndroidUtilities.setViewPagerEdgeEffectColor((ViewPager) viewToInvalidate, color); + } + } if (viewToInvalidate instanceof RecyclerListView) { RecyclerListView recyclerListView = (RecyclerListView) viewToInvalidate; if ((changeFlags & FLAG_SELECTOR) != 0) { @@ -490,11 +548,20 @@ public class ThemeDescription { if (object instanceof View) { ((View) object).invalidate(); } + if (lottieLayerName != null && object instanceof LottieAnimationView) { + ((LottieAnimationView) object).addValueCallback(new KeyPath(lottieLayerName, "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(color))); + } if ((changeFlags & FLAG_USEBACKGROUNDDRAWABLE) != 0 && object instanceof View) { object = ((View) object).getBackground(); } if ((changeFlags & FLAG_BACKGROUND) != 0 && object instanceof View) { - ((View) object).setBackgroundColor(color); + View view = (View) object; + Drawable background = view.getBackground(); + if (background instanceof MessageBackgroundDrawable) { + ((MessageBackgroundDrawable) background).setColor(color); + } else { + view.setBackgroundColor(color); + } } else if (object instanceof EditTextCaption) { if ((changeFlags & FLAG_HINTTEXTCOLOR) != 0) { ((EditTextCaption) object).setHintColor(color); @@ -563,6 +630,8 @@ public class ThemeDescription { } } else if (object instanceof StateListDrawable || Build.VERSION.SDK_INT >= 21 && object instanceof RippleDrawable) { Theme.setSelectorDrawableColor((Drawable) object, color, (changeFlags & FLAG_DRAWABLESELECTEDSTATE) != 0); + } else if (object instanceof GradientDrawable) { + ((GradientDrawable) object).setColor(color); } else { ((Drawable) object).setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java index ca870b100..669a4d696 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java @@ -17,7 +17,6 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.ContactsController; @@ -34,6 +33,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import androidx.recyclerview.widget.RecyclerView; + public class ContactsAdapter extends RecyclerListView.SectionsAdapter { private int currentAccount = UserConfig.selectedAccount; @@ -46,13 +47,15 @@ public class ContactsAdapter extends RecyclerListView.SectionsAdapter { private boolean scrolling; private boolean isAdmin; private int sortType; + private boolean isChannel; - public ContactsAdapter(Context context, int onlyUsersType, boolean arg2, SparseArray arg3, boolean arg4) { + public ContactsAdapter(Context context, int onlyUsersType, boolean arg2, SparseArray arg3, int arg4) { mContext = context; onlyUsers = onlyUsersType; needPhonebook = arg2; ignoreUsers = arg3; - isAdmin = arg4; + isAdmin = arg4 != 0; + isChannel = arg4 == 2; } public void setSortType(int value) { @@ -76,6 +79,9 @@ public class ContactsAdapter extends RecyclerListView.SectionsAdapter { } public void sortOnlineContacts() { + if (onlineContacts == null) { + return; + } try { int currentTime = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); MessagesController messagesController = MessagesController.getInstance(currentAccount); @@ -355,10 +361,14 @@ public class ContactsAdapter extends RecyclerListView.SectionsAdapter { if (needPhonebook) { textCell.setTextAndIcon(LocaleController.getString("InviteFriends", R.string.InviteFriends), R.drawable.menu_invite, false); } else if (isAdmin) { - textCell.setTextAndIcon(LocaleController.getString("InviteToGroupByLink", R.string.InviteToGroupByLink), R.drawable.profile_link, false); + if (isChannel) { + textCell.setTextAndIcon(LocaleController.getString("ChannelInviteViaLink", R.string.ChannelInviteViaLink), R.drawable.profile_link, false); + } else { + textCell.setTextAndIcon(LocaleController.getString("InviteToGroupByLink", R.string.InviteToGroupByLink), R.drawable.profile_link, false); + } } else { if (position == 0) { - textCell.setTextAndIcon(LocaleController.getString("NewGroup", R.string.NewGroup), R.drawable.menu_newgroup, false); + textCell.setTextAndIcon(LocaleController.getString("NewGroup", R.string.NewGroup), R.drawable.menu_groups, false); } else if (position == 1) { textCell.setTextAndIcon(LocaleController.getString("NewSecretChat", R.string.NewSecretChat), R.drawable.menu_secret, false); } else if (position == 2) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java index 8383bc542..fbf368288 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java @@ -12,6 +12,7 @@ import android.content.Context; import android.content.SharedPreferences; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.os.Build; import android.util.TypedValue; import android.view.Gravity; import android.view.View; @@ -21,14 +22,17 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; +import org.telegram.messenger.DialogObject; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.ArchiveHintCell; import org.telegram.ui.Cells.DialogCell; import org.telegram.ui.Cells.DialogMeUrlCell; import org.telegram.ui.Cells.DialogsEmptyCell; @@ -42,11 +46,17 @@ import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.DialogsActivity; import java.util.ArrayList; +import java.util.Collections; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager.widget.ViewPager; public class DialogsAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; + private ArchiveHintCell archiveHintCell; private int dialogsType; + private int folderId; private long openedDialogId; private int currentCount; private boolean isOnlySelect; @@ -54,14 +64,24 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { private boolean hasHints; private int currentAccount = UserConfig.selectedAccount; private boolean showContacts; + private boolean dialogsListFrozen; + private boolean showArchiveHint; + private boolean isReordering; - public DialogsAdapter(Context context, int type, boolean onlySelect) { + public DialogsAdapter(Context context, int type, int folder, boolean onlySelect) { mContext = context; dialogsType = type; + folderId = folder; isOnlySelect = onlySelect; - hasHints = type == 0 && !onlySelect; - if (onlySelect) { - selectedDialogs = new ArrayList<>(); + hasHints = folder == 0 && type == 0 && !onlySelect; + selectedDialogs = new ArrayList<>(); + if (folderId == 1) { + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + showArchiveHint = preferences.getBoolean("archivehint", true); + preferences.edit().putBoolean("archivehint", false).commit(); + if (showArchiveHint) { + archiveHintCell = new ArchiveHintCell(context); + } } } @@ -73,17 +93,19 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { return selectedDialogs != null && !selectedDialogs.isEmpty(); } - public void addOrRemoveSelectedDialog(long did, View cell) { + public boolean addOrRemoveSelectedDialog(long did, View cell) { if (selectedDialogs.contains(did)) { selectedDialogs.remove(did); if (cell instanceof DialogCell) { ((DialogCell) cell).setChecked(false, true); } + return false; } else { selectedDialogs.add(did); if (cell instanceof DialogCell) { ((DialogCell) cell).setChecked(true, true); } + return true; } } @@ -91,6 +113,20 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { return selectedDialogs; } + public void onReorderStateChanged(boolean reordering) { + isReordering = reordering; + } + + public int fixPosition(int position) { + if (hasHints) { + position -= 2 + MessagesController.getInstance(currentAccount).hintDialogs.size(); + } + if (showArchiveHint) { + position -= 2; + } + return position; + } + public boolean isDataSetChanged() { int current = currentCount; return current != getItemCount() || current == 1; @@ -99,18 +135,21 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { @Override public int getItemCount() { showContacts = false; - ArrayList array = DialogsActivity.getDialogsArray(dialogsType, currentAccount); + ArrayList array = DialogsActivity.getDialogsArray(currentAccount, dialogsType, folderId, dialogsListFrozen); int dialogsCount = array.size(); - if (dialogsCount == 0 && MessagesController.getInstance(currentAccount).loadingDialogs) { + if (dialogsCount == 0 && (folderId != 0 || MessagesController.getInstance(currentAccount).isLoadingDialogs(folderId))) { + if (folderId == 1 && showArchiveHint) { + return 2; + } return 0; } int count = dialogsCount; - if (!MessagesController.getInstance(currentAccount).dialogsEndReached || dialogsCount == 0) { + if (!MessagesController.getInstance(currentAccount).isDialogsEndReached(folderId) || dialogsCount == 0) { count++; } if (hasHints) { count += 2 + MessagesController.getInstance(currentAccount).hintDialogs.size(); - } else if (dialogsType == 0 && dialogsCount == 0) { + } else if (dialogsType == 0 && dialogsCount == 0 && folderId == 0) { if (ContactsController.getInstance(currentAccount).contacts.isEmpty() && ContactsController.getInstance(currentAccount).isLoadingContacts()) { return 0; } @@ -119,6 +158,12 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { showContacts = true; } } + if (folderId == 1 && showArchiveHint) { + count += 2; + } + if (folderId == 0 && dialogsCount != 0) { + count++; + } currentCount = count; return count; } @@ -131,7 +176,10 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { } return MessagesController.getInstance(currentAccount).getUser(ContactsController.getInstance(currentAccount).contacts.get(i).user_id); } - ArrayList arrayList = DialogsActivity.getDialogsArray(dialogsType, currentAccount); + if (showArchiveHint) { + i -= 2; + } + ArrayList arrayList = DialogsActivity.getDialogsArray(currentAccount, dialogsType, folderId, dialogsListFrozen); if (hasHints) { int count = MessagesController.getInstance(currentAccount).hintDialogs.size(); if (i < 2 + count) { @@ -146,23 +194,36 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { return arrayList.get(i); } + public void setDialogsListFrozen(boolean frozen) { + dialogsListFrozen = frozen; + } + + public ViewPager getArchiveHintCellPager() { + return archiveHintCell != null ? archiveHintCell.getViewPager() : null; + } + @Override public void notifyDataSetChanged() { - hasHints = dialogsType == 0 && !isOnlySelect && !MessagesController.getInstance(currentAccount).hintDialogs.isEmpty(); + hasHints = folderId == 0 && dialogsType == 0 && !isOnlySelect && !MessagesController.getInstance(currentAccount).hintDialogs.isEmpty(); super.notifyDataSetChanged(); } @Override public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { if (holder.itemView instanceof DialogCell) { - ((DialogCell) holder.itemView).checkCurrentDialogIndex(); + DialogCell dialogCell = (DialogCell) holder.itemView; + dialogCell.onReorderStateChanged(isReordering, false); + int position = fixPosition(holder.getAdapterPosition()); + dialogCell.setDialogIndex(position); + dialogCell.checkCurrentDialogIndex(dialogsListFrozen); + dialogCell.setChecked(selectedDialogs.contains(dialogCell.getDialogId()), false); } } @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { int viewType = holder.getItemViewType(); - return viewType != 1 && viewType != 5 && viewType != 3 && viewType != 8 && viewType != 7; + return viewType != 1 && viewType != 5 && viewType != 3 && viewType != 8 && viewType != 7 && viewType != 9 && viewType != 10; } @Override @@ -170,7 +231,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { View view; switch (viewType) { case 0: - view = new DialogCell(mContext, isOnlySelect); + view = new DialogCell(mContext, true); break; case 1: view = new LoadingCell(mContext); @@ -224,13 +285,54 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { view = headerCell; break; case 8: - default: view = new ShadowSectionCell(mContext); Drawable drawable = Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow); CombinedDrawable combinedDrawable = new CombinedDrawable(new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray)), drawable); combinedDrawable.setFullsize(true); view.setBackgroundDrawable(combinedDrawable); break; + case 9: + view = archiveHintCell; + if (archiveHintCell.getParent() != null) { + ViewGroup parent = (ViewGroup) archiveHintCell.getParent(); + parent.removeView(archiveHintCell); + } + break; + case 10: + default: { + view = new View(mContext) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int size = DialogsActivity.getDialogsArray(currentAccount, dialogsType, folderId, dialogsListFrozen).size(); + boolean hasArchive = MessagesController.getInstance(currentAccount).dialogs_dict.get(DialogObject.makeFolderDialogId(1)) != null; + int height; + if (size == 0 || !hasArchive) { + height = 0; + } else { + height = MeasureSpec.getSize(heightMeasureSpec); + if (height == 0) { + View parent = (View) getParent(); + if (parent != null) { + height = parent.getMeasuredHeight(); + } + } + if (height == 0) { + height = AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight() - (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0); + } + int cellHeight = AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 78 : 72); + int dialogsHeight = size * cellHeight + (size - 1); + if (dialogsHeight < height) { + height = height - dialogsHeight + cellHeight + 1; + } else if (dialogsHeight - height < cellHeight + 1) { + height = cellHeight + 1 - (dialogsHeight - height); + } else { + height = 0; + } + } + setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height); + } + }; + } } view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, viewType == 5 ? RecyclerView.LayoutParams.MATCH_PARENT : RecyclerView.LayoutParams.WRAP_CONTENT)); return new RecyclerListView.Holder(view); @@ -241,22 +343,21 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { switch (holder.getItemViewType()) { case 0: { DialogCell cell = (DialogCell) holder.itemView; - TLRPC.TL_dialog dialog = (TLRPC.TL_dialog) getItem(i); - TLRPC.TL_dialog nextDialog = (TLRPC.TL_dialog) getItem(i + 1); - if (hasHints) { - i -= 2 + MessagesController.getInstance(currentAccount).hintDialogs.size(); + TLRPC.Dialog dialog = (TLRPC.Dialog) getItem(i); + TLRPC.Dialog nextDialog = (TLRPC.Dialog) getItem(i + 1); + if (folderId == 0) { + cell.useSeparator = (i != getItemCount() - 2); + } else { + cell.useSeparator = (i != getItemCount() - 1); } - cell.useSeparator = (i != getItemCount() - 1); cell.fullSeparator = dialog.pinned && nextDialog != null && !nextDialog.pinned; if (dialogsType == 0) { if (AndroidUtilities.isTablet()) { cell.setDialogSelected(dialog.id == openedDialogId); } } - if (selectedDialogs != null) { - cell.setChecked(selectedDialogs.contains(dialog.id), false); - } - cell.setDialog(dialog, i, dialogsType); + cell.setChecked(selectedDialogs.contains(dialog.id), false); + cell.setDialog(dialog, dialogsType, folderId); break; } case 5: { @@ -302,14 +403,41 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { } else { i -= 2 + count; } - } - if (i == DialogsActivity.getDialogsArray(dialogsType, currentAccount).size()) { - if (!MessagesController.getInstance(currentAccount).dialogsEndReached) { - return 1; + } else if (showArchiveHint) { + if (i == 0) { + return 9; + } else if (i == 1) { + return 8; } else { - return 5; + i -= 2; } } + int size = DialogsActivity.getDialogsArray(currentAccount, dialogsType, folderId, dialogsListFrozen).size(); + if (i == size) { + if (!MessagesController.getInstance(currentAccount).isDialogsEndReached(folderId)) { + return 1; + } else if (size == 0) { + return 5; + } else { + return 10; + } + } else if (i > size) { + return 10; + } return 0; } + + @Override + public void notifyItemMoved(int fromPosition, int toPosition) { + ArrayList dialogs = DialogsActivity.getDialogsArray(currentAccount, dialogsType, folderId, false); + int fromIndex = fixPosition(fromPosition); + int toIndex = fixPosition(toPosition); + TLRPC.Dialog fromDialog = dialogs.get(fromIndex); + TLRPC.Dialog toDialog = dialogs.get(toIndex); + int oldNum = fromDialog.pinnedNum; + fromDialog.pinnedNum = toDialog.pinnedNum; + toDialog.pinnedNum = oldNum; + Collections.swap(dialogs, fromIndex, toIndex); + super.notifyItemMoved(fromPosition, toPosition); + } } 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 dbc2d0a1f..4c4a419a1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -30,8 +30,7 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; +import org.telegram.messenger.Utilities; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.tgnet.ConnectionsManager; @@ -51,14 +50,16 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Locale; -import java.util.Timer; -import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; - private Timer searchTimer; + private Runnable searchRunnable; + private Runnable searchRunnable2; private ArrayList searchResult = new ArrayList<>(); private ArrayList searchResultNames = new ArrayList<>(); private ArrayList searchResultMessages = new ArrayList<>(); @@ -122,7 +123,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { HintDialogCell cell = (HintDialogCell) holder.itemView; TLRPC.TL_topPeer peer = DataQuery.getInstance(currentAccount).hints.get(position); - TLRPC.TL_dialog dialog = new TLRPC.TL_dialog(); + TLRPC.Dialog dialog = new TLRPC.TL_dialog(); TLRPC.Chat chat = null; TLRPC.User user = null; int did = 0; @@ -322,7 +323,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } } } - } else if (dialogsType == 0) { + } else if (dialogsType == 0 || dialogsType == 3) { if (!encryptedToLoad.contains(high_id)) { encryptedToLoad.add(high_id); add = true; @@ -476,7 +477,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { if (search1.equals(search2) || search2.length() == 0) { search2 = null; } - String search[] = new String[1 + (search2 != null ? 1 : 0)]; + String[] search = new String[1 + (search2 != null ? 1 : 0)]; search[0] = search1; if (search2 != null) { search[1] = search2; @@ -514,7 +515,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } } } - } else if (dialogsType == 0) { + } else if (dialogsType == 0 || dialogsType == 3) { if (!encryptedToLoad.contains(high_id)) { encryptedToLoad.add(high_id); } @@ -806,13 +807,13 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { return; } lastSearchText = query; - try { - if (searchTimer != null) { - searchTimer.cancel(); - searchTimer = null; - } - } catch (Exception e) { - FileLog.e(e); + if (searchRunnable != null) { + Utilities.searchQueue.cancelRunnable(searchRunnable); + searchRunnable = null; + } + if (searchRunnable2 != null) { + AndroidUtilities.cancelRunOnUIThread(searchRunnable2); + searchRunnable2 = null; } if (TextUtils.isEmpty(query)) { searchAdapterHelper.unloadRecentHashtags(); @@ -849,26 +850,17 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { notifyDataSetChanged(); } final int searchId = ++lastSearchId; - searchTimer = new Timer(); - searchTimer.schedule(new TimerTask() { - @Override - public void run() { - try { - cancel(); - searchTimer.cancel(); - searchTimer = null; - } catch (Exception e) { - FileLog.e(e); + Utilities.globalQueue.postRunnable(searchRunnable = () -> { + searchRunnable = null; + searchDialogsInternal(query, searchId); + AndroidUtilities.runOnUIThread(searchRunnable2 = () -> { + searchRunnable2 = null; + if (needMessagesSearch != 2) { + searchAdapterHelper.queryServerSearch(query, true, true, true, true, 0, 0); } - searchDialogsInternal(query, searchId); - AndroidUtilities.runOnUIThread(() -> { - if (needMessagesSearch != 2) { - searchAdapterHelper.queryServerSearch(query, true, true, true, true, 0, 0); - } - searchMessagesInternal(query); - }); - } - }, 200, 300); + searchMessagesInternal(query); + }); + }, 300); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java index 295110bdb..7a926c739 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java @@ -17,7 +17,6 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.DrawerActionCell; import org.telegram.ui.Cells.DividerCell; @@ -30,6 +29,8 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; import java.util.Collections; +import androidx.recyclerview.widget.RecyclerView; + public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; @@ -224,7 +225,7 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter { items.add(new Item(8, LocaleController.getString("Settings", R.string.Settings), R.drawable.menu_settings_ny)); items.add(new Item(9, LocaleController.getString("TelegramFAQ", R.string.TelegramFAQ), R.drawable.menu_help_ny)); } else { - items.add(new Item(2, LocaleController.getString("NewGroup", R.string.NewGroup), R.drawable.menu_newgroup)); + items.add(new Item(2, LocaleController.getString("NewGroup", R.string.NewGroup), R.drawable.menu_groups)); items.add(new Item(3, LocaleController.getString("NewSecretChat", R.string.NewSecretChat), R.drawable.menu_secret)); items.add(new Item(4, LocaleController.getString("NewChannel", R.string.NewChannel), R.drawable.menu_broadcast)); items.add(null); // divider diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java index 4ac9e1ead..9bd1adb30 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java @@ -19,7 +19,6 @@ import org.telegram.messenger.LocationController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.ui.Cells.EmptyCell; import org.telegram.ui.Cells.GraySectionCell; import org.telegram.ui.Cells.LocationCell; @@ -33,6 +32,8 @@ import org.telegram.ui.LocationActivity; import java.util.ArrayList; import java.util.Locale; +import androidx.recyclerview.widget.RecyclerView; + public class LocationActivityAdapter extends BaseLocationAdapter { private int currentAccount = UserConfig.selectedAccount; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivitySearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivitySearchAdapter.java index c3f2715cc..73154d397 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivitySearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivitySearchAdapter.java @@ -11,11 +11,12 @@ package org.telegram.ui.Adapters; import android.content.Context; import android.view.ViewGroup; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Cells.LocationCell; import org.telegram.ui.Components.RecyclerListView; +import androidx.recyclerview.widget.RecyclerView; + public class LocationActivitySearchAdapter extends BaseLocationAdapter { private Context mContext; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java index 0839ae589..9bfc6a78f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java @@ -25,8 +25,6 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DataQuery; -import org.telegram.messenger.Emoji; -import org.telegram.messenger.EmojiSuggestion; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; @@ -35,7 +33,6 @@ import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.TLObject; @@ -49,9 +46,12 @@ import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import androidx.recyclerview.widget.RecyclerView; + public class MentionsAdapter extends RecyclerListView.SelectionAdapter { public interface MentionsAdapterDelegate { @@ -71,7 +71,8 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { private ArrayList searchResultHashtags; private ArrayList searchResultCommands; private ArrayList searchResultCommandsHelp; - private ArrayList searchResultSuggestions; + private ArrayList searchResultSuggestions; + private String[] lastSearchKeyboardLanguage; private ArrayList searchResultCommandsUsers; private ArrayList searchResultBotContext; private TLRPC.TL_inlineBotSwitchPM searchResultBotContextSwitch; @@ -92,6 +93,8 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { private int channelReqId; private boolean isSearchingMentions; + private Runnable cancelDelayRunnable; + private String searchingContextUsername; private String searchingContextQuery; private String nextQueryOffset; @@ -259,7 +262,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { AlertDialog.Builder builder = new AlertDialog.Builder(parentFragment.getParentActivity()); builder.setTitle(LocaleController.getString("ShareYouLocationTitle", R.string.ShareYouLocationTitle)); builder.setMessage(LocaleController.getString("ShareYouLocationInline", R.string.ShareYouLocationInline)); - final boolean buttonClicked[] = new boolean[1]; + final boolean[] buttonClicked = new boolean[1]; builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> { buttonClicked[0] = true; if (foundContextBotFinal != null) { @@ -461,7 +464,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { final String key = dialog_id + "_" + query + "_" + offset + "_" + dialog_id + "_" + user.id + "_" + (user.bot_inline_geo && lastKnownLocation != null && lastKnownLocation.getLatitude() != -1000 ? lastKnownLocation.getLatitude() + lastKnownLocation.getLongitude() : ""); final MessagesStorage messagesStorage = MessagesStorage.getInstance(currentAccount); RequestDelegate requestDelegate = (response, error) -> AndroidUtilities.runOnUIThread(() -> { - if (searchingContextQuery == null || !query.equals(searchingContextQuery)) { + if (!query.equals(searchingContextQuery)) { return; } contextQueryReqid = 0; @@ -481,7 +484,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { } for (int a = 0; a < res.results.size(); a++) { TLRPC.BotInlineResult result = res.results.get(a); - if (!(result.document instanceof TLRPC.TL_document) && !(result.photo instanceof TLRPC.TL_photo) && result.content == null && result.send_message instanceof TLRPC.TL_botInlineMessageMediaAuto) { + if (!(result.document instanceof TLRPC.TL_document) && !(result.photo instanceof TLRPC.TL_photo) && !"game".equals(result.type) && result.content == null && result.send_message instanceof TLRPC.TL_botInlineMessageMediaAuto) { res.results.remove(a); a--; } @@ -498,6 +501,10 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { nextQueryOffset = ""; } } + if (cancelDelayRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(cancelDelayRunnable); + cancelDelayRunnable = null; + } searchResultHashtags = null; searchResultUsernames = null; searchResultUsernamesMap = null; @@ -541,6 +548,10 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { } public void searchUsernameOrHashtag(String text, int position, ArrayList messageObjects, boolean usernameOnly) { + if (cancelDelayRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(cancelDelayRunnable); + cancelDelayRunnable = null; + } if (channelReqId != 0) { ConnectionsManager.getInstance(currentAccount).cancelRequest(channelReqId, true); channelReqId = 0; @@ -563,7 +574,6 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { lastUsernameOnly = usernameOnly; StringBuilder result = new StringBuilder(); int foundType = -1; - boolean hasIllegalUsernameCharacters = false; if (!usernameOnly && needBotContext && text.charAt(0) == '@') { int index = text.indexOf(' '); int len = text.length(); @@ -651,9 +661,6 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { break; } } - if (!(ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == '_')) { - hasIllegalUsernameCharacters = true; - } result.insert(0, ch); } } @@ -730,14 +737,40 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { } } } + Collections.sort(newResult, (lhs, rhs) -> { + if (newMap.indexOfKey(lhs.id) >= 0 && newMap.indexOfKey(rhs.id) >= 0) { + return 0; + } else if (newMap.indexOfKey(lhs.id) >= 0) { + return -1; + } else if (newMap.indexOfKey(rhs.id) >= 0) { + return 1; + } + int lhsNum = users.indexOf(lhs.id); + int rhsNum = users.indexOf(rhs.id); + if (lhsNum != -1 && rhsNum != -1) { + return lhsNum < rhsNum ? -1 : (lhsNum == rhsNum ? 0 : 1); + } else if (lhsNum != -1 && rhsNum == -1) { + return -1; + } else if (lhsNum == -1 && rhsNum != -1) { + return 1; + } + return 0; + }); searchResultHashtags = null; searchResultCommands = null; searchResultCommandsHelp = null; searchResultCommandsUsers = null; searchResultSuggestions = null; - searchResultUsernames = newResult; - searchResultUsernamesMap = newMap; if (chat != null && chat.megagroup && usernameString.length() > 0) { + if (newResult.size() < 5) { + AndroidUtilities.runOnUIThread(cancelDelayRunnable = () -> { + cancelDelayRunnable = null; + showUsersResult(newResult, newMap, true); + }, 1000); + } else { + showUsersResult(newResult, newMap, true); + } + AndroidUtilities.runOnUIThread(searchGlobalRunnable = new Runnable() { @Override public void run() { @@ -754,9 +787,11 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { final int currentReqId = ++channelLastReqId; channelReqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (channelReqId != 0 && currentReqId == channelLastReqId && searchResultUsernamesMap != null && searchResultUsernames != null) { + showUsersResult(newResult, newMap, false); if (error == null) { TLRPC.TL_channels_channelParticipants res = (TLRPC.TL_channels_channelParticipants) response; messagesController.putUsers(res.users, false); + boolean hasResults = !searchResultUsernames.isEmpty(); if (!res.participants.isEmpty()) { int currentUserId = UserConfig.getInstance(currentAccount).getClientUserId(); for (int a = 0; a < res.participants.size(); a++) { @@ -770,37 +805,18 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { } searchResultUsernames.add(user); } - notifyDataSetChanged(); } } + notifyDataSetChanged(); + delegate.needChangePanelVisibility(!searchResultUsernames.isEmpty()); } channelReqId = 0; })); } }, 200); + } else { + showUsersResult(newResult, newMap, true); } - - Collections.sort(searchResultUsernames, (lhs, rhs) -> { - if (newResultsHashMap.indexOfKey(lhs.id) >= 0 && newResultsHashMap.indexOfKey(rhs.id) >= 0) { - return 0; - } else if (newResultsHashMap.indexOfKey(lhs.id) >= 0) { - return -1; - } else if (newResultsHashMap.indexOfKey(rhs.id) >= 0) { - return 1; - } - int lhsNum = users.indexOf(lhs.id); - int rhsNum = users.indexOf(rhs.id); - if (lhsNum != -1 && rhsNum != -1) { - return lhsNum < rhsNum ? -1 : (lhsNum == rhsNum ? 0 : 1); - } else if (lhsNum != -1 && rhsNum == -1) { - return -1; - } else if (lhsNum == -1 && rhsNum != -1) { - return 1; - } - return 0; - }); - notifyDataSetChanged(); - delegate.needChangePanelVisibility(!newResult.isEmpty()); } else if (foundType == 1) { ArrayList newResult = new ArrayList<>(); String hashtagString = result.toString().toLowerCase(); @@ -846,28 +862,13 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { notifyDataSetChanged(); delegate.needChangePanelVisibility(!newResult.isEmpty()); } else if (foundType == 3) { - if (!hasIllegalUsernameCharacters) { - Object[] suggestions = Emoji.getSuggestion(result.toString()); - if (suggestions != null) { - searchResultSuggestions = new ArrayList<>(); - for (int a = 0; a < suggestions.length; a++) { - EmojiSuggestion suggestion = (EmojiSuggestion) suggestions[a]; - suggestion.emoji = suggestion.emoji.replace("\ufe0f", ""); - searchResultSuggestions.add(suggestion); - } - Emoji.loadRecentEmoji(); - Collections.sort(searchResultSuggestions, (o1, o2) -> { - Integer n1 = Emoji.emojiUseHistory.get(o1.emoji); - if (n1 == null) { - n1 = 0; - } - Integer n2 = Emoji.emojiUseHistory.get(o2.emoji); - if (n2 == null) { - n2 = 0; - } - return n2.compareTo(n1); - }); - } + String[] newLanguage = AndroidUtilities.getCurrentKeyboardLanguage(); + if (!Arrays.equals(newLanguage, lastSearchKeyboardLanguage)) { + DataQuery.getInstance(currentAccount).fetchNewEmojiKeywords(newLanguage); + } + lastSearchKeyboardLanguage = newLanguage; + DataQuery.getInstance(currentAccount).getEmojiSuggestions(lastSearchKeyboardLanguage, result.toString(), false, (param, alias) -> { + searchResultSuggestions = param; searchResultHashtags = null; searchResultUsernames = null; searchResultUsernamesMap = null; @@ -875,10 +876,21 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter { searchResultCommandsHelp = null; searchResultCommandsUsers = null; notifyDataSetChanged(); - delegate.needChangePanelVisibility(searchResultSuggestions != null); - } else { - delegate.needChangePanelVisibility(false); - } + delegate.needChangePanelVisibility(searchResultSuggestions != null && !searchResultSuggestions.isEmpty()); + }); + } + } + + private void showUsersResult(ArrayList newResult, SparseArray newMap, boolean notify) { + searchResultUsernames = newResult; + searchResultUsernamesMap = newMap; + if (cancelDelayRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(cancelDelayRunnable); + cancelDelayRunnable = null; + } + if (notify) { + notifyDataSetChanged(); + delegate.needChangePanelVisibility(!searchResultUsernames.isEmpty()); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhonebookAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhonebookAdapter.java index 308244307..d351d09de 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhonebookAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhonebookAdapter.java @@ -17,7 +17,6 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; import org.telegram.messenger.LocaleController; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Cells.DividerCell; import org.telegram.ui.Cells.LetterSectionCell; @@ -27,6 +26,8 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; import java.util.HashMap; +import androidx.recyclerview.widget.RecyclerView; + public class PhonebookAdapter extends RecyclerListView.SectionsAdapter { private int currentAccount = UserConfig.selectedAccount; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhonebookSearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhonebookSearchAdapter.java index 7450b1bcf..318b3a603 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhonebookSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhonebookSearchAdapter.java @@ -21,7 +21,6 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Cells.UserCell; import org.telegram.ui.Components.RecyclerListView; @@ -30,6 +29,8 @@ import java.util.ArrayList; import java.util.Timer; import java.util.TimerTask; +import androidx.recyclerview.widget.RecyclerView; + public class PhonebookSearchAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; @@ -85,7 +86,7 @@ public class PhonebookSearchAdapter extends RecyclerListView.SelectionAdapter { if (search1.equals(search2) || search2.length() == 0) { search2 = null; } - String search[] = new String[1 + (search2 != null ? 1 : 0)]; + String[] search = new String[1 + (search2 != null ? 1 : 0)]; search[0] = search1; if (search2 != null) { search[1] = search2; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java index 61a9f0d15..784ef2d89 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java @@ -19,7 +19,6 @@ import android.view.ViewGroup; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.ContactsController; @@ -38,6 +37,8 @@ import java.util.HashMap; import java.util.Timer; import java.util.TimerTask; +import androidx.recyclerview.widget.RecyclerView; + public class SearchAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; @@ -138,7 +139,7 @@ public class SearchAdapter extends RecyclerListView.SelectionAdapter { if (search1.equals(search2) || search2.length() == 0) { search2 = null; } - String search[] = new String[1 + (search2 != null ? 1 : 0)]; + String[] search = new String[1 + (search2 != null ? 1 : 0)]; search[0] = search1; if (search2 != null) { search[1] = search2; 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 abe78b4f1..fd249baea 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java @@ -10,31 +10,37 @@ package org.telegram.ui.Adapters; import android.content.Context; import android.text.TextUtils; +import android.view.View; import android.view.ViewGroup; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DataQuery; import org.telegram.messenger.Emoji; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.messenger.FileLoader; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.Cells.EmojiReplacementCell; import org.telegram.ui.Cells.StickerCell; import org.telegram.ui.Components.RecyclerListView; import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import androidx.recyclerview.widget.RecyclerView; + public class StickersAdapter extends RecyclerListView.SelectionAdapter implements NotificationCenter.NotificationCenterDelegate { private int currentAccount = UserConfig.selectedAccount; private Context mContext; + private ArrayList keywordResults; private ArrayList stickers; private ArrayList stickersParents; private HashMap stickersMap; @@ -44,6 +50,8 @@ public class StickersAdapter extends RecyclerListView.SelectionAdapter implement private boolean visible; private int lastReqId; private boolean delayLocalResults; + private String[] lastSearchKeyboardLanguage; + private Runnable searchRunnable; public interface StickersAdapterDelegate { void needChangePanelVisibility(boolean show); @@ -54,11 +62,13 @@ public class StickersAdapter extends RecyclerListView.SelectionAdapter implement this.delegate = delegate; DataQuery.getInstance(currentAccount).checkStickers(DataQuery.TYPE_IMAGE); DataQuery.getInstance(currentAccount).checkStickers(DataQuery.TYPE_MASK); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.newEmojiSuggestionsAvailable); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileDidFailedLoad); } public void onDestroy() { + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.newEmojiSuggestionsAvailable); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileDidFailedLoad); } @@ -70,9 +80,17 @@ public class StickersAdapter extends RecyclerListView.SelectionAdapter implement String fileName = (String) args[0]; stickersToLoad.remove(fileName); if (stickersToLoad.isEmpty()) { - delegate.needChangePanelVisibility(stickers != null && !stickers.isEmpty() && stickersToLoad.isEmpty()); + boolean show = stickers != null && !stickers.isEmpty() && stickersToLoad.isEmpty(); + if (show) { + keywordResults = null; + } + delegate.needChangePanelVisibility(show); } } + } else if (id == NotificationCenter.newEmojiSuggestionsAvailable) { + if ((keywordResults == null || keywordResults.isEmpty()) && !TextUtils.isEmpty(lastSticker) && getItemCount() == 0) { + searchEmojiByKeyword(); + } } } @@ -89,7 +107,7 @@ public class StickersAdapter extends RecyclerListView.SelectionAdapter implement File f = FileLoader.getPathToAttach(thumb, "webp", true); if (!f.exists()) { stickersToLoad.add(FileLoader.getAttachFileName(thumb, "webp")); - FileLoader.getInstance(currentAccount).loadFile(thumb.location, stickersParents.get(a), "webp", 0, 1, 1); + FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForDocument(thumb, document), stickersParents.get(a), "webp", 1, 1); } } } @@ -159,127 +177,165 @@ public class StickersAdapter extends RecyclerListView.SelectionAdapter implement } } - public void loadStikersForEmoji(CharSequence emoji) { - if (SharedConfig.suggestStickers == 2) { - return; + public void hide() { + if (visible && (stickers != null || keywordResults != null && !keywordResults.isEmpty())) { + visible = false; + delegate.needChangePanelVisibility(false); } - boolean search = emoji != null && emoji.length() > 0 && emoji.length() <= 14; - if (search) { - String originalEmoji = emoji.toString(); - int length = emoji.length(); - for (int a = 0; a < length; a++) { - if (a < length - 1 && (emoji.charAt(a) == 0xD83C && emoji.charAt(a + 1) >= 0xDFFB && emoji.charAt(a + 1) <= 0xDFFF || emoji.charAt(a) == 0x200D && (emoji.charAt(a + 1) == 0x2640 || emoji.charAt(a + 1) == 0x2642))) { - emoji = TextUtils.concat(emoji.subSequence(0, a), emoji.subSequence(a + 2, emoji.length())); - length -= 2; - a--; - } else if (emoji.charAt(a) == 0xfe0f) { - emoji = TextUtils.concat(emoji.subSequence(0, a), emoji.subSequence(a + 1, emoji.length())); - length--; - a--; - } - } - lastSticker = emoji.toString();/*.trim();*/ - if (!Emoji.isValidEmoji(originalEmoji) && !Emoji.isValidEmoji(lastSticker)) { - if (visible) { - visible = false; - delegate.needChangePanelVisibility(false); - notifyDataSetChanged(); - } - return; - } - stickers = null; - stickersParents = null; - stickersMap = null; + } - delayLocalResults = false; - final ArrayList recentStickers = DataQuery.getInstance(currentAccount).getRecentStickersNoCopy(DataQuery.TYPE_IMAGE); - final ArrayList favsStickers = DataQuery.getInstance(currentAccount).getRecentStickersNoCopy(DataQuery.TYPE_FAVE); - int recentsAdded = 0; - for (int a = 0, size = recentStickers.size(); a < size; a++) { - TLRPC.Document document = recentStickers.get(a); - if (isValidSticker(document, lastSticker)) { - addStickerToResult(document, "recent"); - recentsAdded++; - if (recentsAdded >= 5) { - break; - } - } - } - for (int a = 0, size = favsStickers.size(); a < size; a++) { - TLRPC.Document document = favsStickers.get(a); - if (isValidSticker(document, lastSticker)) { - addStickerToResult(document, "fav"); - } - } + private void cancelEmojiSearch() { + if (searchRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(searchRunnable); + searchRunnable = null; + } + } - HashMap> allStickers = DataQuery.getInstance(currentAccount).getAllStickers(); - ArrayList newStickers = allStickers != null ? allStickers.get(lastSticker) : null; - if (newStickers != null && !newStickers.isEmpty()) { - ArrayList arrayList = new ArrayList<>(newStickers); - if (!recentStickers.isEmpty()) { - Collections.sort(arrayList, new Comparator() { - private int getIndex(long id) { - for (int a = 0; a < favsStickers.size(); a++) { - if (favsStickers.get(a).id == id) { - return a + 1000; - } - } - for (int a = 0; a < recentStickers.size(); a++) { - if (recentStickers.get(a).id == id) { - return a; - } - } - return -1; - } - - @Override - public int compare(TLRPC.Document lhs, TLRPC.Document rhs) { - int idx1 = getIndex(lhs.id); - int idx2 = getIndex(rhs.id); - if (idx1 > idx2) { - return -1; - } else if (idx1 < idx2) { - return 1; - } - return 0; - } - }); - } - - addStickersToResult(arrayList, null); - } - if (SharedConfig.suggestStickers == 0) { - searchServerStickers(lastSticker, originalEmoji); - } - - if (stickers != null && !stickers.isEmpty()) { - if (SharedConfig.suggestStickers == 0 && stickers.size() < 5) { - delayLocalResults = true; - delegate.needChangePanelVisibility(false); - visible = false; - } else { - checkStickerFilesExistAndDownload(); - delegate.needChangePanelVisibility(stickers != null && !stickers.isEmpty() && stickersToLoad.isEmpty()); - visible = true; + private void searchEmojiByKeyword() { + String[] newLanguage = AndroidUtilities.getCurrentKeyboardLanguage(); + if (!Arrays.equals(newLanguage, lastSearchKeyboardLanguage)) { + DataQuery.getInstance(currentAccount).fetchNewEmojiKeywords(newLanguage); + } + lastSearchKeyboardLanguage = newLanguage; + String query = lastSticker; + cancelEmojiSearch(); + searchRunnable = () -> DataQuery.getInstance(currentAccount).getEmojiSuggestions(lastSearchKeyboardLanguage, query, true, (param, alias) -> { + if (query.equals(lastSticker)) { + if (!param.isEmpty()) { + keywordResults = param; } notifyDataSetChanged(); - } else if (visible) { - delegate.needChangePanelVisibility(false); - visible = false; + delegate.needChangePanelVisibility(visible = !param.isEmpty()); } + }); + if (keywordResults == null || keywordResults.isEmpty()) { + AndroidUtilities.runOnUIThread(searchRunnable, 1000); } else { - lastSticker = ""; - if (visible && stickers != null) { + searchRunnable.run(); + } + } + + public void loadStikersForEmoji(CharSequence emoji, boolean emojiOnly) { + boolean searchEmoji = emoji != null && emoji.length() > 0 && emoji.length() <= 14; + + String originalEmoji = emoji.toString(); + int length = emoji.length(); + for (int a = 0; a < length; a++) { + if (a < length - 1 && (emoji.charAt(a) == 0xD83C && emoji.charAt(a + 1) >= 0xDFFB && emoji.charAt(a + 1) <= 0xDFFF || emoji.charAt(a) == 0x200D && (emoji.charAt(a + 1) == 0x2640 || emoji.charAt(a + 1) == 0x2642))) { + emoji = TextUtils.concat(emoji.subSequence(0, a), emoji.subSequence(a + 2, emoji.length())); + length -= 2; + a--; + } else if (emoji.charAt(a) == 0xfe0f) { + emoji = TextUtils.concat(emoji.subSequence(0, a), emoji.subSequence(a + 1, emoji.length())); + length--; + a--; + } + } + lastSticker = emoji.toString(); + boolean isValidEmoji = searchEmoji && (Emoji.isValidEmoji(originalEmoji) || Emoji.isValidEmoji(lastSticker)); + if (emojiOnly || SharedConfig.suggestStickers == 2 || !isValidEmoji) { + if (visible && (keywordResults == null || keywordResults.isEmpty())) { visible = false; delegate.needChangePanelVisibility(false); + notifyDataSetChanged(); } + if (!isValidEmoji) { + searchEmojiByKeyword(); + } + return; + } + cancelEmojiSearch(); + stickers = null; + stickersParents = null; + stickersMap = null; + if (lastReqId != 0) { + ConnectionsManager.getInstance(currentAccount).cancelRequest(lastReqId, true); + lastReqId = 0; + } + + delayLocalResults = false; + final ArrayList recentStickers = DataQuery.getInstance(currentAccount).getRecentStickersNoCopy(DataQuery.TYPE_IMAGE); + final ArrayList favsStickers = DataQuery.getInstance(currentAccount).getRecentStickersNoCopy(DataQuery.TYPE_FAVE); + int recentsAdded = 0; + for (int a = 0, size = recentStickers.size(); a < size; a++) { + TLRPC.Document document = recentStickers.get(a); + if (isValidSticker(document, lastSticker)) { + addStickerToResult(document, "recent"); + recentsAdded++; + if (recentsAdded >= 5) { + break; + } + } + } + for (int a = 0, size = favsStickers.size(); a < size; a++) { + TLRPC.Document document = favsStickers.get(a); + if (isValidSticker(document, lastSticker)) { + addStickerToResult(document, "fav"); + } + } + + HashMap> allStickers = DataQuery.getInstance(currentAccount).getAllStickers(); + ArrayList newStickers = allStickers != null ? allStickers.get(lastSticker) : null; + if (newStickers != null && !newStickers.isEmpty()) { + ArrayList arrayList = new ArrayList<>(newStickers); + if (!recentStickers.isEmpty()) { + Collections.sort(arrayList, new Comparator() { + private int getIndex(long id) { + for (int a = 0; a < favsStickers.size(); a++) { + if (favsStickers.get(a).id == id) { + return a + 1000; + } + } + for (int a = 0; a < recentStickers.size(); a++) { + if (recentStickers.get(a).id == id) { + return a; + } + } + return -1; + } + + @Override + public int compare(TLRPC.Document lhs, TLRPC.Document rhs) { + int idx1 = getIndex(lhs.id); + int idx2 = getIndex(rhs.id); + if (idx1 > idx2) { + return -1; + } else if (idx1 < idx2) { + return 1; + } + return 0; + } + }); + } + + addStickersToResult(arrayList, null); + } + if (SharedConfig.suggestStickers == 0) { + searchServerStickers(lastSticker, originalEmoji); + } + + if (stickers != null && !stickers.isEmpty()) { + if (SharedConfig.suggestStickers == 0 && stickers.size() < 5) { + delayLocalResults = true; + delegate.needChangePanelVisibility(false); + visible = false; + } else { + checkStickerFilesExistAndDownload(); + boolean show = stickers != null && !stickers.isEmpty() && stickersToLoad.isEmpty(); + if (show) { + keywordResults = null; + } + delegate.needChangePanelVisibility(show); + visible = true; + } + notifyDataSetChanged(); + } else if (visible) { + delegate.needChangePanelVisibility(false); + visible = false; } } private void searchServerStickers(final String emoji, final String originalEmoji) { - if (lastReqId != 0) { - ConnectionsManager.getInstance(currentAccount).cancelRequest(lastReqId, true); - } TLRPC.TL_messages_getStickers req = new TLRPC.TL_messages_getStickers(); req.emoticon = originalEmoji; req.hash = 0; @@ -295,7 +351,11 @@ public class StickersAdapter extends RecyclerListView.SelectionAdapter implement int newCount = stickers != null ? stickers.size() : 0; if (!visible && stickers != null && !stickers.isEmpty()) { checkStickerFilesExistAndDownload(); - delegate.needChangePanelVisibility(stickers != null && !stickers.isEmpty() && stickersToLoad.isEmpty()); + boolean show = stickers != null && !stickers.isEmpty() && stickersToLoad.isEmpty(); + if (show) { + keywordResults = null; + } + delegate.needChangePanelVisibility(show); visible = true; } if (oldCount != newCount) { @@ -305,10 +365,14 @@ public class StickersAdapter extends RecyclerListView.SelectionAdapter implement } public void clearStickers() { + if (delayLocalResults || lastReqId != 0) { + return; + } lastSticker = null; stickers = null; stickersParents = null; stickersMap = null; + keywordResults = null; stickersToLoad.clear(); notifyDataSetChanged(); if (lastReqId != 0) { @@ -317,42 +381,93 @@ public class StickersAdapter extends RecyclerListView.SelectionAdapter implement } } + public boolean isShowingKeywords() { + return keywordResults != null && !keywordResults.isEmpty(); + } + @Override public int getItemCount() { + if (keywordResults != null && !keywordResults.isEmpty()) { + return keywordResults.size(); + } return !delayLocalResults && stickers != null ? stickers.size() : 0; } - public TLRPC.Document getItem(int i) { + public Object getItem(int i) { + if (keywordResults != null && !keywordResults.isEmpty()) { + return keywordResults.get(i).emoji; + } return stickers != null && i >= 0 && i < stickers.size() ? stickers.get(i) : null; } public Object getItemParent(int i) { + if (keywordResults != null && !keywordResults.isEmpty()) { + return null; + } return stickersParents != null && i >= 0 && i < stickersParents.size() ? stickersParents.get(i) : null; } @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { - return true; + return false; } @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { - StickerCell view = new StickerCell(mContext); + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View view; + switch (viewType) { + case 0: + view = new StickerCell(mContext); + break; + case 1: + default: + view = new EmojiReplacementCell(mContext); + } return new RecyclerListView.Holder(view); } @Override - public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) { - int side = 0; - if (i == 0) { - if (stickers.size() == 1) { - side = 2; - } else { - side = -1; - } - } else if (i == stickers.size() - 1) { - side = 1; + public int getItemViewType(int position) { + if (keywordResults != null && !keywordResults.isEmpty()) { + return 1; + } + return 0; + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + switch (holder.getItemViewType()) { + case 0: { + int side = 0; + if (position == 0) { + if (stickers.size() == 1) { + side = 2; + } else { + side = -1; + } + } else if (position == stickers.size() - 1) { + side = 1; + } + StickerCell stickerCell = (StickerCell) holder.itemView; + stickerCell.setSticker(stickers.get(position), stickersParents.get(position), side); + stickerCell.setClearsInputField(true); + break; + } + case 1: { + int side = 0; + if (position == 0) { + if (keywordResults.size() == 1) { + side = 2; + } else { + side = -1; + } + } else if (position == keywordResults.size() - 1) { + side = 1; + } + EmojiReplacementCell cell = (EmojiReplacementCell) holder.itemView; + cell.setEmoji(keywordResults.get(position).emoji, side); + break; + } } - ((StickerCell) viewHolder.itemView).setSticker(stickers.get(i), stickersParents.get(i), side); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArchivedStickersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ArchivedStickersActivity.java index e0ce6cf04..317c4ee3e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArchivedStickersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArchivedStickersActivity.java @@ -18,8 +18,6 @@ import org.telegram.messenger.DataQuery; import org.telegram.messenger.LocaleController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; @@ -36,6 +34,9 @@ import org.telegram.ui.Components.StickersAlert; import java.util.ArrayList; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class ArchivedStickersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListAdapter listAdapter; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java index 67a8e85b0..5bd51ca7c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java @@ -39,10 +39,15 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.support.annotation.Keep; -import android.support.v4.content.FileProvider; -import android.support.v4.view.PagerAdapter; -import android.support.v4.view.ViewPager; +import androidx.annotation.Keep; +import androidx.core.content.FileProvider; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.GridLayoutManagerFixed; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; import android.text.Layout; import android.text.Spannable; import android.text.SpannableStringBuilder; @@ -70,6 +75,7 @@ import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.WindowInsets; import android.view.WindowManager; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.DecelerateInterpolator; import android.webkit.CookieManager; import android.webkit.JavascriptInterface; @@ -97,6 +103,7 @@ import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; @@ -109,11 +116,6 @@ import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.messenger.WebFile; import org.telegram.messenger.browser.Browser; -import org.telegram.messenger.support.widget.DefaultItemAnimator; -import org.telegram.messenger.support.widget.GridLayoutManager; -import org.telegram.messenger.support.widget.GridLayoutManagerFixed; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; @@ -185,6 +187,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg private boolean loadingChannel; private Object lastInsets; + boolean hasCutout; private boolean isVisible; private boolean collapsed; @@ -230,6 +233,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg private AnimatorSet pageSwitchAnimation; private Paint headerPaint = new Paint(); + private Paint statusBarPaint = new Paint(); private Paint headerProgressPaint = new Paint(); private ActionBarPopupWindow popupWindow; @@ -355,6 +359,10 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg private int index = Integer.MAX_VALUE; } + private class TL_pageBlockEmbedPostCaption extends TLRPC.TL_pageBlockEmbedPost { + private TLRPC.TL_pageBlockEmbedPost parent; + } + public class DrawingText { public StaticLayout textLayout; public LinkPath textPath; @@ -726,6 +734,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg bWidth = widthSize; bHeight = insets.getSystemWindowInsetBottom(); } + heightSize -= insets.getSystemWindowInsetTop(); } else { setMeasuredDimension(widthSize, heightSize); } @@ -753,6 +762,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg anchorsOffsetMeasuredWidth = width; } int x; + int y = 0; if (Build.VERSION.SDK_INT >= 21 && lastInsets != null) { WindowInsets insets = (WindowInsets) lastInsets; x = insets.getSystemWindowInsetLeft(); @@ -767,13 +777,16 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg bX = 0; bY = bottom - top - bHeight; } + if (Build.VERSION.SDK_INT >= 28) { + y += insets.getSystemWindowInsetTop(); + } } else { x = 0; } - containerView.layout(x, 0, x + containerView.getMeasuredWidth(), containerView.getMeasuredHeight()); - photoContainerView.layout(x, 0, x + photoContainerView.getMeasuredWidth(), photoContainerView.getMeasuredHeight()); - photoContainerBackground.layout(x, 0, x + photoContainerBackground.getMeasuredWidth(), photoContainerBackground.getMeasuredHeight()); - fullscreenVideoContainer.layout(x, 0, x + fullscreenVideoContainer.getMeasuredWidth(), fullscreenVideoContainer.getMeasuredHeight()); + containerView.layout(x, y, x + containerView.getMeasuredWidth(), y + containerView.getMeasuredHeight()); + photoContainerView.layout(x, y, x + photoContainerView.getMeasuredWidth(), y + photoContainerView.getMeasuredHeight()); + photoContainerBackground.layout(x, y, x + photoContainerBackground.getMeasuredWidth(), y + photoContainerBackground.getMeasuredHeight()); + fullscreenVideoContainer.layout(x, y, x + fullscreenVideoContainer.getMeasuredWidth(), y + fullscreenVideoContainer.getMeasuredHeight()); animatingImageView.layout(0, 0, animatingImageView.getMeasuredWidth(), animatingImageView.getMeasuredHeight()); } @@ -1008,12 +1021,17 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg @Override protected void onDraw(Canvas canvas) { canvas.drawRect(innerTranslationX, 0, getMeasuredWidth(), getMeasuredHeight(), backgroundPaint); + if (Build.VERSION.SDK_INT >= 21 && hasCutout && lastInsets != null) { + WindowInsets insets = (WindowInsets) lastInsets; + canvas.drawRect(innerTranslationX, 0, getMeasuredWidth(), insets.getSystemWindowInsetBottom(), statusBarPaint); + } } @Keep @Override public void setAlpha(float value) { backgroundPaint.setAlpha((int) (255 * value)); + statusBarPaint.setAlpha((int) (255 * value)); alpha = value; if (parentActivity instanceof LaunchActivity) { ((LaunchActivity) parentActivity).drawerLayoutContainer.setAllowDrawContent(!isVisible || alpha != 1.0f || innerTranslationX != 0); @@ -1045,7 +1063,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } else if (pressedLinkOwnerLayout != null && pressedLinkOwnerView != null) { windowView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - int location[] = new int[2]; + int[] location = new int[2]; pressedLinkOwnerView.getLocationInWindow(location); int y = location[1] + pressedLayoutY - AndroidUtilities.dp(54); if (y < 0) { @@ -1218,7 +1236,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg popupWindow = new ActionBarPopupWindow(popupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); popupWindow.setAnimationEnabled(false); - popupWindow.setAnimationStyle(R.style.PopupAnimation); + popupWindow.setAnimationStyle(R.style.PopupContextAnimation); popupWindow.setOutsideTouchable(true); popupWindow.setClippingEnabled(true); popupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); @@ -1349,9 +1367,15 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg private View getLastNonListCell(View view) { if (view instanceof BlockListItemCell) { - return getLastNonListCell(((BlockListItemCell) view).blockLayout.itemView); + BlockListItemCell cell = (BlockListItemCell) view; + if (cell.blockLayout != null) { + return getLastNonListCell(cell.blockLayout.itemView); + } } else if (view instanceof BlockOrderedListItemCell) { - return getLastNonListCell(((BlockOrderedListItemCell) view).blockLayout.itemView); + BlockOrderedListItemCell cell = (BlockOrderedListItemCell) view; + if (cell.blockLayout != null) { + return getLastNonListCell(cell.blockLayout.itemView); + } } return view; } @@ -1817,7 +1841,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg return getText(parentView, parentRichText, ((TLRPC.TL_textStrike) richText).text, parentBlock, maxWidth); } else if (richText instanceof TLRPC.TL_textEmail) { SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(getText(parentView, parentRichText, ((TLRPC.TL_textEmail) richText).text, parentBlock, maxWidth)); - MetricAffectingSpan innerSpans[] = spannableStringBuilder.getSpans(0, spannableStringBuilder.length(), MetricAffectingSpan.class); + MetricAffectingSpan[] innerSpans = spannableStringBuilder.getSpans(0, spannableStringBuilder.length(), MetricAffectingSpan.class); if (spannableStringBuilder.length() != 0) { spannableStringBuilder.setSpan(new TextPaintUrlSpan(innerSpans == null || innerSpans.length == 0 ? getTextPaint(parentRichText, richText, parentBlock) : null, "mailto:" + getUrl(richText)), 0, spannableStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } @@ -1825,7 +1849,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } else if (richText instanceof TLRPC.TL_textUrl) { TLRPC.TL_textUrl textUrl = (TLRPC.TL_textUrl) richText; SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(getText(parentView, parentRichText, ((TLRPC.TL_textUrl) richText).text, parentBlock, maxWidth)); - MetricAffectingSpan innerSpans[] = spannableStringBuilder.getSpans(0, spannableStringBuilder.length(), MetricAffectingSpan.class); + MetricAffectingSpan[] innerSpans = spannableStringBuilder.getSpans(0, spannableStringBuilder.length(), MetricAffectingSpan.class); TextPaint paint = innerSpans == null || innerSpans.length == 0 ? getTextPaint(parentRichText, richText, parentBlock) : null; MetricAffectingSpan span; if (textUrl.webpage_id != 0) { @@ -1893,14 +1917,14 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg return getText(parentView, parentRichText, ((TLRPC.TL_textSuperscript) richText).text, parentBlock, maxWidth); } else if (richText instanceof TLRPC.TL_textMarked) { SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(getText(parentView, parentRichText, ((TLRPC.TL_textMarked) richText).text, parentBlock, maxWidth)); - MetricAffectingSpan innerSpans[] = spannableStringBuilder.getSpans(0, spannableStringBuilder.length(), MetricAffectingSpan.class); + MetricAffectingSpan[] innerSpans = spannableStringBuilder.getSpans(0, spannableStringBuilder.length(), MetricAffectingSpan.class); if (spannableStringBuilder.length() != 0) { spannableStringBuilder.setSpan(new TextPaintMarkSpan(innerSpans == null || innerSpans.length == 0 ? getTextPaint(parentRichText, richText, parentBlock) : null), 0, spannableStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } return spannableStringBuilder; } else if (richText instanceof TLRPC.TL_textPhone) { SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(getText(parentView, parentRichText, ((TLRPC.TL_textPhone) richText).text, parentBlock, maxWidth)); - MetricAffectingSpan innerSpans[] = spannableStringBuilder.getSpans(0, spannableStringBuilder.length(), MetricAffectingSpan.class); + MetricAffectingSpan[] innerSpans = spannableStringBuilder.getSpans(0, spannableStringBuilder.length(), MetricAffectingSpan.class); if (spannableStringBuilder.length() != 0) { spannableStringBuilder.setSpan(new TextPaintUrlSpan(innerSpans == null || innerSpans.length == 0 ? getTextPaint(parentRichText, richText, parentBlock) : null, "tel:" + getUrl(richText)), 0, spannableStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } @@ -1927,7 +1951,52 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg return "not supported " + richText; } - private String getUrl(TLRPC.RichText richText) { + public static CharSequence getPlainText(TLRPC.RichText richText) { + if (richText == null) { + return ""; + } + if (richText instanceof TLRPC.TL_textFixed) { + return getPlainText(((TLRPC.TL_textFixed) richText).text); + } else if (richText instanceof TLRPC.TL_textItalic) { + return getPlainText(((TLRPC.TL_textItalic) richText).text); + } else if (richText instanceof TLRPC.TL_textBold) { + return getPlainText(((TLRPC.TL_textBold) richText).text); + } else if (richText instanceof TLRPC.TL_textUnderline) { + return getPlainText(((TLRPC.TL_textUnderline) richText).text); + } else if (richText instanceof TLRPC.TL_textStrike) { + return getPlainText(((TLRPC.TL_textStrike) richText).text); + } else if (richText instanceof TLRPC.TL_textEmail) { + return getPlainText(((TLRPC.TL_textEmail) richText).text); + } else if (richText instanceof TLRPC.TL_textUrl) { + return getPlainText(((TLRPC.TL_textUrl) richText).text); + } else if (richText instanceof TLRPC.TL_textPlain) { + return ((TLRPC.TL_textPlain) richText).text; + } else if (richText instanceof TLRPC.TL_textAnchor) { + return getPlainText(((TLRPC.TL_textAnchor) richText).text); + } else if (richText instanceof TLRPC.TL_textEmpty) { + return ""; + } else if (richText instanceof TLRPC.TL_textConcat) { + StringBuilder stringBuilder = new StringBuilder(); + int count = richText.texts.size(); + for (int a = 0; a < count; a++) { + stringBuilder.append(getPlainText(richText.texts.get(a))); + } + return stringBuilder; + } else if (richText instanceof TLRPC.TL_textSubscript) { + return getPlainText(((TLRPC.TL_textSubscript) richText).text); + } else if (richText instanceof TLRPC.TL_textSuperscript) { + return getPlainText(((TLRPC.TL_textSuperscript) richText).text); + } else if (richText instanceof TLRPC.TL_textMarked) { + return getPlainText(((TLRPC.TL_textMarked) richText).text); + } else if (richText instanceof TLRPC.TL_textPhone) { + return getPlainText(((TLRPC.TL_textPhone) richText).text); + } else if (richText instanceof TLRPC.TL_textImage) { + return ""; + } + return ""; + } + + public static String getUrl(TLRPC.RichText richText) { if (richText instanceof TLRPC.TL_textFixed) { return getUrl(((TLRPC.TL_textFixed) richText).text); } else if (richText instanceof TLRPC.TL_textItalic) { @@ -2379,7 +2448,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (result != null && finalText instanceof Spanned) { Spanned spanned = (Spanned) finalText; try { - AnchorSpan innerSpans[] = spanned.getSpans(0, spanned.length(), AnchorSpan.class); + AnchorSpan[] innerSpans = spanned.getSpans(0, spanned.length(), AnchorSpan.class); int linesCount = result.getLineCount(); if (innerSpans != null && innerSpans.length > 0) { for (int a = 0; a < innerSpans.length; a++) { @@ -2394,7 +2463,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } try { - TextPaintWebpageUrlSpan innerSpans[] = spanned.getSpans(0, spanned.length(), TextPaintWebpageUrlSpan.class); + TextPaintWebpageUrlSpan[] innerSpans = spanned.getSpans(0, spanned.length(), TextPaintWebpageUrlSpan.class); if (innerSpans != null && innerSpans.length > 0) { textPath = new LinkPath(true); textPath.setAllowReset(false); @@ -2412,7 +2481,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } try { - TextPaintMarkSpan innerSpans[] = spanned.getSpans(0, spanned.length(), TextPaintMarkSpan.class); + TextPaintMarkSpan[] innerSpans = spanned.getSpans(0, spanned.length(), TextPaintMarkSpan.class); if (innerSpans != null && innerSpans.length > 0) { markPath = new LinkPath(true); markPath.setAllowReset(false); @@ -2650,7 +2719,6 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg return null; } - @SuppressWarnings("unchecked") @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.fileDidFailedLoad) { @@ -3023,11 +3091,11 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg windowView.requestLayout(); } if (Build.VERSION.SDK_INT >= 28) { - DisplayCutout cutout = insets.getDisplayCutout(); + DisplayCutout cutout = parentActivity.getWindow().getDecorView().getRootWindowInsets().getDisplayCutout(); if (cutout != null) { List rects = cutout.getBoundingRects(); if (rects != null && !rects.isEmpty()) { - settingsButton.setMenuYOffset(Math.abs(rects.get(0).height())); + hasCutout = rects.get(0).height() != 0; } } } @@ -3244,6 +3312,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } headerPaint.setColor(0xff000000); + statusBarPaint.setColor(0xff000000); headerProgressPaint.setColor(0xff242426); headerView = new FrameLayout(activity) { @Override @@ -3304,6 +3373,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg }*/ close(true, true); }); + backButton.setContentDescription(LocaleController.getString("AccDescrGoBack", R.string.AccDescrGoBack)); titleTextView = new SimpleTextView(activity); titleTextView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); @@ -3443,9 +3513,11 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); textView.setTextColor(0xffb3b3b3); textView.setGravity(Gravity.CENTER); + textView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); settingsButton.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); settingsButton.addSubItem(settingsContainer, AndroidUtilities.dp(220), LayoutHelper.WRAP_CONTENT); settingsButton.redrawPopup(0xffffffff); + settingsButton.setContentDescription(LocaleController.getString("Settings", R.string.Settings)); headerView.addView(settingsButton, LayoutHelper.createFrame(48, 56, Gravity.TOP | Gravity.RIGHT, 0, 0, 56, 0)); shareContainer = new FrameLayout(activity); @@ -3461,6 +3533,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg shareButton.setScaleType(ImageView.ScaleType.CENTER); shareButton.setImageResource(R.drawable.ic_share_article); shareButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); + shareButton.setContentDescription(LocaleController.getString("ShareFile", R.string.ShareFile)); shareContainer.addView(shareButton, LayoutHelper.createFrame(48, 56)); progressView = new ContextProgressView(activity, 2); @@ -3478,6 +3551,9 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + if (Build.VERSION.SDK_INT >= 28) { + windowLayoutParams.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + } } else { windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; } @@ -3547,9 +3623,10 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg menu.addItem(gallery_menu_share, R.drawable.share); menuItem = menu.addItem(0, R.drawable.ic_ab_other); menuItem.setLayoutInScreen(true); - menuItem.addSubItem(gallery_menu_openin, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)); - //menuItem.addSubItem(gallery_menu_share, LocaleController.getString("ShareFile", R.string.ShareFile), 0); - menuItem.addSubItem(gallery_menu_save, LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); + menuItem.addSubItem(gallery_menu_openin, R.drawable.msg_openin, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)).setColors(0xfffafafa, 0xfffafafa); + //menuItem.addSubItem(gallery_menu_share, LocaleController.getString("ShareFile", R.string.ShareFile), 0).setTextColor(0xfffafafa); + menuItem.addSubItem(gallery_menu_save, R.drawable.msg_gallery, LocaleController.getString("SaveToGallery", R.string.SaveToGallery)).setColors(0xfffafafa, 0xfffafafa); + menuItem.redrawPopup(0xf9222222); bottomLayout = new FrameLayout(parentActivity); bottomLayout.setBackgroundColor(0x7f000000); @@ -3579,7 +3656,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } @Override - public ArrayList getImagesArrLocations() { + public ArrayList getImagesArrLocations() { return null; } @@ -3914,7 +3991,11 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg captionTextView.setVisibility(View.GONE); captionTextViewNext.setVisibility(View.GONE); layoutManager[0].scrollToPositionWithOffset(0, 0); - checkScrollAnimated(); + if (first) { + setCurrentHeaderHeight(AndroidUtilities.dp(56)); + } else { + checkScrollAnimated(); + } boolean scrolledToAnchor = addPageToStack(webpage, anchor, 0); @@ -3973,6 +4054,9 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + if (Build.VERSION.SDK_INT >= 28) { + windowLayoutParams.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + } } windowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; windowView.setFocusable(false); @@ -4538,7 +4622,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } else if (richText instanceof TLRPC.TL_textUnderline) { setRichTextParents(richText, ((TLRPC.TL_textUnderline) richText).text); } else if (richText instanceof TLRPC.TL_textStrike) { - setRichTextParents(parentRichText, ((TLRPC.TL_textStrike) richText).text); + setRichTextParents(richText, ((TLRPC.TL_textStrike) richText).text); } else if (richText instanceof TLRPC.TL_textEmail) { setRichTextParents(richText, ((TLRPC.TL_textEmail) richText).text); } else if (richText instanceof TLRPC.TL_textPhone) { @@ -4744,6 +4828,12 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg blocks.add(innerBlock); addAllMediaFromBlock(innerBlock); } + if (!TextUtils.isEmpty(getPlainText(pageBlockEmbedPost.caption.text)) || !TextUtils.isEmpty(getPlainText(pageBlockEmbedPost.caption.credit))) { + TL_pageBlockEmbedPostCaption pageBlockEmbedPostCaption = new TL_pageBlockEmbedPostCaption(); + pageBlockEmbedPostCaption.parent = pageBlockEmbedPost; + pageBlockEmbedPostCaption.caption = pageBlockEmbedPost.caption; + blocks.add(pageBlockEmbedPostCaption); + } } } else if (block instanceof TLRPC.TL_pageBlockRelatedArticles) { TLRPC.TL_pageBlockRelatedArticles pageBlockRelatedArticles = (TLRPC.TL_pageBlockRelatedArticles) block; @@ -4961,6 +5051,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg TLRPC.Photo photo = getPhotoWithId(pageBlockPhoto.photo_id); if (photo != null) { pageBlockPhoto.thumb = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, 56, true); + pageBlockPhoto.thumbObject = photo; photoBlocks.add(block); } } else if (block instanceof TLRPC.TL_pageBlockVideo && isVideoBlock(block)) { @@ -4968,6 +5059,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg TLRPC.Document document = getDocumentWithId(pageBlockVideo.video_id); if (document != null) { pageBlockVideo.thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 56, true); + pageBlockVideo.thumbObject = document; photoBlocks.add(block); } } else if (block instanceof TLRPC.TL_pageBlockSlideshow) { @@ -5141,6 +5233,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } } view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)); + view.setFocusable(true); return new RecyclerListView.Holder(view); } @@ -5159,21 +5252,18 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg TLRPC.PageBlock block = localBlocks.get(position); bindBlockToHolder(holder.getItemViewType(), holder, block, position, localBlocks.size()); } else { - switch (holder.getItemViewType()) { - case 90: { - TextView textView = (TextView) ((ViewGroup) holder.itemView).getChildAt(0); - int color = getSelectedColor(); - if (color == 0) { - textView.setTextColor(0xff78828d); - textView.setBackgroundColor(0xffedeff0); - } else if (color == 1) { - textView.setTextColor(getGrayTextColor()); - textView.setBackgroundColor(0xffe5dec8); - } else if (color == 2) { - textView.setTextColor(getGrayTextColor()); - textView.setBackgroundColor(0xff1b1b1b); - } - break; + if (holder.getItemViewType() == 90) { + TextView textView = (TextView) ((ViewGroup) holder.itemView).getChildAt(0); + int color = getSelectedColor(); + if (color == 0) { + textView.setTextColor(0xff78828d); + textView.setBackgroundColor(0xffedeff0); + } else if (color == 1) { + textView.setTextColor(getGrayTextColor()); + textView.setBackgroundColor(0xffe5dec8); + } else if (color == 2) { + textView.setTextColor(getGrayTextColor()); + textView.setBackgroundColor(0xff1b1b1b); } } } @@ -5710,10 +5800,9 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg imageView.setImageCoords(photoX, (isFirst || currentType == 1 || currentType == 2 || currentBlock.level > 0) ? 0 : AndroidUtilities.dp(8), photoWidth, photoHeight); if (isGif) { - String filter = String.format(Locale.US, "%d_%d", photoWidth, photoHeight); - imageView.setImage(currentDocument, null, null, null, null, thumb, "80_80_b", currentDocument.size, null, currentPage, 1); + imageView.setImage(ImageLocation.getForDocument(currentDocument), null, null, null, ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", null, currentDocument.size, null, currentPage, 1); } else { - imageView.setImage(null, null, thumb, "80_80_b", 0, null, currentPage, 1); + imageView.setImage(null, null, ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", 0, null, currentPage, 1); } imageView.setAspectFit(true); buttonX = (int) (imageView.getImageX() + (imageView.getImageWidth() - size) / 2.0f); @@ -5834,7 +5923,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg radialProgress.setProgress(0, false); if (isGif) { TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(currentDocument.thumbs, 90); - imageView.setImage(currentDocument, null, thumb, "80_80_b", currentDocument.size, null, currentPage, 1); + imageView.setImage(ImageLocation.getForDocument(currentDocument), null, ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", currentDocument.size, null, currentPage, 1); } else { FileLoader.getInstance(currentAccount).loadFile(currentDocument, currentPage, 1, 1); } @@ -5908,6 +5997,18 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg public int getObserverTag() { return TAG; } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + StringBuilder sb = new StringBuilder(LocaleController.getString("AttachVideo", R.string.AttachVideo)); + if(captionLayout != null){ + sb.append(", "); + sb.append(captionLayout.getText()); + } + info.setText(sb.toString()); + } } private class BlockAudioCell extends View implements DownloadController.FileDownloadProgressListener { @@ -6278,13 +6379,10 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg private int nameX; private int dateX; - private int textX = AndroidUtilities.dp(18 + 14); - private int textY = AndroidUtilities.dp(40 + 8 + 8); + private int textX; + private int textY; private int creditOffset; - private int captionX = AndroidUtilities.dp(18); - private int captionY; - private int lineHeight; private TLRPC.TL_pageBlockEmbedPost currentBlock; @@ -6319,31 +6417,55 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg int height; if (currentBlock != null) { - 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); - TLRPC.PhotoSize image = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, AndroidUtilities.dp(40), true); - avatarImageView.setImage(image, String.format(Locale.US, "%d_%d", 40, 40), avatarDrawable, 0, null, currentPage, 1); + if (currentBlock instanceof TL_pageBlockEmbedPostCaption) { + height = 0; + int textWidth = width - AndroidUtilities.dp(36 + 14); + captionLayout = createLayoutForText(this, null, currentBlock.caption.text, textWidth, currentBlock, parentAdapter); + if (captionLayout != null) { + creditOffset = AndroidUtilities.dp(4) + captionLayout.getHeight(); + height += creditOffset + AndroidUtilities.dp(4); } - } - nameLayout = createLayoutForText(this, currentBlock.author, null, width - AndroidUtilities.dp(36 + 14 + (avatarVisible ? 40 + 14 : 0)), 0, currentBlock, Layout.Alignment.ALIGN_NORMAL, 1, parentAdapter); - if (currentBlock.date != 0) { - dateLayout = createLayoutForText(this, LocaleController.getInstance().chatFullDate.format((long) currentBlock.date * 1000), null, width - AndroidUtilities.dp(36 + 14 + (avatarVisible ? 40 + 14 : 0)), currentBlock, parentAdapter); + creditLayout = createLayoutForText(this, null, currentBlock.caption.credit, textWidth, currentBlock, isRtl ? Layout.Alignment.ALIGN_RIGHT : Layout.Alignment.ALIGN_NORMAL, parentAdapter); + if (creditLayout != null) { + height += AndroidUtilities.dp(4) + creditLayout.getHeight(); + } + textX = AndroidUtilities.dp(18); + textY = AndroidUtilities.dp(4); } else { - dateLayout = null; - } + 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); + TLRPC.PhotoSize image = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, AndroidUtilities.dp(40), true); + avatarImageView.setImage(ImageLocation.getForPhoto(image, photo), "40_40", avatarDrawable, 0, null, currentPage, 1); + } + } + nameLayout = createLayoutForText(this, currentBlock.author, null, width - AndroidUtilities.dp(36 + 14 + (avatarVisible ? 40 + 14 : 0)), 0, currentBlock, Layout.Alignment.ALIGN_NORMAL, 1, parentAdapter); + if (currentBlock.date != 0) { + dateLayout = createLayoutForText(this, LocaleController.getInstance().chatFullDate.format((long) currentBlock.date * 1000), null, width - AndroidUtilities.dp(36 + 14 + (avatarVisible ? 40 + 14 : 0)), currentBlock, parentAdapter); + } else { + dateLayout = null; + } - height = AndroidUtilities.dp(40 + 8 + 8); - int textWidth = width - AndroidUtilities.dp(36 + 14); - captionLayout = createLayoutForText(this, null, currentBlock.caption.text, textWidth, currentBlock, parentAdapter); - if (captionLayout != null) { - creditOffset = AndroidUtilities.dp(4) + captionLayout.getHeight(); - height += creditOffset + AndroidUtilities.dp(4); - } - creditLayout = createLayoutForText(this, null, currentBlock.caption.credit, textWidth, currentBlock, isRtl ? Layout.Alignment.ALIGN_RIGHT : Layout.Alignment.ALIGN_NORMAL, parentAdapter); - if (creditLayout != null) { - height += AndroidUtilities.dp(4) + creditLayout.getHeight(); + height = AndroidUtilities.dp(40 + 8 + 8); + + if (currentBlock.blocks.isEmpty()) { + int textWidth = width - AndroidUtilities.dp(36 + 14); + captionLayout = createLayoutForText(this, null, currentBlock.caption.text, textWidth, currentBlock, parentAdapter); + if (captionLayout != null) { + creditOffset = AndroidUtilities.dp(4) + captionLayout.getHeight(); + height += creditOffset + AndroidUtilities.dp(4); + } + creditLayout = createLayoutForText(this, null, currentBlock.caption.credit, textWidth, currentBlock, isRtl ? Layout.Alignment.ALIGN_RIGHT : Layout.Alignment.ALIGN_NORMAL, parentAdapter); + if (creditLayout != null) { + height += AndroidUtilities.dp(4) + creditLayout.getHeight(); + } + textX = AndroidUtilities.dp(18 + 14); + textY = AndroidUtilities.dp(40 + 8 + 8); + } else { + captionLayout = null; + creditLayout = null; + } } lineHeight = height; } else { @@ -6355,24 +6477,26 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg @Override protected void onDraw(Canvas canvas) { - //canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), backgroundPaint); if (currentBlock == null) { return; } - if (avatarVisible) { - avatarImageView.draw(canvas); - } - if (nameLayout != null) { - canvas.save(); - canvas.translate(AndroidUtilities.dp(18 + 14 + (avatarVisible ? 40 + 14 : 0)), AndroidUtilities.dp(dateLayout != null ? 10 : 19)); - nameLayout.draw(canvas); - canvas.restore(); - } - if (dateLayout != null) { - canvas.save(); - canvas.translate(AndroidUtilities.dp(18 + 14 + (avatarVisible ? 40 + 14 : 0)), AndroidUtilities.dp(29)); - dateLayout.draw(canvas); - canvas.restore(); + if (!(currentBlock instanceof TL_pageBlockEmbedPostCaption)) { + if (avatarVisible) { + avatarImageView.draw(canvas); + } + if (nameLayout != null) { + canvas.save(); + canvas.translate(AndroidUtilities.dp(18 + 14 + (avatarVisible ? 40 + 14 : 0)), AndroidUtilities.dp(dateLayout != null ? 10 : 19)); + nameLayout.draw(canvas); + canvas.restore(); + } + if (dateLayout != null) { + canvas.save(); + canvas.translate(AndroidUtilities.dp(18 + 14 + (avatarVisible ? 40 + 14 : 0)), AndroidUtilities.dp(29)); + dateLayout.draw(canvas); + canvas.restore(); + } + canvas.drawRect(AndroidUtilities.dp(18), AndroidUtilities.dp(6), AndroidUtilities.dp(20), lineHeight - (currentBlock.level != 0 ? 0 : AndroidUtilities.dp(6)), quoteLinePaint); } if (captionLayout != null) { canvas.save(); @@ -6386,7 +6510,6 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg creditLayout.draw(canvas); canvas.restore(); } - canvas.drawRect(AndroidUtilities.dp(18), AndroidUtilities.dp(6), AndroidUtilities.dp(20), lineHeight - (currentBlock.level != 0 ? 0 : AndroidUtilities.dp(6)), quoteLinePaint); } } @@ -6461,6 +6584,15 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg canvas.drawRect(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(20), getMeasuredHeight() - (currentBlock.bottom ? AndroidUtilities.dp(6) : 0), quoteLinePaint); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + if (textLayout == null) + return; + info.setText(textLayout.getText()); + } } private class BlockEmbedCell extends FrameLayout { @@ -6469,16 +6601,14 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg @JavascriptInterface public void postEvent(final String eventName, final String eventData) { AndroidUtilities.runOnUIThread(() -> { - switch (eventName) { - case "resize_frame": - try { - JSONObject object = new JSONObject(eventData); - exactWebViewHeight = Utilities.parseInt(object.getString("height")); - requestLayout(); - } catch (Throwable ignore) { + if ("resize_frame".equals(eventName)) { + try { + JSONObject object = new JSONObject(eventData); + exactWebViewHeight = Utilities.parseInt(object.getString("height")); + requestLayout(); + } catch (Throwable ignore) { - } - break; + } } }); } @@ -7159,7 +7289,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } } - private float multiHeight(float array[], int start, int end) { + private float multiHeight(float[] array, int start, int end) { float sum = 0; for (int a = start; a < end; a++) { sum += array[a]; @@ -7336,7 +7466,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } } } else { - float croppedRatios[] = new float[posArray.size()]; + float[] croppedRatios = new float[posArray.size()]; for (int a = 0; a < count; a++) { if (averageAspectRatio > 1.1f) { croppedRatios[a] = Math.max(1.0f, posArray.get(a).aspectRatio); @@ -8150,6 +8280,15 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg canvas.restore(); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + if (textLayout == null) + return; + info.setText(textLayout.getText()); + } } private class BlockOrderedListItemCell extends ViewGroup { @@ -8343,6 +8482,15 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg canvas.restore(); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + if (textLayout == null) + return; + info.setText(textLayout.getText()); + } } private class BlockDetailsCell extends View implements Drawable.Callback { @@ -8590,7 +8738,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (image == thumb) { thumb = null; } - imageView.setImage(image, "64_64", thumb, "64_64_b", image.size, null, currentPage, 1); + imageView.setImage(ImageLocation.getForPhoto(image, photo), "64_64", ImageLocation.getForPhoto(thumb, photo), "64_64_b", image.size, null, currentPage, 1); } else { drawImage = false; } @@ -8729,6 +8877,15 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg canvas.restore(); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + if (textLayout == null) + return; + info.setText(textLayout.getText() + ", " + LocaleController.getString("AccDescrIVHeading", R.string.AccDescrIVHeading)); + } } private class BlockDividerCell extends View { @@ -8809,6 +8966,15 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg canvas.restore(); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + if (textLayout == null) + return; + info.setText(textLayout.getText() + ", " + LocaleController.getString("AccDescrIVHeading", R.string.AccDescrIVHeading)); + } } private class BlockPullquoteCell extends View { @@ -9156,7 +9322,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } else { filter = String.format(Locale.US, "%d_%d", photoWidth, photoHeight); } - imageView.setImage(currentPhotoObject, filter, thumb, "80_80_b", currentPhotoObject.size, null, currentPage, 1); + imageView.setImage(ImageLocation.getForPhoto(currentPhotoObject, photo), filter, ImageLocation.getForPhoto(thumb, photo), "80_80_b", currentPhotoObject.size, null, currentPage, 1); buttonX = (int) (imageView.getImageX() + (imageView.getImageWidth() - size) / 2.0f); buttonY = (int) (imageView.getImageY() + (imageView.getImageHeight() - size) / 2.0f); radialProgress.setProgressRect(buttonX, buttonY, buttonX + size, buttonY + size); @@ -9305,6 +9471,18 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg public int getObserverTag() { return TAG; } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + StringBuilder sb = new StringBuilder(LocaleController.getString("AttachPhoto", R.string.AttachPhoto)); + if(captionLayout != null){ + sb.append(", "); + sb.append(captionLayout.getText()); + } + info.setText(sb.toString()); + } } private class BlockMapCell extends FrameLayout { @@ -9408,7 +9586,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg currentMapProvider = MessagesController.getInstance(currentAccount).mapProvider; if (currentMapProvider == 2) { if (currentWebFile != null) { - imageView.setImage(currentWebFile, null, Theme.chat_locationDrawable[0], null, currentPage, 0); + imageView.setImage(ImageLocation.getForWebFile(currentWebFile), null, Theme.chat_locationDrawable[0], null, currentPage, 0); } } else if (currentUrl != null) { imageView.setImage(currentUrl, null, Theme.chat_locationDrawable[0], null, 0); @@ -9473,6 +9651,18 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg canvas.drawRect(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(20), getMeasuredHeight() - (currentBlock.bottom ? AndroidUtilities.dp(6) : 0), quoteLinePaint); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + StringBuilder sb = new StringBuilder(LocaleController.getString("Map", R.string.Map)); + if(captionLayout != null){ + sb.append(", "); + sb.append(captionLayout.getText()); + } + info.setText(sb.toString()); + } } private class BlockChannelCell extends FrameLayout { @@ -9686,7 +9876,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg CharSequence text; CharSequence author = getText(this, currentBlock.author, currentBlock.author, currentBlock, width); Spannable spannableAuthor; - MetricAffectingSpan spans[]; + MetricAffectingSpan[] spans; if (author instanceof Spannable) { spannableAuthor = (Spannable) author; spans = spannableAuthor.getSpans(0, author.length(), MetricAffectingSpan.class); @@ -9744,7 +9934,16 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg canvas.restore(); } } - } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + if (textLayout == null) + return; + info.setText(textLayout.getText()); + } + } private class BlockTitleCell extends View { @@ -9808,6 +10007,15 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg canvas.restore(); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + if (textLayout == null) + return; + info.setText(textLayout.getText() + ", " + LocaleController.getString("AccDescrIVTitle", R.string.AccDescrIVTitle)); + } } private class BlockKickerCell extends View { @@ -10098,12 +10306,21 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg canvas.restore(); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + if (textLayout == null) + return; + info.setText(textLayout.getText() + ", " + LocaleController.getString("AccDescrIVHeading", R.string.AccDescrIVHeading)); + } } //------------ photo viewer - private int coords[] = new int[2]; + private int[] coords = new int[2]; private boolean isPhotoVisible; @@ -10119,7 +10336,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg private PhotoBackgroundDrawable photoBackgroundDrawable = new PhotoBackgroundDrawable(0xff000000); private Paint blackPaint = new Paint(); - private RadialProgressView radialProgressViews[] = new RadialProgressView[3]; + private RadialProgressView[] radialProgressViews = new RadialProgressView[3]; private AnimatorSet currentActionBarAnimation; private TextView captionTextView; @@ -10156,7 +10373,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } }; - private float animationValues[][] = new float[2][10]; + private float[][] animationValues = new float[2][10]; private int photoAnimationInProgress; private long photoTransitionAnimationStartTime; @@ -10170,7 +10387,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg private ImageReceiver rightImage = new ImageReceiver(); private int currentIndex; private TLRPC.PageBlock currentMedia; - private String currentFileNames[] = new String[3]; + private String[] currentFileNames = new String[3]; private PlaceProviderObject currentPlaceObject; private ImageReceiver.BitmapHolder currentThumb; @@ -10712,7 +10929,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } private boolean isVideoBlock(TLRPC.PageBlock block) { - if (block != null && block instanceof TLRPC.TL_pageBlockVideo) { + if (block instanceof TLRPC.TL_pageBlockVideo) { TLRPC.Document document = getDocumentWithId(((TLRPC.TL_pageBlockVideo) block).video_id); if (document != null) { return MessageObject.isVideoDocument(document); @@ -10740,11 +10957,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg return "image/jpeg"; } - private TLRPC.PhotoSize getFileLocation(int index, int size[]) { - if (index < 0 || index >= imagesArr.size()) { - return null; - } - TLObject media = getMedia(index); + private TLRPC.PhotoSize getFileLocation(TLObject media, int[] size) { if (media instanceof TLRPC.Photo) { TLRPC.Photo photo = (TLRPC.Photo) media; TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, AndroidUtilities.getPhotoSize()); @@ -11067,11 +11280,11 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg private void setIndexToImage(ImageReceiver imageReceiver, int index) { imageReceiver.setOrientation(0, false); - int size[] = new int[1]; - TLRPC.PhotoSize fileLocation = getFileLocation(index, size); + int[] size = new int[1]; + TLObject media = getMedia(index); + TLRPC.PhotoSize fileLocation = getFileLocation(media, size); if (fileLocation != null) { - TLObject media = getMedia(index); if (media instanceof TLRPC.Photo) { TLRPC.Photo photo = (TLRPC.Photo) media; ImageReceiver.BitmapHolder placeHolder = null; @@ -11082,14 +11295,14 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg size[0] = -1; } TLRPC.PhotoSize thumbLocation = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, 80); - imageReceiver.setImage(fileLocation, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, thumbLocation, "b", size[0], null, currentPage, 1); + imageReceiver.setImage(ImageLocation.getForPhoto(fileLocation, photo), null, ImageLocation.getForPhoto(thumbLocation, photo), "b", placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, size[0], null, currentPage, 1); } else if (isMediaVideo(index)) { if (!(fileLocation.location instanceof TLRPC.TL_fileLocationUnavailable)) { ImageReceiver.BitmapHolder placeHolder = null; if (currentThumb != null && imageReceiver == centerImage) { placeHolder = currentThumb; } - imageReceiver.setImage(null, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, fileLocation, "b", 0, null, currentPage, 1); + imageReceiver.setImage(null, null, ImageLocation.getForDocument(fileLocation, (TLRPC.Document) media), "b", placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, 0, null, currentPage, 1); } else { imageReceiver.setImageBitmap(parentActivity.getResources().getDrawable(R.drawable.photoview_placeholder)); } @@ -11167,7 +11380,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg onPhotoShow(index, object); - final Rect drawRegion = object.imageReceiver.getDrawRegion(); + final RectF drawRegion = object.imageReceiver.getDrawRegion(); int orientation = object.imageReceiver.getOrientation(); int animatedOrientation = object.imageReceiver.getAnimatedOrientation(); if (animatedOrientation != 0) { @@ -11188,8 +11401,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg animatingImageView.setTranslationX(object.viewX + drawRegion.left * object.scale); animatingImageView.setTranslationY(object.viewY + drawRegion.top * object.scale); final ViewGroup.LayoutParams layoutParams = animatingImageView.getLayoutParams(); - layoutParams.width = (drawRegion.right - drawRegion.left); - layoutParams.height = (drawRegion.bottom - drawRegion.top); + layoutParams.width = (int) drawRegion.width(); + layoutParams.height = (int) drawRegion.height(); animatingImageView.setLayoutParams(layoutParams); float scaleX = (float) AndroidUtilities.displaySize.x / layoutParams.width; @@ -11206,17 +11419,17 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (object.imageReceiver.isAspectFit()) { clipHorizontal = 0; } else { - clipHorizontal = Math.abs(drawRegion.left - object.imageReceiver.getImageX()); + clipHorizontal = (int) Math.abs(drawRegion.left - object.imageReceiver.getImageX()); } - int clipVertical = Math.abs(drawRegion.top - object.imageReceiver.getImageY()); + int clipVertical = (int) Math.abs(drawRegion.top - object.imageReceiver.getImageY()); - int coords2[] = new int[2]; + int[] coords2 = new int[2]; object.parentView.getLocationInWindow(coords2); - int clipTop = coords2[1] - (object.viewY + drawRegion.top) + object.clipTopAddition; + int clipTop = (int) (coords2[1] - (object.viewY + drawRegion.top) + object.clipTopAddition); if (clipTop < 0) { clipTop = 0; } - int clipBottom = (object.viewY + drawRegion.top + layoutParams.height) - (coords2[1] + object.parentView.getHeight()) + object.clipBottomAddition; + int clipBottom = (int) ((object.viewY + drawRegion.top + layoutParams.height) - (coords2[1] + object.parentView.getHeight()) + object.clipBottomAddition); if (clipBottom < 0) { clipBottom = 0; } @@ -11337,7 +11550,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg AnimatorSet animatorSet = new AnimatorSet(); final ViewGroup.LayoutParams layoutParams = animatingImageView.getLayoutParams(); - Rect drawRegion = null; + RectF drawRegion = null; int orientation = centerImage.getOrientation(); int animatedOrientation = 0; if (object != null && object.imageReceiver != null) { @@ -11350,8 +11563,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (object != null) { animatingImageView.setNeedRadius(object.radius != 0); drawRegion = object.imageReceiver.getDrawRegion(); - layoutParams.width = drawRegion.right - drawRegion.left; - layoutParams.height = drawRegion.bottom - drawRegion.top; + layoutParams.width = (int) drawRegion.width(); + layoutParams.height = (int) drawRegion.height(); animatingImageView.setImageBitmap(object.thumb); } else { animatingImageView.setNeedRadius(false); @@ -11382,17 +11595,17 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (object.imageReceiver.isAspectFit()) { clipHorizontal = 0; } else { - clipHorizontal = Math.abs(drawRegion.left - object.imageReceiver.getImageX()); + clipHorizontal = (int) Math.abs(drawRegion.left - object.imageReceiver.getImageX()); } - int clipVertical = Math.abs(drawRegion.top - object.imageReceiver.getImageY()); + int clipVertical = (int) Math.abs(drawRegion.top - object.imageReceiver.getImageY()); - int coords2[] = new int[2]; + int[] coords2 = new int[2]; object.parentView.getLocationInWindow(coords2); - int clipTop = coords2[1] - (object.viewY + drawRegion.top) + object.clipTopAddition; + int clipTop = (int) (coords2[1] - (object.viewY + drawRegion.top) + object.clipTopAddition); if (clipTop < 0) { clipTop = 0; } - int clipBottom = (object.viewY + drawRegion.top + (drawRegion.bottom - drawRegion.top)) - (coords2[1] + object.parentView.getHeight()) + object.clipBottomAddition; + int clipBottom = (int) ((object.viewY + drawRegion.top + (drawRegion.bottom - drawRegion.top)) - (coords2[1] + object.parentView.getHeight()) + object.clipBottomAddition); if (clipBottom < 0) { clipBottom = 0; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java index 511fe2e4b..7f527195c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java @@ -26,8 +26,6 @@ import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; @@ -44,6 +42,9 @@ import org.telegram.ui.Components.RecyclerListView; import java.io.File; import java.util.ArrayList; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class AudioSelectActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListAdapter listViewAdapter; @@ -192,9 +193,7 @@ public class AudioSelectActivity extends BaseFragment implements NotificationCen }; final ArrayList newAudioEntries = new ArrayList<>(); - Cursor cursor = null; - try { - cursor = ApplicationLoader.applicationContext.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, MediaStore.Audio.Media.IS_MUSIC + " != 0", null, MediaStore.Audio.Media.TITLE); + try (Cursor cursor = ApplicationLoader.applicationContext.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, MediaStore.Audio.Media.IS_MUSIC + " != 0", null, MediaStore.Audio.Media.TITLE)) { int id = -2000000000; while (cursor.moveToNext()) { MediaController.AudioEntry audioEntry = new MediaController.AudioEntry(); @@ -248,10 +247,6 @@ public class AudioSelectActivity extends BaseFragment implements NotificationCen } } catch (Exception e) { FileLog.e(e); - } finally { - if (cursor != null) { - cursor.close(); - } } AndroidUtilities.runOnUIThread(() -> { audioEntries = newAudioEntries; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java index c5f49b5bc..0f5e2cff5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java @@ -17,8 +17,6 @@ import android.widget.FrameLayout; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.LocaleController; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; @@ -35,6 +33,9 @@ import org.telegram.ui.Components.EmptyTextProgressView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class BlockedUsersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, ContactsActivity.ContactsActivityDelegate { private RecyclerListView listView; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java index a28295ea5..d807abc20 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java @@ -34,8 +34,6 @@ import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.NativeByteBuffer; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; @@ -53,10 +51,15 @@ import org.telegram.ui.Components.RecyclerListView; import java.io.File; import java.util.ArrayList; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class CacheControlActivity extends BaseFragment { private ListAdapter listAdapter; private RecyclerListView listView; + @SuppressWarnings("FieldCanBeLocal") + private LinearLayoutManager layoutManager; private int databaseRow; private int databaseInfoRow; @@ -74,7 +77,7 @@ public class CacheControlActivity extends BaseFragment { private long photoSize = -1; private long videoSize = -1; private long totalSize = -1; - private boolean clear[] = new boolean[6]; + private boolean[] clear = new boolean[6]; private boolean calculating = true; private volatile boolean canceled = false; @@ -239,7 +242,7 @@ public class CacheControlActivity extends BaseFragment { listView = new RecyclerListView(context); listView.setVerticalScrollBarEnabled(false); - listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); + listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); listView.setAdapter(listAdapter); listView.setOnItemClickListener((view, position) -> { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CallLogActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CallLogActivity.java index 686dd5912..e15b4a9f2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CallLogActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CallLogActivity.java @@ -29,8 +29,6 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; @@ -52,6 +50,9 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class CallLogActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListAdapter listViewAdapter; @@ -87,7 +88,7 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter. if (id == NotificationCenter.didReceiveNewMessages && firstLoaded) { ArrayList arr = (ArrayList) args[1]; for (MessageObject msg : arr) { - if (msg.messageOwner.action != null && msg.messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall) { + if (msg.messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall) { int userID = msg.messageOwner.from_id == UserConfig.getInstance(currentAccount).getClientUserId() ? msg.messageOwner.to_id.user_id : msg.messageOwner.from_id; int callType = msg.messageOwner.from_id == UserConfig.getInstance(currentAccount).getClientUserId() ? TYPE_OUT : TYPE_IN; TLRPC.PhoneCallDiscardReason reason = msg.messageOwner.action.reason; @@ -209,41 +210,41 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter. frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); listView.setOnItemClickListener((view, position) -> { - if (position < 0 || position >= calls.size()) { - return; - } - CallLogRow row = calls.get(position); - Bundle args = new Bundle(); - args.putInt("user_id", row.user.id); - args.putInt("message_id", row.calls.get(0).id); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats); - presentFragment(new ChatActivity(args), true); - }); + if (position < 0 || position >= calls.size()) { + return; + } + CallLogRow row = calls.get(position); + Bundle args = new Bundle(); + args.putInt("user_id", row.user.id); + args.putInt("message_id", row.calls.get(0).id); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats); + presentFragment(new ChatActivity(args), true); + }); listView.setOnItemLongClickListener((view, position) -> { - if (position < 0 || position >= calls.size()) { - return false; - } - final CallLogRow row = calls.get(position); - ArrayList items = new ArrayList<>(); - items.add(LocaleController.getString("Delete", R.string.Delete)); - if (VoIPHelper.canRateCall((TLRPC.TL_messageActionPhoneCall) row.calls.get(0).action)) { - items.add(LocaleController.getString("CallMessageReportProblem", R.string.CallMessageReportProblem)); - } - new AlertDialog.Builder(getParentActivity()) - .setTitle(LocaleController.getString("Calls", R.string.Calls)) - .setItems(items.toArray(new String[items.size()]), (dialog, which) -> { -switch (which) { -case 0: -confirmAndDelete(row); -break; -case 1: -VoIPHelper.showRateAlert(getParentActivity(), (TLRPC.TL_messageActionPhoneCall) row.calls.get(0).action); -break; -} -}) - .show(); - return true; - }); + if (position < 0 || position >= calls.size()) { + return false; + } + final CallLogRow row = calls.get(position); + ArrayList items = new ArrayList<>(); + items.add(LocaleController.getString("Delete", R.string.Delete)); + if (VoIPHelper.canRateCall((TLRPC.TL_messageActionPhoneCall) row.calls.get(0).action)) { + items.add(LocaleController.getString("CallMessageReportProblem", R.string.CallMessageReportProblem)); + } + new AlertDialog.Builder(getParentActivity()) + .setTitle(LocaleController.getString("Calls", R.string.Calls)) + .setItems(items.toArray(new String[0]), (dialog, which) -> { + switch (which) { + case 0: + confirmAndDelete(row); + break; + case 1: + VoIPHelper.showRateAlert(getParentActivity(), (TLRPC.TL_messageActionPhoneCall) row.calls.get(0).action); + break; + } + }) + .show(); + return true; + }); listView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { @@ -303,7 +304,8 @@ break; } floatingButton.setBackgroundDrawable(drawable); floatingButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_actionIcon), PorterDuff.Mode.MULTIPLY)); - floatingButton.setImageResource(R.drawable.ic_call_white_24dp); + floatingButton.setImageResource(R.drawable.ic_call); + floatingButton.setContentDescription(LocaleController.getString("Call", R.string.Call)); if (Build.VERSION.SDK_INT >= 21) { StateListAnimator animator = new StateListAnimator(); animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(floatingButton, "translationZ", AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); @@ -319,14 +321,14 @@ break; } frameLayout.addView(floatingButton, LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 56 : 60, Build.VERSION.SDK_INT >= 21 ? 56 : 60, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.BOTTOM, LocaleController.isRTL ? 14 : 0, 0, LocaleController.isRTL ? 0 : 14, 14)); floatingButton.setOnClickListener(v -> { - Bundle args = new Bundle(); - args.putBoolean("destroyAfterSelect", true); - args.putBoolean("returnAsResult", true); - args.putBoolean("onlyUsers", true); - ContactsActivity contactsFragment = new ContactsActivity(args); - contactsFragment.setDelegate((user, param, activity) -> VoIPHelper.startCall(user, getParentActivity(), null)); - presentFragment(contactsFragment); - }); + Bundle args = new Bundle(); + args.putBoolean("destroyAfterSelect", true); + args.putBoolean("returnAsResult", true); + args.putBoolean("onlyUsers", true); + ContactsActivity contactsFragment = new ContactsActivity(args); + contactsFragment.setDelegate((user, param, activity) -> VoIPHelper.startCall(user, getParentActivity(), null)); + presentFragment(contactsFragment); + }); return fragmentView; } @@ -360,53 +362,53 @@ break; req.q = ""; req.offset_id = max_id; int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - if (error == null) { - SparseArray users = new SparseArray<>(); - TLRPC.messages_Messages msgs = (TLRPC.messages_Messages) response; - endReached = msgs.messages.isEmpty(); - for (int a = 0; a < msgs.users.size(); a++) { - TLRPC.User user = msgs.users.get(a); - users.put(user.id, user); - } - CallLogRow currentRow = calls.size() > 0 ? calls.get(calls.size() - 1) : null; - for (int a = 0; a < msgs.messages.size(); a++) { - TLRPC.Message msg = msgs.messages.get(a); - if (msg.action == null || msg.action instanceof TLRPC.TL_messageActionHistoryClear) { - continue; - } - int callType = msg.from_id == UserConfig.getInstance(currentAccount).getClientUserId() ? TYPE_OUT : TYPE_IN; - TLRPC.PhoneCallDiscardReason reason = msg.action.reason; - if (callType == TYPE_IN && (reason instanceof TLRPC.TL_phoneCallDiscardReasonMissed || reason instanceof TLRPC.TL_phoneCallDiscardReasonBusy)) { - callType = TYPE_MISSED; - } - int userID = msg.from_id == UserConfig.getInstance(currentAccount).getClientUserId() ? msg.to_id.user_id : msg.from_id; - if (currentRow == null || currentRow.user.id != userID || currentRow.type != callType) { - if (currentRow != null && !calls.contains(currentRow)) { - calls.add(currentRow); - } - CallLogRow row = new CallLogRow(); - row.calls = new ArrayList<>(); - row.user = users.get(userID); - row.type = callType; - currentRow = row; - } - currentRow.calls.add(msg); - } - if (currentRow != null && currentRow.calls.size() > 0 && !calls.contains(currentRow)) { - calls.add(currentRow); - } - } else { - endReached = true; - } - loading = false; - firstLoaded = true; - if (emptyView != null) { - emptyView.showTextView(); - } - if (listViewAdapter != null) { - listViewAdapter.notifyDataSetChanged(); - } - }), ConnectionsManager.RequestFlagFailOnServerErrors); + if (error == null) { + SparseArray users = new SparseArray<>(); + TLRPC.messages_Messages msgs = (TLRPC.messages_Messages) response; + endReached = msgs.messages.isEmpty(); + for (int a = 0; a < msgs.users.size(); a++) { + TLRPC.User user = msgs.users.get(a); + users.put(user.id, user); + } + CallLogRow currentRow = calls.size() > 0 ? calls.get(calls.size() - 1) : null; + for (int a = 0; a < msgs.messages.size(); a++) { + TLRPC.Message msg = msgs.messages.get(a); + if (msg.action == null || msg.action instanceof TLRPC.TL_messageActionHistoryClear) { + continue; + } + int callType = msg.from_id == UserConfig.getInstance(currentAccount).getClientUserId() ? TYPE_OUT : TYPE_IN; + TLRPC.PhoneCallDiscardReason reason = msg.action.reason; + if (callType == TYPE_IN && (reason instanceof TLRPC.TL_phoneCallDiscardReasonMissed || reason instanceof TLRPC.TL_phoneCallDiscardReasonBusy)) { + callType = TYPE_MISSED; + } + int userID = msg.from_id == UserConfig.getInstance(currentAccount).getClientUserId() ? msg.to_id.user_id : msg.from_id; + if (currentRow == null || currentRow.user.id != userID || currentRow.type != callType) { + if (currentRow != null && !calls.contains(currentRow)) { + calls.add(currentRow); + } + CallLogRow row = new CallLogRow(); + row.calls = new ArrayList<>(); + row.user = users.get(userID); + row.type = callType; + currentRow = row; + } + currentRow.calls.add(msg); + } + if (currentRow != null && currentRow.calls.size() > 0 && !calls.contains(currentRow)) { + calls.add(currentRow); + } + } else { + endReached = true; + } + loading = false; + firstLoaded = true; + if (emptyView != null) { + emptyView.showTextView(); + } + if (listViewAdapter != null) { + listViewAdapter.notifyDataSetChanged(); + } + }), ConnectionsManager.RequestFlagFailOnServerErrors); ConnectionsManager.getInstance(currentAccount).bindRequestToGuid(reqId, classGuid); } @@ -417,12 +419,12 @@ break; .setTitle(LocaleController.getString("AppName", R.string.AppName)) .setMessage(LocaleController.getString("ConfirmDeleteCallLog", R.string.ConfirmDeleteCallLog)) .setPositiveButton(LocaleController.getString("Delete", R.string.Delete), (dialog, which) -> { - ArrayList ids = new ArrayList<>(); - for (TLRPC.Message msg : row.calls) { - ids.add(msg.id); - } - MessagesController.getInstance(currentAccount).deleteMessages(ids, null, null, 0, false); - }) + ArrayList ids = new ArrayList<>(); + for (TLRPC.Message msg : row.calls) { + ids.add(msg.id); + } + MessagesController.getInstance(currentAccount).deleteMessages(ids, null, null, 0, false); + }) .setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null) .show() .setCanceledOnTouchOutside(true); @@ -439,9 +441,9 @@ break; @Override public void onRequestPermissionsResultFragment(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == 101) { - if(grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { VoIPHelper.startCall(lastCallUser, getParentActivity(), null); - }else{ + } else { VoIPHelper.permissionDenied(getParentActivity(), null); } } @@ -490,6 +492,7 @@ break; imageView.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_AUDIO_SELECTOR_COLOR, 0)); imageView.setScaleType(ImageView.ScaleType.CENTER); imageView.setOnClickListener(callBtnClickListener); + imageView.setContentDescription(LocaleController.getString("Call", R.string.Call)); frameLayout.addView(imageView, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 8, 0, 8, 0)); view = frameLayout; @@ -525,12 +528,15 @@ break; switch (row.type) { case TYPE_OUT: subtitle.setSpan(iconOut, ldir.length(), ldir.length() + 1, 0); + //cell.setContentDescription(LocaleController.getString("CallMessageOutgoing", R.string.CallMessageOutgoing)); break; case TYPE_IN: subtitle.setSpan(iconIn, ldir.length(), ldir.length() + 1, 0); + //cell.setContentDescription(LocaleController.getString("CallMessageIncoming", R.string.CallMessageIncoming)); break; case TYPE_MISSED: subtitle.setSpan(iconMissed, ldir.length(), ldir.length() + 1, 0); + //cell.setContentDescription(LocaleController.getString("CallMessageIncomingMissed", R.string.CallMessageIncomingMissed)); break; } cell.setData(row.user, null, null, subtitle, false, false); @@ -569,16 +575,16 @@ break; @Override public ThemeDescription[] getThemeDescriptions() { ThemeDescription.ThemeDescriptionDelegate cellDelegate = () -> { - if (listView != null) { - int count = listView.getChildCount(); - for (int a = 0; a < count; a++) { - View child = listView.getChildAt(a); - if (child instanceof ProfileSearchCell) { - ((ProfileSearchCell) child).update(0); - } - } - } - }; + if (listView != null) { + int count = listView.getChildCount(); + for (int a = 0; a < count; a++) { + View child = listView.getChildAt(a); + if (child instanceof ProfileSearchCell) { + ((ProfileSearchCell) child).update(0); + } + } + } + }; return new ThemeDescription[]{ new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{LocationCell.class, CustomCell.class}, null, null, null, Theme.key_windowBackgroundWhite), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CancelAccountDeletionActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CancelAccountDeletionActivity.java index 8ca4cc263..03b6ac14e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CancelAccountDeletionActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CancelAccountDeletionActivity.java @@ -28,6 +28,7 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; +import android.telephony.PhoneNumberUtils; import android.telephony.SmsManager; import android.telephony.TelephonyManager; import android.text.Editable; @@ -216,7 +217,7 @@ public class CancelAccountDeletionActivity extends BaseFragment { @Override protected void onDialogDismiss(Dialog dialog) { if (Build.VERSION.SDK_INT >= 23 && dialog == permissionsDialog && !permissionsItems.isEmpty()) { - getParentActivity().requestPermissions(permissionsItems.toArray(new String[permissionsItems.size()]), 6); + getParentActivity().requestPermissions(permissionsItems.toArray(new String[0]), 6); } if (dialog == errorDialog) { finishFragment(); @@ -409,7 +410,7 @@ public class CancelAccountDeletionActivity extends BaseFragment { try { @SuppressLint("HardwareIds") String number = tm.getLine1Number(); if (!TextUtils.isEmpty(number)) { - req.settings.current_number = phone.contains(number) || number.contains(phone); + req.settings.current_number = PhoneNumberUtils.compare(phone, number); if (!req.settings.current_number) { req.settings.allow_flashcall = false; } @@ -1199,6 +1200,6 @@ public class CancelAccountDeletionActivity extends BaseFragment { arrayList.add(new ThemeDescription(smsView4.blackImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); arrayList.add(new ThemeDescription(smsView4.blueImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chats_actionBackground)); - return arrayList.toArray(new ThemeDescription[arrayList.size()]); + return arrayList.toArray(new ThemeDescription[0]); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AccountSelectCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AccountSelectCell.java index 76dab61e4..6b72fbbc2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AccountSelectCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AccountSelectCell.java @@ -21,6 +21,7 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; @@ -82,14 +83,8 @@ public class AccountSelectCell extends FrameLayout { TLRPC.User user = UserConfig.getInstance(accountNumber).getCurrentUser(); avatarDrawable.setInfo(user); textView.setText(ContactsController.formatName(user.first_name, user.last_name)); - TLRPC.FileLocation avatar; - if (user.photo != null && user.photo.photo_small != null && user.photo.photo_small.volume_id != 0 && user.photo.photo_small.local_id != 0) { - avatar = user.photo.photo_small; - } else { - avatar = null; - } imageView.getImageReceiver().setCurrentAccount(account); - imageView.setImage(avatar, "50_50", avatarDrawable, user); + imageView.setImage(ImageLocation.getForUser(user,false), "50_50", avatarDrawable, user); checkImageView.setVisibility(check && account == UserConfig.selectedAccount ? VISIBLE : INVISIBLE); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AdminedChannelCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AdminedChannelCell.java index 941c4846d..833781d5d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AdminedChannelCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AdminedChannelCell.java @@ -19,6 +19,7 @@ import android.widget.FrameLayout; import android.widget.ImageView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; @@ -73,10 +74,6 @@ public class AdminedChannelCell extends FrameLayout { } public void setChannel(TLRPC.Chat channel, boolean last) { - TLRPC.FileLocation photo = null; - if (channel.photo != null) { - photo = channel.photo.photo_small; - } final String url = MessagesController.getInstance(currentAccount).linkPrefix + "/"; currentChannel = channel; avatarDrawable.setInfo(channel); @@ -84,7 +81,7 @@ public class AdminedChannelCell extends FrameLayout { SpannableStringBuilder stringBuilder = new SpannableStringBuilder(url + channel.username); stringBuilder.setSpan(new URLSpanNoUnderline(""), url.length(), stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); statusTextView.setText(stringBuilder); - avatarImageView.setImage(photo, "50_50", avatarDrawable, currentChannel); + avatarImageView.setImage(ImageLocation.getForChat(channel, false), "50_50", avatarDrawable, currentChannel); isLast = last; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ArchiveHintCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ArchiveHintCell.java new file mode 100644 index 000000000..58f8a5ef6 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ArchiveHintCell.java @@ -0,0 +1,135 @@ +package org.telegram.ui.Cells; + +import android.content.Context; +import android.database.DataSetObserver; +import android.os.Parcelable; +import android.view.Gravity; +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.FileLog; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.BottomPagesView; +import org.telegram.ui.Components.LayoutHelper; + +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +public class ArchiveHintCell extends FrameLayout { + + private BottomPagesView bottomPages; + private ViewPager viewPager; + + public ArchiveHintCell(Context context) { + super(context); + + viewPager = new ViewPager(context) { + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (getParent() != null) { + getParent().requestDisallowInterceptTouchEvent(true); + } + return super.onInterceptTouchEvent(ev); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + requestLayout(); + } + }; + AndroidUtilities.setViewPagerEdgeEffectColor(viewPager, Theme.getColor(Theme.key_actionBarDefaultArchived)); + viewPager.setAdapter(new Adapter()); + viewPager.setPageMargin(0); + viewPager.setOffscreenPageLimit(1); + addView(viewPager, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + bottomPages.setPageOffset(position, positionOffset); + } + + @Override + public void onPageSelected(int i) { + FileLog.d("test1"); + } + + @Override + public void onPageScrollStateChanged(int i) { + FileLog.d("test1"); + } + }); + + bottomPages = new BottomPagesView(context, viewPager, 3); + bottomPages.setColor(Theme.key_chats_unreadCounterMuted, Theme.key_chats_actionBackground); + addView(bottomPages, LayoutHelper.createFrame(33, 5, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0, 0, 19)); + } + + @Override + public void invalidate() { + super.invalidate(); + bottomPages.invalidate(); + } + + public ViewPager getViewPager() { + return viewPager; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(204), MeasureSpec.EXACTLY)); + } + + private class Adapter extends PagerAdapter { + @Override + public int getCount() { + return 3; + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { + ArchiveHintInnerCell innerCell = new ArchiveHintInnerCell(container.getContext(), position); + if (innerCell.getParent() != null) { + ViewGroup parent = (ViewGroup) innerCell.getParent(); + parent.removeView(innerCell); + } + container.addView(innerCell, 0); + return innerCell; + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + container.removeView((View) object); + } + + @Override + public void setPrimaryItem(ViewGroup container, int position, Object object) { + super.setPrimaryItem(container, position, object); + bottomPages.setCurrentPage(position); + } + + @Override + public boolean isViewFromObject(View view, Object object) { + return view.equals(object); + } + + @Override + public void restoreState(Parcelable arg0, ClassLoader arg1) { + } + + @Override + public Parcelable saveState() { + return null; + } + + @Override + public void unregisterDataSetObserver(DataSetObserver observer) { + if (observer != null) { + super.unregisterDataSetObserver(observer); + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ArchiveHintInnerCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ArchiveHintInnerCell.java new file mode 100644 index 000000000..9e013875e --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ArchiveHintInnerCell.java @@ -0,0 +1,75 @@ +package org.telegram.ui.Cells; + +import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.util.TypedValue; +import android.view.Gravity; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; + +@SuppressWarnings("FieldCanBeLocal") +public class ArchiveHintInnerCell extends FrameLayout { + + private ImageView imageView; + private ImageView imageView2; + private TextView headerTextView; + private TextView messageTextView; + + public ArchiveHintInnerCell(Context context, int num) { + super(context); + + imageView = new ImageView(context); + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_nameMessage_threeLines), PorterDuff.Mode.MULTIPLY)); + + headerTextView = new TextView(context); + headerTextView.setTextColor(Theme.getColor(Theme.key_chats_nameMessage_threeLines)); + headerTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + headerTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + headerTextView.setGravity(Gravity.CENTER); + addView(headerTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 52, 75, 52, 0)); + + messageTextView = new TextView(context); + messageTextView.setTextColor(Theme.getColor(Theme.key_chats_message)); + messageTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + messageTextView.setGravity(Gravity.CENTER); + addView(messageTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 52, 110, 52, 0)); + + switch (num) { + case 0: { + addView(imageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 20, 8, 0)); + + imageView2 = new ImageView(context); + imageView2.setImageResource(R.drawable.chats_archive_arrow); + imageView2.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_unreadCounter), PorterDuff.Mode.MULTIPLY)); + addView(imageView2, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 20, 8, 0)); + + headerTextView.setText(LocaleController.getString("ArchiveHintHeader1", R.string.ArchiveHintHeader1)); + messageTextView.setText(LocaleController.getString("ArchiveHintText1", R.string.ArchiveHintText1)); + imageView.setImageResource(R.drawable.chats_archive_box); + break; + } + case 1: + addView(imageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 18, 0, 0)); + + headerTextView.setText(LocaleController.getString("ArchiveHintHeader2", R.string.ArchiveHintHeader2)); + messageTextView.setText(LocaleController.getString("ArchiveHintText2", R.string.ArchiveHintText2)); + imageView.setImageResource(R.drawable.chats_archive_muted); + break; + case 2: + addView(imageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 18, 0, 0)); + + headerTextView.setText(LocaleController.getString("ArchiveHintHeader3", R.string.ArchiveHintHeader3)); + messageTextView.setText(LocaleController.getString("ArchiveHintText3", R.string.ArchiveHintText3)); + imageView.setImageResource(R.drawable.chats_archive_pin); + break; + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ArchivedStickerSetCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ArchivedStickerSetCell.java index 13654bd95..a67f8e818 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ArchivedStickerSetCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ArchivedStickerSetCell.java @@ -20,6 +20,7 @@ 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.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; @@ -98,12 +99,13 @@ public class ArchivedStickerSetCell extends FrameLayout { valueTextView.setText(LocaleController.formatPluralString("Stickers", set.set.count)); TLRPC.PhotoSize thumb = set.cover != null ? FileLoader.getClosestPhotoSizeWithSize(set.cover.thumbs, 90) : null; if (thumb != null && thumb.location != null) { - imageView.setImage(thumb, null, "webp", null, set); + imageView.setImage(ImageLocation.getForDocument(thumb, set.cover), null, "webp", null, set); + } else if (!set.covers.isEmpty()) { + TLRPC.Document document = set.covers.get(0); + thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); + imageView.setImage(ImageLocation.getForDocument(thumb, document), null, "webp", null, set); } else { - thumb = !set.covers.isEmpty() ? FileLoader.getClosestPhotoSizeWithSize(set.covers.get(0).thumbs, 90) : null; - if (thumb != null) { - imageView.setImage(thumb, null, "webp", null, set); - } + imageView.setImage(null, null, "webp", null, set); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioCell.java index 2388ba027..8ae8e07a8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioCell.java @@ -129,6 +129,7 @@ public class AudioCell extends FrameLayout { CombinedDrawable combinedDrawable = new CombinedDrawable(circle, drawable); combinedDrawable.setCustomSize(AndroidUtilities.dp(46), AndroidUtilities.dp(46)); playButton.setBackgroundDrawable(combinedDrawable); + playButton.setContentDescription(play ? LocaleController.getString("AccActionPause", R.string.AccActionPause) : LocaleController.getString("AccActionPlay", R.string.AccActionPlay)); } public ImageView getPlayButton() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioPlayerCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioPlayerCell.java index a08bd4370..b279be98a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioPlayerCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioPlayerCell.java @@ -17,6 +17,7 @@ import android.text.TextUtils; import android.view.MotionEvent; import android.view.SoundEffectConstants; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DownloadController; @@ -26,6 +27,7 @@ import org.telegram.messenger.ImageLoader; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.MessageObject; +import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; @@ -63,6 +65,7 @@ public class AudioPlayerCell extends View implements DownloadController.FileDown radialProgress = new RadialProgress2(this); radialProgress.setColors(Theme.key_chat_inLoader, Theme.key_chat_inLoaderSelected, Theme.key_chat_inMediaIcon, Theme.key_chat_inMediaIconSelected); TAG = DownloadController.getInstance(currentAccount).generateObserverTag(); + setFocusable(true); } @SuppressLint("DrawAllocation") @@ -104,13 +107,13 @@ public class AudioPlayerCell extends View implements DownloadController.FileDown TLRPC.Document document = messageObject.getDocument(); TLRPC.PhotoSize thumb = document != null ? FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90) : null; if (thumb instanceof TLRPC.TL_photoSize) { - radialProgress.setImageOverlay(thumb, messageObject); + radialProgress.setImageOverlay(thumb, document, messageObject); } else { String artworkUrl = messageObject.getArtworkUrl(true); if (!TextUtils.isEmpty(artworkUrl)) { radialProgress.setImageOverlay(artworkUrl); } else { - radialProgress.setImageOverlay(null, null); + radialProgress.setImageOverlay(null, null, null); } } requestLayout(); @@ -376,7 +379,7 @@ public class AudioPlayerCell extends View implements DownloadController.FileDown @Override public void onSuccessDownload(String fileName) { radialProgress.setProgress(1, true); - updateButtonState(false,true); + updateButtonState(false, true); } @Override @@ -402,4 +405,14 @@ public class AudioPlayerCell extends View implements DownloadController.FileDown public int getObserverTag() { return TAG; } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (currentMessageObject.isMusic()) { + info.setText(LocaleController.formatString("AccDescrMusicInfo", R.string.AccDescrMusicInfo, currentMessageObject.getMusicAuthor(), currentMessageObject.getMusicTitle())); + } else { // voice message + info.setText(titleLayout.getText() + ", " + descriptionLayout.getText()); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BaseCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BaseCell.java index 3dc6842f4..ce7e4dd53 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BaseCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BaseCell.java @@ -15,6 +15,8 @@ import android.view.MotionEvent; import android.view.ViewConfiguration; import android.view.ViewGroup; +import com.airbnb.lottie.LottieDrawable; + public abstract class BaseCell extends ViewGroup { private final class CheckForTap implements Runnable { @@ -50,6 +52,7 @@ public abstract class BaseCell extends ViewGroup { public BaseCell(Context context) { super(context); setWillNotDraw(false); + setFocusable(true); } public static void setDrawableBounds(Drawable drawable, int x, int y) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java index 18ece357f..e0a59a22b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java @@ -19,6 +19,7 @@ import android.text.style.ClickableSpan; import android.text.style.URLSpan; import android.view.MotionEvent; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.Emoji; @@ -71,7 +72,7 @@ public class BotHelpCell extends View { setVisibility(GONE); return; } - if (text != null && oldText != null && text.equals(oldText)) { + if (text != null && text.equals(oldText)) { return; } oldText = text; @@ -208,4 +209,10 @@ public class BotHelpCell extends View { } canvas.restore(); } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setText(textLayout.getText()); + } } 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 3c377780b..be5e3c21a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -18,8 +18,10 @@ import android.text.TextUtils; import android.text.style.URLSpan; import android.view.MotionEvent; import android.view.SoundEffectConstants; +import android.view.accessibility.AccessibilityNodeInfo; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; @@ -36,19 +38,19 @@ import org.telegram.ui.Components.AvatarDrawable; public class ChatActionCell extends BaseCell { public interface ChatActionCellDelegate { - default void didClickedImage(ChatActionCell cell) { + default void didClickImage(ChatActionCell cell) { } - default void didLongPressed(ChatActionCell cell) { + default void didLongPress(ChatActionCell cell, float x, float y) { } default void needOpenUserProfile(int uid) { } - default void didPressedBotButton(MessageObject messageObject, TLRPC.KeyboardButton button) { + default void didPressBotButton(MessageObject messageObject, TLRPC.KeyboardButton button) { } - default void didPressedReplyMessage(ChatActionCell cell, int id) { + default void didPressReplyMessage(ChatActionCell cell, int id) { } } @@ -57,13 +59,18 @@ public class ChatActionCell extends BaseCell { private ImageReceiver imageReceiver; private AvatarDrawable avatarDrawable; private StaticLayout textLayout; - private int textWidth = 0; - private int textHeight = 0; - private int textX = 0; - private int textY = 0; - private int textXLeft = 0; - private int previousWidth = 0; - private boolean imagePressed = false; + private int textWidth; + private int textHeight; + private int textX; + private int textY; + private int textXLeft; + private int previousWidth; + private boolean imagePressed; + + private float lastTouchX; + private float lastTouchY; + + private boolean wasLayout; private boolean hasReplyMessage; @@ -92,14 +99,17 @@ public class ChatActionCell extends BaseCell { if (customText != null && TextUtils.equals(newText, customText)) { return; } - previousWidth = 0; customDate = date; customText = newText; if (getMeasuredWidth() != 0) { createLayout(customText, getMeasuredWidth()); invalidate(); } - AndroidUtilities.runOnUIThread(this::requestLayout); + if (!wasLayout) { + AndroidUtilities.runOnUIThread(this::requestLayout); + } else { + buildLayout(); + } } public void setMessageObject(MessageObject messageObject) { @@ -125,11 +135,11 @@ public class ChatActionCell extends BaseCell { } avatarDrawable.setInfo(id, null, null, false); if (currentMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) { - imageReceiver.setImage(currentMessageObject.messageOwner.action.newUserPhoto.photo_small, "50_50", avatarDrawable, null, currentMessageObject, 0); + imageReceiver.setImage(null, null, avatarDrawable, null, currentMessageObject, 0); } else { TLRPC.PhotoSize photo = FileLoader.getClosestPhotoSizeWithSize(currentMessageObject.photoThumbs, AndroidUtilities.dp(64)); if (photo != null) { - imageReceiver.setImage(photo, "50_50", avatarDrawable, null, currentMessageObject, 0); + imageReceiver.setImage(ImageLocation.getForObject(photo, currentMessageObject.photoThumbsObject), "50_50", avatarDrawable, null, currentMessageObject, 0); } else { imageReceiver.setImageBitmap(avatarDrawable); } @@ -152,7 +162,7 @@ public class ChatActionCell extends BaseCell { @Override protected void onLongPress() { if (delegate != null) { - delegate.didLongPressed(this); + delegate.didLongPress(this, lastTouchX, lastTouchY); } } @@ -161,13 +171,19 @@ public class ChatActionCell extends BaseCell { } + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + wasLayout = false; + } + @Override public boolean onTouchEvent(MotionEvent event) { if (currentMessageObject == null) { return super.onTouchEvent(event); } - float x = event.getX(); - float y = event.getY(); + float x = lastTouchX = event.getX(); + float y = lastTouchY = event.getY(); boolean result = false; if (event.getAction() == MotionEvent.ACTION_DOWN) { @@ -188,7 +204,7 @@ public class ChatActionCell extends BaseCell { if (event.getAction() == MotionEvent.ACTION_UP) { imagePressed = false; if (delegate != null) { - delegate.didClickedImage(this); + delegate.didClickImage(this); playSoundEffect(SoundEffectConstants.CLICK); } } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { @@ -206,7 +222,7 @@ public class ChatActionCell extends BaseCell { y -= textY; x -= textXLeft; - final int line = textLayout.getLineForVertical((int)y); + final int line = textLayout.getLineForVertical((int) y); final int off = textLayout.getOffsetForHorizontal(line, x); final float left = textLayout.getLineLeft(line); if (left <= x && left + textLayout.getLineWidth(line) >= x && currentMessageObject.messageText instanceof Spannable) { @@ -222,7 +238,7 @@ public class ChatActionCell extends BaseCell { if (delegate != null) { String url = link[0].getURL(); if (url.startsWith("game")) { - delegate.didPressedReplyMessage(this, currentMessageObject.messageOwner.reply_to_msg_id); + delegate.didPressReplyMessage(this, currentMessageObject.messageOwner.reply_to_msg_id); /*TLRPC.KeyboardButton gameButton = null; MessageObject messageObject = currentMessageObject.replyMessageObject; if (messageObject != null && messageObject.messageOwner.reply_markup != null) { @@ -241,7 +257,7 @@ public class ChatActionCell extends BaseCell { } } if (gameButton != null) { - delegate.didPressedBotButton(messageObject, gameButton); + delegate.didPressBotButton(messageObject, gameButton); }*/ } else if (url.startsWith("http")) { Browser.openUrl(getContext(), url); @@ -285,12 +301,12 @@ public class ChatActionCell extends BaseCell { if (lineWidth > maxWidth) { lineWidth = maxWidth; } - textHeight = (int)Math.max(textHeight, Math.ceil(textLayout.getLineBottom(a))); + textHeight = (int) Math.max(textHeight, Math.ceil(textLayout.getLineBottom(a))); } catch (Exception e) { FileLog.e(e); return; } - textWidth = (int)Math.max(textWidth, Math.ceil(lineWidth)); + textWidth = (int) Math.max(textWidth, Math.ceil(lineWidth)); } } catch (Exception e) { FileLog.e(e); @@ -307,30 +323,35 @@ public class ChatActionCell extends BaseCell { return; } int width = Math.max(AndroidUtilities.dp(30), MeasureSpec.getSize(widthMeasureSpec)); - if (width != previousWidth) { - CharSequence text; - if (currentMessageObject != null) { - if (currentMessageObject.messageOwner != null && currentMessageObject.messageOwner.media != null && currentMessageObject.messageOwner.media.ttl_seconds != 0) { - if (currentMessageObject.messageOwner.media.photo instanceof TLRPC.TL_photoEmpty) { - text = LocaleController.getString("AttachPhotoExpired", R.string.AttachPhotoExpired); - } else if (currentMessageObject.messageOwner.media.document instanceof TLRPC.TL_documentEmpty) { - text = LocaleController.getString("AttachVideoExpired", R.string.AttachVideoExpired); - } else { - text = currentMessageObject.messageText; - } + if (previousWidth != width) { + wasLayout = true; + previousWidth = width; + buildLayout(); + } + setMeasuredDimension(width, textHeight + AndroidUtilities.dp(14 + (currentMessageObject != null && currentMessageObject.type == 11 ? 70 : 0))); + } + + private void buildLayout() { + CharSequence text; + if (currentMessageObject != null) { + if (currentMessageObject.messageOwner != null && currentMessageObject.messageOwner.media != null && currentMessageObject.messageOwner.media.ttl_seconds != 0) { + if (currentMessageObject.messageOwner.media.photo instanceof TLRPC.TL_photoEmpty) { + text = LocaleController.getString("AttachPhotoExpired", R.string.AttachPhotoExpired); + } else if (currentMessageObject.messageOwner.media.document instanceof TLRPC.TL_documentEmpty) { + text = LocaleController.getString("AttachVideoExpired", R.string.AttachVideoExpired); } else { text = currentMessageObject.messageText; } } else { - text = customText; - } - previousWidth = width; - createLayout(text, width); - if (currentMessageObject != null && currentMessageObject.type == 11) { - imageReceiver.setImageCoords((width - AndroidUtilities.dp(64)) / 2, textHeight + AndroidUtilities.dp(15), AndroidUtilities.dp(64), AndroidUtilities.dp(64)); + text = currentMessageObject.messageText; } + } else { + text = customText; + } + createLayout(text, previousWidth); + if (currentMessageObject != null && currentMessageObject.type == 11) { + imageReceiver.setImageCoords((previousWidth - AndroidUtilities.dp(64)) / 2, textHeight + AndroidUtilities.dp(15), AndroidUtilities.dp(64), AndroidUtilities.dp(64)); } - setMeasuredDimension(width, textHeight + AndroidUtilities.dp(14 + (currentMessageObject != null && currentMessageObject.type == 11 ? 70 : 0))); } public int getCustomDate() { @@ -566,4 +587,14 @@ public class ChatActionCell extends BaseCell { canvas.restore(); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (TextUtils.isEmpty(customText) && currentMessageObject == null) { + return; + } + info.setText(!TextUtils.isEmpty(customText) ? customText : currentMessageObject.messageText); + info.setEnabled(true); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatListCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatListCell.java new file mode 100644 index 000000000..ec62b2947 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatListCell.java @@ -0,0 +1,129 @@ +package org.telegram.ui.Cells; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; +import android.text.TextPaint; +import android.view.Gravity; +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.SharedConfig; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RadioButton; + +public class ChatListCell extends LinearLayout { + + private class ListView extends FrameLayout { + + private RadioButton button; + private boolean isThreeLines; + private RectF rect = new RectF(); + private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + + public ListView(Context context, boolean threeLines) { + super(context); + setWillNotDraw(false); + + isThreeLines = threeLines; + button = new RadioButton(context); + + 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.RIGHT | Gravity.TOP, 0, 26, 10, 0)); + button.setChecked(isThreeLines && SharedConfig.useThreeLinesLayout || !isThreeLines && !SharedConfig.useThreeLinesLayout, false); + } + + @Override + protected void onDraw(Canvas canvas) { + int color = Theme.getColor(Theme.key_switchTrack); + int r = Color.red(color); + int g = Color.green(color); + int b = Color.blue(color); + + button.setColor(Theme.getColor(Theme.key_radioBackground), Theme.getColor(Theme.key_radioBackgroundChecked)); + + rect.set(AndroidUtilities.dp(1), AndroidUtilities.dp(1), getMeasuredWidth() - AndroidUtilities.dp(1), AndroidUtilities.dp(73)); + Theme.chat_instantViewRectPaint.setColor(Color.argb((int) (43 * button.getProgress()), r, g, b)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Theme.chat_instantViewRectPaint); + + rect.set(0, 0, getMeasuredWidth(), AndroidUtilities.dp(74)); + Theme.dialogs_onlineCirclePaint.setColor(Color.argb((int) (31 * (1.0f - button.getProgress())), r, g, b)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Theme.dialogs_onlineCirclePaint); + + String text = isThreeLines ? LocaleController.getString("ChatListExpanded", R.string.ChatListExpanded) : LocaleController.getString("ChatListDefault", R.string.ChatListDefault); + int width = (int) Math.ceil(textPaint.measureText(text)); + + textPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + canvas.drawText(text, (getMeasuredWidth() - width) / 2, AndroidUtilities.dp(96), textPaint); + + for (int a = 0; a < 2; a++) { + int cy = AndroidUtilities.dp(a == 0 ? 21 : 53); + Theme.dialogs_onlineCirclePaint.setColor(Color.argb(a == 0 ? 204 : 90, r, g, b)); + canvas.drawCircle(AndroidUtilities.dp(22), cy, AndroidUtilities.dp(11), Theme.dialogs_onlineCirclePaint); + + for (int i = 0; i < (isThreeLines ? 3 : 2); i++) { + Theme.dialogs_onlineCirclePaint.setColor(Color.argb(i == 0 ? 204 : 90, r, g, b)); + if (isThreeLines) { + rect.set(AndroidUtilities.dp(41), cy - AndroidUtilities.dp(8.3f - i * 7), getMeasuredWidth() - AndroidUtilities.dp(i == 0 ? 72 : 48), cy - AndroidUtilities.dp(8.3f - 3 - i * 7)); + canvas.drawRoundRect(rect, AndroidUtilities.dpf2(1.5f), AndroidUtilities.dpf2(1.5f), Theme.dialogs_onlineCirclePaint); + } else { + rect.set(AndroidUtilities.dp(41), cy - AndroidUtilities.dp(7 - i * 10), getMeasuredWidth() - AndroidUtilities.dp(i == 0 ? 72 : 48), cy - AndroidUtilities.dp(7 - 4 - i * 10)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(2), AndroidUtilities.dp(2), Theme.dialogs_onlineCirclePaint); + } + } + } + } + } + + private ListView[] listView = new ListView[2]; + + public ChatListCell(Context context) { + super(context); + setOrientation(HORIZONTAL); + setPadding(AndroidUtilities.dp(21), AndroidUtilities.dp(10), AndroidUtilities.dp(21), 0); + + for (int a = 0; a < listView.length; a++) { + boolean isThreeLines = a == 1; + listView[a] = new ListView(context, isThreeLines); + addView(listView[a], LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0.5f, a == 1 ? 10 : 0, 0, 0, 0)); + listView[a].setOnClickListener(v -> { + for (int b = 0; b < 2; b++) { + listView[b].button.setChecked(listView[b] == v, true); + } + didSelectChatType(isThreeLines); + }); + } + } + + protected void didSelectChatType(boolean threeLines) { + + } + + @Override + public void invalidate() { + super.invalidate(); + for (int a = 0; a < listView.length; a++) { + listView[a].invalidate(); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(123), MeasureSpec.EXACTLY)); + } +} 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 da3b52ade..23ea03c32 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -15,6 +15,7 @@ import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Paint; +import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; @@ -26,6 +27,7 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.RippleDrawable; import android.net.Uri; import android.os.Build; +import android.os.Bundle; import android.os.SystemClock; import android.text.Layout; import android.text.Spannable; @@ -37,6 +39,7 @@ import android.text.TextUtils; import android.text.style.CharacterStyle; import android.text.style.ClickableSpan; import android.text.style.URLSpan; +import android.util.SparseArray; import android.util.StateSet; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; @@ -44,6 +47,11 @@ import android.view.SoundEffectConstants; import android.view.View; import android.view.ViewGroup; import android.view.ViewStructure; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityNodeProvider; +import android.view.animation.Interpolator; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AndroidUtilities; @@ -52,6 +60,7 @@ import org.telegram.messenger.ContactsController; import org.telegram.messenger.DownloadController; import org.telegram.messenger.Emoji; import org.telegram.messenger.ImageLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; @@ -68,11 +77,15 @@ import org.telegram.messenger.Utilities; import org.telegram.messenger.WebFile; import org.telegram.messenger.browser.Browser; import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LinkPath; import org.telegram.ui.Components.MediaActionDrawable; +import org.telegram.ui.Components.MessageBackgroundDrawable; +import org.telegram.ui.Components.CheckBoxBase; import org.telegram.ui.Components.RadialProgress2; import org.telegram.ui.Components.RoundVideoPlayingDrawable; import org.telegram.ui.Components.SeekBar; @@ -96,19 +109,22 @@ import java.util.Locale; public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate, ImageReceiver.ImageReceiverDelegate, DownloadController.FileDownloadProgressListener { public interface ChatMessageCellDelegate { - default void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user) { + default void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user, float touchX, float touchY) { + } + + default void didPressHiddenForward(ChatMessageCell cell) { } default void didPressViaBot(ChatMessageCell cell, String username) { } - default void didPressChannelAvatar(ChatMessageCell cell, TLRPC.Chat chat, int postId) { + default void didPressChannelAvatar(ChatMessageCell cell, TLRPC.Chat chat, int postId, float touchX, float touchY) { } default void didPressCancelSendButton(ChatMessageCell cell) { } - default void didLongPress(ChatMessageCell cell) { + default void didLongPress(ChatMessageCell cell, float x, float y) { } default void didPressReplyMessage(ChatMessageCell cell, int id) { @@ -120,13 +136,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate default void needOpenWebView(String url, String title, String description, String originalUrl, int w, int h) { } - default void didPressImage(ChatMessageCell cell) { + default void didPressImage(ChatMessageCell cell, float x, float y) { } default void didPressShare(ChatMessageCell cell) { } - default void didPressOther(ChatMessageCell cell) { + default void didPressOther(ChatMessageCell cell, float otherX, float otherY) { } default void didPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) { @@ -226,6 +242,18 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private AvatarDrawable contactAvatarDrawable; private boolean disallowLongPress; + private float lastTouchX; + private float lastTouchY; + + private boolean drawPhotoCheckBox; + private boolean drawSelectionBackground; + private CheckBoxBase photoCheckBox; + private CheckBoxBase checkBox; + private boolean checkBoxVisible; + private boolean checkBoxAnimationInProgress; + private float checkBoxAnimationProgress; + private long lastCheckBoxAnimationTime; + private int checkBoxTranslation; private boolean isSmallImage; private boolean drawImageButton; @@ -238,6 +266,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private int animatingNoSound; private float animatingNoSoundProgress; private int noSoundCenterX; + private int forwardNameCenterX; private long lastAnimationTime; private int documentAttachType; private TLRPC.Document documentAttach; @@ -277,7 +306,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private boolean instantButtonPressed; private Drawable selectorDrawable; private RectF instantButtonRect = new RectF(); - private int pressedState[] = new int[] {android.R.attr.state_enabled, android.R.attr.state_pressed}; + private int[] pressedState = new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}; private RoundVideoPlayingDrawable roundVideoPlayingDrawable; @@ -325,6 +354,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private boolean photoNotSet; private RectF deleteProgressRect = new RectF(); private RectF rect = new RectF(); + private TLObject photoParentObject; private TLRPC.PhotoSize currentPhotoObject; private TLRPC.PhotoSize currentPhotoObjectThumb; private String currentPhotoFilter; @@ -384,7 +414,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private ArrayList lastPollResults; private int lastPollResultsVoters; - private boolean autoPlayingVideo; + private boolean autoPlayingMedia; private ArrayList botButtons = new ArrayList<>(); private HashMap botButtonsByData = new HashMap<>(); @@ -403,6 +433,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private int TAG; private int currentAccount = UserConfig.selectedAccount; + private boolean invalidatesParent; + public boolean isChat; private boolean isPressed; private boolean forwardName; @@ -472,7 +504,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private boolean drawForwardedName; private int forwardNameX; private int forwardNameY; - private float forwardNameOffsetX[] = new float[2]; + private float[] forwardNameOffsetX = new float[2]; private StaticLayout timeLayout; private int timeWidth; @@ -494,6 +526,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private TLRPC.User currentForwardUser; private TLRPC.User currentViaBotUser; private TLRPC.Chat currentForwardChannel; + private String currentForwardName; private String currentForwardNameString; private ChatMessageCellDelegate delegate; @@ -520,6 +553,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } }; + private SparseArray accessibilityVirtualViewBounds = new SparseArray<>(); + private int currentFocusedVirtualView = -1; public ChatMessageCell(Context context) { super(context); @@ -986,7 +1021,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && drawImageButton) { if (buttonState == -1) { if (SharedConfig.autoplayGifs) { - delegate.didPressImage(this); + delegate.didPressImage(this, lastTouchX, lastTouchY); } else { buttonState = 2; currentMessageObject.gifState = 1; @@ -1005,7 +1040,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (webPage != null && !TextUtils.isEmpty(webPage.embed_url)) { delegate.needOpenWebView(webPage.embed_url, webPage.site_name, webPage.title, webPage.url, webPage.embed_width, webPage.embed_height); } else if (buttonState == -1 || buttonState == 3) { - delegate.didPressImage(this); + delegate.didPressImage(this, lastTouchX, lastTouchY); playSoundEffect(SoundEffectConstants.CLICK); } else if (webPage != null) { Browser.openUrl(getContext(), webPage.url); @@ -1149,7 +1184,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (otherPressed) { otherPressed = false; playSoundEffect(SoundEffectConstants.CLICK); - delegate.didPressOther(this); + delegate.didPressOther(this, otherX, otherY); invalidate(); result = true; } @@ -1214,9 +1249,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (currentMessageObject.type == 8 && buttonState == -1 && SharedConfig.autoplayGifs && photoImage.getAnimation() == null) { imagePressed = false; result = false; - } else if (currentMessageObject.type == 5 && buttonState != -1) { - imagePressed = false; - result = false; } } } else { @@ -1245,7 +1277,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (buttonState == -1 || buttonState == 2 || buttonState == 3 || drawVideoImageButton) { playSoundEffect(SoundEffectConstants.CLICK); didClickedImage(); - } else if (buttonState == 0 && documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT) { + } else if (buttonState == 0) { playSoundEffect(SoundEffectConstants.CLICK); didPressButton(true, false); } @@ -1383,6 +1415,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } disallowLongPress = false; + lastTouchX = event.getX(); + lastTouchX = event.getY(); boolean result = checkTextBlockMotionEvent(event); if (!result) { @@ -1420,6 +1454,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate pressedVoteButton = -1; linkPreviewPressed = false; otherPressed = false; + sharePressed = false; imagePressed = false; gamePreviewPressed = false; instantPressed = instantButtonPressed = false; @@ -1486,9 +1521,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate playSoundEffect(SoundEffectConstants.CLICK); if (delegate != null) { if (currentUser != null) { - delegate.didPressUserAvatar(this, currentUser); + if (currentUser.id == 0) { + delegate.didPressHiddenForward(this); + } else { + delegate.didPressUserAvatar(this, currentUser, lastTouchX, lastTouchY); + } } else if (currentChat != null) { - delegate.didPressChannelAvatar(this, currentChat, 0); + delegate.didPressChannelAvatar(this, currentChat, 0, lastTouchX, lastTouchY); } } } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { @@ -1504,9 +1543,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate playSoundEffect(SoundEffectConstants.CLICK); if (delegate != null) { if (currentForwardChannel != null) { - delegate.didPressChannelAvatar(this, currentForwardChannel, currentMessageObject.messageOwner.fwd_from.channel_post); + delegate.didPressChannelAvatar(this, currentForwardChannel, currentMessageObject.messageOwner.fwd_from.channel_post, lastTouchX, lastTouchY); } else if (currentForwardUser != null) { - delegate.didPressUserAvatar(this, currentForwardUser); + delegate.didPressUserAvatar(this, currentForwardUser, lastTouchX, lastTouchY); + } else if (currentForwardName != null) { + delegate.didPressHiddenForward(this); } } } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { @@ -1552,7 +1593,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { replyEnd = replyStartX + backgroundDrawableRight; } - if (!(x >= replyStartX && x <= replyEnd && y >= replyStartY && y <= replyStartY + AndroidUtilities.dp(35))){ + if (!(x >= replyStartX && x <= replyEnd && y >= replyStartY && y <= replyStartY + AndroidUtilities.dp(35))) { replyPressed = false; } } @@ -1624,10 +1665,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (MediaController.getInstance().isPlayingMessage(currentMessageObject)) { duration = Math.max(0, duration - currentMessageObject.audioProgressSec); - if (!currentMessageObject.mediaExists && !currentMessageObject.attachPathExists) { - currentMessageObject.mediaExists = true; - updateButtonState(true, true, false); - } } if (lastTime != duration) { lastTime = duration; @@ -1769,45 +1806,51 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private void didClickedImage() { if (currentMessageObject.type == 1 || currentMessageObject.type == 13) { if (buttonState == -1) { - delegate.didPressImage(this); + delegate.didPressImage(this, lastTouchX, lastTouchY); } else if (buttonState == 0) { didPressButton(true, false); } } else if (currentMessageObject.type == 12) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(currentMessageObject.messageOwner.media.user_id); - delegate.didPressUserAvatar(this, user); + delegate.didPressUserAvatar(this, user, lastTouchX, lastTouchY); } else if (currentMessageObject.type == 5) { - if (!MediaController.getInstance().isPlayingMessage(currentMessageObject) || MediaController.getInstance().isMessagePaused()) { - delegate.needPlayMessage(currentMessageObject); + if (buttonState != -1) { + didPressButton(true, false); } else { - MediaController.getInstance().pauseMessage(currentMessageObject); + if (!MediaController.getInstance().isPlayingMessage(currentMessageObject) || MediaController.getInstance().isMessagePaused()) { + delegate.needPlayMessage(currentMessageObject); + } else { + MediaController.getInstance().pauseMessage(currentMessageObject); + } } } else if (currentMessageObject.type == 8) { - if (buttonState == -1) { - if (SharedConfig.autoplayGifs) { - delegate.didPressImage(this); - } else { + if (buttonState == -1 || buttonState == 1 && canStreamVideo && autoPlayingMedia) { + //if (SharedConfig.autoplayGifs) { + delegate.didPressImage(this, lastTouchX, lastTouchY); + /*} else { buttonState = 2; currentMessageObject.gifState = 1; photoImage.setAllowStartAnimation(false); photoImage.stopAnimation(); radialProgress.setIcon(getIconForCurrentState(), false, true); invalidate(); - } + }*/ } else if (buttonState == 2 || buttonState == 0) { didPressButton(true, false); } } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) { - if (buttonState == -1 || drawVideoImageButton) { - delegate.didPressImage(this); + if (buttonState == -1 || drawVideoImageButton && (autoPlayingMedia || SharedConfig.streamMedia && canStreamVideo)) { + delegate.didPressImage(this, lastTouchX, lastTouchY); + } else if (drawVideoImageButton) { + didPressButton(true, true); } else if (buttonState == 0 || buttonState == 3) { didPressButton(true, false); } } else if (currentMessageObject.type == 4) { - delegate.didPressImage(this); + delegate.didPressImage(this, lastTouchX, lastTouchY); } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT) { if (buttonState == -1) { - delegate.didPressImage(this); + delegate.didPressImage(this, lastTouchX, lastTouchY); } } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF) { if (buttonState == -1) { @@ -1822,7 +1865,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else if (hasInvoicePreview) { if (buttonState == -1) { - delegate.didPressImage(this); + delegate.didPressImage(this, lastTouchX, lastTouchY); } } } @@ -1901,7 +1944,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate TLRPC.FileLocation newPhoto = null; if (isAvatarVisible) { - if (currentUser != null && currentUser.photo != null){ + if (currentUser != null && currentUser.photo != null) { newPhoto = currentUser.photo.photo_small; } else if (currentChat != null && currentChat.photo != null) { newPhoto = currentChat.photo.photo_small; @@ -1957,9 +2000,22 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return noSoundCenterX; } + public int getForwardNameCenterX() { + if (currentUser != null && currentUser.id == 0) { + return (int) avatarImage.getCenterX(); + } + return forwardNameX + forwardNameCenterX; + } + @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); + if (checkBox != null) { + checkBox.onDetachedFromWindow(); + } + if (photoCheckBox != null) { + photoCheckBox.onDetachedFromWindow(); + } attachedToWindow = false; radialProgress.onDetachedFromWindow(); videoRadialProgress.onDetachedFromWindow(); @@ -1983,6 +2039,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate messageObjectToSet = null; groupedMessagesToSet = null; } + if (checkBox != null) { + checkBox.onAttachedToWindow(); + } + if (photoCheckBox != null) { + photoCheckBox.onAttachedToWindow(); + } attachedToWindow = true; setTranslationX(0); @@ -2002,14 +2064,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessageObject != null && (currentMessageObject.isRoundVideo() || currentMessageObject.isVideo())) { checkVideoPlayback(true); } - if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO && autoPlayingVideo) { + if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO && autoPlayingMedia) { animatingNoSoundPlaying = MediaController.getInstance().isPlayingMessage(currentMessageObject); - animatingNoSound = 0; animatingNoSoundProgress = animatingNoSoundPlaying ? 0.0f : 1.0f; + animatingNoSound = 0; } else { animatingNoSoundPlaying = false; animatingNoSoundProgress = 0; - animatingDrawVideoImageButtonProgress = documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO && drawVideoSize ? 1.0f : 0.0f; + animatingDrawVideoImageButtonProgress = (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF) && drawVideoSize ? 1.0f : 0.0f; } } @@ -2017,6 +2079,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (messageObject.checkLayout() || currentPosition != null && lastHeight != AndroidUtilities.displaySize.y) { currentMessageObject = null; } + lastHeight = AndroidUtilities.displaySize.y; boolean messageIdChanged = currentMessageObject == null || currentMessageObject.getId() != messageObject.getId(); boolean messageChanged = currentMessageObject != messageObject || messageObject.forceUpdate; boolean dataChanged = currentMessageObject != null && currentMessageObject.getId() == messageObject.getId() && lastSendState == MessageObject.MESSAGE_SEND_STATE_EDITING && messageObject.isSent() @@ -2083,6 +2146,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate lastViewsCount = messageObject.messageOwner.views; isPressed = false; gamePreviewPressed = false; + sharePressed = false; isCheckPressed = true; hasNewLineForTime = false; isAvatarVisible = isChat && !messageObject.isOutOwner() && messageObject.needDrawAvatar() && (currentPosition == null || currentPosition.edge); @@ -2099,7 +2163,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate checkOnlyButtonPressed = false; replyTextLayout = null; hasEmbed = false; - autoPlayingVideo = false; + autoPlayingMedia = false; replyNameWidth = 0; replyTextWidth = 0; viaWidth = 0; @@ -2119,6 +2183,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate resetPressedLink(-1); messageObject.forceUpdate = false; drawPhotoImage = false; + drawPhotoCheckBox = false; hasLinkPreview = false; hasOldCaptionPreview = false; hasGamePreview = false; @@ -2150,6 +2215,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate drawImageButton = false; drawVideoImageButton = false; currentPhotoObject = null; + photoParentObject = null; currentPhotoObjectThumb = null; currentPhotoFilter = null; infoLayout = null; @@ -2170,6 +2236,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate drawInstantView = false; drawInstantViewType = 0; drawForwardedName = false; + photoImage.setSideClip(0); imageBackgroundColor = 0; imageBackgroundSideColor = 0; mediaBackground = false; @@ -2227,7 +2294,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate hasInvoicePreview = messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaInvoice; hasLinkPreview = messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageObject.messageOwner.media.webpage instanceof TLRPC.TL_webPage; drawInstantView = hasLinkPreview && messageObject.messageOwner.media.webpage.cached_page != null; - hasEmbed = hasLinkPreview && !TextUtils.isEmpty(messageObject.messageOwner.media.webpage.embed_url); + hasEmbed = hasLinkPreview && !TextUtils.isEmpty(messageObject.messageOwner.media.webpage.embed_url) && !messageObject.isGif(); boolean slideshow = false; String siteName = hasLinkPreview ? messageObject.messageOwner.media.webpage.site_name : null; String webpageType = hasLinkPreview ? messageObject.messageOwner.media.webpage.type : null; @@ -2248,8 +2315,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Uri url = Uri.parse(messageObject.messageOwner.media.webpage.url); int intensity = Utilities.parseInt(url.getQueryParameter("intensity")); String bgColor = url.getQueryParameter("bg_color"); + if (TextUtils.isEmpty(bgColor)) { + TLRPC.Document document = messageObject.getDocument(); + if (document != null && "image/png".equals(document.mime_type)) { + bgColor = "ffffff"; + } + if (intensity == 0) { + intensity = 50; + } + } if (bgColor != null) { - imageBackgroundColor = Integer.parseInt(url.getQueryParameter("bg_color"), 16) | 0xff000000; + imageBackgroundColor = Integer.parseInt(bgColor, 16) | 0xff000000; imageBackgroundSideColor = AndroidUtilities.getPatternSideColor(imageBackgroundColor); photoImage.setColorFilter(new PorterDuffColorFilter(AndroidUtilities.getPatternColor(imageBackgroundColor), PorterDuff.Mode.SRC_IN)); photoImage.setAlpha(intensity / 100.0f); @@ -2367,8 +2443,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (site_name != null && photo != null && site_name.toLowerCase().equals("instagram")) { linkPreviewMaxWidth = Math.max(AndroidUtilities.displaySize.y / 3, currentMessageObject.textWidth); } - smallImage = !slideshow && !drawInstantView && document == null && type != null && (type.equals("app") || type.equals("profile") || type.equals("article")); - isSmallImage = !slideshow && !drawInstantView && document == null && description != null && type != null && (type.equals("app") || type.equals("profile") || type.equals("article")) && currentMessageObject.photoThumbs != null; + boolean isSmallImageType = "app".equals(type) || "profile".equals(type) || "article".equals(type); + smallImage = !slideshow && !drawInstantView && document == null && isSmallImageType; + isSmallImage = !slideshow && !drawInstantView && document == null && description != null && type != null && isSmallImageType && currentMessageObject.photoThumbs != null; } else if (hasInvoicePreview) { TLRPC.TL_messageMediaInvoice invoice = (TLRPC.TL_messageMediaInvoice) messageObject.messageOwner.media; site_name = messageObject.messageOwner.media.title; @@ -2590,14 +2667,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (document != null) { if (MessageObject.isRoundVideoDocument(document)) { currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); + photoParentObject = document; documentAttach = document; documentAttachType = DOCUMENT_ATTACH_TYPE_ROUND; } else if (MessageObject.isGifDocument(document)) { - if (!SharedConfig.autoplayGifs) { + if (!messageObject.isGame() && !SharedConfig.autoplayGifs) { messageObject.gifState = 1; } photoImage.setAllowStartAnimation(messageObject.gifState != 1); currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); + 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); @@ -2617,10 +2696,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (photo != null) { currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, AndroidUtilities.getPhotoSize(), true); currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, 40); + photoParentObject = photo; } if (currentPhotoObject == null) { currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 320); currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 40); + photoParentObject = document; } if (currentPhotoObject == currentPhotoObjectThumb) { currentPhotoObjectThumb = null; @@ -2652,6 +2733,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate createDocumentLayout(0, messageObject); } else if (MessageObject.isStickerDocument(document)) { currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); + 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); @@ -2669,6 +2751,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate documentAttachType = DOCUMENT_ATTACH_TYPE_STICKER; } else if (drawInstantViewType == 6) { currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 320); + 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); @@ -2744,6 +2827,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (photo != null) { boolean isPhoto = type != null && type.equals("photo"); currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, isPhoto || !smallImage ? AndroidUtilities.getPhotoSize() : maxPhotoWidth, !isPhoto); + photoParentObject = messageObject.photoThumbsObject; checkOnlyButtonPressed = !isPhoto; currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 40); if (currentPhotoObjectThumb == currentPhotoObject) { @@ -2823,6 +2907,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate width /= scale; height /= scale; } + if (height < AndroidUtilities.dp(60)) { + height = AndroidUtilities.dp(60); + } } } if (isSmallImage) { @@ -2846,16 +2933,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentPhotoFilterThumb = String.format(Locale.US, "%d_%d_b", width, height); if (webDocument != null) { - photoImage.setImage(webDocument, currentPhotoFilter, null, null, "b1", webDocument.size, null, messageObject, 1); + photoImage.setImage(ImageLocation.getForWebFile(webDocument), currentPhotoFilter, null, null, webDocument.size, null, messageObject, 1); } else { if (documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER) { if (messageObject.mediaExists) { - photoImage.setImage(documentAttach, currentPhotoFilter, null, currentPhotoObject, "b1", 0, "jpg", messageObject, 1); + photoImage.setImage(ImageLocation.getForDocument(documentAttach), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObject, document), "b1", 0, "jpg", messageObject, 1); } else { - photoImage.setImage(null, currentPhotoFilter, null, currentPhotoObject, "b1", 0, "jpg", messageObject, 1); + photoImage.setImage(null, null, ImageLocation.getForDocument(currentPhotoObject, document), "b1", 0, "jpg", messageObject, 1); } } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER) { - photoImage.setImage(documentAttach, currentPhotoFilter, null, currentPhotoObject, "b1", documentAttach.size, "webp", messageObject, 1); + photoImage.setImage(ImageLocation.getForDocument(documentAttach), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObject, documentAttach), "b1", documentAttach.size, "webp", messageObject, 1); } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) { photoImage.setNeedsQualityThumb(true); photoImage.setShouldGenerateQualityThumb(true); @@ -2866,41 +2953,41 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoImage.setAllowDecodeSingleFrame(true); photoImage.setAllowStartAnimation(true); photoImage.startAnimation(); - photoImage.setImage(documentAttach, ImageLoader.VIDEO_FILTER, currentPhotoObject, currentPhotoFilter, null, currentPhotoObjectThumb, currentPhotoFilterThumb, documentAttach.size, null, messageObject, 0); - autoPlayingVideo = true; + photoImage.setImage(ImageLocation.getForDocument(documentAttach), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForDocument(currentPhotoObject, documentAttach), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, documentAttach), currentPhotoFilterThumb, null, documentAttach.size, null, messageObject, 0); + autoPlayingMedia = true; } else { if (currentPhotoObjectThumb != null) { - photoImage.setImage(currentPhotoObject, currentPhotoFilter, currentPhotoObjectThumb, currentPhotoFilterThumb, 0, null, messageObject, 0); + photoImage.setImage(ImageLocation.getForDocument(currentPhotoObject, documentAttach), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, documentAttach), currentPhotoFilterThumb, 0, null, messageObject, 0); } else { - photoImage.setImage(null, null, currentPhotoObject, currentPhotoObject instanceof TLRPC.TL_photoStrippedSize || "s".equals(currentPhotoObject.type) ? currentPhotoFilterThumb : currentPhotoFilter, 0, null, messageObject, 0); + photoImage.setImage(null, null, ImageLocation.getForDocument(currentPhotoObject, documentAttach), currentPhotoObject instanceof TLRPC.TL_photoStrippedSize || "s".equals(currentPhotoObject.type) ? currentPhotoFilterThumb : currentPhotoFilter, 0, null, messageObject, 0); } } } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF || documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND) { + photoImage.setAllowDecodeSingleFrame(true); String fileName = FileLoader.getAttachFileName(document); boolean autoDownload = false; if (MessageObject.isRoundVideoDocument(document)) { photoImage.setRoundRadius(AndroidUtilities.roundMessageSize / 2); autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject); - } else if (MessageObject.isNewGifDocument(document)) { + } else if (MessageObject.isGifDocument(document)) { autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject); } - if (!messageObject.isSending() && !messageObject.isEditing() && (messageObject.mediaExists || FileLoader.getInstance(currentAccount).isLoadingFile(fileName) || autoDownload)) { - photoNotSet = false; - photoImage.setImage(document, null, currentPhotoObject, currentPhotoFilterThumb, document.size, null, currentMessageObject, 0); + if (messageObject.mediaExists || autoDownload) { + autoPlayingMedia = true; + photoImage.setImage(ImageLocation.getForDocument(document), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForDocument(currentPhotoObject, documentAttach), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, documentAttach), currentPhotoFilterThumb, null, document.size, null, messageObject, 0); } else { - photoNotSet = true; - photoImage.setImage(null, null, currentPhotoObject, currentPhotoFilterThumb, 0, null, currentMessageObject, 0); + photoImage.setImage(null, null, ImageLocation.getForDocument(currentPhotoObject, documentAttach), currentPhotoFilterThumb, 0, null, currentMessageObject, 0); } } else { boolean photoExist = messageObject.mediaExists; String fileName = FileLoader.getAttachFileName(currentPhotoObject); if (hasGamePreview || photoExist || DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject) || FileLoader.getInstance(currentAccount).isLoadingFile(fileName)) { photoNotSet = false; - photoImage.setImage(currentPhotoObject, currentPhotoFilter, currentPhotoObjectThumb, currentPhotoFilterThumb, 0, null, messageObject, 0); + photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, 0); } else { photoNotSet = true; if (currentPhotoObjectThumb != null) { - photoImage.setImage(null, null, currentPhotoObjectThumb, String.format(Locale.US, "%d_%d_b", width, height), 0, null, messageObject, 0); + photoImage.setImage(null, null, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), String.format(Locale.US, "%d_%d_b", width, height), 0, null, messageObject, 0); } else { photoImage.setImageBitmap((Drawable) null); } @@ -3030,15 +3117,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (maxWidth < 0) { maxWidth = AndroidUtilities.dp(10); } - - TLRPC.FileLocation currentPhoto = null; if (user != null) { - if (user.photo != null) { - currentPhoto = user.photo.photo_small; - } contactAvatarDrawable.setInfo(user); } - photoImage.setImage(currentPhoto, "50_50", user != null ? contactAvatarDrawable : Theme.chat_contactDrawable[messageObject.isOutOwner() ? 1 : 0], null, messageObject, 0); + photoImage.setImage(ImageLocation.getForUser(user, false), "50_50", user != null ? contactAvatarDrawable : Theme.chat_contactDrawable[messageObject.isOutOwner() ? 1 : 0], null, messageObject, 0); CharSequence phone; if (!TextUtils.isEmpty(messageObject.vCardData)) { @@ -3279,11 +3361,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate messageObject.gifState = 1; } + photoImage.setAllowDecodeSingleFrame(true); if (messageObject.isVideo()) { - photoImage.setAllowDecodeSingleFrame(true); photoImage.setAllowStartAnimation(true); } else if (messageObject.isRoundVideo()) { - photoImage.setAllowDecodeSingleFrame(true); MessageObject playingMessage = MediaController.getInstance().getPlayingMessageObject(); photoImage.setAllowStartAnimation(playingMessage == null || !playingMessage.isRoundVideo()); } else { @@ -3302,12 +3383,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } int maxTextWidth = 0; int maxWidth = backgroundWidth - AndroidUtilities.dp(86 + 52); + int widthForCaption = 0; createDocumentLayout(maxWidth, messageObject); if (!TextUtils.isEmpty(messageObject.caption)) { try { currentCaption = messageObject.caption; int width = backgroundWidth - AndroidUtilities.dp(31); - int widthForCaption = width - AndroidUtilities.dp(10); + widthForCaption = width - AndroidUtilities.dp(10); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { captionLayout = StaticLayout.Builder.obtain(messageObject.caption, 0, messageObject.caption.length(), Theme.chat_msgTextPaint, widthForCaption) .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY) @@ -3334,7 +3416,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (captionLayout != null) { for (int a = 0, N = captionLayout.getLineCount(); a < N; a++) { - int w = (int) Math.ceil(captionLayout.getLineWidth(a) + captionLayout.getLineLeft(a)) + AndroidUtilities.dp(31); + int w = (int) Math.ceil(Math.min(widthForCaption, captionLayout.getLineWidth(a) + captionLayout.getLineLeft(a))) + AndroidUtilities.dp(31); if (w > maxTextWidth) { maxTextWidth = w; } @@ -3360,8 +3442,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int lineCount = infoLayout.getLineCount(); measureTime(messageObject); int timeLeft = backgroundWidth - AndroidUtilities.dp(40 + 18 + 56 + 8) - (int) Math.ceil(infoLayout.getLineWidth(0)); - if (timeLeft < timeWidth && lineCount > 1) { - photoHeight += AndroidUtilities.dp(8); + if (timeLeft < timeWidth) { + photoHeight += AndroidUtilities.dp(12); } else if (lineCount == 1) { photoHeight += AndroidUtilities.dp(4); } @@ -3406,24 +3488,19 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } docTitleLayout = new StaticLayout(TextUtils.ellipsize(LocaleController.getString("AttachLiveLocation", R.string.AttachLiveLocation), Theme.chat_locationTitlePaint, maxWidth, TextUtils.TruncateAt.END), Theme.chat_locationTitlePaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - TLRPC.FileLocation currentPhoto = null; updateCurrentUserAndChat(); - Object parentObject = null; if (currentUser != null) { - if (currentUser.photo != null) { - currentPhoto = currentUser.photo.photo_small; - } contactAvatarDrawable.setInfo(currentUser); - parentObject = currentUser; + locationImageReceiver.setImage(ImageLocation.getForUser(currentUser, false), "50_50", contactAvatarDrawable, null, currentUser, 0); } else if (currentChat != null) { if (currentChat.photo != null) { currentPhoto = currentChat.photo.photo_small; } contactAvatarDrawable.setInfo(currentChat); - parentObject = currentChat; + locationImageReceiver.setImage(ImageLocation.getForChat(currentChat, false), "50_50", contactAvatarDrawable, null, currentChat, 0); + } else { + locationImageReceiver.setImage(null, null, contactAvatarDrawable, null, null, 0); } - locationImageReceiver.setImage(currentPhoto, "50_50", contactAvatarDrawable, null, parentObject, 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); } else if (!TextUtils.isEmpty(messageObject.messageOwner.media.title)) { if (AndroidUtilities.isTablet()) { @@ -3491,7 +3568,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoImage.setImage(null, null, Theme.chat_locationDrawable[messageObject.isOutOwner() ? 1 : 0], null, messageObject, 0); } else if (currentMapProvider == 2) { if (currentWebFile != null) { - photoImage.setImage(currentWebFile, null, Theme.chat_locationDrawable[messageObject.isOutOwner() ? 1 : 0], null, messageObject, 0); + photoImage.setImage(ImageLocation.getForWebFile(currentWebFile), null, Theme.chat_locationDrawable[messageObject.isOutOwner() ? 1 : 0], null, messageObject, 0); } } else { if (currentMapProvider == 3 || currentMapProvider == 4) { @@ -3504,14 +3581,19 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else if (messageObject.type == 13) { //webp drawBackground = false; + boolean isWebpSticker = false; for (int a = 0; a < messageObject.messageOwner.media.document.attributes.size(); a++) { TLRPC.DocumentAttribute attribute = messageObject.messageOwner.media.document.attributes.get(a); if (attribute instanceof TLRPC.TL_documentAttributeImageSize) { photoWidth = attribute.w; photoHeight = attribute.h; - break; + } else if (attribute instanceof TLRPC.TL_documentAttributeAnimated) { + isWebpSticker = true; } } + if (!isWebpSticker) { + isWebpSticker = "image/webp".equals(messageObject.messageOwner.media.document.mime_type); + } float maxHeight; float maxWidth; if (AndroidUtilities.isTablet()) { @@ -3534,27 +3616,31 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate backgroundWidth = photoWidth + AndroidUtilities.dp(12); currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 40); - if (messageObject.attachPathExists) { - photoImage.setImage(messageObject.messageOwner.attachPath, - String.format(Locale.US, "%d_%d", photoWidth, photoHeight), - null, - currentPhotoObjectThumb, - "b1", - messageObject.messageOwner.media.document.size, "webp", messageObject, 1); - } else if (messageObject.messageOwner.media.document.id != 0) { - photoImage.setImage(messageObject.messageOwner.media.document, - String.format(Locale.US, "%d_%d", photoWidth, photoHeight), - null, - currentPhotoObjectThumb, - "b1", - messageObject.messageOwner.media.document.size, "webp", messageObject, 1); + photoParentObject = messageObject.photoThumbsObject; + if (isWebpSticker) { + if (messageObject.attachPathExists) { + photoImage.setImage(ImageLocation.getForPath(messageObject.messageOwner.attachPath), String.format(Locale.US, "%d_%d", photoWidth, photoHeight), + ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), "b1", + messageObject.messageOwner.media.document.size, "webp", messageObject, 1); + } else if (messageObject.messageOwner.media.document.id != 0) { + photoImage.setImage(ImageLocation.getForDocument(messageObject.messageOwner.media.document), String.format(Locale.US, "%d_%d", photoWidth, photoHeight), + ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), "b1", + messageObject.messageOwner.media.document.size, "webp", messageObject, 1); + } + } else { + photoImage.setImage(ImageLocation.getForDocument(messageObject.messageOwner.media.document), String.format(Locale.US, "%d_%d", photoWidth, photoHeight), + null, "b1", + messageObject.messageOwner.media.document.size, null, messageObject, 0); } } else { currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize()); + photoParentObject = messageObject.photoThumbsObject; int maxPhotoWidth; boolean useFullWidth = false; if (messageObject.type == 5) { maxPhotoWidth = photoWidth = AndroidUtilities.roundMessageSize; + documentAttach = messageObject.getDocument(); + documentAttachType = DOCUMENT_ATTACH_TYPE_ROUND; } else { if (AndroidUtilities.isTablet()) { maxPhotoWidth = photoWidth = (int) (AndroidUtilities.getMinTabletSide() * 0.7f); @@ -3588,7 +3674,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (messageObject.type == 1) { //photo updateSecretTimeText(messageObject); currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 40); - } else if (messageObject.type == 3) { //video + } else if (messageObject.type == 3 || messageObject.type == 8) { //video, gif createDocumentLayout(0, messageObject); currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 40); updateSecretTimeText(messageObject); @@ -3596,12 +3682,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (messageObject.type == 5) { //round video currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 40); needQualityPreview = true; - } else if (messageObject.type == 8) { //gif - currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 40); - String str = AndroidUtilities.formatFileSize(messageObject.messageOwner.media.document.size); - infoWidth = (int) Math.ceil(Theme.chat_infoPaint.measureText(str)); - infoLayout = new StaticLayout(str, Theme.chat_infoPaint, infoWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - needQualityPreview = true; } int w; int h; @@ -3770,7 +3850,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate for (int a = 0; a < currentPosition.siblingHeights.length; a++) { h += (int) Math.ceil(maxHeight * currentPosition.siblingHeights[a]); } - h += (currentPosition.maxY - currentPosition.minY) * AndroidUtilities.dp(7); //TODO fix + h += (currentPosition.maxY - currentPosition.minY) * Math.round(7 * AndroidUtilities.density); //TODO fix } else { h = (int) Math.ceil(maxHeight * currentPosition.ph); } @@ -3948,19 +4028,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (SharedConfig.autoplayVideo && messageObject.type == 3 && !messageObject.needDrawBluredPreview() && ( currentMessageObject.mediaExists || - messageObject.canStreamVideo() && DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject) + messageObject.canStreamVideo() && DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject) )) { if (currentPosition != null) { - autoPlayingVideo = (currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) != 0 && (currentPosition.flags & MessageObject.POSITION_FLAG_RIGHT) != 0; + autoPlayingMedia = (currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) != 0 && (currentPosition.flags & MessageObject.POSITION_FLAG_RIGHT) != 0; } else { - autoPlayingVideo = true; + autoPlayingMedia = true; } } - if (autoPlayingVideo) { + if (autoPlayingMedia) { photoImage.setAllowStartAnimation(true); photoImage.startAnimation(); - photoImage.setImage(messageObject.messageOwner.media.document, ImageLoader.VIDEO_FILTER, currentPhotoObject, currentPhotoFilter, null, currentPhotoObjectThumb, currentPhotoFilterThumb, messageObject.messageOwner.media.document.size, null, messageObject, 0); + TLRPC.Document document = messageObject.messageOwner.media.document; + photoImage.setImage(ImageLocation.getForDocument(document), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, document), currentPhotoFilterThumb, null, messageObject.messageOwner.media.document.size, null, messageObject, 0); } else if (messageObject.type == 1) { if (messageObject.useCustomPhoto) { photoImage.setImageBitmap(getResources().getDrawable(R.drawable.theme_preview_image)); @@ -3974,11 +4055,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoExist = false; } if (photoExist || DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject) || FileLoader.getInstance(currentAccount).isLoadingFile(fileName)) { - photoImage.setImage(currentPhotoObject, currentPhotoFilter, currentPhotoObjectThumb, currentPhotoFilterThumb, noSize ? 0 : currentPhotoObject.size, null, currentMessageObject, currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); + photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, noSize ? 0 : currentPhotoObject.size, null, currentMessageObject, currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); } else { photoNotSet = true; if (currentPhotoObjectThumb != null) { - photoImage.setImage(null, null, currentPhotoObjectThumb, currentPhotoFilterThumb, 0, null, currentMessageObject, currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); + photoImage.setImage(null, null, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, currentMessageObject, currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); } else { photoImage.setImageBitmap((Drawable) null); } @@ -3997,23 +4078,23 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate localFile = 2; } boolean autoDownload = false; - if (MessageObject.isNewGifDocument(messageObject.messageOwner.media.document)) { - autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject); - } else if (messageObject.type == 5) { + if (MessageObject.isGifDocument(messageObject.messageOwner.media.document) || messageObject.type == 5) { autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject); } if (!messageObject.isSending() && !messageObject.isEditing() && (localFile != 0 || FileLoader.getInstance(currentAccount).isLoadingFile(fileName) || autoDownload)) { - if (localFile == 1) { - photoImage.setImage(messageObject.isSendError() ? null : messageObject.messageOwner.attachPath, null, null, currentPhotoObjectThumb, currentPhotoFilterThumb, 0, null, messageObject, 0); + if (localFile != 1 && !messageObject.needDrawBluredPreview() && (localFile != 0 || messageObject.canStreamVideo() && autoDownload)) { + autoPlayingMedia = true; + photoImage.setImage(ImageLocation.getForDocument(messageObject.messageOwner.media.document), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, null, messageObject.messageOwner.media.document.size, null, messageObject, 0); + } else if (localFile == 1) { + photoImage.setImage(ImageLocation.getForPath(messageObject.isSendError() ? null : messageObject.messageOwner.attachPath), null, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, 0); } else { - photoImage.setImage(messageObject.messageOwner.media.document, null, currentPhotoObjectThumb, currentPhotoFilterThumb, messageObject.messageOwner.media.document.size, null, messageObject, 0); + photoImage.setImage(ImageLocation.getForDocument(messageObject.messageOwner.media.document), null, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, null, messageObject.messageOwner.media.document.size, null, messageObject, 0); } } else { - photoNotSet = true; - photoImage.setImage(currentPhotoObject, currentPhotoFilter, currentPhotoObjectThumb, currentPhotoFilterThumb, 0, null, messageObject, 0); + photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, 0); } } else { - photoImage.setImage(currentPhotoObject, currentPhotoFilter, currentPhotoObjectThumb, currentPhotoFilterThumb, 0, null, messageObject, currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); + photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); } } setMessageObjectInternal(messageObject); @@ -4263,17 +4344,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC) { if (MessageObject.isDocumentHasThumb(documentAttach)) { TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(documentAttach.thumbs, 90); - radialProgress.setImageOverlay(thumb, messageObject); + radialProgress.setImageOverlay(thumb, documentAttach, messageObject); } else { String artworkUrl = messageObject.getArtworkUrl(true); if (!TextUtils.isEmpty(artworkUrl)) { radialProgress.setImageOverlay(artworkUrl); } else { - radialProgress.setImageOverlay(null, null); + radialProgress.setImageOverlay(null, null, null); } } } else { - radialProgress.setImageOverlay(null, null); + radialProgress.setImageOverlay(null, null, null); } } updateWaveform(); @@ -4284,6 +4365,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate buttonState = 4; radialProgress.setIcon(getIconForCurrentState(), false, false); } + + accessibilityVirtualViewBounds.clear(); } public void checkVideoPlayback(boolean allowStart) { @@ -4327,11 +4410,18 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate resetPressedLink(-1); if (buttonPressed != 0 || miniButtonPressed != 0 || videoButtonPressed != 0 || pressedBotButton != -1) { buttonPressed = 0; - miniButtonState = 0; + miniButtonPressed = 0; videoButtonPressed = 0; pressedBotButton = -1; invalidate(); } + + linkPreviewPressed = false; + otherPressed = false; + sharePressed = false; + imagePressed = false; + gamePreviewPressed = false; + if (instantPressed) { instantPressed = instantButtonPressed = false; if (Build.VERSION.SDK_INT >= 21 && selectorDrawable != null) { @@ -4347,7 +4437,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate invalidate(); } if (delegate != null) { - delegate.didLongPress(this); + delegate.didLongPress(this, lastTouchX, lastTouchY); } } @@ -4356,18 +4446,37 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate isPressed = pressed; updateRadialProgressBackground(); if (useSeekBarWaweform) { - seekBarWaveform.setSelected(isDrawSelectedBackground()); + seekBarWaveform.setSelected(isDrawSelectionBackground()); } else { - seekBar.setSelected(isDrawSelectedBackground()); + seekBar.setSelected(isDrawSelectionBackground()); } invalidate(); } + public void setInvalidatesParent(boolean value) { + invalidatesParent = value; + } + + @Override + public void invalidate() { + super.invalidate(); + if (invalidatesParent && getParent() != null) { + View parent = (View) getParent(); + if (parent.getParent() != null) { + parent = (View) parent.getParent(); + parent.invalidate(); + } + } + } + public void setHighlightedAnimated() { isHighlightedAnimated = true; highlightProgress = 1000; lastHighlightProgressTime = System.currentTimeMillis(); invalidate(); + if (getParent() != null) { + ((View) getParent()).invalidate(); + } } public boolean isHighlighted() { @@ -4390,11 +4499,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate updateRadialProgressBackground(); if (useSeekBarWaweform) { - seekBarWaveform.setSelected(isDrawSelectedBackground()); + seekBarWaveform.setSelected(isDrawSelectionBackground()); } else { - seekBar.setSelected(isDrawSelectedBackground()); + seekBar.setSelected(isDrawSelectionBackground()); } invalidate(); + if (getParent() != null) { + ((View) getParent()).invalidate(); + } } @Override @@ -4402,9 +4514,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate super.setPressed(pressed); updateRadialProgressBackground(); if (useSeekBarWaweform) { - seekBarWaveform.setSelected(isDrawSelectedBackground()); + seekBarWaveform.setSelected(isDrawSelectionBackground()); } else { - seekBar.setSelected(isDrawSelectedBackground()); + seekBar.setSelected(isDrawSelectionBackground()); } invalidate(); } @@ -4413,11 +4525,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (drawRadialCheckBackground) { return; } - radialProgress.setPressed(isHighlighted || isPressed || buttonPressed != 0 || isPressed(), false); + boolean forcePressed = (isHighlighted || isPressed || isPressed()) && (!drawPhotoImage || !photoImage.hasBitmapImage()); + radialProgress.setPressed(forcePressed || buttonPressed != 0, false); if (hasMiniProgress != 0) { - radialProgress.setPressed(isHighlighted || isPressed || miniButtonPressed != 0 || isPressed(), true); + radialProgress.setPressed(forcePressed || miniButtonPressed != 0, true); } - videoRadialProgress.setPressed(isHighlighted || isPressed || videoButtonPressed != 0 || isPressed(), false); + videoRadialProgress.setPressed(forcePressed || videoButtonPressed != 0, false); } @Override @@ -4515,6 +4628,19 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate docTitleLayout = new StaticLayout(str, Theme.chat_infoPaint, docTitleWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } return 0; + } else if (MessageObject.isGifDocument(documentAttach)) { + documentAttachType = DOCUMENT_ATTACH_TYPE_GIF; + if (!messageObject.needDrawBluredPreview()) { + + String str = LocaleController.getString("AttachGif", R.string.AttachGif); + infoWidth = (int) Math.ceil(Theme.chat_infoPaint.measureText(str)); + infoLayout = new StaticLayout(str, Theme.chat_infoPaint, infoWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + + str = String.format("%s", AndroidUtilities.formatFileSize(documentAttach.size)); + docTitleWidth = (int) Math.ceil(Theme.chat_infoPaint.measureText(str)); + docTitleLayout = new StaticLayout(str, Theme.chat_infoPaint, docTitleWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + } + return 0; } else { drawPhotoImage = documentAttach.mime_type != null && documentAttach.mime_type.toLowerCase().startsWith("image/") || MessageObject.isDocumentHasThumb(documentAttach); if (!drawPhotoImage) { @@ -4565,7 +4691,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoImage.setShouldGenerateQualityThumb(true); } currentPhotoFilter = "86_86_b"; - photoImage.setImage(currentPhotoObject, "86_86", null, currentPhotoObjectThumb, currentPhotoFilter, 0, null, messageObject, 1); + photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, messageObject.photoThumbsObject), "86_86", ImageLocation.getForObject(currentPhotoObjectThumb, messageObject.photoThumbsObject), currentPhotoFilter, 0, null, messageObject, 1); } return width; } @@ -4576,7 +4702,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate totalHeight += AndroidUtilities.dp(14); hasNewLineForTime = true; backgroundWidth = Math.max(maxChildWidth, currentMessageObject.lastLineWidth) + AndroidUtilities.dp(31); - backgroundWidth = Math.max(backgroundWidth, (currentMessageObject.isOutOwner() ? timeWidth + AndroidUtilities.dp(17) : timeWidth)+ AndroidUtilities.dp(31)); + backgroundWidth = Math.max(backgroundWidth, (currentMessageObject.isOutOwner() ? timeWidth + AndroidUtilities.dp(17) : timeWidth) + AndroidUtilities.dp(31)); } else { int diff = maxChildWidth - currentMessageObject.lastLineWidth; if (diff >= 0 && diff <= timeMore) { @@ -4589,8 +4715,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public void setHighlightedText(String text) { MessageObject messageObject = messageObjectToSet != null ? messageObjectToSet : currentMessageObject; - - if (messageObject == null || messageObject.messageOwner.message == null || messageObject.type != 0 || TextUtils.isEmpty(messageObject.messageText) || text == null) { + if (messageObject == null || TextUtils.isEmpty(text)) { if (!urlPathSelection.isEmpty()) { linkSelectionBlockNum = -1; resetUrlPaths(true); @@ -4598,7 +4723,31 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } return; } - int start = TextUtils.indexOf(messageObject.messageOwner.message.toLowerCase(), text.toLowerCase()); + text = text.toLowerCase(); + String message = messageObject.messageOwner.message.toLowerCase(); + int start = -1; + int length = -1; + String punctuationsChars = " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\n"; + for (int a = 0, N1 = message.length(); a < N1; a++) { + int currentLen = 0; + for (int b = 0, N2 = Math.min(text.length(), N1 - a); b < N2; b++) { + boolean match = message.charAt(a + b) == text.charAt(b); + if (match) { + if (currentLen != 0 || a == 0 || punctuationsChars.indexOf(message.charAt(a - 1)) >= 0) { + currentLen++; + } else { + match = false; + } + } + if (!match || b == N2 - 1) { + if (currentLen > 0 && currentLen > length) { + length = currentLen; + start = a; + } + break; + } + } + } if (start == -1) { if (!urlPathSelection.isEmpty()) { linkSelectionBlockNum = -1; @@ -4607,34 +4756,52 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } return; } - int end = start + text.length(); - for (int c = 0; c < messageObject.textLayoutBlocks.size(); c++) { - MessageObject.TextLayoutBlock block = messageObject.textLayoutBlocks.get(c); - if (start >= block.charactersOffset && start < block.charactersOffset + block.textLayout.getText().length()) { - linkSelectionBlockNum = c; - resetUrlPaths(true); - try { - LinkPath path = obtainNewUrlPath(true); - int length = block.textLayout.getText().length(); - path.setCurrentLayout(block.textLayout, start, 0); - block.textLayout.getSelectionPath(start, end - block.charactersOffset, path); - if (end >= block.charactersOffset + length) { - for (int a = c + 1; a < messageObject.textLayoutBlocks.size(); a++) { - MessageObject.TextLayoutBlock nextBlock = messageObject.textLayoutBlocks.get(a); - length = nextBlock.textLayout.getText().length(); - path = obtainNewUrlPath(true); - path.setCurrentLayout(nextBlock.textLayout, 0, nextBlock.height); - nextBlock.textLayout.getSelectionPath(0, end - nextBlock.charactersOffset, path); - if (end < block.charactersOffset + length - 1) { - break; + for (int a = start + length, N = message.length(); a < N; a++) { + if (punctuationsChars.indexOf(message.charAt(a)) < 0) { + length++; + } else { + break; + } + } + int end = start + length; + if (captionLayout != null && !TextUtils.isEmpty(messageObject.caption)) { + resetUrlPaths(true); + try { + LinkPath path = obtainNewUrlPath(true); + path.setCurrentLayout(captionLayout, start, 0); + captionLayout.getSelectionPath(start, end, path); + } catch (Exception e) { + FileLog.e(e); + } + invalidate(); + } else if (messageObject.textLayoutBlocks != null) { + for (int c = 0; c < messageObject.textLayoutBlocks.size(); c++) { + MessageObject.TextLayoutBlock block = messageObject.textLayoutBlocks.get(c); + if (start >= block.charactersOffset && start < block.charactersOffset + block.textLayout.getText().length()) { + linkSelectionBlockNum = c; + resetUrlPaths(true); + try { + LinkPath path = obtainNewUrlPath(true); + path.setCurrentLayout(block.textLayout, start, 0); + block.textLayout.getSelectionPath(start, end - block.charactersOffset, path); + if (end >= block.charactersOffset + length) { + for (int a = c + 1; a < messageObject.textLayoutBlocks.size(); a++) { + MessageObject.TextLayoutBlock nextBlock = messageObject.textLayoutBlocks.get(a); + length = nextBlock.textLayout.getText().length(); + path = obtainNewUrlPath(true); + path.setCurrentLayout(nextBlock.textLayout, 0, nextBlock.height); + nextBlock.textLayout.getSelectionPath(0, end - nextBlock.charactersOffset, path); + if (end < block.charactersOffset + length - 1) { + break; + } } } + } catch (Exception e) { + FileLog.e(e); } - } catch (Exception e) { - FileLog.e(e); + invalidate(); + break; } - invalidate(); - break; } } } @@ -4786,7 +4953,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (currentMessageObject != null && (currentMessageObject.checkLayout() || (currentMessageObject.type == MessageObject.TYPE_POLL || currentPosition != null) && lastHeight != AndroidUtilities.displaySize.y)) { + if (currentMessageObject != null && (currentMessageObject.checkLayout() || lastHeight != AndroidUtilities.displaySize.y)) { inLayout = true; MessageObject messageObject = currentMessageObject; currentMessageObject = null; @@ -4794,11 +4961,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate inLayout = false; } setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), totalHeight + keyboardHeight); - lastHeight = AndroidUtilities.displaySize.y; } public void forceResetMessageObject() { - MessageObject messageObject = currentMessageObject; + MessageObject messageObject = messageObjectToSet != null ? messageObjectToSet : currentMessageObject; currentMessageObject = null; setMessageObject(messageObject, currentMessagesGroup, pinnedBottom, pinnedTop); } @@ -4999,7 +5165,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate buttonY = photoImage.getImageY() + (photoImage.getImageHeight() - AndroidUtilities.dp(48)) / 2; radialProgress.setProgressRect(buttonX, buttonY, buttonX + AndroidUtilities.dp(48), buttonY + AndroidUtilities.dp(48)); deleteProgressRect.set(buttonX + AndroidUtilities.dp(5), buttonY + AndroidUtilities.dp(5), buttonX + AndroidUtilities.dp(43), buttonY + AndroidUtilities.dp(43)); - if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) { + if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF) { videoButtonX = photoImage.getImageX() + AndroidUtilities.dp(8); videoButtonY = photoImage.getImageY() + AndroidUtilities.dp(8); videoRadialProgress.setProgressRect(videoButtonX, videoButtonY, videoButtonX + AndroidUtilities.dp(24), videoButtonY + AndroidUtilities.dp(24)); @@ -5074,7 +5240,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate needNewVisiblePart = false; } forceNotDrawTime = currentMessagesGroup != null; - photoImage.setPressed(isDrawSelectedBackground() ? (currentPosition != null ? 2 : 1) : 0); photoImage.setVisible(!PhotoViewer.isShowingImage(currentMessageObject) && !SecretMediaViewer.getInstance().isShowingImage(currentMessageObject), false); if (!photoImage.getVisible()) { mediaWasInvisible = true; @@ -5425,6 +5590,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.drawCircle(photoImage.getCenterX(), photoImage.getCenterY(), photoImage.getImageWidth() / 2, Theme.chat_docBackPaint); } } + drawPhotoCheckBox = photoCheckBox != null && (checkBoxVisible || photoCheckBox.getProgress() != 0 || checkBoxAnimationInProgress) && currentMessagesGroup != null && currentMessagesGroup.messages.size() > 1; + if (drawPhotoCheckBox && (photoCheckBox.isChecked() || photoCheckBox.getProgress() != 0 || checkBoxAnimationInProgress)) { + Theme.chat_replyLinePaint.setColor(Theme.getColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outBubbleSelected : Theme.key_chat_inBubbleSelected)); + rect.set(photoImage.getImageX(), photoImage.getImageY(), photoImage.getImageX2(), photoImage.getImageY2()); + canvas.drawRoundRect(rect, AndroidUtilities.dp(4), AndroidUtilities.dp(4), Theme.chat_replyLinePaint); + photoImage.setSideClip(AndroidUtilities.dp(14) * photoCheckBox.getProgress()); + if (checkBoxAnimationInProgress) { + photoCheckBox.setBackgroundAlpha(checkBoxAnimationProgress); + } else { + photoCheckBox.setBackgroundAlpha(checkBoxVisible ? 1.0f : photoCheckBox.getProgress()); + } + } else { + photoImage.setSideClip(0); + } imageDrawn = photoImage.draw(canvas); boolean drawTimeOld = drawTime; drawTime = photoImage.getVisible(); @@ -5457,7 +5636,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF || currentMessageObject.type == 8) { + if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF) { if (photoImage.getVisible() && !hasGamePreview && !currentMessageObject.needDrawBluredPreview()) { int oldAlpha = ((BitmapDrawable) Theme.chat_msgMediaMenuDrawable).getPaint().getAlpha(); Theme.chat_msgMediaMenuDrawable.setAlpha((int) (oldAlpha * controlsAlpha)); @@ -5465,7 +5644,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_msgMediaMenuDrawable.draw(canvas); Theme.chat_msgMediaMenuDrawable.setAlpha(oldAlpha); } - } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND || currentMessageObject.type == 5) { + } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND) { if (durationLayout != null) { int x1; int y1; @@ -5473,11 +5652,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate boolean playing = MediaController.getInstance().isPlayingMessage(currentMessageObject); if (playing && currentMessageObject.type == 5) { drawRoundProgress(canvas); + drawOverlays(canvas); } - if (documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND) { - x1 = backgroundDrawableLeft + AndroidUtilities.dp(currentMessageObject.isOutOwner() || drawPinnedBottom ? 12 : 18); - y1 = layoutHeight - AndroidUtilities.dp(6.3f - (drawPinnedBottom ? 2 : 0)) - timeLayout.getHeight(); - } else { + if (currentMessageObject.type == 5) { x1 = backgroundDrawableLeft + AndroidUtilities.dp(8); y1 = layoutHeight - AndroidUtilities.dp(28 - (drawPinnedBottom ? 2 : 0)); rect.set(x1, y1, x1 + timeWidthAudio + AndroidUtilities.dp(8 + 12 + 2), y1 + AndroidUtilities.dp(17)); @@ -5502,6 +5679,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } x1 += AndroidUtilities.dp(4); y1 += AndroidUtilities.dp(1.7f); + } else { + x1 = backgroundDrawableLeft + AndroidUtilities.dp(currentMessageObject.isOutOwner() || drawPinnedBottom ? 12 : 18); + y1 = layoutHeight - AndroidUtilities.dp(6.3f - (drawPinnedBottom ? 2 : 0)) - timeLayout.getHeight(); } Theme.chat_timePaint.setAlpha((int) (255 * timeAlpha)); @@ -5514,14 +5694,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC) { if (currentMessageObject.isOutOwner()) { Theme.chat_audioTitlePaint.setColor(Theme.getColor(Theme.key_chat_outAudioTitleText)); - Theme.chat_audioPerformerPaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_outAudioPerformerSelectedText : Theme.key_chat_outAudioPerformerText)); - Theme.chat_audioTimePaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_outAudioDurationSelectedText : Theme.key_chat_outAudioDurationText)); - radialProgress.setProgressColor(Theme.getColor(isDrawSelectedBackground() || buttonPressed != 0 ? Theme.key_chat_outAudioSelectedProgress : Theme.key_chat_outAudioProgress)); + Theme.chat_audioPerformerPaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outAudioPerformerSelectedText : Theme.key_chat_outAudioPerformerText)); + Theme.chat_audioTimePaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outAudioDurationSelectedText : Theme.key_chat_outAudioDurationText)); + radialProgress.setProgressColor(Theme.getColor(isDrawSelectionBackground() || buttonPressed != 0 ? Theme.key_chat_outAudioSelectedProgress : Theme.key_chat_outAudioProgress)); } else { Theme.chat_audioTitlePaint.setColor(Theme.getColor(Theme.key_chat_inAudioTitleText)); - Theme.chat_audioPerformerPaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_inAudioPerformerSelectedText : Theme.key_chat_inAudioPerformerText)); - Theme.chat_audioTimePaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_inAudioDurationSelectedText : Theme.key_chat_inAudioDurationText)); - radialProgress.setProgressColor(Theme.getColor(isDrawSelectedBackground() || buttonPressed != 0 ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress)); + Theme.chat_audioPerformerPaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_inAudioPerformerSelectedText : Theme.key_chat_inAudioPerformerText)); + Theme.chat_audioTimePaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_inAudioDurationSelectedText : Theme.key_chat_inAudioDurationText)); + radialProgress.setProgressColor(Theme.getColor(isDrawSelectionBackground() || buttonPressed != 0 ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress)); } radialProgress.draw(canvas); @@ -5548,19 +5728,19 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Drawable menuDrawable; if (currentMessageObject.isOutOwner()) { - menuDrawable = isDrawSelectedBackground() ? Theme.chat_msgOutMenuSelectedDrawable : Theme.chat_msgOutMenuDrawable; + menuDrawable = isDrawSelectionBackground() ? Theme.chat_msgOutMenuSelectedDrawable : Theme.chat_msgOutMenuDrawable; } else { - menuDrawable = isDrawSelectedBackground() ? Theme.chat_msgInMenuSelectedDrawable : Theme.chat_msgInMenuDrawable; + menuDrawable = isDrawSelectionBackground() ? Theme.chat_msgInMenuSelectedDrawable : Theme.chat_msgInMenuDrawable; } setDrawableBounds(menuDrawable, otherX = buttonX + backgroundWidth - AndroidUtilities.dp(currentMessageObject.type == 0 ? 58 : 48), otherY = buttonY - AndroidUtilities.dp(5)); menuDrawable.draw(canvas); } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO) { if (currentMessageObject.isOutOwner()) { - Theme.chat_audioTimePaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_outAudioDurationSelectedText : Theme.key_chat_outAudioDurationText)); - radialProgress.setProgressColor(Theme.getColor(isDrawSelectedBackground() || buttonPressed != 0 ? Theme.key_chat_outAudioSelectedProgress : Theme.key_chat_outAudioProgress)); + Theme.chat_audioTimePaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outAudioDurationSelectedText : Theme.key_chat_outAudioDurationText)); + radialProgress.setProgressColor(Theme.getColor(isDrawSelectionBackground() || buttonPressed != 0 ? Theme.key_chat_outAudioSelectedProgress : Theme.key_chat_outAudioProgress)); } else { - Theme.chat_audioTimePaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_inAudioDurationSelectedText : Theme.key_chat_inAudioDurationText)); - radialProgress.setProgressColor(Theme.getColor(isDrawSelectedBackground() || buttonPressed != 0 ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress)); + Theme.chat_audioTimePaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_inAudioDurationSelectedText : Theme.key_chat_inAudioDurationText)); + radialProgress.setProgressColor(Theme.getColor(isDrawSelectionBackground() || buttonPressed != 0 ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress)); } radialProgress.draw(canvas); @@ -5652,14 +5832,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Drawable menuDrawable; if (currentMessageObject.isOutOwner()) { Theme.chat_docNamePaint.setColor(Theme.getColor(Theme.key_chat_outFileNameText)); - Theme.chat_infoPaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_outFileInfoSelectedText : Theme.key_chat_outFileInfoText)); - Theme.chat_docBackPaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_outFileBackgroundSelected : Theme.key_chat_outFileBackground)); - menuDrawable = isDrawSelectedBackground() ? Theme.chat_msgOutMenuSelectedDrawable : Theme.chat_msgOutMenuDrawable; + Theme.chat_infoPaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outFileInfoSelectedText : Theme.key_chat_outFileInfoText)); + Theme.chat_docBackPaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outFileBackgroundSelected : Theme.key_chat_outFileBackground)); + menuDrawable = isDrawSelectionBackground() ? Theme.chat_msgOutMenuSelectedDrawable : Theme.chat_msgOutMenuDrawable; } else { Theme.chat_docNamePaint.setColor(Theme.getColor(Theme.key_chat_inFileNameText)); - Theme.chat_infoPaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_inFileInfoSelectedText : Theme.key_chat_inFileInfoText)); - Theme.chat_docBackPaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_inFileBackgroundSelected : Theme.key_chat_inFileBackground)); - menuDrawable = isDrawSelectedBackground() ? Theme.chat_msgInMenuSelectedDrawable : Theme.chat_msgInMenuDrawable; + Theme.chat_infoPaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_inFileInfoSelectedText : Theme.key_chat_inFileInfoText)); + Theme.chat_docBackPaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_inFileBackgroundSelected : Theme.key_chat_inFileBackground)); + menuDrawable = isDrawSelectionBackground() ? Theme.chat_msgInMenuSelectedDrawable : Theme.chat_msgInMenuDrawable; } int x; @@ -5678,14 +5858,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!imageDrawn) { if (currentMessageObject.isOutOwner()) { radialProgress.setColors(Theme.key_chat_outLoader, Theme.key_chat_outLoaderSelected, Theme.key_chat_outMediaIcon, Theme.key_chat_outMediaIconSelected); - radialProgress.setProgressColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_outFileProgressSelected : Theme.key_chat_outFileProgress)); + radialProgress.setProgressColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outFileProgressSelected : Theme.key_chat_outFileProgress)); videoRadialProgress.setColors(Theme.key_chat_outLoader, Theme.key_chat_outLoaderSelected, Theme.key_chat_outMediaIcon, Theme.key_chat_outMediaIconSelected); - videoRadialProgress.setProgressColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_outFileProgressSelected : Theme.key_chat_outFileProgress)); + videoRadialProgress.setProgressColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outFileProgressSelected : Theme.key_chat_outFileProgress)); } else { radialProgress.setColors(Theme.key_chat_inLoader, Theme.key_chat_inLoaderSelected, Theme.key_chat_inMediaIcon, Theme.key_chat_inMediaIconSelected); - radialProgress.setProgressColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_inFileProgressSelected : Theme.key_chat_inFileProgress)); + radialProgress.setProgressColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_inFileProgressSelected : Theme.key_chat_inFileProgress)); videoRadialProgress.setColors(Theme.key_chat_inLoader, Theme.key_chat_inLoaderSelected, Theme.key_chat_inMediaIcon, Theme.key_chat_inMediaIconSelected); - videoRadialProgress.setProgressColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_inFileProgressSelected : Theme.key_chat_inFileProgress)); + videoRadialProgress.setProgressColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_inFileProgressSelected : Theme.key_chat_inFileProgress)); } rect.set(photoImage.getImageX(), photoImage.getImageY(), photoImage.getImageX() + photoImage.getImageWidth(), photoImage.getImageY() + photoImage.getImageHeight()); @@ -5709,11 +5889,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate subtitleY += (docTitleLayout.getLineCount() - 1) * AndroidUtilities.dp(16) + AndroidUtilities.dp(2); } if (currentMessageObject.isOutOwner()) { - radialProgress.setProgressColor(Theme.getColor(isDrawSelectedBackground() || buttonPressed != 0 ? Theme.key_chat_outAudioSelectedProgress : Theme.key_chat_outAudioProgress)); - videoRadialProgress.setProgressColor(Theme.getColor(isDrawSelectedBackground() || videoButtonPressed != 0 ? Theme.key_chat_outAudioSelectedProgress : Theme.key_chat_outAudioProgress)); + radialProgress.setProgressColor(Theme.getColor(isDrawSelectionBackground() || buttonPressed != 0 ? Theme.key_chat_outAudioSelectedProgress : Theme.key_chat_outAudioProgress)); + videoRadialProgress.setProgressColor(Theme.getColor(isDrawSelectionBackground() || videoButtonPressed != 0 ? Theme.key_chat_outAudioSelectedProgress : Theme.key_chat_outAudioProgress)); } else { - radialProgress.setProgressColor(Theme.getColor(isDrawSelectedBackground() || buttonPressed != 0 ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress)); - videoRadialProgress.setProgressColor(Theme.getColor(isDrawSelectedBackground() || videoButtonPressed != 0 ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress)); + radialProgress.setProgressColor(Theme.getColor(isDrawSelectionBackground() || buttonPressed != 0 ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress)); + videoRadialProgress.setProgressColor(Theme.getColor(isDrawSelectionBackground() || videoButtonPressed != 0 ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress)); } } menuDrawable.draw(canvas); @@ -5877,9 +6057,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (buttonState == 1) { return MediaActionDrawable.ICON_CANCEL; } else if (buttonState == 2) { - return MediaActionDrawable.ICON_GIF; + return MediaActionDrawable.ICON_PLAY; } else if (buttonState == 3) { - return autoPlayingVideo ? MediaActionDrawable.ICON_NONE : MediaActionDrawable.ICON_PLAY; + return autoPlayingMedia ? MediaActionDrawable.ICON_NONE : MediaActionDrawable.ICON_PLAY; } } else if (buttonState == -1) { if (documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT) { @@ -5952,11 +6132,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate boolean fileExists = false; if (currentMessageObject.type == 1) { if (currentPhotoObject == null) { + radialProgress.setIcon(MediaActionDrawable.ICON_NONE, ifSame, animated); return; } fileName = FileLoader.getAttachFileName(currentPhotoObject); fileExists = currentMessageObject.mediaExists; - } else if (currentMessageObject.type == 8 || currentMessageObject.type == 5 || documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER || currentMessageObject.type == 9 || documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO || documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC) { + } else if (currentMessageObject.type == 8 || documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER || currentMessageObject.type == 9 || documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO || documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC) { if (currentMessageObject.useCustomPhoto) { buttonState = 1; radialProgress.setIcon(getIconForCurrentState(), ifSame, animated); @@ -5976,10 +6157,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate fileName = FileLoader.getAttachFileName(currentPhotoObject); fileExists = currentMessageObject.mediaExists; } - canStreamVideo = currentMessageObject.isSent() && documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO && currentMessageObject.canStreamVideo() && !currentMessageObject.needDrawBluredPreview(); + boolean autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject); + canStreamVideo = currentMessageObject.isSent() && (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && autoDownload) && currentMessageObject.canStreamVideo() && !currentMessageObject.needDrawBluredPreview(); if (SharedConfig.streamMedia && (int) currentMessageObject.getDialogId() != 0 && !currentMessageObject.isSecretMedia() && (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC || - canStreamVideo && currentPosition != null && ((currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) == 0 || (currentPosition.flags & MessageObject.POSITION_FLAG_RIGHT) == 0))) { + canStreamVideo && currentPosition != null && ((currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) == 0 || (currentPosition.flags & MessageObject.POSITION_FLAG_RIGHT) == 0))) { hasMiniProgress = fileExists ? 1 : 2; fileExists = true; } @@ -6069,7 +6251,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } updatePlayingMessageProgress(); - } else if (currentMessageObject.type == 0 && documentAttachType != DOCUMENT_ATTACH_TYPE_DOCUMENT && 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) { if (currentPhotoObject == null || !drawImageButton) { return; } @@ -6077,9 +6259,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate DownloadController.getInstance(currentAccount).addLoadingFileObserver(fileName, currentMessageObject, this); float setProgress = 0; if (!FileLoader.getInstance(currentAccount).isLoadingFile(fileName)) { - if (!cancelLoading && - (documentAttachType == 0 && DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject) || - documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && MessageObject.isNewGifDocument(documentAttach) && DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject))) { + if (!cancelLoading && (documentAttachType == 0 && autoDownload || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && MessageObject.isGifDocument(documentAttach) && autoDownload)) { buttonState = 1; } else { buttonState = 0; @@ -6136,7 +6316,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { buttonState = -1; getIconForCurrentState(); - radialProgress.setIcon(currentMessageObject.isSticker() || currentMessageObject.isLocation() ? MediaActionDrawable.ICON_NONE : MediaActionDrawable.ICON_CANCEL_NOPROFRESS, ifSame, false); + radialProgress.setIcon(currentMessageObject.isSticker() || currentMessageObject.isAnimatedSticker() || currentMessageObject.isLocation() ? MediaActionDrawable.ICON_NONE : MediaActionDrawable.ICON_CANCEL_NOPROFRESS, ifSame, false); radialProgress.setProgress(0, false); } videoRadialProgress.setIcon(MediaActionDrawable.ICON_NONE, ifSame, false); @@ -6144,24 +6324,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (wasSending && !TextUtils.isEmpty(currentMessageObject.messageOwner.attachPath)) { DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); } - boolean playingCurrentMessage = MediaController.getInstance().isPlayingMessage(currentMessageObject); - /*boolean playingCurrentMessageAndDrawing = MediaController.getInstance().isPlayingMessageAndReadyToDraw(currentMessageObject); - if (autoPlayingVideo && documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) { - photoImage.setAllowStartAnimation(!playingCurrentMessageAndDrawing); - if (playingCurrentMessageAndDrawing) { - photoImage.stopAnimation(); - AnimatedFileDrawable animation = photoImage.getAnimation(); - if (animation != null) { - //animation.seekTo(0, true); - } - } else if (!playingCurrentMessage && !PhotoViewer.isPlayingMessage(currentMessageObject) && !MediaController.getInstance().isGoingToShowMessageObject(currentMessageObject)) { - photoImage.startAnimation(); - } - }*/ - boolean isLoadingVideo = false; - if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO && autoPlayingVideo) { - isLoadingVideo = FileLoader.getInstance(currentAccount).isLoadingVideo(documentAttach, playingCurrentMessage); + if ((documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF || documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND) && autoPlayingMedia) { + isLoadingVideo = FileLoader.getInstance(currentAccount).isLoadingVideo(documentAttach, MediaController.getInstance().isPlayingMessage(currentMessageObject)); AnimatedFileDrawable animation = photoImage.getAnimation(); if (animation != null) { if (currentMessageObject.hadAnimationNotReadyLoading) { @@ -6171,6 +6336,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { currentMessageObject.hadAnimationNotReadyLoading = isLoadingVideo && !animation.hasBitmap(); } + } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && !fileExists) { + currentMessageObject.hadAnimationNotReadyLoading = true; } } if (hasMiniProgress != 0) { @@ -6195,7 +6362,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } radialProgress.setMiniIcon(getMiniIconForCurrentState(), ifSame, animated); - } else if (fileExists || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO && autoPlayingVideo && !currentMessageObject.hadAnimationNotReadyLoading && !isLoadingVideo) { + } else if (fileExists || (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF || documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND) && autoPlayingMedia && !currentMessageObject.hadAnimationNotReadyLoading && !isLoadingVideo) { DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); if (drawVideoImageButton && animated) { if (animatingDrawVideoImageButton != 1 && animatingDrawVideoImageButtonProgress > 0) { @@ -6212,7 +6379,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessageObject.needDrawBluredPreview()) { buttonState = -1; } else { - if (currentMessageObject.type == 8 && !photoImage.isAllowStartAnimation()) { + if (currentMessageObject.type == 8 && currentMessageObject.gifState == 1) { buttonState = 2; } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) { buttonState = 3; @@ -6227,8 +6394,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } invalidate(); } else { - drawVideoSize = documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO; - if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO && canStreamVideo && !drawVideoImageButton && animated) { + drawVideoSize = documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF; + if ((documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF || documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND) && canStreamVideo && !drawVideoImageButton && animated) { if (animatingDrawVideoImageButton != 2 && animatingDrawVideoImageButtonProgress < 1.0f) { if (animatingDrawVideoImageButton == 0) { animatingDrawVideoImageButtonProgress = 0.0f; @@ -6241,44 +6408,36 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate DownloadController.getInstance(currentAccount).addLoadingFileObserver(fileName, currentMessageObject, this); boolean progressVisible = false; if (!FileLoader.getInstance(currentAccount).isLoadingFile(fileName)) { - boolean autoDownload = false; - if (currentMessageObject.type == 1) { - autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject); - } else if (currentMessageObject.type == 8 && MessageObject.isNewGifDocument(currentMessageObject.messageOwner.media.document)) { - autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject); - } else if (currentMessageObject.type == 5) { - autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject); - } if (!cancelLoading && autoDownload) { buttonState = 1; } else { buttonState = 0; } - if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO && canStreamVideo) { + if ((documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && autoDownload) && canStreamVideo) { drawVideoImageButton = true; getIconForCurrentState(); - radialProgress.setIcon(autoPlayingVideo ? MediaActionDrawable.ICON_NONE : MediaActionDrawable.ICON_PLAY, ifSame, animated); + radialProgress.setIcon(autoPlayingMedia ? MediaActionDrawable.ICON_NONE : MediaActionDrawable.ICON_PLAY, ifSame, animated); videoRadialProgress.setIcon(MediaActionDrawable.ICON_DOWNLOAD, ifSame, animated); } else { drawVideoImageButton = false; radialProgress.setIcon(getIconForCurrentState(), ifSame, animated); videoRadialProgress.setIcon(MediaActionDrawable.ICON_NONE, ifSame, false); if (!drawVideoSize && animatingDrawVideoImageButton == 0) { - animatingDrawVideoImageButtonProgress = 0.0f; + animatingDrawVideoImageButtonProgress = 0.0f; } } } else { buttonState = 1; Float progress = ImageLoader.getInstance().getFileProgress(fileName); - if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO && canStreamVideo) { + if ((documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && autoDownload) && canStreamVideo) { drawVideoImageButton = true; getIconForCurrentState(); - radialProgress.setIcon(autoPlayingVideo ? MediaActionDrawable.ICON_NONE : MediaActionDrawable.ICON_PLAY, ifSame, animated); - videoRadialProgress.setProgress(progress != null ? progress : 0, false); + radialProgress.setIcon(autoPlayingMedia || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF ? MediaActionDrawable.ICON_NONE : MediaActionDrawable.ICON_PLAY, ifSame, animated); + videoRadialProgress.setProgress(progress != null ? progress : 0, animated); videoRadialProgress.setIcon(MediaActionDrawable.ICON_CANCEL_FILL, ifSame, animated); } else { drawVideoImageButton = false; - radialProgress.setProgress(progress != null ? progress : 0, false); + radialProgress.setProgress(progress != null ? progress : 0, animated); radialProgress.setIcon(getIconForCurrentState(), ifSame, animated); videoRadialProgress.setIcon(MediaActionDrawable.ICON_NONE, ifSame, false); if (!drawVideoSize && animatingDrawVideoImageButton == 0) { @@ -6320,7 +6479,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } private void didPressButton(boolean animated, boolean video) { - if (buttonState == 0 && (!drawVideoImageButton && !video || video)) { + if (buttonState == 0 && (!drawVideoImageButton || video)) { if (documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO || documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC) { if (miniButtonState == 0) { FileLoader.getInstance(currentAccount).loadFile(documentAttach, currentMessageObject, 1, 0); @@ -6354,11 +6513,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (currentMessageObject.type == 1) { photoImage.setForceLoading(true); - photoImage.setImage(currentPhotoObject, currentPhotoFilter, currentPhotoObjectThumb, currentPhotoFilterThumb, currentPhotoObject.size, null, currentMessageObject, currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); + photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, currentPhotoObject.size, null, currentMessageObject, currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); } else if (currentMessageObject.type == 8) { - currentMessageObject.gifState = 2; - photoImage.setForceLoading(true); - photoImage.setImage(currentMessageObject.messageOwner.media.document, null, thumb, thumbFilter, currentMessageObject.messageOwner.media.document.size, null, currentMessageObject, 0); + FileLoader.getInstance(currentAccount).loadFile(documentAttach, currentMessageObject, 1, 0); } else if (currentMessageObject.isRoundVideo()) { if (currentMessageObject.isSecretMedia()) { FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.getDocument(), currentMessageObject, 1, 1); @@ -6367,7 +6524,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate TLRPC.Document document = currentMessageObject.getDocument(); photoImage.setForceLoading(true); - photoImage.setImage(document, null, thumb, thumbFilter, document.size, null, currentMessageObject, 0); + photoImage.setImage(ImageLocation.getForDocument(document), null, ImageLocation.getForObject(thumb, document), thumbFilter, document.size, null, currentMessageObject, 0); } } else if (currentMessageObject.type == 9) { FileLoader.getInstance(currentAccount).loadFile(documentAttach, currentMessageObject, 0, 0); @@ -6376,16 +6533,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (currentMessageObject.type == 0 && documentAttachType != DOCUMENT_ATTACH_TYPE_NONE) { if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF) { photoImage.setForceLoading(true); - photoImage.setImage(documentAttach, null, currentPhotoObject, currentPhotoFilterThumb, documentAttach.size, null, currentMessageObject, 0); + photoImage.setImage(ImageLocation.getForDocument(documentAttach), null, ImageLocation.getForDocument(currentPhotoObject, documentAttach), currentPhotoFilterThumb, documentAttach.size, null, currentMessageObject, 0); currentMessageObject.gifState = 2; } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT) { FileLoader.getInstance(currentAccount).loadFile(documentAttach, currentMessageObject, 0, 0); } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER) { - photoImage.setImage(documentAttach, currentPhotoFilter, null, currentPhotoObject, "b1", 0, "jpg", currentMessageObject, 1); + photoImage.setImage(ImageLocation.getForDocument(documentAttach), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObject, documentAttach), "b1", 0, "jpg", currentMessageObject, 1); } } else { photoImage.setForceLoading(true); - photoImage.setImage(currentPhotoObject, currentPhotoFilter, currentPhotoObjectThumb, currentPhotoFilterThumb, 0, null, currentMessageObject, 0); + photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, currentMessageObject, 0); } buttonState = 1; if (video) { @@ -6395,7 +6552,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } invalidate(); } - } else if (buttonState == 1 && (!drawVideoImageButton && !video || video)) { + } else if (buttonState == 1 && (!drawVideoImageButton || video)) { photoImage.setForceLoading(false); if (documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO || documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC) { boolean result = MediaController.getInstance().pauseMessage(currentMessageObject); @@ -6411,7 +6568,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else { cancelLoading = true; - if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER) { + if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER) { FileLoader.getInstance(currentAccount).cancelLoadFile(documentAttach); } else if (currentMessageObject.type == 0 || currentMessageObject.type == 1 || currentMessageObject.type == 8 || currentMessageObject.type == 5) { ImageLoader.getInstance().cancelForceLoadingForImageReceiver(photoImage); @@ -6456,7 +6613,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate radialProgress.setProgress(0, false); radialProgress.setMiniIcon(getMiniIconForCurrentState(), false, animated); } - delegate.didPressImage(this); + delegate.didPressImage(this, 0, 0); } else if (buttonState == 4) { if (documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO || documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC) { if (currentMessageObject.isOut() && (currentMessageObject.isSending() || currentMessageObject.isEditing()) || currentMessageObject.isSendError()) { @@ -6489,19 +6646,37 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { radialProgress.setProgress(1, true); } - if (SharedConfig.autoplayVideo && !currentMessageObject.needDrawBluredPreview() && !autoPlayingVideo && documentAttach != null && documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO && (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) != 0 && (currentPosition.flags & MessageObject.POSITION_FLAG_RIGHT) != 0)) { - animatingNoSound = 2; - photoImage.setImage(documentAttach, ImageLoader.VIDEO_FILTER, currentPhotoObject, currentPhotoObject instanceof TLRPC.TL_photoStrippedSize || currentPhotoObject != null && "s".equals(currentPhotoObject.type) ? currentPhotoFilterThumb : currentPhotoFilter, null, currentPhotoObjectThumb, currentPhotoFilterThumb, documentAttach.size, null, currentMessageObject, 0); - if (!PhotoViewer.isPlayingMessage(currentMessageObject)) { + boolean startedAutoplay = false; + if (!currentMessageObject.needDrawBluredPreview() && !autoPlayingMedia && documentAttach != null) { + if (documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND) { + photoImage.setImage(ImageLocation.getForDocument(documentAttach), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoObject instanceof TLRPC.TL_photoStrippedSize || currentPhotoObject != null && "s".equals(currentPhotoObject.type) ? currentPhotoFilterThumb : currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, null, documentAttach.size, null, currentMessageObject, 0); photoImage.setAllowStartAnimation(true); photoImage.startAnimation(); - } else { - photoImage.setAllowStartAnimation(false); + autoPlayingMedia = true; + } else if (SharedConfig.autoplayVideo && documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO && (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) != 0 && (currentPosition.flags & MessageObject.POSITION_FLAG_RIGHT) != 0)) { + animatingNoSound = 2; + photoImage.setImage(ImageLocation.getForDocument(documentAttach), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoObject instanceof TLRPC.TL_photoStrippedSize || currentPhotoObject != null && "s".equals(currentPhotoObject.type) ? currentPhotoFilterThumb : currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, null, documentAttach.size, null, currentMessageObject, 0); + if (!PhotoViewer.isPlayingMessage(currentMessageObject)) { + photoImage.setAllowStartAnimation(true); + photoImage.startAnimation(); + } else { + photoImage.setAllowStartAnimation(false); + } + autoPlayingMedia = true; + } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF) { + photoImage.setImage(ImageLocation.getForDocument(documentAttach), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoObject instanceof TLRPC.TL_photoStrippedSize || currentPhotoObject != null && "s".equals(currentPhotoObject.type) ? currentPhotoFilterThumb : currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, null, documentAttach.size, null, currentMessageObject, 0); + if (SharedConfig.autoplayGifs) { + photoImage.setAllowStartAnimation(true); + photoImage.startAnimation(); + } else { + photoImage.setAllowStartAnimation(false); + photoImage.stopAnimation(); + } + autoPlayingMedia = true; } - autoPlayingVideo = true; } if (currentMessageObject.type == 0) { - if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && currentMessageObject.gifState != 1) { + if (!autoPlayingMedia && documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && currentMessageObject.gifState != 1) { buttonState = 2; didPressButton(true, false); } else if (!photoNotSet) { @@ -6510,14 +6685,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate setMessageObject(currentMessageObject, currentMessagesGroup, pinnedBottom, pinnedTop); } } else { - if (!photoNotSet || (currentMessageObject.type == 8 || currentMessageObject.type == 5) && currentMessageObject.gifState != 1) { - if ((currentMessageObject.type == 8 || currentMessageObject.type == 5) && currentMessageObject.gifState != 1) { - photoNotSet = false; - buttonState = 2; - didPressButton(true, false); - } else { - updateButtonState(false, true, false); - } + if (!photoNotSet) { + updateButtonState(false, true, false); } if (photoNotSet) { setMessageObject(currentMessageObject, currentMessagesGroup, pinnedBottom, pinnedTop); @@ -6528,10 +6697,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate @Override public void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb) { - boolean animationLoaded = !thumb && imageReceiver.getAnimation() != null; if (currentMessageObject != null && set && !thumb && !currentMessageObject.mediaExists && !currentMessageObject.attachPathExists && - (currentMessageObject.type == 0 && (documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER || documentAttachType == DOCUMENT_ATTACH_TYPE_NONE || documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER || animationLoaded && (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF || documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND)) || - currentMessageObject.type == 1 || animationLoaded && (currentMessageObject.type == 5 || currentMessageObject.type == 8))) { + (currentMessageObject.type == 0 && (documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER || documentAttachType == DOCUMENT_ATTACH_TYPE_NONE || documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER) || currentMessageObject.type == 1)) { currentMessageObject.mediaExists = true; updateButtonState(false, true, false); } @@ -6628,7 +6795,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate edited = (messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_EDITED) != 0 || messageObject.isEditing(); } else { edited = false; - for (int a = 0, size = currentMessagesGroup.messages.size(); a < size; a++){ + for (int a = 0, size = currentMessagesGroup.messages.size(); a < size; a++) { MessageObject object = currentMessagesGroup.messages.get(a); if ((object.messageOwner.flags & TLRPC.MESSAGE_FLAG_EDITED) != 0 || object.isEditing()) { edited = true; @@ -6680,7 +6847,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - private boolean isDrawSelectedBackground() { + private boolean isDrawSelectionBackground() { return isPressed() && isCheckPressed || !isCheckPressed && isPressed || isHighlighted; } @@ -6698,7 +6865,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } public boolean isInsideBackground(float x, float y) { - return currentBackgroundDrawable != null && x >= getLeft() + backgroundDrawableLeft && x <= getLeft() + backgroundDrawableLeft + backgroundDrawableRight; + return currentBackgroundDrawable != null && x >= backgroundDrawableLeft && x <= backgroundDrawableLeft + backgroundDrawableRight; } private void updateCurrentUserAndChat() { @@ -6729,6 +6896,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else if (fwd_from != null && fwd_from.from_id != 0 && fwd_from.channel_id == 0 && currentMessageObject.getDialogId() == currentUserId) { currentUser = messagesController.getUser(fwd_from.from_id); + } else if (fwd_from != null && !TextUtils.isEmpty(fwd_from.from_name) && currentMessageObject.getDialogId() == currentUserId) { + currentUser = new TLRPC.TL_user(); + currentUser.first_name = fwd_from.from_name; } else if (currentMessageObject.isFromUser()) { currentUser = messagesController.getUser(currentMessageObject.messageOwner.from_id); } else if (currentMessageObject.messageOwner.from_id < 0) { @@ -6749,7 +6919,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate updateCurrentUserAndChat(); if (isAvatarVisible) { - Object parentObject = null; if (currentUser != null) { if (currentUser.photo != null) { currentPhoto = currentUser.photo.photo_small; @@ -6757,7 +6926,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentPhoto = null; } avatarDrawable.setInfo(currentUser); - parentObject = currentUser; + avatarImage.setImage(ImageLocation.getForUser(currentUser, false), "50_50", avatarDrawable, null, currentUser, 0); } else if (currentChat != null) { if (currentChat.photo != null) { currentPhoto = currentChat.photo.photo_small; @@ -6765,12 +6934,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentPhoto = null; } avatarDrawable.setInfo(currentChat); - parentObject = currentChat; + avatarImage.setImage(ImageLocation.getForChat(currentChat, false), "50_50", avatarDrawable, null, currentChat, 0); } else { currentPhoto = null; avatarDrawable.setInfo(messageObject.messageOwner.from_id, null, null, false); + avatarImage.setImage(null, null, avatarDrawable, null, null, 0); } - avatarImage.setImage(currentPhoto, "50_50", avatarDrawable, null, parentObject, 0); } else { currentPhoto = null; } @@ -6883,6 +7052,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentForwardUser = null; currentForwardNameString = null; currentForwardChannel = null; + currentForwardName = null; forwardedNameLayout[0] = null; forwardedNameLayout[1] = null; forwardedNameWidth = 0; @@ -6893,8 +7063,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (messageObject.messageOwner.fwd_from.from_id != 0) { currentForwardUser = MessagesController.getInstance(currentAccount).getUser(messageObject.messageOwner.fwd_from.from_id); } + if (messageObject.messageOwner.fwd_from.from_name != null) { + currentForwardName = messageObject.messageOwner.fwd_from.from_name; + } - if (currentForwardUser != null || currentForwardChannel != null) { + if (currentForwardUser != null || currentForwardChannel != null || currentForwardName != null) { if (currentForwardChannel != null) { if (currentForwardUser != null) { currentForwardNameString = String.format("%s (%s)", currentForwardChannel.title, UserObject.getUserName(currentForwardUser)); @@ -6903,6 +7076,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else if (currentForwardUser != null) { currentForwardNameString = UserObject.getUserName(currentForwardUser); + } else if (currentForwardName != null) { + currentForwardNameString = currentForwardName; } forwardedNameWidth = getMaxNameWidth(); @@ -6926,7 +7101,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { stringBuilder = new SpannableStringBuilder(String.format(fromFormattedString, name)); } - if (idx >= 0) { + forwardNameCenterX = fromWidth + (int) Math.ceil(Theme.chat_forwardNamePaint.measureText(name, 0, name.length())) / 2; + if (idx >= 0 && (currentForwardName == null || messageObject.messageOwner.fwd_from.from_id != 0)) { stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), idx, idx + name.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } lastLine = stringBuilder; @@ -6965,9 +7141,27 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate CharSequence stringFinalText = null; + int cacheType = 1; + int size = 0; + TLObject photoObject; TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs2, 320); + TLRPC.PhotoSize thumbPhotoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs2, 40); + photoObject = messageObject.replyMessageObject.photoThumbsObject2; if (photoSize == null) { - photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs, 320); + if (messageObject.replyMessageObject.mediaExists) { + photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs, AndroidUtilities.getPhotoSize()); + if (photoSize != null) { + size = photoSize.size; + } + cacheType = 0; + } else { + photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs, 320); + } + thumbPhotoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs, 40); + photoObject = messageObject.replyMessageObject.photoThumbsObject; + } + if (thumbPhotoSize == photoSize) { + thumbPhotoSize = null; } if (photoSize == null || messageObject.replyMessageObject.type == 13 || messageObject.type == 13 && !AndroidUtilities.isTablet() || messageObject.replyMessageObject.isSecretMedia()) { replyImageReceiver.setImageBitmap((Drawable) null); @@ -6979,7 +7173,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate replyImageReceiver.setRoundRadius(0); } currentReplyPhoto = photoSize; - replyImageReceiver.setImage(photoSize, "50_50", null, null, messageObject.replyMessageObject, 1); + replyImageReceiver.setImage(ImageLocation.getForObject(photoSize, photoObject), "50_50", ImageLocation.getForObject(thumbPhotoSize, photoObject), "50_50_b", size, null, messageObject.replyMessageObject, cacheType); needReplyImage = true; maxWidth -= AndroidUtilities.dp(44); } @@ -7063,6 +7257,19 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return isAvatarVisible ? avatarImage : null; } + public float getCheckBoxTranslation() { + return checkBoxTranslation; + } + + public void drawCheckBox(Canvas canvas) { + if (currentMessageObject != null && !currentMessageObject.isSending() && !currentMessageObject.isSendError() && checkBox != null && (checkBoxVisible || checkBoxAnimationInProgress) && (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 && (currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) != 0)) { + canvas.save(); + canvas.translate(0, getTop()); + checkBox.draw(canvas); + canvas.restore(); + } + } + @Override protected void onDraw(Canvas canvas) { if (currentMessageObject == null) { @@ -7117,9 +7324,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else { if (currentMessageObject.isOutOwner()) { - Theme.chat_timePaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_outTimeSelectedText : Theme.key_chat_outTimeText)); + Theme.chat_timePaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outTimeSelectedText : Theme.key_chat_outTimeText)); } else { - Theme.chat_timePaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_inTimeSelectedText : Theme.key_chat_inTimeText)); + Theme.chat_timePaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_inTimeSelectedText : Theme.key_chat_inTimeText)); } } } @@ -7232,6 +7439,43 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate setDrawableBounds(currentBackgroundSelectedDrawable, backgroundDrawableLeft, backgroundTop, backgroundDrawableRight, layoutHeight - offsetBottom + additionalBottom); setDrawableBounds(currentBackgroundShadowDrawable, backgroundDrawableLeft, backgroundTop, backgroundDrawableRight, layoutHeight - offsetBottom + additionalBottom); } + + if (checkBoxVisible || checkBoxAnimationInProgress) { + if (checkBoxVisible && checkBoxAnimationProgress == 1.0f || !checkBoxVisible && checkBoxAnimationProgress == 0.0f) { + checkBoxAnimationInProgress = false; + } + Interpolator interpolator = checkBoxVisible ? CubicBezierInterpolator.EASE_OUT : CubicBezierInterpolator.EASE_IN; + checkBoxTranslation = (int) Math.ceil(interpolator.getInterpolation(checkBoxAnimationProgress) * AndroidUtilities.dp(35)); + if (!currentMessageObject.isOutOwner()) { + setTranslationX(checkBoxTranslation); + } + + int size = AndroidUtilities.dp(21); + checkBox.setBounds(AndroidUtilities.dp(8 - 35) + checkBoxTranslation, currentBackgroundDrawable.getBounds().bottom - AndroidUtilities.dp(8) - size, size, size); + + if (checkBoxAnimationInProgress) { + long newTime = SystemClock.uptimeMillis(); + long dt = newTime - lastCheckBoxAnimationTime; + lastCheckBoxAnimationTime = newTime; + + if (checkBoxVisible) { + checkBoxAnimationProgress += dt / MessageBackgroundDrawable.ANIMATION_DURATION; + if (checkBoxAnimationProgress > 1.0f) { + checkBoxAnimationProgress = 1.0f; + } + invalidate(); + ((View) getParent()).invalidate(); + } else { + checkBoxAnimationProgress -= dt / MessageBackgroundDrawable.ANIMATION_DURATION; + if (checkBoxAnimationProgress <= 0.0f) { + checkBoxAnimationProgress = 0.0f; + } + invalidate(); + ((View) getParent()).invalidate(); + } + } + } + if (drawBackground && currentBackgroundDrawable != null) { if (isHighlightedAnimated) { currentBackgroundDrawable.draw(canvas); @@ -7240,20 +7484,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentBackgroundSelectedDrawable.setAlpha((int) (alpha * 255)); currentBackgroundSelectedDrawable.draw(canvas); } - long newTime = System.currentTimeMillis(); - long dt = Math.abs(newTime - lastHighlightProgressTime); - if (dt > 17) { - dt = 17; - } - highlightProgress -= dt; - lastHighlightProgressTime = newTime; - if (highlightProgress <= 0) { - highlightProgress = 0; - isHighlightedAnimated = false; - } - invalidate(); } else { - if (isDrawSelectedBackground() && (currentPosition == null || getBackground() != null)) { + if (isDrawSelectionBackground() && (currentPosition == null || getBackground() != null)) { currentBackgroundSelectedDrawable.setAlpha(255); currentBackgroundSelectedDrawable.draw(canvas); } else { @@ -7264,6 +7496,23 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentBackgroundShadowDrawable.draw(canvas); } } + if (isHighlightedAnimated) { + long newTime = System.currentTimeMillis(); + long dt = Math.abs(newTime - lastHighlightProgressTime); + if (dt > 17) { + dt = 17; + } + highlightProgress -= dt; + lastHighlightProgressTime = newTime; + if (highlightProgress <= 0) { + highlightProgress = 0; + isHighlightedAnimated = false; + } + invalidate(); + if (getParent() != null) { + ((View) getParent()).invalidate(); + } + } drawContent(canvas); @@ -7324,7 +7573,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate drawNamesLayout(canvas); } - if (!autoPlayingVideo || !MediaController.getInstance().isPlayingMessageAndReadyToDraw(currentMessageObject)) { + if (!autoPlayingMedia || !MediaController.getInstance().isPlayingMessageAndReadyToDraw(currentMessageObject)) { drawOverlays(canvas); } if ((drawTime || !mediaBackground) && !forceNotDrawTime) { @@ -7378,6 +7627,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate replyNameLayout != null; } + public boolean isDrawNameLayout() { + return drawNameLayout && nameLayout != null; + } + public void drawNamesLayout(Canvas canvas) { if (drawNameLayout && nameLayout != null) { canvas.save(); @@ -7417,7 +7670,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate nameLayout.draw(canvas); canvas.restore(); if (adminLayout != null) { - Theme.chat_adminPaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_adminSelectedText : Theme.key_chat_adminText)); + Theme.chat_adminPaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_adminSelectedText : Theme.key_chat_adminText)); canvas.save(); canvas.translate(backgroundDrawableLeft + backgroundDrawableRight - AndroidUtilities.dp(11) - adminLayout.getLineWidth(0), nameY + AndroidUtilities.dp(0.5f)); adminLayout.draw(canvas); @@ -7477,7 +7730,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessageObject.hasValidReplyMessageObject() && currentMessageObject.replyMessageObject.type == 0 && !(currentMessageObject.replyMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame || currentMessageObject.replyMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaInvoice)) { Theme.chat_replyTextPaint.setColor(Theme.getColor(Theme.key_chat_outReplyMessageText)); } else { - Theme.chat_replyTextPaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_outReplyMediaMessageSelectedText : Theme.key_chat_outReplyMediaMessageText)); + Theme.chat_replyTextPaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outReplyMediaMessageSelectedText : Theme.key_chat_outReplyMediaMessageText)); } } else { Theme.chat_replyLinePaint.setColor(Theme.getColor(Theme.key_chat_inReplyLine)); @@ -7485,7 +7738,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessageObject.hasValidReplyMessageObject() && currentMessageObject.replyMessageObject.type == 0 && !(currentMessageObject.replyMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame || currentMessageObject.replyMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaInvoice)) { Theme.chat_replyTextPaint.setColor(Theme.getColor(Theme.key_chat_inReplyMessageText)); } else { - Theme.chat_replyTextPaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_inReplyMediaMessageSelectedText : Theme.key_chat_inReplyMediaMessageText)); + Theme.chat_replyTextPaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_inReplyMediaMessageSelectedText : Theme.key_chat_inReplyMediaMessageText)); } } } @@ -7516,6 +7769,61 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return captionLayout != null; } + public void setDrawSelectionBackground(boolean value) { + drawSelectionBackground = value; + invalidate(); + } + + public boolean isDrawingSelectionBackground() { + return drawSelectionBackground || isHighlightedAnimated || isHighlighted; + } + + public float getHightlightAlpha() { + if (!drawSelectionBackground && isHighlightedAnimated) { + return highlightProgress >= 300 ? 1.0f : highlightProgress / 300.0f; + } + return 1.0f; + } + + public void setCheckBoxVisible(boolean visible, boolean animated) { + if (visible && checkBox == null) { + checkBox = new CheckBoxBase(this); + if (attachedToWindow) { + checkBox.onAttachedToWindow(); + } + } + if (visible && photoCheckBox == null && currentMessagesGroup != null && currentMessagesGroup.messages.size() > 1) { + photoCheckBox = new CheckBoxBase(this); + if (attachedToWindow) { + photoCheckBox.onAttachedToWindow(); + } + } + if (checkBoxVisible == visible) { + if (animated != checkBoxAnimationInProgress && !animated) { + checkBoxAnimationProgress = visible ? 1.0f : 0.0f; + invalidate(); + } + return; + } + checkBoxAnimationInProgress = animated; + checkBoxVisible = visible; + if (animated) { + lastCheckBoxAnimationTime = SystemClock.uptimeMillis(); + } else { + checkBoxAnimationProgress = visible ? 1.0f : 0.0f; + } + invalidate(); + } + + public void setChecked(boolean checked, boolean allChecked, boolean animated) { + if (checkBox != null) { + checkBox.setChecked(allChecked, animated); + } + if (photoCheckBox != null) { + photoCheckBox.setChecked(checked, animated); + } + } + public void drawCaptionLayout(Canvas canvas, boolean selectionOnly) { if (captionLayout == null || selectionOnly && pressedLink == null) { return; @@ -7527,6 +7835,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.drawPath(urlPath.get(b), Theme.chat_urlPaint); } } + if (!urlPathSelection.isEmpty()) { + for (int b = 0; b < urlPathSelection.size(); b++) { + canvas.drawPath(urlPathSelection.get(b), Theme.chat_textSearchSelectionPaint); + } + } if (!selectionOnly) { try { captionLayout.draw(canvas); @@ -7556,9 +7869,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else { if (currentMessageObject.isOutOwner()) { - Theme.chat_timePaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_outTimeSelectedText : Theme.key_chat_outTimeText)); + Theme.chat_timePaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outTimeSelectedText : Theme.key_chat_outTimeText)); } else { - Theme.chat_timePaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_inTimeSelectedText : Theme.key_chat_inTimeText)); + Theme.chat_timePaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_inTimeSelectedText : Theme.key_chat_inTimeText)); } } } @@ -7633,7 +7946,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessageObject.isSending() || currentMessageObject.isEditing()) { if (!currentMessageObject.isOutOwner()) { - Drawable clockDrawable = isDrawSelectedBackground() ? Theme.chat_msgInSelectedClockDrawable : Theme.chat_msgInClockDrawable; + Drawable clockDrawable = isDrawSelectionBackground() ? Theme.chat_msgInSelectedClockDrawable : Theme.chat_msgInClockDrawable; setDrawableBounds(clockDrawable, timeX + AndroidUtilities.dp(11), layoutHeight - AndroidUtilities.dp(8.5f) - clockDrawable.getIntrinsicHeight()); clockDrawable.draw(canvas); } @@ -7648,11 +7961,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else { if (!currentMessageObject.isOutOwner()) { - Drawable viewsDrawable = isDrawSelectedBackground() ? Theme.chat_msgInViewsSelectedDrawable : Theme.chat_msgInViewsDrawable; + Drawable viewsDrawable = isDrawSelectionBackground() ? Theme.chat_msgInViewsSelectedDrawable : Theme.chat_msgInViewsDrawable; setDrawableBounds(viewsDrawable, timeX, layoutHeight - AndroidUtilities.dp(4.5f) - timeLayout.getHeight()); viewsDrawable.draw(canvas); } else { - Drawable viewsDrawable = isDrawSelectedBackground() ? Theme.chat_msgOutViewsSelectedDrawable : Theme.chat_msgOutViewsDrawable; + Drawable viewsDrawable = isDrawSelectionBackground() ? Theme.chat_msgOutViewsSelectedDrawable : Theme.chat_msgOutViewsDrawable; setDrawableBounds(viewsDrawable, timeX, layoutHeight - AndroidUtilities.dp(4.5f) - timeLayout.getHeight()); viewsDrawable.draw(canvas); } @@ -7749,7 +8062,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_msgMediaCheckDrawable.setAlpha(255); } } else { - Drawable drawable = isDrawSelectedBackground() ? Theme.chat_msgOutCheckSelectedDrawable : Theme.chat_msgOutCheckDrawable; + Drawable drawable = isDrawSelectionBackground() ? Theme.chat_msgOutCheckSelectedDrawable : Theme.chat_msgOutCheckDrawable; if (drawCheck1) { setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(22.5f) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(8.0f) - drawable.getIntrinsicHeight()); } else { @@ -7770,7 +8083,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_msgMediaHalfCheckDrawable.setAlpha(255); } } else { - Drawable drawable = isDrawSelectedBackground() ? Theme.chat_msgOutHalfCheckSelectedDrawable : Theme.chat_msgOutHalfCheckDrawable; + Drawable drawable = isDrawSelectionBackground() ? Theme.chat_msgOutHalfCheckSelectedDrawable : Theme.chat_msgOutHalfCheckDrawable; setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(18) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(8.0f) - drawable.getIntrinsicHeight()); drawable.draw(canvas); } @@ -7802,19 +8115,24 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } lastAnimationTime = newAnimationTime; - if (currentMessageObject.type == 1 || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) { + if (currentMessageObject.hadAnimationNotReadyLoading && photoImage.getVisible() && !currentMessageObject.needDrawBluredPreview() && (documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF)) { + AnimatedFileDrawable animation = photoImage.getAnimation(); + if (animation != null && animation.hasBitmap()) { + currentMessageObject.hadAnimationNotReadyLoading = false; + updateButtonState(false, true, false); + } + } + + if (currentMessageObject.type == 1 || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF) { if (photoImage.getVisible()) { if (!currentMessageObject.needDrawBluredPreview()) { if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) { - if (currentMessageObject.hadAnimationNotReadyLoading) { - AnimatedFileDrawable animation = photoImage.getAnimation(); - if (animation != null && animation.hasBitmap()) { - currentMessageObject.hadAnimationNotReadyLoading = false; - updateButtonState(false, true, false); - } - } int oldAlpha = ((BitmapDrawable) Theme.chat_msgMediaMenuDrawable).getPaint().getAlpha(); - Theme.chat_msgMediaMenuDrawable.setAlpha((int) (oldAlpha * controlsAlpha)); + if (drawPhotoCheckBox) { + Theme.chat_msgMediaMenuDrawable.setAlpha((int) (oldAlpha * controlsAlpha * (1.0f - checkBoxAnimationProgress))); + } else { + Theme.chat_msgMediaMenuDrawable.setAlpha((int) (oldAlpha * controlsAlpha)); + } setDrawableBounds(Theme.chat_msgMediaMenuDrawable, otherX = photoImage.getImageX() + photoImage.getImageWidth() - AndroidUtilities.dp(14), otherY = photoImage.getImageY() + AndroidUtilities.dp(8.1f)); Theme.chat_msgMediaMenuDrawable.draw(canvas); Theme.chat_msgMediaMenuDrawable.setAlpha(oldAlpha); @@ -7827,11 +8145,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate animatingNoSound = playing ? 1 : 2; animatingNoSoundProgress = playing ? 1.0f : 0.0f; } - if (buttonState == 1 || buttonState == 0 || buttonState == 3 || currentMessageObject.needDrawBluredPreview()) { - if (autoPlayingVideo) { + if (buttonState == 1 || buttonState == 2 || buttonState == 0 || buttonState == 3 || buttonState == -1 || currentMessageObject.needDrawBluredPreview()) { + if (autoPlayingMedia) { updatePlayingMessageProgress(); } - if (infoLayout != null && (!forceNotDrawTime || autoPlayingVideo || drawVideoImageButton)) { + if (infoLayout != null && (!forceNotDrawTime || autoPlayingMedia || drawVideoImageButton)) { float alpha = currentMessageObject.needDrawBluredPreview() && docTitleLayout == null ? 0 : animatingDrawVideoImageButtonProgress; Theme.chat_infoPaint.setColor(Theme.getColor(Theme.key_chat_mediaInfoText)); @@ -7839,7 +8157,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int y1 = photoImage.getImageY() + AndroidUtilities.dp(4); int imageW; - if (autoPlayingVideo && (!playing || animatingNoSound != 0)) { + if (autoPlayingMedia && (!playing || animatingNoSound != 0)) { imageW = (int) ((Theme.chat_msgNoSoundDrawable.getIntrinsicWidth() + AndroidUtilities.dp(4)) * animatingNoSoundProgress); } else { imageW = 0; @@ -7917,10 +8235,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (docTitleLayout != null) { if (currentMessageObject.isOutOwner()) { Theme.chat_locationTitlePaint.setColor(Theme.getColor(Theme.key_chat_messageTextOut)); - Theme.chat_locationAddressPaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_outVenueInfoSelectedText : Theme.key_chat_outVenueInfoText)); + Theme.chat_locationAddressPaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outVenueInfoSelectedText : Theme.key_chat_outVenueInfoText)); } else { Theme.chat_locationTitlePaint.setColor(Theme.getColor(Theme.key_chat_messageTextIn)); - Theme.chat_locationAddressPaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_inVenueInfoSelectedText : Theme.key_chat_inVenueInfoText)); + Theme.chat_locationAddressPaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_inVenueInfoSelectedText : Theme.key_chat_inVenueInfoText)); } if (currentMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { @@ -7976,10 +8294,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (currentMessageObject.type == 16) { if (currentMessageObject.isOutOwner()) { Theme.chat_audioTitlePaint.setColor(Theme.getColor(Theme.key_chat_messageTextOut)); - Theme.chat_contactPhonePaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_outTimeSelectedText : Theme.key_chat_outTimeText)); + Theme.chat_contactPhonePaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outTimeSelectedText : Theme.key_chat_outTimeText)); } else { Theme.chat_audioTitlePaint.setColor(Theme.getColor(Theme.key_chat_messageTextIn)); - Theme.chat_contactPhonePaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_inTimeSelectedText : Theme.key_chat_inTimeText)); + Theme.chat_contactPhonePaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_inTimeSelectedText : Theme.key_chat_inTimeText)); } forceNotDrawTime = true; int x; @@ -8009,7 +8327,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Drawable phone; if (currentMessageObject.isOutOwner()) { icon = Theme.chat_msgCallUpGreenDrawable; - phone = isDrawSelectedBackground() || otherPressed ? Theme.chat_msgOutCallSelectedDrawable : Theme.chat_msgOutCallDrawable; + phone = isDrawSelectionBackground() || otherPressed ? Theme.chat_msgOutCallSelectedDrawable : Theme.chat_msgOutCallDrawable; } else { TLRPC.PhoneCallDiscardReason reason = currentMessageObject.messageOwner.action.reason; if (reason instanceof TLRPC.TL_phoneCallDiscardReasonMissed || reason instanceof TLRPC.TL_phoneCallDiscardReasonBusy) { @@ -8017,7 +8335,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { icon = Theme.chat_msgCallDownGreenDrawable; } - phone = isDrawSelectedBackground() || otherPressed ? Theme.chat_msgInCallSelectedDrawable : Theme.chat_msgInCallDrawable; + phone = isDrawSelectionBackground() || otherPressed ? Theme.chat_msgInCallSelectedDrawable : Theme.chat_msgInCallDrawable; } setDrawableBounds(icon, x - AndroidUtilities.dp(3), AndroidUtilities.dp(36) + namesOffset); icon.draw(canvas); @@ -8030,7 +8348,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_audioTitlePaint.setColor(color); Theme.chat_audioPerformerPaint.setColor(color); Theme.chat_instantViewPaint.setColor(color); - color = Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_outTimeSelectedText : Theme.key_chat_outTimeText); + color = Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outTimeSelectedText : Theme.key_chat_outTimeText); Theme.chat_timePaint.setColor(color); Theme.chat_livePaint.setColor(color); } else { @@ -8038,7 +8356,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_audioTitlePaint.setColor(color); Theme.chat_audioPerformerPaint.setColor(color); Theme.chat_instantViewPaint.setColor(color); - color = Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_inTimeSelectedText : Theme.key_chat_inTimeText); + color = Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_inTimeSelectedText : Theme.key_chat_inTimeText); Theme.chat_timePaint.setColor(color); Theme.chat_livePaint.setColor(color); } @@ -8097,7 +8415,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (!pollVoted && !pollClosed || animatePollAnswerAlpha) { - if (isDrawSelectedBackground()) { + if (isDrawSelectionBackground()) { Theme.chat_replyLinePaint.setColor(Theme.getColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outVoiceSeekbarSelected : Theme.key_chat_inVoiceSeekbarSelected)); } else { Theme.chat_replyLinePaint.setColor(Theme.getColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outVoiceSeekbar : Theme.key_chat_inVoiceSeekbar)); @@ -8117,9 +8435,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.drawArc(instantButtonRect, voteRadOffset, voteCurrentCircleLength, false, Theme.chat_instantViewRectPaint); } else { if (currentMessageObject.isOutOwner()) { - Theme.chat_instantViewRectPaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_outMenuSelected : Theme.key_chat_outMenu)); + Theme.chat_instantViewRectPaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outMenuSelected : Theme.key_chat_outMenu)); } else { - Theme.chat_instantViewRectPaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_inMenuSelected : Theme.key_chat_inMenu)); + Theme.chat_instantViewRectPaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_inMenuSelected : Theme.key_chat_inMenu)); } if (animatePollAnswerAlpha) { float oldAlpha = Theme.chat_instantViewRectPaint.getAlpha() / 255.0f; @@ -8143,10 +8461,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (currentMessageObject.type == 12) { if (currentMessageObject.isOutOwner()) { Theme.chat_contactNamePaint.setColor(Theme.getColor(Theme.key_chat_outContactNameText)); - Theme.chat_contactPhonePaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_outContactPhoneSelectedText : Theme.key_chat_outContactPhoneText)); + Theme.chat_contactPhonePaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_outContactPhoneSelectedText : Theme.key_chat_outContactPhoneText)); } else { Theme.chat_contactNamePaint.setColor(Theme.getColor(Theme.key_chat_inContactNameText)); - Theme.chat_contactPhonePaint.setColor(Theme.getColor(isDrawSelectedBackground() ? Theme.key_chat_inContactPhoneSelectedText : Theme.key_chat_inContactPhoneText)); + Theme.chat_contactPhonePaint.setColor(Theme.getColor(isDrawSelectionBackground() ? Theme.key_chat_inContactPhoneSelectedText : Theme.key_chat_inContactPhoneText)); } if (titleLayout != null) { canvas.save(); @@ -8163,9 +8481,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Drawable menuDrawable; if (currentMessageObject.isOutOwner()) { - menuDrawable = isDrawSelectedBackground() ? Theme.chat_msgOutMenuSelectedDrawable : Theme.chat_msgOutMenuDrawable; + menuDrawable = isDrawSelectionBackground() ? Theme.chat_msgOutMenuSelectedDrawable : Theme.chat_msgOutMenuDrawable; } else { - menuDrawable = isDrawSelectedBackground() ? Theme.chat_msgInMenuSelectedDrawable : Theme.chat_msgInMenuDrawable; + menuDrawable = isDrawSelectionBackground() ? Theme.chat_msgInMenuSelectedDrawable : Theme.chat_msgInMenuDrawable; } setDrawableBounds(menuDrawable, otherX = photoImage.getImageX() + backgroundWidth - AndroidUtilities.dp(48), otherY = photoImage.getImageY() - AndroidUtilities.dp(5)); menuDrawable.draw(canvas); @@ -8210,6 +8528,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } videoRadialProgress.draw(canvas); } + if (drawPhotoCheckBox) { + int size = AndroidUtilities.dp(21); + photoCheckBox.setColor(null, null, currentMessageObject.isOutOwner() ? Theme.key_chat_outBubbleSelected : Theme.key_chat_inBubbleSelected); + photoCheckBox.setBounds(photoImage.getImageX2() - AndroidUtilities.dp(21 + 4), photoImage.getImageY() + AndroidUtilities.dp(4), size, size); + photoCheckBox.draw(canvas); + } } @Override @@ -8218,11 +8542,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } public MessageObject getMessageObject() { - return currentMessageObject; + return messageObjectToSet != null ? messageObjectToSet : currentMessageObject; } - public TLRPC.Document getStreamingVideo() { - return documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO ? documentAttach : null; + public TLRPC.Document getStreamingMedia() { + return documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF ? documentAttach : null; } public boolean isPinnedBottom() { @@ -8244,4 +8568,438 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public int getLayoutHeight() { return layoutHeight; } + + @Override + public boolean performAccessibilityAction(int action, Bundle arguments) { + if (action == AccessibilityNodeInfo.ACTION_CLICK) { + int icon = getIconForCurrentState(); + if (icon != MediaActionDrawable.ICON_NONE) { + didPressButton(true, false); + } else if (currentMessageObject.type == 16) { + delegate.didPressOther(this, otherX, otherY); + } else { + didClickedImage(); + } + return true; + } else if (action == R.id.acc_action_small_button) { + didPressMiniButton(true); + } else if (action == R.id.acc_action_msg_options) { + if (delegate != null) { + if (currentMessageObject.type == 16) + delegate.didLongPress(this, 0, 0); + else + delegate.didPressOther(this, otherX, otherY); + } + } + return super.performAccessibilityAction(action, arguments); + } + + @Override + public boolean onHoverEvent(MotionEvent event) { + int x = (int) event.getX(); + int y = (int) event.getY(); + if (event.getAction() == MotionEvent.ACTION_HOVER_ENTER || event.getAction() == MotionEvent.ACTION_HOVER_MOVE) { + for (int i = 0; i < accessibilityVirtualViewBounds.size(); i++) { + Rect rect = accessibilityVirtualViewBounds.valueAt(i); + if (rect.contains(x, y)) { + int id = accessibilityVirtualViewBounds.keyAt(i); + if (id != currentFocusedVirtualView) { + currentFocusedVirtualView = id; + sendAccessibilityEventForVirtualView(id, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); + } + return true; + } + } + } else if (event.getAction() == MotionEvent.ACTION_HOVER_EXIT) { + currentFocusedVirtualView = 0; + } + return super.onHoverEvent(event); + } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + } + + @Override + public AccessibilityNodeProvider getAccessibilityNodeProvider() { + return new MessageAccessibilityNodeProvider(); + } + + private void sendAccessibilityEventForVirtualView(int viewId, int eventType) { + AccessibilityManager am = (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); + if (am.isTouchExplorationEnabled()) { + AccessibilityEvent event = AccessibilityEvent.obtain(eventType); + event.setPackageName(getContext().getPackageName()); + event.setSource(ChatMessageCell.this, viewId); + getParent().requestSendAccessibilityEvent(ChatMessageCell.this, event); + } + } + + private class MessageAccessibilityNodeProvider extends AccessibilityNodeProvider { + + private final int LINK_IDS_START = 2000; + private final int BOT_BUTTONS_START = 1000; + private final int POLL_BUTTONS_START = 500; + private final int INSTANT_VIEW = 499; + private final int SHARE = 498; + private final int REPLY = 497; + private Path linkPath = new Path(); + private RectF rectF = new RectF(); + private Rect rect = new Rect(); + + @Override + public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) { + //FileLog.e("create node info "+virtualViewId); + int[] pos = {0, 0}; + getLocationOnScreen(pos); + if (virtualViewId == HOST_VIEW_ID) { + AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(ChatMessageCell.this); + onInitializeAccessibilityNodeInfo(info); + StringBuilder sb = new StringBuilder(); + if (isChat && currentUser!=null && !currentMessageObject.isOut()) { + sb.append(UserObject.getUserName(currentUser)); + sb.append('\n'); + } + if (!TextUtils.isEmpty(currentMessageObject.messageText)) + sb.append(currentMessageObject.messageText); + if (currentMessageObject.isMusic()) { + sb.append("\n"); + sb.append(LocaleController.formatString("AccDescrMusicInfo", R.string.AccDescrMusicInfo, currentMessageObject.getMusicAuthor(), currentMessageObject.getMusicTitle())); + }else if(currentMessageObject.isVoice() || currentMessageObject.isRoundVideo()){ + sb.append(", "); + sb.append(LocaleController.formatCallDuration(currentMessageObject.getDuration())); + if(currentMessageObject.isContentUnread()){ + sb.append(", "); + sb.append(LocaleController.getString("AccDescrMsgNotPlayed", R.string.AccDescrMsgNotPlayed)); + } + } + if (lastPoll != null) { + sb.append(", "); + sb.append(lastPoll.question); + sb.append(", "); + sb.append(LocaleController.getString("AnonymousPoll", R.string.AnonymousPoll)); + } + if (currentMessageObject.messageOwner.media != null && !TextUtils.isEmpty(currentMessageObject.caption)) { + sb.append("\n"); + sb.append(currentMessageObject.caption); + } + sb.append("\n"); + CharSequence time = LocaleController.getString("TodayAt", R.string.TodayAt) + " " + currentTimeString; + if (currentMessageObject.isOut()) { + sb.append(LocaleController.formatString("AccDescrSentDate", R.string.AccDescrSentDate, time)); + sb.append(", "); + sb.append(currentMessageObject.isUnread() ? LocaleController.getString("AccDescrMsgUnread", R.string.AccDescrMsgUnread) : LocaleController.getString("AccDescrMsgRead", R.string.AccDescrMsgRead)); + } else { + sb.append(LocaleController.formatString("AccDescrReceivedDate", R.string.AccDescrReceivedDate, time)); + } + info.setContentDescription(sb.toString()); + info.setEnabled(true); + if (Build.VERSION.SDK_INT >= 19) { + AccessibilityNodeInfo.CollectionItemInfo itemInfo = info.getCollectionItemInfo(); + if (itemInfo != null) { + info.setCollectionItemInfo(AccessibilityNodeInfo.CollectionItemInfo.obtain(itemInfo.getRowIndex(), 1, 0, 1, false)); + } + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + info.addAction(new AccessibilityNodeInfo.AccessibilityAction(R.id.acc_action_msg_options, LocaleController.getString("AccActionMessageOptions", R.string.AccActionMessageOptions))); + int icon = getIconForCurrentState(); + CharSequence actionLabel = null; + switch (icon) { + case MediaActionDrawable.ICON_PLAY: + actionLabel = LocaleController.getString("AccActionPlay", R.string.AccActionPlay); + break; + case MediaActionDrawable.ICON_PAUSE: + actionLabel = LocaleController.getString("AccActionPause", R.string.AccActionPause); + break; + case MediaActionDrawable.ICON_FILE: + actionLabel = LocaleController.getString("AccActionOpenFile", R.string.AccActionOpenFile); + break; + case MediaActionDrawable.ICON_DOWNLOAD: + actionLabel = LocaleController.getString("AccActionDownload", R.string.AccActionDownload); + break; + case MediaActionDrawable.ICON_CANCEL: + actionLabel = LocaleController.getString("AccActionCancelDownload", R.string.AccActionCancelDownload); + break; + default: + if (currentMessageObject.type == 16) { + actionLabel = LocaleController.getString("CallAgain", R.string.CallAgain); + } + } + info.addAction(new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK, actionLabel)); + info.addAction(new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_LONG_CLICK, LocaleController.getString("AccActionEnterSelectionMode", R.string.AccActionEnterSelectionMode))); + int smallIcon = getMiniIconForCurrentState(); + if (smallIcon == MediaActionDrawable.ICON_DOWNLOAD) { + info.addAction(new AccessibilityNodeInfo.AccessibilityAction(R.id.acc_action_small_button, LocaleController.getString("AccActionDownload", R.string.AccActionDownload))); + } + } else { + info.addAction(AccessibilityNodeInfo.ACTION_CLICK); + info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK); + } + + int i; + if (currentMessageObject.messageText instanceof Spannable) { + Spannable buffer = (Spannable) currentMessageObject.messageText; + CharacterStyle[] links = buffer.getSpans(0, buffer.length(), ClickableSpan.class); + i = 0; + for (CharacterStyle link : links) { + info.addChild(ChatMessageCell.this, LINK_IDS_START + i); + i++; + } + } + i = 0; + for (BotButton button : botButtons) { + info.addChild(ChatMessageCell.this, BOT_BUTTONS_START + i); + i++; + } + i = 0; + for (PollButton button : pollButtons) { + info.addChild(ChatMessageCell.this, POLL_BUTTONS_START + i); + i++; + } + if (drawInstantView) { + info.addChild(ChatMessageCell.this, INSTANT_VIEW); + } + if (drawShareButton) { + info.addChild(ChatMessageCell.this, SHARE); + } + if (replyNameLayout != null) { + info.addChild(ChatMessageCell.this, REPLY); + } + if (drawSelectionBackground || getBackground() != null) { + info.setSelected(true); + } + return info; + } else { + AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); + info.setSource(ChatMessageCell.this, virtualViewId); + info.setParent(ChatMessageCell.this); + info.setPackageName(getContext().getPackageName()); + if (virtualViewId >= LINK_IDS_START) { + Spannable buffer = (Spannable) currentMessageObject.messageText; + ClickableSpan link = getLinkById(virtualViewId); + if (link == null) { + return null; + } + int start = buffer.getSpanStart(link); + int end = buffer.getSpanEnd(link); + String content = buffer.subSequence(start, end).toString(); + info.setText(content); + for (MessageObject.TextLayoutBlock block : currentMessageObject.textLayoutBlocks) { + int length = block.textLayout.getText().length(); + if (block.charactersOffset <= start && block.charactersOffset + length >= end) { + block.textLayout.getSelectionPath(start - block.charactersOffset, end - block.charactersOffset, linkPath); + linkPath.computeBounds(rectF, true); + rect.set((int) rectF.left, (int) rectF.top, (int) rectF.right, (int) rectF.bottom); + rect.offset(0, (int) block.textYOffset); + rect.offset(textX, textY); + info.setBoundsInParent(rect); + if (accessibilityVirtualViewBounds.get(virtualViewId) == null) { + accessibilityVirtualViewBounds.put(virtualViewId, new Rect(rect)); + } + rect.offset(pos[0], pos[1]); + info.setBoundsInScreen(rect); + break; + } + } + + info.setClassName("android.widget.TextView"); + info.setEnabled(true); + info.setClickable(true); + info.setLongClickable(true); + info.addAction(AccessibilityNodeInfo.ACTION_CLICK); + info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK); + } else if (virtualViewId >= BOT_BUTTONS_START) { + int buttonIndex = virtualViewId - BOT_BUTTONS_START; + if (buttonIndex >= botButtons.size()) { + return null; + } + BotButton button = botButtons.get(buttonIndex); + info.setText(button.title.getText()); + info.setClassName("android.widget.Button"); + info.setEnabled(true); + info.setClickable(true); + info.addAction(AccessibilityNodeInfo.ACTION_CLICK); + + rect.set(button.x, button.y, button.x + button.width, button.y + button.height); + int addX; + if (currentMessageObject.isOutOwner()) { + addX = getMeasuredWidth() - widthForButtons - AndroidUtilities.dp(10); + } else { + addX = backgroundDrawableLeft + AndroidUtilities.dp(mediaBackground ? 1 : 7); + } + rect.offset(addX, layoutHeight); + info.setBoundsInParent(rect); + if (accessibilityVirtualViewBounds.get(virtualViewId) == null) { + accessibilityVirtualViewBounds.put(virtualViewId, new Rect(rect)); + } + rect.offset(pos[0], pos[1]); + info.setBoundsInScreen(rect); + } else if (virtualViewId >= POLL_BUTTONS_START) { + int buttonIndex = virtualViewId - POLL_BUTTONS_START; + if (buttonIndex >= pollButtons.size()) { + return null; + } + PollButton button = pollButtons.get(buttonIndex); + info.setText(button.title.getText()); + if (!pollVoted) { + info.setClassName("android.widget.Button"); + } else { + info.setText(info.getText() + ", " + button.percent + "%"); + } + info.setEnabled(true); + info.addAction(AccessibilityNodeInfo.ACTION_CLICK); + + int width = backgroundWidth - AndroidUtilities.dp(76); + rect.set(button.x, button.y, button.x + width, button.y + button.height); + info.setBoundsInParent(rect); + if (accessibilityVirtualViewBounds.get(virtualViewId) == null) { + accessibilityVirtualViewBounds.put(virtualViewId, new Rect(rect)); + } + rect.offset(pos[0], pos[1]); + info.setBoundsInScreen(rect); + + info.setClickable(true); + } else if (virtualViewId == INSTANT_VIEW) { + info.setClassName("android.widget.Button"); + info.setEnabled(true); + if (instantViewLayout != null) { + info.setText(instantViewLayout.getText()); + } + info.addAction(AccessibilityNodeInfo.ACTION_CLICK); + int textX = photoImage.getImageX(); + int instantY = getMeasuredHeight() - AndroidUtilities.dp(36 + 28); + int addX; + if (currentMessageObject.isOutOwner()) { + addX = getMeasuredWidth() - widthForButtons - AndroidUtilities.dp(10); + } else { + addX = backgroundDrawableLeft + AndroidUtilities.dp(mediaBackground ? 1 : 7); + } + rect.set(textX + addX, instantY, textX + instantWidth + addX, instantY + AndroidUtilities.dp(38)); + info.setBoundsInParent(rect); + if (accessibilityVirtualViewBounds.get(virtualViewId) == null || !accessibilityVirtualViewBounds.get(virtualViewId).equals(rect)) { + accessibilityVirtualViewBounds.put(virtualViewId, new Rect(rect)); + } + rect.offset(pos[0], pos[1]); + info.setBoundsInScreen(rect); + info.setClickable(true); + } else if (virtualViewId == SHARE) { + info.setClassName("android.widget.ImageButton"); + info.setEnabled(true); + if (isOpenChatByShare(currentMessageObject)) { + info.setContentDescription(LocaleController.getString("AccDescrOpenChat", R.string.AccDescrOpenChat)); + } else { + info.setContentDescription(LocaleController.getString("ShareFile", R.string.ShareFile)); + } + info.addAction(AccessibilityNodeInfo.ACTION_CLICK); + // } else if (drawShareButton && x >= shareStartX && x <= shareStartX + AndroidUtilities.dp(40) && y >= shareStartY && y <= shareStartY + AndroidUtilities.dp(32)) { + rect.set(shareStartX, shareStartY, shareStartX + AndroidUtilities.dp(40), shareStartY + AndroidUtilities.dp(32)); + info.setBoundsInParent(rect); + if (accessibilityVirtualViewBounds.get(virtualViewId) == null || !accessibilityVirtualViewBounds.get(virtualViewId).equals(rect)) { + accessibilityVirtualViewBounds.put(virtualViewId, new Rect(rect)); + } + rect.offset(pos[0], pos[1]); + info.setBoundsInScreen(rect); + info.setClickable(true); + } else if (virtualViewId == REPLY) { + info.setEnabled(true); + StringBuilder sb = new StringBuilder(); + sb.append(LocaleController.getString("Reply", R.string.Reply)); + sb.append(", "); + if (replyNameLayout != null) { + sb.append(replyNameLayout.getText()); + sb.append(", "); + } + if (replyTextLayout != null) { + sb.append(replyTextLayout.getText()); + } + info.setContentDescription(sb.toString()); + info.addAction(AccessibilityNodeInfo.ACTION_CLICK); + + rect.set(replyStartX, replyStartY, replyStartX + Math.max(replyNameWidth, replyTextWidth), replyStartY + AndroidUtilities.dp(35)); + info.setBoundsInParent(rect); + if (accessibilityVirtualViewBounds.get(virtualViewId) == null || !accessibilityVirtualViewBounds.get(virtualViewId).equals(rect)) { + accessibilityVirtualViewBounds.put(virtualViewId, new Rect(rect)); + } + rect.offset(pos[0], pos[1]); + info.setBoundsInScreen(rect); + info.setClickable(true); + } + info.setFocusable(true); + info.setVisibleToUser(true); + return info; + } + } + + @Override + public boolean performAction(int virtualViewId, int action, Bundle arguments) { + if (virtualViewId == HOST_VIEW_ID) { + performAccessibilityAction(action, arguments); + } else { + if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) { + sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); + } else if (action == AccessibilityNodeInfo.ACTION_CLICK) { + if (virtualViewId >= LINK_IDS_START) { + ClickableSpan link = getLinkById(virtualViewId); + if (link != null) { + delegate.didPressUrl(currentMessageObject, link, false); + sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_CLICKED); + } + } else if (virtualViewId >= BOT_BUTTONS_START) { + int buttonIndex = virtualViewId - BOT_BUTTONS_START; + if (buttonIndex >= botButtons.size()) { + return false; + } + BotButton button = botButtons.get(buttonIndex); + if (delegate != null) { + delegate.didPressBotButton(ChatMessageCell.this, button.button); + } + sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_CLICKED); + } else if (virtualViewId >= POLL_BUTTONS_START) { + int buttonIndex = virtualViewId - POLL_BUTTONS_START; + if (buttonIndex >= pollButtons.size()) { + return false; + } + PollButton button = pollButtons.get(buttonIndex); + if (delegate != null) { + delegate.didPressVoteButton(ChatMessageCell.this, button.answer); + } + sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_CLICKED); + } else if (virtualViewId == INSTANT_VIEW) { + if (delegate != null) { + delegate.didPressInstantButton(ChatMessageCell.this, drawInstantViewType); + } + } else if (virtualViewId == SHARE) { + if (delegate != null) { + delegate.didPressShare(ChatMessageCell.this); + } + } else if (virtualViewId == REPLY) { + if (delegate != null) { + delegate.didPressReplyMessage(ChatMessageCell.this, currentMessageObject.messageOwner.reply_to_msg_id); + } + } + } else if (action == AccessibilityNodeInfo.ACTION_LONG_CLICK) { + ClickableSpan link = getLinkById(virtualViewId); + if (link != null) { + delegate.didPressUrl(currentMessageObject, link, true); + sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); + } + } + } + return true; + } + + private ClickableSpan getLinkById(int id) { + id -= LINK_IDS_START; + if (!(currentMessageObject.messageText instanceof Spannable)) { + return null; + } + Spannable buffer = (Spannable) currentMessageObject.messageText; + ClickableSpan[] links = buffer.getSpans(0, buffer.length(), ClickableSpan.class); + if (links.length <= id) { + return null; + } + return links[id]; + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/CheckBoxCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/CheckBoxCell.java index 9e26424bc..c6ef54afa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/CheckBoxCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/CheckBoxCell.java @@ -13,6 +13,7 @@ import android.graphics.Canvas; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.TextView; @@ -125,4 +126,12 @@ public class CheckBoxCell extends FrameLayout { canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(20), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.CheckBox"); + info.setCheckable(true); + info.setChecked(isChecked()); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/CheckBoxUserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/CheckBoxUserCell.java index 35f9e3ceb..040e158e9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/CheckBoxUserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/CheckBoxUserCell.java @@ -18,6 +18,7 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; @@ -75,12 +76,8 @@ public class CheckBoxUserCell extends FrameLayout { currentUser = user; textView.setText(ContactsController.formatName(user.first_name, user.last_name)); checkBox.setChecked(checked, false); - TLRPC.FileLocation photo = null; avatarDrawable.setInfo(user); - if (user != null && user.photo != null) { - photo = user.photo.photo_small; - } - imageView.setImage(photo, "50_50", avatarDrawable, user); + imageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); needDivider = divider; setWillNotDraw(!divider); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ContextLinkCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ContextLinkCell.java index 6308d5b84..3f329bdb5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ContextLinkCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ContextLinkCell.java @@ -17,6 +17,7 @@ import android.text.TextUtils; import android.view.MotionEvent; import android.view.SoundEffectConstants; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.AccelerateInterpolator; import org.telegram.messenger.AndroidUtilities; @@ -25,11 +26,13 @@ import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.messenger.WebFile; @@ -70,6 +73,8 @@ public class ContextLinkCell extends View implements DownloadController.FileDown private boolean buttonPressed; private boolean needShadow; + private boolean canPreviewGif; + private int linkY; private StaticLayout linkLayout; @@ -81,6 +86,7 @@ public class ContextLinkCell extends View implements DownloadController.FileDown private TLRPC.BotInlineResult inlineResult; private TLRPC.Document documentAttach; + private TLRPC.Photo photoAttach; private TLRPC.PhotoSize currentPhotoObject; private int documentAttachType; private boolean mediaWebpage; @@ -101,9 +107,11 @@ public class ContextLinkCell extends View implements DownloadController.FileDown super(context); linkImageView = new ImageReceiver(this); + linkImageView.setUseSharedAnimationQueue(true); letterDrawable = new LetterDrawable(); radialProgress = new RadialProgress2(this); TAG = DownloadController.getInstance(currentAccount).generateObserverTag(); + setFocusable(true); } @SuppressLint("DrawAllocation") @@ -193,10 +201,8 @@ public class ContextLinkCell extends View implements DownloadController.FileDown if (inlineResult.content instanceof TLRPC.TL_webDocument) { if (inlineResult.type != null) { if (inlineResult.type.startsWith("gif")) { - if (documentAttachType != DOCUMENT_ATTACH_TYPE_GIF) { - webDocument = (TLRPC.TL_webDocument) inlineResult.content; - documentAttachType = DOCUMENT_ATTACH_TYPE_GIF; - } + webDocument = (TLRPC.TL_webDocument) inlineResult.content; + documentAttachType = DOCUMENT_ATTACH_TYPE_GIF; } else if (inlineResult.type.equals("photo")) { if (inlineResult.thumb instanceof TLRPC.TL_webDocument) { webDocument = (TLRPC.TL_webDocument) inlineResult.thumb; @@ -247,7 +253,7 @@ public class ContextLinkCell extends View implements DownloadController.FileDown w = currentPhotoObject.w; h = currentPhotoObject.h; } else if (inlineResult != null) { - int result[] = MessageObject.getInlineResultWidthAndHeight(inlineResult); + int[] result = MessageObject.getInlineResultWidthAndHeight(inlineResult); w = result[0]; h = result[1]; } @@ -274,15 +280,23 @@ public class ContextLinkCell extends View implements DownloadController.FileDown if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF) { if (documentAttach != null) { - linkImageView.setImage(documentAttach, null, currentPhotoObject, currentPhotoFilter, documentAttach.size, ext, parentObject, 0); + linkImageView.setImage(ImageLocation.getForDocument(documentAttach), null, ImageLocation.getForDocument(currentPhotoObject, documentAttach), currentPhotoFilter, documentAttach.size, ext, parentObject, 0); + } else if (webFile != null) { + linkImageView.setImage(ImageLocation.getForWebFile(webFile), null, ImageLocation.getForPhoto(currentPhotoObject, photoAttach), currentPhotoFilter, -1, ext, parentObject, 1); } else { - linkImageView.setImage(webFile != null ? webFile : urlLocation, null, null, currentPhotoObject, currentPhotoFilter, -1, ext, parentObject, 1); + linkImageView.setImage(ImageLocation.getForPath(urlLocation), null, ImageLocation.getForPhoto(currentPhotoObject, photoAttach), currentPhotoFilter, -1, ext, parentObject, 1); } } else { if (currentPhotoObject != null) { - linkImageView.setImage(currentPhotoObject, currentPhotoFilter, currentPhotoObjectThumb, currentPhotoFilterThumb, currentPhotoObject.size, ext, parentObject, 0); + if (documentAttach != null) { + linkImageView.setImage(ImageLocation.getForDocument(currentPhotoObject, documentAttach), currentPhotoFilter, ImageLocation.getForPhoto(currentPhotoObjectThumb, photoAttach), currentPhotoFilterThumb, currentPhotoObject.size, ext, parentObject, 0); + } else { + linkImageView.setImage(ImageLocation.getForPhoto(currentPhotoObject, photoAttach), currentPhotoFilter, ImageLocation.getForPhoto(currentPhotoObjectThumb, photoAttach), currentPhotoFilterThumb, currentPhotoObject.size, ext, parentObject, 0); + } + } else if (webFile != null) { + linkImageView.setImage(ImageLocation.getForWebFile(webFile), currentPhotoFilter, ImageLocation.getForPhoto(currentPhotoObjectThumb, photoAttach), currentPhotoFilterThumb, -1, ext, parentObject, 1); } else { - linkImageView.setImage(webFile != null ? webFile : urlLocation, currentPhotoFilter, null, currentPhotoObjectThumb, currentPhotoFilterThumb, -1, ext, parentObject, 1); + linkImageView.setImage(ImageLocation.getForPath(urlLocation), currentPhotoFilter, ImageLocation.getForPhoto(currentPhotoObjectThumb, photoAttach), currentPhotoFilterThumb, -1, ext, parentObject, 1); } } drawLinkImageView = true; @@ -398,10 +412,12 @@ public class ContextLinkCell extends View implements DownloadController.FileDown needDivider = divider; needShadow = shadow; parentObject = inlineResult = contextResult; - if (inlineResult != null && inlineResult.document != null) { + if (inlineResult != null) { documentAttach = inlineResult.document; + photoAttach = inlineResult.photo; } else { documentAttach = null; + photoAttach = null; } mediaWebpage = media; setAttachType(); @@ -413,8 +429,9 @@ public class ContextLinkCell extends View implements DownloadController.FileDown needDivider = divider; needShadow = false; inlineResult = null; - parentObject = "gif"; + parentObject = "gif" + document; documentAttach = document; + photoAttach = null; mediaWebpage = true; setAttachType(); requestLayout(); @@ -425,6 +442,10 @@ public class ContextLinkCell extends View implements DownloadController.FileDown return documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER; } + public boolean isGif() { + return documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && canPreviewGif; + } + public boolean showingBitmap() { return linkImageView.getBitmap() != null; } @@ -443,6 +464,14 @@ public class ContextLinkCell extends View implements DownloadController.FileDown invalidate(); } + public void setCanPreviewGif(boolean value) { + canPreviewGif = value; + } + + public boolean isCanPreviewGif() { + return canPreviewGif; + } + @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); @@ -825,4 +854,51 @@ public class ContextLinkCell extends View implements DownloadController.FileDown public int getObserverTag() { return TAG; } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + StringBuilder sbuf = new StringBuilder(); + switch (documentAttachType) { + case DOCUMENT_ATTACH_TYPE_DOCUMENT: + sbuf.append(LocaleController.getString("AttachDocument", R.string.AttachDocument)); + break; + case DOCUMENT_ATTACH_TYPE_GIF: + sbuf.append(LocaleController.getString("AttachGif", R.string.AttachGif)); + break; + case DOCUMENT_ATTACH_TYPE_AUDIO: + sbuf.append(LocaleController.getString("AttachAudio", R.string.AttachAudio)); + break; + case DOCUMENT_ATTACH_TYPE_VIDEO: + sbuf.append(LocaleController.getString("AttachVideo", R.string.AttachVideo)); + break; + case DOCUMENT_ATTACH_TYPE_MUSIC: + sbuf.append(LocaleController.getString("AttachMusic", R.string.AttachMusic)); + if (descriptionLayout != null && titleLayout != null) { + sbuf.append(", "); + sbuf.append(LocaleController.formatString("AccDescrMusicInfo", R.string.AccDescrMusicInfo, descriptionLayout.getText(), titleLayout.getText())); + } + break; + case DOCUMENT_ATTACH_TYPE_STICKER: + sbuf.append(LocaleController.getString("AttachSticker", R.string.AttachSticker)); + break; + case DOCUMENT_ATTACH_TYPE_PHOTO: + sbuf.append(LocaleController.getString("AttachPhoto", R.string.AttachPhoto)); + break; + case DOCUMENT_ATTACH_TYPE_GEO: + sbuf.append(LocaleController.getString("AttachLocation", R.string.AttachLocation)); + break; + default: + if (titleLayout != null && !TextUtils.isEmpty(titleLayout.getText())) { + sbuf.append(titleLayout.getText()); + } + if (descriptionLayout != null && !TextUtils.isEmpty(descriptionLayout.getText())) { + if (sbuf.length() > 0) + sbuf.append(", "); + sbuf.append(descriptionLayout.getText()); + } + break; + } + info.setText(sbuf); + } } 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 638545ccd..f7c4e9eb6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -8,10 +8,14 @@ package org.telegram.ui.Cells; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; +import android.graphics.Paint; import android.graphics.RectF; +import android.graphics.drawable.Drawable; import android.os.Build; +import android.os.SystemClock; import android.text.Layout; import android.text.SpannableStringBuilder; import android.text.Spanned; @@ -19,15 +23,29 @@ import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.text.style.ForegroundColorSpan; +import android.view.HapticFeedbackConstants; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.animation.Interpolator; + +import com.airbnb.lottie.LottieDrawable; +import com.airbnb.lottie.LottieProperty; +import com.airbnb.lottie.SimpleColorFilter; +import com.airbnb.lottie.model.KeyPath; +import com.airbnb.lottie.value.LottieValueCallback; import org.telegram.messenger.AndroidUtilities; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.ChatObject; import org.telegram.messenger.DataQuery; +import org.telegram.messenger.DialogObject; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; +import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserObject; import org.telegram.messenger.FileLog; +import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.ContactsController; import org.telegram.messenger.Emoji; @@ -37,7 +55,9 @@ import org.telegram.messenger.UserConfig; import org.telegram.messenger.ImageReceiver; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AvatarDrawable; -import org.telegram.ui.Components.GroupCreateCheckBox; +import org.telegram.ui.Components.CheckBox2; +import org.telegram.ui.Components.StaticLayoutEx; +import org.telegram.ui.Components.TypefaceSpan; import org.telegram.ui.DialogsActivity; import java.util.ArrayList; @@ -61,6 +81,8 @@ public class DialogCell extends BaseCell { private int currentAccount = UserConfig.selectedAccount; private CustomDialog customDialog; private long currentDialogId; + private int currentDialogFolderId; + private int currentDialogFolderDialogsCount; private int currentEditDate; private boolean isDialogCell; private int lastMessageDate; @@ -75,10 +97,31 @@ public class DialogCell extends BaseCell { private CharSequence lastMessageString; private int index; private int dialogsType; + private int folderId; private int messageId; + private boolean archiveHidden; + + private float cornerProgress; + private long lastUpdateTime; + private float onlineProgress; + + private float clipProgress; + private int topClip; + private int bottomClip; + private float translationX; + private boolean isSliding; + private Drawable translationDrawable; + private boolean translationAnimationStarted; + private boolean drawRevealBackground; + private float currentRevealProgress; + private float currentRevealBounceProgress; + private float archiveBackgroundProgress; private ImageReceiver avatarImage = new ImageReceiver(this); private AvatarDrawable avatarDrawable = new AvatarDrawable(); + private boolean animatingArchiveAvatar; + private float animatingArchiveAvatarProgress; + private BounceInterpolator interpolator = new BounceInterpolator(); private TLRPC.User user; private TLRPC.Chat chat; @@ -86,10 +129,11 @@ public class DialogCell extends BaseCell { private CharSequence lastPrintString; private TLRPC.DraftMessage draftMessage; - private GroupCreateCheckBox checkBox; + private CheckBox2 checkBox; public boolean useSeparator; public boolean fullSeparator; + public boolean fullSeparator2; private int nameLeft; private StaticLayout nameLayout; @@ -102,31 +146,39 @@ public class DialogCell extends BaseCell { private int nameLockTop; private int timeLeft; - private int timeTop = AndroidUtilities.dp(17); + private int timeTop; private StaticLayout timeLayout; private boolean drawCheck1; private boolean drawCheck2; private boolean drawClock; private int checkDrawLeft; - private int checkDrawTop = AndroidUtilities.dp(18); + private int checkDrawTop; private int halfCheckDrawLeft; - private int messageTop = AndroidUtilities.dp(40); + private int messageTop; private int messageLeft; private StaticLayout messageLayout; + private int messageNameTop; + private int messageNameLeft; + private StaticLayout messageNameLayout; + private boolean drawError; - private int errorTop = AndroidUtilities.dp(39); + private int errorTop; private int errorLeft; + private boolean attachedToWindow; + + private float reorderIconProgress; + private boolean drawReorder; private boolean drawPinBackground; private boolean drawPin; - private int pinTop = AndroidUtilities.dp(39); + private int pinTop; private int pinLeft; private boolean drawCount; - private int countTop = AndroidUtilities.dp(39); + private int countTop; private int countLeft; private int countWidth; private StaticLayout countLayout; @@ -134,41 +186,79 @@ public class DialogCell extends BaseCell { private boolean drawMention; private int mentionLeft; private int mentionWidth; + private StaticLayout mentionLayout; private boolean drawVerified; - private int avatarTop = AndroidUtilities.dp(10); + private boolean drawScam; private boolean isSelected; private RectF rect = new RectF(); + public class BounceInterpolator implements Interpolator { + + public float getInterpolation(float t) { + if (t < 0.33f) { + return 0.1f * (t / 0.33f); + } else { + t -= 0.33f; + if (t < 0.33f) { + return 0.1f - 0.15f * (t / 0.34f); + } else { + t -= 0.34f; + return -0.05f + 0.05f * (t / 0.33f); + } + } + } + } + public DialogCell(Context context, boolean needCheck) { super(context); Theme.createDialogsResources(context); - avatarImage.setRoundRadius(AndroidUtilities.dp(26)); + avatarImage.setRoundRadius(AndroidUtilities.dp(28)); if (needCheck) { - checkBox = new GroupCreateCheckBox(context); - checkBox.setVisibility(VISIBLE); + checkBox = new CheckBox2(context); + checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck); + checkBox.setSize(21); + checkBox.setDrawUnchecked(false); + checkBox.setDrawBackgroundAsArc(3); addView(checkBox); } } - public void setDialog(TLRPC.TL_dialog dialog, int i, int type) { + public void setDialog(TLRPC.Dialog dialog, int type, int folder) { currentDialogId = dialog.id; isDialogCell = true; - index = i; + if (dialog instanceof TLRPC.TL_dialogFolder) { + TLRPC.TL_dialogFolder dialogFolder = (TLRPC.TL_dialogFolder) dialog; + currentDialogFolderId = dialogFolder.folder.id; + } else { + currentDialogFolderId = 0; + } dialogsType = type; + folderId = folder; messageId = 0; update(0); + checkOnline(); + } + + public void setDialogIndex(int i) { + index = i; } public void setDialog(CustomDialog dialog) { customDialog = dialog; messageId = 0; update(0); + checkOnline(); + } + + private void checkOnline() { + boolean isOnline = user != null && !user.self && (user.status != null && user.status.expires > ConnectionsManager.getInstance(currentAccount).getCurrentTime() || MessagesController.getInstance(currentAccount).onlinePrivacy.containsKey(user.id)); + onlineProgress = isOnline ? 1.0f : 0.0f; } public void setDialog(long dialog_id, MessageObject messageObject, int date) { @@ -192,6 +282,10 @@ public class DialogCell extends BaseCell { return currentDialogId; } + public int getDialogIndex() { + return index; + } + public int getMessageId() { return messageId; } @@ -199,13 +293,37 @@ public class DialogCell extends BaseCell { @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); + isSliding = false; + drawRevealBackground = false; + currentRevealProgress = 0.0f; + attachedToWindow = false; + reorderIconProgress = drawPin && drawReorder ? 1.0f : 0.0f; avatarImage.onDetachedFromWindow(); + if (translationDrawable != null) { + if (translationDrawable instanceof LottieDrawable) { + LottieDrawable lottieDrawable = (LottieDrawable) translationDrawable; + lottieDrawable.stop(); + lottieDrawable.setProgress(0.0f); + lottieDrawable.setCallback(null); + } + translationDrawable = null; + translationAnimationStarted = false; + } } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); avatarImage.onAttachedToWindow(); + archiveHidden = SharedConfig.archiveHidden; + archiveBackgroundProgress = archiveHidden ? 0.0f : 1.0f; + avatarDrawable.setArchivedAvatarHiddenProgress(archiveBackgroundProgress); + clipProgress = 0.0f; + isSliding = false; + reorderIconProgress = drawPin && drawReorder ? 1.0f : 0.0f; + attachedToWindow = true; + cornerProgress = 0.0f; + setTranslationX(0); } @Override @@ -213,7 +331,9 @@ public class DialogCell extends BaseCell { if (checkBox != null) { checkBox.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(24), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(24), MeasureSpec.EXACTLY)); } - setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), AndroidUtilities.dp(72) + (useSeparator ? 1 : 0)); + setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 78 : 72) + (useSeparator ? 1 : 0)); + topClip = 0; + bottomClip = getMeasuredHeight(); } @Override @@ -222,8 +342,8 @@ public class DialogCell extends BaseCell { return; } if (checkBox != null) { - int x = LocaleController.isRTL ? (right - left) - AndroidUtilities.dp(42) : AndroidUtilities.dp(42); - int y = AndroidUtilities.dp(43); + int x = LocaleController.isRTL ? (right - left) - AndroidUtilities.dp(45) : AndroidUtilities.dp(45); + int y = AndroidUtilities.dp(46); checkBox.layout(x, y, x + checkBox.getMeasuredWidth(), y + checkBox.getMeasuredHeight()); } if (changed) { @@ -239,17 +359,83 @@ public class DialogCell extends BaseCell { return (unreadCount != 0 || markUnread) && !dialogMuted; } + private CharSequence formatArchivedDialogNames() { + ArrayList dialogs = MessagesController.getInstance(currentAccount).getDialogs(currentDialogFolderId); + currentDialogFolderDialogsCount = dialogs.size(); + SpannableStringBuilder builder = new SpannableStringBuilder(); + for (int a = 0, N = dialogs.size(); a < N; a++) { + TLRPC.Dialog dialog = dialogs.get(a); + TLRPC.User currentUser = null; + TLRPC.Chat currentChat = null; + if (DialogObject.isSecretDialogId(dialog.id)) { + TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance(currentAccount).getEncryptedChat((int) dialog.id); + if (encryptedChat != null) { + currentUser = MessagesController.getInstance(currentAccount).getUser(encryptedChat.user_id); + } + } else { + int lowerId = (int) dialog.id; + if (lowerId > 0) { + currentUser = MessagesController.getInstance(currentAccount).getUser(lowerId); + } else { + currentChat = MessagesController.getInstance(currentAccount).getChat(-lowerId); + } + } + String title; + if (currentChat != null) { + title = currentChat.title.replace('\n', ' '); + } else if (currentUser != null) { + if (UserObject.isDeleted(currentUser)) { + title = LocaleController.getString("HiddenName", R.string.HiddenName); + } else { + title = ContactsController.formatName(currentUser.first_name, currentUser.last_name).replace('\n', ' '); + } + } else { + continue; + } + if (builder.length() > 0) { + builder.append(", "); + } + int boldStart = builder.length(); + int boldEnd = boldStart + title.length(); + builder.append(title); + if (dialog.unread_count > 0) { + builder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf"), 0, Theme.getColor(Theme.key_chats_nameArchived)), boldStart, boldEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + if (builder.length() > 150) { + break; + } + } + return Emoji.replaceEmoji(builder, Theme.dialogs_messagePaint.getFontMetricsInt(), AndroidUtilities.dp(17), false); + } + public void buildLayout() { + if (SharedConfig.useThreeLinesLayout) { + Theme.dialogs_namePaint.setTextSize(AndroidUtilities.dp(16)); + Theme.dialogs_nameEncryptedPaint.setTextSize(AndroidUtilities.dp(16)); + Theme.dialogs_messagePaint.setTextSize(AndroidUtilities.dp(15)); + Theme.dialogs_messagePrintingPaint.setTextSize(AndroidUtilities.dp(15)); + + Theme.dialogs_messagePaint.setColor(Theme.dialogs_messagePaint.linkColor = Theme.getColor(Theme.key_chats_message_threeLines)); + } else { + Theme.dialogs_namePaint.setTextSize(AndroidUtilities.dp(17)); + Theme.dialogs_nameEncryptedPaint.setTextSize(AndroidUtilities.dp(17)); + Theme.dialogs_messagePaint.setTextSize(AndroidUtilities.dp(16)); + Theme.dialogs_messagePrintingPaint.setTextSize(AndroidUtilities.dp(16)); + + Theme.dialogs_messagePaint.setColor(Theme.dialogs_messagePaint.linkColor = Theme.getColor(Theme.key_chats_message)); + } + + currentDialogFolderDialogsCount = 0; String nameString = ""; String timeString = ""; String countString = null; String mentionString = null; CharSequence messageString = ""; + CharSequence messageNameString = null; CharSequence printingString = null; if (isDialogCell) { printingString = MessagesController.getInstance(currentAccount).printingStrings.get(currentDialogId); } - TextPaint currentNamePaint = Theme.dialogs_namePaint; TextPaint currentMessagePaint = Theme.dialogs_messagePaint; boolean checkMessage = true; @@ -258,15 +444,29 @@ public class DialogCell extends BaseCell { drawNameLock = false; drawNameBot = false; drawVerified = false; + drawScam = false; drawPinBackground = false; boolean showChecks = !UserObject.isUserSelf(user); boolean drawTime = true; String messageFormat; + boolean hasNameInMessage; if (Build.VERSION.SDK_INT >= 18) { - messageFormat = "%s: \u2068%s\u2069"; + if (!SharedConfig.useThreeLinesLayout || currentDialogFolderId != 0) { + messageFormat = "%2$s: \u2068%1$s\u2069"; + hasNameInMessage = true; + } else { + messageFormat = "\u2068%s\u2069"; + hasNameInMessage = false; + } } else { - messageFormat = "%s: %s"; + if (!SharedConfig.useThreeLinesLayout || currentDialogFolderId != 0) { + messageFormat = "%2$s: %1$s"; + hasNameInMessage = true; + } else { + messageFormat = "%1$s"; + hasNameInMessage = false; + } } lastMessageString = message != null ? message.messageText : null; @@ -274,52 +474,83 @@ public class DialogCell extends BaseCell { if (customDialog != null) { if (customDialog.type == 2) { drawNameLock = true; - nameLockTop = AndroidUtilities.dp(16.5f); - if (!LocaleController.isRTL) { - nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); - nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + Theme.dialogs_lockDrawable.getIntrinsicWidth(); + if (SharedConfig.useThreeLinesLayout) { + nameLockTop = AndroidUtilities.dp(12.5f); + if (!LocaleController.isRTL) { + nameLockLeft = AndroidUtilities.dp(72 + 6); + nameLeft = AndroidUtilities.dp(72 + 10) + Theme.dialogs_lockDrawable.getIntrinsicWidth(); + } else { + nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(72 + 6) - Theme.dialogs_lockDrawable.getIntrinsicWidth(); + nameLeft = AndroidUtilities.dp(22); + } } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline) - Theme.dialogs_lockDrawable.getIntrinsicWidth(); - nameLeft = AndroidUtilities.dp(14); + nameLockTop = AndroidUtilities.dp(16.5f); + if (!LocaleController.isRTL) { + nameLockLeft = AndroidUtilities.dp(72 + 4); + nameLeft = AndroidUtilities.dp(72 + 8) + Theme.dialogs_lockDrawable.getIntrinsicWidth(); + } else { + nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(72 + 4) - Theme.dialogs_lockDrawable.getIntrinsicWidth(); + nameLeft = AndroidUtilities.dp(18); + } } } else { drawVerified = customDialog.verified; - if (customDialog.type == 1) { + if (SharedConfig.drawDialogIcons && customDialog.type == 1) { drawNameGroup = true; - nameLockTop = AndroidUtilities.dp(17.5f); - if (!LocaleController.isRTL) { - nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); - nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); + if (SharedConfig.useThreeLinesLayout) { + nameLockTop = AndroidUtilities.dp(13.5f); + if (!LocaleController.isRTL) { + nameLockLeft = AndroidUtilities.dp(72 + 6); + nameLeft = AndroidUtilities.dp(72 + 10) + (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); + } else { + nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(72 + 6) - (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); + nameLeft = AndroidUtilities.dp(22); + } } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline) - (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); - nameLeft = AndroidUtilities.dp(14); + if (!LocaleController.isRTL) { + nameLockTop = AndroidUtilities.dp(17.5f); + nameLockLeft = AndroidUtilities.dp(72 + 4); + nameLeft = AndroidUtilities.dp(72 + 8) + (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); + } else { + nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(72 + 4) - (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); + nameLeft = AndroidUtilities.dp(18); + } } } else { - if (!LocaleController.isRTL) { - nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); + if (SharedConfig.useThreeLinesLayout) { + if (!LocaleController.isRTL) { + nameLeft = AndroidUtilities.dp(72 + 6); + } else { + nameLeft = AndroidUtilities.dp(22); + } } else { - nameLeft = AndroidUtilities.dp(14); + if (!LocaleController.isRTL) { + nameLeft = AndroidUtilities.dp(72 + 4); + } else { + nameLeft = AndroidUtilities.dp(18); + } } } } if (customDialog.type == 1) { - String name = LocaleController.getString("FromYou", R.string.FromYou); + messageNameString = LocaleController.getString("FromYou", R.string.FromYou); checkMessage = false; SpannableStringBuilder stringBuilder; if (customDialog.isMedia) { currentMessagePaint = Theme.dialogs_messagePrintingPaint; - stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, name, message.messageText)); - stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chats_attachMessage)), name.length() + 2, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, message.messageText)); + stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chats_attachMessage)), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } else { String mess = customDialog.message; if (mess.length() > 150) { mess = mess.substring(0, 150); } - stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, name, mess.replace('\n', ' '))); - } - if (stringBuilder.length() > 0) { - stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chats_nameMessage)), 0, name.length() + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + if (SharedConfig.useThreeLinesLayout) { + stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, mess, messageNameString)); + } else { + stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, mess.replace('\n', ' '), messageNameString)); + } } messageString = Emoji.replaceEmoji(stringBuilder, Theme.dialogs_messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); } else { @@ -350,57 +581,117 @@ public class DialogCell extends BaseCell { drawError = false; } nameString = customDialog.name; - if (customDialog.type == 2) { - currentNamePaint = Theme.dialogs_nameEncryptedPaint; - } } else { - if (encryptedChat != null) { - drawNameLock = true; - nameLockTop = AndroidUtilities.dp(16.5f); + if (SharedConfig.useThreeLinesLayout) { if (!LocaleController.isRTL) { - nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); - nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + Theme.dialogs_lockDrawable.getIntrinsicWidth(); + nameLeft = AndroidUtilities.dp(72 + 6); } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline) - Theme.dialogs_lockDrawable.getIntrinsicWidth(); - nameLeft = AndroidUtilities.dp(14); + nameLeft = AndroidUtilities.dp(22); } } else { - if (chat != null) { - if (chat.id < 0 || ChatObject.isChannel(chat) && !chat.megagroup) { - drawNameBroadcast = true; - nameLockTop = AndroidUtilities.dp(16.5f); - } else { - drawNameGroup = true; - nameLockTop = AndroidUtilities.dp(17.5f); - } - drawVerified = chat.verified; - - if (!LocaleController.isRTL) { - nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); - nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); - } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline) - (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); - nameLeft = AndroidUtilities.dp(14); - } + if (!LocaleController.isRTL) { + nameLeft = AndroidUtilities.dp(72 + 4); } else { - if (!LocaleController.isRTL) { - nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); + nameLeft = AndroidUtilities.dp(18); + } + } + + if (encryptedChat != null) { + if (currentDialogFolderId == 0) { + drawNameLock = true; + if (SharedConfig.useThreeLinesLayout) { + nameLockTop = AndroidUtilities.dp(12.5f); + if (!LocaleController.isRTL) { + nameLockLeft = AndroidUtilities.dp(72 + 6); + nameLeft = AndroidUtilities.dp(72 + 10) + Theme.dialogs_lockDrawable.getIntrinsicWidth(); + } else { + nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(72 + 6) - Theme.dialogs_lockDrawable.getIntrinsicWidth(); + nameLeft = AndroidUtilities.dp(22); + } } else { - nameLeft = AndroidUtilities.dp(14); + nameLockTop = AndroidUtilities.dp(16.5f); + if (!LocaleController.isRTL) { + nameLockLeft = AndroidUtilities.dp(72 + 4); + nameLeft = AndroidUtilities.dp(72 + 8) + Theme.dialogs_lockDrawable.getIntrinsicWidth(); + } else { + nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(72 + 4) - Theme.dialogs_lockDrawable.getIntrinsicWidth(); + nameLeft = AndroidUtilities.dp(18); + } } - if (user != null) { - if (user.bot) { - drawNameBot = true; - nameLockTop = AndroidUtilities.dp(16.5f); - if (!LocaleController.isRTL) { - nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); - nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + Theme.dialogs_botDrawable.getIntrinsicWidth(); + } + } else { + if (currentDialogFolderId == 0) { + if (chat != null) { + if (chat.scam) { + drawScam = true; + Theme.dialogs_scamDrawable.checkText(); + } else { + drawVerified = chat.verified; + } + if (SharedConfig.drawDialogIcons) { + if (SharedConfig.useThreeLinesLayout) { + if (chat.id < 0 || ChatObject.isChannel(chat) && !chat.megagroup) { + drawNameBroadcast = true; + nameLockTop = AndroidUtilities.dp(12.5f); + } else { + drawNameGroup = true; + nameLockTop = AndroidUtilities.dp(13.5f); + } + + if (!LocaleController.isRTL) { + nameLockLeft = AndroidUtilities.dp(72 + 6); + nameLeft = AndroidUtilities.dp(72 + 10) + (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); + } else { + nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(72 + 6) - (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); + nameLeft = AndroidUtilities.dp(22); + } } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline) - Theme.dialogs_botDrawable.getIntrinsicWidth(); - nameLeft = AndroidUtilities.dp(14); + if (chat.id < 0 || ChatObject.isChannel(chat) && !chat.megagroup) { + drawNameBroadcast = true; + nameLockTop = AndroidUtilities.dp(16.5f); + } else { + drawNameGroup = true; + nameLockTop = AndroidUtilities.dp(17.5f); + } + + if (!LocaleController.isRTL) { + nameLockLeft = AndroidUtilities.dp(72 + 4); + nameLeft = AndroidUtilities.dp(72 + 8) + (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); + } else { + nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(72 + 4) - (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); + nameLeft = AndroidUtilities.dp(18); + } + } + } + } else if (user != null) { + if (user.scam) { + drawScam = true; + Theme.dialogs_scamDrawable.checkText(); + } else { + drawVerified = user.verified; + } + if (SharedConfig.drawDialogIcons && user.bot) { + drawNameBot = true; + if (SharedConfig.useThreeLinesLayout) { + nameLockTop = AndroidUtilities.dp(12.5f); + if (!LocaleController.isRTL) { + nameLockLeft = AndroidUtilities.dp(72 + 6); + nameLeft = AndroidUtilities.dp(72 + 10) + Theme.dialogs_botDrawable.getIntrinsicWidth(); + } else { + nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(72 + 6) - Theme.dialogs_botDrawable.getIntrinsicWidth(); + nameLeft = AndroidUtilities.dp(22); + } + } else { + nameLockTop = AndroidUtilities.dp(16.5f); + if (!LocaleController.isRTL) { + nameLockLeft = AndroidUtilities.dp(72 + 4); + nameLeft = AndroidUtilities.dp(72 + 8) + Theme.dialogs_botDrawable.getIntrinsicWidth(); + } else { + nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(72 + 4) - Theme.dialogs_botDrawable.getIntrinsicWidth(); + nameLeft = AndroidUtilities.dp(18); + } } } - drawVerified = user.verified; } } } @@ -426,22 +717,29 @@ public class DialogCell extends BaseCell { currentMessagePaint = Theme.dialogs_messagePrintingPaint; } else { lastPrintString = null; - if (draftMessage != null) { checkMessage = false; + messageNameString = LocaleController.getString("Draft", R.string.Draft); if (TextUtils.isEmpty(draftMessage.message)) { - String draftString = LocaleController.getString("Draft", R.string.Draft); - SpannableStringBuilder stringBuilder = SpannableStringBuilder.valueOf(draftString); - stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chats_draft)), 0, draftString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - messageString = stringBuilder; + if (SharedConfig.useThreeLinesLayout) { + messageString = ""; + } else { + SpannableStringBuilder stringBuilder = SpannableStringBuilder.valueOf(messageNameString); + stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chats_draft)), 0, messageNameString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + messageString = stringBuilder; + } } else { String mess = draftMessage.message; if (mess.length() > 150) { mess = mess.substring(0, 150); } - String draftString = LocaleController.getString("Draft", R.string.Draft); - SpannableStringBuilder stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, draftString, mess.replace('\n', ' '))); - stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chats_draft)), 0, draftString.length() + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + SpannableStringBuilder stringBuilder; + if (SharedConfig.useThreeLinesLayout) { + stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, mess.replace('\n', ' '), messageNameString)); + } else { + stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, mess.replace('\n', ' '), messageNameString)); + stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chats_draft)), 0, messageNameString.length() + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } messageString = Emoji.replaceEmoji(stringBuilder, Theme.dialogs_messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); } } else { @@ -487,6 +785,9 @@ public class DialogCell extends BaseCell { messageString = LocaleController.getString("SavedMessagesInfo", R.string.SavedMessagesInfo); showChecks = false; drawTime = false; + } else if (!SharedConfig.useThreeLinesLayout && currentDialogFolderId != 0) { + checkMessage = false; + messageString = formatArchivedDialogNames(); } else if (message.messageOwner instanceof TLRPC.TL_messageService) { if (ChatObject.isChannel(chat) && (message.messageOwner.action instanceof TLRPC.TL_messageActionHistoryClear || message.messageOwner.action instanceof TLRPC.TL_messageActionChannelMigrateFrom)) { @@ -498,15 +799,22 @@ public class DialogCell extends BaseCell { currentMessagePaint = Theme.dialogs_messagePrintingPaint; } else { if (chat != null && chat.id > 0 && fromChat == null) { - String name; if (message.isOutOwner()) { - name = LocaleController.getString("FromYou", R.string.FromYou); + messageNameString = LocaleController.getString("FromYou", R.string.FromYou); } else if (fromUser != null) { - name = UserObject.getFirstName(fromUser).replace("\n", ""); + if (SharedConfig.useThreeLinesLayout) { + if (UserObject.isDeleted(fromUser)) { + messageNameString = LocaleController.getString("HiddenName", R.string.HiddenName); + } else { + messageNameString = ContactsController.formatName(fromUser.first_name, fromUser.last_name).replace("\n", ""); + } + } else { + messageNameString = UserObject.getFirstName(fromUser).replace("\n", ""); + } } else if (fromChat != null) { - name = fromChat.title.replace("\n", ""); + messageNameString = fromChat.title.replace("\n", ""); } else { - name = "DELETED"; + messageNameString = "DELETED"; } checkMessage = false; SpannableStringBuilder stringBuilder; @@ -515,36 +823,58 @@ public class DialogCell extends BaseCell { if (mess.length() > 150) { mess = mess.substring(0, 150); } - stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, name, mess.replace('\n', ' '))); + String emoji; + if (message.isVideo()) { + emoji = "\uD83D\uDCF9 "; + } else if (message.isVoice()) { + emoji = "\uD83C\uDFA4 "; + } else if (message.isMusic()) { + emoji = "\uD83C\uDFA7 "; + } else if (message.isPhoto()) { + emoji = "\uD83D\uDDBC "; + } else { + emoji = "\uD83D\uDCCE "; + } + stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, emoji + mess.replace('\n', ' '), messageNameString)); } else if (message.messageOwner.media != null && !message.isMediaEmpty()) { currentMessagePaint = Theme.dialogs_messagePrintingPaint; + CharSequence innerMessage; if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { if (Build.VERSION.SDK_INT >= 18) { - stringBuilder = SpannableStringBuilder.valueOf(String.format("%s: \uD83C\uDFAE \u2068%s\u2069", name, message.messageOwner.media.game.title)); + innerMessage = String.format("\uD83C\uDFAE \u2068%s\u2069", message.messageOwner.media.game.title); } else { - stringBuilder = SpannableStringBuilder.valueOf(String.format("%s: \uD83C\uDFAE %s", name, message.messageOwner.media.game.title)); + innerMessage = String.format("\uD83C\uDFAE %s", message.messageOwner.media.game.title); } } else if (message.type == 14) { if (Build.VERSION.SDK_INT >= 18) { - stringBuilder = SpannableStringBuilder.valueOf(String.format("%s: \uD83C\uDFA7 \u2068%s - %s\u2069", name, message.getMusicAuthor(), message.getMusicTitle())); + innerMessage = String.format("\uD83C\uDFA7 \u2068%s - %s\u2069", message.getMusicAuthor(), message.getMusicTitle()); } else { - stringBuilder = SpannableStringBuilder.valueOf(String.format("%s: \uD83C\uDFA7 %s - %s", name, message.getMusicAuthor(), message.getMusicTitle())); + innerMessage = String.format("\uD83C\uDFA7 %s - %s", message.getMusicAuthor(), message.getMusicTitle()); } } else { - stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, name, message.messageText)); + innerMessage = message.messageText; + } + stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, innerMessage, messageNameString)); + try { + stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chats_attachMessage)), hasNameInMessage ? messageNameString.length() + 2 : 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } catch (Exception e) { + FileLog.e(e); } - stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chats_attachMessage)), name.length() + 2, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } else if (message.messageOwner.message != null) { String mess = message.messageOwner.message; if (mess.length() > 150) { mess = mess.substring(0, 150); } - stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, name, mess.replace('\n', ' '))); + stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, mess.replace('\n', ' '), messageNameString)); } else { stringBuilder = SpannableStringBuilder.valueOf(""); } - if (stringBuilder.length() > 0) { - stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chats_nameMessage)), 0, name.length() + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + if (!SharedConfig.useThreeLinesLayout || currentDialogFolderId != 0 && stringBuilder.length() > 0) { + try { + stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chats_nameMessage)), 0, messageNameString.length() + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } catch (Exception e) { + FileLog.e(e); + } } messageString = Emoji.replaceEmoji(stringBuilder, Theme.dialogs_messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); } else { @@ -553,7 +883,19 @@ public class DialogCell extends BaseCell { } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaDocument && message.messageOwner.media.document instanceof TLRPC.TL_documentEmpty && message.messageOwner.media.ttl_seconds != 0) { messageString = LocaleController.getString("AttachVideoExpired", R.string.AttachVideoExpired); } else if (message.caption != null) { - messageString = message.caption; + String emoji; + if (message.isVideo()) { + emoji = "\uD83D\uDCF9 "; + } else if (message.isVoice()) { + emoji = "\uD83C\uDFA4 "; + } else if (message.isMusic()) { + emoji = "\uD83C\uDFA7 "; + } else if (message.isPhoto()) { + emoji = "\uD83D\uDDBC "; + } else { + emoji = "\uD83D\uDCCE "; + } + messageString = emoji + message.caption; } else { if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { messageString = "\uD83C\uDFAE " + message.messageOwner.media.game.title; @@ -568,6 +910,9 @@ public class DialogCell extends BaseCell { } } } + if (currentDialogFolderId != 0) { + messageNameString = formatArchivedDialogNames(); + } } } } @@ -588,26 +933,43 @@ public class DialogCell extends BaseCell { drawMention = false; drawError = false; } else { - if (clearingDialog) { - drawCount = false; - showChecks = false; - } else if (unreadCount != 0 && (unreadCount != 1 || unreadCount != mentionCount || message == null || !message.messageOwner.mentioned)) { - drawCount = true; - countString = String.format("%d", unreadCount); - } else if (markUnread) { - drawCount = true; - countString = ""; + if (currentDialogFolderId != 0) { + if (unreadCount + mentionCount > 0) { + if (unreadCount > mentionCount) { + drawCount = true; + drawMention = false; + countString = String.format("%d", unreadCount + mentionCount); + } else { + drawCount = false; + drawMention = true; + mentionString = String.format("%d", unreadCount + mentionCount); + } + } else { + drawCount = false; + drawMention = false; + } } else { - drawCount = false; - } - if (mentionCount != 0) { - drawMention = true; - mentionString = "@"; - } else { - drawMention = false; + if (clearingDialog) { + drawCount = false; + showChecks = false; + } else if (unreadCount != 0 && (unreadCount != 1 || unreadCount != mentionCount || message == null || !message.messageOwner.mentioned)) { + drawCount = true; + countString = String.format("%d", unreadCount); + } else if (markUnread) { + drawCount = true; + countString = ""; + } else { + drawCount = false; + } + if (mentionCount != 0) { + drawMention = true; + mentionString = "@"; + } else { + drawMention = false; + } } - if (message.isOut() && draftMessage == null && showChecks) { + if (message.isOut() && draftMessage == null && showChecks && !(message.messageOwner.action instanceof TLRPC.TL_messageActionHistoryClear)) { if (message.isSending()) { drawCheck1 = false; drawCheck2 = false; @@ -639,34 +1001,35 @@ public class DialogCell extends BaseCell { timeString = LocaleController.getString("UseProxySponsor", R.string.UseProxySponsor); } - if (chat != null) { - nameString = chat.title; - } else if (user != null) { - if (UserObject.isUserSelf(user)) { - if (dialogsType == 3) { - drawPinBackground = true; - } - nameString = LocaleController.getString("SavedMessages", R.string.SavedMessages); - } else if (user.id / 1000 != 777 && user.id / 1000 != 333 && ContactsController.getInstance(currentAccount).contactsDict.get(user.id) == null) { - if (ContactsController.getInstance(currentAccount).contactsDict.size() == 0 && (!ContactsController.getInstance(currentAccount).contactsLoaded || ContactsController.getInstance(currentAccount).isLoadingContacts())) { - nameString = UserObject.getUserName(user); - } else { - if (user.phone != null && user.phone.length() != 0) { - nameString = PhoneFormat.getInstance().format("+" + user.phone); - } else { - nameString = UserObject.getUserName(user); + if (currentDialogFolderId != 0) { + nameString = LocaleController.getString("ArchivedChats", R.string.ArchivedChats); + } else { + if (chat != null) { + nameString = chat.title; + } else if (user != null) { + if (UserObject.isUserSelf(user)) { + if (dialogsType == 3) { + drawPinBackground = true; } + nameString = LocaleController.getString("SavedMessages", R.string.SavedMessages); + } else if (user.id / 1000 != 777 && user.id / 1000 != 333 && ContactsController.getInstance(currentAccount).contactsDict.get(user.id) == null) { + if (ContactsController.getInstance(currentAccount).contactsDict.size() == 0 && (!ContactsController.getInstance(currentAccount).contactsLoaded || ContactsController.getInstance(currentAccount).isLoadingContacts())) { + nameString = UserObject.getUserName(user); + } else { + if (user.phone != null && user.phone.length() != 0) { + nameString = PhoneFormat.getInstance().format("+" + user.phone); + } else { + nameString = UserObject.getUserName(user); + } + } + } else { + nameString = UserObject.getUserName(user); } - } else { - nameString = UserObject.getUserName(user); } - if (encryptedChat != null) { - currentNamePaint = Theme.dialogs_nameEncryptedPaint; + if (nameString.length() == 0) { + nameString = LocaleController.getString("HiddenName", R.string.HiddenName); } } - if (nameString.length() == 0) { - nameString = LocaleController.getString("HiddenName", R.string.HiddenName); - } } int timeWidth; @@ -689,7 +1052,7 @@ public class DialogCell extends BaseCell { if (!LocaleController.isRTL) { nameWidth = getMeasuredWidth() - nameLeft - AndroidUtilities.dp(14) - timeWidth; } else { - nameWidth = getMeasuredWidth() - nameLeft - AndroidUtilities.dp(AndroidUtilities.leftBaseline) - timeWidth; + nameWidth = getMeasuredWidth() - nameLeft - AndroidUtilities.dp(77) - timeWidth; nameLeft += timeWidth; } if (drawNameLock) { @@ -733,7 +1096,7 @@ public class DialogCell extends BaseCell { } } - if (dialogMuted && !drawVerified) { + if (dialogMuted && !drawVerified && !drawScam) { int w = AndroidUtilities.dp(6) + Theme.dialogs_muteDrawable.getIntrinsicWidth(); nameWidth -= w; if (LocaleController.isRTL) { @@ -745,26 +1108,69 @@ public class DialogCell extends BaseCell { if (LocaleController.isRTL) { nameLeft += w; } + } else if (drawScam) { + int w = AndroidUtilities.dp(6) + Theme.dialogs_scamDrawable.getIntrinsicWidth(); + nameWidth -= w; + if (LocaleController.isRTL) { + nameLeft += w; + } } nameWidth = Math.max(AndroidUtilities.dp(12), nameWidth); try { - CharSequence nameStringFinal = TextUtils.ellipsize(nameString.replace('\n', ' '), currentNamePaint, nameWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END); - nameLayout = new StaticLayout(nameStringFinal, currentNamePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + CharSequence nameStringFinal = TextUtils.ellipsize(nameString.replace('\n', ' '), Theme.dialogs_namePaint, nameWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END); + nameLayout = new StaticLayout(nameStringFinal, Theme.dialogs_namePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } catch (Exception e) { FileLog.e(e); } - int messageWidth = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline + 16); + int messageWidth; int avatarLeft; - if (!LocaleController.isRTL) { - messageLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); - avatarLeft = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 13 : 9); + int avatarTop; + if (SharedConfig.useThreeLinesLayout) { + avatarTop = AndroidUtilities.dp(11); + messageNameTop = AndroidUtilities.dp(32); + timeTop = AndroidUtilities.dp(13); + errorTop = AndroidUtilities.dp(43); + pinTop = AndroidUtilities.dp(43); + countTop = AndroidUtilities.dp(43); + checkDrawTop = AndroidUtilities.dp(13); + messageWidth = getMeasuredWidth() - AndroidUtilities.dp(72 + 21); + + if (!LocaleController.isRTL) { + messageLeft = messageNameLeft = AndroidUtilities.dp(72 + 6); + avatarLeft = AndroidUtilities.dp(10); + } else { + messageLeft = messageNameLeft = AndroidUtilities.dp(16); + avatarLeft = getMeasuredWidth() - AndroidUtilities.dp(66); + } + avatarImage.setImageCoords(avatarLeft, avatarTop, AndroidUtilities.dp(56), AndroidUtilities.dp(56)); } else { - messageLeft = AndroidUtilities.dp(16); - avatarLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.isTablet() ? 65 : 61); + avatarTop = AndroidUtilities.dp(9); + messageNameTop = AndroidUtilities.dp(31); + timeTop = AndroidUtilities.dp(16); + errorTop = AndroidUtilities.dp(39); + pinTop = AndroidUtilities.dp(39); + countTop = AndroidUtilities.dp(39); + checkDrawTop = AndroidUtilities.dp(17); + messageWidth = getMeasuredWidth() - AndroidUtilities.dp(72 + 23); + + if (!LocaleController.isRTL) { + messageLeft = messageNameLeft = AndroidUtilities.dp(72 + 4); + avatarLeft = AndroidUtilities.dp(10); + } else { + messageLeft = messageNameLeft = AndroidUtilities.dp(22); + avatarLeft = getMeasuredWidth() - AndroidUtilities.dp(64); + } + avatarImage.setImageCoords(avatarLeft, avatarTop, AndroidUtilities.dp(54), AndroidUtilities.dp(54)); + } + if (drawPin) { + if (!LocaleController.isRTL) { + pinLeft = getMeasuredWidth() - Theme.dialogs_pinnedDrawable.getIntrinsicWidth() - AndroidUtilities.dp(14); + } else { + pinLeft = AndroidUtilities.dp(14); + } } - avatarImage.setImageCoords(avatarLeft, avatarTop, AndroidUtilities.dp(52), AndroidUtilities.dp(52)); if (drawError) { int w = AndroidUtilities.dp(23 + 8); messageWidth -= w; @@ -773,6 +1179,7 @@ public class DialogCell extends BaseCell { } else { errorLeft = AndroidUtilities.dp(11); messageLeft += w; + messageNameLeft += w; } } else if (countString != null || mentionString != null) { if (countString != null) { @@ -781,24 +1188,31 @@ public class DialogCell extends BaseCell { int w = countWidth + AndroidUtilities.dp(18); messageWidth -= w; if (!LocaleController.isRTL) { - countLeft = getMeasuredWidth() - countWidth - AndroidUtilities.dp(19); + countLeft = getMeasuredWidth() - countWidth - AndroidUtilities.dp(20); } else { - countLeft = AndroidUtilities.dp(19); + countLeft = AndroidUtilities.dp(20); messageLeft += w; + messageNameLeft += w; } drawCount = true; } else { countWidth = 0; } if (mentionString != null) { - mentionWidth = AndroidUtilities.dp(12); + if (currentDialogFolderId != 0) { + mentionWidth = Math.max(AndroidUtilities.dp(12), (int) Math.ceil(Theme.dialogs_countTextPaint.measureText(mentionString))); + mentionLayout = new StaticLayout(mentionString, Theme.dialogs_countTextPaint, mentionWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + } else { + mentionWidth = AndroidUtilities.dp(12); + } int w = mentionWidth + AndroidUtilities.dp(18); messageWidth -= w; if (!LocaleController.isRTL) { - mentionLeft = getMeasuredWidth() - mentionWidth - AndroidUtilities.dp(19) - (countWidth != 0 ? countWidth + AndroidUtilities.dp(18) : 0); + mentionLeft = getMeasuredWidth() - mentionWidth - AndroidUtilities.dp(20) - (countWidth != 0 ? countWidth + AndroidUtilities.dp(18) : 0); } else { - mentionLeft = AndroidUtilities.dp(19) + (countWidth != 0 ? countWidth + AndroidUtilities.dp(18) : 0); + mentionLeft = AndroidUtilities.dp(20) + (countWidth != 0 ? countWidth + AndroidUtilities.dp(18) : 0); messageLeft += w; + messageNameLeft += w; } drawMention = true; } @@ -806,11 +1220,9 @@ public class DialogCell extends BaseCell { if (drawPin) { int w = Theme.dialogs_pinnedDrawable.getIntrinsicWidth() + AndroidUtilities.dp(8); messageWidth -= w; - if (!LocaleController.isRTL) { - pinLeft = getMeasuredWidth() - Theme.dialogs_pinnedDrawable.getIntrinsicWidth() - AndroidUtilities.dp(14); - } else { - pinLeft = AndroidUtilities.dp(14); + if (LocaleController.isRTL) { messageLeft += w; + messageNameLeft += w; } } drawCount = false; @@ -825,13 +1237,44 @@ public class DialogCell extends BaseCell { if (mess.length() > 150) { mess = mess.substring(0, 150); } - mess = mess.replace('\n', ' '); + if (!SharedConfig.useThreeLinesLayout || messageNameString != null) { + mess = mess.replace('\n', ' '); + } messageString = Emoji.replaceEmoji(mess, Theme.dialogs_messagePaint.getFontMetricsInt(), AndroidUtilities.dp(17), false); } messageWidth = Math.max(AndroidUtilities.dp(12), messageWidth); - CharSequence messageStringFinal = TextUtils.ellipsize(messageString, currentMessagePaint, messageWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END); + if (SharedConfig.useThreeLinesLayout && messageNameString != null && (currentDialogFolderId == 0 || currentDialogFolderDialogsCount == 1)) { + try { + messageNameLayout = StaticLayoutEx.createStaticLayout(messageNameString, Theme.dialogs_messageNamePaint, messageWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0, false, TextUtils.TruncateAt.END, messageWidth, 1); + } catch (Exception e) { + FileLog.e(e); + } + messageTop = AndroidUtilities.dp(32 + 19); + } else { + messageNameLayout = null; + if (SharedConfig.useThreeLinesLayout) { + messageTop = AndroidUtilities.dp(32); + } else { + messageTop = AndroidUtilities.dp(39); + } + } + try { - messageLayout = new StaticLayout(messageStringFinal, currentMessagePaint, messageWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + CharSequence messageStringFinal; + if (SharedConfig.useThreeLinesLayout && currentDialogFolderId != 0 && currentDialogFolderDialogsCount > 1) { + messageStringFinal = messageNameString; + messageNameString = null; + currentMessagePaint = Theme.dialogs_messagePaint; + } else if (!SharedConfig.useThreeLinesLayout || messageNameString != null) { + messageStringFinal = TextUtils.ellipsize(messageString, currentMessagePaint, messageWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END); + } else { + messageStringFinal = messageString; + } + if (SharedConfig.useThreeLinesLayout) { + messageLayout = StaticLayoutEx.createStaticLayout(messageStringFinal, currentMessagePaint, messageWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, AndroidUtilities.dp(1), false, TextUtils.TruncateAt.END, messageWidth, messageNameString != null ? 1 : 2); + } else { + messageLayout = new StaticLayout(messageStringFinal, currentMessagePaint, messageWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + } } catch (Exception e) { FileLog.e(e); } @@ -842,10 +1285,12 @@ public class DialogCell extends BaseCell { if (nameLayout != null && nameLayout.getLineCount() > 0) { left = nameLayout.getLineLeft(0); widthpx = Math.ceil(nameLayout.getLineWidth(0)); - if (dialogMuted && !drawVerified) { + if (dialogMuted && !drawVerified && !drawScam) { nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - Theme.dialogs_muteDrawable.getIntrinsicWidth()); } else if (drawVerified) { nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - Theme.dialogs_verifiedDrawable.getIntrinsicWidth()); + } else if (drawScam) { + nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - Theme.dialogs_scamDrawable.getIntrinsicWidth()); } if (left == 0) { if (widthpx < nameWidth) { @@ -853,12 +1298,31 @@ public class DialogCell extends BaseCell { } } } - if (messageLayout != null && messageLayout.getLineCount() > 0) { - left = messageLayout.getLineLeft(0); + if (messageLayout != null) { + int lineCount = messageLayout.getLineCount(); + if (lineCount > 0) { + int w = Integer.MAX_VALUE; + for (int a = 0; a < lineCount; a++) { + left = messageLayout.getLineLeft(a); + if (left == 0) { + widthpx = Math.ceil(messageLayout.getLineWidth(a)); + w = Math.min(w, (int) (messageWidth - widthpx)); + } else { + w = 0; + break; + } + } + if (w != Integer.MAX_VALUE) { + messageLeft += w; + } + } + } + if (messageNameLayout != null && messageNameLayout.getLineCount() > 0) { + left = messageNameLayout.getLineLeft(0); if (left == 0) { - widthpx = Math.ceil(messageLayout.getLineWidth(0)); + widthpx = Math.ceil(messageNameLayout.getLineWidth(0)); if (widthpx < messageWidth) { - messageLeft += (messageWidth - widthpx); + messageNameLeft += (messageWidth - widthpx); } } } @@ -871,19 +1335,23 @@ public class DialogCell extends BaseCell { nameLeft -= (nameWidth - widthpx); } } - if (dialogMuted || drawVerified) { + if (dialogMuted || drawVerified || drawScam) { nameMuteLeft = (int) (nameLeft + left + AndroidUtilities.dp(6)); } } - if (messageLayout != null && messageLayout.getLineCount() > 0) { - left = messageLayout.getLineRight(0); - if (left == messageWidth) { - widthpx = Math.ceil(messageLayout.getLineWidth(0)); - if (widthpx < messageWidth) { - messageLeft -= (messageWidth - widthpx); + if (messageLayout != null) { + int lineCount = messageLayout.getLineCount(); + if (lineCount > 0) { + left = Integer.MAX_VALUE; + for (int a = 0; a < lineCount; a++) { + left = Math.min(left, messageLayout.getLineLeft(a)); } + messageLeft -= left; } } + if (messageNameLayout != null && messageNameLayout.getLineCount() > 0) { + messageNameLeft -= messageNameLayout.getLineLeft(0); + } } } @@ -902,13 +1370,18 @@ public class DialogCell extends BaseCell { isSelected = value; } - public void checkCurrentDialogIndex() { - ArrayList dialogsArray = DialogsActivity.getDialogsArray(dialogsType, currentAccount); + public void checkCurrentDialogIndex(boolean frozen) { + ArrayList dialogsArray = DialogsActivity.getDialogsArray(currentAccount, dialogsType, folderId, frozen); if (index < dialogsArray.size()) { - TLRPC.TL_dialog dialog = dialogsArray.get(index); - TLRPC.TL_dialog nextDialog = index + 1 < dialogsArray.size() ? dialogsArray.get(index + 1) : null; + TLRPC.Dialog dialog = dialogsArray.get(index); + TLRPC.Dialog nextDialog = index + 1 < dialogsArray.size() ? dialogsArray.get(index + 1) : null; TLRPC.DraftMessage newDraftMessage = DataQuery.getInstance(currentAccount).getDraft(currentDialogId); - MessageObject newMessageObject = MessagesController.getInstance(currentAccount).dialogMessage.get(dialog.id); + MessageObject newMessageObject; + if (currentDialogFolderId != 0) { + newMessageObject = findFolderTopMessage(); + } else { + newMessageObject = MessagesController.getInstance(currentAccount).dialogMessage.get(dialog.id); + } if (currentDialogId != dialog.id || message != null && message.getId() != dialog.top_message || newMessageObject != null && newMessageObject.messageOwner.edit_date != currentEditDate || @@ -917,13 +1390,37 @@ public class DialogCell extends BaseCell { markUnread != dialog.unread_mark || message != newMessageObject || message == null && newMessageObject != null || newDraftMessage != draftMessage || drawPin != dialog.pinned) { + boolean dialogChanged = currentDialogId != dialog.id; currentDialogId = dialog.id; - fullSeparator = dialog.pinned && nextDialog != null && !nextDialog.pinned; + if (dialog instanceof TLRPC.TL_dialogFolder) { + TLRPC.TL_dialogFolder dialogFolder = (TLRPC.TL_dialogFolder) dialog; + currentDialogFolderId = dialogFolder.folder.id; + } else { + currentDialogFolderId = 0; + } + fullSeparator = dialog instanceof TLRPC.TL_dialog && dialog.pinned && nextDialog != null && !nextDialog.pinned; + fullSeparator2 = dialog instanceof TLRPC.TL_dialogFolder && nextDialog != null && !nextDialog.pinned; update(0); + if (dialogChanged) { + reorderIconProgress = drawPin && drawReorder ? 1.0f : 0.0f; + } + checkOnline(); } } } + public void animateArchiveAvatar() { + if (avatarDrawable.getAvatarType() != AvatarDrawable.AVATAR_TYPE_ARCHIVED) { + return; + } + animatingArchiveAvatar = true; + animatingArchiveAvatarProgress = 0.0f; + Theme.dialogs_archiveAvatarDrawable.setCallback(this); + Theme.dialogs_archiveAvatarDrawable.setProgress(0.0f); + Theme.dialogs_archiveAvatarDrawable.start(); + invalidate(); + } + public void setChecked(boolean checked, boolean animated) { if (checkBox == null) { return; @@ -931,6 +1428,24 @@ public class DialogCell extends BaseCell { checkBox.setChecked(checked, animated); } + private MessageObject findFolderTopMessage() { + ArrayList dialogs = DialogsActivity.getDialogsArray(currentAccount, dialogsType, currentDialogFolderId, false); + MessageObject maxMessage = null; + if (!dialogs.isEmpty()) { + for (int a = 0, N = dialogs.size(); a < N; a++) { + TLRPC.Dialog dialog = dialogs.get(a); + MessageObject object = MessagesController.getInstance(currentAccount).dialogMessage.get(dialog.id); + if (object != null && (maxMessage == null || object.messageOwner.date > maxMessage.messageOwner.date)) { + maxMessage = object; + } + if (dialog.pinnedNum == 0) { + break; + } + } + } + return maxMessage; + } + public void update(int mask) { if (customDialog != null) { lastMessageDate = customDialog.date; @@ -942,20 +1457,28 @@ public class DialogCell extends BaseCell { avatarImage.setImage(null, "50_50", avatarDrawable, null, 0); } else { if (isDialogCell) { - TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(currentDialogId); - if (dialog != null && mask == 0) { - clearingDialog = MessagesController.getInstance(currentAccount).isClearingDialog(dialog.id); - message = MessagesController.getInstance(currentAccount).dialogMessage.get(dialog.id); - lastUnreadState = message != null && message.isUnread(); - unreadCount = dialog.unread_count; - markUnread = dialog.unread_mark; - mentionCount = dialog.unread_mentions_count; - currentEditDate = message != null ? message.messageOwner.edit_date : 0; - lastMessageDate = dialog.last_message_date; - drawPin = dialog.pinned; - if (message != null) { - lastSendState = message.messageOwner.send_state; + TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(currentDialogId); + if (dialog != null) { + if (mask == 0) { + clearingDialog = MessagesController.getInstance(currentAccount).isClearingDialog(dialog.id); + message = MessagesController.getInstance(currentAccount).dialogMessage.get(dialog.id); + lastUnreadState = message != null && message.isUnread(); + unreadCount = dialog.unread_count; + markUnread = dialog.unread_mark; + mentionCount = dialog.unread_mentions_count; + currentEditDate = message != null ? message.messageOwner.edit_date : 0; + lastMessageDate = dialog.last_message_date; + drawPin = currentDialogFolderId == 0 && dialog.pinned; + if (message != null) { + lastSendState = message.messageOwner.send_state; + } } + } else { + unreadCount = 0; + mentionCount = 0; + currentEditDate = 0; + lastMessageDate = 0; + clearingDialog = false; } } else { drawPin = false; @@ -963,6 +1486,10 @@ public class DialogCell extends BaseCell { if (mask != 0) { boolean continueUpdate = false; + if (user != null && (mask & MessagesController.UPDATE_MASK_STATUS) != 0) { + user = MessagesController.getInstance(currentAccount).getUser(user.id); + invalidate(); + } if (isDialogCell) { if ((mask & MessagesController.UPDATE_MASK_USER_PRINT) != 0) { CharSequence printString = MessagesController.getInstance(currentAccount).printingStrings.get(currentDialogId); @@ -1001,7 +1528,7 @@ public class DialogCell extends BaseCell { lastUnreadState = message.isUnread(); continueUpdate = true; } else if (isDialogCell) { - TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(currentDialogId); + TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(currentDialogId); if (dialog != null && (unreadCount != dialog.unread_count || markUnread != dialog.unread_mark || mentionCount != dialog.unread_mentions_count)) { unreadCount = dialog.unread_count; mentionCount = dialog.unread_mentions_count; @@ -1023,54 +1550,68 @@ public class DialogCell extends BaseCell { } } - dialogMuted = isDialogCell && MessagesController.getInstance(currentAccount).isDialogMuted(currentDialogId); user = null; chat = null; encryptedChat = null; - int lower_id = (int) currentDialogId; - int high_id = (int) (currentDialogId >> 32); - if (lower_id != 0) { - if (high_id == 1) { - chat = MessagesController.getInstance(currentAccount).getChat(lower_id); + long dialogId; + if (currentDialogFolderId != 0) { + dialogMuted = false; + message = findFolderTopMessage(); + if (message != null) { + dialogId = message.getDialogId(); } 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; - } - } - } else { - user = MessagesController.getInstance(currentAccount).getUser(lower_id); - } + dialogId = 0; } } else { - encryptedChat = MessagesController.getInstance(currentAccount).getEncryptedChat(high_id); - if (encryptedChat != null) { - user = MessagesController.getInstance(currentAccount).getUser(encryptedChat.user_id); + dialogMuted = isDialogCell && MessagesController.getInstance(currentAccount).isDialogMuted(currentDialogId); + dialogId = currentDialogId; + } + + if (dialogId != 0) { + 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; + } + } + } else { + user = MessagesController.getInstance(currentAccount).getUser(lower_id); + } + } + } else { + encryptedChat = MessagesController.getInstance(currentAccount).getEncryptedChat(high_id); + if (encryptedChat != null) { + user = MessagesController.getInstance(currentAccount).getUser(encryptedChat.user_id); + } } } - TLRPC.FileLocation photo = null; - Object parentObject = null; - if (user != null) { - avatarDrawable.setInfo(user); - if (UserObject.isUserSelf(user)) { - avatarDrawable.setSavedMessages(1); - } else if (user.photo != null) { - photo = user.photo.photo_small; + if (currentDialogFolderId != 0) { + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_ARCHIVED); + avatarImage.setImage(null, null, avatarDrawable, null, user, 0); + } else { + if (user != null) { + avatarDrawable.setInfo(user); + if (UserObject.isUserSelf(user)) { + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_SAVED); + avatarImage.setImage(null, null, avatarDrawable, null, user, 0); + } else { + avatarImage.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, null, user, 0); + } + } else if (chat != null) { + avatarDrawable.setInfo(chat); + avatarImage.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, null, chat, 0); } - parentObject = user; - } else if (chat != null) { - if (chat.photo != null) { - photo = chat.photo.photo_small; - } - avatarDrawable.setInfo(chat); - parentObject = chat; } - avatarImage.setImage(photo, "50_50", avatarDrawable, null, parentObject, 0); } if (getMeasuredWidth() != 0 || getMeasuredHeight() != 0) { buildLayout(); @@ -1081,17 +1622,214 @@ public class DialogCell extends BaseCell { invalidate(); } + @Override + public float getTranslationX() { + return translationX; + } + + @Override + public void setTranslationX(float value) { + translationX = (int) value; + if (translationDrawable != null && translationX == 0) { + if (translationDrawable instanceof LottieDrawable) { + LottieDrawable lottieDrawable = (LottieDrawable) translationDrawable; + lottieDrawable.setProgress(0.0f); + } + translationAnimationStarted = false; + archiveHidden = SharedConfig.archiveHidden; + currentRevealProgress = 0; + isSliding = false; + } + if (translationX != 0) { + isSliding = true; + } + if (isSliding) { + boolean prevValue = drawRevealBackground; + drawRevealBackground = Math.abs(translationX) >= getMeasuredWidth() * 0.3f; + if (prevValue != drawRevealBackground && archiveHidden == SharedConfig.archiveHidden) { + try { + performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + } catch (Exception ignore) { + + } + } + } + invalidate(); + } + + @SuppressLint("DrawAllocation") @Override protected void onDraw(Canvas canvas) { if (currentDialogId == 0 && customDialog == null) { return; } + boolean needInvalidate = false; + + long newTime = SystemClock.uptimeMillis(); + long dt = newTime - lastUpdateTime; + if (dt > 17) { + dt = 17; + } + lastUpdateTime = newTime; + + if (clipProgress != 0.0f && Build.VERSION.SDK_INT != 24) { + canvas.save(); + canvas.clipRect(0, topClip * clipProgress, getMeasuredWidth(), getMeasuredHeight() - (int) (bottomClip * clipProgress)); + } + + if (translationX != 0 || cornerProgress != 0.0f) { + canvas.save(); + String archive; + int backgroundColor; + int revealBackgroundColor; + if (currentDialogFolderId != 0) { + if (archiveHidden) { + backgroundColor = Theme.getColor(Theme.key_chats_archivePinBackground); + revealBackgroundColor = Theme.getColor(Theme.key_chats_archiveBackground); + archive = LocaleController.getString("UnhideFromTop", R.string.UnhideFromTop); + translationDrawable = Theme.dialogs_unpinArchiveDrawable; + } else { + backgroundColor = Theme.getColor(Theme.key_chats_archiveBackground); + revealBackgroundColor = Theme.getColor(Theme.key_chats_archivePinBackground); + archive = LocaleController.getString("HideOnTop", R.string.HideOnTop); + translationDrawable = Theme.dialogs_pinArchiveDrawable; + } + } else { + if (folderId == 0) { + backgroundColor = Theme.getColor(Theme.key_chats_archiveBackground); + revealBackgroundColor = Theme.getColor(Theme.key_chats_archivePinBackground); + archive = LocaleController.getString("Archive", R.string.Archive); + translationDrawable = Theme.dialogs_archiveDrawable; + } else { + backgroundColor = Theme.getColor(Theme.key_chats_archivePinBackground); + revealBackgroundColor = Theme.getColor(Theme.key_chats_archiveBackground); + archive = LocaleController.getString("Unarchive", R.string.Unarchive); + translationDrawable = Theme.dialogs_unarchiveDrawable; + } + } + if (!translationAnimationStarted && Math.abs(translationX) > AndroidUtilities.dp(43)) { + translationAnimationStarted = true; + if (translationDrawable instanceof LottieDrawable) { + LottieDrawable lottieDrawable = (LottieDrawable) translationDrawable; + lottieDrawable.setProgress(0.0f); + lottieDrawable.setCallback(this); + lottieDrawable.start(); + } + } + + float tx = getMeasuredWidth() + translationX; + if (currentRevealProgress < 1.0f) { + Theme.dialogs_pinnedPaint.setColor(backgroundColor); + canvas.drawRect(tx - AndroidUtilities.dp(8), 0, getMeasuredWidth(), getMeasuredHeight(), Theme.dialogs_pinnedPaint); + if (currentRevealProgress == 0 && Theme.dialogs_archiveDrawableRecolored) { + if (Theme.dialogs_archiveDrawable instanceof LottieDrawable) { + LottieDrawable lottieDrawable = (LottieDrawable) Theme.dialogs_archiveDrawable; + lottieDrawable.addValueCallback(new KeyPath("Arrow", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_chats_archiveBackground)))); + } + Theme.dialogs_archiveDrawableRecolored = false; + } + } + int drawableX = getMeasuredWidth() - AndroidUtilities.dp(43) - translationDrawable.getIntrinsicWidth() / 2; + int drawableY = AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 12 : 9); + if (!(translationDrawable instanceof LottieDrawable)) { + drawableY += AndroidUtilities.dp(2); + } + int drawableCx = drawableX + translationDrawable.getIntrinsicWidth() / 2; + int drawableCy = drawableY + translationDrawable.getIntrinsicHeight() / 2; + + if (currentRevealProgress > 0.0f) { + canvas.save(); + canvas.clipRect(tx - AndroidUtilities.dp(8), 0, getMeasuredWidth(), getMeasuredHeight()); + Theme.dialogs_pinnedPaint.setColor(revealBackgroundColor); + + float rad = (float) Math.sqrt(drawableCx * drawableCx + (drawableCy - getMeasuredHeight()) * (drawableCy - getMeasuredHeight())); + canvas.drawCircle(drawableCx, drawableCy, rad * AndroidUtilities.accelerateInterpolator.getInterpolation(currentRevealProgress), Theme.dialogs_pinnedPaint); + canvas.restore(); + + if (!Theme.dialogs_archiveDrawableRecolored) { + if (Theme.dialogs_archiveDrawable instanceof LottieDrawable) { + LottieDrawable lottieDrawable = (LottieDrawable) Theme.dialogs_archiveDrawable; + lottieDrawable.addValueCallback(new KeyPath("Arrow", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_chats_archivePinBackground)))); + } + Theme.dialogs_archiveDrawableRecolored = true; + } + } + + canvas.save(); + canvas.translate(drawableX, drawableY); + if (currentRevealBounceProgress != 0.0f && currentRevealBounceProgress != 1.0f) { + float scale = 1.0f + interpolator.getInterpolation(currentRevealBounceProgress); + canvas.scale(scale, scale, translationDrawable.getIntrinsicWidth() / 2, translationDrawable.getIntrinsicHeight() / 2); + } + setDrawableBounds(translationDrawable, 0, 0); + translationDrawable.draw(canvas); + canvas.restore(); + + canvas.clipRect(tx, 0, getMeasuredWidth(), getMeasuredHeight()); + + int width = (int) Math.ceil(Theme.dialogs_countTextPaint.measureText(archive)); + canvas.drawText(archive, getMeasuredWidth() - AndroidUtilities.dp(43) - width / 2, AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 62 : 59), Theme.dialogs_archiveTextPaint); + + canvas.restore(); + } else if (translationDrawable != null) { + if (translationDrawable instanceof LottieDrawable) { + LottieDrawable lottieDrawable = (LottieDrawable) translationDrawable; + lottieDrawable.stop(); + lottieDrawable.setProgress(0.0f); + lottieDrawable.setCallback(null); + } + translationDrawable = null; + translationAnimationStarted = false; + } + + if (translationX != 0) { + canvas.save(); + canvas.translate(translationX, 0); + } + if (isSelected) { canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), Theme.dialogs_tabletSeletedPaint); } - if (drawPin || drawPinBackground) { + if (currentDialogFolderId != 0 && (!SharedConfig.archiveHidden || archiveBackgroundProgress != 0)) { + Theme.dialogs_pinnedPaint.setColor(AndroidUtilities.getOffsetColor(0, Theme.getColor(Theme.key_chats_pinnedOverlay), archiveBackgroundProgress, 1.0f)); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), Theme.dialogs_pinnedPaint); + } else if (drawPin || drawPinBackground) { + Theme.dialogs_pinnedPaint.setColor(Theme.getColor(Theme.key_chats_pinnedOverlay)); + canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), Theme.dialogs_pinnedPaint); + } + + if (translationX != 0 || cornerProgress != 0.0f) { + canvas.save(); + + Theme.dialogs_pinnedPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + rect.set(getMeasuredWidth() - AndroidUtilities.dp(64), 0, getMeasuredWidth(), getMeasuredHeight()); + canvas.drawRoundRect(rect, AndroidUtilities.dp(8) * cornerProgress, AndroidUtilities.dp(8) * cornerProgress, Theme.dialogs_pinnedPaint); + + if (currentDialogFolderId != 0 && (!SharedConfig.archiveHidden || archiveBackgroundProgress != 0)) { + Theme.dialogs_pinnedPaint.setColor(AndroidUtilities.getOffsetColor(0, Theme.getColor(Theme.key_chats_pinnedOverlay), archiveBackgroundProgress, 1.0f)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(8) * cornerProgress, AndroidUtilities.dp(8) * cornerProgress, Theme.dialogs_pinnedPaint); + } else if (drawPin || drawPinBackground) { + Theme.dialogs_pinnedPaint.setColor(Theme.getColor(Theme.key_chats_pinnedOverlay)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(8) * cornerProgress, AndroidUtilities.dp(8) * cornerProgress, Theme.dialogs_pinnedPaint); + } + canvas.restore(); + } + + if (translationX != 0) { + if (cornerProgress < 1.0f) { + cornerProgress += dt / 150.0f; + if (cornerProgress > 1.0f) { + cornerProgress = 1.0f; + } + needInvalidate = true; + } + } else if (cornerProgress > 0.0f) { + cornerProgress -= dt / 150.0f; + if (cornerProgress < 0.0f) { + cornerProgress = 0.0f; + } + needInvalidate = true; } if (drawNameLock) { @@ -1109,8 +1847,15 @@ public class DialogCell extends BaseCell { } if (nameLayout != null) { + if (currentDialogFolderId != 0) { + Theme.dialogs_namePaint.setColor(Theme.dialogs_namePaint.linkColor = Theme.getColor(Theme.key_chats_nameArchived)); + } else if (encryptedChat != null) { + Theme.dialogs_namePaint.setColor(Theme.dialogs_namePaint.linkColor = Theme.getColor(Theme.key_chats_secretName)); + } else { + Theme.dialogs_namePaint.setColor(Theme.dialogs_namePaint.linkColor = Theme.getColor(Theme.key_chats_name)); + } canvas.save(); - canvas.translate(nameLeft, AndroidUtilities.dp(13)); + canvas.translate(nameLeft, AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 10 : 13)); nameLayout.draw(canvas); canvas.restore(); } @@ -1122,7 +1867,34 @@ public class DialogCell extends BaseCell { canvas.restore(); } + if (messageNameLayout != null) { + if (currentDialogFolderId != 0) { + Theme.dialogs_messageNamePaint.setColor(Theme.dialogs_messageNamePaint.linkColor = Theme.getColor(Theme.key_chats_nameMessageArchived_threeLines)); + } else if (draftMessage != null) { + Theme.dialogs_messageNamePaint.setColor(Theme.dialogs_messageNamePaint.linkColor = Theme.getColor(Theme.key_chats_draft)); + } else { + Theme.dialogs_messageNamePaint.setColor(Theme.dialogs_messageNamePaint.linkColor = Theme.getColor(Theme.key_chats_nameMessage_threeLines)); + } + canvas.save(); + canvas.translate(messageNameLeft, messageNameTop); + try { + messageNameLayout.draw(canvas); + } catch (Exception e) { + FileLog.e(e); + } + canvas.restore(); + } + if (messageLayout != null) { + if (currentDialogFolderId != 0) { + if (chat != null) { + Theme.dialogs_messagePaint.setColor(Theme.dialogs_messagePaint.linkColor = Theme.getColor(Theme.key_chats_nameMessageArchived)); + } else { + Theme.dialogs_messagePaint.setColor(Theme.dialogs_messagePaint.linkColor = Theme.getColor(Theme.key_chats_messageArchived)); + } + } else { + Theme.dialogs_messagePaint.setColor(Theme.dialogs_messagePaint.linkColor = Theme.getColor(Theme.key_chats_message)); + } canvas.save(); canvas.translate(messageLeft, messageTop); try { @@ -1148,51 +1920,128 @@ public class DialogCell extends BaseCell { } } - if (dialogMuted && !drawVerified) { - setDrawableBounds(Theme.dialogs_muteDrawable, nameMuteLeft, AndroidUtilities.dp(16.5f)); + if (dialogMuted && !drawVerified && !drawScam) { + setDrawableBounds(Theme.dialogs_muteDrawable, nameMuteLeft - AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 0 : 1), AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 13.5f : 17.5f)); Theme.dialogs_muteDrawable.draw(canvas); } else if (drawVerified) { - setDrawableBounds(Theme.dialogs_verifiedDrawable, nameMuteLeft, AndroidUtilities.dp(16.5f)); - setDrawableBounds(Theme.dialogs_verifiedCheckDrawable, nameMuteLeft, AndroidUtilities.dp(16.5f)); + setDrawableBounds(Theme.dialogs_verifiedDrawable, nameMuteLeft, AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 12.5f : 16.5f)); + setDrawableBounds(Theme.dialogs_verifiedCheckDrawable, nameMuteLeft, AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 12.5f : 16.5f)); Theme.dialogs_verifiedDrawable.draw(canvas); Theme.dialogs_verifiedCheckDrawable.draw(canvas); + } else if (drawScam) { + setDrawableBounds(Theme.dialogs_scamDrawable, nameMuteLeft, AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 12 : 15)); + Theme.dialogs_scamDrawable.draw(canvas); } + if (drawReorder || reorderIconProgress != 0) { + Theme.dialogs_reorderDrawable.setAlpha((int) (reorderIconProgress * 255)); + setDrawableBounds(Theme.dialogs_reorderDrawable, pinLeft, pinTop); + Theme.dialogs_reorderDrawable.draw(canvas); + } if (drawError) { + Theme.dialogs_errorDrawable.setAlpha((int) ((1.0f - reorderIconProgress) * 255)); rect.set(errorLeft, errorTop, errorLeft + AndroidUtilities.dp(23), errorTop + AndroidUtilities.dp(23)); canvas.drawRoundRect(rect, 11.5f * AndroidUtilities.density, 11.5f * AndroidUtilities.density, Theme.dialogs_errorPaint); setDrawableBounds(Theme.dialogs_errorDrawable, errorLeft + AndroidUtilities.dp(5.5f), errorTop + AndroidUtilities.dp(5)); Theme.dialogs_errorDrawable.draw(canvas); } else if (drawCount || drawMention) { if (drawCount) { + Paint paint = dialogMuted || currentDialogFolderId != 0 ? Theme.dialogs_countGrayPaint : Theme.dialogs_countPaint; + paint.setAlpha((int) ((1.0f - reorderIconProgress) * 255)); + Theme.dialogs_countTextPaint.setAlpha((int) ((1.0f - reorderIconProgress) * 255)); + int x = countLeft - AndroidUtilities.dp(5.5f); rect.set(x, countTop, x + countWidth + AndroidUtilities.dp(11), countTop + AndroidUtilities.dp(23)); - canvas.drawRoundRect(rect, 11.5f * AndroidUtilities.density, 11.5f * AndroidUtilities.density, dialogMuted ? Theme.dialogs_countGrayPaint : Theme.dialogs_countPaint); - canvas.save(); - canvas.translate(countLeft, countTop + AndroidUtilities.dp(4)); + canvas.drawRoundRect(rect, 11.5f * AndroidUtilities.density, 11.5f * AndroidUtilities.density, paint); if (countLayout != null) { + canvas.save(); + canvas.translate(countLeft, countTop + AndroidUtilities.dp(4)); countLayout.draw(canvas); + canvas.restore(); } - canvas.restore(); } if (drawMention) { + Theme.dialogs_countPaint.setAlpha((int) ((1.0f - reorderIconProgress) * 255)); + int x = mentionLeft - AndroidUtilities.dp(5.5f); rect.set(x, countTop, x + mentionWidth + AndroidUtilities.dp(11), countTop + AndroidUtilities.dp(23)); - canvas.drawRoundRect(rect, 11.5f * AndroidUtilities.density, 11.5f * AndroidUtilities.density, Theme.dialogs_countPaint); - setDrawableBounds(Theme.dialogs_mentionDrawable, mentionLeft - AndroidUtilities.dp(2), countTop + AndroidUtilities.dp(3.2f), AndroidUtilities.dp(16), AndroidUtilities.dp(16)); - Theme.dialogs_mentionDrawable.draw(canvas); + Paint paint = dialogMuted && folderId != 0 ? Theme.dialogs_countGrayPaint : Theme.dialogs_countPaint; + canvas.drawRoundRect(rect, 11.5f * AndroidUtilities.density, 11.5f * AndroidUtilities.density, paint); + if (mentionLayout != null) { + Theme.dialogs_countTextPaint.setAlpha((int) ((1.0f - reorderIconProgress) * 255)); + + canvas.save(); + canvas.translate(mentionLeft, countTop + AndroidUtilities.dp(4)); + mentionLayout.draw(canvas); + canvas.restore(); + } else { + Theme.dialogs_mentionDrawable.setAlpha((int) ((1.0f - reorderIconProgress) * 255)); + + setDrawableBounds(Theme.dialogs_mentionDrawable, mentionLeft - AndroidUtilities.dp(2), countTop + AndroidUtilities.dp(3.2f), AndroidUtilities.dp(16), AndroidUtilities.dp(16)); + Theme.dialogs_mentionDrawable.draw(canvas); + } } } else if (drawPin) { + Theme.dialogs_pinnedDrawable.setAlpha((int) ((1.0f - reorderIconProgress) * 255)); setDrawableBounds(Theme.dialogs_pinnedDrawable, pinLeft, pinTop); Theme.dialogs_pinnedDrawable.draw(canvas); } + if (animatingArchiveAvatar) { + canvas.save(); + float scale = 1.0f + interpolator.getInterpolation(animatingArchiveAvatarProgress / 170.0f); + canvas.scale(scale, scale, avatarImage.getCenterX(), avatarImage.getCenterY()); + } + avatarImage.draw(canvas); + if (animatingArchiveAvatar) { + canvas.restore(); + } + + if (user != null && isDialogCell && currentDialogFolderId == 0 && !MessagesController.isSupportUser(user) && !user.bot) { + boolean isOnline = !user.self && (user.status != null && user.status.expires > ConnectionsManager.getInstance(currentAccount).getCurrentTime() || MessagesController.getInstance(currentAccount).onlinePrivacy.containsKey(user.id)); + if (isOnline || onlineProgress != 0) { + int top = avatarImage.getImageY2() - AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 6 : 8); + int left; + if (LocaleController.isRTL) { + left = avatarImage.getImageX() + AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 10 : 6); + } else { + left = avatarImage.getImageX2() - AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 10 : 6); + } + + Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + canvas.drawCircle(left, top, AndroidUtilities.dp(7) * onlineProgress, Theme.dialogs_onlineCirclePaint); + Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_chats_onlineCircle)); + canvas.drawCircle(left, top, AndroidUtilities.dp(5) * onlineProgress, Theme.dialogs_onlineCirclePaint); + if (isOnline) { + if (onlineProgress < 1.0f) { + onlineProgress += dt / 150.0f; + if (onlineProgress > 1.0f) { + onlineProgress = 1.0f; + } + needInvalidate = true; + } + } else { + if (onlineProgress > 0.0f) { + onlineProgress -= dt / 150.0f; + if (onlineProgress < 0.0f) { + onlineProgress = 0.0f; + } + needInvalidate = true; + } + } + } + } + + if (translationX != 0) { + canvas.restore(); + } + if (useSeparator) { int left; - if (fullSeparator) { + if (fullSeparator || currentDialogFolderId != 0 && archiveHidden && !fullSeparator2 || fullSeparator2 && !archiveHidden) { left = 0; } else { - left = AndroidUtilities.dp(AndroidUtilities.leftBaseline); + left = AndroidUtilities.dp(72); } if (LocaleController.isRTL) { canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth() - left, getMeasuredHeight() - 1, Theme.dividerPaint); @@ -1201,11 +2050,228 @@ public class DialogCell extends BaseCell { } } - avatarImage.draw(canvas); + if (clipProgress != 0.0f) { + if (Build.VERSION.SDK_INT != 24) { + canvas.restore(); + } else { + Theme.dialogs_pinnedPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + canvas.drawRect(0, 0, getMeasuredWidth(), topClip * clipProgress, Theme.dialogs_pinnedPaint); + canvas.drawRect(0, getMeasuredHeight() - (int) (bottomClip * clipProgress), getMeasuredWidth(), getMeasuredHeight(), Theme.dialogs_pinnedPaint); + } + } + + if (drawReorder || reorderIconProgress != 0.0f) { + if (drawReorder) { + if (reorderIconProgress < 1.0f) { + reorderIconProgress += dt / 170.0f; + if (reorderIconProgress > 1.0f) { + reorderIconProgress = 1.0f; + } + needInvalidate = true; + } + } else { + if (reorderIconProgress > 0.0f) { + reorderIconProgress -= dt / 170.0f; + if (reorderIconProgress < 0.0f) { + reorderIconProgress = 0.0f; + } + needInvalidate = true; + } + } + } + + if (archiveHidden) { + if (archiveBackgroundProgress > 0.0f) { + archiveBackgroundProgress -= dt / 170.0f; + if (currentRevealBounceProgress < 0.0f) { + currentRevealBounceProgress = 0.0f; + } + if (avatarDrawable.getAvatarType() == AvatarDrawable.AVATAR_TYPE_ARCHIVED) { + avatarDrawable.setArchivedAvatarHiddenProgress(archiveBackgroundProgress); + } + needInvalidate = true; + } + } else { + if (archiveBackgroundProgress < 1.0f) { + archiveBackgroundProgress += dt / 170.0f; + if (currentRevealBounceProgress > 1.0f) { + currentRevealBounceProgress = 1.0f; + } + if (avatarDrawable.getAvatarType() == AvatarDrawable.AVATAR_TYPE_ARCHIVED) { + avatarDrawable.setArchivedAvatarHiddenProgress(archiveBackgroundProgress); + } + needInvalidate = true; + } + } + + if (animatingArchiveAvatar) { + animatingArchiveAvatarProgress += dt; + if (animatingArchiveAvatarProgress >= 170.0f) { + animatingArchiveAvatarProgress = 170.0f; + animatingArchiveAvatar = false; + } + needInvalidate = true; + } + if (drawRevealBackground) { + if (currentRevealBounceProgress < 1.0f) { + currentRevealBounceProgress += dt / 170.0f; + if (currentRevealBounceProgress > 1.0f) { + currentRevealBounceProgress = 1.0f; + needInvalidate = true; + } + } + if (currentRevealProgress < 1.0f) { + currentRevealProgress += dt / 300.0f; + if (currentRevealProgress > 1.0f) { + currentRevealProgress = 1.0f; + } + needInvalidate = true; + } + } else { + if (currentRevealBounceProgress == 1.0f) { + currentRevealBounceProgress = 0.0f; + needInvalidate = true; + } + if (currentRevealProgress > 0.0f) { + currentRevealProgress -= dt / 300.0f; + if (currentRevealProgress < 0.0f) { + currentRevealProgress = 0.0f; + } + needInvalidate = true; + } + } + if (needInvalidate) { + invalidate(); + } + } + + public void onReorderStateChanged(boolean reordering, boolean animated) { + if (!drawPin && reordering || drawReorder == reordering) { + if (!drawPin) { + drawReorder = false; + } + return; + } + drawReorder = reordering; + if (animated) { + reorderIconProgress = drawReorder ? 0.0f : 1.0f; + } else { + reorderIconProgress = drawReorder ? 1.0f : 0.0f; + } + invalidate(); + } + + public void setSliding(boolean value) { + isSliding = value; + } + + @Override + public void invalidateDrawable(Drawable who) { + if (who == translationDrawable || who == Theme.dialogs_archiveAvatarDrawable) { + invalidate(who.getBounds()); + } else { + super.invalidateDrawable(who); + } } @Override public boolean hasOverlappingRendering() { return false; } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.addAction(AccessibilityNodeInfo.ACTION_CLICK); + info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK); + } + + @Override + public void onPopulateAccessibilityEvent(AccessibilityEvent event) { + super.onPopulateAccessibilityEvent(event); + StringBuilder sb = new StringBuilder(); + if (currentDialogFolderId == 1) { + sb.append(LocaleController.getString("ArchivedChats", R.string.ArchivedChats)); + sb.append(". "); + } else { + if (encryptedChat != null) { + sb.append(LocaleController.getString("AccDescrSecretChat", R.string.AccDescrSecretChat)); + sb.append(". "); + } + if (user != null) { + if (user.bot) { + sb.append(LocaleController.getString("Bot", R.string.Bot)); + sb.append(". "); + } + if (user.self) { + sb.append(LocaleController.getString("SavedMessages", R.string.SavedMessages)); + } else { + sb.append(ContactsController.formatName(user.first_name, user.last_name)); + } + sb.append(". "); + } else if (chat != null) { + if (chat.broadcast) { + sb.append(LocaleController.getString("AccDescrChannel", R.string.AccDescrChannel)); + } else { + sb.append(LocaleController.getString("AccDescrGroup", R.string.AccDescrGroup)); + } + sb.append(". "); + sb.append(chat.title); + sb.append(". "); + } + } + if (unreadCount > 0) { + sb.append(LocaleController.formatPluralString("NewMessages", unreadCount)); + sb.append(". "); + } + if (message == null || currentDialogFolderId != 0) { + event.setContentDescription(sb.toString()); + return; + } + int lastDate = lastMessageDate; + if (lastMessageDate == 0 && message != null) { + lastDate = message.messageOwner.date; + } + String date = LocaleController.formatDateAudio(lastDate); + if (message.isOut()) { + sb.append(LocaleController.formatString("AccDescrSentDate", R.string.AccDescrSentDate, date)); + } else { + sb.append(LocaleController.formatString("AccDescrReceivedDate", R.string.AccDescrReceivedDate, date)); + } + sb.append(". "); + if (chat != null && !message.isOut() && message.isFromUser() && message.messageOwner.action == null) { + TLRPC.User fromUser = MessagesController.getInstance(currentAccount).getUser(message.messageOwner.from_id); + if (fromUser != null) { + sb.append(ContactsController.formatName(fromUser.first_name, fromUser.last_name)); + sb.append(". "); + } + } + if (encryptedChat == null) { + sb.append(message.messageText); + if (!message.isMediaEmpty()) { + if (!TextUtils.isEmpty(message.caption)) { + sb.append(". "); + sb.append(message.caption); + } + } + } + event.setContentDescription(sb.toString()); + } + + public void setClipProgress(float value) { + clipProgress = value; + invalidate(); + } + + public float getClipProgress() { + return clipProgress; + } + + public void setTopClip(int value) { + topClip = value; + } + + public void setBottomClip(int value) { + bottomClip = value; + } } 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 6b61ad09a..dadce8f68 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogMeUrlCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogMeUrlCell.java @@ -17,14 +17,15 @@ import android.text.TextUtils; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; +import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; -import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AvatarDrawable; @@ -108,8 +109,6 @@ public class DialogMeUrlCell extends BaseCell { drawNameBot = false; drawVerified = false; - TLObject image; - if (recentMeUrl instanceof TLRPC.TL_recentMeUrlChat) { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(recentMeUrl.chat_id); if (chat.id < 0 || ChatObject.isChannel(chat) && !chat.megagroup) { @@ -129,12 +128,8 @@ public class DialogMeUrlCell extends BaseCell { nameLeft = AndroidUtilities.dp(14); } nameString = chat.title; - if (chat.photo != null) { - image = chat.photo.photo_small; - } else { - image = null; - } avatarDrawable.setInfo(chat); + avatarImage.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, null, recentMeUrl, 0); } else if (recentMeUrl instanceof TLRPC.TL_recentMeUrlUser) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(recentMeUrl.user_id); if (!LocaleController.isRTL) { @@ -157,12 +152,8 @@ public class DialogMeUrlCell extends BaseCell { drawVerified = user.verified; } nameString = UserObject.getUserName(user); - if (user.photo != null) { - image = user.photo.photo_small; - } else { - image = null; - } avatarDrawable.setInfo(user); + avatarImage.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, null, recentMeUrl, 0); } else if (recentMeUrl instanceof TLRPC.TL_recentMeUrlStickerSet) { if (!LocaleController.isRTL) { nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); @@ -170,8 +161,8 @@ public class DialogMeUrlCell extends BaseCell { nameLeft = AndroidUtilities.dp(14); } nameString = recentMeUrl.set.set.title; - image = recentMeUrl.set.cover; avatarDrawable.setInfo(5, recentMeUrl.set.set.title, null, false); + avatarImage.setImage(ImageLocation.getForDocument(recentMeUrl.set.cover), null, avatarDrawable, null, recentMeUrl, 0); } else if (recentMeUrl instanceof TLRPC.TL_recentMeUrlChatInvite) { if (!LocaleController.isRTL) { nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); @@ -181,11 +172,6 @@ public class DialogMeUrlCell extends BaseCell { if (recentMeUrl.chat_invite.chat != null) { avatarDrawable.setInfo(recentMeUrl.chat_invite.chat); nameString = recentMeUrl.chat_invite.chat.title; - if (recentMeUrl.chat_invite.chat.photo != null) { - image = recentMeUrl.chat_invite.chat.photo.photo_small; - } else { - image = null; - } if (recentMeUrl.chat_invite.chat.id < 0 || ChatObject.isChannel(recentMeUrl.chat_invite.chat) && !recentMeUrl.chat_invite.chat.megagroup) { drawNameBroadcast = true; nameLockTop = AndroidUtilities.dp(16.5f); @@ -194,9 +180,9 @@ public class DialogMeUrlCell extends BaseCell { nameLockTop = AndroidUtilities.dp(17.5f); } drawVerified = recentMeUrl.chat_invite.chat.verified; + avatarImage.setImage(ImageLocation.getForChat(recentMeUrl.chat_invite.chat, false), "50_50", avatarDrawable, null, recentMeUrl, 0); } else { nameString = recentMeUrl.chat_invite.title; - image = recentMeUrl.chat_invite.photo.photo_small; avatarDrawable.setInfo(5, recentMeUrl.chat_invite.title, null, false); if (recentMeUrl.chat_invite.broadcast || recentMeUrl.chat_invite.channel) { drawNameBroadcast = true; @@ -205,6 +191,8 @@ public class DialogMeUrlCell extends BaseCell { drawNameGroup = true; nameLockTop = AndroidUtilities.dp(17.5f); } + TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(recentMeUrl.chat_invite.photo.sizes, 50); + avatarImage.setImage(ImageLocation.getForPhoto(size, recentMeUrl.chat_invite.photo), "50_50", avatarDrawable, null, recentMeUrl, 0); } if (!LocaleController.isRTL) { nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); @@ -220,12 +208,11 @@ public class DialogMeUrlCell extends BaseCell { nameLeft = AndroidUtilities.dp(14); } nameString = "Url"; - image = null; + avatarImage.setImage(null, null, avatarDrawable, null, recentMeUrl, 0); } else { - image = null; + avatarImage.setImage(null, null, avatarDrawable, null, recentMeUrl, 0); } messageString = MessagesController.getInstance(currentAccount).linkPrefix + "/" + recentMeUrl.url; - avatarImage.setImage(image, "50_50", avatarDrawable, null, recentMeUrl, 0); if (TextUtils.isEmpty(nameString)) { nameString = LocaleController.getString("HiddenName", R.string.HiddenName); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogsEmptyCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogsEmptyCell.java index f3b8d0108..554708b47 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogsEmptyCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogsEmptyCell.java @@ -12,8 +12,6 @@ import android.content.Context; import android.os.Build; import android.util.TypedValue; import android.view.Gravity; -import android.view.MotionEvent; -import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; @@ -43,19 +41,15 @@ public class DialogsEmptyCell extends LinearLayout { setGravity(Gravity.CENTER); setOrientation(VERTICAL); - setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - return true; - } - }); + setOnTouchListener((v, event) -> true); emptyTextView1 = new TextView(context); + emptyTextView1.setTextColor(Theme.getColor(Theme.key_chats_nameMessage_threeLines)); emptyTextView1.setText(LocaleController.getString("NoChats", R.string.NoChats)); - emptyTextView1.setTextColor(Theme.getColor(Theme.key_emptyListPlaceholder)); - emptyTextView1.setGravity(Gravity.CENTER); emptyTextView1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); - addView(emptyTextView1, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, 20, 0, 0)); + emptyTextView1.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + emptyTextView1.setGravity(Gravity.CENTER); + addView(emptyTextView1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 52, 4, 52, 0)); emptyTextView2 = new TextView(context); String help = LocaleController.getString("NoChatsHelp", R.string.NoChatsHelp); @@ -63,12 +57,11 @@ public class DialogsEmptyCell extends LinearLayout { help = help.replace('\n', ' '); } emptyTextView2.setText(help); - emptyTextView2.setTextColor(Theme.getColor(Theme.key_emptyListPlaceholder)); - emptyTextView2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + emptyTextView2.setTextColor(Theme.getColor(Theme.key_chats_message)); + emptyTextView2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); emptyTextView2.setGravity(Gravity.CENTER); - emptyTextView2.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(6), AndroidUtilities.dp(8), 0); emptyTextView2.setLineSpacing(AndroidUtilities.dp(2), 1); - addView(emptyTextView2, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, 0, 0, 20)); + addView(emptyTextView2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 52, 7, 52, 0)); } public void setType(int value) { @@ -101,7 +94,7 @@ public class DialogsEmptyCell extends LinearLayout { } super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(totalHeight, MeasureSpec.EXACTLY)); } else { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(totalHeight, MeasureSpec.AT_MOST)); + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(166), MeasureSpec.EXACTLY)); } } } 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 788a17cd1..a970f686e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java @@ -28,6 +28,8 @@ import android.widget.TextView; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.UserObject; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; @@ -85,6 +87,7 @@ public class DrawerProfileCell extends FrameLayout { arrowView = new ImageView(context); arrowView.setScaleType(ImageView.ScaleType.CENTER); + arrowView.setContentDescription(accountsShowed ? LocaleController.getString("AccDescrHideAccounts", R.string.AccDescrHideAccounts) : LocaleController.getString("AccDescrShowAccounts", R.string.AccDescrShowAccounts)); addView(arrowView, LayoutHelper.createFrame(59, 59, Gravity.RIGHT | Gravity.BOTTOM)); if (Theme.getEventType() == 0) { @@ -171,6 +174,7 @@ public class DrawerProfileCell extends FrameLayout { accountsShowed = !accountsShowed; arrowView.setImageResource(accountsShowed ? R.drawable.collapse_up : R.drawable.collapse_down); onClickListener.onClick(DrawerProfileCell.this); + arrowView.setContentDescription(accountsShowed ? LocaleController.getString("AccDescrHideAccounts", R.string.AccDescrHideAccounts) : LocaleController.getString("AccDescrShowAccounts", R.string.AccDescrShowAccounts)); }); } @@ -178,16 +182,12 @@ public class DrawerProfileCell extends FrameLayout { if (user == null) { return; } - TLRPC.FileLocation photo = null; - if (user.photo != null) { - photo = user.photo.photo_small; - } accountsShowed = accounts; arrowView.setImageResource(accountsShowed ? R.drawable.collapse_up : R.drawable.collapse_down); nameTextView.setText(UserObject.getUserName(user)); phoneTextView.setText(PhoneFormat.getInstance().format("+" + user.phone)); AvatarDrawable avatarDrawable = new AvatarDrawable(user); avatarDrawable.setColor(Theme.getColor(Theme.key_avatar_backgroundInProfileBlue)); - avatarImageView.setImage(photo, "50_50", avatarDrawable, user); + avatarImageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerUserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerUserCell.java index 4960db93c..9f9d4bf78 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerUserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerUserCell.java @@ -19,6 +19,7 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.NotificationsController; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; @@ -88,14 +89,8 @@ public class DrawerUserCell extends FrameLayout { } avatarDrawable.setInfo(user); textView.setText(ContactsController.formatName(user.first_name, user.last_name)); - TLRPC.FileLocation avatar; - if (user.photo != null && user.photo.photo_small != null && user.photo.photo_small.volume_id != 0 && user.photo.photo_small.local_id != 0) { - avatar = user.photo.photo_small; - } else { - avatar = null; - } imageView.getImageReceiver().setCurrentAccount(account); - imageView.setImage(avatar, "50_50", avatarDrawable, user); + imageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); checkBox.setVisibility(account == UserConfig.selectedAccount ? VISIBLE : INVISIBLE); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/EmojiReplacementCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/EmojiReplacementCell.java new file mode 100644 index 000000000..5d88f4ab2 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/EmojiReplacementCell.java @@ -0,0 +1,75 @@ +/* + * This is the source code of Telegram for Android v. 2.0.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.Cells; + +import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.Drawable; +import android.view.Gravity; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; + +public class EmojiReplacementCell extends FrameLayout { + + private ImageView imageView; + private String emoji; + + public EmojiReplacementCell(Context context) { + super(context); + + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.CENTER); + addView(imageView, LayoutHelper.createFrame(42, 42, Gravity.CENTER_HORIZONTAL, 0, 5, 0, 0)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(52) + getPaddingLeft() + getPaddingRight(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(54), MeasureSpec.EXACTLY)); + } + + public void setEmoji(String e, int side) { + emoji = e; + imageView.setImageDrawable(Emoji.getEmojiBigDrawable(e)); + if (side == -1) { + setBackgroundResource(R.drawable.stickers_back_left); + setPadding(AndroidUtilities.dp(7), 0, 0, 0); + } else if (side == 0) { + setBackgroundResource(R.drawable.stickers_back_center); + setPadding(0, 0, 0, 0); + } else if (side == 1) { + setBackgroundResource(R.drawable.stickers_back_right); + setPadding(0, 0, AndroidUtilities.dp(7), 0); + } else if (side == 2) { + setBackgroundResource(R.drawable.stickers_back_all); + setPadding(AndroidUtilities.dp(3), 0, AndroidUtilities.dp(3), 0); + } + Drawable background = getBackground(); + if (background != null) { + background.setAlpha(230); + background.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_stickersHintPanel), PorterDuff.Mode.MULTIPLY)); + } + } + + public String getEmoji() { + return emoji; + } + + @Override + public void invalidate() { + super.invalidate(); + imageView.invalidate(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/FeaturedStickerSetCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/FeaturedStickerSetCell.java index f59abbe6c..5ac83b1bd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/FeaturedStickerSetCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/FeaturedStickerSetCell.java @@ -32,6 +32,7 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DataQuery; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; @@ -227,12 +228,13 @@ public class FeaturedStickerSetCell extends FrameLayout { valueTextView.setText(LocaleController.formatPluralString("Stickers", set.set.count)); TLRPC.PhotoSize thumb = set.cover != null ? FileLoader.getClosestPhotoSizeWithSize(set.cover.thumbs, 90) : null; if (thumb != null && thumb.location != null) { - imageView.setImage(thumb, null, "webp", null, set); + imageView.setImage(ImageLocation.getForDocument(thumb, set.cover), null, "webp", null, set); + } else if (!set.covers.isEmpty()) { + TLRPC.Document document = set.covers.get(0); + thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); + imageView.setImage(ImageLocation.getForDocument(thumb, document), null, "webp", null, set); } else { - thumb = !set.covers.isEmpty() ? FileLoader.getClosestPhotoSizeWithSize(set.covers.get(0).thumbs, 90) : null; - if (thumb != null) { - imageView.setImage(thumb, null, "webp", null, set); - } + imageView.setImage(null, null, "webp", null, set); } if (sameSet) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GroupCreateUserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GroupCreateUserCell.java index 4762e8683..2e64de12b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GroupCreateUserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GroupCreateUserCell.java @@ -13,6 +13,7 @@ import android.view.Gravity; import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; @@ -165,7 +166,7 @@ public class GroupCreateUserCell extends FrameLayout { } } - avatarImageView.setImage(photo, "50_50", avatarDrawable, currentUser); + avatarImageView.setImage(ImageLocation.getForUser(currentUser, false), "50_50", avatarDrawable, currentUser); } @Override 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 806f3b142..1d6bbbe30 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java @@ -11,9 +11,11 @@ package org.telegram.ui.Cells; import android.animation.Animator; import android.animation.ObjectAnimator; import android.content.Context; +import android.os.Build; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.TextView; @@ -45,11 +47,9 @@ public class HeaderCell extends FrameLayout { textView = new TextView(getContext()); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - textView.setLines(1); - textView.setMaxLines(1); - textView.setSingleLine(true); textView.setEllipsize(TextUtils.TruncateAt.END); textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + textView.setMinHeight(AndroidUtilities.dp(height - topMargin)); if (dialog) { textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); } else { @@ -66,7 +66,7 @@ public class HeaderCell extends FrameLayout { } public void setHeight(int value) { - height = value; + textView.setMinHeight(AndroidUtilities.dp(height) - ((LayoutParams) textView.getLayoutParams()).topMargin); } public void setEnabled(boolean value, ArrayList animators) { @@ -79,7 +79,7 @@ public class HeaderCell extends FrameLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(height), MeasureSpec.EXACTLY)); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); } public void setText(String text) { @@ -96,4 +96,15 @@ public class HeaderCell extends FrameLayout { public SimpleTextView getTextView2() { return textView2; } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + AccessibilityNodeInfo.CollectionItemInfo collection = info.getCollectionItemInfo(); + if (collection != null) { + info.setCollectionItemInfo(AccessibilityNodeInfo.CollectionItemInfo.obtain(collection.getRowIndex(), collection.getRowSpan(), collection.getColumnIndex(), collection.getColumnSpan(), true)); + } + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HintDialogCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HintDialogCell.java index 2cae7c23a..c525455e5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HintDialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HintDialogCell.java @@ -21,6 +21,7 @@ import android.widget.FrameLayout; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.MessagesController; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; @@ -79,7 +80,7 @@ public class HintDialogCell extends FrameLayout { if (mask != 0 && (mask & MessagesController.UPDATE_MASK_READ_DIALOG_MESSAGE) == 0 && (mask & MessagesController.UPDATE_MASK_NEW_MESSAGE) == 0) { return; } - TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(dialog_id); + TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(dialog_id); if (dialog != null && dialog.unread_count != 0) { if (lastUnreadCount != dialog.unread_count) { lastUnreadCount = dialog.unread_count; @@ -114,8 +115,6 @@ public class HintDialogCell extends FrameLayout { public void setDialog(int uid, boolean counter, CharSequence name) { dialog_id = uid; - TLRPC.FileLocation photo = null; - Object parentObject; if (uid > 0) { currentUser = MessagesController.getInstance(currentAccount).getUser(uid); if (name != null) { @@ -126,10 +125,7 @@ public class HintDialogCell extends FrameLayout { nameTextView.setText(""); } avatarDrawable.setInfo(currentUser); - if (currentUser != null && currentUser.photo != null) { - photo = currentUser.photo.photo_small; - } - parentObject = currentUser; + imageView.setImage(ImageLocation.getForUser(currentUser, false), "50_50", avatarDrawable, currentUser); } else { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-uid); if (name != null) { @@ -140,13 +136,9 @@ public class HintDialogCell extends FrameLayout { nameTextView.setText(""); } avatarDrawable.setInfo(chat); - if (chat != null && chat.photo != null) { - photo = chat.photo.photo_small; - } - parentObject = chat; currentUser = null; + imageView.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, chat); } - imageView.setImage(photo, "50_50", avatarDrawable, parentObject); if (counter) { update(0); } else { @@ -169,7 +161,7 @@ public class HintDialogCell extends FrameLayout { countLayout.draw(canvas); canvas.restore(); } - if (currentUser != null && currentUser.status != null && currentUser.status.expires > ConnectionsManager.getInstance(currentAccount).getCurrentTime() || MessagesController.getInstance(currentAccount).onlinePrivacy.containsKey(currentUser.id)) { + if (currentUser != null && !currentUser.bot && (currentUser.status != null && currentUser.status.expires > ConnectionsManager.getInstance(currentAccount).getCurrentTime() || MessagesController.getInstance(currentAccount).onlinePrivacy.containsKey(currentUser.id))) { int top = AndroidUtilities.dp(53); int left = AndroidUtilities.dp(59); Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite)); 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 9b0474a8e..c33ad1902 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/JoinSheetUserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/JoinSheetUserCell.java @@ -17,6 +17,7 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; @@ -57,11 +58,7 @@ public class JoinSheetUserCell extends FrameLayout { public void setUser(TLRPC.User user) { nameTextView.setText(ContactsController.formatName(user.first_name, user.last_name)); avatarDrawable.setInfo(user); - TLRPC.FileLocation photo = null; - if (user != null && user.photo != null) { - photo = user.photo.photo_small; - } - imageView.setImage(photo, "50_50", avatarDrawable, user); + imageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); } public void setCount(int count) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ManageChatUserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ManageChatUserCell.java index 3b76b95be..ac73615ed 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ManageChatUserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ManageChatUserCell.java @@ -17,6 +17,7 @@ import android.widget.FrameLayout; import android.widget.ImageView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; @@ -98,6 +99,7 @@ public class ManageChatUserCell extends FrameLayout { optionsButton.setScaleType(ImageView.ScaleType.CENTER); addView(optionsButton, LayoutHelper.createFrame(52, 64, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP)); optionsButton.setOnClickListener(v -> delegate.onOptionsButtonCheck(ManageChatUserCell.this, true)); + optionsButton.setContentDescription(LocaleController.getString("AccDescrUserOptions", R.string.AccDescrUserOptions)); } } @@ -211,7 +213,8 @@ public class ManageChatUserCell extends FrameLayout { } } } - avatarImageView.setImage(photo, "50_50", avatarDrawable, currentUser); + lastAvatar = photo; + avatarImageView.setImage(ImageLocation.getForUser(currentUser, false), "50_50", avatarDrawable, currentUser); } public void recycle() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java index 64688cf48..c7f9dc910 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java @@ -16,8 +16,9 @@ import android.widget.LinearLayout; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.DataQuery; import org.telegram.messenger.Emoji; -import org.telegram.messenger.EmojiSuggestion; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.UserObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; @@ -75,7 +76,7 @@ public class MentionCell extends LinearLayout { } avatarDrawable.setInfo(user); if (user.photo != null && user.photo.photo_small != null) { - imageView.setImage(user.photo.photo_small, "50_50", avatarDrawable, user); + imageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); } else { imageView.setImageDrawable(avatarDrawable); } @@ -101,13 +102,13 @@ public class MentionCell extends LinearLayout { nameTextView.invalidate(); } - public void setEmojiSuggestion(EmojiSuggestion suggestion) { + public void setEmojiSuggestion(DataQuery.KeywordResult suggestion) { imageView.setVisibility(INVISIBLE); usernameTextView.setVisibility(INVISIBLE); - StringBuilder stringBuilder = new StringBuilder(suggestion.emoji.length() + suggestion.label.length() + 3); + StringBuilder stringBuilder = new StringBuilder(suggestion.emoji.length() + suggestion.keyword.length() + 4); stringBuilder.append(suggestion.emoji); - stringBuilder.append(" "); - stringBuilder.append(suggestion.label); + stringBuilder.append(" :"); + stringBuilder.append(suggestion.keyword); nameTextView.setText(Emoji.replaceEmoji(stringBuilder, nameTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false)); } @@ -116,7 +117,7 @@ public class MentionCell extends LinearLayout { imageView.setVisibility(VISIBLE); avatarDrawable.setInfo(user); if (user.photo != null && user.photo.photo_small != null) { - imageView.setImage(user.photo.photo_small, "50_50", avatarDrawable, user); + imageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); } else { imageView.setImageDrawable(avatarDrawable); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/NotificationsCheckCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/NotificationsCheckCell.java index fa3bd4c24..97a644c54 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/NotificationsCheckCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/NotificationsCheckCell.java @@ -63,6 +63,7 @@ public class NotificationsCheckCell extends FrameLayout { checkBox = new Switch(context); checkBox.setColors(Theme.key_switchTrack, Theme.key_switchTrackChecked, Theme.key_windowBackgroundWhite, Theme.key_windowBackgroundWhite); addView(checkBox, LayoutHelper.createFrame(37, 40, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 21, 0, 21, 0)); + checkBox.setFocusable(true); } @Override @@ -103,6 +104,7 @@ public class NotificationsCheckCell extends FrameLayout { valueTextView.setEllipsize(TextUtils.TruncateAt.END); valueTextView.setPadding(0, 0, 0, 0); } + checkBox.setContentDescription(text); } public void setDrawLine(boolean value) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PaymentInfoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PaymentInfoCell.java index 3d10656b5..da858bba3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PaymentInfoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PaymentInfoCell.java @@ -16,6 +16,7 @@ import android.widget.FrameLayout; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.WebFile; import org.telegram.tgnet.TLRPC; @@ -101,7 +102,8 @@ public class PaymentInfoCell extends FrameLayout { detailTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 10 : 123, 33, LocaleController.isRTL ? 123 : 10, 0)); detailExTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 10 : 123, 90, LocaleController.isRTL ? 123 : 10, 0)); imageView.setVisibility(VISIBLE); - imageView.getImageReceiver().setImage(WebFile.createWithWebDocument(invoice.photo), String.format(Locale.US, "%d_%d", width, height), null, null, null, -1, null, invoice, 1); + String filter = String.format(Locale.US, "%d_%d", width, height); + imageView.getImageReceiver().setImage(ImageLocation.getForWebFile(WebFile.createWithWebDocument(invoice.photo)), filter, null, null, -1, null, invoice, 1); } else { nameTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 9, 17, 0)); detailTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 33, 17, 0)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachCameraCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachCameraCell.java index 837ecf6a3..376637e5f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachCameraCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachCameraCell.java @@ -33,6 +33,7 @@ public class PhotoAttachCameraCell extends FrameLayout { imageView.setImageResource(R.drawable.instant_camera); imageView.setBackgroundColor(0xff000000); addView(imageView, LayoutHelper.createFrame(80, 80)); + setFocusable(true); } @Override 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 4f7e624eb..646e7a30a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java @@ -14,17 +14,23 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; import android.graphics.Rect; +import android.os.Build; +import android.os.Bundle; +import android.os.SystemClock; import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; import android.view.SoundEffectConstants; import android.view.View; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.R; import org.telegram.ui.Components.BackupImageView; @@ -73,6 +79,7 @@ public class PhotoAttachPhotoCell extends FrameLayout { videoTextView = new TextView(context); videoTextView.setTextColor(0xffffffff); videoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + videoTextView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); videoInfoContainer.addView(videoTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 18, -0.7f, 0, 0)); checkBox = new CheckBox(context, R.drawable.checkbig); @@ -82,6 +89,7 @@ public class PhotoAttachPhotoCell extends FrameLayout { checkBox.setColor(0xff3ccaef, 0xffffffff); addView(checkBox, LayoutHelper.createFrame(30, 30, Gravity.LEFT | Gravity.TOP, 46, 4, 0, 0)); checkBox.setVisibility(VISIBLE); + setFocusable(true); } public void setIsVertical(boolean value) { @@ -214,6 +222,7 @@ public class PhotoAttachPhotoCell extends FrameLayout { getParent().requestDisallowInterceptTouchEvent(true); pressed = false; playSoundEffect(SoundEffectConstants.CLICK); + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); delegate.onCheckClick(this); invalidate(); } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { @@ -232,4 +241,30 @@ public class PhotoAttachPhotoCell extends FrameLayout { return result; } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + if (photoEntry.isVideo) { + info.setText(LocaleController.getString("AttachVideo", R.string.AttachVideo) + ", " + LocaleController.formatCallDuration(photoEntry.duration)); + } else { + info.setText(LocaleController.getString("AttachPhoto", R.string.AttachPhoto)); + } + if (checkBox.isChecked()) + info.setSelected(true); + if (Build.VERSION.SDK_INT >= 21) { + info.addAction(new AccessibilityNodeInfo.AccessibilityAction(R.id.acc_action_open_photo, LocaleController.getString("Open", R.string.Open))); + } + } + + @Override + public boolean performAccessibilityAction(int action, Bundle arguments) { + if (action == R.id.acc_action_open_photo) { + View parent = (View)getParent(); + parent.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, getLeft(), getTop() + getHeight() - 1, 0)); + parent.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, getLeft(), getTop() + getHeight() - 1, 0)); + } + return super.performAccessibilityAction(action, arguments); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java index d4c8d522b..323beb45a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java @@ -23,6 +23,7 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.MediaController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.R; @@ -66,6 +67,7 @@ public class PhotoPickerPhotoCell extends FrameLayout { videoTextView = new TextView(context); videoTextView.setTextColor(0xffffffff); videoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + videoTextView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); videoInfoContainer.addView(videoTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 18, -0.7f, 0, 0)); checkBox = new CheckBox(context, R.drawable.checkbig); @@ -74,6 +76,8 @@ public class PhotoPickerPhotoCell extends FrameLayout { checkBox.setDrawBackground(true); checkBox.setColor(0xff66bffa, 0xffffffff); addView(checkBox, LayoutHelper.createFrame(zoom ? 30 : 26, zoom ? 30 : 26, Gravity.RIGHT | Gravity.TOP, 0, 4, 4, 0)); + + setFocusable(true); } @Override @@ -110,16 +114,16 @@ public class PhotoPickerPhotoCell extends FrameLayout { public void setImage(MediaController.SearchImage searchImage) { Drawable thumb = getResources().getDrawable(R.drawable.nophotos); if (searchImage.thumbPhotoSize != null) { - photoImage.setImage(searchImage.thumbPhotoSize, null, thumb, searchImage); + photoImage.setImage(ImageLocation.getForPhoto(searchImage.thumbPhotoSize, searchImage.photo), null, thumb, searchImage); } else if (searchImage.photoSize != null) { - photoImage.setImage(searchImage.photoSize, "80_80", thumb, searchImage); + photoImage.setImage(ImageLocation.getForPhoto(searchImage.photoSize, searchImage.photo), "80_80", thumb, searchImage); } else if (searchImage.thumbPath != null) { photoImage.setImage(searchImage.thumbPath, null, thumb); } else if (searchImage.thumbUrl != null && searchImage.thumbUrl.length() > 0) { photoImage.setImage(searchImage.thumbUrl, null, thumb); - } else if (searchImage.document != null && MessageObject.isDocumentHasThumb(searchImage.document)) { - TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(searchImage.document.thumbs, 90); - photoImage.setImage(photoSize, null, thumb, searchImage); + } else if (MessageObject.isDocumentHasThumb(searchImage.document)) { + TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(searchImage.document.thumbs, 320); + photoImage.setImage(ImageLocation.getForDocument(photoSize, searchImage.document), null, thumb, searchImage); } else { photoImage.setImageDrawable(thumb); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PollEditTextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PollEditTextCell.java index c38583918..c82ce581d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PollEditTextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PollEditTextCell.java @@ -72,6 +72,7 @@ public class PollEditTextCell extends FrameLayout { deleteImageView.setImageResource(R.drawable.msg_panel_clear); deleteImageView.setOnClickListener(onDelete); deleteImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText), PorterDuff.Mode.MULTIPLY)); + deleteImageView.setContentDescription(LocaleController.getString("Delete", R.string.Delete)); addView(deleteImageView, LayoutHelper.createFrame(48, 50, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, LocaleController.isRTL ? 3 : 0, 0, LocaleController.isRTL ? 0 : 3, 0)); textView2 = new SimpleTextView(getContext()); 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 887a394e0..0af35368f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java @@ -15,10 +15,12 @@ import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; +import android.view.accessibility.AccessibilityNodeInfo; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; @@ -250,7 +252,7 @@ public class ProfileSearchCell extends BaseCell { } else { nameLeft = AndroidUtilities.dp(11); } - if (user.bot) { + if (user.bot && !MessagesController.isSupportUser(user)) { drawNameBot = true; if (!LocaleController.isRTL) { nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); @@ -311,7 +313,7 @@ public class ProfileSearchCell extends BaseCell { onlineWidth -= getPaddingLeft() + getPaddingRight(); if (drawCount) { - TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(dialog_id); + TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(dialog_id); if (dialog != null && dialog.unread_count != 0) { lastUnreadCount = dialog.unread_count; String countString = String.format("%d", dialog.unread_count); @@ -350,7 +352,9 @@ public class ProfileSearchCell extends BaseCell { if (subLabel != null) { onlineString = subLabel; } else if (user != null) { - if (user.bot) { + if (MessagesController.isSupportUser(user)) { + onlineString = LocaleController.getString("SupportStatus", R.string.SupportStatus); + } else if (user.bot) { onlineString = LocaleController.getString("Bot", R.string.Bot); } else if (user.id == 333000 || user.id == 777000) { onlineString = LocaleController.getString("ServiceNotifications", R.string.ServiceNotifications); @@ -437,29 +441,32 @@ public class ProfileSearchCell extends BaseCell { public void update(int mask) { TLRPC.FileLocation photo = null; - Object parentObject = null; if (user != null) { avatarDrawable.setInfo(user); if (savedMessages) { - avatarDrawable.setSavedMessages(1); - } else if (user.photo != null) { - photo = user.photo.photo_small; + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_SAVED); + avatarImage.setImage(null, null, avatarDrawable, null, null, 0); + } else { + if (user.photo != null) { + photo = user.photo.photo_small; + } + avatarImage.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, null, user, 0); } - parentObject = user; } else if (chat != null) { if (chat.photo != null) { photo = chat.photo.photo_small; } avatarDrawable.setInfo(chat); - parentObject = chat; + avatarImage.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, null, chat, 0); } else { avatarDrawable.setInfo(0, null, null, false); + avatarImage.setImage(null, null, avatarDrawable, null, null, 0); } if (mask != 0) { boolean continueUpdate = false; if ((mask & MessagesController.UPDATE_MASK_AVATAR) != 0 && user != null || (mask & MessagesController.UPDATE_MASK_CHAT_AVATAR) != 0 && chat != null) { - if (lastAvatar != null && photo == null || lastAvatar == null && photo != null && lastAvatar != null && photo != null && (lastAvatar.volume_id != photo.volume_id || lastAvatar.local_id != photo.local_id)) { + if (lastAvatar != null && photo == null || lastAvatar == null && photo != null || lastAvatar != null && photo != null && (lastAvatar.volume_id != photo.volume_id || lastAvatar.local_id != photo.local_id)) { continueUpdate = true; } } @@ -484,7 +491,7 @@ public class ProfileSearchCell extends BaseCell { } } if (!continueUpdate && drawCount && (mask & MessagesController.UPDATE_MASK_READ_DIALOG_MESSAGE) != 0) { - TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(dialog_id); + TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(dialog_id); if (dialog != null && dialog.unread_count != lastUnreadCount) { continueUpdate = true; } @@ -507,7 +514,6 @@ public class ProfileSearchCell extends BaseCell { } lastAvatar = photo; - avatarImage.setImage(photo, "50_50", avatarDrawable, null, parentObject, 0); if (getMeasuredWidth() != 0 || getMeasuredHeight() != 0) { buildLayout(); @@ -588,4 +594,10 @@ public class ProfileSearchCell extends BaseCell { avatarImage.draw(canvas); } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setText(nameLayout.getText() + ", " + subLabel); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioButtonCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioButtonCell.java index 18b1485a6..05241c71d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioButtonCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioButtonCell.java @@ -13,6 +13,7 @@ import android.graphics.Canvas; import android.util.TypedValue; import android.view.Gravity; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.TextView; @@ -95,4 +96,12 @@ public class RadioButtonCell extends FrameLayout { canvas.drawLine(AndroidUtilities.dp(LocaleController.isRTL ? 0 : 60), getHeight() - 1, getMeasuredWidth() - AndroidUtilities.dp(LocaleController.isRTL ? 60 : 0), getHeight() - 1, Theme.dividerPaint); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.RadioButton"); + info.setCheckable(true); + info.setChecked(radioButton.isChecked()); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioCell.java index 1b78e8aed..39da2953c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioCell.java @@ -15,6 +15,7 @@ import android.graphics.Canvas; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.TextView; @@ -107,4 +108,12 @@ public class RadioCell extends FrameLayout { canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(20), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.RadioButton"); + info.setCheckable(true); + info.setChecked(isChecked()); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioColorCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioColorCell.java index b97113879..737a879d8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioColorCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioColorCell.java @@ -11,6 +11,7 @@ package org.telegram.ui.Cells; import android.content.Context; import android.util.TypedValue; import android.view.Gravity; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.TextView; @@ -60,4 +61,12 @@ public class RadioColorCell extends FrameLayout { public void setChecked(boolean checked, boolean animated) { radioButton.setChecked(checked, animated); } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.RadioButton"); + info.setCheckable(true); + info.setChecked(radioButton.isChecked()); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java index 339889818..f45fbb681 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java @@ -18,6 +18,7 @@ import android.widget.LinearLayout; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; @@ -182,13 +183,7 @@ public class SessionCell extends FrameLayout { if (user != null) { avatarDrawable.setInfo(user); name = UserObject.getFirstName(user); - TLRPC.FileLocation currentPhoto; - if (user.photo != null) { - currentPhoto = user.photo.photo_small; - } else { - currentPhoto = null; - } - imageView.setImage(currentPhoto, "50_50", avatarDrawable, user); + imageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); } else { name = ""; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SettingsSearchCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SettingsSearchCell.java new file mode 100644 index 000000000..9303ee1db --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SettingsSearchCell.java @@ -0,0 +1,205 @@ +package org.telegram.ui.Cells; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.text.style.ImageSpan; +import android.util.TypedValue; +import android.view.Gravity; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; + +public class SettingsSearchCell extends FrameLayout { + + private TextView textView; + private TextView valueTextView; + private ImageView imageView; + private boolean needDivider; + private int left; + + public class VerticalImageSpan extends ImageSpan { + + public VerticalImageSpan(Drawable drawable) { + super(drawable); + } + + @Override + public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fontMetricsInt) { + Drawable drawable = getDrawable(); + Rect rect = drawable.getBounds(); + if (fontMetricsInt != null) { + Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt(); + int fontHeight = fmPaint.descent - fmPaint.ascent; + int drHeight = rect.bottom - rect.top; + int centerY = fmPaint.ascent + fontHeight / 2; + + fontMetricsInt.ascent = centerY - drHeight / 2; + fontMetricsInt.top = fontMetricsInt.ascent; + fontMetricsInt.bottom = centerY + drHeight / 2; + fontMetricsInt.descent = fontMetricsInt.bottom; + } + return rect.right; + } + + @Override + public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { + Drawable drawable = getDrawable(); + canvas.save(); + Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt(); + int fontHeight = fmPaint.descent - fmPaint.ascent; + int centerY = y + fmPaint.descent - fontHeight / 2; + int transY = centerY - (drawable.getBounds().bottom - drawable.getBounds().top) / 2; + canvas.translate(x, transY); + if (LocaleController.isRTL) { + canvas.scale(-1, 1, drawable.getIntrinsicWidth() / 2, drawable.getIntrinsicHeight() / 2); + } + drawable.draw(canvas); + canvas.restore(); + } + } + + public SettingsSearchCell(Context context) { + super(context); + + textView = new TextView(context); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + textView.setLines(1); + textView.setMaxLines(1); + textView.setSingleLine(true); + textView.setEllipsize(TextUtils.TruncateAt.END); + addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 16 : 71, 10, LocaleController.isRTL ? 71 : 16, 0)); + + valueTextView = new TextView(context); + valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2)); + valueTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + valueTextView.setLines(1); + valueTextView.setMaxLines(1); + valueTextView.setSingleLine(true); + valueTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 16 : 71, 33, LocaleController.isRTL ? 71 : 16, 0)); + + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.CENTER); + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.MULTIPLY)); + addView(imageView, LayoutHelper.createFrame(48, 48, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 10, 8, 10, 0)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(64) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY)); + } + + public void setTextAndValueAndIcon(CharSequence text, String[] value, int icon, boolean divider) { + textView.setText(text); + LayoutParams layoutParams = (LayoutParams) textView.getLayoutParams(); + layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 16 : 71); + layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 71 : 16); + + if (value != null) { + SpannableStringBuilder builder = new SpannableStringBuilder(); + for (int a = 0; a < value.length; a++) { + if (a != 0) { + builder.append(" > "); + Drawable drawable = getContext().getResources().getDrawable(R.drawable.settings_arrow).mutate(); + drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); + drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), PorterDuff.Mode.MULTIPLY)); + builder.setSpan(new VerticalImageSpan(drawable), builder.length() - 2, builder.length() - 1, SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE); + } + builder.append(value[a]); + } + valueTextView.setText(builder); + valueTextView.setVisibility(VISIBLE); + layoutParams.topMargin = AndroidUtilities.dp(10); + + layoutParams = (LayoutParams) valueTextView.getLayoutParams(); + layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 16 : 71); + layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 71 : 16); + } else { + layoutParams.topMargin = AndroidUtilities.dp(21); + valueTextView.setVisibility(GONE); + } + if (icon != 0) { + imageView.setImageResource(icon); + imageView.setVisibility(VISIBLE); + } else { + imageView.setVisibility(GONE); + } + left = 69; + needDivider = divider; + setWillNotDraw(!needDivider); + } + + public void setTextAndValue(CharSequence text, String[] value, boolean faq, boolean divider) { + LayoutParams layoutParams = (LayoutParams) textView.getLayoutParams(); + if (faq) { + valueTextView.setText(text); + SpannableStringBuilder builder = new SpannableStringBuilder(); + for (int a = 0; a < value.length; a++) { + if (a != 0) { + builder.append(" > "); + Drawable drawable = getContext().getResources().getDrawable(R.drawable.settings_arrow).mutate(); + drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); + drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.MULTIPLY)); + builder.setSpan(new VerticalImageSpan(drawable), builder.length() - 2, builder.length() - 1, SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE); + } + builder.append(value[a]); + } + textView.setText(builder); + valueTextView.setVisibility(VISIBLE); + layoutParams.topMargin = AndroidUtilities.dp(10); + } else { + textView.setText(text); + if (value != null) { + SpannableStringBuilder builder = new SpannableStringBuilder(); + for (int a = 0; a < value.length; a++) { + if (a != 0) { + builder.append(" > "); + Drawable drawable = getContext().getResources().getDrawable(R.drawable.settings_arrow).mutate(); + drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); + drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), PorterDuff.Mode.MULTIPLY)); + builder.setSpan(new VerticalImageSpan(drawable), builder.length() - 2, builder.length() - 1, SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE); + } + builder.append(value[a]); + } + valueTextView.setText(builder); + valueTextView.setVisibility(VISIBLE); + layoutParams.topMargin = AndroidUtilities.dp(10); + } else { + layoutParams.topMargin = AndroidUtilities.dp(21); + valueTextView.setVisibility(GONE); + } + } + + layoutParams.leftMargin = layoutParams.rightMargin = AndroidUtilities.dp(16); + + layoutParams = (LayoutParams) valueTextView.getLayoutParams(); + layoutParams.leftMargin = layoutParams.rightMargin = AndroidUtilities.dp(16); + + imageView.setVisibility(GONE); + needDivider = divider; + setWillNotDraw(!needDivider); + left = 16; + } + + @Override + protected void onDraw(Canvas canvas) { + if (needDivider) { + canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(left), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(left) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShareDialogCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShareDialogCell.java index aec4cfaa4..59de24883 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShareDialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShareDialogCell.java @@ -9,41 +9,52 @@ package org.telegram.ui.Cells; import android.content.Context; +import android.graphics.Canvas; +import android.os.SystemClock; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.View; import android.widget.FrameLayout; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; +import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.BackupImageView; -import org.telegram.ui.Components.CheckBox; +import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.LayoutHelper; public class ShareDialogCell extends FrameLayout { private BackupImageView imageView; private TextView nameTextView; - private CheckBox checkBox; + private CheckBox2 checkBox; private AvatarDrawable avatarDrawable = new AvatarDrawable(); + private TLRPC.User user; + + private float onlineProgress; + private long lastUpdateTime; private int currentAccount = UserConfig.selectedAccount; public ShareDialogCell(Context context) { super(context); + setWillNotDraw(false); + imageView = new BackupImageView(context); - imageView.setRoundRadius(AndroidUtilities.dp(27)); - addView(imageView, LayoutHelper.createFrame(54, 54, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 7, 0, 0)); + imageView.setRoundRadius(AndroidUtilities.dp(28)); + addView(imageView, LayoutHelper.createFrame(56, 56, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 7, 0, 0)); nameTextView = new TextView(context); nameTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); @@ -52,30 +63,34 @@ public class ShareDialogCell extends FrameLayout { nameTextView.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL); nameTextView.setLines(2); nameTextView.setEllipsize(TextUtils.TruncateAt.END); - addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 6, 64, 6, 0)); + addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 6, 66, 6, 0)); - checkBox = new CheckBox(context, R.drawable.round_check2); - checkBox.setSize(24); - checkBox.setCheckOffset(AndroidUtilities.dp(1)); - checkBox.setVisibility(VISIBLE); - checkBox.setColor(Theme.getColor(Theme.key_dialogRoundCheckBox), Theme.getColor(Theme.key_dialogRoundCheckBoxCheck)); - addView(checkBox, LayoutHelper.createFrame(24, 24, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 17, 39, 0, 0)); + checkBox = new CheckBox2(context); + checkBox.setSize(21); + checkBox.setColor(Theme.key_dialogRoundCheckBox, Theme.key_dialogBackground, Theme.key_dialogRoundCheckBoxCheck); + checkBox.setDrawUnchecked(false); + checkBox.setDrawBackgroundAsArc(4); + checkBox.setProgressDelegate(progress -> { + float scale = 1.0f - (1.0f - 0.857f) * checkBox.getProgress(); + imageView.setScaleX(scale); + imageView.setScaleY(scale); + }); + addView(checkBox, LayoutHelper.createFrame(24, 24, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 19, 42, 0, 0)); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(100), MeasureSpec.EXACTLY)); + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(103), MeasureSpec.EXACTLY)); } public void setDialog(int uid, boolean checked, CharSequence name) { - TLRPC.FileLocation photo = null; - Object parentObject; if (uid > 0) { - TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(uid); + user = MessagesController.getInstance(currentAccount).getUser(uid); avatarDrawable.setInfo(user); if (UserObject.isUserSelf(user)) { nameTextView.setText(LocaleController.getString("SavedMessages", R.string.SavedMessages)); - avatarDrawable.setSavedMessages(1); + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_SAVED); + imageView.setImage(null, null, avatarDrawable, user); } else { if (name != null) { nameTextView.setText(name); @@ -84,12 +99,10 @@ public class ShareDialogCell extends FrameLayout { } else { nameTextView.setText(""); } - if (user != null && user.photo != null) { - photo = user.photo.photo_small; - } + imageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); } - parentObject = user; } else { + user = null; TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-uid); if (name != null) { nameTextView.setText(name); @@ -99,16 +112,66 @@ public class ShareDialogCell extends FrameLayout { nameTextView.setText(""); } avatarDrawable.setInfo(chat); - if (chat != null && chat.photo != null) { - photo = chat.photo.photo_small; - } - parentObject = chat; + imageView.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, chat); } - imageView.setImage(photo, "50_50", avatarDrawable, parentObject); checkBox.setChecked(checked, false); } public void setChecked(boolean checked, boolean animated) { checkBox.setChecked(checked, animated); } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + boolean result = super.drawChild(canvas, child, drawingTime); + if (child == imageView) { + if (user != null && !MessagesController.isSupportUser(user)) { + long newTime = SystemClock.uptimeMillis(); + long dt = newTime - lastUpdateTime; + if (dt > 17) { + dt = 17; + } + lastUpdateTime = newTime; + + boolean isOnline = !user.self && !user.bot && (user.status != null && user.status.expires > ConnectionsManager.getInstance(currentAccount).getCurrentTime() || MessagesController.getInstance(currentAccount).onlinePrivacy.containsKey(user.id)); + if (isOnline || onlineProgress != 0) { + int top = imageView.getBottom() - AndroidUtilities.dp(6); + int left = imageView.getRight() - AndroidUtilities.dp(10); + Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + canvas.drawCircle(left, top, AndroidUtilities.dp(7) * onlineProgress, Theme.dialogs_onlineCirclePaint); + Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_chats_onlineCircle)); + canvas.drawCircle(left, top, AndroidUtilities.dp(5) * onlineProgress, Theme.dialogs_onlineCirclePaint); + if (isOnline) { + if (onlineProgress < 1.0f) { + onlineProgress += dt / 150.0f; + if (onlineProgress > 1.0f) { + onlineProgress = 1.0f; + } + imageView.invalidate(); + invalidate(); + } + } else { + if (onlineProgress > 0.0f) { + onlineProgress -= dt / 150.0f; + if (onlineProgress < 0.0f) { + onlineProgress = 0.0f; + } + imageView.invalidate(); + invalidate(); + } + } + } + } + } + return result; + } + + @Override + protected void onDraw(Canvas canvas) { + int cx = imageView.getLeft() + imageView.getMeasuredWidth() / 2; + int cy = imageView.getTop() + imageView.getMeasuredHeight() / 2; + Theme.checkboxSquare_checkPaint.setColor(Theme.getColor(Theme.key_dialogRoundCheckBox)); + Theme.checkboxSquare_checkPaint.setAlpha((int) (checkBox.getProgress() * 255)); + canvas.drawCircle(cx, cy, AndroidUtilities.dp(28), Theme.checkboxSquare_checkPaint); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java index 0f0e719eb..c066b4300 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java @@ -9,6 +9,7 @@ import android.text.TextUtils; import android.view.Gravity; import android.view.MotionEvent; import android.view.SoundEffectConstants; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; @@ -24,14 +25,14 @@ import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; -import org.telegram.ui.Components.CheckBox; +import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.MediaActionDrawable; import org.telegram.ui.Components.RadialProgress2; public class SharedAudioCell extends FrameLayout implements DownloadController.FileDownloadProgressListener { - private CheckBox checkBox; + private CheckBox2 checkBox; private boolean needDivider; @@ -57,6 +58,7 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F public SharedAudioCell(Context context) { super(context); + setFocusable(true); radialProgress = new RadialProgress2(this); radialProgress.setColors(Theme.key_chat_inLoader, Theme.key_chat_inLoaderSelected, Theme.key_chat_inMediaIcon, Theme.key_chat_inMediaIconSelected); @@ -64,10 +66,13 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F TAG = DownloadController.getInstance(currentAccount).generateObserverTag(); setWillNotDraw(false); - checkBox = new CheckBox(context, R.drawable.round_check2); + checkBox = new CheckBox2(context); checkBox.setVisibility(INVISIBLE); - checkBox.setColor(Theme.getColor(Theme.key_checkbox), Theme.getColor(Theme.key_checkboxCheck)); - addView(checkBox, LayoutHelper.createFrame(20, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 40, 34, LocaleController.isRTL ? 40 : 0, 0)); + checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck); + checkBox.setSize(21); + checkBox.setDrawUnchecked(false); + checkBox.setDrawBackgroundAsArc(3); + addView(checkBox, LayoutHelper.createFrame(24, 24, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 38, 32, LocaleController.isRTL ? 39 : 0, 0)); } @SuppressLint("DrawAllocation") @@ -113,13 +118,13 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F TLRPC.PhotoSize thumb = document != null ? FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90) : null; if (thumb instanceof TLRPC.TL_photoSize) { - radialProgress.setImageOverlay(thumb, messageObject); + radialProgress.setImageOverlay(thumb, document, messageObject); } else { String artworkUrl = messageObject.getArtworkUrl(true); if (!TextUtils.isEmpty(artworkUrl)) { radialProgress.setImageOverlay(artworkUrl); } else { - radialProgress.setImageOverlay(null, null); + radialProgress.setImageOverlay(null, null, null); } } updateButtonState(false, false); @@ -392,7 +397,7 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F @Override public void onSuccessDownload(String fileName) { radialProgress.setProgress(1, true); - updateButtonState(false,true); + updateButtonState(false, true); } @Override @@ -422,5 +427,19 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F protected boolean needPlayMessage(MessageObject messageObject) { return false; } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (currentMessageObject.isMusic()) { + info.setText(LocaleController.formatString("AccDescrMusicInfo", R.string.AccDescrMusicInfo, currentMessageObject.getMusicAuthor(), currentMessageObject.getMusicTitle())); + } else { // voice message + info.setText(titleLayout.getText() + ", " + descriptionLayout.getText()); + } + if (checkBox.isChecked()) { + info.setCheckable(true); + info.setChecked(true); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java index e7a166c9e..939fb32be 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java @@ -16,6 +16,7 @@ import android.graphics.drawable.Drawable; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -23,6 +24,7 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DownloadController; import org.telegram.messenger.ImageLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.FileLoader; @@ -31,7 +33,7 @@ import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.BackupImageView; -import org.telegram.ui.Components.CheckBox; +import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LineProgressView; @@ -46,7 +48,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle private TextView dateTextView; private ImageView statusImageView; private LineProgressView progressView; - private CheckBox checkBox; + private CheckBox2 checkBox; private boolean needDivider; @@ -74,6 +76,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle extTextView.setSingleLine(true); extTextView.setGravity(Gravity.CENTER); extTextView.setEllipsize(TextUtils.TruncateAt.END); + extTextView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); addView(extTextView, LayoutHelper.createFrame(32, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 16, 22, LocaleController.isRTL ? 16 : 0, 0)); thumbImageView = new BackupImageView(context) { @@ -121,10 +124,13 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle progressView.setProgressColor(Theme.getColor(Theme.key_sharedMedia_startStopLoadIcon)); addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 2, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 72, 54, LocaleController.isRTL ? 72 : 0, 0)); - checkBox = new CheckBox(context, R.drawable.round_check2); + checkBox = new CheckBox2(context); checkBox.setVisibility(INVISIBLE); - checkBox.setColor(Theme.getColor(Theme.key_checkbox), Theme.getColor(Theme.key_checkboxCheck)); - addView(checkBox, LayoutHelper.createFrame(22, 22, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 34, 30, LocaleController.isRTL ? 34 : 0, 0)); + checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck); + checkBox.setSize(21); + checkBox.setDrawUnchecked(false); + checkBox.setDrawBackgroundAsArc(2); + addView(checkBox, LayoutHelper.createFrame(24, 24, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 33, 28, LocaleController.isRTL ? 33 : 0, 0)); } public void setTextAndValueAndTypeAndThumb(String text, String value, String type, String thumb, int resId) { @@ -187,16 +193,11 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle loaded = false; loading = false; - if (messageObject != null && messageObject.getDocument() != null) { + TLRPC.Document document = messageObject.getDocument(); + if (messageObject != null && document != null) { int idx; String name = null; if (messageObject.isMusic()) { - TLRPC.Document document; - if (messageObject.type == 0) { - document = messageObject.messageOwner.media.webpage.document; - } else { - document = messageObject.messageOwner.media.document; - } for (int a = 0; a < document.attributes.size(); a++) { TLRPC.DocumentAttribute attribute = document.attributes.get(a); if (attribute instanceof TLRPC.TL_documentAttributeAudio) { @@ -206,27 +207,35 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle } } } - String fileName = FileLoader.getDocumentFileName(messageObject.getDocument()); + String fileName = FileLoader.getDocumentFileName(document); if (name == null) { name = fileName; } nameTextView.setText(name); placeholderImageView.setVisibility(VISIBLE); extTextView.setVisibility(VISIBLE); - placeholderImageView.setImageResource(AndroidUtilities.getThumbForNameOrMime(fileName, messageObject.getDocument().mime_type, false)); + placeholderImageView.setImageResource(AndroidUtilities.getThumbForNameOrMime(fileName, document.mime_type, false)); extTextView.setText((idx = fileName.lastIndexOf('.')) == -1 ? "" : fileName.substring(idx + 1).toLowerCase()); - TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.getDocument().thumbs, 90); + + TLRPC.PhotoSize bigthumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 320); + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 40); + if (thumb == bigthumb) { + bigthumb = null; + } if (thumb instanceof TLRPC.TL_photoSizeEmpty || thumb == null) { thumbImageView.setVisibility(INVISIBLE); thumbImageView.setImageBitmap(null); extTextView.setAlpha(1.0f); placeholderImageView.setAlpha(1.0f); } else { + thumbImageView.getImageReceiver().setNeedsQualityThumb(bigthumb == null); + thumbImageView.getImageReceiver().setShouldGenerateQualityThumb(bigthumb == null); + thumbImageView.setVisibility(VISIBLE); - thumbImageView.setImage(thumb, "40_40", (Drawable) null, messageObject); + thumbImageView.setImage(ImageLocation.getForDocument(bigthumb, document), "40_40", ImageLocation.getForDocument(thumb, document), "40_40_b", null, 0, 1, messageObject); } long date = (long) messageObject.messageOwner.date * 1000; - dateTextView.setText(String.format("%s, %s", AndroidUtilities.formatFileSize(messageObject.getDocument().size), LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, LocaleController.getInstance().formatterYear.format(new Date(date)), LocaleController.getInstance().formatterDay.format(new Date(date))))); + dateTextView.setText(String.format("%s, %s", AndroidUtilities.formatFileSize(document.size), LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, LocaleController.getInstance().formatterYear.format(new Date(date)), LocaleController.getInstance().formatterDay.format(new Date(date))))); } else { nameTextView.setText(""); extTextView.setText(""); @@ -351,4 +360,13 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle public int getObserverTag() { return TAG; } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (checkBox.isChecked()) { + info.setCheckable(true); + info.setChecked(true); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java index 1cb5e2a19..db9a8f549 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java @@ -21,18 +21,19 @@ import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.ViewConfiguration; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; -import org.telegram.messenger.R; import org.telegram.messenger.browser.Browser; import org.telegram.tgnet.TLRPC; -import org.telegram.ui.Components.CheckBox; +import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LetterDrawable; import org.telegram.ui.Components.LinkPath; @@ -45,7 +46,9 @@ public class SharedLinkCell extends FrameLayout { public interface SharedLinkCellDelegate { void needOpenWebView(TLRPC.WebPage webPage); + boolean canPerformActions(); + void onLinkLongPress(final String urlFinal); } @@ -109,7 +112,7 @@ public class SharedLinkCell extends FrameLayout { private ImageReceiver linkImageView; private boolean drawLinkImageView; private LetterDrawable letterDrawable; - private CheckBox checkBox; + private CheckBox2 checkBox; private SharedLinkCellDelegate delegate; @@ -135,6 +138,7 @@ public class SharedLinkCell extends FrameLayout { public SharedLinkCell(Context context) { super(context); + setFocusable(true); urlPath = new LinkPath(); urlPath.setUseRoundRect(true); @@ -153,10 +157,13 @@ public class SharedLinkCell extends FrameLayout { linkImageView.setRoundRadius(AndroidUtilities.dp(4)); letterDrawable = new LetterDrawable(); - checkBox = new CheckBox(context, R.drawable.round_check2); + checkBox = new CheckBox2(context); checkBox.setVisibility(INVISIBLE); - checkBox.setColor(Theme.getColor(Theme.key_checkbox), Theme.getColor(Theme.key_checkboxCheck)); - addView(checkBox, LayoutHelper.createFrame(22, 22, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 44, 44, LocaleController.isRTL ? 44 : 0, 0)); + checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck); + checkBox.setSize(21); + checkBox.setDrawUnchecked(false); + checkBox.setDrawBackgroundAsArc(2); + addView(checkBox, LayoutHelper.createFrame(24, 24, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 44, 44, LocaleController.isRTL ? 44 : 0, 0)); } @SuppressLint("DrawAllocation") @@ -330,7 +337,8 @@ public class SharedLinkCell extends FrameLayout { linkImageView.setImageCoords(x, AndroidUtilities.dp(11), maxPhotoWidth, maxPhotoWidth); String fileName = FileLoader.getAttachFileName(currentPhotoObject); String filter = String.format(Locale.US, "%d_%d", maxPhotoWidth, maxPhotoWidth); - linkImageView.setImage(currentPhotoObject, filter, currentPhotoObjectThumb, String.format(Locale.US, "%d_%d_b", maxPhotoWidth, maxPhotoWidth), 0, null, message, 0); + String thumbFilter = String.format(Locale.US, "%d_%d_b", maxPhotoWidth, maxPhotoWidth); + linkImageView.setImage(ImageLocation.getForObject(currentPhotoObject, message.photoThumbsObject), filter, ImageLocation.getForObject(currentPhotoObjectThumb, message.photoThumbsObject), thumbFilter, 0, null, message, 0); drawLinkImageView = true; } @@ -353,7 +361,7 @@ public class SharedLinkCell extends FrameLayout { height += layout.getLineBottom(layout.getLineCount() - 1); } } - checkBox.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(22), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(22), MeasureSpec.EXACTLY)); + checkBox.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(24), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(24), MeasureSpec.EXACTLY)); setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), Math.max(AndroidUtilities.dp(76), height + AndroidUtilities.dp(17)) + (needDivider ? 1 : 0)); } @@ -525,4 +533,25 @@ public class SharedLinkCell extends FrameLayout { } } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + StringBuilder sb = new StringBuilder(); + if (titleLayout != null) { + sb.append(titleLayout.getText()); + } + if (descriptionLayout != null) { + sb.append(", "); + sb.append(descriptionLayout.getText()); + } + if (descriptionLayout2 != null) { + sb.append(", "); + sb.append(descriptionLayout2.getText()); + } + if (checkBox.isChecked()) { + info.setChecked(true); + info.setCheckable(true); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java index 06944a871..d38853d95 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java @@ -21,12 +21,15 @@ import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DownloadController; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLoader; @@ -35,7 +38,7 @@ import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.BackupImageView; -import org.telegram.ui.Components.CheckBox; +import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.PhotoViewer; @@ -54,6 +57,7 @@ public class SharedPhotoVideoCell extends FrameLayout { public interface SharedPhotoVideoCellDelegate { void didClickItem(SharedPhotoVideoCell cell, int index, MessageObject messageObject, int a); + boolean didLongClickItem(SharedPhotoVideoCell cell, int index, MessageObject messageObject, int a); } @@ -63,7 +67,7 @@ public class SharedPhotoVideoCell extends FrameLayout { private TextView videoTextView; private FrameLayout videoInfoContainer; private View selector; - private CheckBox checkBox; + private CheckBox2 checkBox; private FrameLayout container; private AnimatorSet animator; @@ -104,16 +108,20 @@ public class SharedPhotoVideoCell extends FrameLayout { videoTextView.setTextColor(0xffffffff); videoTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); videoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + videoTextView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); videoInfoContainer.addView(videoTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 13, -0.7f, 0, 0)); selector = new View(context); selector.setBackgroundDrawable(Theme.getSelectorDrawable(false)); addView(selector, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - checkBox = new CheckBox(context, R.drawable.round_check2); + checkBox = new CheckBox2(context); checkBox.setVisibility(INVISIBLE); - checkBox.setColor(Theme.getColor(Theme.key_checkbox), Theme.getColor(Theme.key_checkboxCheck)); - addView(checkBox, LayoutHelper.createFrame(22, 22, Gravity.RIGHT | Gravity.TOP, 0, 2, 2, 0)); + checkBox.setColor(null, Theme.key_sharedMedia_photoPlaceholder, Theme.key_checkboxCheck); + checkBox.setSize(21); + checkBox.setDrawUnchecked(false); + checkBox.setDrawBackgroundAsArc(1); + addView(checkBox, LayoutHelper.createFrame(24, 24, Gravity.RIGHT | Gravity.TOP, 0, 1, 1, 0)); } @Override @@ -135,8 +143,9 @@ public class SharedPhotoVideoCell extends FrameLayout { } if (animated) { animator = new AnimatorSet(); - animator.playTogether(ObjectAnimator.ofFloat(container, "scaleX", checked ? 0.85f : 1.0f), - ObjectAnimator.ofFloat(container, "scaleY", checked ? 0.85f : 1.0f)); + animator.playTogether( + ObjectAnimator.ofFloat(container, "scaleX", checked ? 0.81f : 1.0f), + ObjectAnimator.ofFloat(container, "scaleY", checked ? 0.81f : 1.0f)); animator.setDuration(200); animator.addListener(new AnimatorListenerAdapter() { @Override @@ -179,7 +188,7 @@ public class SharedPhotoVideoCell extends FrameLayout { qualityThumb = null; } if (thumb != null) { - imageView.setImage(qualityThumb, "100_100", ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.photo_placeholder_in), null, thumb, "b", null, 0, messageObject); + imageView.setImage(ImageLocation.getForDocument(qualityThumb, document), "100_100", ImageLocation.getForDocument(thumb, document), "b", ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.photo_placeholder_in), null, null, 0, messageObject); } else { imageView.setImageResource(R.drawable.photo_placeholder_in); } @@ -191,9 +200,9 @@ public class SharedPhotoVideoCell extends FrameLayout { if (currentPhotoObject == currentPhotoObjectThumb) { currentPhotoObjectThumb = null; } - imageView.getImageReceiver().setImage(currentPhotoObject, "100_100", currentPhotoObjectThumb, "b", currentPhotoObject.size, null, messageObject, messageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); + imageView.getImageReceiver().setImage(ImageLocation.getForObject(currentPhotoObject, messageObject.photoThumbsObject), "100_100", ImageLocation.getForObject(currentPhotoObjectThumb, messageObject.photoThumbsObject), "b", currentPhotoObject.size, null, messageObject, messageObject.shouldEncryptPhotoOrVideo() ? 2 : 1); } else { - imageView.setImage(null, null, ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.photo_placeholder_in), null, currentPhotoObjectThumb, "b", null, 0, messageObject); + imageView.setImage(null, null, ImageLocation.getForObject(currentPhotoObjectThumb, messageObject.photoThumbsObject), "b", ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.photo_placeholder_in), null, null, 0, messageObject); } } else { videoInfoContainer.setVisibility(INVISIBLE); @@ -216,6 +225,20 @@ public class SharedPhotoVideoCell extends FrameLayout { canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), backgroundPaint); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (currentMessageObject.isVideo()) { + info.setText(LocaleController.getString("AttachVideo", R.string.AttachVideo) + ", " + LocaleController.formatCallDuration(currentMessageObject.getDuration())); + } else { + info.setText(LocaleController.getString("AttachPhoto", R.string.AttachPhoto)); + } + if (checkBox.isChecked()) { + info.setCheckable(true); + info.setChecked(true); + } + } } public SharedPhotoVideoCell(Context context) { @@ -248,7 +271,7 @@ public class SharedPhotoVideoCell extends FrameLayout { public void updateCheckboxColor() { for (int a = 0; a < 6; a++) { - photoVideoViews[a].checkBox.setColor(Theme.getColor(Theme.key_checkbox), Theme.getColor(Theme.key_checkboxCheck)); + photoVideoViews[a].checkBox.invalidate(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharingLiveLocationCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharingLiveLocationCell.java index 6633d101c..237e998d4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharingLiveLocationCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharingLiveLocationCell.java @@ -23,6 +23,7 @@ import com.google.android.gms.maps.model.LatLng; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.LocationController; import org.telegram.messenger.MessageObject; @@ -123,7 +124,6 @@ public class SharingLiveLocationCell extends FrameLayout { } currentAccount = messageObject.currentAccount; String address = null; - TLRPC.FileLocation photo = null; String name; if (!TextUtils.isEmpty(messageObject.messageOwner.media.address)) { address = messageObject.messageOwner.media.address; @@ -142,29 +142,21 @@ public class SharingLiveLocationCell extends FrameLayout { } else { name = ""; avatarDrawable = null; - Object parentObject = null; if (fromId > 0) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(fromId); if (user != null) { - if (user.photo != null) { - photo = user.photo.photo_small; - } avatarDrawable = new AvatarDrawable(user); name = UserObject.getUserName(user); - parentObject = user; + avatarImageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); } } else { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-fromId); if (chat != null) { - if (chat.photo != null) { - photo = chat.photo.photo_small; - } avatarDrawable = new AvatarDrawable(chat); name = chat.title; - parentObject = chat; + avatarImageView.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, chat); } } - avatarImageView.setImage(photo, null, avatarDrawable, parentObject); } nameTextView.setText(name); @@ -197,27 +189,19 @@ public class SharingLiveLocationCell extends FrameLayout { public void setDialog(LocationActivity.LiveLocation info, Location userLocation) { liveLocation = info; int lower_id = info.id; - TLRPC.FileLocation photo = null; - Object parentObject = null; if (lower_id > 0) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(lower_id); - avatarDrawable.setInfo(user); if (user != null) { + avatarDrawable.setInfo(user); nameTextView.setText(ContactsController.formatName(user.first_name, user.last_name)); - if (user.photo != null && user.photo.photo_small != null) { - photo = user.photo.photo_small; - } - parentObject = user; + avatarImageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); } } else { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_id); if (chat != null) { avatarDrawable.setInfo(chat); nameTextView.setText(chat.title); - if (chat.photo != null && chat.photo.photo_small != null) { - photo = chat.photo.photo_small; - } - parentObject = chat; + avatarImageView.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, chat); } } @@ -236,37 +220,26 @@ public class SharingLiveLocationCell extends FrameLayout { } else { distanceTextView.setText(time); } - - avatarImageView.setImage(photo, null, avatarDrawable, parentObject); } public void setDialog(LocationController.SharingLocationInfo info) { currentInfo = info; int lower_id = (int) info.did; - TLRPC.FileLocation photo = null; - Object parentObject = null; if (lower_id > 0) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(lower_id); if (user != null) { avatarDrawable.setInfo(user); nameTextView.setText(ContactsController.formatName(user.first_name, user.last_name)); - if (user.photo != null && user.photo.photo_small != null) { - photo = user.photo.photo_small; - } - parentObject = user; + avatarImageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); } } else { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_id); if (chat != null) { avatarDrawable.setInfo(chat); nameTextView.setText(chat.title); - if (chat.photo != null && chat.photo.photo_small != null) { - photo = chat.photo.photo_small; - } - parentObject = chat; + avatarImageView.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, chat); } } - avatarImageView.setImage(photo, null, avatarDrawable, parentObject); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java index 1cf4763d4..ba78a8521 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java @@ -15,11 +15,14 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; import android.view.Gravity; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.AccelerateInterpolator; import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; @@ -34,6 +37,7 @@ public class StickerCell extends FrameLayout { private boolean scaled; private float scale; private long time = 0; + private boolean clearsInputField; private static AccelerateInterpolator interpolator = new AccelerateInterpolator(0.5f); public StickerCell(Context context) { @@ -42,6 +46,7 @@ public class StickerCell extends FrameLayout { imageView = new BackupImageView(context); imageView.setAspectFit(true); addView(imageView, LayoutHelper.createFrame(66, 66, Gravity.CENTER_HORIZONTAL, 0, 5, 0, 0)); + setFocusable(true); } @Override @@ -58,12 +63,18 @@ public class StickerCell extends FrameLayout { super.setPressed(pressed); } + public void setClearsInputField(boolean value) { + clearsInputField = value; + } + + public boolean isClearsInputField() { + return clearsInputField; + } + public void setSticker(TLRPC.Document document, Object parentObject, int side) { if (document != null) { TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); - if (thumb != null) { - imageView.setImage(thumb, null, "webp", null, parentObject); - } + imageView.setImage(ImageLocation.getForDocument(thumb, document), null, "webp", null, parentObject); } sticker = document; if (side == -1) { @@ -125,4 +136,23 @@ public class StickerCell extends FrameLayout { } return result; } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info){ + super.onInitializeAccessibilityNodeInfo(info); + if (sticker == null) + return; + String emoji = null; + for (int a = 0; a < sticker.attributes.size(); a++) { + TLRPC.DocumentAttribute attribute = sticker.attributes.get(a); + if (attribute instanceof TLRPC.TL_documentAttributeSticker) { + emoji = attribute.alt != null && attribute.alt.length() > 0 ? attribute.alt : null; + } + } + if (emoji != null) + info.setText(emoji + " " + LocaleController.getString("AttachSticker", R.string.AttachSticker)); + else + info.setText(LocaleController.getString("AttachSticker", R.string.AttachSticker)); + info.setEnabled(true); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java index 7a4060536..3937c1030 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java @@ -13,6 +13,7 @@ import android.graphics.Canvas; import android.util.TypedValue; import android.view.Gravity; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.AccelerateInterpolator; import android.widget.FrameLayout; import android.widget.TextView; @@ -21,6 +22,9 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DataQuery; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Components.BackupImageView; @@ -52,6 +56,7 @@ public class StickerEmojiCell extends FrameLayout { emojiTextView = new TextView(context); emojiTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); addView(emojiTextView, LayoutHelper.createFrame(28, 28, Gravity.BOTTOM | Gravity.RIGHT)); + setFocusable(true); } public TLRPC.Document getSticker() { @@ -71,15 +76,24 @@ public class StickerEmojiCell extends FrameLayout { } public void setSticker(TLRPC.Document document, Object parent, boolean showEmoji) { + setSticker(document, parent, null, showEmoji); + } + + public void setSticker(TLRPC.Document document, Object parent, String emoji, boolean showEmoji) { if (document != null) { sticker = document; parentObject = parent; TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); if (thumb != null) { - imageView.setImage(thumb, null, "webp", null, parentObject); + imageView.setImage(ImageLocation.getForDocument(thumb, document), null, "webp", null, parentObject); + } else { + imageView.setImage(ImageLocation.getForDocument(document), null, "webp", null, parentObject); } - if (showEmoji) { + if (emoji != null) { + emojiTextView.setText(Emoji.replaceEmoji(emoji, emojiTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(16), false)); + emojiTextView.setVisibility(VISIBLE); + } else if (showEmoji) { boolean set = false; for (int a = 0; a < document.attributes.size(); a++) { TLRPC.DocumentAttribute attribute = document.attributes.get(a); @@ -167,4 +181,22 @@ public class StickerEmojiCell extends FrameLayout { } return result; } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + String descr = LocaleController.getString("AttachSticker", R.string.AttachSticker); + for (int a = 0; a < sticker.attributes.size(); a++) { + TLRPC.DocumentAttribute attribute = sticker.attributes.get(a); + if (attribute instanceof TLRPC.TL_documentAttributeSticker) { + if (attribute.alt != null && attribute.alt.length() > 0) { + emojiTextView.setText(Emoji.replaceEmoji(attribute.alt, emojiTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(16), false)); + descr = attribute.alt + " " + descr; + } + break; + } + } + info.setContentDescription(descr); + info.setEnabled(true); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java index 09eb668a8..d16aea5bf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java @@ -24,6 +24,7 @@ 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.R; import org.telegram.tgnet.TLRPC; @@ -147,9 +148,7 @@ public class StickerSetCell extends FrameLayout { valueTextView.setText(LocaleController.formatPluralString("Stickers", documents.size())); TLRPC.Document document = documents.get(0); TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); - if (thumb != null) { - imageView.setImage(thumb, null, "webp", null, set); - } + imageView.setImage(ImageLocation.getForDocument(thumb, document), null, "webp", null, set); } else { valueTextView.setText(LocaleController.formatPluralString("Stickers", 0)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetNameCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetNameCell.java index 89174c91e..eeddc2aa9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetNameCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetNameCell.java @@ -33,17 +33,20 @@ public class StickerSetNameCell extends FrameLayout { private TextView urlTextView; private ImageView buttonView; private boolean empty; + private boolean isEmoji; - public StickerSetNameCell(Context context) { + public StickerSetNameCell(Context context, boolean emoji) { super(context); + isEmoji = emoji; + textView = new TextView(context); textView.setTextColor(Theme.getColor(Theme.key_chat_emojiPanelStickerSetName)); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); textView.setEllipsize(TextUtils.TruncateAt.END); textView.setSingleLine(true); - addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 17, 4, 57, 0)); + addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, emoji ? 15 : 17, 4, 57, 0)); urlTextView = new TextView(context); urlTextView.setTextColor(Theme.getColor(Theme.key_chat_emojiPanelStickerSetName)); @@ -63,7 +66,7 @@ public class StickerSetNameCell extends FrameLayout { if (text != null) { SpannableStringBuilder builder = new SpannableStringBuilder(text); try { - builder.setSpan(new ColorSpanUnderline(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)), 0, searchLength, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + builder.setSpan(new ColorSpanUnderline(Theme.getColor(Theme.key_chat_emojiPanelStickerSetNameHighlight)), 0, searchLength, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //TODO builder.setSpan(new ColorSpanUnderline(Theme.getColor(Theme.key_chat_emojiPanelStickerSetName)), searchLength, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } catch (Exception ignore) { @@ -88,7 +91,7 @@ public class StickerSetNameCell extends FrameLayout { if (searchLength != 0) { SpannableStringBuilder builder = new SpannableStringBuilder(text); try { - builder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)), index, index + searchLength, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + builder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chat_emojiPanelStickerSetNameHighlight)), index, index + searchLength, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } catch (Exception ignore) { } @@ -120,7 +123,7 @@ public class StickerSetNameCell extends FrameLayout { if (empty) { super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(1, MeasureSpec.EXACTLY)); } else { - super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(24), MeasureSpec.EXACTLY)); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(isEmoji ? 28 : 24), MeasureSpec.EXACTLY)); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java index 446f6d705..3f7d97d4a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java @@ -53,6 +53,8 @@ public class TextCell extends FrameLayout { valueImageView = new ImageView(context); valueImageView.setScaleType(ImageView.ScaleType.CENTER); addView(valueImageView); + + setFocusable(true); } public SimpleTextView getTextView() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckBoxCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckBoxCell.java index 426473822..8f3f0f22b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckBoxCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckBoxCell.java @@ -13,6 +13,7 @@ import android.graphics.Canvas; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.TextView; @@ -85,4 +86,12 @@ public class TextCheckBoxCell extends FrameLayout { canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(20), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.CheckBox"); + info.setCheckable(true); + info.setChecked(isChecked()); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java index 7b7e5cb03..f63aee662 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java @@ -20,11 +20,13 @@ import android.util.Property; import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AnimationProperties; import org.telegram.ui.Components.CubicBezierInterpolator; @@ -263,4 +265,13 @@ public class TextCheckCell extends FrameLayout { canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(20), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.Switch"); + info.setCheckable(true); + info.setChecked(checkBox.isChecked()); + info.setContentDescription(checkBox.isChecked() ? LocaleController.getString("NotificationsOn", R.string.NotificationsOn) : LocaleController.getString("NotificationsOff", R.string.NotificationsOff)); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell2.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell2.java index b60301469..99676b052 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell2.java @@ -13,11 +13,13 @@ import android.graphics.Canvas; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.Switch; @@ -144,4 +146,13 @@ public class TextCheckCell2 extends FrameLayout { canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(20), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.Switch"); + info.setCheckable(true); + info.setChecked(checkBox.isChecked()); + info.setContentDescription(checkBox.isChecked() ? LocaleController.getString("NotificationsOn", R.string.NotificationsOn) : LocaleController.getString("NotificationsOff", R.string.NotificationsOff)); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java index 915c160ea..adc135f69 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java @@ -13,7 +13,7 @@ import android.animation.ObjectAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.util.TypedValue; import android.view.Gravity; import android.widget.FrameLayout; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java index 69153ad23..0f97dcc76 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java @@ -133,7 +133,7 @@ public class TextDetailSettingsCell extends FrameLayout { @Override protected void onDraw(Canvas canvas) { - if (needDivider) { + if (needDivider && Theme.dividerPaint != null) { canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(imageView.getVisibility() == VISIBLE ? 71 : 20), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(imageView.getVisibility() == VISIBLE ? 71 : 20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java index 50e638f45..5a8fdfb80 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java @@ -17,6 +17,7 @@ import android.graphics.PorterDuffColorFilter; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -182,4 +183,10 @@ public class TextSettingsCell extends FrameLayout { canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(20), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(20) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(isEnabled()); + } } 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 ed4877e01..3ddf4ce9e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemeCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemeCell.java @@ -17,6 +17,7 @@ import android.graphics.PorterDuffColorFilter; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -75,6 +76,7 @@ public class ThemeCell extends FrameLayout { optionsButton.setImageResource(R.drawable.ic_ab_other); optionsButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_stickers_menu), PorterDuff.Mode.MULTIPLY)); optionsButton.setScaleType(ImageView.ScaleType.CENTER); + optionsButton.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); addView(optionsButton, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP)); } else { addView(checkImage, LayoutHelper.createFrame(19, 14, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 21, 0, 21, 0)); @@ -218,4 +220,10 @@ public class ThemeCell extends FrameLayout { } canvas.drawCircle(x, AndroidUtilities.dp(13 + 11), AndroidUtilities.dp(11), paint); } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + setSelected(checkImage.getVisibility() == VISIBLE); + } } 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 6cee4bcd5..eeb1b9422 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java @@ -15,11 +15,13 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.Typeface; import android.util.TypedValue; import android.view.Gravity; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.UserObject; @@ -52,7 +54,7 @@ public class UserCell extends FrameLayout { private TLRPC.EncryptedChat encryptedChat; private CharSequence currentName; - private CharSequence currrntStatus; + private CharSequence currentStatus; private int currentId; private int currentDrawable; @@ -113,6 +115,7 @@ public class UserCell extends FrameLayout { adminTextView.setTextColor(Theme.getColor(Theme.key_profile_creatorIcon)); addView(adminTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, LocaleController.isRTL ? 23 : 0, 15, LocaleController.isRTL ? 0 : 23, 0)); } + setFocusable(true); } public void setAvatarPadding(int padding) { @@ -165,7 +168,7 @@ public class UserCell extends FrameLayout { public void setData(TLObject object, TLRPC.EncryptedChat ec, CharSequence name, CharSequence status, int resId, boolean divider) { if (object == null && name == null && status == null) { - currrntStatus = null; + currentStatus = null; currentName = null; currentObject = null; nameTextView.setText(""); @@ -174,7 +177,7 @@ public class UserCell extends FrameLayout { return; } encryptedChat = ec; - currrntStatus = status; + currentStatus = status; currentName = name; currentObject = object; currentDrawable = resId; @@ -383,9 +386,9 @@ public class UserCell extends FrameLayout { } nameTextView.setText(lastName); } - if (currrntStatus != null) { + if (currentStatus != null) { statusTextView.setTextColor(statusColor); - statusTextView.setText(currrntStatus); + statusTextView.setText(currentStatus); } else if (currentUser != null) { if (currentUser.bot) { statusTextView.setTextColor(statusColor); @@ -409,7 +412,13 @@ public class UserCell extends FrameLayout { imageView.setVisibility(currentDrawable == 0 ? GONE : VISIBLE); imageView.setImageResource(currentDrawable); } - avatarImageView.setImage(photo, "50_50", avatarDrawable, currentObject); + + lastAvatar = photo; + if (currentUser != null) { + avatarImageView.setImage(ImageLocation.getForUser(currentUser, false), "50_50", avatarDrawable, currentUser); + } else if (currentChat != null) { + avatarImageView.setImage(ImageLocation.getForChat(currentChat, false), "50_50", avatarDrawable, currentChat); + } } @Override @@ -423,4 +432,18 @@ public class UserCell extends FrameLayout { canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(68), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(68) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (checkBoxBig != null && checkBoxBig.getVisibility() == VISIBLE) { + info.setCheckable(true); + info.setChecked(checkBoxBig.isChecked()); + info.setClassName("android.widget.CheckBox"); + } else if (checkBox != null && checkBox.getVisibility() == VISIBLE) { + info.setCheckable(true); + info.setChecked(checkBox.isChecked()); + info.setClassName("android.widget.CheckBox"); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java index 8a69569db..08f588e4f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java @@ -27,6 +27,7 @@ import android.widget.ImageView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.MediaController; import org.telegram.messenger.R; import org.telegram.tgnet.TLRPC; @@ -130,14 +131,18 @@ public class WallpaperCell extends FrameLayout { int size = image != null ? image.size : wallPaper.document.size; if (wallPaper.pattern) { imageView.setBackgroundColor(0xff000000 | wallPaper.settings.background_color); - imageView.setImage(image, "100_100", thumb, null, "jpg", size, 1, wallPaper); + imageView.setImage(ImageLocation.getForDocument(image, wallPaper.document), "100_100", ImageLocation.getForDocument(thumb, wallPaper.document), null, "jpg", size, 1, wallPaper); imageView.getImageReceiver().setColorFilter(new PorterDuffColorFilter(AndroidUtilities.getPatternColor(wallPaper.settings.background_color), PorterDuff.Mode.SRC_IN)); imageView.getImageReceiver().setAlpha(wallPaper.settings.intensity / 100.0f); } else { /*if (wallPaper.settings != null && wallPaper.settings.blur) { imageView.setImage(null, "100_100", thumb, "100_100_b", "jpg", size, 1, wallPaper); } else {*/ - imageView.setImage(image != null ? image : wallPaper.document, "100_100", thumb, "100_100_b", "jpg", size, 1, wallPaper); + if (image != null) { + imageView.setImage(ImageLocation.getForDocument(image, wallPaper.document), "100_100", ImageLocation.getForDocument(thumb, wallPaper.document), "100_100_b", "jpg", size, 1, wallPaper); + } else { + imageView.setImage(ImageLocation.getForDocument(wallPaper.document), "100_100", ImageLocation.getForDocument(thumb, wallPaper.document), "100_100_b", "jpg", size, 1, wallPaper); + } //} } } else if (object instanceof WallpapersListActivity.ColorWallpaper) { @@ -170,7 +175,7 @@ public class WallpaperCell extends FrameLayout { image = null; } int size = image != null ? image.size : 0; - imageView.setImage(image, "100_100", thumb, "100_100_b", "jpg", size, 1, wallPaper); + imageView.setImage(ImageLocation.getForPhoto(image, wallPaper.photo), "100_100", ImageLocation.getForPhoto(thumb, wallPaper.photo), "100_100_b", "jpg", size, 1, wallPaper); } else { imageView.setImage(wallPaper.thumbUrl, "100_100", null); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells2/UserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells2/UserCell.java index e767ce13a..74c271c07 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells2/UserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells2/UserCell.java @@ -19,6 +19,7 @@ import android.widget.ImageView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; @@ -211,6 +212,7 @@ public class UserCell extends FrameLayout { return; } } + lastAvatar = photo; if (currentUser != null) { avatarDrawable.setInfo(currentUser); @@ -258,6 +260,7 @@ public class UserCell extends FrameLayout { statusTextView.setText(LocaleController.formatUserStatus(currentAccount, currentUser)); } } + avatarImageView.setImage(ImageLocation.getForUser(currentUser, false), "50_50", avatarDrawable, currentUser); } else if (currentChat != null) { statusTextView.setTextColor(statusColor); if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { @@ -277,13 +280,13 @@ public class UserCell extends FrameLayout { statusTextView.setText(LocaleController.getString("MegaPublic", R.string.MegaPublic)); } } + avatarImageView.setImage(ImageLocation.getForChat(currentChat, false), "50_50", avatarDrawable, currentObject); } if (imageView.getVisibility() == VISIBLE && currentDrawable == 0 || imageView.getVisibility() == GONE && currentDrawable != 0) { imageView.setVisibility(currentDrawable == 0 ? GONE : VISIBLE); imageView.setImageResource(currentDrawable); } - avatarImageView.setImage(photo, "50_50", avatarDrawable, currentObject); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeBioActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeBioActivity.java index 112721614..96e8cb0c3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeBioActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeBioActivity.java @@ -155,7 +155,7 @@ public class ChangeBioActivity extends BaseFragment { helpTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("UserBioInfo", R.string.UserBioInfo))); linearLayout.addView(helpTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 24, 10, 24, 0)); - TLRPC.TL_userFull userFull = MessagesController.getInstance(currentAccount).getUserFull(UserConfig.getInstance(currentAccount).getClientUserId()); + TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(UserConfig.getInstance(currentAccount).getClientUserId()); if (userFull != null && userFull.about != null) { firstNameField.setText(userFull.about); firstNameField.setSelection(firstNameField.length()); @@ -176,7 +176,7 @@ public class ChangeBioActivity extends BaseFragment { } private void saveName() { - final TLRPC.TL_userFull userFull = MessagesController.getInstance(currentAccount).getUserFull(UserConfig.getInstance(currentAccount).getClientUserId()); + final TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(UserConfig.getInstance(currentAccount).getClientUserId()); if (getParentActivity() == null || userFull == null) { return; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java index 9d91ad346..6a5546750 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java @@ -30,6 +30,7 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; +import android.telephony.PhoneNumberUtils; import android.telephony.SmsManager; import android.telephony.TelephonyManager; import android.text.Editable; @@ -775,7 +776,7 @@ public class ChangePhoneActivity extends BaseFragment { try { @SuppressLint("HardwareIds") String number = tm.getLine1Number(); if (!TextUtils.isEmpty(number)) { - req.settings.current_number = phone.contains(number) || number.contains(phone); + req.settings.current_number = PhoneNumberUtils.compare(phone, number); if (!req.settings.current_number) { req.settings.allow_flashcall = false; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java index e2a4c8aae..b4d191dee 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java @@ -30,7 +30,11 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.support.v4.content.FileProvider; +import androidx.core.content.FileProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.LinearSmoothScrollerMiddle; +import androidx.recyclerview.widget.RecyclerView; + import android.text.TextUtils; import android.text.style.CharacterStyle; import android.text.style.ClickableSpan; @@ -71,9 +75,6 @@ import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.messenger.browser.Browser; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.LinearSmoothScrollerMiddle; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; @@ -886,6 +887,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio bottomOverlayImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_fieldOverlayText), PorterDuff.Mode.MULTIPLY)); bottomOverlayImage.setScaleType(ImageView.ScaleType.CENTER); bottomOverlayChat.addView(bottomOverlayImage, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 3, 0, 0, 0)); + bottomOverlayImage.setContentDescription(LocaleController.getString("BotHelp", R.string.BotHelp)); bottomOverlayImage.setOnClickListener(v -> { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); if (currentChat.megagroup) { @@ -917,7 +919,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio /*searchUpButton = new ImageView(context); searchUpButton.setScaleType(ImageView.ScaleType.CENTER); - searchUpButton.setImageResource(R.drawable.search_up); + searchUpButton.setImageResource(R.drawable.msg_go_up); searchUpButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); searchContainer.addView(searchUpButton, LayoutHelper.createFrame(48, 48)); searchUpButton.setOnClickListener(new View.OnClickListener() { @@ -929,7 +931,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio searchDownButton = new ImageView(context); searchDownButton.setScaleType(ImageView.ScaleType.CENTER); - searchDownButton.setImageResource(R.drawable.search_down); + searchDownButton.setImageResource(R.drawable.msg_go_down); searchDownButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); searchContainer.addView(searchDownButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP, 48, 0, 0, 0)); searchDownButton.setOnClickListener(new View.OnClickListener() { @@ -941,7 +943,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio searchCalendarButton = new ImageView(context); searchCalendarButton.setScaleType(ImageView.ScaleType.CENTER); - searchCalendarButton.setImageResource(R.drawable.search_calendar); + searchCalendarButton.setImageResource(R.drawable.msg_calendar); searchCalendarButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); searchContainer.addView(searchCalendarButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP)); searchCalendarButton.setOnClickListener(view -> { @@ -1114,7 +1116,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio if (options.isEmpty()) { return; } - final CharSequence[] finalItems = items.toArray(new CharSequence[items.size()]); + final CharSequence[] finalItems = items.toArray(new CharSequence[0]); builder.setItems(finalItems, (dialogInterface, i) -> { if (selectedObject == null || i < 0 || i >= options.size()) { return; @@ -1925,7 +1927,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio if (getParentActivity() == null) { return; } - showDialog(ShareAlert.createShareAlert(mContext, cell.getMessageObject(), null, ChatObject.isChannel(currentChat) && !currentChat.megagroup && currentChat.username != null && currentChat.username.length() > 0, null, false)); + showDialog(ShareAlert.createShareAlert(mContext, cell.getMessageObject(), null, ChatObject.isChannel(currentChat) && !currentChat.megagroup, null, false)); } @Override @@ -1941,7 +1943,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } @Override - public void didPressChannelAvatar(ChatMessageCell cell, TLRPC.Chat chat, int postId) { + public void didPressChannelAvatar(ChatMessageCell cell, TLRPC.Chat chat, int postId, float touchX, float touchY) { if (chat != null && chat != currentChat) { Bundle args = new Bundle(); args.putInt("chat_id", chat.id); @@ -1955,12 +1957,12 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } @Override - public void didPressOther(ChatMessageCell cell) { + public void didPressOther(ChatMessageCell cell, float x, float y) { createMenu(cell); } @Override - public void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user) { + public void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user, float touchX, float touchY) { if (user != null && user.id != UserConfig.getInstance(currentAccount).getClientUserId()) { Bundle args = new Bundle(); args.putInt("user_id", user.id); @@ -1987,7 +1989,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } @Override - public void didLongPress(ChatMessageCell cell) { + public void didLongPress(ChatMessageCell cell, float x, float y) { createMenu(cell); } @@ -2074,7 +2076,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } @Override - public void didPressImage(ChatMessageCell cell) { + public void didPressImage(ChatMessageCell cell, float x, float y) { MessageObject message = cell.getMessageObject(); if (message.type == 13) { showDialog(new StickersAlert(getParentActivity(), ChannelAdminLogActivity.this, message.getInputStickerSet(), null, null)); @@ -2180,7 +2182,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio view = new ChatActionCell(mContext); ((ChatActionCell) view).setDelegate(new ChatActionCell.ChatActionCellDelegate() { @Override - public void didClickedImage(ChatActionCell cell) { + public void didClickImage(ChatActionCell cell) { MessageObject message = cell.getMessageObject(); PhotoViewer.getInstance().setParentActivity(getParentActivity()); TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(message.photoThumbs, 640); @@ -2192,7 +2194,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } @Override - public void didLongPressed(ChatActionCell cell) { + public void didLongPress(ChatActionCell cell, float x, float y) { createMenu(cell); } @@ -2215,12 +2217,12 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } @Override - public void didPressedReplyMessage(ChatActionCell cell, int id) { + public void didPressReplyMessage(ChatActionCell cell, int id) { } @Override - public void didPressedBotButton(MessageObject messageObject, TLRPC.KeyboardButton button) { + public void didPressBotButton(MessageObject messageObject, TLRPC.KeyboardButton button) { } }); @@ -2424,6 +2426,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUBACKGROUND, null, null, null, null, Theme.key_actionBarDefaultSubmenuBackground), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM, null, null, null, null, Theme.key_actionBarDefaultSubmenuItem), + new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubmenuItemIcon), 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), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelCreateActivity.java index 36b75ac79..7f0300dbb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelCreateActivity.java @@ -12,7 +12,6 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; -import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Canvas; @@ -41,6 +40,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ChatObject; import org.telegram.messenger.FileLog; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; @@ -219,7 +219,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC finishFragment(); } else if (id == done_button) { if (currentStep == 0) { - if (donePressed) { + if (donePressed || getParentActivity() == null) { return; } if (nameTextView.length() == 0) { @@ -289,6 +289,8 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC SizeNotifierFrameLayout sizeNotifierFrameLayout = new SizeNotifierFrameLayout(context) { + private boolean ignoreLayout; + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSize = MeasureSpec.getSize(widthMeasureSpec); @@ -300,8 +302,13 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC measureChildWithMargins(actionBar, widthMeasureSpec, 0, heightMeasureSpec, 0); int keyboardSize = getKeyboardHeight(); - int childCount = getChildCount(); + if (keyboardSize > AndroidUtilities.dp(20)) { + ignoreLayout = true; + nameTextView.hideEmojiView(); + ignoreLayout = false; + } + int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); if (child == null || child.getVisibility() == GONE || child == actionBar) { @@ -389,6 +396,14 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC notifyHeightChanged(); } + + @Override + public void requestLayout() { + if (ignoreLayout) { + return; + } + super.requestLayout(); + } }; sizeNotifierFrameLayout.setOnTouchListener((v, event) -> true); fragmentView = sizeNotifierFrameLayout; @@ -442,7 +457,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC avatarBig = null; uploadedAvatar = null; showAvatarProgress(false, true); - avatarImage.setImage(avatar, "50_50", avatarDrawable, null); + avatarImage.setImage(null, null, avatarDrawable, null); })); avatarEditor = new ImageView(context) { @@ -471,7 +486,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC showAvatarProgress(false, false); - nameTextView = new EditTextEmoji((Activity) context, sizeNotifierFrameLayout, this); + nameTextView = new EditTextEmoji(context, sizeNotifierFrameLayout, this, EditTextEmoji.STYLE_FRAGMENT); nameTextView.setHint(LocaleController.getString("EnterChannelName", R.string.EnterChannelName)); if (nameToSet != null) { nameTextView.setText(nameToSet); @@ -759,7 +774,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC } else { avatar = smallSize.location; avatarBig = bigSize.location; - avatarImage.setImage(avatar, "50_50", avatarDrawable, null); + avatarImage.setImage(ImageLocation.getForLocal(avatar), "50_50", avatarDrawable, null); showAvatarProgress(true, false); } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index db4d52aa5..ef21c046f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -26,6 +26,7 @@ import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.Path; @@ -34,16 +35,20 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; -import android.graphics.SurfaceTexture; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.media.ThumbnailUtils; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.SystemClock; import android.provider.MediaStore; -import android.support.annotation.NonNull; -import android.support.v4.content.FileProvider; +import androidx.core.content.FileProvider; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.LinearSmoothScrollerMiddle; +import androidx.recyclerview.widget.RecyclerView; + import android.text.Spannable; import android.text.SpannableString; import android.text.SpannableStringBuilder; @@ -61,6 +66,7 @@ import android.util.SparseIntArray; import android.util.TypedValue; import android.view.Gravity; import android.view.HapticFeedbackConstants; +import android.view.KeyEvent; import android.view.Menu; import android.view.MotionEvent; import android.view.TextureView; @@ -68,12 +74,16 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; +import android.view.WindowManager; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.DecelerateInterpolator; import android.widget.DatePicker; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; @@ -87,7 +97,7 @@ import org.telegram.messenger.ChatObject; import org.telegram.messenger.DataQuery; import org.telegram.messenger.DownloadController; import org.telegram.messenger.Emoji; -import org.telegram.messenger.EmojiSuggestion; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.MessagesStorage; @@ -100,14 +110,10 @@ import org.telegram.messenger.Utilities; import org.telegram.messenger.VideoEditedInfo; import org.telegram.messenger.browser.Browser; import org.telegram.messenger.support.SparseLongArray; -import org.telegram.messenger.support.widget.GridLayoutManager; -import org.telegram.messenger.support.widget.GridLayoutManagerFixed; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.LinearSmoothScrollerMiddle; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLoader; import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.ContactsController; import org.telegram.messenger.FileLog; @@ -117,6 +123,7 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.ui.ActionBar.ActionBarLayout; +import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BottomSheet; @@ -135,6 +142,7 @@ import org.telegram.ui.Cells.ChatUnreadCell; import org.telegram.ui.Cells.CheckBoxCell; import org.telegram.ui.Cells.ContextLinkCell; import org.telegram.ui.Cells.MentionCell; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; import org.telegram.ui.Cells.StickerCell; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AnimatedFileDrawable; @@ -149,13 +157,15 @@ import org.telegram.ui.Components.ChatAvatarContainer; import org.telegram.ui.Components.ChatBigEmptyView; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.CorrectlyMeasuringTextView; +import org.telegram.ui.Components.EditTextCaption; import org.telegram.ui.Components.EmbedBottomSheet; import org.telegram.ui.Components.EmojiView; import org.telegram.ui.Components.ExtendedGridLayoutManager; import org.telegram.ui.Components.FragmentContextView; +import androidx.recyclerview.widget.GridLayoutManagerFixed; import org.telegram.ui.Components.InstantCameraView; import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.NoSoundHintView; +import org.telegram.ui.Components.HintView; import org.telegram.ui.Components.NumberTextView; import org.telegram.ui.Components.PipRoundVideoView; import org.telegram.ui.Components.RadialProgressView; @@ -206,14 +216,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private ActionBarMenuItem editTextItem; private ActionBarMenuItem searchItem; private RadialProgressView progressBar; - private TextView addContactItem; + private ActionBarMenuSubItem addContactItem; private RecyclerListView chatListView; + private int chatListViewClipTop; private GridLayoutManagerFixed chatLayoutManager; private ChatActivityAdapter chatAdapter; private TextView bottomOverlayChatText; private RadialProgressView bottomOverlayProgress; private AnimatorSet bottomOverlayAnimation; private FrameLayout bottomOverlayChat; + private FrameLayout bottomMessagesActionContainer; + private TextView forwardButton; + private TextView replyButton; private FrameLayout emptyViewContainer; private SizeNotifierFrameLayout contentView; private ChatBigEmptyView bigEmptyView; @@ -227,7 +241,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private RecyclerListView.OnItemClickListener mentionsOnItemClickListener; private StickersAdapter stickersAdapter; private FrameLayout stickersPanel; - private TextView muteItem; + private ActionBarMenuSubItem muteItem; private FrameLayout pagedownButton; private ImageView pagedownButtonImage; private boolean pagedownButtonShowedByScroll; @@ -259,7 +273,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private TextView gifHintTextView; private TextView mediaBanTooltip; private TextView voiceHintTextView; - private NoSoundHintView noSoundHintView; + private HintView noSoundHintView; + private HintView forwardHintView; private Runnable voiceHintHideRunnable; private AnimatorSet voiceHintAnimation; private View emojiButtonRed; @@ -282,6 +297,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private ImageView searchDownButton; private SimpleTextView searchCountText; private ChatActionCell floatingDateView; + private int hideDateDelay = 500; private InstantCameraView instantCameraView; private View overlayView; private boolean currentFloatingDateOnScreen; @@ -323,6 +339,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private AnimatorSet pagedownButtonAnimation; private ObjectAnimator mentiondownButtonAnimation; private AnimatorSet replyButtonAnimation; + private AnimatorSet editButtonAnimation; + private AnimatorSet forwardButtonAnimation; private boolean openSearchKeyboard; @@ -347,8 +365,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean pausedOnLastMessage; private boolean wasPaused; boolean firstOpen = true; + private int replyImageSize; + private int replyImageCacheType; private TLRPC.PhotoSize replyImageLocation; + private TLRPC.PhotoSize replyImageThumbLocation; + private TLObject replyImageLocationObject; + private int pinnedImageSize; + private int pinnedImageCacheType; private TLRPC.PhotoSize pinnedImageLocation; + private TLRPC.PhotoSize pinnedImageThumbLocation; + private TLObject pinnedImageLocationObject; private int linkSearchRequestId; private TLRPC.WebPage foundWebPage; private ArrayList foundUrls; @@ -371,6 +397,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private SparseArray[] selectedMessagesCanStarIds = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; private boolean hasUnfavedSelected; private int cantDeleteMessagesCount; + private int cantForwardMessagesCount; private int canEditMessagesCount; private ArrayList waitingForLoad = new ArrayList<>(); @@ -379,20 +406,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private int newMentionsCount; private boolean hasAllMentionsLocal; - private boolean startReplyOnTextChange; - private SparseArray[] messagesDict = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; private HashMap> messagesByDays = new HashMap<>(); protected ArrayList messages = new ArrayList<>(); private LongSparseArray> polls = new LongSparseArray<>(); private LongSparseArray groupedMessagesMap = new LongSparseArray<>(); - private int maxMessageId[] = new int[] {Integer.MAX_VALUE, Integer.MAX_VALUE}; - private int minMessageId[] = new int[] {Integer.MIN_VALUE, Integer.MIN_VALUE}; - private int maxDate[] = new int[] {Integer.MIN_VALUE, Integer.MIN_VALUE}; - private int minDate[] = new int[2]; - private boolean endReached[] = new boolean[2]; - private boolean cacheEndReached[] = new boolean[2]; - private boolean forwardEndReached[] = new boolean[] {true, true}; + private int[] maxMessageId = new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE}; + private int[] minMessageId = new int[]{Integer.MIN_VALUE, Integer.MIN_VALUE}; + private int[] maxDate = new int[]{Integer.MIN_VALUE, Integer.MIN_VALUE}; + private int[] minDate = new int[2]; + private boolean[] endReached = new boolean[2]; + private boolean[] cacheEndReached = new boolean[2]; + private boolean[] forwardEndReached = new boolean[]{true, true}; private boolean loading; private boolean firstLoading = true; private boolean firstUnreadSent = false; @@ -416,11 +441,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private MessageObject scrollToMessage; private int highlightMessageId = Integer.MAX_VALUE; private int scrollToMessagePosition = -10000; + private Runnable unselectRunnable; private String currentPicturePath; protected TLRPC.ChatFull chatInfo; - protected TLRPC.TL_userFull userInfo; + protected TLRPC.UserFull userInfo; private SparseArray botInfo = new SparseArray<>(); private String botUser; @@ -444,6 +470,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private Path aspectPath; private Paint aspectPaint; + private Paint scrimPaint; + private View scrimView; + private AnimatorSet scrimAnimatorSet; + private ActionBarPopupWindow scrimPopupWindow; + private PhotoViewer.PhotoViewerProvider photoViewerProvider = new PhotoViewer.EmptyPhotoViewerProvider() { @Override @@ -482,7 +513,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (imageReceiver != null) { - int coords[] = new int[2]; + int[] coords = new int[2]; view.getLocationInWindow(coords); PhotoViewer.PlaceProviderObject object = new PhotoViewer.PlaceProviderObject(); object.viewX = coords[0]; @@ -499,6 +530,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (pinnedMessageView != null && pinnedMessageView.getTag() == null || reportSpamView != null && reportSpamView.getTag() == null) { object.clipTopAddition = AndroidUtilities.dp(48); } + object.clipTopAddition += chatListViewClipTop; return object; } } @@ -528,7 +560,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (imageReceiver != null) { - int coords[] = new int[2]; + int[] coords = new int[2]; view.getLocationInWindow(coords); PhotoViewer.PlaceProviderObject object = new PhotoViewer.PlaceProviderObject(); object.viewX = coords[0]; @@ -561,7 +593,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private final static int delete_chat = 16; private final static int share_contact = 17; private final static int mute = 18; - private final static int reply = 19; private final static int report = 21; private final static int star = 22; private final static int edit = 23; @@ -595,13 +626,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public boolean onItemClick(View view, int position, float x, float y) { wasManualScroll = true; if (!actionBar.isActionModeShowed()) { - createMenu(view, false, true); + createMenu(view, false, true, x, y); } else { boolean outside = false; if (view instanceof ChatMessageCell) { outside = !((ChatMessageCell) view).isInsideBackground(x, y); } - processRowSelect(view, outside); + processRowSelect(view, outside, x, y); } return true; } @@ -626,10 +657,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (view instanceof ChatMessageCell) { outside = !((ChatMessageCell) view).isInsideBackground(x, y); } - processRowSelect(view, outside); + processRowSelect(view, outside, x, y); return; } - createMenu(view, true, false); + createMenu(view, true, false, x, y); } }; @@ -895,7 +926,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatAttachAlert.dismissInternal(); } if (undoView != null) { - undoView.hide(true, false); + undoView.hide(true, 0); } MessagesController.getInstance(currentAccount).setLastCreatedDialogId(dialog_id, false); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagesDidLoad); @@ -994,6 +1025,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } cantDeleteMessagesCount = 0; canEditMessagesCount = 0; + cantForwardMessagesCount = 0; videoPlayerContainer = null; hasOwnBackground = true; @@ -1032,9 +1064,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); } - cantDeleteMessagesCount = 0; - canEditMessagesCount = 0; - actionBar.hideActionMode(); + hideActionMode(); updatePinnedMessageView(true); updateVisibleRows(); } else { @@ -1059,7 +1089,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (str.length() != 0) { str += "\n\n"; } - str += getMessageContent(messageObject, previousUid, currentUser == null || !currentUser.self); + str += getMessageContent(messageObject, previousUid, ids.size() != 1 && (currentUser == null || !currentUser.self)); previousUid = messageObject.messageOwner.from_id; } } @@ -1071,9 +1101,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); } - cantDeleteMessagesCount = 0; - canEditMessagesCount = 0; - actionBar.hideActionMode(); + hideActionMode(); updatePinnedMessageView(true); updateVisibleRows(); } else if (id == delete) { @@ -1082,12 +1110,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } createDeleteMessagesAlert(null, null); } else if (id == forward) { - Bundle args = new Bundle(); - args.putBoolean("onlySelect", true); - args.putInt("dialogsType", 3); - DialogsActivity fragment = new DialogsActivity(args); - fragment.setDelegate(ChatActivity.this); - presentFragment(fragment); + openForward(); } else if (id == chat_enc_timer) { if (getParentActivity() == null) { return; @@ -1099,18 +1122,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } final boolean isChat = (int) dialog_id < 0 && (int) (dialog_id >> 32) != 1; - AlertsCreator.createClearOrDeleteDialogAlert(ChatActivity.this, id == clear_history, currentChat, currentUser, currentEncryptedChat != null, () -> { + AlertsCreator.createClearOrDeleteDialogAlert(ChatActivity.this, id == clear_history, currentChat, currentUser, currentEncryptedChat != null, (param) -> { if (id == clear_history && ChatObject.isChannel(currentChat) && (!currentChat.megagroup || !TextUtils.isEmpty(currentChat.username))) { - MessagesController.getInstance(currentAccount).deleteDialog(dialog_id, 2); + MessagesController.getInstance(currentAccount).deleteDialog(dialog_id, 2, param); } else { if (id != clear_history) { NotificationCenter.getInstance(currentAccount).removeObserver(ChatActivity.this, NotificationCenter.closeChats); NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.needDeleteDialog, dialog_id, currentUser, currentChat); finishFragment(); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.needDeleteDialog, dialog_id, currentUser, currentChat, param); } else { clearingHistory = true; - undoView.showWithAction(dialog_id, id == clear_history, () -> { + undoView.showWithAction(dialog_id, id == clear_history ? UndoView.ACTION_CLEAR : UndoView.ACTION_DELETE, () -> { if (id == clear_history) { if (chatInfo != null && chatInfo.pinned_msg_id != 0) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); @@ -1121,18 +1144,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not preferences.edit().putInt("pin_" + dialog_id, userInfo.pinned_msg_id).commit(); updatePinnedMessageView(true); } - MessagesController.getInstance(currentAccount).deleteDialog(dialog_id, 1); + MessagesController.getInstance(currentAccount).deleteDialog(dialog_id, 1, param); clearingHistory = false; + clearHistory(false); chatAdapter.notifyDataSetChanged(); } else { if (isChat) { if (ChatObject.isNotInChat(currentChat)) { - MessagesController.getInstance(currentAccount).deleteDialog(dialog_id, 0); + MessagesController.getInstance(currentAccount).deleteDialog(dialog_id, 0, param); } else { MessagesController.getInstance(currentAccount).deleteUserFromChat((int) -dialog_id, MessagesController.getInstance(currentAccount).getUser(UserConfig.getInstance(currentAccount).getClientUserId()), null); } } else { - MessagesController.getInstance(currentAccount).deleteDialog(dialog_id, 0); + MessagesController.getInstance(currentAccount).deleteDialog(dialog_id, 0, param); } finishFragment(); } @@ -1166,28 +1190,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (id == report) { AlertsCreator.createReportAlert(getParentActivity(), dialog_id, 0, ChatActivity.this); - } else if (id == reply) { - MessageObject messageObject = null; - for (int a = 1; a >= 0; a--) { - if (messageObject == null && selectedMessagesIds[a].size() == 1) { - ArrayList ids = new ArrayList<>(); - for (int b = 0; b < selectedMessagesIds[a].size(); b++) { - ids.add(selectedMessagesIds[a].keyAt(b)); - } - messageObject = messagesDict[a].get(ids.get(0)); - } - selectedMessagesIds[a].clear(); - selectedMessagesCanCopyIds[a].clear(); - selectedMessagesCanStarIds[a].clear(); - } - if (messageObject != null && (messageObject.messageOwner.id > 0 || messageObject.messageOwner.id < 0 && currentEncryptedChat != null)) { - showFieldPanelForReply(true, messageObject); - } - cantDeleteMessagesCount = 0; - canEditMessagesCount = 0; - actionBar.hideActionMode(); - updatePinnedMessageView(true); - updateVisibleRows(); } else if (id == star) { for (int a = 0; a < 2; a++) { for (int b = 0; b < selectedMessagesCanStarIds[a].size(); b++) { @@ -1200,9 +1202,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); } - cantDeleteMessagesCount = 0; - canEditMessagesCount = 0; - actionBar.hideActionMode(); + hideActionMode(); updatePinnedMessageView(true); updateVisibleRows(); } else if (id == edit) { @@ -1219,11 +1219,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); } - startReplyOnTextChange = false; startEditingMessageObject(messageObject); - cantDeleteMessagesCount = 0; - canEditMessagesCount = 0; - actionBar.hideActionMode(); + hideActionMode(); updatePinnedMessageView(true); updateVisibleRows(); } else if (id == chat_menu_attach) { @@ -1331,10 +1328,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } searchItem.setVisibility(View.GONE); - highlightMessageId = Integer.MAX_VALUE; - if (searchWas) { - scrollToLastMessage(false); - } + removeSelectedMessageHighlight(); updateBottomOverlay(); updatePinnedMessageView(true); updateVisibleRows(); @@ -1395,9 +1389,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } headerItem = menu.addItem(0, R.drawable.ic_ab_other); + headerItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); if (currentUser != null) { - headerItem.addSubItem(call, LocaleController.getString("Call", R.string.Call)); - TLRPC.TL_userFull userFull = MessagesController.getInstance(currentAccount).getUserFull(currentUser.id); + headerItem.addSubItem(call, R.drawable.msg_callback, LocaleController.getString("Call", R.string.Call)); + TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(currentUser.id); if (userFull != null && userFull.phone_calls_available) { headerItem.showSubItem(call); } else { @@ -1421,44 +1416,44 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not editTextItem.addSubItem(text_regular, LocaleController.getString("Regular", R.string.Regular)); if (searchItem != null) { - headerItem.addSubItem(search, LocaleController.getString("Search", R.string.Search)); + headerItem.addSubItem(search, R.drawable.msg_search, LocaleController.getString("Search", R.string.Search)); } if (currentChat != null && !currentChat.creator) { - headerItem.addSubItem(report, LocaleController.getString("ReportChat", R.string.ReportChat)); + headerItem.addSubItem(report, R.drawable.msg_report, LocaleController.getString("ReportChat", R.string.ReportChat)); } if (currentUser != null) { - addContactItem = headerItem.addSubItem(share_contact, ""); + addContactItem = headerItem.addSubItem(share_contact, R.drawable.msg_addcontact, ""); } if (currentEncryptedChat != null) { - timeItem2 = headerItem.addSubItem(chat_enc_timer, LocaleController.getString("SetTimer", R.string.SetTimer)); + 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, LocaleController.getString("ClearHistory", R.string.ClearHistory)); + headerItem.addSubItem(clear_history, R.drawable.msg_clear, LocaleController.getString("ClearHistory", R.string.ClearHistory)); } if (currentUser == null || !currentUser.self) { - muteItem = headerItem.addSubItem(mute, null); + 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, LocaleController.getString("DeleteAndExit", R.string.DeleteAndExit)); + headerItem.addSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString("DeleteAndExit", R.string.DeleteAndExit)); } else { - headerItem.addSubItem(delete_chat, LocaleController.getString("LeaveChannelMenu", R.string.LeaveChannelMenu)); + headerItem.addSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString("LeaveChannelMenu", R.string.LeaveChannelMenu)); } } } else if (!ChatObject.isChannel(currentChat)) { if (currentChat != null && !isBroadcast) { - headerItem.addSubItem(delete_chat, LocaleController.getString("DeleteAndExit", R.string.DeleteAndExit)); + headerItem.addSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString("DeleteAndExit", R.string.DeleteAndExit)); } else { - headerItem.addSubItem(delete_chat, LocaleController.getString("DeleteChatUser", R.string.DeleteChatUser)); + headerItem.addSubItem(delete_chat, R.drawable.msg_delete, LocaleController.getString("DeleteChatUser", R.string.DeleteChatUser)); } } if (currentUser != null && currentUser.self) { - headerItem.addSubItem(add_shortcut, LocaleController.getString("AddShortcut", R.string.AddShortcut)); + 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, LocaleController.getString("BotSettings", R.string.BotSettings)); - headerItem.addSubItem(bot_help, LocaleController.getString("BotHelp", R.string.BotHelp)); + 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(); } @@ -1487,20 +1482,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selectedMessagesCountTextView.setOnTouchListener((v, event) -> true); if (currentEncryptedChat == null) { - actionModeViews.add(actionMode.addItemWithWidth(edit, R.drawable.group_edit, AndroidUtilities.dp(54))); - if (!isBroadcast) { - actionModeViews.add(actionMode.addItemWithWidth(reply, R.drawable.ic_ab_reply, AndroidUtilities.dp(54))); - } - actionModeViews.add(actionMode.addItemWithWidth(star, R.drawable.ic_ab_fave, AndroidUtilities.dp(54))); - actionModeViews.add(actionMode.addItemWithWidth(copy, R.drawable.ic_ab_copy, AndroidUtilities.dp(54))); - actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.ic_ab_forward, AndroidUtilities.dp(54))); - actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.ic_ab_delete, AndroidUtilities.dp(54))); + actionModeViews.add(actionMode.addItemWithWidth(edit, R.drawable.msg_edit, AndroidUtilities.dp(54), LocaleController.getString("Edit", R.string.Edit))); + actionModeViews.add(actionMode.addItemWithWidth(star, R.drawable.msg_fave, AndroidUtilities.dp(54), LocaleController.getString("AddToFavorites", R.string.AddToFavorites))); + actionModeViews.add(actionMode.addItemWithWidth(copy, R.drawable.msg_copy, AndroidUtilities.dp(54), LocaleController.getString("Copy", R.string.Copy))); + actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.msg_forward, AndroidUtilities.dp(54), LocaleController.getString("Forward", R.string.Forward))); + actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete))); } else { - actionModeViews.add(actionMode.addItemWithWidth(edit, R.drawable.group_edit, AndroidUtilities.dp(54))); - actionModeViews.add(actionMode.addItemWithWidth(reply, R.drawable.ic_ab_reply, AndroidUtilities.dp(54))); - actionModeViews.add(actionMode.addItemWithWidth(star, R.drawable.ic_ab_fave, AndroidUtilities.dp(54))); - actionModeViews.add(actionMode.addItemWithWidth(copy, R.drawable.ic_ab_copy, AndroidUtilities.dp(54))); - actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.ic_ab_delete, AndroidUtilities.dp(54))); + actionModeViews.add(actionMode.addItemWithWidth(edit, R.drawable.msg_edit, AndroidUtilities.dp(54), LocaleController.getString("Edit", R.string.Edit))); + actionModeViews.add(actionMode.addItemWithWidth(star, R.drawable.msg_fave, AndroidUtilities.dp(54), LocaleController.getString("AddToFavorites", R.string.AddToFavorites))); + actionModeViews.add(actionMode.addItemWithWidth(copy, R.drawable.msg_copy, AndroidUtilities.dp(54), LocaleController.getString("Copy", R.string.Copy))); + actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete))); } actionMode.getItem(edit).setVisibility(canEditMessagesCount == 1 && selectedMessagesIds[0].size() + selectedMessagesIds[1].size() == 1 ? View.VISIBLE : View.GONE); actionMode.getItem(copy).setVisibility(selectedMessagesCanCopyIds[0].size() + selectedMessagesCanCopyIds[1].size() != 0 ? View.VISIBLE : View.GONE); @@ -1508,10 +1499,24 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not actionMode.getItem(delete).setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); checkActionBarMenu(); + scrimPaint = new Paint() { + @Override + public void setAlpha(int a) { + super.setAlpha(a); + if (fragmentView != null) { + fragmentView.invalidate(); + } + } + }; + fragmentView = new SizeNotifierFrameLayout(context) { int inputFieldHeight = 0; + ArrayList drawTimeAfter = new ArrayList<>(); + ArrayList drawNamesAfter = new ArrayList<>(); + ArrayList drawCaptionAfter = new ArrayList<>(); + @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); @@ -1521,8 +1526,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (scrimView != null || chatActivityEnterView != null && chatActivityEnterView.isStickersExpanded() && ev.getY() < chatActivityEnterView.getY()) { + return false; + } + return super.dispatchTouchEvent(ev); + } + @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (scrimView != null && (child == pagedownButton || child == mentiondownButton || child == floatingDateView)) { + return false; + } boolean result; MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); boolean isRoundVideo = false; @@ -1553,9 +1569,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not super.drawChild(canvas, videoPlayerContainer, drawingTime); if (drawLaterRoundProgressCell != null) { canvas.save(); - canvas.translate(drawLaterRoundProgressCell.getX(), drawLaterRoundProgressCell.getTop() + chatListView.getTop()); + canvas.translate(drawLaterRoundProgressCell.getX(), drawLaterRoundProgressCell.getTop() + chatListView.getY()); if (isRoundVideo) { drawLaterRoundProgressCell.drawRoundProgress(canvas); + drawLaterRoundProgressCell.drawOverlays(canvas); } else { drawLaterRoundProgressCell.drawOverlays(canvas); if (drawLaterRoundProgressCell.needDrawTime()) { @@ -1577,6 +1594,149 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return actionBar.getVisibility() == VISIBLE; } + private void drawChildElement(Canvas canvas, float listTop, ChatMessageCell cell, int type) { + canvas.save(); + canvas.clipRect(chatListView.getLeft(), listTop, chatListView.getRight(), chatListView.getY() + chatListView.getMeasuredHeight()); + canvas.translate(chatListView.getLeft() + cell.getLeft(), chatListView.getY() + cell.getTop()); + if (type == 0) { + cell.drawTime(canvas); + } else if (type == 1) { + cell.drawNamesLayout(canvas); + } else { + cell.drawCaptionLayout(canvas, (cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_LEFT) == 0); + } + canvas.restore(); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (scrimView != null) { + canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), scrimPaint); + int chatListViewTop = (int) chatListView.getY(); + int chatListViewBottom = chatListViewTop + chatListView.getMeasuredHeight(); + int listTop = chatListView.getTop() + chatListView.getPaddingTop() - AndroidUtilities.dp(4) + (chatActivityEnterView.getMeasuredHeight() - AndroidUtilities.dp(51)); + MessageObject.GroupedMessages scrimGroup; + if (scrimView instanceof ChatMessageCell) { + scrimGroup = ((ChatMessageCell) scrimView).getCurrentMessagesGroup(); + } else { + scrimGroup = null; + } + + int count = chatListView.getChildCount(); + for (int num = 0; num < count; num++) { + View child = chatListView.getChildAt(num); + MessageObject.GroupedMessages group; + MessageObject.GroupedMessagePosition position; + ChatMessageCell cell; + if (child instanceof ChatMessageCell) { + cell = (ChatMessageCell) child; + group = cell.getCurrentMessagesGroup(); + position = cell.getCurrentPosition(); + } else { + position = null; + group = null; + cell = null; + } + if (child != scrimView && (scrimGroup == null || scrimGroup != group)) { + continue; + } + + int clipLeft = 0; + int clipBottom = 0; + if (position != null) { + if (position.pw != position.spanSize && position.spanSize == 1000 && position.siblingHeights == null && group.hasSibling) { + clipLeft = cell.getBackgroundDrawableLeft(); + } else if (position.siblingHeights != null) { + clipBottom = child.getBottom() - AndroidUtilities.dp(1 + (cell.isPinnedBottom() ? 1 : 0)); + } + } + float viewClipLeft; + float viewClipRight; + float viewClipTop; + float viewClipBottom; + if (clipLeft != 0) { + float x = chatListView.getLeft() + clipLeft + child.getTranslationX(); + float y = chatListView.getTop() + child.getTop(); + + viewClipLeft = Math.max(chatListView.getLeft(), x); + viewClipTop = Math.max(listTop, y); + viewClipRight = Math.min(chatListView.getRight(), x + child.getMeasuredWidth()); + viewClipBottom = Math.min(chatListView.getY() + chatListView.getMeasuredHeight(), chatListView.getY() + child.getTop() + child.getMeasuredHeight()); + } else if (clipBottom != 0) { + float x = chatListView.getLeft() + child.getTranslationX(); + float y = chatListView.getTop() + child.getTop(); + + viewClipLeft = Math.max(chatListView.getLeft(), x); + viewClipTop = Math.max(listTop, y); + viewClipRight = Math.min(chatListView.getRight(), x + child.getMeasuredWidth()); + viewClipBottom = Math.min(chatListView.getY() + chatListView.getMeasuredHeight(), chatListView.getY() + clipBottom); + } else { + viewClipLeft = Math.max(chatListView.getLeft(), chatListView.getLeft() + child.getX()); + viewClipTop = Math.max(listTop, chatListView.getTop() + child.getY()); + viewClipRight = Math.min(chatListView.getRight(), chatListView.getLeft() + child.getX() + child.getMeasuredWidth()); + viewClipBottom = Math.min(chatListView.getY() + chatListView.getMeasuredHeight(), chatListView.getY() + child.getY() + child.getMeasuredHeight()); + } + if (viewClipTop < viewClipBottom) { + canvas.save(); + canvas.clipRect(viewClipLeft, viewClipTop, viewClipRight, viewClipBottom); + canvas.translate(chatListView.getLeft() + child.getLeft(), chatListView.getY() + child.getTop()); + child.draw(canvas); + canvas.restore(); + } + + if (position != null) { + if (position.last || position.minX == 0 && position.minY == 0) { + if (position.last) { + drawTimeAfter.add(cell); + } + if (position.minX == 0 && position.minY == 0 && cell.hasNameLayout()) { + drawNamesAfter.add(cell); + } + } + if (cell.hasCaptionLayout() && (position.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0) { + drawCaptionAfter.add(cell); + } + } + } + int size = drawTimeAfter.size(); + if (size > 0) { + for (int a = 0; a < size; a++) { + drawChildElement(canvas, listTop, drawTimeAfter.get(a), 0); + } + drawTimeAfter.clear(); + } + size = drawNamesAfter.size(); + if (size > 0) { + for (int a = 0; a < size; a++) { + drawChildElement(canvas, listTop, drawNamesAfter.get(a), 1); + } + drawNamesAfter.clear(); + } + size = drawCaptionAfter.size(); + if (size > 0) { + for (int a = 0; a < size; a++) { + ChatMessageCell cell = drawCaptionAfter.get(a); + if (cell.getCurrentPosition() == null) { + continue; + } + drawChildElement(canvas, listTop, cell, 2); + } + drawCaptionAfter.clear(); + } + + if (pagedownButton != null && pagedownButton.getTag() != null) { + super.drawChild(canvas, pagedownButton, SystemClock.uptimeMillis()); + } + if (mentiondownButton != null && mentiondownButton.getTag() != null) { + super.drawChild(canvas, mentiondownButton, SystemClock.uptimeMillis()); + } + if (floatingDateView != null && floatingDateView.getTag() != null) { + super.drawChild(canvas, floatingDateView, SystemClock.uptimeMillis()); + } + } + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int allHeight; @@ -1594,18 +1754,27 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int keyboardSize = getKeyboardHeight(); - if (keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow) { - heightSize -= chatActivityEnterView.getEmojiPadding(); - allHeight -= chatActivityEnterView.getEmojiPadding(); + if (keyboardSize <= AndroidUtilities.dp(20)) { + if (!AndroidUtilities.isInMultiwindow) { + heightSize -= chatActivityEnterView.getEmojiPadding(); + allHeight -= chatActivityEnterView.getEmojiPadding(); + } + } else { + globalIgnoreLayout = true; + chatActivityEnterView.hideEmojiView(); + globalIgnoreLayout = false; } int childCount = getChildCount(); measureChildWithMargins(chatActivityEnterView, widthMeasureSpec, 0, heightMeasureSpec, 0); + int listViewTopHeight; if (inPreviewMode) { inputFieldHeight = 0; + listViewTopHeight = 0; } else { inputFieldHeight = chatActivityEnterView.getMeasuredHeight(); + listViewTopHeight = AndroidUtilities.dp(49); } for (int i = 0; i < childCount; i++) { @@ -1613,7 +1782,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (child == null || child.getVisibility() == GONE || child == chatActivityEnterView || child == actionBar) { continue; } - if (child == chatListView || child == progressView) { + if (child == chatListView) { + /*globalIgnoreLayout = true; + int additionalPadding = inputFieldHeight - AndroidUtilities.dp(51); + if (pinnedMessageView != null && pinnedMessageView.getTag() == null || reportSpamView != null && reportSpamView.getTag() == null) { + chatListView.setPadding(0, AndroidUtilities.dp(52) + additionalPadding, 0, AndroidUtilities.dp(3)); + } else { + chatListView.setPadding(0, AndroidUtilities.dp(4) + additionalPadding, 0, AndroidUtilities.dp(3)); + } + globalIgnoreLayout = false;*/ + if (chatActivityEnterView.getAlpha() != 1.0f) { + chatListView.setTranslationY(inputFieldHeight - AndroidUtilities.dp(51)); + } + chatListViewClipTop = inPreviewMode ? 0 : (inputFieldHeight - AndroidUtilities.dp(51)); + int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); + int contentHeightSpec = MeasureSpec.makeMeasureSpec(Math.max(AndroidUtilities.dp(10), heightSize - listViewTopHeight - (inPreviewMode && Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0)), MeasureSpec.EXACTLY); + child.measure(contentWidthSpec, contentHeightSpec); + } else if (child == progressView) { int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); int contentHeightSpec = MeasureSpec.makeMeasureSpec(Math.max(AndroidUtilities.dp(10), heightSize - inputFieldHeight - (inPreviewMode && Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0) + AndroidUtilities.dp(2 + (chatActivityEnterView.isTopViewVisible() ? 48 : 0))), MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); @@ -1794,7 +1979,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (child == gifHintTextView || child == voiceHintTextView || child == mediaBanTooltip) { childTop -= inputFieldHeight; - } else if (child == chatListView || child == progressView) { + } else if (child == chatListView) { + if (!inPreviewMode) { + childTop -= (inputFieldHeight - AndroidUtilities.dp(51)); + } + } else if (child == progressView) { if (chatActivityEnterView.isTopViewVisible()) { childTop -= AndroidUtilities.dp(48); } @@ -1812,7 +2001,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } updateMessagesVisiblePart(true); - checkAutoDownloadMessages(); + updateTextureViewPosition(false); + if (!scrollingChatListView) { + checkAutoDownloadMessages(false); + } notifyHeightChanged(); } }; @@ -1904,6 +2096,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (noSoundHintView != null) { noSoundHintView.hide(); } + if (forwardHintView != null) { + forwardHintView.hide(); + } } forceScrollToTop = false; if (chatAdapter.isBot) { @@ -1942,6 +2137,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not invalidate(); } + @Override + public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate) { + if (scrimPopupWindow != null) { + return false; + } + return super.requestChildRectangleOnScreen(child, rect, immediate); + } + @Override public boolean onInterceptTouchEvent(MotionEvent e) { boolean result = super.onInterceptTouchEvent(e); @@ -2062,14 +2265,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not slidingView.setTranslationX(dx); MessageObject messageObject = slidingView.getMessageObject(); if (messageObject.isRoundVideo() || messageObject.isVideo()) { - updateTextureViewPosition(); + updateTextureViewPosition(false); } setGroupTranslationX(slidingView, dx); invalidate(); } } else if (slidingView != null && e.getPointerId(0) == startedTrackingPointerId && (e.getAction() == MotionEvent.ACTION_CANCEL || e.getAction() == MotionEvent.ACTION_UP || e.getAction() == MotionEvent.ACTION_POINTER_UP)) { if (Math.abs(slidingView.getTranslationX()) >= AndroidUtilities.dp(50)) { - showFieldPanelForReply(true, slidingView.getMessageObject()); + showFieldPanelForReply(slidingView.getMessageObject()); } endedTrackingX = slidingView.getTranslationX(); lastTrackingAnimationTime = System.currentTimeMillis(); @@ -2147,7 +2350,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not slidingView.setTranslationX(translationX); MessageObject messageObject = slidingView.getMessageObject(); if (messageObject.isRoundVideo() || messageObject.isVideo()) { - updateTextureViewPosition(); + updateTextureViewPosition(false); } invalidate(); } @@ -2158,6 +2361,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected void dispatchDraw(Canvas canvas) { drawLaterRoundProgressCell = null; + int count = getChildCount(); + for (int a = 0; a < count; a++) { + View child = getChildAt(a); + if (child instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) child; + MessageObject.GroupedMessagePosition position = cell.getCurrentPosition(); + if (cell.isDrawingSelectionBackground() && (position == null || (position.flags & MessageObject.POSITION_FLAG_RIGHT) != 0)) { + int color = Theme.getColor(Theme.key_chat_selectedBackground); + int alpha = Color.alpha(color); + Theme.chat_replyLinePaint.setColor(Theme.getColor(Theme.key_chat_selectedBackground)); + Theme.chat_replyLinePaint.setAlpha((int) (alpha * cell.getHightlightAlpha())); + canvas.drawRect(0, cell.getTop(), getMeasuredWidth(), cell.getBottom(), Theme.chat_replyLinePaint); + } + } + } super.dispatchDraw(canvas); } @@ -2165,8 +2383,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public boolean drawChild(Canvas canvas, View child, long drawingTime) { int clipLeft = 0; int clipBottom = 0; + boolean skipDraw = child == scrimView; + ChatMessageCell cell; if (child instanceof ChatMessageCell) { - ChatMessageCell cell = (ChatMessageCell) child; + cell = (ChatMessageCell) child; MessageObject.GroupedMessagePosition position = cell.getCurrentPosition(); MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); if (position != null) { @@ -2179,18 +2399,34 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (cell.needDelayRoundProgressDraw()) { drawLaterRoundProgressCell = cell; } + if (!skipDraw && scrimView instanceof ChatMessageCell) { + ChatMessageCell cell2 = (ChatMessageCell) scrimView; + if (cell2.getCurrentMessagesGroup() != null && cell2.getCurrentMessagesGroup() == group) { + skipDraw = true; + } + } + } else { + cell = null; } if (clipLeft != 0) { canvas.save(); - canvas.clipRect(clipLeft + child.getTranslationX(), child.getTop(), child.getRight() + child.getTranslationX(), child.getBottom()); + //canvas.clipRect(clipLeft + child.getTranslationX(), child.getTop(), child.getRight() + child.getTranslationX(), child.getBottom()); } else if (clipBottom != 0) { canvas.save(); - canvas.clipRect(child.getLeft() + child.getTranslationX(), child.getTop(), child.getRight() + child.getTranslationX(), clipBottom); + //canvas.clipRect(child.getLeft() + child.getTranslationX(), child.getTop(), child.getRight() + child.getTranslationX(), clipBottom); + } + boolean result; + if (!skipDraw) { + result = super.drawChild(canvas, child, drawingTime); + } else { + result = false; } - boolean result = super.drawChild(canvas, child, drawingTime); if (clipLeft != 0 || clipBottom != 0) { canvas.restore(); } + if (cell != null) { + cell.drawCheckBox(canvas); + } int num = 0; int count = getChildCount(); for (int a = 0; a < count; a++) { @@ -2203,7 +2439,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int size = drawTimeAfter.size(); if (size > 0) { for (int a = 0; a < size; a++) { - ChatMessageCell cell = drawTimeAfter.get(a); + cell = drawTimeAfter.get(a); canvas.save(); canvas.translate(cell.getLeft() + cell.getTranslationX(), cell.getTop()); cell.drawTime(canvas); @@ -2214,7 +2450,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not size = drawNamesAfter.size(); if (size > 0) { for (int a = 0; a < size; a++) { - ChatMessageCell cell = drawNamesAfter.get(a); + cell = drawNamesAfter.get(a); canvas.save(); canvas.translate(cell.getLeft() + cell.getTranslationX(), cell.getTop()); cell.drawNamesLayout(canvas); @@ -2225,7 +2461,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not size = drawCaptionAfter.size(); if (size > 0) { for (int a = 0; a < size; a++) { - ChatMessageCell cell = drawCaptionAfter.get(a); + cell = drawCaptionAfter.get(a); if (cell.getCurrentPosition() == null) { continue; } @@ -2278,9 +2514,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject message = chatMessageCell.getMessageObject(); if (videoPlayerContainer != null && (message.isRoundVideo() || message.isVideo()) && MediaController.getInstance().isPlayingMessage(message)) { ImageReceiver imageReceiver = chatMessageCell.getPhotoImage(); - int additionalTop = chatActivityEnterView.isTopViewVisible() ? AndroidUtilities.dp(48) : 0; float newX = imageReceiver.getImageX() + chatMessageCell.getX(); - float newY = fragmentView.getPaddingTop() + chatMessageCell.getTop() + imageReceiver.getImageY() - additionalTop + (inPreviewMode ? AndroidUtilities.statusBarHeight : 0); + float newY = fragmentView.getPaddingTop() + chatMessageCell.getTop() + imageReceiver.getImageY() - chatListViewClipTop + chatListView.getTranslationY() + (inPreviewMode ? AndroidUtilities.statusBarHeight : 0); if (videoPlayerContainer.getTranslationX() != newX || videoPlayerContainer.getTranslationY() != newY) { videoPlayerContainer.setTranslationX(newX); videoPlayerContainer.setTranslationY(newY); @@ -2369,7 +2604,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not tx = Math.min(holder.itemView.getTranslationX(), tx); } if (holder.itemView instanceof ChatMessageCell) { - ChatMessageCell cell = (ChatMessageCell) holder.itemView; + cell = (ChatMessageCell) holder.itemView; if (!cell.isPinnedTop()) { break; } @@ -2398,13 +2633,40 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } return result; } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + if (currentEncryptedChat != null) { + return; + } + super.onInitializeAccessibilityNodeInfo(info); + if (Build.VERSION.SDK_INT >= 19) { + AccessibilityNodeInfo.CollectionInfo collection = info.getCollectionInfo(); + if (collection != null) { + info.setCollectionInfo(AccessibilityNodeInfo.CollectionInfo.obtain(collection.getRowCount(), 1, false)); + } + } + } + + @Override + public AccessibilityNodeInfo createAccessibilityNodeInfo() { + if (currentEncryptedChat != null) { + return null; + } + return super.createAccessibilityNodeInfo(); + } }; + if (currentEncryptedChat != null && Build.VERSION.SDK_INT >= 19) { + chatListView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); + } + chatListView.setInstantClick(true); + chatListView.setDisableHighlightState(true); chatListView.setTag(1); chatListView.setVerticalScrollBarEnabled(true); chatListView.setAdapter(chatAdapter = new ChatActivityAdapter(context)); chatListView.setClipToPadding(false); chatListView.setPadding(0, AndroidUtilities.dp(4), 0, AndroidUtilities.dp(3)); - chatListView.setItemAnimator(/*itemAnimator = new ChatItemAnimator(chatListView, this)*/null); + chatListView.setItemAnimator(null); chatListView.setLayoutAnimation(null); chatLayoutManager = new GridLayoutManagerFixed(context, 1000, LinearLayoutManager.VERTICAL, true) { @@ -2488,7 +2750,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not for (int a = 0; a < position.siblingHeights.length; a++) { h += (int) Math.ceil(maxHeight * position.siblingHeights[a]); } - h += (position.maxY - position.minY) * AndroidUtilities.dp2(7); + h += (position.maxY - position.minY) * Math.round(7 * AndroidUtilities.density); int count = group.posArray.size(); for (int a = 0; a < count; a++) { MessageObject.GroupedMessagePosition pos = group.posArray.get(a); @@ -2512,6 +2774,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatListView.setOnScrollListener(new RecyclerView.OnScrollListener() { private float totalDy = 0; + private boolean scrollUp; private final int scrollValue = AndroidUtilities.dp(100); @Override @@ -2529,42 +2792,31 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not scrollingChatListView = false; checkTextureViewPosition = false; hideFloatingDateView(true); - checkAutoDownloadMessages(); + checkAutoDownloadMessages(scrollUp); } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { chatListView.invalidate(); + scrollUp = dy < 0; if (!wasManualScroll && dy != 0) { wasManualScroll = true; } - if (dy != 0 && noSoundHintView != null) { - noSoundHintView.hide(); + if (dy != 0) { + if (noSoundHintView != null) { + noSoundHintView.hide(); + } + if (forwardHintView != null) { + forwardHintView.hide(); + } } if (dy != 0 && scrollingFloatingDate && !currentFloatingTopIsNotMessage) { if (highlightMessageId != Integer.MAX_VALUE) { - highlightMessageId = Integer.MAX_VALUE; + removeSelectedMessageHighlight(); updateVisibleRows(); } - if (floatingDateView.getTag() == null) { - if (floatingDateAnimation != null) { - floatingDateAnimation.cancel(); - } - floatingDateView.setTag(1); - floatingDateAnimation = new AnimatorSet(); - floatingDateAnimation.setDuration(150); - floatingDateAnimation.playTogether(ObjectAnimator.ofFloat(floatingDateView, "alpha", 1.0f)); - floatingDateAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (animation.equals(floatingDateAnimation)) { - floatingDateAnimation = null; - } - } - }); - floatingDateAnimation.start(); - } + showFloatingDateView(true); } checkScrollForLoad(true); int firstVisibleItem = chatLayoutManager.findFirstVisibleItemPosition(); @@ -2614,7 +2866,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not floatingDateView = new ChatActionCell(context) { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { - if (getAlpha() == 0) { + if (getAlpha() == 0 || actionBar.isActionModeShowed()) { return false; } return super.onInterceptTouchEvent(ev); @@ -2622,7 +2874,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public boolean onTouchEvent(MotionEvent event) { - if (getAlpha() == 0) { + if (getAlpha() == 0 || actionBar.isActionModeShowed()) { return false; } return super.onTouchEvent(event); @@ -2631,7 +2883,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not floatingDateView.setAlpha(0.0f); contentView.addView(floatingDateView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 4, 0, 0)); floatingDateView.setOnClickListener(view -> { - if (floatingDateView.getAlpha() == 0) { + if (floatingDateView.getAlpha() == 0 || actionBar.isActionModeShowed()) { return; } Calendar calendar = Calendar.getInstance(); @@ -2684,6 +2936,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not closePinned.setImageResource(R.drawable.miniplayer_close); closePinned.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_topPanelClose), PorterDuff.Mode.MULTIPLY)); closePinned.setScaleType(ImageView.ScaleType.CENTER); + closePinned.setContentDescription(LocaleController.getString("Close", R.string.Close)); pinnedMessageView.addView(closePinned, LayoutHelper.createFrame(36, 48, Gravity.RIGHT | Gravity.TOP)); closePinned.setOnClickListener(v -> { if (getParentActivity() == null) { @@ -2880,7 +3133,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not messagesStorage.resetMentionsCount(dialog_id, newMentionsCount); if (newMentionsCount == 0) { hasAllMentionsLocal = true; - showMentiondownButton(false, true); + showMentionDownButton(false, true); } else { mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); loadLastUnreadMention(); @@ -2919,7 +3172,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not newMentionsCount = 0; MessagesController.getInstance(currentAccount).markMentionsAsRead(dialog_id); hasAllMentionsLocal = true; - showMentiondownButton(false, true); + showMentionDownButton(false, true); return true; }); @@ -2960,6 +3213,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }; mentionContainer.setVisibility(View.GONE); + updateMessageListAccessibilityVisibility(); mentionContainer.setWillNotDraw(false); contentView.addView(mentionContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 110, Gravity.LEFT | Gravity.BOTTOM)); @@ -2979,7 +3233,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return false; } } - boolean result = StickerPreviewViewer.getInstance().onInterceptTouchEvent(event, mentionListView, 0, null); + boolean result = ContentPreviewViewer.getInstance().onInterceptTouchEvent(event, mentionListView, 0, null); return super.onInterceptTouchEvent(event) || result; } @@ -3036,7 +3290,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mentionListViewUpdateLayout(); } }; - mentionListView.setOnTouchListener((v, event) -> StickerPreviewViewer.getInstance().onTouch(event, mentionListView, 0, mentionsOnItemClickListener, null)); + mentionListView.setOnTouchListener((v, event) -> ContentPreviewViewer.getInstance().onTouch(event, mentionListView, 0, mentionsOnItemClickListener, null)); mentionListView.setTag(2); mentionLayoutManager = new LinearLayoutManager(context) { @Override @@ -3176,8 +3430,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (mentionsAdapter.isBotContext() && mentionsAdapter.isMediaLayout()) { mentionGridLayoutManager.scrollToPositionWithOffset(0, 10000); - } else { - mentionLayoutManager.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()) { @@ -3192,10 +3446,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } mentionContainer.setVisibility(View.VISIBLE); + updateMessageListAccessibilityVisibility(); mentionContainer.setTag(null); mentionListAnimation = new AnimatorSet(); mentionListAnimation.playTogether( - ObjectAnimator.ofFloat(mentionContainer, "alpha", 0.0f, 1.0f) + ObjectAnimator.ofFloat(mentionContainer, View.ALPHA, 0.0f, 1.0f) ); mentionListAnimation.addListener(new AnimatorListenerAdapter() { @Override @@ -3217,6 +3472,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { mentionContainer.setAlpha(1.0f); mentionContainer.setVisibility(View.INVISIBLE); + updateMessageListAccessibilityVisibility(); } } else { if (mentionListAnimation != null) { @@ -3230,7 +3486,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (allowStickersPanel) { mentionListAnimation = new AnimatorSet(); mentionListAnimation.playTogether( - ObjectAnimator.ofFloat(mentionContainer, "alpha", 0.0f) + ObjectAnimator.ofFloat(mentionContainer, View.ALPHA, 0.0f) ); mentionListAnimation.addListener(new AnimatorListenerAdapter() { @Override @@ -3238,6 +3494,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { mentionContainer.setVisibility(View.GONE); mentionContainer.setTag(null); + updateMessageListAccessibilityVisibility(); mentionListAnimation = null; } } @@ -3254,6 +3511,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { mentionContainer.setTag(null); mentionContainer.setVisibility(View.GONE); + updateMessageListAccessibilityVisibility(); } } } @@ -3272,7 +3530,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } if (result.type.equals("video") || result.type.equals("web_player_video")) { - int size[] = MessageObject.getInlineResultWidthAndHeight(result); + 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); @@ -3330,7 +3588,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (mentionsAdapter.isBotCommands()) { SendMessagesHelper.getInstance(currentAccount).sendMessage((String) object, dialog_id, replyingMessageObject, null, false, null, null, null); chatActivityEnterView.setFieldText(""); - hideFieldPanel(); + hideFieldPanel(false); } else { chatActivityEnterView.replaceWithText(start, len, object + " ", false); } @@ -3350,8 +3608,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (object instanceof TLRPC.TL_inlineBotSwitchPM) { processInlineBotContextPM((TLRPC.TL_inlineBotSwitchPM) object); - } else if (object instanceof EmojiSuggestion) { - String code = ((EmojiSuggestion) object).emoji; + } else if (object instanceof DataQuery.KeywordResult) { + String code = ((DataQuery.KeywordResult) object).emoji; chatActivityEnterView.addEmojiToRecent(code); chatActivityEnterView.replaceWithText(start, len, code, true); } @@ -3421,6 +3679,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pagedownButtonImage.setBackgroundDrawable(drawable); pagedownButton.addView(pagedownButtonImage, LayoutHelper.createFrame(46, 46, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)); + pagedownButton.setContentDescription(LocaleController.getString("AccDescrPageDown", R.string.AccDescrPageDown)); pagedownButtonCounter = new TextView(context); pagedownButtonCounter.setVisibility(View.INVISIBLE); @@ -3458,6 +3717,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mentiondownButtonCounter.setMinWidth(AndroidUtilities.dp(23)); mentiondownButtonCounter.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), AndroidUtilities.dp(1)); mentiondownButton.addView(mentiondownButtonCounter, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 23, Gravity.TOP | Gravity.CENTER_HORIZONTAL)); + mentiondownButton.setContentDescription(LocaleController.getString("AccDescrMentionDown", R.string.AccDescrMentionDown)); if (!AndroidUtilities.isTablet() || AndroidUtilities.isSmallTablet()) { FragmentContextView fragmentLocationContextView = new FragmentContextView(context, this, true); @@ -3483,10 +3743,50 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not instantCameraView = new InstantCameraView(context, this); contentView.addView(instantCameraView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP)); - chatActivityEnterView = new ChatActivityEnterView(getParentActivity(), contentView, this, true); + bottomMessagesActionContainer = new FrameLayout(context) { + @Override + public void onDraw(Canvas canvas) { + int bottom = Theme.chat_composeShadowDrawable.getIntrinsicHeight(); + Theme.chat_composeShadowDrawable.setBounds(0, 0, getMeasuredWidth(), bottom); + Theme.chat_composeShadowDrawable.draw(canvas); + canvas.drawRect(0, bottom, getMeasuredWidth(), getMeasuredHeight(), Theme.chat_composeBackgroundPaint); + } + }; + bottomMessagesActionContainer.setVisibility(View.INVISIBLE); + bottomMessagesActionContainer.setWillNotDraw(false); + bottomMessagesActionContainer.setPadding(0, AndroidUtilities.dp(2), 0, 0); + contentView.addView(bottomMessagesActionContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM)); + bottomMessagesActionContainer.setOnTouchListener((v, event) -> true); + + chatActivityEnterView = new ChatActivityEnterView(getParentActivity(), contentView, this, true) { + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (getAlpha() != 1.0f) { + return false; + } + return super.onInterceptTouchEvent(ev); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (getAlpha() != 1.0f) { + return false; + } + return super.onTouchEvent(event); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (getAlpha() != 1.0f) { + return false; + } + return super.dispatchTouchEvent(ev); + } + }; chatActivityEnterView.setDialogId(dialog_id, currentAccount); 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); @@ -3496,7 +3796,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void onMessageSend(CharSequence message) { moveScrollToLastMessage(); - hideFieldPanel(); + hideFieldPanel(false); if (mentionsAdapter != null) { mentionsAdapter.addHashtagsFromMessage(message); } @@ -3543,13 +3843,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void onTextChanged(final CharSequence text, boolean bigChange) { - if (startReplyOnTextChange && text.length() > 0) { - actionBar.getActionBarMenuOnItemClick().onItemClick(reply); - startReplyOnTextChange = false; - } MediaController.getInstance().setInputFieldHasText(!TextUtils.isEmpty(text) || chatActivityEnterView.isEditingMessage()); - if (stickersAdapter != null && !chatActivityEnterView.isEditingMessage() && (currentChat == null || ChatObject.canSendStickers(currentChat))) { - stickersAdapter.loadStikersForEmoji(text); + if (stickersAdapter != null && chatActivityEnterView != null && chatActivityEnterView.getVisibility() == View.VISIBLE && (bottomOverlay == null || bottomOverlay.getVisibility() != View.VISIBLE)) { + stickersAdapter.loadStikersForEmoji(text, currentChat != null && !ChatObject.canSendStickers(currentChat) || chatActivityEnterView.isEditingMessage()); } if (mentionsAdapter != null) { mentionsAdapter.searchUsernameOrHashtag(text.toString(), chatActivityEnterView.getCursorPosition(), messages, false); @@ -3614,12 +3910,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void onMessageEditEnd(boolean loading) { if (!loading) { mentionsAdapter.setNeedBotContext(currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 46); - chatListView.setOnItemLongClickListener(onItemLongClickListener); - chatListView.setOnItemClickListener(onItemClickListener); - chatListView.setClickable(true); - chatListView.setLongClickable(true); if (editingMessageObject != null) { - hideFieldPanel(); + hideFieldPanel(false); } chatActivityEnterView.setAllowStickersAndGifs(currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 23, currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 46); if (editingMessageObjectReqId != 0) { @@ -3641,6 +3933,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (mentionContainer != null && mentionContainer.getVisibility() == View.VISIBLE) { mentionContainer.setVisibility(View.INVISIBLE); + updateMessageListAccessibilityVisibility(); } } else { allowStickersPanel = true; @@ -3650,6 +3943,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (mentionContainer != null && mentionContainer.getVisibility() == View.INVISIBLE && (!mentionsAdapter.isBotContext() || (allowContextBotPanel || allowContextBotPanelSecond))) { mentionContainer.setVisibility(View.VISIBLE); mentionContainer.setTag(null); + updateMessageListAccessibilityVisibility(); } } @@ -3721,7 +4015,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.invalidate(); } if (getVisibility() != GONE) { - int height = getLayoutParams().height; if (chatListView != null) { chatListView.setTranslationY(translationY); } @@ -3737,6 +4030,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (mentiondownButton != null) { mentiondownButton.setTranslationY(pagedownButton.getVisibility() != VISIBLE ? translationY : translationY - AndroidUtilities.dp(72)); } + updateMessagesVisiblePart(false); + if (fragmentView != null) { + fragmentView.invalidate(); + } } } @@ -3767,7 +4064,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } }; - chatActivityEnterView.addTopView(replyLayout, 48); + + replyLineView = new View(context); + replyLineView.setBackgroundColor(Theme.getColor(Theme.key_chat_replyPanelLine)); + chatActivityEnterView.addTopView(replyLayout, replyLineView, 48); + replyLayout.setOnClickListener(v -> { if (forwardingMessages != null && !forwardingMessages.isEmpty()) { for (int a = 0, N = forwardingMessages.size(); a < N; a++) { @@ -3791,10 +4092,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }); - replyLineView = new View(context); - replyLineView.setBackgroundColor(Theme.getColor(Theme.key_chat_replyPanelLine)); - replyLayout.addView(replyLineView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1, Gravity.BOTTOM | Gravity.LEFT)); - replyIconImageView = new ImageView(context); replyIconImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_replyPanelIcons), PorterDuff.Mode.MULTIPLY)); replyIconImageView.setScaleType(ImageView.ScaleType.CENTER); @@ -3802,14 +4099,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not replyCloseImageView = new ImageView(context); replyCloseImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_replyPanelClose), PorterDuff.Mode.MULTIPLY)); - replyCloseImageView.setImageResource(R.drawable.msg_panel_clear); + replyCloseImageView.setImageResource(R.drawable.input_clear); replyCloseImageView.setScaleType(ImageView.ScaleType.CENTER); replyLayout.addView(replyCloseImageView, LayoutHelper.createFrame(52, 46, Gravity.RIGHT | Gravity.TOP, 0, 0.5f, 0, 0)); replyCloseImageView.setOnClickListener(v -> { if (forwardingMessages != null) { forwardingMessages.clear(); } - showFieldPanel(false, null, null, null, foundWebPage, true); + showFieldPanel(false, null, null, null, foundWebPage, true, true); }); replyNameTextView = new SimpleTextView(context); @@ -3830,7 +4127,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not stickersPanel.setVisibility(View.GONE); contentView.addView(stickersPanel, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 81.5f, Gravity.LEFT | Gravity.BOTTOM, 0, 0, 0, 38)); - final StickerPreviewViewer.StickerPreviewViewerDelegate stickerPreviewViewerDelegate = new StickerPreviewViewer.StickerPreviewViewerDelegate() { + final ContentPreviewViewer.ContentPreviewViewerDelegate contentPreviewViewerDelegate = new ContentPreviewViewer.ContentPreviewViewerDelegate() { @Override public void sendSticker(TLRPC.Document sticker, Object parent) { @@ -3842,25 +4139,27 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } @Override - public void openSet(TLRPC.InputStickerSet set) { + public void openSet(TLRPC.InputStickerSet set, boolean clearsInputField) { if (set == null || getParentActivity() == null) { return; } TLRPC.TL_inputStickerSetID inputStickerSet = new TLRPC.TL_inputStickerSetID(); inputStickerSet.access_hash = set.access_hash; inputStickerSet.id = set.id; - showDialog(new StickersAlert(getParentActivity(), ChatActivity.this, inputStickerSet, null, chatActivityEnterView)); + StickersAlert alert = new StickersAlert(getParentActivity(), ChatActivity.this, inputStickerSet, null, chatActivityEnterView); + alert.setClearsInputField(clearsInputField); + showDialog(alert); } }; stickersListView = new RecyclerListView(context) { @Override public boolean onInterceptTouchEvent(MotionEvent event) { - boolean result = StickerPreviewViewer.getInstance().onInterceptTouchEvent(event, stickersListView, 0, stickerPreviewViewerDelegate); + boolean result = ContentPreviewViewer.getInstance().onInterceptTouchEvent(event, stickersListView, 0, contentPreviewViewerDelegate); return super.onInterceptTouchEvent(event) || result; } }; stickersListView.setTag(3); - stickersListView.setOnTouchListener((v, event) -> StickerPreviewViewer.getInstance().onTouch(event, stickersListView, 0, stickersOnItemClickListener, stickerPreviewViewerDelegate)); + stickersListView.setOnTouchListener((v, event) -> ContentPreviewViewer.getInstance().onTouch(event, stickersListView, 0, stickersOnItemClickListener, contentPreviewViewerDelegate)); stickersListView.setDisallowInterceptTouchEvents(true); LinearLayoutManager layoutManager = new LinearLayoutManager(context); layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); @@ -3873,7 +4172,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not stickersPanelArrow = new ImageView(context); stickersPanelArrow.setImageResource(R.drawable.stickers_back_arrow); stickersPanelArrow.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_stickersHintPanel), PorterDuff.Mode.MULTIPLY)); - stickersPanel.addView(stickersPanelArrow, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT, 53, 0, 0, 0)); + stickersPanel.addView(stickersPanelArrow, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT, 53, 0, 53, 0)); searchContainer = new FrameLayout(context) { @Override @@ -3894,23 +4193,28 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchUpButton = new ImageView(context); searchUpButton.setScaleType(ImageView.ScaleType.CENTER); - searchUpButton.setImageResource(R.drawable.search_up); + searchUpButton.setImageResource(R.drawable.msg_go_up); searchUpButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); + searchUpButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchContainer.addView(searchUpButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 48, 0)); searchUpButton.setOnClickListener(view -> DataQuery.getInstance(currentAccount).searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, 1, searchingUserMessages)); + searchUpButton.setContentDescription(LocaleController.getString("AccDescrSearchNext", R.string.AccDescrSearchNext)); searchDownButton = new ImageView(context); searchDownButton.setScaleType(ImageView.ScaleType.CENTER); - searchDownButton.setImageResource(R.drawable.search_down); + searchDownButton.setImageResource(R.drawable.msg_go_down); searchDownButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); + searchDownButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchContainer.addView(searchDownButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 0, 0, 0, 0)); searchDownButton.setOnClickListener(view -> DataQuery.getInstance(currentAccount).searchMessagesInChat(null, dialog_id, mergeDialogId, classGuid, 2, searchingUserMessages)); + searchDownButton.setContentDescription(LocaleController.getString("AccDescrSearchPrev", R.string.AccDescrSearchPrev)); if (currentChat != null && (!ChatObject.isChannel(currentChat) || currentChat.megagroup)) { searchUserButton = new ImageView(context); searchUserButton.setScaleType(ImageView.ScaleType.CENTER); - searchUserButton.setImageResource(R.drawable.usersearch); + searchUserButton.setImageResource(R.drawable.msg_usersearch); searchUserButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); + searchUserButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchContainer.addView(searchUserButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP, 48, 0, 0, 0)); searchUserButton.setOnClickListener(view -> { mentionLayoutManager.setReverseLayout(true); @@ -3924,12 +4228,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not AndroidUtilities.showKeyboard(searchItem.getSearchField()); searchItem.clearSearchText(); }); + searchUserButton.setContentDescription(LocaleController.getString("AccDescrSearchByUser", R.string.AccDescrSearchByUser)); } searchCalendarButton = new ImageView(context); searchCalendarButton.setScaleType(ImageView.ScaleType.CENTER); - searchCalendarButton.setImageResource(R.drawable.search_calendar); + searchCalendarButton.setImageResource(R.drawable.msg_calendar); searchCalendarButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_searchPanelIcons), PorterDuff.Mode.MULTIPLY)); + searchCalendarButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchContainer.addView(searchCalendarButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP)); searchCalendarButton.setOnClickListener(view -> { if (getParentActivity() == null) { @@ -3973,6 +4279,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not FileLog.e(e); } }); + searchCalendarButton.setContentDescription(LocaleController.getString("JumpToDate", R.string.JumpToDate)); searchCountText = new SimpleTextView(context); searchCountText.setTextColor(Theme.getColor(Theme.key_chat_searchPanelText)); @@ -4060,11 +4367,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not toggleMute(true); } } else { - AlertsCreator.createClearOrDeleteDialogAlert(ChatActivity.this, false, currentChat, currentUser, currentEncryptedChat != null, () -> { + AlertsCreator.createClearOrDeleteDialogAlert(ChatActivity.this, false, currentChat, currentUser, currentEncryptedChat != null, (param) -> { NotificationCenter.getInstance(currentAccount).removeObserver(ChatActivity.this, NotificationCenter.closeChats); NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.needDeleteDialog, dialog_id, currentUser, currentChat); finishFragment(); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.needDeleteDialog, dialog_id, currentUser, currentChat, param); }); } } @@ -4085,10 +4392,58 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not 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); + } + 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)); + forwardButton.setGravity(Gravity.CENTER_VERTICAL); + forwardButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + forwardButton.setPadding(AndroidUtilities.dp(21), 0, AndroidUtilities.dp(21), 0); + forwardButton.setCompoundDrawablePadding(AndroidUtilities.dp(6)); + 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.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon), PorterDuff.Mode.MULTIPLY)); + forwardButton.setCompoundDrawablesWithIntrinsicBounds(image, null, null, null); + forwardButton.setOnClickListener(v -> openForward()); + bottomMessagesActionContainer.addView(forwardButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.RIGHT | Gravity.TOP)); + contentView.addView(searchContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM)); undoView = new UndoView(context); - contentView.addView(undoView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT)); + contentView.addView(undoView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT, 8, 0, 8, 8)); chatAdapter.updateRows(); if (loading && messages.isEmpty()) { @@ -4228,6 +4583,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + private void openForward() { + Bundle args = new Bundle(); + args.putBoolean("onlySelect", true); + args.putInt("dialogsType", 3); + DialogsActivity fragment = new DialogsActivity(args); + fragment.setDelegate(ChatActivity.this); + presentFragment(fragment); + } + private void showBottomOverlayProgress(boolean show, boolean animated) { if (show && bottomOverlayProgress.getTag() != null || !show && bottomOverlayProgress.getTag() == null) { return; @@ -4242,21 +4606,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (show) { bottomOverlayProgress.setVisibility(View.VISIBLE); bottomOverlayAnimation.playTogether( - ObjectAnimator.ofFloat(bottomOverlayChatText, "scaleX", 0.1f), - ObjectAnimator.ofFloat(bottomOverlayChatText, "scaleY", 0.1f), - ObjectAnimator.ofFloat(bottomOverlayChatText, "alpha", 0.0f), - ObjectAnimator.ofFloat(bottomOverlayProgress, "scaleX", 1.0f), - ObjectAnimator.ofFloat(bottomOverlayProgress, "scaleY", 1.0f), - ObjectAnimator.ofFloat(bottomOverlayProgress, "alpha", 1.0f)); + ObjectAnimator.ofFloat(bottomOverlayChatText, View.SCALE_X, 0.1f), + ObjectAnimator.ofFloat(bottomOverlayChatText, View.SCALE_Y, 0.1f), + ObjectAnimator.ofFloat(bottomOverlayChatText, View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(bottomOverlayProgress, View.SCALE_X, 1.0f), + ObjectAnimator.ofFloat(bottomOverlayProgress, View.SCALE_Y, 1.0f), + ObjectAnimator.ofFloat(bottomOverlayProgress, View.ALPHA, 1.0f)); } else { bottomOverlayChatText.setVisibility(View.VISIBLE); bottomOverlayAnimation.playTogether( - ObjectAnimator.ofFloat(bottomOverlayProgress, "scaleX", 0.1f), - ObjectAnimator.ofFloat(bottomOverlayProgress, "scaleY", 0.1f), - ObjectAnimator.ofFloat(bottomOverlayProgress, "alpha", 0.0f), - ObjectAnimator.ofFloat(bottomOverlayChatText, "scaleX", 1.0f), - ObjectAnimator.ofFloat(bottomOverlayChatText, "scaleY", 1.0f), - ObjectAnimator.ofFloat(bottomOverlayChatText, "alpha", 1.0f)); + ObjectAnimator.ofFloat(bottomOverlayProgress, View.SCALE_X, 0.1f), + ObjectAnimator.ofFloat(bottomOverlayProgress, View.SCALE_Y, 0.1f), + ObjectAnimator.ofFloat(bottomOverlayProgress, View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(bottomOverlayChatText, View.SCALE_X, 1.0f), + ObjectAnimator.ofFloat(bottomOverlayChatText, View.SCALE_Y, 1.0f), + ObjectAnimator.ofFloat(bottomOverlayChatText, View.ALPHA, 1.0f)); } bottomOverlayAnimation.addListener(new AnimatorListenerAdapter() { @@ -4301,7 +4665,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not params.put("bot_name", mentionsAdapter.getContextBotName()); SendMessagesHelper.prepareSendingBotContextResult(result, params, dialog_id, replyingMessageObject); chatActivityEnterView.setFieldText(""); - hideFieldPanel(); + hideFieldPanel(false); DataQuery.getInstance(currentAccount).increaseInlineRaiting(uid); } @@ -4473,7 +4837,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); SendMessagesHelper.prepareSendingMedia(photos, dialog_id, replyingMessageObject, null, button == 4, SharedConfig.groupPhotosEnabled, editingMessageObject); - hideFieldPanel(); + hideFieldPanel(false); DataQuery.getInstance(currentAccount).cleanDraft(dialog_id, true); } return; @@ -4549,12 +4913,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } stickersListView.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); stickersListView.setAdapter(stickersAdapter = new StickersAdapter(getParentActivity(), show -> { - if (show && stickersPanel.getVisibility() == View.VISIBLE || !show && stickersPanel.getVisibility() == View.GONE) { + if (show && stickersPanel.getTag() != null || !show && stickersPanel.getTag() == null) { return; } if (show) { + stickersListView.setPadding(AndroidUtilities.dp(18), stickersAdapter.isShowingKeywords() ? AndroidUtilities.dp(24) : 0, AndroidUtilities.dp(18), 0); stickersListView.scrollToPosition(0); stickersPanel.setVisibility(allowStickersPanel ? View.VISIBLE : View.INVISIBLE); + stickersPanel.setTag(1); + + boolean isRtl = chatActivityEnterView.isRtlText(); + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) stickersPanelArrow.getLayoutParams(); + layoutParams.gravity = Gravity.BOTTOM | (isRtl ? Gravity.RIGHT : Gravity.LEFT); + stickersPanelArrow.requestLayout(); + } else { + stickersPanel.setTag(null); } if (runningAnimation != null) { runningAnimation.cancel(); @@ -4563,7 +4936,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (stickersPanel.getVisibility() != View.INVISIBLE) { runningAnimation = new AnimatorSet(); runningAnimation.playTogether( - ObjectAnimator.ofFloat(stickersPanel, "alpha", show ? 0.0f : 1.0f, show ? 1.0f : 0.0f) + ObjectAnimator.ofFloat(stickersPanel, View.ALPHA, show ? 0.0f : 1.0f, show ? 1.0f : 0.0f) ); runningAnimation.setDuration(150); runningAnimation.addListener(new AnimatorListenerAdapter() { @@ -4573,10 +4946,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!show) { stickersAdapter.clearStickers(); stickersPanel.setVisibility(View.GONE); - if (StickerPreviewViewer.getInstance().isVisible()) { - StickerPreviewViewer.getInstance().close(); + if (ContentPreviewViewer.getInstance().isVisible()) { + ContentPreviewViewer.getInstance().close(); } - StickerPreviewViewer.getInstance().reset(); + ContentPreviewViewer.getInstance().reset(); } runningAnimation = null; } @@ -4595,14 +4968,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } })); stickersListView.setOnItemClickListener(stickersOnItemClickListener = (view, position) -> { - TLRPC.Document document = stickersAdapter.getItem(position); + Object item = stickersAdapter.getItem(position); Object parent = stickersAdapter.getItemParent(position); - if (document instanceof TLRPC.TL_document) { + if (item instanceof TLRPC.TL_document) { + TLRPC.TL_document document = (TLRPC.TL_document) item; SendMessagesHelper.getInstance(currentAccount).sendSticker(document, dialog_id, replyingMessageObject, parent); - hideFieldPanel(); + hideFieldPanel(false); chatActivityEnterView.addStickerToRecent(document); + chatActivityEnterView.setFieldText(""); + } else if (item instanceof String) { + String emoji = (String) item; + SpannableString string = new SpannableString(emoji); + Emoji.replaceEmoji(string, chatActivityEnterView.getEditField().getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false); + stickersAdapter.loadStikersForEmoji("", false); + chatActivityEnterView.setFieldText(string, false); } - chatActivityEnterView.setFieldText(""); }); } @@ -4621,7 +5001,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> { SendMessagesHelper.getInstance(currentAccount).sendMessage(UserConfig.getInstance(currentAccount).getCurrentUser(), dialog_id, messageObject, null, null); moveScrollToLastMessage(); - hideFieldPanel(); + hideFieldPanel(false); }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); @@ -4630,7 +5010,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private void hideVoiceHint() { voiceHintAnimation = new AnimatorSet(); voiceHintAnimation.playTogether( - ObjectAnimator.ofFloat(voiceHintTextView, "alpha", 0.0f) + ObjectAnimator.ofFloat(voiceHintTextView, View.ALPHA, 0.0f) ); voiceHintAnimation.addListener(new AnimatorListenerAdapter() { @Override @@ -4706,7 +5086,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not voiceHintTextView.setVisibility(View.VISIBLE); voiceHintAnimation = new AnimatorSet(); voiceHintAnimation.playTogether( - ObjectAnimator.ofFloat(voiceHintTextView, "alpha", 1.0f) + ObjectAnimator.ofFloat(voiceHintTextView, View.ALPHA, 1.0f) ); voiceHintAnimation.addListener(new AnimatorListenerAdapter() { @Override @@ -4765,7 +5145,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mediaBanTooltip.setVisibility(View.VISIBLE); AnimatorSet AnimatorSet = new AnimatorSet(); AnimatorSet.playTogether( - ObjectAnimator.ofFloat(mediaBanTooltip, "alpha", 0.0f, 1.0f) + ObjectAnimator.ofFloat(mediaBanTooltip, View.ALPHA, 0.0f, 1.0f) ); AnimatorSet.addListener(new AnimatorListenerAdapter() { @Override @@ -4776,7 +5156,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } AnimatorSet AnimatorSet = new AnimatorSet(); AnimatorSet.playTogether( - ObjectAnimator.ofFloat(mediaBanTooltip, "alpha", 0.0f) + ObjectAnimator.ofFloat(mediaBanTooltip, View.ALPHA, 0.0f) ); AnimatorSet.addListener(new AnimatorListenerAdapter() { @Override @@ -4806,7 +5186,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (index == -1) { return; } - noSoundHintView = new NoSoundHintView(getParentActivity()); + noSoundHintView = new HintView(getParentActivity(), 0); frameLayout.addView(noSoundHintView, index + 1, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 19, 0, 19, 0)); noSoundHintView.setAlpha(0.0f); noSoundHintView.setVisibility(View.INVISIBLE); @@ -4828,13 +5208,32 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (animation == null || animation.getCurrentProgressMs() < 3000) { continue; } - if (noSoundHintView.showForMessageCell(messageCell)) { + if (noSoundHintView.showForMessageCell(messageCell, true)) { SharedConfig.setNoSoundHintShowed(true); break; } } } + private void showForwardHint(ChatMessageCell cell) { + if (scrollingChatListView || chatListView == null || getParentActivity() == null || fragmentView == null) { + return; + } + + if (forwardHintView == null) { + SizeNotifierFrameLayout frameLayout = (SizeNotifierFrameLayout) fragmentView; + int index = frameLayout.indexOfChild(chatActivityEnterView); + if (index == -1) { + return; + } + forwardHintView = new HintView(getParentActivity(), 1); + frameLayout.addView(forwardHintView, index + 1, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 19, 0, 19, 0)); + forwardHintView.setAlpha(0.0f); + forwardHintView.setVisibility(View.INVISIBLE); + } + forwardHintView.showForMessageCell(cell, true); + } + private void showGifHint() { SharedPreferences preferences = MessagesController.getGlobalMainSettings(); if (preferences.getBoolean("gifhint", false)) { @@ -4872,8 +5271,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not AnimatorSet AnimatorSet = new AnimatorSet(); AnimatorSet.playTogether( - ObjectAnimator.ofFloat(gifHintTextView, "alpha", 0.0f, 1.0f), - ObjectAnimator.ofFloat(emojiButtonRed, "alpha", 0.0f, 1.0f) + ObjectAnimator.ofFloat(gifHintTextView, View.ALPHA, 0.0f, 1.0f), + ObjectAnimator.ofFloat(emojiButtonRed, View.ALPHA, 0.0f, 1.0f) ); AnimatorSet.addListener(new AnimatorListenerAdapter() { @Override @@ -4884,7 +5283,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } AnimatorSet AnimatorSet = new AnimatorSet(); AnimatorSet.playTogether( - ObjectAnimator.ofFloat(gifHintTextView, "alpha", 0.0f) + ObjectAnimator.ofFloat(gifHintTextView, View.ALPHA, 0.0f) ); AnimatorSet.addListener(new AnimatorListenerAdapter() { @Override @@ -4927,7 +5326,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mentionContainer.setTag(1); mentionListAnimation = new AnimatorSet(); mentionListAnimation.playTogether( - ObjectAnimator.ofFloat(mentionContainer, "alpha", 0.0f) + ObjectAnimator.ofFloat(mentionContainer, View.ALPHA, 0.0f) ); mentionListAnimation.addListener(new AnimatorListenerAdapter() { @Override @@ -4935,6 +5334,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { mentionContainer.setVisibility(View.INVISIBLE); mentionListAnimation = null; + updateMessageListAccessibilityVisibility(); } } @@ -4955,9 +5355,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } mentionContainer.setTag(null); mentionContainer.setVisibility(View.VISIBLE); + updateMessageListAccessibilityVisibility(); mentionListAnimation = new AnimatorSet(); mentionListAnimation.playTogether( - ObjectAnimator.ofFloat(mentionContainer, "alpha", 0.0f, 1.0f) + ObjectAnimator.ofFloat(mentionContainer, View.ALPHA, 0.0f, 1.0f) ); mentionListAnimation.addListener(new AnimatorListenerAdapter() { @Override @@ -4981,16 +5382,27 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - private void checkAutoDownloadMessages() { + private void checkAutoDownloadMessages(boolean scrollUp) { if (chatListView == null) { return; } int count = chatListView.getChildCount(); + int firstMessagePosition = -1; + int lastMessagePosition = -1; for (int a = 0; a < count; a++) { View child = chatListView.getChildAt(a); if (!(child instanceof ChatMessageCell)) { continue; } + RecyclerListView.ViewHolder holder = chatListView.findContainingViewHolder(child); + if (holder != null) { + int p = holder.getAdapterPosition(); + if (firstMessagePosition == -1) { + firstMessagePosition = p; + } + lastMessagePosition = p; + } + ChatMessageCell cell = (ChatMessageCell) child; MessageObject object = cell.getMessageObject(); if (object == null || object.mediaExists || !object.isSent()) { @@ -5013,16 +5425,99 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } + if (firstMessagePosition != -1) { + int lastPosition; + if (scrollUp) { + firstMessagePosition = lastPosition = lastMessagePosition; + if (firstMessagePosition + 10 >= chatAdapter.messagesEndRow) { + firstMessagePosition = chatAdapter.messagesEndRow; + } else { + firstMessagePosition = firstMessagePosition + 10; + } + for (int a = lastPosition, N = messages.size(); a < firstMessagePosition; a++) { + int n = a - chatAdapter.messagesStartRow; + if (n < 0 || n >= N) { + continue; + } + checkAutoDownloadMessage(messages.get(n)); + } + } else { + if (firstMessagePosition - 20 <= chatAdapter.messagesStartRow) { + lastPosition = chatAdapter.messagesStartRow; + } else { + lastPosition = firstMessagePosition - 20; + } + for (int a = firstMessagePosition - 1, N = messages.size(); a >= lastPosition; a--) { + int n = a - chatAdapter.messagesStartRow; + if (n < 0 || n >= N) { + continue; + } + checkAutoDownloadMessage(messages.get(n)); + } + } + } showNoSoundHint(); } + private void checkAutoDownloadMessage(MessageObject object) { + if (object.mediaExists) { + return; + } + TLRPC.Message message = object.messageOwner; + int canDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(message); + if (canDownload == 0) { + return; + } + TLRPC.Document document = object.getDocument(); + TLRPC.PhotoSize photo = document == null ? FileLoader.getClosestPhotoSizeWithSize(object.photoThumbs, AndroidUtilities.getPhotoSize()) : null; + if (document == null && photo == null) { + return; + } + if (canDownload == 2 || canDownload == 1 && object.isVideo()) { + if (document != null && currentEncryptedChat == null && !object.shouldEncryptPhotoOrVideo() && object.canStreamVideo()) { + FileLoader.getInstance(currentAccount).loadFile(document, object, 0, 10); + } + } else { + if (document != null) { + FileLoader.getInstance(currentAccount).loadFile(document, object, 0, MessageObject.isVideoDocument(document) && object.shouldEncryptPhotoOrVideo() ? 2 : 0); + } else { + FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForObject(photo, object.photoThumbsObject), object, null, 0, object.shouldEncryptPhotoOrVideo() ? 2 : 0); + } + } + } + + private void showFloatingDateView(boolean scroll) { + if (floatingDateView.getTag() == null) { + if (floatingDateAnimation != null) { + floatingDateAnimation.cancel(); + } + floatingDateView.setTag(1); + floatingDateAnimation = new AnimatorSet(); + floatingDateAnimation.setDuration(150); + floatingDateAnimation.playTogether(ObjectAnimator.ofFloat(floatingDateView, View.ALPHA, 1.0f)); + floatingDateAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (animation.equals(floatingDateAnimation)) { + floatingDateAnimation = null; + } + } + }); + floatingDateAnimation.start(); + } + if (!scroll) { + updateMessagesVisiblePart(false); + hideDateDelay = 1000; + } + } + private void hideFloatingDateView(boolean animated) { if (floatingDateView.getTag() != null && !currentFloatingDateOnScreen && (!scrollingFloatingDate || currentFloatingTopIsNotMessage)) { floatingDateView.setTag(null); if (animated) { floatingDateAnimation = new AnimatorSet(); floatingDateAnimation.setDuration(150); - floatingDateAnimation.playTogether(ObjectAnimator.ofFloat(floatingDateView, "alpha", 0.0f)); + floatingDateAnimation.playTogether(ObjectAnimator.ofFloat(floatingDateView, View.ALPHA, 0.0f)); floatingDateAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -5031,7 +5526,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } }); - floatingDateAnimation.setStartDelay(500); + floatingDateAnimation.setStartDelay(hideDateDelay); floatingDateAnimation.start(); } else { if (floatingDateAnimation != null) { @@ -5040,6 +5535,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } floatingDateView.setAlpha(0.0f); } + hideDateDelay = 500; } } @@ -5146,7 +5642,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); SendMessagesHelper.prepareSendingMedia(photos, dialog_id, replyingMessageObject, null, false, SharedConfig.groupPhotosEnabled, editingMessageObject); - hideFieldPanel(); + hideFieldPanel(false); DataQuery.getInstance(currentAccount).cleanDraft(dialog_id, true); } @@ -5222,7 +5718,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not activity.finishFragment(); fillEditingMediaWithCaption(null, null); SendMessagesHelper.prepareSendingDocuments(files, files, null, null, null, dialog_id, replyingMessageObject, null, editingMessageObject); - hideFieldPanel(); + hideFieldPanel(false); DataQuery.getInstance(currentAccount).cleanDraft(dialog_id, true); } @@ -5247,7 +5743,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not parentFragment.removeSelfFromStack(); fillEditingMediaWithCaption(null, null); SendMessagesHelper.prepareSendingAudioDocuments(audios, dialog_id, replyingMessageObject, editingMessageObject); - hideFieldPanel(); + hideFieldPanel(false); DataQuery.getInstance(currentAccount).cleanDraft(dialog_id, true); }); presentFragment(fragment); @@ -5263,7 +5759,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not fragment.setDelegate(audios -> { fillEditingMediaWithCaption(null, null); SendMessagesHelper.prepareSendingAudioDocuments(audios, dialog_id, replyingMessageObject, editingMessageObject); - hideFieldPanel(); + hideFieldPanel(false); DataQuery.getInstance(currentAccount).cleanDraft(dialog_id, true); }); presentFragment(fragment); @@ -5277,7 +5773,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not PhonebookSelectActivity activity = new PhonebookSelectActivity(); activity.setDelegate(user -> { SendMessagesHelper.getInstance(currentAccount).sendMessage(user, dialog_id, replyingMessageObject, null, null); - hideFieldPanel(); + hideFieldPanel(false); DataQuery.getInstance(currentAccount).cleanDraft(dialog_id, true); }); presentFragment(activity); @@ -5288,7 +5784,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not PollCreateActivity pollCreateActivity = new PollCreateActivity(); pollCreateActivity.setDelegate(poll -> { SendMessagesHelper.getInstance(currentAccount).sendMessage(poll, dialog_id, replyingMessageObject, null, null); - hideFieldPanel(); + hideFieldPanel(false); DataQuery.getInstance(currentAccount).cleanDraft(dialog_id, true); }); presentFragment(pollCreateActivity); @@ -5476,38 +5972,38 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (preferences.getInt("answered_" + dialog_id, 0) != botButtons.getId() && (replyingMessageObject == null || chatActivityEnterView.getFieldText() == null)) { botReplyButtons = botButtons; chatActivityEnterView.setButtons(botButtons); - showFieldPanelForReply(true, botButtons); + showFieldPanelForReply(botButtons); } } else { if (replyingMessageObject != null && botReplyButtons == replyingMessageObject) { botReplyButtons = null; - hideFieldPanel(); + hideFieldPanel(true); } chatActivityEnterView.setButtons(botButtons); } } - public void hideFieldPanel() { - showFieldPanel(false, null, null, null, null, false); + public void hideFieldPanel(boolean animated) { + showFieldPanel(false, null, null, null, null, false, animated); } public void showFieldPanelForWebPage(boolean show, TLRPC.WebPage webPage, boolean cancel) { - showFieldPanel(show, null, null, null, webPage, cancel); + showFieldPanel(show, null, null, null, webPage, cancel, true); } public void showFieldPanelForForward(boolean show, ArrayList messageObjectsToForward) { - showFieldPanel(show, null, null, messageObjectsToForward, null, false); + showFieldPanel(show, null, null, messageObjectsToForward, null, false, true); } - public void showFieldPanelForReply(boolean show, MessageObject messageObjectToReply) { - showFieldPanel(show, messageObjectToReply, null, null, null, false); + public void showFieldPanelForReply(MessageObject messageObjectToReply) { + showFieldPanel(true, messageObjectToReply, null, null, null, false, true); } public void showFieldPanelForEdit(boolean show, MessageObject messageObjectToEdit) { - showFieldPanel(show, null, messageObjectToEdit, null, null, false); + showFieldPanel(show, null, messageObjectToEdit, null, null, false, true); } - public void showFieldPanel(boolean show, MessageObject messageObjectToReply, MessageObject messageObjectToEdit, ArrayList messageObjectsToForward, TLRPC.WebPage webPage, boolean cancel) { + public void showFieldPanel(boolean show, MessageObject messageObjectToReply, MessageObject messageObjectToEdit, ArrayList messageObjectsToForward, TLRPC.WebPage webPage, boolean cancel, boolean animated) { if (chatActivityEnterView == null) { return; } @@ -5515,6 +6011,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (messageObjectToReply == null && messageObjectsToForward == null && messageObjectToEdit == null && webPage == null) { return; } + if (noSoundHintView != null) { + noSoundHintView.hide(); + } + if (forwardHintView != null) { + forwardHintView.hide(); + } if (searchItem != null && actionBar.isSearchFieldVisible()) { actionBar.closeSearchField(false); chatActivityEnterView.setFieldFocused(); @@ -5542,6 +6044,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } chatActivityEnterView.setForceShowSendButton(false, false); replyIconImageView.setImageResource(R.drawable.group_edit); + replyIconImageView.setContentDescription(LocaleController.getString("AccDescrEditing", R.string.AccDescrEditing)); + replyCloseImageView.setContentDescription(LocaleController.getString("AccDescrCancelEdit", R.string.AccDescrCancelEdit)); if (messageObjectToEdit.isMediaEmpty()) { replyNameTextView.setText(LocaleController.getString("EditMessage", R.string.EditMessage)); } else { @@ -5583,6 +6087,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } replyIconImageView.setImageResource(R.drawable.msg_panel_reply); replyNameTextView.setText(name); + replyIconImageView.setContentDescription(LocaleController.getString("AccDescrReplying", R.string.AccDescrReplying)); + replyCloseImageView.setContentDescription(LocaleController.getString("AccDescrCancelReply", R.string.AccDescrCancelReply)); if (messageObjectToReply.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { replyObjectTextView.setText(Emoji.replaceEmoji(messageObjectToReply.messageOwner.media.game.title, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false)); @@ -5609,6 +6115,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.setForceShowSendButton(true, false); ArrayList uids = new ArrayList<>(); replyIconImageView.setImageResource(R.drawable.msg_panel_forward); + replyIconImageView.setContentDescription(LocaleController.getString("AccDescrForwarding", R.string.AccDescrForwarding)); + replyCloseImageView.setContentDescription(LocaleController.getString("AccDescrCancelForward", R.string.AccDescrCancelForward)); MessageObject object = messageObjectsToForward.get(0); if (object.isFromUser()) { uids.add(object.messageOwner.from_id); @@ -5730,7 +6238,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } else { - replyIconImageView.setImageResource(R.drawable.msg_panel_link); + replyIconImageView.setImageResource(R.drawable.msg_link); if (webPage instanceof TLRPC.TL_webPagePending) { replyNameTextView.setText(LocaleController.getString("GettingLinkInfo", R.string.GettingLinkInfo)); replyObjectTextView.setText(pendingLinkSearchString); @@ -5765,16 +6273,37 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not FrameLayout.LayoutParams layoutParams1 = (FrameLayout.LayoutParams) replyNameTextView.getLayoutParams(); FrameLayout.LayoutParams layoutParams2 = (FrameLayout.LayoutParams) replyObjectTextView.getLayoutParams(); + + int cacheType = 1; + int size = 0; TLRPC.PhotoSize photoSize = null; + TLRPC.PhotoSize thumbPhotoSize = null; + TLObject photoSizeObject = null; if (thumbMediaMessageObject != null) { photoSize = FileLoader.getClosestPhotoSizeWithSize(thumbMediaMessageObject.photoThumbs2, 320); + thumbPhotoSize = FileLoader.getClosestPhotoSizeWithSize(thumbMediaMessageObject.photoThumbs2, AndroidUtilities.dp(40)); + photoSizeObject = thumbMediaMessageObject.photoThumbsObject2; if (photoSize == null) { - photoSize = FileLoader.getClosestPhotoSizeWithSize(thumbMediaMessageObject.photoThumbs, 320); + if (thumbMediaMessageObject.mediaExists) { + photoSize = FileLoader.getClosestPhotoSizeWithSize(thumbMediaMessageObject.photoThumbs, AndroidUtilities.getPhotoSize()); + if (photoSize != null) { + size = photoSize.size; + } + cacheType = 0; + } else { + photoSize = FileLoader.getClosestPhotoSizeWithSize(thumbMediaMessageObject.photoThumbs, 320); + } + thumbPhotoSize = FileLoader.getClosestPhotoSizeWithSize(thumbMediaMessageObject.photoThumbs, AndroidUtilities.dp(40)); + photoSizeObject = thumbMediaMessageObject.photoThumbsObject; } } + if (photoSize == thumbPhotoSize) { + thumbPhotoSize = null; + } if (photoSize == null || photoSize instanceof TLRPC.TL_photoSizeEmpty || photoSize.location instanceof TLRPC.TL_fileLocationUnavailable || thumbMediaMessageObject.type == 13 || thumbMediaMessageObject != null && thumbMediaMessageObject.isSecretMedia()) { replyImageView.setImageBitmap(null); replyImageLocation = null; + replyImageLocationObject = null; replyImageView.setVisibility(View.INVISIBLE); layoutParams1.leftMargin = layoutParams2.leftMargin = AndroidUtilities.dp(52); } else { @@ -5783,14 +6312,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { replyImageView.setRoundRadius(0); } + replyImageSize = size; + replyImageCacheType = cacheType; replyImageLocation = photoSize; - replyImageView.setImage(replyImageLocation, "50_50", (Drawable) null, thumbMediaMessageObject); + replyImageThumbLocation = thumbPhotoSize; + replyImageLocationObject = photoSizeObject; + replyImageView.setImage(ImageLocation.getForObject(replyImageLocation, photoSizeObject), "50_50", ImageLocation.getForObject(thumbPhotoSize, photoSizeObject), "50_50_b", null, size, cacheType, thumbMediaMessageObject); replyImageView.setVisibility(View.VISIBLE); layoutParams1.leftMargin = layoutParams2.leftMargin = AndroidUtilities.dp(96); } replyNameTextView.setLayoutParams(layoutParams1); replyObjectTextView.setLayoutParams(layoutParams2); - chatActivityEnterView.showTopView(false, openKeyboard); + chatActivityEnterView.showTopView(true, openKeyboard); } else { if (replyingMessageObject == null && forwardingMessages == null && foundWebPage == null && editingMessageObject == null) { return; @@ -5803,7 +6336,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not foundWebPage = null; chatActivityEnterView.setWebPage(null, !cancel); if (webPage != null && (replyingMessageObject != null || forwardingMessages != null || editingMessageObject != null)) { - showFieldPanel(true, replyingMessageObject, editingMessageObject, forwardingMessages, null, false); + showFieldPanel(true, replyingMessageObject, editingMessageObject, forwardingMessages, null, false, true); return; } } @@ -5811,13 +6344,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not forwardMessages(forwardingMessages, false); } chatActivityEnterView.setForceShowSendButton(false, false); - chatActivityEnterView.hideTopView(false); + chatActivityEnterView.hideTopView(animated); chatActivityEnterView.setReplyingMessageObject(null); chatActivityEnterView.setEditingMessageObject(null, false); replyingMessageObject = null; editingMessageObject = null; forwardingMessages = null; replyImageLocation = null; + replyImageLocationObject = null; } } @@ -5881,7 +6415,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (forwardEndReached[0] && first_unread_id == 0 && startLoadFromMessageId == 0) { if (pagedown && chatLayoutManager.findFirstCompletelyVisibleItemPosition() == 0) { showPagedownButton(false, true); - highlightMessageId = Integer.MAX_VALUE; + removeSelectedMessageHighlight(); updateVisibleRows(); } else { chatLayoutManager.scrollToPositionWithOffset(0, 0); @@ -5893,13 +6427,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - public void updateTextureViewPosition() { + public void updateTextureViewPosition(boolean needScroll) { if (fragmentView == null || paused) { return; } boolean foundTextureViewMessage = false; int count = chatListView.getChildCount(); - int additionalTop = chatActivityEnterView.isTopViewVisible() ? AndroidUtilities.dp(48) : 0; for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); if (view instanceof ChatMessageCell) { @@ -5908,7 +6441,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (videoPlayerContainer != null && (messageObject.isRoundVideo() || messageObject.isVideo()) && MediaController.getInstance().isPlayingMessage(messageObject)) { ImageReceiver imageReceiver = messageCell.getPhotoImage(); videoPlayerContainer.setTranslationX(imageReceiver.getImageX() + messageCell.getX()); - videoPlayerContainer.setTranslationY(fragmentView.getPaddingTop() + messageCell.getTop() + imageReceiver.getImageY() - additionalTop + (inPreviewMode ? AndroidUtilities.statusBarHeight : 0)); + videoPlayerContainer.setTranslationY(fragmentView.getPaddingTop() + messageCell.getTop() + imageReceiver.getImageY() - chatListViewClipTop + chatListView.getTranslationY() + (inPreviewMode ? AndroidUtilities.statusBarHeight : 0)); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) videoPlayerContainer.getLayoutParams(); if (messageObject.isRoundVideo()) { videoPlayerContainer.setTag(R.id.parent_tag, null); @@ -5933,7 +6466,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } - if (videoPlayerContainer != null) { + if (needScroll && videoPlayerContainer != null) { MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); if (messageObject != null && messageObject.eventId == 0) { if (!foundTextureViewMessage) { @@ -5967,7 +6500,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } int count = chatListView.getChildCount(); - int additionalTop = chatActivityEnterView.isTopViewVisible() ? AndroidUtilities.dp(48) : 0; int height = chatListView.getMeasuredHeight(); int minPositionHolder = Integer.MAX_VALUE; int minPositionDateHolder = Integer.MAX_VALUE; @@ -6003,7 +6535,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not foundTextureViewMessage = false; } else { videoPlayerContainer.setTranslationX(imageReceiver.getImageX() + messageCell.getX()); - videoPlayerContainer.setTranslationY(fragmentView.getPaddingTop() + top + imageReceiver.getImageY() - additionalTop + (inPreviewMode ? AndroidUtilities.statusBarHeight : 0)); + videoPlayerContainer.setTranslationY(fragmentView.getPaddingTop() + top + imageReceiver.getImageY() - chatListViewClipTop + chatListView.getTranslationY() + (inPreviewMode ? AndroidUtilities.statusBarHeight : 0)); fragmentView.invalidate(); videoPlayerContainer.invalidate(); foundTextureViewMessage = true; @@ -6027,7 +6559,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pollsToCheck.add(messageObject); } } - if (view.getBottom() <= chatListView.getPaddingTop()) { + if (view.getBottom() <= chatListView.getPaddingTop() + AndroidUtilities.dp(1) + chatListViewClipTop) { continue; } int position = view.getBottom(); @@ -6079,7 +6611,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not currentFloatingDateOnScreen = false; currentFloatingTopIsNotMessage = !(minChild instanceof ChatMessageCell || minChild instanceof ChatActionCell); if (minDateChild != null) { - if (minDateChild.getTop() > chatListView.getPaddingTop() || currentFloatingTopIsNotMessage) { + if (minDateChild.getTop() - chatListViewClipTop > chatListView.getPaddingTop() || currentFloatingTopIsNotMessage) { if (minDateChild.getAlpha() != 1.0f) { minDateChild.setAlpha(1.0f); } @@ -6100,7 +6632,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } currentFloatingDateOnScreen = true; } - int offset = minDateChild.getBottom() - chatListView.getPaddingTop(); + float offset = minDateChild.getBottom() - chatListView.getPaddingTop() - chatListViewClipTop; if (offset > floatingDateView.getMeasuredHeight() && offset < floatingDateView.getMeasuredHeight() * 2) { floatingDateView.setTranslationY(-floatingDateView.getMeasuredHeight() * 2 + offset); } else { @@ -6197,7 +6729,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not flags = 1; MessagesStorage.getInstance(currentAccount).setDialogFlags(dialog_id, flags); editor.commit(); - TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(dialog_id); + TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(dialog_id); if (dialog != null) { dialog.notify_settings = new TLRPC.TL_peerNotifySettings(); dialog.notify_settings.mute_until = Integer.MAX_VALUE; @@ -6213,7 +6745,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not editor.putInt("notify2_" + dialog_id, 0); MessagesStorage.getInstance(currentAccount).setDialogFlags(dialog_id, 0); editor.commit(); - TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(dialog_id); + TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(dialog_id); if (dialog != null) { dialog.notify_settings = new TLRPC.TL_peerNotifySettings(); } @@ -6258,6 +6790,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return Math.max(0, offset == Integer.MAX_VALUE ? (chatListView.getMeasuredHeight() - object.getApproximateHeight()) / 2 : offset); } + private void startMessageUnselect() { + if (unselectRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(unselectRunnable); + } + unselectRunnable = () -> { + highlightMessageId = Integer.MAX_VALUE; + updateVisibleRows(); + unselectRunnable = null; + }; + AndroidUtilities.runOnUIThread(unselectRunnable, 1000); + } + + private void removeSelectedMessageHighlight() { + if (unselectRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(unselectRunnable); + unselectRunnable = null; + } + highlightMessageId = Integer.MAX_VALUE; + } + public void scrollToMessageId(int id, int fromMessageId, boolean select, int loadIndex, boolean smooth) { wasManualScroll = true; MessageObject object = messagesDict[loadIndex].get(id); @@ -6265,10 +6817,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (object != null) { int index = messages.indexOf(object); if (index != -1) { + removeSelectedMessageHighlight(); if (select) { highlightMessageId = id; - } else { - highlightMessageId = Integer.MAX_VALUE; } int yOffset = getScrollOffsetForMessage(object); if (smooth) { @@ -6294,6 +6845,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject messageObject = cell.getMessageObject(); if (messageObject != null && messageObject.getId() == object.getId()) { found = true; + view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); break; } } else if (view instanceof ChatActionCell) { @@ -6301,6 +6853,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject messageObject = cell.getMessageObject(); if (messageObject != null && messageObject.getId() == object.getId()) { found = true; + view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); break; } } @@ -6328,7 +6881,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not waitingForLoad.clear(); waitingForReplyMessageLoad = true; - highlightMessageId = Integer.MAX_VALUE; + removeSelectedMessageHighlight(); scrollToMessagePosition = -10000; startLoadFromMessageId = id; if (id == createUnreadMessageAfterId) { @@ -6337,6 +6890,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not waitingForLoad.add(lastLoadIndex); MessagesController.getInstance(currentAccount).loadMessages(loadIndex == 0 ? dialog_id : mergeDialogId, AndroidUtilities.isTablet() ? 30 : 20, startLoadFromMessageId, 0, true, 0, classGuid, 3, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); //emptyViewContainer.setVisibility(View.INVISIBLE); + } else { + showFloatingDateView(false); } returnToMessageId = fromMessageId; returnToLoadIndex = loadIndex; @@ -6363,10 +6918,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pagedownButtonAnimation = new AnimatorSet(); if (mentiondownButton.getVisibility() == View.VISIBLE) { pagedownButtonAnimation.playTogether( - ObjectAnimator.ofFloat(pagedownButton, "translationY", 0), - ObjectAnimator.ofFloat(mentiondownButton, "translationY", -AndroidUtilities.dp(72))); + ObjectAnimator.ofFloat(pagedownButton, View.TRANSLATION_Y, 0), + ObjectAnimator.ofFloat(mentiondownButton, View.TRANSLATION_Y, -AndroidUtilities.dp(72))); } else { - pagedownButtonAnimation.playTogether(ObjectAnimator.ofFloat(pagedownButton, "translationY", 0)); + pagedownButtonAnimation.playTogether(ObjectAnimator.ofFloat(pagedownButton, View.TRANSLATION_Y, 0)); } pagedownButtonAnimation.setDuration(200); pagedownButtonAnimation.start(); @@ -6387,10 +6942,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pagedownButtonAnimation = new AnimatorSet(); if (mentiondownButton.getVisibility() == View.VISIBLE) { pagedownButtonAnimation.playTogether( - ObjectAnimator.ofFloat(pagedownButton, "translationY", AndroidUtilities.dp(100)), - ObjectAnimator.ofFloat(mentiondownButton, "translationY", 0)); + ObjectAnimator.ofFloat(pagedownButton, View.TRANSLATION_Y, AndroidUtilities.dp(100)), + ObjectAnimator.ofFloat(mentiondownButton, View.TRANSLATION_Y, 0)); } else { - pagedownButtonAnimation.playTogether(ObjectAnimator.ofFloat(pagedownButton, "translationY", AndroidUtilities.dp(100))); + pagedownButtonAnimation.playTogether(ObjectAnimator.ofFloat(pagedownButton, View.TRANSLATION_Y, AndroidUtilities.dp(100))); } pagedownButtonAnimation.setDuration(200); pagedownButtonAnimation.addListener(new AnimatorListenerAdapter() { @@ -6408,7 +6963,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - private void showMentiondownButton(boolean show, boolean animated) { + private void showMentionDownButton(boolean show, boolean animated) { if (mentiondownButton == null) { return; } @@ -6423,12 +6978,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mentiondownButton.setTag(1); if (pagedownButton.getVisibility() == View.VISIBLE) { mentiondownButton.setTranslationY(-AndroidUtilities.dp(72)); - mentiondownButtonAnimation = ObjectAnimator.ofFloat(mentiondownButton, "alpha", 0.0f, 1.0f).setDuration(200); + mentiondownButtonAnimation = ObjectAnimator.ofFloat(mentiondownButton, View.ALPHA, 0.0f, 1.0f).setDuration(200); } else { if (mentiondownButton.getTranslationY() == 0) { mentiondownButton.setTranslationY(AndroidUtilities.dp(100)); } - mentiondownButtonAnimation = ObjectAnimator.ofFloat(mentiondownButton, "translationY", 0).setDuration(200); + mentiondownButtonAnimation = ObjectAnimator.ofFloat(mentiondownButton, View.TRANSLATION_Y, 0).setDuration(200); } mentiondownButtonAnimation.start(); } else { @@ -6445,9 +7000,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (animated) { if (pagedownButton.getVisibility() == View.VISIBLE) { - mentiondownButtonAnimation = ObjectAnimator.ofFloat(mentiondownButton, "alpha", 1.0f, 0.0f).setDuration(200); + mentiondownButtonAnimation = ObjectAnimator.ofFloat(mentiondownButton, View.ALPHA, 1.0f, 0.0f).setDuration(200); } else { - mentiondownButtonAnimation = ObjectAnimator.ofFloat(mentiondownButton, "translationY", AndroidUtilities.dp(100)).setDuration(200); + mentiondownButtonAnimation = ObjectAnimator.ofFloat(mentiondownButton, View.TRANSLATION_Y, AndroidUtilities.dp(100)).setDuration(200); } mentiondownButtonAnimation.addListener(new AnimatorListenerAdapter() { @Override @@ -6484,10 +7039,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } mentionContainer.setVisibility(View.GONE); mentionContainer.setTag(null); + updateMessageListAccessibilityVisibility(); hideKeyboard = true; + if (stickersAdapter != null) { + stickersAdapter.hide(); + } } else { if (currentEncryptedChat == null || bigEmptyView == null) { bottomOverlay.setVisibility(View.INVISIBLE); + if (stickersAdapter != null && chatActivityEnterView != null && chatActivityEnterView.hasText()) { + stickersAdapter.loadStikersForEmoji(chatActivityEnterView.getFieldText(), false); + } return; } if (currentEncryptedChat instanceof TLRPC.TL_encryptedChatRequested) { @@ -6530,7 +7092,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mentionsAdapter.onRequestPermissionsResultFragment(requestCode, permissions, grantResults); } if (requestCode == 17 && chatAttachAlert != null) { - chatAttachAlert.checkCamera(false); + chatAttachAlert.checkCamera(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED); } else if (requestCode == 21) { if (getParentActivity() == null) { return; @@ -6609,7 +7171,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { if (messageObject.type == 6) { return -1; - } else if (messageObject.type == 10 || messageObject.type == 11 || messageObject.type == 16) { + } else if (messageObject.type == 10 || messageObject.type == 11) { if (messageObject.getId() == 0) { return -1; } @@ -6734,6 +7296,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void addToSelectedMessages(MessageObject messageObject, boolean outside, boolean last) { + int prevCantForwardCount = cantForwardMessagesCount; if (messageObject != null) { int index = messageObject.getDialogId() == dialog_id ? 0 : 1; if (outside && messageObject.getGroupId() != 0) { @@ -6770,15 +7333,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (messageObject.isSticker()) { selectedMessagesCanStarIds[index].remove(messageObject.getId()); } - if (messageObject.canEditMessage(currentChat) && messageObject.getGroupId() != 0) { - MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(messageObject.getGroupId()); - if (groupedMessages != null && groupedMessages.messages.size() > 1) { - canEditMessagesCount--; - } + if (messageObject.canEditMessage(currentChat)) { + canEditMessagesCount--; } if (!messageObject.canDeleteMessage(currentChat)) { cantDeleteMessagesCount--; } + if (!messageObject.canForwardMessage()) { + cantForwardMessagesCount--; + } } else { if (selectedMessagesIds[0].size() + selectedMessagesIds[1].size() >= 100) { return; @@ -6790,28 +7353,63 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (messageObject.isSticker()) { selectedMessagesCanStarIds[index].put(messageObject.getId(), messageObject); } - if (messageObject.canEditMessage(currentChat) && messageObject.getGroupId() != 0) { - MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(messageObject.getGroupId()); - if (groupedMessages != null && groupedMessages.messages.size() > 1) { - canEditMessagesCount++; - } + if (messageObject.canEditMessage(currentChat)) { + canEditMessagesCount++; } if (!messageObject.canDeleteMessage(currentChat)) { cantDeleteMessagesCount++; } + if (!messageObject.canForwardMessage()) { + cantForwardMessagesCount++; + } } } + if (forwardButtonAnimation != null) { + forwardButtonAnimation.cancel(); + forwardButtonAnimation = null; + } if (last && actionBar.isActionModeShowed()) { int selectedCount = selectedMessagesIds[0].size() + selectedMessagesIds[1].size(); if (selectedCount == 0) { - actionBar.hideActionMode(); + hideActionMode(); updatePinnedMessageView(true); - startReplyOnTextChange = false; } else { ActionBarMenuItem copyItem = actionBar.createActionMode().getItem(copy); ActionBarMenuItem starItem = actionBar.createActionMode().getItem(star); ActionBarMenuItem editItem = actionBar.createActionMode().getItem(edit); - final ActionBarMenuItem replyItem = actionBar.createActionMode().getItem(reply); + ActionBarMenuItem forwardItem = actionBar.createActionMode().getItem(forward); + + if (prevCantForwardCount == 0 && cantForwardMessagesCount != 0 || prevCantForwardCount != 0 && cantForwardMessagesCount == 0) { + forwardButtonAnimation = new AnimatorSet(); + ArrayList animators = new ArrayList<>(); + if (forwardItem != null) { + forwardItem.setEnabled(cantForwardMessagesCount == 0); + animators.add(ObjectAnimator.ofFloat(forwardItem, View.ALPHA, cantForwardMessagesCount == 0 ? 1.0f : 0.5f)); + } + if (forwardButton != null) { + forwardButton.setEnabled(cantForwardMessagesCount == 0); + animators.add(ObjectAnimator.ofFloat(forwardButton, View.ALPHA, cantForwardMessagesCount == 0 ? 1.0f : 0.5f)); + } + forwardButtonAnimation.playTogether(animators); + forwardButtonAnimation.setDuration(100); + forwardButtonAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + forwardButtonAnimation = null; + } + }); + forwardButtonAnimation.start(); + } else { + if (forwardItem != null) { + forwardItem.setEnabled(cantForwardMessagesCount == 0); + forwardItem.setAlpha(cantForwardMessagesCount == 0 ? 1.0f : 0.5f); + } + if (forwardButton != null) { + forwardButton.setEnabled(cantForwardMessagesCount == 0); + forwardButton.setAlpha(cantForwardMessagesCount == 0 ? 1.0f : 0.5f); + } + } + int copyVisible = copyItem.getVisibility(); int starVisible = starItem.getVisibility(); copyItem.setVisibility(selectedMessagesCanCopyIds[0].size() + selectedMessagesCanCopyIds[1].size() != 0 ? View.VISIBLE : View.GONE); @@ -6819,9 +7417,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int newCopyVisible = copyItem.getVisibility(); int newStarVisible = starItem.getVisibility(); actionBar.createActionMode().getItem(delete).setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); - if (editItem != null) { - editItem.setVisibility(canEditMessagesCount == 1 && selectedMessagesIds[0].size() + selectedMessagesIds[1].size() == 1 ? View.VISIBLE : View.GONE); - } hasUnfavedSelected = false; for (int a = 0; a < 2; a++) { for (int b = 0; b < selectedMessagesCanStarIds[a].size(); b++) { @@ -6835,8 +7430,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not break; } } - starItem.setIcon(hasUnfavedSelected ? R.drawable.ic_ab_fave : R.drawable.ic_ab_unfave); - if (replyItem != null) { + starItem.setIcon(hasUnfavedSelected ? R.drawable.msg_fave : R.drawable.msg_unfave); + final int newEditVisibility = canEditMessagesCount == 1 && selectedCount == 1 ? View.VISIBLE : View.GONE; + if (replyButton != null) { boolean allowChatActions = true; if (currentEncryptedChat != null && AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 46 || isBroadcast || @@ -6844,68 +7440,127 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not currentChat != null && (ChatObject.isNotInChat(currentChat) || ChatObject.isChannel(currentChat) && !ChatObject.canPost(currentChat) && !currentChat.megagroup || !ChatObject.canSendMessages(currentChat))) { allowChatActions = false; } - final int newVisibility = allowChatActions && selectedMessagesIds[0].size() + selectedMessagesIds[1].size() == 1 ? View.VISIBLE : View.GONE; - startReplyOnTextChange = newVisibility == View.VISIBLE && !chatActivityEnterView.hasText(); - if (replyItem.getVisibility() != newVisibility) { + + int newVisibility; + + if (!allowChatActions || selectedCount == 0 || selectedMessagesIds[0].size() != 0 && selectedMessagesIds[1].size() != 0) { + newVisibility = View.GONE; + } else if (selectedCount == 1) { + newVisibility = View.VISIBLE; + } else { + newVisibility = View.VISIBLE; + long lastGroupId = 0; + for (int a = 0; a < 2; a++) { + for (int b = 0, N = selectedMessagesIds[a].size(); b < N; b++) { + MessageObject message = selectedMessagesIds[a].valueAt(b); + long groupId = message.getGroupId(); + if (groupId == 0 || lastGroupId != 0 && lastGroupId != groupId) { + newVisibility = View.GONE; + break; + } + lastGroupId = groupId; + } + if (newVisibility == View.GONE) { + break; + } + } + } + + if (replyButton.getVisibility() != newVisibility) { if (replyButtonAnimation != null) { replyButtonAnimation.cancel(); } - if (copyVisible != newCopyVisible || starVisible != newStarVisible) { - if (newVisibility == View.VISIBLE) { - replyItem.setAlpha(1.0f); - replyItem.setScaleX(1.0f); - } else { - replyItem.setAlpha(0.0f); - replyItem.setScaleX(0.0f); - } - replyItem.setVisibility(newVisibility); + replyButtonAnimation = new AnimatorSet(); + if (newVisibility == View.VISIBLE) { + replyButton.setVisibility(newVisibility); + replyButtonAnimation.playTogether( + ObjectAnimator.ofFloat(replyButton, View.ALPHA, 1.0f), + ObjectAnimator.ofFloat(replyButton, View.SCALE_Y, 1.0f) + ); } else { - replyButtonAnimation = new AnimatorSet(); - replyItem.setPivotX(AndroidUtilities.dp(54)); - editItem.setPivotX(AndroidUtilities.dp(54)); - if (newVisibility == View.VISIBLE) { - replyItem.setVisibility(newVisibility); - replyButtonAnimation.playTogether( - ObjectAnimator.ofFloat(replyItem, "alpha", 1.0f), - ObjectAnimator.ofFloat(replyItem, "scaleX", 1.0f), - ObjectAnimator.ofFloat(editItem, "alpha", 1.0f), - ObjectAnimator.ofFloat(editItem, "scaleX", 1.0f) - ); - } else { - replyButtonAnimation.playTogether( - ObjectAnimator.ofFloat(replyItem, "alpha", 0.0f), - ObjectAnimator.ofFloat(replyItem, "scaleX", 0.0f), - ObjectAnimator.ofFloat(editItem, "alpha", 0.0f), - ObjectAnimator.ofFloat(editItem, "scaleX", 0.0f) - ); - } - replyButtonAnimation.setDuration(100); - replyButtonAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (replyButtonAnimation != null && replyButtonAnimation.equals(animation)) { - if (newVisibility == View.GONE) { - replyItem.setVisibility(View.GONE); - } - } - } - - @Override - public void onAnimationCancel(Animator animation) { - if (replyButtonAnimation != null && replyButtonAnimation.equals(animation)) { - replyButtonAnimation = null; - } - } - }); - replyButtonAnimation.start(); + replyButtonAnimation.playTogether( + ObjectAnimator.ofFloat(replyButton, View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(replyButton, View.SCALE_Y, 0.0f) + ); } + replyButtonAnimation.setDuration(100); + int newVisibilityFinal = newVisibility; + replyButtonAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (replyButtonAnimation != null && replyButtonAnimation.equals(animation)) { + if (newVisibilityFinal == View.GONE) { + replyButton.setVisibility(View.GONE); + } + } + } + + @Override + public void onAnimationCancel(Animator animation) { + if (replyButtonAnimation != null && replyButtonAnimation.equals(animation)) { + replyButtonAnimation = null; + } + } + }); + replyButtonAnimation.start(); + } + } + + if (editItem != null) { + if (copyVisible != newCopyVisible || starVisible != newStarVisible) { + if (newEditVisibility == View.VISIBLE) { + editItem.setAlpha(1.0f); + editItem.setScaleX(1.0f); + } else { + editItem.setAlpha(0.0f); + editItem.setScaleX(0.0f); + } + editItem.setVisibility(newEditVisibility); + } else if (editItem.getVisibility() != newEditVisibility) { + if (editButtonAnimation != null) { + editButtonAnimation.cancel(); + } + editButtonAnimation = new AnimatorSet(); + editItem.setPivotX(AndroidUtilities.dp(54)); + editItem.setPivotX(AndroidUtilities.dp(54)); + if (newEditVisibility == View.VISIBLE) { + editItem.setVisibility(newEditVisibility); + editButtonAnimation.playTogether( + ObjectAnimator.ofFloat(editItem, View.ALPHA, 1.0f), + ObjectAnimator.ofFloat(editItem, View.SCALE_X, 1.0f) + ); + } else { + editButtonAnimation.playTogether( + ObjectAnimator.ofFloat(editItem, View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(editItem, View.SCALE_X, 0.0f) + ); + } + editButtonAnimation.setDuration(100); + editButtonAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (editButtonAnimation != null && editButtonAnimation.equals(animation)) { + if (newEditVisibility == View.GONE) { + editItem.setVisibility(View.GONE); + } + } + } + + @Override + public void onAnimationCancel(Animator animation) { + if (editButtonAnimation != null && editButtonAnimation.equals(animation)) { + editButtonAnimation = null; + } + } + }); + editButtonAnimation.start(); } } } } } - private void processRowSelect(View view, boolean outside) { + private void processRowSelect(View view, boolean outside, float touchX, float touchY) { MessageObject message = null; if (view instanceof ChatMessageCell) { message = ((ChatMessageCell) view).getMessageObject(); @@ -6937,7 +7592,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } if (currentChat != null) { - avatarContainer.setTitle(currentChat.title); + avatarContainer.setTitle(currentChat.title, currentChat.scam); } else if (currentUser != null) { if (currentUser.self) { avatarContainer.setTitle(LocaleController.getString("SavedMessages", R.string.SavedMessages)); @@ -6945,12 +7600,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!TextUtils.isEmpty(currentUser.phone)) { avatarContainer.setTitle(PhoneFormat.getInstance().format("+" + currentUser.phone)); } else { - avatarContainer.setTitle(UserObject.getUserName(currentUser)); + avatarContainer.setTitle(UserObject.getUserName(currentUser), currentUser.scam); } } else { - avatarContainer.setTitle(UserObject.getUserName(currentUser)); + avatarContainer.setTitle(UserObject.getUserName(currentUser), currentUser.scam); } } + setParentActivityTitle(avatarContainer.getTitleTextView().getText()); } private void updateBotButtons() { @@ -6995,9 +7651,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not avatarContainer.setTitleIcons(currentEncryptedChat != null ? Theme.chat_lockIconDrawable : null, rightIcon); if (muteItem != null) { if (rightIcon != null) { - muteItem.setText(LocaleController.getString("UnmuteNotifications", R.string.UnmuteNotifications)); + muteItem.setTextAndIcon(LocaleController.getString("UnmuteNotifications", R.string.UnmuteNotifications), R.drawable.msg_unmute); } else { - muteItem.setText(LocaleController.getString("MuteNotifications", R.string.MuteNotifications)); + muteItem.setTextAndIcon(LocaleController.getString("MuteNotifications", R.string.MuteNotifications), R.drawable.msg_mute); } } } @@ -7048,7 +7704,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { fillEditingMediaWithCaption(caption, null); SendMessagesHelper.prepareSendingVideo(videoPath, 0, 0, 0, 0, null, dialog_id, replyingMessageObject, null, null, 0, editingMessageObject); - hideFieldPanel(); + hideFieldPanel(false); DataQuery.getInstance(currentAccount).cleanDraft(dialog_id, true); } } @@ -7106,7 +7762,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } fillEditingMediaWithCaption(null, null); SendMessagesHelper.prepareSendingDocument(tempPath, originalPath, null, null, null, dialog_id, replyingMessageObject, null, editingMessageObject); - hideFieldPanel(); + hideFieldPanel(false); } @Override @@ -7143,7 +7799,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not fillEditingMediaWithCaption(null, null); SendMessagesHelper.prepareSendingPhoto(null, uri, dialog_id, replyingMessageObject, null, null, null, null, 0, editingMessageObject); } - hideFieldPanel(); + hideFieldPanel(false); DataQuery.getInstance(currentAccount).cleanDraft(dialog_id, true); } else if (requestCode == 21) { if (data == null) { @@ -7160,7 +7816,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { showAttachmentError(); } - hideFieldPanel(); + hideFieldPanel(false); DataQuery.getInstance(currentAccount).cleanDraft(dialog_id, true); } } @@ -7204,7 +7860,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not setItemAnimationsEnabled(false); if (!openAnimationEnded) { NotificationCenter.getInstance(currentAccount).setAllowedNotificationsDutingAnimation(new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload, - NotificationCenter.closeChats, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad/*, NotificationCenter.botInfoDidLoad*/}); + NotificationCenter.closeChats, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.needDeleteDialog/*, NotificationCenter.botInfoDidLoad*/}); } int queryLoadIndex = (Integer) args[11]; int index = waitingForLoad.indexOf(queryLoadIndex); @@ -7216,6 +7872,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } ArrayList messArr = (ArrayList) args[2]; boolean createUnreadLoading = false; + boolean showDateAfter = waitingForReplyMessageLoad; if (waitingForReplyMessageLoad) { if (!createUnreadMessageAfterIdLoading) { boolean found = false; @@ -7343,7 +8000,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not DataQuery.getInstance(currentAccount).loadReplyMessagesForMessages(messArr, dialog_id); } int approximateHeightSum = 0; - if (load_type == 2 && messArr.isEmpty() && !isCache) { + if ((load_type == 2 || load_type == 1) && messArr.isEmpty() && !isCache) { forwardEndReached[0] = true; } LongSparseArray newGroups = null; @@ -7537,10 +8194,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not newRowsCount++; } } else if ((load_type == 3 || load_type == 4) && obj.getId() == startLoadFromMessageId) { + removeSelectedMessageHighlight(); if (needSelectFromMessageId) { highlightMessageId = obj.getId(); - } else { - highlightMessageId = Integer.MAX_VALUE; } scrollToMessage = obj; startLoadFromMessageId = 0; @@ -7675,7 +8331,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not yOffset = scrollToMessagePosition; } if (!messages.isEmpty()) { - if (chatAdapter.loadingUpRow != -1 && (messages.get(messages.size() - 1) == scrollToMessage || messages.get(messages.size() - 2) == scrollToMessage)) { + if (chatAdapter.loadingUpRow != -1 && !messages.isEmpty() && (messages.get(messages.size() - 1) == scrollToMessage || messages.get(messages.size() - 2) == scrollToMessage)) { chatLayoutManager.scrollToPositionWithOffset(chatAdapter.loadingUpRow, yOffset, bottom); } else { chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + messages.indexOf(scrollToMessage), yOffset, bottom); @@ -7700,7 +8356,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not moveScrollToLastMessage(); } if (loaded_mentions_count != 0) { - showMentiondownButton(true, true); + showMentionDownButton(true, true); if (mentiondownButtonCounter != null) { mentiondownButtonCounter.setVisibility(View.VISIBLE); mentiondownButtonCounter.setText(String.format("%d", newMentionsCount = loaded_mentions_count)); @@ -7814,7 +8470,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (newRowsCount == 0 && mergeDialogId != 0 && loadIndex == 0) { NotificationCenter.getInstance(currentAccount).setAllowedNotificationsDutingAnimation(new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload, - NotificationCenter.closeChats, NotificationCenter.messagesDidLoad, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad/*, NotificationCenter.botInfoDidLoad*/}); + NotificationCenter.closeChats, NotificationCenter.messagesDidLoad, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.needDeleteDialog/*, NotificationCenter.botInfoDidLoad*/}); + } + if (showDateAfter) { + showFloatingDateView(false); } checkScrollForLoad(false); setItemAnimationsEnabled(true); @@ -7835,10 +8494,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (mentionListView != null) { mentionListView.invalidateViews(); } + if (stickersListView != null) { + stickersListView.invalidateViews(); + } } else if (id == NotificationCenter.didUpdateConnectionState) { int state = ConnectionsManager.getInstance(account).getConnectionState(); if (state == ConnectionsManager.ConnectionStateConnected) { - checkAutoDownloadMessages(); + checkAutoDownloadMessages(false); } } else if (id == NotificationCenter.chatOnlineCountDidLoad) { Integer chatId = (Integer) args[0]; @@ -7919,54 +8581,54 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } - if (currentChat != null || inlineReturn != 0) { - boolean notifiedSearch = false; - for (int a = 0; a < arr.size(); a++) { - MessageObject messageObject = arr.get(a); - if (!notifiedSearch && messageObject.isOut()) { - notifiedSearch = true; - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.closeSearchByActiveAction); + + boolean notifiedSearch = false; + for (int a = 0; a < arr.size(); a++) { + MessageObject messageObject = arr.get(a); + if (!notifiedSearch && messageObject.isOut()) { + notifiedSearch = true; + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.closeSearchByActiveAction); + } + if (currentChat != null) { + if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatDeleteUser && messageObject.messageOwner.action.user_id == currentUserId || + messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatAddUser && messageObject.messageOwner.action.users.contains(currentUserId)) { + TLRPC.Chat newChat = MessagesController.getInstance(currentAccount).getChat(currentChat.id); + if (newChat != null) { + currentChat = newChat; + checkActionBarMenu(); + updateBottomOverlay(); + if (avatarContainer != null) { + avatarContainer.updateSubtitle(); + } + } } - if (currentChat != null) { - if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatDeleteUser && messageObject.messageOwner.action.user_id == currentUserId || - messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatAddUser && messageObject.messageOwner.action.users.contains(currentUserId)) { - TLRPC.Chat newChat = MessagesController.getInstance(currentAccount).getChat(currentChat.id); - if (newChat != null) { - currentChat = newChat; - checkActionBarMenu(); - updateBottomOverlay(); - if (avatarContainer != null) { - avatarContainer.updateSubtitle(); - } - } - } else if (messageObject.messageOwner.reply_to_msg_id != 0 && messageObject.replyMessageObject == null) { - messageObject.replyMessageObject = messagesDict[0].get(messageObject.messageOwner.reply_to_msg_id); - if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage) { - messageObject.generatePinMessageText(null, null); - } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore) { - messageObject.generateGameMessageText(null); - } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) { - messageObject.generatePaymentSentMessageText(null); - } - if (messageObject.isMegagroup() && messageObject.replyMessageObject != null && messageObject.replyMessageObject.messageOwner != null) { - messageObject.replyMessageObject.messageOwner.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP; - } - } - } else if (inlineReturn != 0) { - if (messageObject.messageOwner.reply_markup != null) { - for (int b = 0; b < messageObject.messageOwner.reply_markup.rows.size(); b++) { - TLRPC.TL_keyboardButtonRow row = messageObject.messageOwner.reply_markup.rows.get(b); - for (int c = 0; c < row.buttons.size(); c++) { - TLRPC.KeyboardButton button = row.buttons.get(c); - if (button instanceof TLRPC.TL_keyboardButtonSwitchInline) { - processSwitchButton((TLRPC.TL_keyboardButtonSwitchInline) button); - break; - } + } else if (inlineReturn != 0) { + if (messageObject.messageOwner.reply_markup != null) { + for (int b = 0; b < messageObject.messageOwner.reply_markup.rows.size(); b++) { + TLRPC.TL_keyboardButtonRow row = messageObject.messageOwner.reply_markup.rows.get(b); + for (int c = 0; c < row.buttons.size(); c++) { + TLRPC.KeyboardButton button = row.buttons.get(c); + if (button instanceof TLRPC.TL_keyboardButtonSwitchInline) { + processSwitchButton((TLRPC.TL_keyboardButtonSwitchInline) button); + break; } } } } } + if (messageObject.messageOwner.reply_to_msg_id != 0 && messageObject.replyMessageObject == null) { + messageObject.replyMessageObject = messagesDict[0].get(messageObject.messageOwner.reply_to_msg_id); + if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPinMessage) { + messageObject.generatePinMessageText(null, null); + } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGameScore) { + messageObject.generateGameMessageText(null); + } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionPaymentSent) { + messageObject.generatePaymentSentMessageText(null); + } + if (messageObject.isMegagroup() && messageObject.replyMessageObject != null && messageObject.replyMessageObject.messageOwner != null) { + messageObject.replyMessageObject.messageOwner.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP; + } + } } boolean reloadMegagroup = false; @@ -8037,7 +8699,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (newMentionsCount != 0 && mentiondownButtonCounter != null) { mentiondownButtonCounter.setVisibility(View.VISIBLE); mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); - showMentiondownButton(true, true); + showMentionDownButton(true, true); } updateVisibleRows(); @@ -8295,7 +8957,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (newMentionsCount != 0 && mentiondownButtonCounter != null) { mentiondownButtonCounter.setVisibility(View.VISIBLE); mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); - showMentiondownButton(true, true); + showMentionDownButton(true, true); } } else { scrollToTopOnResume = true; @@ -8466,6 +9128,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } + showPagedownButton(false, true); + showMentionDownButton(false, true); if (updated && chatAdapter != null) { removeUnreadPlane(true); chatAdapter.notifyDataSetChanged(); @@ -8504,8 +9168,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updatePinnedMessageView(true); } if (obj != null) { + if (editingMessageObject == obj) { + hideFieldPanel(true); + } int index = messages.indexOf(obj); if (index != -1) { + removeUnreadPlane(false); if (selectedMessagesIds[loadIndex].indexOfKey(ids) >= 0) { updatedSelected = true; addToSelectedMessages(obj, false, updatedSelectedLast = (a == size - 1)); @@ -8536,8 +9204,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } - if (updatedSelected && !updatedSelectedLast) { - addToSelectedMessages(null, false, true); + if (updatedSelected) { + if (!updatedSelectedLast) { + addToSelectedMessages(null, false, true); + } + updateActionModeTitle(); } if (newGroups != null) { for (int a = 0; a < newGroups.size(); a++) { @@ -8588,10 +9259,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateBottomOverlay(); } } + showPagedownButton(false, true); + showMentionDownButton(false, true); } if (chatAdapter != null) { if (updated) { - removeUnreadPlane(false); int count = chatListView.getChildCount(); int position = -1; int bottom = 0; @@ -8679,7 +9351,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not obj.localSentGroupId = obj.messageOwner.grouped_id; obj.messageOwner.grouped_id = grouped_id; } + TLRPC.MessageFwdHeader fwdHeader = obj.messageOwner.fwd_from; obj.messageOwner = newMsgObj; + if (fwdHeader != null && newMsgObj.fwd_from != null && !TextUtils.isEmpty(newMsgObj.fwd_from.from_name)) { + obj.messageOwner.fwd_from = fwdHeader; + } obj.generateThumbs(true); obj.setType(); @@ -8892,67 +9568,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (id == NotificationCenter.removeAllMessagesFromDialog) { long did = (Long) args[0]; if (dialog_id == did) { - messages.clear(); - waitingForLoad.clear(); - messagesByDays.clear(); - groupedMessagesMap.clear(); - for (int a = 1; a >= 0; a--) { - messagesDict[a].clear(); - if (currentEncryptedChat == null) { - maxMessageId[a] = Integer.MAX_VALUE; - minMessageId[a] = Integer.MIN_VALUE; - } else { - maxMessageId[a] = Integer.MIN_VALUE; - minMessageId[a] = Integer.MAX_VALUE; - } - maxDate[a] = Integer.MIN_VALUE; - minDate[a] = 0; - selectedMessagesIds[a].clear(); - selectedMessagesCanCopyIds[a].clear(); - selectedMessagesCanStarIds[a].clear(); - } - cantDeleteMessagesCount = 0; - canEditMessagesCount = 0; - actionBar.hideActionMode(); - updatePinnedMessageView(true); - - if (botButtons != null) { - botButtons = null; - if (chatActivityEnterView != null) { - chatActivityEnterView.setButtons(null, false); - } - } - if ((Boolean) args[1]) { - if (chatAdapter != null) { - progressView.setVisibility(chatAdapter.botInfoRow == -1 ? View.VISIBLE : View.INVISIBLE); - chatListView.setEmptyView(null); - } - for (int a = 0; a < 2; a++) { - endReached[a] = false; - cacheEndReached[a] = false; - forwardEndReached[a] = true; - } - first = true; - firstLoading = true; - loading = true; - startLoadFromMessageId = 0; - needSelectFromMessageId = false; - waitingForLoad.add(lastLoadIndex); - MessagesController.getInstance(currentAccount).loadMessages(dialog_id, AndroidUtilities.isTablet() ? 30 : 20, 0, 0, true, 0, classGuid, 2, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); - } else { - if (progressView != null) { - progressView.setVisibility(View.INVISIBLE); - chatListView.setEmptyView(emptyViewContainer); - } - } - - if (chatAdapter != null) { - chatAdapter.notifyDataSetChanged(); - } - if (currentEncryptedChat == null && currentUser != null && currentUser.bot && botUser == null) { - botUser = ""; - updateBottomOverlay(); - } + clearHistory((Boolean) args[1]); } } else if (id == NotificationCenter.screenshotTook) { updateInformationForScreenshotDetector(); @@ -9010,7 +9626,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if ((messageObject.isRoundVideo() || messageObject.isVideo()) && fragmentView != null && fragmentView.getParent() != null) { MediaController.getInstance().setTextureView(createTextureView(true), aspectRatioFrameLayout, videoPlayerContainer, true); - updateTextureViewPosition(); + updateTextureViewPosition(true); } if (chatListView != null) { @@ -9430,7 +10046,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (newMentionsCount <= 0) { newMentionsCount = 0; hasAllMentionsLocal = true; - showMentiondownButton(false, true); + showMentionDownButton(false, true); } else { mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); } @@ -9472,7 +10088,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatActivityEnterView != null) { if (replyingMessageObject != null && botReplyButtons == replyingMessageObject) { botReplyButtons = null; - hideFieldPanel(); + hideFieldPanel(true); } chatActivityEnterView.setButtons(botButtons); } @@ -9484,6 +10100,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not long did = (Long) args[3]; if (messageId != 0) { scrollToMessageId(messageId, 0, true, did == dialog_id ? 0 : 1, false); + } else { + updateVisibleRows(); } updateSearchButtons((Integer) args[2], (Integer) args[4], (Integer) args[5]); if (searchItem != null) { @@ -9527,7 +10145,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (id == NotificationCenter.userInfoDidLoad) { Integer uid = (Integer) args[0]; if (currentUser != null && currentUser.id == uid) { - userInfo = (TLRPC.TL_userFull) args[1]; + userInfo = (TLRPC.UserFull) args[1]; if (headerItem != null) { if (userInfo.phone_calls_available) { headerItem.showSubItem(call); @@ -9570,7 +10188,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (newMentionsCount <= 0) { newMentionsCount = 0; hasAllMentionsLocal = true; - showMentiondownButton(false, true); + showMentionDownButton(false, true); } else { mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); } @@ -9588,7 +10206,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not continue; } ChatMessageCell cell = (ChatMessageCell) child; - TLRPC.Document document = cell.getStreamingVideo(); + TLRPC.Document document = cell.getStreamingMedia(); if (document == null) { continue; } @@ -9620,6 +10238,68 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }, true); } + private void clearHistory(boolean overwrite) { + messages.clear(); + waitingForLoad.clear(); + messagesByDays.clear(); + groupedMessagesMap.clear(); + for (int a = 1; a >= 0; a--) { + messagesDict[a].clear(); + if (currentEncryptedChat == null) { + maxMessageId[a] = Integer.MAX_VALUE; + minMessageId[a] = Integer.MIN_VALUE; + } else { + maxMessageId[a] = Integer.MIN_VALUE; + minMessageId[a] = Integer.MAX_VALUE; + } + maxDate[a] = Integer.MIN_VALUE; + minDate[a] = 0; + selectedMessagesIds[a].clear(); + selectedMessagesCanCopyIds[a].clear(); + selectedMessagesCanStarIds[a].clear(); + } + hideActionMode(); + updatePinnedMessageView(true); + + if (botButtons != null) { + botButtons = null; + if (chatActivityEnterView != null) { + chatActivityEnterView.setButtons(null, false); + } + } + if (overwrite) { + if (chatAdapter != null) { + progressView.setVisibility(chatAdapter.botInfoRow == -1 ? View.VISIBLE : View.INVISIBLE); + chatListView.setEmptyView(null); + } + for (int a = 0; a < 2; a++) { + endReached[a] = false; + cacheEndReached[a] = false; + forwardEndReached[a] = true; + } + first = true; + firstLoading = true; + loading = true; + startLoadFromMessageId = 0; + needSelectFromMessageId = false; + waitingForLoad.add(lastLoadIndex); + MessagesController.getInstance(currentAccount).loadMessages(dialog_id, AndroidUtilities.isTablet() ? 30 : 20, 0, 0, true, 0, classGuid, 2, 0, ChatObject.isChannel(currentChat), lastLoadIndex++); + } else { + if (progressView != null) { + progressView.setVisibility(View.INVISIBLE); + chatListView.setEmptyView(emptyViewContainer); + } + } + + if (chatAdapter != null) { + chatAdapter.notifyDataSetChanged(); + } + if (currentEncryptedChat == null && currentUser != null && currentUser.bot && botUser == null) { + botUser = ""; + updateBottomOverlay(); + } + } + public boolean processSwitchButton(TLRPC.TL_keyboardButtonSwitchInline button) { if (inlineReturn == 0 || button.same_peer || parentLayout == null) { return false; @@ -9750,14 +10430,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected void onBecomeFullyHidden() { if (undoView != null) { - undoView.hide(true, false); + undoView.hide(true, 0); } } @Override public void onTransitionAnimationStart(boolean isOpen, boolean backward) { NotificationCenter.getInstance(currentAccount).setAllowedNotificationsDutingAnimation(new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload, - NotificationCenter.closeChats, NotificationCenter.messagesDidLoad, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad/*, NotificationCenter.botInfoDidLoad*/}); + NotificationCenter.closeChats, NotificationCenter.messagesDidLoad, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.needDeleteDialog/*, NotificationCenter.botInfoDidLoad*/}); NotificationCenter.getInstance(currentAccount).setAnimationInProgress(true); if (isOpen) { openAnimationEnded = false; @@ -9882,7 +10562,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatActivityEnterView != null) { if (replyingMessageObject != null && botReplyButtons == replyingMessageObject) { botReplyButtons = null; - hideFieldPanel(); + hideFieldPanel(false); } chatActivityEnterView.setButtons(botButtons, false); } @@ -9935,6 +10615,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.setFieldFocused(false); chatActivityEnterView.setVisibility(View.INVISIBLE); chatActivityEnterView.closeKeyboard(); + if (stickersAdapter != null) { + stickersAdapter.hide(); + } } attachItem.setVisibility(View.GONE); editTextItem.setVisibility(View.GONE); @@ -9970,7 +10653,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not alertView.setVisibility(View.VISIBLE); alertViewAnimator = new AnimatorSet(); - alertViewAnimator.playTogether(ObjectAnimator.ofFloat(alertView, "translationY", 0)); + alertViewAnimator.playTogether(ObjectAnimator.ofFloat(alertView, View.TRANSLATION_Y, 0)); alertViewAnimator.setDuration(200); alertViewAnimator.addListener(new AnimatorListenerAdapter() { @Override @@ -10007,7 +10690,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not alertViewAnimator = null; } alertViewAnimator = new AnimatorSet(); - alertViewAnimator.playTogether(ObjectAnimator.ofFloat(alertView, "translationY", -AndroidUtilities.dp(50))); + alertViewAnimator.playTogether(ObjectAnimator.ofFloat(alertView, View.TRANSLATION_Y, -AndroidUtilities.dp(50))); alertViewAnimator.setDuration(200); alertViewAnimator.addListener(new AnimatorListenerAdapter() { @Override @@ -10040,7 +10723,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (animated) { pinnedMessageViewAnimator = new AnimatorSet(); - pinnedMessageViewAnimator.playTogether(ObjectAnimator.ofFloat(pinnedMessageView, "translationY", -AndroidUtilities.dp(50))); + pinnedMessageViewAnimator.playTogether(ObjectAnimator.ofFloat(pinnedMessageView, View.TRANSLATION_Y, -AndroidUtilities.dp(50))); pinnedMessageViewAnimator.setDuration(200); pinnedMessageViewAnimator.addListener(new AnimatorListenerAdapter() { @Override @@ -10104,7 +10787,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (animated) { pinnedMessageView.setVisibility(View.VISIBLE); pinnedMessageViewAnimator = new AnimatorSet(); - pinnedMessageViewAnimator.playTogether(ObjectAnimator.ofFloat(pinnedMessageView, "translationY", 0)); + pinnedMessageViewAnimator.playTogether(ObjectAnimator.ofFloat(pinnedMessageView, View.TRANSLATION_Y, 0)); pinnedMessageViewAnimator.setDuration(200); pinnedMessageViewAnimator.addListener(new AnimatorListenerAdapter() { @Override @@ -10129,13 +10812,32 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } FrameLayout.LayoutParams layoutParams1 = (FrameLayout.LayoutParams) pinnedMessageNameTextView.getLayoutParams(); FrameLayout.LayoutParams layoutParams2 = (FrameLayout.LayoutParams) pinnedMessageTextView.getLayoutParams(); + + int cacheType = 1; + int size = 0; TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(pinnedMessageObject.photoThumbs2, AndroidUtilities.dp(320)); + TLRPC.PhotoSize thumbPhotoSize = FileLoader.getClosestPhotoSizeWithSize(pinnedMessageObject.photoThumbs2, AndroidUtilities.dp(40)); + TLObject photoSizeObject = pinnedMessageObject.photoThumbsObject2; if (photoSize == null) { - photoSize = FileLoader.getClosestPhotoSizeWithSize(pinnedMessageObject.photoThumbs, AndroidUtilities.dp(320)); + if (pinnedMessageObject.mediaExists) { + photoSize = FileLoader.getClosestPhotoSizeWithSize(pinnedMessageObject.photoThumbs, AndroidUtilities.getPhotoSize()); + if (photoSize != null) { + size = photoSize.size; + } + cacheType = 0; + } else { + photoSize = FileLoader.getClosestPhotoSizeWithSize(pinnedMessageObject.photoThumbs, AndroidUtilities.dp(320)); + } + thumbPhotoSize = FileLoader.getClosestPhotoSizeWithSize(pinnedMessageObject.photoThumbs, AndroidUtilities.dp(40)); + photoSizeObject = pinnedMessageObject.photoThumbsObject; + } + if (photoSize == thumbPhotoSize) { + thumbPhotoSize = null; } if (photoSize == null || photoSize instanceof TLRPC.TL_photoSizeEmpty || photoSize.location instanceof TLRPC.TL_fileLocationUnavailable || pinnedMessageObject.type == 13) { pinnedMessageImageView.setImageBitmap(null); pinnedImageLocation = null; + pinnedImageLocationObject = null; pinnedMessageImageView.setVisibility(View.INVISIBLE); layoutParams1.leftMargin = layoutParams2.leftMargin = AndroidUtilities.dp(18); } else { @@ -10144,8 +10846,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { pinnedMessageImageView.setRoundRadius(0); } + pinnedImageSize = size; + pinnedImageCacheType = cacheType; pinnedImageLocation = photoSize; - pinnedMessageImageView.setImage(pinnedImageLocation, "50_50", (Drawable) null, pinnedMessageObject); + pinnedImageThumbLocation = thumbPhotoSize; + pinnedImageLocationObject = photoSizeObject; + pinnedMessageImageView.setImage(ImageLocation.getForObject(pinnedImageLocation, photoSizeObject), "50_50", ImageLocation.getForObject(thumbPhotoSize, photoSizeObject), "50_50_b", null, size, cacheType, pinnedMessageObject); pinnedMessageImageView.setVisibility(View.VISIBLE); layoutParams1.leftMargin = layoutParams2.leftMargin = AndroidUtilities.dp(55); } @@ -10179,6 +10885,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else { pinnedImageLocation = null; + pinnedImageLocationObject = null; hidePinnedMessageView(animated); if (loadingPinnedMessage != pinned_msg_id) { loadingPinnedMessage = pinned_msg_id; @@ -10217,7 +10924,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not reportSpamViewAnimator.cancel(); } reportSpamViewAnimator = new AnimatorSet(); - reportSpamViewAnimator.playTogether(ObjectAnimator.ofFloat(reportSpamView, "translationY", -AndroidUtilities.dp(50))); + reportSpamViewAnimator.playTogether(ObjectAnimator.ofFloat(reportSpamView, View.TRANSLATION_Y, -AndroidUtilities.dp(50))); reportSpamViewAnimator.setDuration(200); reportSpamViewAnimator.addListener(new AnimatorListenerAdapter() { @Override @@ -10248,7 +10955,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not reportSpamViewAnimator.cancel(); } reportSpamViewAnimator = new AnimatorSet(); - reportSpamViewAnimator.playTogether(ObjectAnimator.ofFloat(reportSpamView, "translationY", 0)); + reportSpamViewAnimator.playTogether(ObjectAnimator.ofFloat(reportSpamView, View.TRANSLATION_Y, 0)); reportSpamViewAnimator.setDuration(200); reportSpamViewAnimator.addListener(new AnimatorListenerAdapter() { @Override @@ -10420,7 +11127,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (newMentionsCount <= 0) { newMentionsCount = 0; hasAllMentionsLocal = true; - showMentiondownButton(false, true); + showMentionDownButton(false, true); } else { mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); } @@ -10468,10 +11175,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not checkActionBarMenu(); if (replyImageLocation != null && replyImageView != null) { - replyImageView.setImage(replyImageLocation, "50_50", (Drawable) null, replyingMessageObject); + replyImageView.setImage(ImageLocation.getForObject(replyImageLocation, replyImageLocationObject), "50_50", ImageLocation.getForObject(replyImageThumbLocation, replyImageLocationObject), "50_50_b", null, replyImageSize, replyImageCacheType, replyingMessageObject); } if (pinnedImageLocation != null && pinnedMessageImageView != null) { - pinnedMessageImageView.setImage(pinnedImageLocation, "50_50", (Drawable) null, pinnedMessageObject); + pinnedMessageImageView.setImage(ImageLocation.getForObject(pinnedImageLocation, pinnedImageLocationObject), "50_50", ImageLocation.getForObject(pinnedImageThumbLocation, pinnedImageLocationObject), "50_50_b", null, pinnedImageSize, pinnedImageCacheType, pinnedMessageObject); } NotificationsController.getInstance(currentAccount).setOpenedDialogId(dialog_id); @@ -10535,11 +11242,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatListView.setLongClickable(true); } checkBotCommands(); + updateTitle(); + } + + @Override + public void finishFragment() { + super.finishFragment(); + if (scrimPopupWindow != null) { + scrimPopupWindow.dismiss(); + } } @Override public void onPause() { super.onPause(); + if (scrimPopupWindow != null) { + scrimPopupWindow.dismiss(); + } MessagesController.getInstance(currentAccount).markDialogAsReadNow(dialog_id); MediaController.getInstance().stopRaiseToEarSensors(this, true); paused = true; @@ -10553,10 +11272,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.onPause(); replyMessage = replyingMessageObject; if (!chatActivityEnterView.isEditingMessage()) { - CharSequence text = AndroidUtilities.getTrimmedString(chatActivityEnterView.getFieldText()); - if (!TextUtils.isEmpty(text) && !TextUtils.equals(text, "@gif")) { - draftMessage = text; - } + draftMessage = AndroidUtilities.getTrimmedString(chatActivityEnterView.getFieldText()); } searchWebpage = chatActivityEnterView.isMessageWebPageSearchEnabled(); chatActivityEnterView.setFieldFocused(false); @@ -10645,7 +11361,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateInformationForScreenshotDetector(); } if (undoView != null) { - undoView.hide(true, false); + undoView.hide(true, 0); } } @@ -10709,11 +11425,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (canClear && draftMessage == null) { chatActivityEnterView.setFieldText(""); - hideFieldPanel(); + hideFieldPanel(true); } if (replyingMessageObject == null && draftReplyMessage != null) { replyingMessageObject = new MessageObject(currentAccount, draftReplyMessage, MessagesController.getInstance(currentAccount).getUsers(), false); - showFieldPanelForReply(true, replyingMessageObject); + showFieldPanelForReply(replyingMessageObject); } } @@ -10871,6 +11587,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (noSoundHintView != null) { noSoundHintView.hide(); } + if (forwardHintView != null) { + forwardHintView.hide(); + } if (visibleMessage.isRoundVideo()) { boolean result = MediaController.getInstance().playMessage(visibleMessage); MediaController.getInstance().setVoiceMessagesPlaylist(result ? createVoiceMessagesPlaylist(visibleMessage, false) : null, false); @@ -10895,6 +11614,37 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (visibleDialog instanceof DatePickerDialog) { visibleDialog.dismiss(); } + if (scrimPopupWindow != null) { + scrimPopupWindow.dismiss(); + } + + if (!AndroidUtilities.isTablet()) { + if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { + if (PhotoViewer.hasInstance() && PhotoViewer.getInstance().isVisible()) { + return; + } + MessageObject message = MediaController.getInstance().getPlayingMessageObject(); + if (message != null && message.isVideo()) { + PhotoViewer.getInstance().setParentActivity(getParentActivity()); + FileLoader.getInstance(currentAccount).setLoadingVideoForPlayer(message.getDocument(), false); + MediaController.getInstance().cleanupPlayer(true, true, false, true); + + if (PhotoViewer.getInstance().openPhoto(message, message.type != 0 ? dialog_id : 0, message.type != 0 ? mergeDialogId : 0, photoViewerProvider, false)) { + PhotoViewer.getInstance().setParentChatActivity(ChatActivity.this); + } + if (noSoundHintView != null) { + noSoundHintView.hide(); + } + if (forwardHintView != null) { + forwardHintView.hide(); + } + MediaController.getInstance().resetGoingToShowMessageObject(); + } + } else if (PhotoViewer.hasInstance() && PhotoViewer.getInstance().isOpenedFullScreenVideo()) { + PhotoViewer.getInstance().injectVideoPlayerToMediaController(); + PhotoViewer.getInstance().closePhoto(false, true); + } + } } private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages selectedGroup) { @@ -10902,303 +11652,31 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void createDeleteMessagesAlert(final MessageObject finalSelectedObject, final MessageObject.GroupedMessages finalSelectedGroup, int loadParticipant) { - if (getParentActivity() == null) { - return; - } - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - int count; - if (finalSelectedGroup != null) { - count = finalSelectedGroup.messages.size(); - } else if (finalSelectedObject != null) { - count = 1; - } else { - count = selectedMessagesIds[0].size() + selectedMessagesIds[1].size(); - } - builder.setMessage(LocaleController.formatString("AreYouSureDeleteMessages", R.string.AreYouSureDeleteMessages, LocaleController.formatPluralString("messages", count))); - builder.setTitle(LocaleController.getString("Message", R.string.Message)); - - final boolean[] checks = new boolean[3]; - final boolean[] deleteForAll = new boolean[1]; - TLRPC.User user = null; - int revokeTimeLimit; - boolean canRevokeInbox = currentUser != null && MessagesController.getInstance(currentAccount).canRevokePmInbox; - if (currentUser != null) { - revokeTimeLimit = MessagesController.getInstance(currentAccount).revokeTimePmLimit; - } else { - revokeTimeLimit = MessagesController.getInstance(currentAccount).revokeTimeLimit; - } - if (currentChat != null && currentChat.megagroup) { - boolean hasOutgoing = false; - boolean canBan = ChatObject.canBlockUsers(currentChat); - int currentDate = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); - if (finalSelectedObject != null) { - if (finalSelectedObject.messageOwner.action == null || finalSelectedObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty || - finalSelectedObject.messageOwner.action instanceof TLRPC.TL_messageActionChatDeleteUser || - finalSelectedObject.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByLink || - finalSelectedObject.messageOwner.action instanceof TLRPC.TL_messageActionChatAddUser) { - user = MessagesController.getInstance(currentAccount).getUser(finalSelectedObject.messageOwner.from_id); - } - hasOutgoing = !finalSelectedObject.isSendError() && finalSelectedObject.getDialogId() == mergeDialogId && (finalSelectedObject.messageOwner.action == null || finalSelectedObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) && finalSelectedObject.isOut() && (currentDate - finalSelectedObject.messageOwner.date) <= revokeTimeLimit; - } else { - int from_id = -1; - for (int a = 1; a >= 0; a--) { - int channelId = 0; - for (int b = 0; b < selectedMessagesIds[a].size(); b++) { - MessageObject msg = selectedMessagesIds[a].valueAt(b); - if (from_id == -1) { - from_id = msg.messageOwner.from_id; - } - if (from_id < 0 || from_id != msg.messageOwner.from_id) { - from_id = -2; - break; - } - } - if (from_id == -2) { - break; - } - } - boolean exit = false; - for (int a = 1; a >= 0; a--) { - for (int b = 0; b < selectedMessagesIds[a].size(); b++) { - MessageObject msg = selectedMessagesIds[a].valueAt(b); - if (a == 1) { - if (msg.isOut() && msg.messageOwner.action == null) { - if ((currentDate - msg.messageOwner.date) <= 2 * 24 * 60 * 60) { - hasOutgoing = true; - } - } else { - hasOutgoing = false; - exit = true; - break; - } - } else if (a == 0) { - if (!msg.isOut()) { - hasOutgoing = false; - exit = true; - break; - } - } - } - if (exit) { - break; - } - } - if (from_id != -1) { - user = MessagesController.getInstance(currentAccount).getUser(from_id); - } - } - if (user != null && user.id != UserConfig.getInstance(currentAccount).getClientUserId() && loadParticipant != 2) { - if (loadParticipant == 1 && !currentChat.creator) { - final AlertDialog progressDialog[] = new AlertDialog[] {new AlertDialog(getParentActivity(), 3)}; - - TLRPC.TL_channels_getParticipant req = new TLRPC.TL_channels_getParticipant(); - req.channel = MessagesController.getInputChannel(currentChat); - req.user_id = MessagesController.getInstance(currentAccount).getInputUser(user); - int requestId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - try { - progressDialog[0].dismiss(); - } catch (Throwable ignore) { - - } - progressDialog[0] = null; - int loadType = 2; - if (response != null) { - TLRPC.TL_channels_channelParticipant participant = (TLRPC.TL_channels_channelParticipant) response; - if (!(participant.participant instanceof TLRPC.TL_channelParticipantAdmin || participant.participant instanceof TLRPC.TL_channelParticipantCreator)) { - loadType = 0; - } - } - createDeleteMessagesAlert(finalSelectedObject, finalSelectedGroup, loadType); - })); - AndroidUtilities.runOnUIThread(() -> { - if (progressDialog[0] == null) { - return; - } - progressDialog[0].setOnCancelListener(dialog -> ConnectionsManager.getInstance(currentAccount).cancelRequest(requestId, true)); - showDialog(progressDialog[0]); - }, 1000); - return; - } - FrameLayout frameLayout = new FrameLayout(getParentActivity()); - int num = 0; - for (int a = 0; a < 3; a++) { - if (!canBan && a == 0) { - continue; - } - CheckBoxCell cell = new CheckBoxCell(getParentActivity(), 1); - cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); - cell.setTag(a); - if (a == 0) { - cell.setText(LocaleController.getString("DeleteBanUser", R.string.DeleteBanUser), "", false, false); - } else if (a == 1) { - cell.setText(LocaleController.getString("DeleteReportSpam", R.string.DeleteReportSpam), "", false, false); - } else if (a == 2) { - cell.setText(LocaleController.formatString("DeleteAllFrom", R.string.DeleteAllFrom, ContactsController.formatName(user.first_name, user.last_name)), "", false, false); - } - cell.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0, LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0); - frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 0, 48 * num, 0, 0)); - cell.setOnClickListener(v -> { - if (!v.isEnabled()) { - return; - } - CheckBoxCell cell13 = (CheckBoxCell) v; - Integer num1 = (Integer) cell13.getTag(); - checks[num1] = !checks[num1]; - cell13.setChecked(checks[num1], true); - }); - num++; - } - builder.setView(frameLayout); - } else if (hasOutgoing) { - FrameLayout frameLayout = new FrameLayout(getParentActivity()); - CheckBoxCell cell = new CheckBoxCell(getParentActivity(), 1); - cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); - if (currentChat != null) { - cell.setText(LocaleController.getString("DeleteForAll", R.string.DeleteForAll), "", false, false); - } else { - cell.setText(LocaleController.formatString("DeleteForUser", R.string.DeleteForUser, UserObject.getFirstName(currentUser)), "", false, false); - } - cell.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0, LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0); - frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0)); - cell.setOnClickListener(v -> { - CheckBoxCell cell12 = (CheckBoxCell) v; - deleteForAll[0] = !deleteForAll[0]; - cell12.setChecked(deleteForAll[0], true); - }); - builder.setView(frameLayout); - } else { - user = null; - } - } else if (!ChatObject.isChannel(currentChat) && currentEncryptedChat == null) { - boolean hasOutgoing = false; - int currentDate = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); - if (currentUser != null && currentUser.id != UserConfig.getInstance(currentAccount).getClientUserId() && !currentUser.bot || currentChat != null) { - if (finalSelectedObject != null) { - hasOutgoing = !finalSelectedObject.isSendError() && (finalSelectedObject.messageOwner.action == null || finalSelectedObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) && (finalSelectedObject.isOut() || canRevokeInbox || ChatObject.hasAdminRights(currentChat)) && (currentDate - finalSelectedObject.messageOwner.date) <= revokeTimeLimit; - } else { - boolean exit = false; - for (int a = 1; a >= 0; a--) { - int channelId = 0; - for (int b = 0; b < selectedMessagesIds[a].size(); b++) { - MessageObject msg = selectedMessagesIds[a].valueAt(b); - if (msg.messageOwner.action != null) { - continue; - } - if ((msg.isOut() || canRevokeInbox) || currentChat != null && ChatObject.canBlockUsers(currentChat)) { - if (!hasOutgoing && (currentDate - msg.messageOwner.date) <= revokeTimeLimit) { - hasOutgoing = true; - } - } else { - exit = true; - hasOutgoing = false; - break; - } - } - if (exit) { - break; - } - } - } - } - if (hasOutgoing) { - FrameLayout frameLayout = new FrameLayout(getParentActivity()); - CheckBoxCell cell = new CheckBoxCell(getParentActivity(), 1); - cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); - if (currentChat != null) { - cell.setText(LocaleController.getString("DeleteForAll", R.string.DeleteForAll), "", false, false); - } else { - cell.setText(LocaleController.formatString("DeleteForUser", R.string.DeleteForUser, UserObject.getFirstName(currentUser)), "", false, false); - } - cell.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0, LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0); - frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0)); - cell.setOnClickListener(v -> { - CheckBoxCell cell1 = (CheckBoxCell) v; - deleteForAll[0] = !deleteForAll[0]; - cell1.setChecked(deleteForAll[0], true); - }); - builder.setView(frameLayout); - } - } - final TLRPC.User userFinal = user; - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> { - ArrayList ids = null; - if (finalSelectedObject != null) { - ids = new ArrayList<>(); - ArrayList random_ids = null; - if (finalSelectedGroup != null) { - for (int a = 0; a < finalSelectedGroup.messages.size(); a++) { - MessageObject messageObject = finalSelectedGroup.messages.get(a); - ids.add(messageObject.getId()); - if (currentEncryptedChat != null && messageObject.messageOwner.random_id != 0 && messageObject.type != 10) { - if (random_ids == null) { - random_ids = new ArrayList<>(); - } - random_ids.add(messageObject.messageOwner.random_id); - } - } - } else { - ids.add(finalSelectedObject.getId()); - if (currentEncryptedChat != null && finalSelectedObject.messageOwner.random_id != 0 && finalSelectedObject.type != 10) { - random_ids = new ArrayList<>(); - random_ids.add(finalSelectedObject.messageOwner.random_id); - } - } - MessagesController.getInstance(currentAccount).deleteMessages(ids, random_ids, currentEncryptedChat, finalSelectedObject.messageOwner.to_id.channel_id, deleteForAll[0]); - } else { - for (int a = 1; a >= 0; a--) { - ids = new ArrayList<>(); - for (int b = 0; b < selectedMessagesIds[a].size(); b++) { - ids.add(selectedMessagesIds[a].keyAt(b)); - } - ArrayList random_ids = null; - int channelId = 0; - if (!ids.isEmpty()) { - MessageObject msg = selectedMessagesIds[a].get(ids.get(0)); - if (channelId == 0 && msg.messageOwner.to_id.channel_id != 0) { - channelId = msg.messageOwner.to_id.channel_id; - } - } - if (currentEncryptedChat != null) { - random_ids = new ArrayList<>(); - for (int b = 0; b < selectedMessagesIds[a].size(); b++) { - MessageObject msg = selectedMessagesIds[a].valueAt(b); - if (msg.messageOwner.random_id != 0 && msg.type != 10) { - random_ids.add(msg.messageOwner.random_id); - } - } - } - MessagesController.getInstance(currentAccount).deleteMessages(ids, random_ids, currentEncryptedChat, channelId, deleteForAll[0]); - } - actionBar.hideActionMode(); - updatePinnedMessageView(true); - } - if (userFinal != null) { - if (checks[0]) { - MessagesController.getInstance(currentAccount).deleteUserFromChat(currentChat.id, userFinal, chatInfo); - } - if (checks[1]) { - TLRPC.TL_channels_reportSpam req = new TLRPC.TL_channels_reportSpam(); - req.channel = MessagesController.getInputChannel(currentChat); - req.user_id = MessagesController.getInstance(currentAccount).getInputUser(userFinal); - req.id = ids; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - - }); - } - if (checks[2]) { - MessagesController.getInstance(currentAccount).deleteUserChannelHistory(currentChat, userFinal, 0); - } - } + AlertsCreator.createDeleteMessagesAlert(this, currentUser, currentChat, currentEncryptedChat, chatInfo, mergeDialogId, finalSelectedObject, selectedMessagesIds, finalSelectedGroup, loadParticipant, () -> { + hideActionMode(); + updatePinnedMessageView(true); }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showDialog(builder.create()); } - private void createMenu(View v, boolean single, boolean listView) { - createMenu(v, single, listView, true); + private void hideActionMode() { + if (actionBar != null) { + actionBar.hideActionMode(); + } + cantDeleteMessagesCount = 0; + canEditMessagesCount = 0; + cantForwardMessagesCount = 0; + if (chatActivityEnterView != null) { + EditTextCaption editTextCaption = chatActivityEnterView.getEditField(); + editTextCaption.requestFocus(); + editTextCaption.setAllowDrawCursor(true); + } } - private void createMenu(View v, boolean single, boolean listView, boolean searchGroup) { + private void createMenu(View v, boolean single, boolean listView, float x, float y) { + createMenu(v, single, listView, x, y, true); + } + + private void createMenu(View v, boolean single, boolean listView, float x, float y, boolean searchGroup) { if (actionBar.isActionModeShowed()) { return; } @@ -11229,9 +11707,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selectedMessagesCanStarIds[a].clear(); selectedMessagesIds[a].clear(); } - cantDeleteMessagesCount = 0; - canEditMessagesCount = 0; - actionBar.hideActionMode(); + hideActionMode(); updatePinnedMessageView(true); MessageObject.GroupedMessages groupedMessages; @@ -11267,10 +11743,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not allowChatActions = false; } - if (single || type < 2 || type == 20 || message.needDrawBluredPreview() || message.isLiveLocation()) { + if (single || type < 2 || type == 20) { if (getParentActivity() == null) { return; } + ArrayList icons = new ArrayList<>(); ArrayList items = new ArrayList<>(); final ArrayList options = new ArrayList<>(); @@ -11279,160 +11756,208 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selectedObjectGroup = groupedMessages; if (type == -1) { + if (selectedObject.type == 0 || selectedObject.caption != null) { + items.add(LocaleController.getString("Copy", R.string.Copy)); + options.add(3); + icons.add(R.drawable.msg_copy); + } items.add(LocaleController.getString("CancelSending", R.string.CancelSending)); options.add(24); + icons.add(R.drawable.msg_delete); } else if (type == 0) { items.add(LocaleController.getString("Retry", R.string.Retry)); options.add(0); + icons.add(R.drawable.msg_retry); items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); + icons.add(R.drawable.msg_delete); } else if (type == 1) { if (currentChat != null && !isBroadcast) { if (allowChatActions) { items.add(LocaleController.getString("Reply", R.string.Reply)); options.add(8); + icons.add(R.drawable.msg_reply); } if (allowUnpin) { items.add(LocaleController.getString("UnpinMessage", R.string.UnpinMessage)); options.add(14); + icons.add(R.drawable.msg_unpin); } else if (allowPin) { items.add(LocaleController.getString("PinMessage", R.string.PinMessage)); options.add(13); + icons.add(R.drawable.msg_pin); } if (allowEdit) { items.add(LocaleController.getString("Edit", R.string.Edit)); options.add(12); + icons.add(R.drawable.msg_edit); } if (selectedObject.contentType == 0 && !selectedObject.isMediaEmptyWebpage() && 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)) { items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); + icons.add(R.drawable.msg_delete); } } else { - if (message.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)); - options.add(18); - if(VoIPHelper.canRateCall(call)){ - items.add(LocaleController.getString("CallMessageReportProblem", R.string.CallMessageReportProblem)); - options.add(19); - } - } - if (single && selectedObject.getId() > 0 && allowChatActions) { + if (selectedObject.getId() > 0 && allowChatActions) { items.add(LocaleController.getString("Reply", R.string.Reply)); options.add(8); + icons.add(R.drawable.msg_reply); } if (message.canDeleteMessage(currentChat)) { items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); + icons.add(R.drawable.msg_delete); } } } else if (type == 20) { items.add(LocaleController.getString("Retry", R.string.Retry)); options.add(0); + icons.add(R.drawable.msg_retry); items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(3); + icons.add(R.drawable.msg_copy); items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); + icons.add(R.drawable.msg_delete); } else { if (currentEncryptedChat == null) { + 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)); + options.add(18); + icons.add(R.drawable.msg_callback); + if (VoIPHelper.canRateCall(call)) { + items.add(LocaleController.getString("CallMessageReportProblem", R.string.CallMessageReportProblem)); + options.add(19); + icons.add(R.drawable.msg_fave); + } + } if (allowChatActions) { items.add(LocaleController.getString("Reply", R.string.Reply)); options.add(8); + icons.add(R.drawable.msg_reply); } if (selectedObject.type == 0 || selectedObject.caption != null) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(3); + icons.add(R.drawable.msg_copy); } - if (ChatObject.isChannel(currentChat) && currentChat.megagroup && !TextUtils.isEmpty(currentChat.username)) { + if (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); } } } else if (type == 3) { if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && MessageObject.isNewGifDocument(selectedObject.messageOwner.media.webpage.document)) { items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); options.add(11); + icons.add(R.drawable.msg_gif); } } else if (type == 4) { if (selectedObject.isVideo()) { if (!selectedObject.needDrawBluredPreview()) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(4); + icons.add(R.drawable.msg_gallery); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); + icons.add(R.drawable.msg_shareout); } } else if (selectedObject.isMusic()) { items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); options.add(10); + icons.add(R.drawable.msg_download); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); + icons.add(R.drawable.msg_shareout); } else if (selectedObject.getDocument() != null) { if (MessageObject.isNewGifDocument(selectedObject.getDocument())) { items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); options.add(11); + icons.add(R.drawable.msg_gif); } items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(10); + icons.add(R.drawable.msg_download); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); + icons.add(R.drawable.msg_shareout); } else { if (!selectedObject.needDrawBluredPreview()) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(4); + icons.add(R.drawable.msg_gallery); } } } else if (type == 5) { items.add(LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile)); options.add(5); + icons.add(R.drawable.msg_language); items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(10); + icons.add(R.drawable.msg_download); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); + icons.add(R.drawable.msg_shareout); } else if (type == 10) { items.add(LocaleController.getString("ApplyThemeFile", R.string.ApplyThemeFile)); options.add(5); + icons.add(R.drawable.msg_theme); items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(10); + icons.add(R.drawable.msg_download); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); + icons.add(R.drawable.msg_shareout); } else if (type == 6) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(7); + icons.add(R.drawable.msg_gallery); items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(10); + icons.add(R.drawable.msg_download); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); + icons.add(R.drawable.msg_shareout); } else if (type == 7) { if (selectedObject.isMask()) { items.add(LocaleController.getString("AddToMasks", R.string.AddToMasks)); options.add(9); + icons.add(R.drawable.msg_sticker); } else { items.add(LocaleController.getString("AddToStickers", R.string.AddToStickers)); options.add(9); + icons.add(R.drawable.msg_sticker); if (!DataQuery.getInstance(currentAccount).isStickerInFavorites(selectedObject.getDocument())) { if (DataQuery.getInstance(currentAccount).canAddStickerToFavorites()) { items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); options.add(20); + icons.add(R.drawable.msg_fave); } } else { items.add(LocaleController.getString("DeleteFromFavorites", R.string.DeleteFromFavorites)); options.add(21); + icons.add(R.drawable.msg_unfave); } } } else if (type == 8) { @@ -11440,129 +11965,363 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (user != null && user.id != UserConfig.getInstance(currentAccount).getClientUserId() && ContactsController.getInstance(currentAccount).contactsDict.get(user.id) == null) { items.add(LocaleController.getString("AddContactTitle", R.string.AddContactTitle)); options.add(15); + icons.add(R.drawable.msg_addcontact); } if (!TextUtils.isEmpty(selectedObject.messageOwner.media.phone_number)) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(16); + icons.add(R.drawable.msg_copy); items.add(LocaleController.getString("Call", R.string.Call)); options.add(17); + icons.add(R.drawable.msg_callback); } } else if (type == 9) { if (!DataQuery.getInstance(currentAccount).isStickerInFavorites(selectedObject.getDocument())) { items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); options.add(20); + icons.add(R.drawable.msg_fave); } else { items.add(LocaleController.getString("DeleteFromFavorites", R.string.DeleteFromFavorites)); options.add(21); + icons.add(R.drawable.msg_unfave); } } - if (!selectedObject.needDrawBluredPreview() && !selectedObject.isLiveLocation()) { + if (!selectedObject.needDrawBluredPreview() && !selectedObject.isLiveLocation() && selectedObject.type != 16) { items.add(LocaleController.getString("Forward", R.string.Forward)); options.add(2); + icons.add(R.drawable.msg_forward); } if (allowUnpin) { items.add(LocaleController.getString("UnpinMessage", R.string.UnpinMessage)); options.add(14); + icons.add(R.drawable.msg_unpin); } else if (allowPin) { items.add(LocaleController.getString("PinMessage", R.string.PinMessage)); options.add(13); + icons.add(R.drawable.msg_pin); } if (allowEdit) { items.add(LocaleController.getString("Edit", R.string.Edit)); options.add(12); + icons.add(R.drawable.msg_edit); } if (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)) { items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); + icons.add(R.drawable.msg_delete); } } else { if (allowChatActions) { items.add(LocaleController.getString("Reply", R.string.Reply)); options.add(8); + icons.add(R.drawable.msg_reply); } if (selectedObject.type == 0 || selectedObject.caption != null) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(3); + icons.add(R.drawable.msg_copy); } if (type == 4) { if (selectedObject.isVideo()) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(4); + icons.add(R.drawable.msg_gallery); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); + icons.add(R.drawable.msg_shareout); } else if (selectedObject.isMusic()) { items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); options.add(10); + icons.add(R.drawable.msg_download); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); + icons.add(R.drawable.msg_shareout); } else if (!selectedObject.isVideo() && selectedObject.getDocument() != null) { items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(10); + icons.add(R.drawable.msg_download); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); options.add(6); + icons.add(R.drawable.msg_shareout); } else { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); options.add(4); + icons.add(R.drawable.msg_gallery); } } else if (type == 5) { items.add(LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile)); options.add(5); + icons.add(R.drawable.msg_language); } else if (type == 10) { items.add(LocaleController.getString("ApplyThemeFile", R.string.ApplyThemeFile)); options.add(5); + icons.add(R.drawable.msg_theme); } else if (type == 7) { items.add(LocaleController.getString("AddToStickers", R.string.AddToStickers)); options.add(9); + icons.add(R.drawable.msg_sticker); } else if (type == 8) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(selectedObject.messageOwner.media.user_id); if (user != null && user.id != UserConfig.getInstance(currentAccount).getClientUserId() && ContactsController.getInstance(currentAccount).contactsDict.get(user.id) == null) { items.add(LocaleController.getString("AddContactTitle", R.string.AddContactTitle)); options.add(15); + icons.add(R.drawable.msg_addcontact); } if (!TextUtils.isEmpty(selectedObject.messageOwner.media.phone_number)) { items.add(LocaleController.getString("Copy", R.string.Copy)); options.add(16); + icons.add(R.drawable.msg_copy); items.add(LocaleController.getString("Call", R.string.Call)); options.add(17); + icons.add(R.drawable.msg_callback); } } items.add(LocaleController.getString("Delete", R.string.Delete)); options.add(1); + icons.add(R.drawable.msg_delete); } } } if (options.isEmpty()) { return; } - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - final CharSequence[] finalItems = items.toArray(new CharSequence[0]); - builder.setItems(finalItems, (dialogInterface, i) -> { - if (selectedObject == null || i < 0 || i >= options.size()) { - return; - } - processSelectedOption(options.get(i)); - }); - builder.setTitle(LocaleController.getString("Message", R.string.Message)); - showDialog(builder.create()); + if (scrimPopupWindow != null) { + scrimPopupWindow.dismiss(); + scrimPopupWindow = null; + return; + } + + Rect rect = new Rect(); + + ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getParentActivity()); + popupLayout.setOnTouchListener((view, event) -> { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + if (scrimPopupWindow != null && scrimPopupWindow.isShowing()) { + v.getHitRect(rect); + if (!rect.contains((int) event.getX(), (int) event.getY())) { + scrimPopupWindow.dismiss(); + } + } + } else if (event.getActionMasked() == MotionEvent.ACTION_OUTSIDE) { + if (scrimPopupWindow != null && scrimPopupWindow.isShowing()) { + scrimPopupWindow.dismiss(); + } + } + return false; + }); + popupLayout.setDispatchKeyEventListener(keyEvent -> { + if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK && keyEvent.getRepeatCount() == 0 && scrimPopupWindow != null && scrimPopupWindow.isShowing()) { + scrimPopupWindow.dismiss(); + } + }); + Rect backgroundPaddings = new Rect(); + Drawable shadowDrawable = getParentActivity().getResources().getDrawable(R.drawable.popup_fixed_alert).mutate(); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); + shadowDrawable.getPadding(backgroundPaddings); + popupLayout.setBackgroundDrawable(shadowDrawable); + + LinearLayout linearLayout = new LinearLayout(getParentActivity()); + ScrollView scrollView; + if (Build.VERSION.SDK_INT >= 21) { + scrollView = new ScrollView(getParentActivity(), null, 0, R.style.scrollbarShapeStyle) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + setMeasuredDimension(linearLayout.getMeasuredWidth(), getMeasuredHeight()); + } + }; + } else { + scrollView = new ScrollView(getParentActivity()); + } + scrollView.setClipToPadding(false); + popupLayout.addView(scrollView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + + linearLayout.setMinimumWidth(AndroidUtilities.dp(200)); + linearLayout.setOrientation(LinearLayout.VERTICAL); + for (int a = 0, N = items.size(); a < N; a++) { + ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity()); + cell.setTextAndIcon(items.get(a), icons.get(a)); + linearLayout.addView(cell); + final int i = a; + cell.setOnClickListener(v1 -> { + if (selectedObject == null || i < 0 || i >= options.size()) { + return; + } + processSelectedOption(options.get(i)); + if (scrimPopupWindow != null) { + scrimPopupWindow.dismiss(); + } + }); + } + scrollView.addView(linearLayout, LayoutHelper.createScroll(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP)); + scrimPopupWindow = new ActionBarPopupWindow(popupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { + @Override + public void dismiss() { + super.dismiss(); + if (scrimPopupWindow != this) { + return; + } + scrimPopupWindow = null; + if (scrimAnimatorSet != null) { + scrimAnimatorSet.cancel(); + scrimAnimatorSet = null; + } + if (scrimView instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) scrimView; + cell.setInvalidatesParent(false); + } + chatLayoutManager.setCanScrollVertically(true); + scrimAnimatorSet = new AnimatorSet(); + ArrayList animators = new ArrayList<>(); + animators.add(ObjectAnimator.ofInt(scrimPaint, AnimationProperties.PAINT_ALPHA, 0)); + if (pagedownButton.getTag() != null) { + animators.add(ObjectAnimator.ofFloat(pagedownButton, View.ALPHA, 1.0f)); + } + if (mentiondownButton.getTag() != null) { + animators.add(ObjectAnimator.ofFloat(mentiondownButton, View.ALPHA, 1.0f)); + } + scrimAnimatorSet.playTogether(animators); + scrimAnimatorSet.setDuration(220); + scrimAnimatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + scrimView = null; + contentView.invalidate(); + chatListView.invalidate(); + } + }); + scrimAnimatorSet.start(); + if (chatActivityEnterView != null) { + chatActivityEnterView.getEditField().setAllowDrawCursor(true); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + getParentActivity().getWindow().getDecorView().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); + } + } + }; + scrimPopupWindow.setDismissAnimationDuration(220); + scrimPopupWindow.setOutsideTouchable(true); + scrimPopupWindow.setClippingEnabled(true); + scrimPopupWindow.setAnimationStyle(R.style.PopupContextAnimation); + scrimPopupWindow.setFocusable(true); + popupLayout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); + scrimPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); + scrimPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); + scrimPopupWindow.getContentView().setFocusableInTouchMode(true); + int popupX = v.getLeft() + (int) x - popupLayout.getMeasuredWidth() + backgroundPaddings.left - AndroidUtilities.dp(28); + if (popupX < AndroidUtilities.dp(6)) { + popupX = AndroidUtilities.dp(6); + } else if (popupX > chatListView.getMeasuredWidth() - AndroidUtilities.dp(6) - popupLayout.getMeasuredWidth()) { + popupX = chatListView.getMeasuredWidth() - AndroidUtilities.dp(6) - popupLayout.getMeasuredWidth(); + } + if (AndroidUtilities.isTablet()) { + int[] location = new int[2]; + fragmentView.getLocationInWindow(location); + popupX += location[0]; + } + int totalHeight = contentView.getHeight(); + int height = popupLayout.getMeasuredHeight(); + int keyboardHeight = contentView.getKeyboardHeight(); + if (keyboardHeight > AndroidUtilities.dp(20)) { + totalHeight += keyboardHeight; + } + int popupY; + if (height < totalHeight) { + popupY = (int) (chatListView.getY() + v.getTop() + y); + if (height - backgroundPaddings.top - backgroundPaddings.bottom > AndroidUtilities.dp(240)) { + popupY += AndroidUtilities.dp(240) - height; + } + if (popupY < chatListView.getY() + AndroidUtilities.dp(24)) { + popupY = (int) (chatListView.getY() + AndroidUtilities.dp(24)); + } else if (popupY > totalHeight - height - AndroidUtilities.dp(8)) { + popupY = totalHeight - height - AndroidUtilities.dp(8); + } + } else { + popupY = AndroidUtilities.statusBarHeight; + } + scrimPopupWindow.showAtLocation(chatListView, Gravity.LEFT | Gravity.TOP, popupX, popupY); + chatListView.stopScroll(); + chatLayoutManager.setCanScrollVertically(false); + scrimView = v; + if (scrimView instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) scrimView; + cell.setInvalidatesParent(true); + } + contentView.invalidate(); + chatListView.invalidate(); + if (scrimAnimatorSet != null) { + scrimAnimatorSet.cancel(); + } + scrimAnimatorSet = new AnimatorSet(); + ArrayList animators = new ArrayList<>(); + animators.add(ObjectAnimator.ofInt(scrimPaint, AnimationProperties.PAINT_ALPHA, 0, 50)); + if (pagedownButton.getTag() != null) { + animators.add(ObjectAnimator.ofFloat(pagedownButton, View.ALPHA, 0)); + } + if (mentiondownButton.getTag() != null) { + animators.add(ObjectAnimator.ofFloat(mentiondownButton, View.ALPHA, 0)); + } + scrimAnimatorSet.playTogether(animators); + scrimAnimatorSet.setDuration(150); + scrimAnimatorSet.start(); + if (forwardHintView != null) { + forwardHintView.hide(); + } + if (noSoundHintView != null) { + noSoundHintView.hide(); + } + if (chatActivityEnterView != null) { + chatActivityEnterView.getEditField().setAllowDrawCursor(false); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + getParentActivity().getWindow().getDecorView().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); + } + return; + } + + if (chatActivityEnterView != null && (chatActivityEnterView.isRecordingAudioVideo() || chatActivityEnterView.isRecordLocked())) { return; } final ActionBarMenu actionMode = actionBar.createActionMode(); - View item = actionMode.getItem(forward); - if (item != null) { - item.setVisibility(View.VISIBLE); - } - item = actionMode.getItem(delete); + View item = actionMode.getItem(delete); if (item != null) { item.setVisibility(View.VISIBLE); } + bottomMessagesActionContainer.setVisibility(View.VISIBLE); - actionBar.showActionMode(); + int translationY = chatActivityEnterView.getMeasuredHeight() - AndroidUtilities.dp(51); + if (chatActivityEnterView.getVisibility() == View.VISIBLE) { + ArrayList views = new ArrayList<>(); + views.add(chatActivityEnterView); + if (mentionContainer != null && mentionContainer.getVisibility() == View.VISIBLE) { + views.add(mentionContainer); + } + if (stickersPanel != null && stickersPanel.getVisibility() == View.VISIBLE) { + views.add(stickersPanel); + } + actionBar.showActionMode(bottomMessagesActionContainer, null, views.toArray(new View[0]), new boolean[]{false, true, true}, chatListView, translationY); + if (getParentActivity() != null) { + ((LaunchActivity) getParentActivity()).hideVisibleActionMode(); + } + chatActivityEnterView.getEditField().setAllowDrawCursor(false); + } else if (bottomOverlayChat.getVisibility() == View.VISIBLE) { + actionBar.showActionMode(bottomMessagesActionContainer, null, new View[]{bottomOverlayChat}, new boolean[]{true}, chatListView, translationY); + } else if (searchContainer.getVisibility() == View.VISIBLE) { + actionBar.showActionMode(bottomMessagesActionContainer, null, new View[]{searchContainer}, new boolean[]{true}, chatListView, translationY); + } else { + actionBar.showActionMode(bottomMessagesActionContainer, null, null, null, chatListView, translationY); + } + if (scrimPopupWindow != null) { + scrimPopupWindow.dismiss(); + } + chatLayoutManager.setCanScrollVertically(true); updatePinnedMessageView(true); AnimatorSet animatorSet = new AnimatorSet(); @@ -11571,7 +12330,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not View view = actionModeViews.get(a); view.setPivotY(ActionBar.getCurrentActionBarHeight() / 2); AndroidUtilities.clearDrawableAnimation(view); - animators.add(ObjectAnimator.ofFloat(view, "scaleY", 0.1f, 1.0f)); + animators.add(ObjectAnimator.ofFloat(view, View.SCALE_Y, 0.1f, 1.0f)); } animatorSet.playTogether(animators); animatorSet.setDuration(250); @@ -11593,10 +12352,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } mentionsAdapter.setNeedBotContext(false); - chatListView.setOnItemLongClickListener((RecyclerListView.OnItemLongClickListenerExtended) null); - chatListView.setOnItemClickListener((RecyclerListView.OnItemClickListenerExtended) null); - chatListView.setClickable(false); - chatListView.setLongClickable(false); chatActivityEnterView.setVisibility(View.VISIBLE); showFieldPanelForEdit(true, messageObject); updateBottomOverlay(); @@ -11621,7 +12376,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatActivityEnterView != null) { chatActivityEnterView.setEditingMessageObject(null, false); - hideFieldPanel(); + hideFieldPanel(true); } } else { if (chatActivityEnterView != null) { @@ -11854,7 +12609,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not break; } case 8: { - showFieldPanelForReply(true, selectedObject); + showFieldPanelForReply(selectedObject); break; } case 9: { @@ -11995,7 +12750,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); ClipData clip = ClipData.newPlainText("label", exportedMessageLink.link); clipboard.setPrimaryClip(clip); - Toast.makeText(ApplicationLoader.applicationContext, LocaleController.getString("LinkCopied", R.string.LinkCopied), Toast.LENGTH_SHORT).show(); + if (exportedMessageLink.link.contains("/c/")) { + Toast.makeText(ApplicationLoader.applicationContext, LocaleController.getString("LinkCopiedPrivate", R.string.LinkCopiedPrivate), Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(ApplicationLoader.applicationContext, LocaleController.getString("LinkCopied", R.string.LinkCopied), Toast.LENGTH_SHORT).show(); + } } catch (Exception e) { FileLog.e(e); } @@ -12019,7 +12778,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not break; } case 25: { - final AlertDialog progressDialog[] = new AlertDialog[] {new AlertDialog(getParentActivity(), 3)}; + final AlertDialog[] progressDialog = new AlertDialog[]{new AlertDialog(getParentActivity(), 3)}; int requestId = SendMessagesHelper.getInstance(currentAccount).sendVote(selectedObject, null, () -> { try { progressDialog[0].dismiss(); @@ -12045,7 +12804,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not builder.setTitle(LocaleController.getString("StopPollAlertTitle", R.string.StopPollAlertTitle)); builder.setMessage(LocaleController.getString("StopPollAlertText", R.string.StopPollAlertText)); builder.setPositiveButton(LocaleController.getString("Stop", R.string.Stop), (dialogInterface, i) -> { - final AlertDialog progressDialog[] = new AlertDialog[] {new AlertDialog(getParentActivity(), 3)}; + final AlertDialog[] progressDialog = new AlertDialog[]{new AlertDialog(getParentActivity(), 3)}; TLRPC.TL_messages_editMessage req = new TLRPC.TL_messages_editMessage(); TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) object.messageOwner.media; TLRPC.TL_inputMediaPoll poll = new TLRPC.TL_inputMediaPoll(); @@ -12122,9 +12881,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selectedMessagesCanStarIds[a].clear(); selectedMessagesIds[a].clear(); } - cantDeleteMessagesCount = 0; - canEditMessagesCount = 0; - actionBar.hideActionMode(); + hideActionMode(); updatePinnedMessageView(true); } @@ -12172,7 +12929,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not moveScrollToLastMessage(); showFieldPanelForForward(true, fmessages); if (AndroidUtilities.isTablet()) { - actionBar.hideActionMode(); + hideActionMode(); updatePinnedMessageView(true); } updateVisibleRows(); @@ -12204,7 +12961,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public boolean onBackPressed() { - if (checkRecordLocked()) { + if (scrimPopupWindow != null) { + scrimPopupWindow.dismiss(); + return false; + } else if (checkRecordLocked()) { return false; } else if (actionBar != null && actionBar.isActionModeShowed()) { for (int a = 1; a >= 0; a--) { @@ -12212,10 +12972,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selectedMessagesCanCopyIds[a].clear(); selectedMessagesCanStarIds[a].clear(); } - actionBar.hideActionMode(); + hideActionMode(); updatePinnedMessageView(true); - cantDeleteMessagesCount = 0; - canEditMessagesCount = 0; updateVisibleRows(); return false; } else if (chatActivityEnterView != null && chatActivityEnterView.isPopupShowing()) { @@ -12247,21 +13005,30 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean disableSelection = false; boolean selected = false; if (actionBar.isActionModeShowed()) { + cell.setCheckBoxVisible(true, true); int idx = messageObject.getDialogId() == dialog_id ? 0 : 1; if (messageObject == editingMessageObject || selectedMessagesIds[idx].indexOfKey(messageObject.getId()) >= 0) { - setCellSelectionBackground(messageObject, cell, idx); + setCellSelectionBackground(messageObject, cell, idx, true); selected = true; } else { - view.setBackgroundDrawable(null); + cell.setDrawSelectionBackground(false); + cell.setChecked(false, false, true); } disableSelection = true; } else { - view.setBackgroundDrawable(null); + cell.setDrawSelectionBackground(false); + cell.setCheckBoxVisible(false, true); + cell.setChecked(false, false, true); } cell.setMessageObject(cell.getMessageObject(), cell.getCurrentMessagesGroup(), cell.isPinnedBottom(), cell.isPinnedTop()); - cell.setCheckPressed(!disableSelection, disableSelection && selected); + if (cell != scrimView) { + cell.setCheckPressed(!disableSelection, disableSelection && selected); + } cell.setHighlighted(highlightMessageId != Integer.MAX_VALUE && messageObject != null && messageObject.getId() == highlightMessageId); + if (highlightMessageId != Integer.MAX_VALUE) { + startMessageUnselect(); + } if (searchContainer != null && searchContainer.getVisibility() == View.VISIBLE && DataQuery.getInstance(currentAccount).isMessageFound(messageObject.getId(), messageObject.getDialogId() == mergeDialogId) && DataQuery.getInstance(currentAccount).getLastSearchQuery() != null) { cell.setHighlightedText(DataQuery.getInstance(currentAccount).getLastSearchQuery()); } else { @@ -12364,7 +13131,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not SendMessagesHelper.getInstance(currentAccount).sendMessage(location, dialog_id, replyingMessageObject, null, null); moveScrollToLastMessage(); if (live == 1) { - hideFieldPanel(); + hideFieldPanel(false); DataQuery.getInstance(currentAccount).cleanDraft(dialog_id, true); } if (paused) { @@ -12400,7 +13167,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return chatInfo; } - public TLRPC.TL_userFull getCurrentUserInfo() { + public TLRPC.UserFull getCurrentUserInfo() { return userInfo; } @@ -12415,16 +13182,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { SendMessagesHelper.prepareSendingVideo(photoEntry.path, 0, 0, 0, 0, null, dialog_id, replyingMessageObject, photoEntry.caption, photoEntry.entities, photoEntry.ttl, editingMessageObject); } - hideFieldPanel(); + hideFieldPanel(false); DataQuery.getInstance(currentAccount).cleanDraft(dialog_id, true); } else { if (photoEntry.imagePath != null) { SendMessagesHelper.prepareSendingPhoto(photoEntry.imagePath, null, dialog_id, replyingMessageObject, photoEntry.caption, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject); - hideFieldPanel(); + hideFieldPanel(false); DataQuery.getInstance(currentAccount).cleanDraft(dialog_id, true); } else if (photoEntry.path != null) { SendMessagesHelper.prepareSendingPhoto(photoEntry.path, null, dialog_id, replyingMessageObject, photoEntry.caption, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject); - hideFieldPanel(); + hideFieldPanel(false); DataQuery.getInstance(currentAccount).cleanDraft(dialog_id, true); } } @@ -12509,7 +13276,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - private void setCellSelectionBackground(MessageObject message, ChatMessageCell messageCell, int idx) { + private void setCellSelectionBackground(MessageObject message, ChatMessageCell messageCell, int idx, boolean animated) { MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); if (groupedMessages != null) { boolean hasUnselected = false; @@ -12523,20 +13290,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not groupedMessages = null; } } - if (groupedMessages == null) { - messageCell.setBackgroundColor(Theme.getColor(Theme.key_chat_selectedBackground)); - } else { - messageCell.setBackground(null); - } + messageCell.setDrawSelectionBackground(groupedMessages == null); + messageCell.setChecked(true, groupedMessages == null, animated); } - private void setItemAnimationsEnabled(boolean enabled){ + private void setItemAnimationsEnabled(boolean enabled) { /*if (chatListView == null) { return; } chatListView.setItemAnimator(enabled ? itemAnimator : null);*/ } + private void updateMessageListAccessibilityVisibility() { + if (currentEncryptedChat != null) + return; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + chatListView.setImportantForAccessibility(mentionContainer.getVisibility()==View.VISIBLE || (scrimPopupWindow!=null && scrimPopupWindow.isShowing()) ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); + } + } + public class ChatActivityAdapter extends RecyclerView.Adapter { private Context mContext; @@ -12646,7 +13418,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not arrayList = new ArrayList<>(); arrayList.add(messageObject); } - showDialog(new ShareAlert(mContext, arrayList, null, ChatObject.isChannel(currentChat) && !currentChat.megagroup && currentChat.username != null && currentChat.username.length() > 0, null, false)); + showDialog(new ShareAlert(mContext, arrayList, null, ChatObject.isChannel(currentChat), null, false) { + @Override + public void dismissInternal() { + super.dismissInternal(); + AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + if (chatActivityEnterView.getVisibility() == View.VISIBLE) { + fragmentView.requestLayout(); + } + } + }); + AndroidUtilities.setAdjustResizeToNothing(getParentActivity(), classGuid); + fragmentView.requestLayout(); } } @@ -12668,9 +13451,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } @Override - public void didPressChannelAvatar(ChatMessageCell cell, TLRPC.Chat chat, int postId) { + public void didPressChannelAvatar(ChatMessageCell cell, TLRPC.Chat chat, int postId, float touchX, float touchY) { if (actionBar.isActionModeShowed()) { - processRowSelect(cell, true); + processRowSelect(cell, true, touchX, touchY); return; } if (chat != null && chat != currentChat) { @@ -12686,20 +13469,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } @Override - public void didPressOther(ChatMessageCell cell) { + public void didPressHiddenForward(ChatMessageCell cell) { + showForwardHint(cell); + } + + @Override + public void didPressOther(ChatMessageCell cell, float otherX, float otherY) { if (cell.getMessageObject().type == 16) { if (currentUser != null) { VoIPHelper.startCall(currentUser, getParentActivity(), MessagesController.getInstance(currentAccount).getUserFull(currentUser.id)); } } else { - createMenu(cell, true, false, false); + createMenu(cell, true, false, otherX, otherY, false); } } @Override - public void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user) { + public void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user, float touchX, float touchY) { if (actionBar.isActionModeShowed()) { - processRowSelect(cell, true); + processRowSelect(cell, true, touchX, touchY); return; } if (user != null && user.id != UserConfig.getInstance(currentAccount).getClientUserId()) { @@ -12736,8 +13524,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } @Override - public void didLongPress(ChatMessageCell cell) { - createMenu(cell, false, false); + public void didLongPress(ChatMessageCell cell, float x, float y) { + createMenu(cell, false, false, x, y); } @Override @@ -12793,7 +13581,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (URLSpanBotCommand.enabled) { chatActivityEnterView.setCommand(messageObject, str, longPress, currentChat != null && currentChat.megagroup); if (!longPress && chatActivityEnterView.getFieldText() == null) { - hideFieldPanel(); + hideFieldPanel(false); } } } @@ -12823,7 +13611,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageObject.messageOwner.media.webpage != null && messageObject.messageOwner.media.webpage.cached_page != null) { String lowerUrl = urlFinal.toLowerCase(); String lowerUrl2 = messageObject.messageOwner.media.webpage.url.toLowerCase(); - if ((lowerUrl.contains("telegra.ph") || lowerUrl.contains("t.me/iv")) && (lowerUrl.contains(lowerUrl2) || lowerUrl2.contains(lowerUrl))) { + if ((lowerUrl.contains("telegram.org/blog") || lowerUrl.contains("telegra.ph") || lowerUrl.contains("t.me/iv")) && (lowerUrl.contains(lowerUrl2) || lowerUrl2.contains(lowerUrl))) { ArticleViewer.getInstance().setParentActivity(getParentActivity(), ChatActivity.this); ArticleViewer.getInstance().open(messageObject); return; @@ -12864,10 +13652,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } @Override - public void didPressImage(ChatMessageCell cell) { + public void didPressImage(ChatMessageCell cell, float x, float y) { MessageObject message = cell.getMessageObject(); if (message.isSendError()) { - createMenu(cell, false, false); + createMenu(cell, false, false, x, y); return; } else if (message.isSending()) { return; @@ -12888,7 +13676,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject playingObject = MediaController.getInstance().getPlayingMessageObject(); if (playingObject != null && playingObject.isVideo()) { FileLoader.getInstance(currentAccount).setLoadingVideoForPlayer(playingObject.getDocument(), false); - if (playingObject == message) { + if (playingObject.equals(message)) { AnimatedFileDrawable animation = cell.getPhotoImage().getAnimation(); if (animation != null && videoTextureView != null && videoPlayerContainer.getTag() != null) { Bitmap bitmap = animation.getAnimatedBitmap(); @@ -12904,7 +13692,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } - MediaController.getInstance().cleanupPlayer(true, true, false, playingObject == 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)) { PhotoViewer.getInstance().setParentChatActivity(ChatActivity.this); @@ -12912,6 +13700,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (noSoundHintView != null) { noSoundHintView.hide(); } + if (forwardHintView != null) { + forwardHintView.hide(); + } MediaController.getInstance().resetGoingToShowMessageObject(); } else if (message.type == 3) { sendSecretMessageRead(message); @@ -13036,7 +13827,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not view = new ChatActionCell(mContext); ((ChatActionCell) view).setDelegate(new ChatActionCell.ChatActionCellDelegate() { @Override - public void didClickedImage(ChatActionCell cell) { + public void didClickImage(ChatActionCell cell) { MessageObject message = cell.getMessageObject(); PhotoViewer.getInstance().setParentActivity(getParentActivity()); TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(message.photoThumbs, 640); @@ -13048,8 +13839,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } @Override - public void didLongPressed(ChatActionCell cell) { - createMenu(cell, false, false); + public void didLongPress(ChatActionCell cell, float x, float y) { + createMenu(cell, false, false, x, y); } @Override @@ -13073,13 +13864,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } @Override - public void didPressedReplyMessage(ChatActionCell cell, int id) { + public void didPressReplyMessage(ChatActionCell cell, int id) { MessageObject messageObject = cell.getMessageObject(); scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, false); } @Override - public void didPressedBotButton(MessageObject messageObject, TLRPC.KeyboardButton button) { + public void didPressBotButton(MessageObject messageObject, TLRPC.KeyboardButton button) { if (getParentActivity() == null || bottomOverlayChat.getVisibility() == View.VISIBLE && !(button instanceof TLRPC.TL_keyboardButtonSwitchInline) && !(button instanceof TLRPC.TL_keyboardButtonCallback) && !(button instanceof TLRPC.TL_keyboardButtonGame) && !(button instanceof TLRPC.TL_keyboardButtonUrl) && @@ -13103,7 +13894,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (url.startsWith("/")) { chatActivityEnterView.setCommand(null, url, false, false); if (chatActivityEnterView.getFieldText() == null) { - hideFieldPanel(); + hideFieldPanel(false); } } }); @@ -13184,12 +13975,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } messageCell.setMessageObject(message, groupedMessages, pinnedBottom, pinnedTop); - messageCell.setHighlighted(highlightMessageId != Integer.MAX_VALUE && message.getId() == highlightMessageId); - if (searchContainer != null && searchContainer.getVisibility() == View.VISIBLE && DataQuery.getInstance(currentAccount).isMessageFound(message.getId(), message.getDialogId() == mergeDialogId) && DataQuery.getInstance(currentAccount).getLastSearchQuery() != null) { - messageCell.setHighlightedText(DataQuery.getInstance(currentAccount).getLastSearchQuery()); - } else { - messageCell.setHighlightedText(null); + if (highlightMessageId != Integer.MAX_VALUE) { + startMessageUnselect(); } int index; if ((index = animatingMessageObjects.indexOf(message)) != -1) { @@ -13207,7 +13995,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int w = imageReceiver.getImageWidth(); org.telegram.ui.Components.Rect rect = instantCameraView.getCameraRect(); float scale = w / rect.width; - int position[] = new int[2]; + int[] position = new int[2]; messageCell.setAlpha(0.0f); messageCell.setTimeAlpha(0.0f); messageCell.getLocationOnScreen(position); @@ -13218,14 +14006,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not cameraContainer.setPivotY(0.0f); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether( - ObjectAnimator.ofFloat(instantCameraView, "alpha", 0.0f), - ObjectAnimator.ofFloat(cameraContainer, "scaleX", scale), - ObjectAnimator.ofFloat(cameraContainer, "scaleY", scale), - ObjectAnimator.ofFloat(cameraContainer, "translationX", position[0] - rect.x), - ObjectAnimator.ofFloat(cameraContainer, "translationY", position[1] - rect.y), - ObjectAnimator.ofFloat(instantCameraView.getSwitchButtonView(), "alpha", 0.0f), - ObjectAnimator.ofInt(instantCameraView.getPaint(), "alpha", 0), - ObjectAnimator.ofFloat(instantCameraView.getMuteImageView(), "alpha", 0.0f)); + ObjectAnimator.ofFloat(instantCameraView, View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(cameraContainer, View.SCALE_X, scale), + ObjectAnimator.ofFloat(cameraContainer, View.SCALE_Y, scale), + ObjectAnimator.ofFloat(cameraContainer, View.TRANSLATION_X, position[0] - rect.x), + ObjectAnimator.ofFloat(cameraContainer, View.TRANSLATION_Y, position[1] - rect.y), + ObjectAnimator.ofFloat(instantCameraView.getSwitchButtonView(), View.ALPHA, 0.0f), + ObjectAnimator.ofInt(instantCameraView.getPaint(), AnimationProperties.PAINT_ALPHA, 0), + ObjectAnimator.ofFloat(instantCameraView.getMuteImageView(), View.ALPHA, 0.0f)); animatorSet.setDuration(180); animatorSet.setInterpolator(new DecelerateInterpolator()); animatorSet.addListener(new AnimatorListenerAdapter() { @@ -13300,20 +14088,30 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean selected = false; boolean disableSelection = false; if (actionBar.isActionModeShowed()) { + messageCell.setCheckBoxVisible(true, false); MessageObject messageObject = chatActivityEnterView != null ? chatActivityEnterView.getEditingMessageObject() : null; int idx = message.getDialogId() == dialog_id ? 0 : 1; if (messageObject == message || selectedMessagesIds[idx].indexOfKey(message.getId()) >= 0) { - setCellSelectionBackground(message, messageCell, idx); + setCellSelectionBackground(message, messageCell, idx, false); selected = true; } else { - messageCell.setBackgroundDrawable(null); + messageCell.setDrawSelectionBackground(false); + messageCell.setChecked(false, false, false); } disableSelection = true; } else { - messageCell.setBackgroundDrawable(null); + messageCell.setDrawSelectionBackground(false); + messageCell.setChecked(false, false, false); + messageCell.setCheckBoxVisible(false, false); } messageCell.setCheckPressed(!disableSelection, disableSelection && selected); + if (searchContainer != null && searchContainer.getVisibility() == View.VISIBLE && DataQuery.getInstance(currentAccount).isMessageFound(message.getId(), message.getDialogId() == mergeDialogId) && DataQuery.getInstance(currentAccount).getLastSearchQuery() != null) { + messageCell.setHighlightedText(DataQuery.getInstance(currentAccount).getLastSearchQuery()); + } else { + messageCell.setHighlightedText(null); + } + messageCell.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { @@ -13334,6 +14132,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); if (!inPreviewMode || !messageCell.isHighlighted()) { messageCell.setHighlighted(highlightMessageId != Integer.MAX_VALUE && messageCell.getMessageObject().getId() == highlightMessageId); + if (highlightMessageId != Integer.MAX_VALUE) { + startMessageUnselect(); + } } } @@ -13348,7 +14149,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (newMentionsCount <= 0) { newMentionsCount = 0; hasAllMentionsLocal = true; - showMentiondownButton(false, true); + showMentionDownButton(false, true); } else { mentiondownButtonCounter.setText(String.format("%d", newMentionsCount)); } @@ -13357,10 +14158,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (view instanceof ChatMessageCell) { + ChatMessageCell messageCell = (ChatMessageCell) view; if (inPreviewMode) { - ((ChatMessageCell) view).setHighlighted(true); + messageCell.setHighlighted(true); } else { - ((ChatMessageCell) view).setHighlightedAnimated(); + messageCell.setHighlightedAnimated(); } } } @@ -13494,8 +14296,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatActivityEnterView != null && chatActivityEnterView.getEmojiView() != null) { chatActivityEnterView.getEmojiView().updateUIColors(); } - }; - ThemeDescription.ThemeDescriptionDelegate attachAlertDelegate = () -> { if (chatAttachAlert != null) { chatAttachAlert.checkColors(); } @@ -13509,11 +14309,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUBACKGROUND, null, null, null, null, Theme.key_actionBarDefaultSubmenuBackground), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM, null, null, null, null, Theme.key_actionBarDefaultSubmenuItem), + new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubmenuItemIcon), 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), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon), new ThemeDescription(avatarContainer != null ? avatarContainer.getTitleTextView() : null, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle), + new ThemeDescription(avatarContainer != null ? avatarContainer.getTitleTextView() : null, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubtitle), new ThemeDescription(avatarContainer != null ? avatarContainer.getSubtitleTextView() : null, 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(actionBar, ThemeDescription.FLAG_AB_SEARCH, null, null, null, null, Theme.key_actionBarDefaultSearch), @@ -13726,6 +14528,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not new ThemeDescription(bottomOverlay, 0, null, null, new Drawable[]{Theme.chat_composeShadowDrawable}, null, Theme.key_chat_messagePanelShadow), new ThemeDescription(bottomOverlayChat, 0, null, Theme.chat_composeBackgroundPaint, null, null, Theme.key_chat_messagePanelBackground), new ThemeDescription(bottomOverlayChat, 0, null, null, new Drawable[]{Theme.chat_composeShadowDrawable}, null, Theme.key_chat_messagePanelShadow), + new ThemeDescription(bottomMessagesActionContainer, 0, null, Theme.chat_composeBackgroundPaint, null, null, Theme.key_chat_messagePanelBackground), + new ThemeDescription(bottomMessagesActionContainer, 0, null, null, new Drawable[]{Theme.chat_composeShadowDrawable}, null, Theme.key_chat_messagePanelShadow), new ThemeDescription(chatActivityEnterView, 0, null, Theme.chat_composeBackgroundPaint, null, null, Theme.key_chat_messagePanelBackground), new ThemeDescription(chatActivityEnterView, 0, null, null, new Drawable[]{Theme.chat_composeShadowDrawable}, null, Theme.key_chat_messagePanelShadow), @@ -13740,7 +14544,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not 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, new Class[]{ChatActivityEnterView.class}, new String[]{"doneButtonImage"}, null, null, null, Theme.key_chat_editDoneIcon), + 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, 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), new ThemeDescription(chatActivityEnterView, 0, new Class[]{ChatActivityEnterView.class}, new String[]{"cameraDrawable"}, null, null, null, Theme.key_chat_messagePanelVoicePressed), @@ -13778,12 +14583,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelIcon), new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelIconSelected), new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelStickerPackSelector), - new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelIconSelector), new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelBackspace), new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelTrendingTitle), new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelTrendingDescription), new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelBadgeText), new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelBadgeBackground), + new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiBottomPanelIcon), + new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiSearchIcon), + new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelStickerSetNameHighlight), + new ThemeDescription(chatActivityEnterView != null ? chatActivityEnterView.getEmojiView() : chatActivityEnterView, 0, new Class[]{EmojiView.class}, null, null, null, selectedBackgroundDelegate, Theme.key_chat_emojiPanelStickerPackSelectorLine), new ThemeDescription(undoView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_undo_background), new ThemeDescription(undoView, 0, new Class[]{UndoView.class}, new String[]{"undoImageView"}, null, null, null, Theme.key_undo_cancelColor), @@ -13791,6 +14599,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not new ThemeDescription(undoView, 0, new Class[]{UndoView.class}, new String[]{"infoTextView"}, null, null, null, Theme.key_undo_infoColor), new ThemeDescription(undoView, 0, new Class[]{UndoView.class}, new String[]{"textPaint"}, null, null, null, Theme.key_undo_infoColor), new ThemeDescription(undoView, 0, new Class[]{UndoView.class}, new String[]{"progressPaint"}, null, null, null, Theme.key_undo_infoColor), + new ThemeDescription(undoView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{UndoView.class}, new String[]{"leftImageView"}, null, null, null, Theme.key_undo_infoColor), new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_botKeyboardButtonText), new ThemeDescription(null, 0, null, null, null, null, Theme.key_chat_botKeyboardButtonBackground), @@ -13869,10 +14678,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not new ThemeDescription(gifHintTextView, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chat_gifSaveHintBackground), new ThemeDescription(gifHintTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_gifSaveHintText), - new ThemeDescription(noSoundHintView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{NoSoundHintView.class}, new String[]{"usernameTextView"}, null, null, null, Theme.key_chat_gifSaveHintText), - new ThemeDescription(noSoundHintView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{NoSoundHintView.class}, new String[]{"imageView"}, null, null, null, Theme.key_chat_gifSaveHintText), - new ThemeDescription(noSoundHintView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{NoSoundHintView.class}, new String[]{"usernameTextView"}, null, null, null, Theme.key_chat_gifSaveHintBackground), - new ThemeDescription(noSoundHintView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{NoSoundHintView.class}, new String[]{"arrowImageView"}, null, null, null, Theme.key_chat_gifSaveHintBackground), + new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachMediaBanBackground), + new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_chat_attachMediaBanText), + + new ThemeDescription(noSoundHintView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{HintView.class}, new String[]{"textView"}, null, null, null, Theme.key_chat_gifSaveHintText), + new ThemeDescription(noSoundHintView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{HintView.class}, new String[]{"imageView"}, null, null, null, Theme.key_chat_gifSaveHintText), + new ThemeDescription(noSoundHintView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{HintView.class}, new String[]{"arrowImageView"}, null, null, null, Theme.key_chat_gifSaveHintBackground), + + new ThemeDescription(forwardHintView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{HintView.class}, new String[]{"textView"}, null, null, null, Theme.key_chat_gifSaveHintText), + new ThemeDescription(forwardHintView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{HintView.class}, new String[]{"arrowImageView"}, null, null, null, Theme.key_chat_gifSaveHintBackground), new ThemeDescription(pagedownButtonCounter, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chat_goDownButtonCounterBackground), new ThemeDescription(pagedownButtonCounter, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_goDownButtonCounter), @@ -13921,12 +14735,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not //new ThemeDescription(null, 0, null, null, new Drawable[]{Theme.chat_attachButtonDrawables[7]}, null, Theme.key_chat_attachSendBackgroundPressed), new ThemeDescription(null, 0, null, null, new Drawable[]{Theme.chat_attachButtonDrawables[8]}, null, Theme.key_chat_attachSendIcon), - new ThemeDescription(null, 0, null, null, null, attachAlertDelegate, Theme.key_dialogBackground), - new ThemeDescription(null, 0, null, null, null, attachAlertDelegate, Theme.key_dialogBackgroundGray), - new ThemeDescription(null, 0, null, null, null, attachAlertDelegate, Theme.key_dialogTextGray2), - new ThemeDescription(null, 0, null, null, null, attachAlertDelegate, Theme.key_dialogScrollGlow), - new ThemeDescription(null, 0, null, null, null, attachAlertDelegate, Theme.key_dialogGrayLine), - new ThemeDescription(null, 0, null, null, null, attachAlertDelegate, Theme.key_dialogCameraIcon), + new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_dialogBackground), + new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_dialogBackgroundGray), + new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_dialogTextGray2), + new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_dialogScrollGlow), + new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_dialogGrayLine), + new ThemeDescription(null, 0, null, null, null, selectedBackgroundDelegate, Theme.key_dialogCameraIcon), }; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java index 6b11fa25d..712af647b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java @@ -12,7 +12,6 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; -import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Canvas; @@ -38,6 +37,7 @@ import android.widget.ScrollView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; import org.telegram.messenger.FileLog; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; @@ -242,6 +242,8 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image SizeNotifierFrameLayout sizeNotifierFrameLayout = new SizeNotifierFrameLayout(context) { + private boolean ignoreLayout; + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSize = MeasureSpec.getSize(widthMeasureSpec); @@ -253,8 +255,13 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image measureChildWithMargins(actionBar, widthMeasureSpec, 0, heightMeasureSpec, 0); int keyboardSize = getKeyboardHeight(); - int childCount = getChildCount(); + if (keyboardSize > AndroidUtilities.dp(20)) { + ignoreLayout = true; + nameTextView.hideEmojiView(); + ignoreLayout = false; + } + int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); if (child == null || child.getVisibility() == GONE || child == actionBar) { @@ -342,6 +349,14 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image notifyHeightChanged(); } + + @Override + public void requestLayout() { + if (ignoreLayout) { + return; + } + super.requestLayout(); + } }; sizeNotifierFrameLayout.setOnTouchListener((v, event) -> true); fragmentView = sizeNotifierFrameLayout; @@ -407,8 +422,9 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image avatarBig = null; uploadedAvatar = null; showAvatarProgress(false, true); - avatarImage.setImage(avatar, "50_50", avatarDrawable, currentChat); + avatarImage.setImage(null, null, avatarDrawable, currentChat); })); + avatarOverlay.setContentDescription(LocaleController.getString("ChoosePhoto", R.string.ChoosePhoto)); avatarEditor = new ImageView(context) { @Override @@ -439,7 +455,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image avatarDrawable.setInfo(5, currentChat.title, null, false); } - nameTextView = new EditTextEmoji((Activity) context, sizeNotifierFrameLayout, this); + nameTextView = new EditTextEmoji(context, sizeNotifierFrameLayout, this, EditTextEmoji.STYLE_FRAGMENT); if (isChannel) { nameTextView.setHint(LocaleController.getString("EnterChannelName", R.string.EnterChannelName)); } else { @@ -584,6 +600,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image ActionBarMenu menu = actionBar.createMenu(); if (ChatObject.canChangeChatInfo(currentChat) || signCell != null || historyCell != null) { doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)); + doneButton.setContentDescription(LocaleController.getString("Done", R.string.Done)); } if (signCell != null || historyCell != null || typeCell != null) { @@ -687,16 +704,20 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image deleteCell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); if (isChannel) { deleteCell.setText(LocaleController.getString("ChannelDelete", R.string.ChannelDelete), false); - } else { + } else if (currentChat.megagroup) { deleteCell.setText(LocaleController.getString("DeleteMega", R.string.DeleteMega), false); + } else { + deleteCell.setText(LocaleController.getString("DeleteAndExitButton", R.string.DeleteAndExitButton), false); } deleteContainer.addView(deleteCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); deleteCell.setOnClickListener(v -> { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); if (isChannel) { builder.setMessage(LocaleController.getString("ChannelDeleteAlert", R.string.ChannelDeleteAlert)); - } else { + } else if (currentChat.megagroup) { builder.setMessage(LocaleController.getString("MegaDeleteAlert", R.string.MegaDeleteAlert)); + } else { + builder.setMessage(LocaleController.getString("AreYouSureDeleteAndExit", R.string.AreYouSureDeleteAndExit)); } builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> { @@ -705,7 +726,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } else { NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats); } - MessagesController.getInstance(currentAccount).deleteUserFromChat(chatId, MessagesController.getInstance(currentAccount).getUser(UserConfig.getInstance(currentAccount).getClientUserId()), info, true); + MessagesController.getInstance(currentAccount).deleteUserFromChat(chatId, MessagesController.getInstance(currentAccount).getUser(UserConfig.getInstance(currentAccount).getClientUserId()), info, true, false); finishFragment(); }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); @@ -739,7 +760,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image if (currentChat.photo != null) { avatar = currentChat.photo.photo_small; avatarBig = currentChat.photo.photo_big; - avatarImage.setImage(avatar, "50_50", avatarDrawable, currentChat); + avatarImage.setImage(ImageLocation.getForChat(currentChat, false), "50_50", avatarDrawable, currentChat); } else { avatarImage.setImageDrawable(avatarDrawable); } @@ -785,7 +806,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } else { avatar = smallSize.location; avatarBig = bigSize.location; - avatarImage.setImage(avatar, "50_50", avatarDrawable, currentChat); + avatarImage.setImage(ImageLocation.getForLocal(avatar), "50_50", avatarDrawable, currentChat); showAvatarProgress(true, false); } }); @@ -835,7 +856,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } private void processDone() { - if (donePressed) { + if (donePressed || nameTextView == null) { return; } if (nameTextView.length() == 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java index 0e6f84eed..f7b01e3b0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java @@ -28,8 +28,6 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; @@ -52,6 +50,9 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.Calendar; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class ChatRightsEditActivity extends BaseFragment { private ListAdapter listViewAdapter; @@ -294,7 +295,7 @@ public class ChatRightsEditActivity extends BaseFragment { if (canEdit) { ActionBarMenu menu = actionBar.createMenu(); - menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)); + menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); } fragmentView = new FrameLayout(context); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java index 50e4e990c..f8412f207 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java @@ -40,8 +40,6 @@ import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; @@ -71,6 +69,9 @@ import java.util.HashMap; import java.util.Timer; import java.util.TimerTask; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class ChatUsersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListAdapter listViewAdapter; @@ -87,7 +88,13 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente private String initialBannedRights; private TLRPC.TL_chatBannedRights defaultBannedRights = new TLRPC.TL_chatBannedRights(); private ArrayList participants = new ArrayList<>(); + private ArrayList bots = new ArrayList<>(); + private ArrayList contacts = new ArrayList<>(); + private boolean botsEndReached; + private boolean contactsEndReached; private SparseArray participantsMap = new SparseArray<>(); + private SparseArray botsMap = new SparseArray<>(); + private SparseArray contactsMap = new SparseArray<>(); private int chatId; private int type; private boolean loadingUsers; @@ -114,11 +121,21 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente private int participantsDividerRow; private int participantsDivider2Row; + private int contactsHeaderRow; + private int contactsStartRow; + private int contactsEndRow; + private int botHeaderRow; + private int botStartRow; + private int botEndRow; + private int membersHeaderRow; + private int participantsInfoRow; private int blockedEmptyRow; private int rowCount; private int selectType; + private int delayResults; + private ChatUsersActivityDelegate delegate; private boolean needOpenSearch; @@ -189,6 +206,13 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente pinMessagesRow = -1; changeInfoRow = -1; removedUsersRow = -1; + contactsHeaderRow = -1; + contactsStartRow = -1; + contactsEndRow = -1; + botHeaderRow = -1; + botStartRow = -1; + botEndRow = -1; + membersHeaderRow = -1; rowCount = 0; if (type == TYPE_KICKED) { @@ -258,13 +282,31 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente participantsInfoRow = rowCount++; } else if (type == TYPE_USERS) { if (selectType == 0 && ChatObject.canAddUsers(currentChat)) { - if (ChatObject.canUserDoAdminAction(currentChat, ChatObject.ACTION_INVITE) && (!ChatObject.isChannel(currentChat) || currentChat.megagroup || TextUtils.isEmpty(currentChat.username))) { + /*if (ChatObject.canUserDoAdminAction(currentChat, ChatObject.ACTION_INVITE) && (!ChatObject.isChannel(currentChat) || currentChat.megagroup || TextUtils.isEmpty(currentChat.username))) { addNew2Row = rowCount++; addNewSectionRow = rowCount++; - } + }*/ addNewRow = rowCount++; } + boolean hasAnyOther = false; + if (!contacts.isEmpty()) { + contactsHeaderRow = rowCount++; + contactsStartRow = rowCount; + rowCount += contacts.size(); + contactsEndRow = rowCount; + hasAnyOther = true; + } + if (!bots.isEmpty()) { + botHeaderRow = rowCount++; + botStartRow = rowCount; + rowCount += bots.size(); + botEndRow = rowCount; + hasAnyOther = true; + } if (!participants.isEmpty()) { + if (hasAnyOther) { + membersHeaderRow = rowCount++; + } participantsStartRow = rowCount; rowCount += participants.size(); participantsEndRow = rowCount; @@ -273,9 +315,6 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente participantsInfoRow = rowCount++; } } - if (searchItem != null && !actionBar.isSearchFieldVisible()) { - searchItem.setVisibility(selectType == 0 && participants.isEmpty() ? View.GONE : View.VISIBLE); - } } @Override @@ -385,10 +424,9 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } else { searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); } - searchItem.setVisibility(selectType == 0 && participants.isEmpty() ? View.GONE : View.VISIBLE); if (type == TYPE_KICKED) { - doneItem = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)); + doneItem = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); } } @@ -400,6 +438,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente if (type == TYPE_BANNED || type == TYPE_USERS || type == TYPE_KICKED) { emptyView.setText(LocaleController.getString("NoResult", R.string.NoResult)); } + emptyView.setShowAtCenter(true); frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); listView = new RecyclerListView(context); @@ -456,10 +495,8 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente args.putString("selectAlertString", LocaleController.getString("ChannelAddTo", R.string.ChannelAddTo)); args.putInt("channelId", currentChat.id); } else { - if (!ChatObject.isChannel(currentChat)) { - args.putInt("chat_id", currentChat.id); - } args.putString("selectAlertString", LocaleController.getString("AddToTheGroup", R.string.AddToTheGroup)); + args.putInt("chat_id", currentChat.id); } ContactsActivity fragment = new ContactsActivity(args); fragment.setDelegate((user, param, activity) -> { @@ -605,7 +642,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente if (object instanceof TLRPC.User) { TLRPC.User user = (TLRPC.User) object; MessagesController.getInstance(currentAccount).putUser(user, false); - participant = participantsMap.get(user_id = user.id); + participant = getAnyParticipant(user_id = user.id); } else if (object instanceof TLRPC.ChannelParticipant || object instanceof TLRPC.ChatParticipant) { participant = object; } else { @@ -636,7 +673,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente if (user_id != 0) { if (selectType != 0) { if (selectType == 3 || selectType == 1) { - if (canEditAdmin && (participant instanceof TLRPC.TL_channelParticipantAdmin || participant instanceof TLRPC.TL_chatParticipantAdmin)) { + if (selectType != 1 && canEditAdmin && (participant instanceof TLRPC.TL_channelParticipantAdmin || participant instanceof TLRPC.TL_chatParticipantAdmin)) { final TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(user_id); final TLRPC.TL_chatBannedRights br = bannedRights; final TLRPC.TL_chatAdminRights ar = adminRights; @@ -661,6 +698,9 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente canEdit = ChatObject.canBlockUsers(currentChat); } if (type == TYPE_BANNED || type != TYPE_ADMIN && isChannel || type == TYPE_USERS && selectType == 0) { + if (user_id == getUserConfig().getClientUserId()) { + return; + } Bundle args = new Bundle(); args.putInt("user_id", user_id); presentFragment(new ProfileActivity(args)); @@ -686,12 +726,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente TLRPC.ChannelParticipant channelParticipant = (TLRPC.ChannelParticipant) participant; channelParticipant.admin_rights = rightsAdmin; channelParticipant.banned_rights = rightsBanned; - TLObject p = participantsMap.get(channelParticipant.user_id); - if (p instanceof TLRPC.ChannelParticipant) { - channelParticipant = (TLRPC.ChannelParticipant) p; - channelParticipant.admin_rights = rightsAdmin; - channelParticipant.banned_rights = rightsBanned; - } + updateParticipantWithRights(channelParticipant, rightsAdmin, rightsBanned, 0, false); } }); presentFragment(fragment); @@ -705,7 +740,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente listView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - if (newState == RecyclerView.SCROLL_STATE_DRAGGING && searching && searchWas) { + if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); } } @@ -769,18 +804,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } } else if (type == 1) { if (rights == 0) { - for (int a = 0; a < participants.size(); a++) { - TLObject p = participants.get(a); - if (p instanceof TLRPC.ChannelParticipant) { - TLRPC.ChannelParticipant p2 = (TLRPC.ChannelParticipant) p; - if (p2.user_id == userId) { - participants.remove(a); - updateRows(); - listViewAdapter.notifyDataSetChanged(); - break; - } - } - } + removeParticipants(userId); } } }); @@ -794,16 +818,6 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente TLRPC.ChannelParticipant channelParticipant = (TLRPC.ChannelParticipant) participant; channelParticipant.admin_rights = rightsAdmin; channelParticipant.banned_rights = rightsBanned; - TLObject p = participantsMap.get(channelParticipant.user_id); - if (p instanceof TLRPC.ChannelParticipant) { - channelParticipant = (TLRPC.ChannelParticipant) p; - channelParticipant.admin_rights = rightsAdmin; - channelParticipant.banned_rights = rightsBanned; - channelParticipant.promoted_by = UserConfig.getInstance(currentAccount).getClientUserId(); - } - if (delegate != null) { - delegate.didAddParticipantToList(user_id, p); - } } removeSelfFromStack(); }); @@ -819,6 +833,91 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente finishFragment(); } + private TLObject getAnyParticipant(int userId) { + boolean updated = false; + for (int a = 0; a < 3; a++) { + SparseArray map; + ArrayList arrayList; + if (a == 0) { + map = contactsMap; + } else if (a == 1) { + map = botsMap; + } else { + map = participantsMap; + } + TLObject p = map.get(userId); + if (p != null) { + return p; + } + } + return null; + } + + private void removeParticipants(TLObject object) { + if (object instanceof TLRPC.ChatParticipant) { + TLRPC.ChatParticipant chatParticipant = (TLRPC.ChatParticipant) object; + removeParticipants(chatParticipant.user_id); + } else if (object instanceof TLRPC.ChannelParticipant) { + TLRPC.ChannelParticipant channelParticipant = (TLRPC.ChannelParticipant) object; + removeParticipants(channelParticipant.user_id); + } + } + + private void removeParticipants(int userId) { + boolean updated = false; + for (int a = 0; a < 3; a++) { + SparseArray map; + ArrayList arrayList; + if (a == 0) { + map = contactsMap; + arrayList = contacts; + } else if (a == 1) { + map = botsMap; + arrayList = bots; + } else { + map = participantsMap; + arrayList = participants; + } + TLObject p = map.get(userId); + if (p != null) { + map.remove(userId); + arrayList.remove(p); + updated = true; + } + } + if (updated) { + updateRows(); + listViewAdapter.notifyDataSetChanged(); + } + } + + private void updateParticipantWithRights(TLRPC.ChannelParticipant channelParticipant, TLRPC.TL_chatAdminRights rightsAdmin, TLRPC.TL_chatBannedRights rightsBanned, int user_id, boolean withDelegate) { + boolean delegateCalled = false; + for (int a = 0; a < 3; a++) { + SparseArray map; + if (a == 0) { + map = contactsMap; + } else if (a == 1) { + map = botsMap; + } else { + map = participantsMap; + } + TLObject p = map.get(channelParticipant.user_id); + if (p instanceof TLRPC.ChannelParticipant) { + channelParticipant = (TLRPC.ChannelParticipant) p; + channelParticipant.admin_rights = rightsAdmin; + channelParticipant.banned_rights = rightsBanned; + if (withDelegate) { + channelParticipant.promoted_by = UserConfig.getInstance(currentAccount).getClientUserId(); + } + } + if (withDelegate && p != null && !delegateCalled && delegate != null) { + delegateCalled = true; + delegate.didAddParticipantToList(user_id, p); + } + } + } + private boolean createMenuForParticipant(final TLObject participant, boolean resultOnly) { if (participant == null || selectType != 0) { return false; @@ -908,18 +1007,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente builder.setItems(items.toArray(new CharSequence[actions.size()]), AndroidUtilities.toIntArray(icons), (dialogInterface, i) -> { if (actions.get(i) == 2) { MessagesController.getInstance(currentAccount).deleteUserFromChat(chatId, user, null); - for (int a = 0; a < participants.size(); a++) { - TLObject p = participants.get(a); - if (p instanceof TLRPC.ChannelParticipant) { - TLRPC.ChannelParticipant p2 = (TLRPC.ChannelParticipant) p; - if (p2.user_id == userId) { - participants.remove(a); - updateRows(); - listViewAdapter.notifyDataSetChanged(); - break; - } - } - } + removeParticipants(userId); if (searchItem != null && actionBar.isSearchFieldVisible()) { actionBar.closeSearchField(); } @@ -994,48 +1082,28 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente if (i == 0 && items.length == 2) { ChatRightsEditActivity fragment = new ChatRightsEditActivity(userId, chatId, adminRights, null, null, ChatRightsEditActivity.TYPE_ADMIN, true, false); fragment.setDelegate((rights, rightsAdmin, rightsBanned) -> { - if (participant != null) { - if (participant instanceof TLRPC.ChannelParticipant) { - TLRPC.ChannelParticipant channelParticipant = (TLRPC.ChannelParticipant) participant; - channelParticipant.admin_rights = rightsAdmin; - channelParticipant.banned_rights = rightsBanned; - } - TLObject p = participantsMap.get(userId); - if (p instanceof TLRPC.ChannelParticipant) { - TLRPC.ChannelParticipant channelParticipant = (TLRPC.ChannelParticipant) p; - channelParticipant.admin_rights = rightsAdmin; - channelParticipant.banned_rights = rightsBanned; - } + if (participant instanceof TLRPC.ChannelParticipant) { + TLRPC.ChannelParticipant channelParticipant = (TLRPC.ChannelParticipant) participant; + channelParticipant.admin_rights = rightsAdmin; + channelParticipant.banned_rights = rightsBanned; + updateParticipantWithRights(channelParticipant, rightsAdmin, rightsBanned, 0, false); } }); presentFragment(fragment); } else { MessagesController.getInstance(currentAccount).setUserAdminRole(chatId, MessagesController.getInstance(currentAccount).getUser(userId), new TLRPC.TL_chatAdminRights(), !isChannel, ChatUsersActivity.this, false); - TLObject p = participantsMap.get(userId); - if (p != null) { - participantsMap.remove(userId); - participants.remove(p); - updateRows(); - listViewAdapter.notifyDataSetChanged(); - } + removeParticipants(userId); } } else if (type == TYPE_BANNED || type == TYPE_KICKED) { if (i == 0) { if (type == TYPE_KICKED) { ChatRightsEditActivity fragment = new ChatRightsEditActivity(userId, chatId, null, defaultBannedRights, bannedRights, ChatRightsEditActivity.TYPE_BANNED, true, false); fragment.setDelegate((rights, rightsAdmin, rightsBanned) -> { - if (participant != null) { - if (participant instanceof TLRPC.ChannelParticipant) { - TLRPC.ChannelParticipant channelParticipant = (TLRPC.ChannelParticipant) participant; - channelParticipant.admin_rights = rightsAdmin; - channelParticipant.banned_rights = rightsBanned; - } - TLObject p = participantsMap.get(userId); - if (p instanceof TLRPC.ChannelParticipant) { - TLRPC.ChannelParticipant channelParticipant = (TLRPC.ChannelParticipant) p; - channelParticipant.admin_rights = rightsAdmin; - channelParticipant.banned_rights = rightsBanned; - } + if (participant instanceof TLRPC.ChannelParticipant) { + TLRPC.ChannelParticipant channelParticipant = (TLRPC.ChannelParticipant) participant; + channelParticipant.admin_rights = rightsAdmin; + channelParticipant.banned_rights = rightsBanned; + updateParticipantWithRights(channelParticipant, rightsAdmin, rightsBanned, 0, false); } }); presentFragment(fragment); @@ -1065,9 +1133,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } } if (i == 0 && type == TYPE_BANNED || i == 1) { - participants.remove(participant); - updateRows(); - listViewAdapter.notifyDataSetChanged(); + removeParticipants(participant); } } else { if (i == 0) { @@ -1223,10 +1289,20 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente if (loadingUsers) { return; } + contactsEndReached = false; + botsEndReached = false; + loadChatParticipants(offset, count, true); + } + + private void loadChatParticipants(int offset, int count, boolean reset) { if (!ChatObject.isChannel(currentChat)) { loadingUsers = false; participants.clear(); + bots.clear(); + contacts.clear(); participantsMap.clear(); + contactsMap.clear(); + botsMap.clear(); if (type == TYPE_ADMIN) { if (info != null) { for (int a = 0, size = info.participants.participants.size(); a < size; a++) { @@ -1245,17 +1321,35 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente if (selectType != 0 && participant.user_id == selfUserId) { continue; } - participants.add(participant); - participantsMap.put(participant.user_id, participant); + if (selectType == 1) { + if (ContactsController.getInstance(currentAccount).isContact(participant.user_id)) { + contacts.add(participant); + contactsMap.put(participant.user_id, participant); + } else { + participants.add(participant); + participantsMap.put(participant.user_id, participant); + } + } else { + if (ContactsController.getInstance(currentAccount).isContact(participant.user_id)) { + contacts.add(participant); + contactsMap.put(participant.user_id, participant); + } else { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(participant.user_id); + if (user != null && user.bot) { + bots.add(participant); + botsMap.put(participant.user_id, participant); + } else { + participants.add(participant); + participantsMap.put(participant.user_id, participant); + } + } + } } } } if (listViewAdapter != null) { listViewAdapter.notifyDataSetChanged(); } - if (searchItem != null && !actionBar.isSearchFieldVisible()) { - searchItem.setVisibility(selectType == 0 && participants.isEmpty() ? View.GONE : View.VISIBLE); - } updateRows(); if (listViewAdapter != null) { listViewAdapter.notifyDataSetChanged(); @@ -1275,7 +1369,33 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } else if (type == TYPE_ADMIN) { req.filter = new TLRPC.TL_channelParticipantsAdmins(); } else if (type == TYPE_USERS) { - req.filter = new TLRPC.TL_channelParticipantsRecent(); + if (info != null && info.participants_count <= 200 && currentChat != null && currentChat.megagroup) { + req.filter = new TLRPC.TL_channelParticipantsRecent(); + } else { + if (selectType == 1) { + if (!contactsEndReached) { + delayResults = 2; + req.filter = new TLRPC.TL_channelParticipantsContacts(); + contactsEndReached = true; + loadChatParticipants(0, 200, false); + } else { + req.filter = new TLRPC.TL_channelParticipantsRecent(); + } + } else { + if (!contactsEndReached) { + delayResults = 3; + req.filter = new TLRPC.TL_channelParticipantsContacts(); + contactsEndReached = true; + loadChatParticipants(0, 200, false); + } else if (!botsEndReached) { + req.filter = new TLRPC.TL_channelParticipantsBots(); + botsEndReached = true; + loadChatParticipants(0, 200, false); + } else { + req.filter = new TLRPC.TL_channelParticipantsRecent(); + } + } + } } else if (type == TYPE_KICKED) { req.filter = new TLRPC.TL_channelParticipantsBanned(); } @@ -1283,11 +1403,6 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente req.offset = offset; req.limit = count; int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - loadingUsers = false; - firstLoaded = true; - if (emptyView != null) { - emptyView.showTextView(); - } if (error == null) { TLRPC.TL_channels_channelParticipants res = (TLRPC.TL_channels_channelParticipants) response; MessagesController.getInstance(currentAccount).putUsers(res.users, false); @@ -1300,19 +1415,59 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } } } - participants.clear(); - participants.addAll(res.participants); - participantsMap.clear(); + ArrayList objects; + SparseArray map; + if (type == TYPE_USERS) { + delayResults--; + if (req.filter instanceof TLRPC.TL_channelParticipantsContacts) { + objects = contacts; + map = contactsMap; + } else if (req.filter instanceof TLRPC.TL_channelParticipantsBots) { + objects = bots; + map = botsMap; + } else { + objects = participants; + map = participantsMap; + } + if (delayResults <= 0) { + if (emptyView != null) { + emptyView.showTextView(); + } + } + } else { + objects = participants; + map = participantsMap; + participantsMap.clear(); + if (emptyView != null) { + emptyView.showTextView(); + } + } + objects.clear(); + objects.addAll(res.participants); for (int a = 0, size = res.participants.size(); a < size; a++) { TLRPC.ChannelParticipant participant = res.participants.get(a); - participantsMap.put(participant.user_id, participant); + map.put(participant.user_id, participant); + } + if (type == TYPE_USERS) { + for (int a = 0, N = participants.size(); a < N; a++) { + TLRPC.ChannelParticipant participant = (TLRPC.ChannelParticipant) participants.get(a); + if (contactsMap.get(participant.user_id) != null || + botsMap.get(participant.user_id) != null) { + participants.remove(a); + participantsMap.remove(participant.user_id); + a--; + N--; + } + } } try { - if (type == TYPE_BANNED || type == TYPE_KICKED || type == TYPE_USERS) { + if ((type == TYPE_BANNED || type == TYPE_KICKED || type == TYPE_USERS) && currentChat != null && currentChat.megagroup && info instanceof TLRPC.TL_channelFull && info.participants_count <= 200) { int currentTime = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); - Collections.sort(res.participants, (lhs, rhs) -> { - TLRPC.User user1 = MessagesController.getInstance(currentAccount).getUser(rhs.user_id); - TLRPC.User user2 = MessagesController.getInstance(currentAccount).getUser(lhs.user_id); + Collections.sort(objects, (lhs, rhs) -> { + TLRPC.ChannelParticipant p1 = (TLRPC.ChannelParticipant) lhs; + TLRPC.ChannelParticipant p2 = (TLRPC.ChannelParticipant) rhs; + TLRPC.User user1 = MessagesController.getInstance(currentAccount).getUser(p1.user_id); + TLRPC.User user2 = MessagesController.getInstance(currentAccount).getUser(p2.user_id); int status1 = 0; int status2 = 0; if (user1 != null && user1.status != null) { @@ -1351,7 +1506,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente return 0; }); } else if (type == TYPE_ADMIN) { - Collections.sort(res.participants, (lhs, rhs) -> { + Collections.sort(participants, (lhs, rhs) -> { int type1 = getChannelAdminParticipantType(lhs); int type2 = getChannelAdminParticipantType(rhs); if (type1 > type2) { @@ -1366,6 +1521,10 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente FileLog.e(e); } } + if (type != TYPE_USERS || delayResults <= 0) { + loadingUsers = false; + firstLoaded = true; + } updateRows(); if (listViewAdapter != null) { listViewAdapter.notifyDataSetChanged(); @@ -1378,6 +1537,8 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente @Override public void onResume() { super.onResume(); + AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + AndroidUtilities.removeAdjustResize(getParentActivity(), classGuid); if (listViewAdapter != null) { listViewAdapter.notifyDataSetChanged(); } @@ -1468,7 +1629,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente if (search1.equals(search2) || search2.length() == 0) { search2 = null; } - String search[] = new String[1 + (search2 != null ? 1 : 0)]; + String[] search = new String[1 + (search2 != null ? 1 : 0)]; search[0] = search1; if (search2 != null) { search[1] = search2; @@ -1915,11 +2076,14 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente view = new TextSettingsCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; - default: case 7: view = new TextCheckCell2(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; + case 8: + default: + view = new GraySectionCell(mContext); + break; } return new RecyclerListView.Holder(view); } @@ -1931,6 +2095,16 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente ManageChatUserCell userCell = (ManageChatUserCell) holder.itemView; userCell.setTag(position); TLObject item = getItem(position); + int lastRow; + + if (position >= participantsStartRow && position < participantsEndRow) { + lastRow = participantsEndRow; + } else if (position >= contactsStartRow && position < contactsEndRow) { + lastRow = contactsEndRow; + } else { + lastRow = botEndRow; + } + int userId; int kickedBy; int promotedBy; @@ -1960,7 +2134,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(userId); if (user != null) { if (type == TYPE_KICKED) { - userCell.setData(user, null, formatUserPermissions(bannedRights), position != participantsEndRow - 1); + userCell.setData(user, null, formatUserPermissions(bannedRights), position != lastRow - 1); } else if (type == TYPE_BANNED) { String role = null; if (banned) { @@ -1969,7 +2143,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente role = LocaleController.formatString("UserRemovedBy", R.string.UserRemovedBy, ContactsController.formatName(user1.first_name, user1.last_name)); } } - userCell.setData(user, null, role, position != participantsEndRow - 1); + userCell.setData(user, null, role, position != lastRow - 1); } else if (type == TYPE_ADMIN) { String role = null; if (creator) { @@ -1980,9 +2154,9 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente role = LocaleController.formatString("EditAdminPromotedBy", R.string.EditAdminPromotedBy, ContactsController.formatName(user1.first_name, user1.last_name)); } } - userCell.setData(user, null, role, position != participantsEndRow - 1); + userCell.setData(user, null, role, position != lastRow - 1); } else if (type == TYPE_USERS) { - userCell.setData(user, null, null, position != participantsEndRow - 1); + userCell.setData(user, null, null, position != lastRow - 1); } } break; @@ -2041,15 +2215,15 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } else if (type == TYPE_USERS) { actionCell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton); if (isChannel) { - actionCell.setText(LocaleController.getString("AddSubscriber", R.string.AddSubscriber), null, R.drawable.actions_addmember2, true); + actionCell.setText(LocaleController.getString("AddSubscriber", R.string.AddSubscriber), null, R.drawable.actions_addmember2, membersHeaderRow == -1 && !participants.isEmpty()); } else { - actionCell.setText(LocaleController.getString("AddMember", R.string.AddMember), null, R.drawable.actions_addmember2, true); + actionCell.setText(LocaleController.getString("AddMember", R.string.AddMember), null, R.drawable.actions_addmember2, membersHeaderRow == -1 && !participants.isEmpty()); } } } else if (position == recentActionsRow) { actionCell.setText(LocaleController.getString("EventLog", R.string.EventLog), null, R.drawable.group_log, false); } else if (position == addNew2Row) { - actionCell.setText(LocaleController.getString("ChannelInviteViaLink", R.string.ChannelInviteViaLink), null, R.drawable.profile_link, false); + actionCell.setText(LocaleController.getString("ChannelInviteViaLink", R.string.ChannelInviteViaLink), null, R.drawable.profile_link, true); } break; case 3: @@ -2118,6 +2292,24 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente checkCell.setIcon(0); } break; + case 8: + GraySectionCell sectionCell = (GraySectionCell) holder.itemView; + if (position == membersHeaderRow) { + if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { + sectionCell.setText(LocaleController.getString("ChannelOtherSubscribers", R.string.ChannelOtherSubscribers)); + } else { + sectionCell.setText(LocaleController.getString("ChannelOtherMembers", R.string.ChannelOtherMembers)); + } + } else if (position == botHeaderRow) { + sectionCell.setText(LocaleController.getString("ChannelBots", R.string.ChannelBots)); + } else if (position == contactsHeaderRow) { + if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { + sectionCell.setText(LocaleController.getString("ChannelContacts", R.string.ChannelContacts)); + } else { + sectionCell.setText(LocaleController.getString("GroupContacts", R.string.GroupContacts)); + } + } + break; } } @@ -2132,7 +2324,9 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente public int getItemViewType(int position) { if (position == addNewRow || position == addNew2Row || position == recentActionsRow) { return 2; - } else if (position >= participantsStartRow && position < participantsEndRow) { + } else if (position >= participantsStartRow && position < participantsEndRow || + position >= botStartRow && position < botEndRow || + position >= contactsStartRow && position < contactsEndRow) { return 0; } else if (position == addNewSectionRow || position == participantsDividerRow || position == participantsDivider2Row) { return 3; @@ -2147,13 +2341,19 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } else if (position == changeInfoRow || position == addUsersRow || position == pinMessagesRow || position == sendMessagesRow || position == sendMediaRow || position == sendStickersRow || position == embedLinksRow || position == sendPollsRow) { return 7; + } else if (position == membersHeaderRow || position == contactsHeaderRow || position == botHeaderRow) { + return 8; } return 0; } public TLObject getItem(int position) { - if (participantsStartRow != -1 && position >= participantsStartRow && position < participantsEndRow) { + if (position >= participantsStartRow && position < participantsEndRow) { return participants.get(position - participantsStartRow); + } else if (position >= contactsStartRow && position < contactsEndRow) { + return contacts.get(position - contactsStartRow); + } else if (position >= botStartRow && position < botEndRow) { + return bots.get(position - botStartRow); } return null; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CommonGroupsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CommonGroupsActivity.java index ebbfbf7c9..3afba0638 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CommonGroupsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CommonGroupsActivity.java @@ -20,8 +20,6 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; @@ -37,6 +35,9 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class CommonGroupsActivity extends BaseFragment { private ListAdapter listViewAdapter; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AdminLogFilterAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AdminLogFilterAlert.java index 9b023fc64..20e61d657 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AdminLogFilterAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AdminLogFilterAlert.java @@ -26,19 +26,20 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.CheckBoxCell; import org.telegram.ui.Cells.CheckBoxUserCell; import org.telegram.ui.Cells.ShadowSectionCell; -import org.telegram.ui.StickerPreviewViewer; +import org.telegram.ui.ContentPreviewViewer; import java.util.ArrayList; import java.util.regex.Pattern; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class AdminLogFilterAlert extends BottomSheet { public interface AdminLogFilterAlertDelegate { @@ -74,7 +75,7 @@ public class AdminLogFilterAlert extends BottomSheet { private int allAdminsRow; public AdminLogFilterAlert(Context context, TLRPC.TL_channelAdminLogEventsFilter filter, SparseArray admins, boolean megagroup) { - super(context, false); + super(context, false, 0); if (filter != null) { currentFilter = new TLRPC.TL_channelAdminLogEventsFilter(); currentFilter.join = filter.join; @@ -189,7 +190,7 @@ public class AdminLogFilterAlert extends BottomSheet { listView = new RecyclerListView(context) { @Override public boolean onInterceptTouchEvent(MotionEvent event) { - boolean result = StickerPreviewViewer.getInstance().onInterceptTouchEvent(event, listView, 0, null); + boolean result = ContentPreviewViewer.getInstance().onInterceptTouchEvent(event, listView, 0, null); return super.onInterceptTouchEvent(event) || result; } @@ -401,7 +402,7 @@ public class AdminLogFilterAlert extends BottomSheet { @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view = null; + FrameLayout view = null; switch (viewType) { case 0: view = new CheckBoxCell(context, 1, 21); @@ -410,7 +411,7 @@ public class AdminLogFilterAlert extends BottomSheet { case 1: ShadowSectionCell shadowSectionCell = new ShadowSectionCell(context, 18); view = new FrameLayout(context); - ((FrameLayout) view).addView(shadowSectionCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + view.addView(shadowSectionCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); view.setBackgroundColor(Theme.getColor(Theme.key_dialogBackgroundGray)); break; case 2: 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 5131d0542..807e47824 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java @@ -24,6 +24,7 @@ import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.style.URLSpan; import android.util.Base64; +import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; import android.view.View; @@ -36,8 +37,11 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; +import org.telegram.messenger.ContactsController; import org.telegram.messenger.FileLog; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; @@ -59,6 +63,7 @@ import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.CacheControlActivity; import org.telegram.ui.Cells.AccountSelectCell; +import org.telegram.ui.Cells.CheckBoxCell; import org.telegram.ui.Cells.RadioColorCell; import org.telegram.ui.Cells.TextColorCell; import org.telegram.ui.ChatActivity; @@ -68,7 +73,6 @@ import org.telegram.ui.NotificationsCustomSettingsActivity; import org.telegram.ui.NotificationsSettingsActivity; import org.telegram.ui.ProfileNotificationsActivity; import org.telegram.ui.ReportOtherActivity; -import org.telegram.ui.SettingsActivity; import java.util.ArrayList; import java.util.Calendar; @@ -473,7 +477,7 @@ public class AlertsCreator { } MessagesStorage.getInstance(currentAccount).setDialogFlags(did, 0); editor.commit(); - TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(did); + TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(did); if (dialog != null) { dialog.notify_settings = new TLRPC.TL_peerNotifySettings(); } @@ -526,7 +530,7 @@ public class AlertsCreator { NotificationsController.getInstance(currentAccount).removeNotificationsForDialog(did); MessagesStorage.getInstance(currentAccount).setDialogFlags(did, flags); editor.commit(); - TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(did); + TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(did); if (dialog != null) { dialog.notify_settings = new TLRPC.TL_peerNotifySettings(); if (i != 4 || defaultEnabled) { @@ -736,14 +740,34 @@ public class AlertsCreator { } } - public static void createClearOrDeleteDialogAlert(BaseFragment fragment, boolean clear, TLRPC.Chat chat, TLRPC.User user, boolean secret, Runnable onProcessRunnable) { + public static void createClearOrDeleteDialogAlert(BaseFragment fragment, boolean clear, TLRPC.Chat chat, TLRPC.User user, boolean secret, MessagesStorage.BooleanCallback onProcessRunnable) { if (fragment == null || fragment.getParentActivity() == null || chat == null && user == null) { return; } + int account = fragment.getCurrentAccount(); + Context context = fragment.getParentActivity(); AlertDialog.Builder builder = new AlertDialog.Builder(context); + int selfUserId = UserConfig.getInstance(account).getClientUserId(); - FrameLayout frameLayout = new FrameLayout(context); + CheckBoxCell[] cell = new CheckBoxCell[1]; + + TextView messageTextView = new TextView(context); + messageTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + messageTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + messageTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); + + boolean clearingCache = ChatObject.isChannel(chat) && !TextUtils.isEmpty(chat.username); + + FrameLayout frameLayout = new FrameLayout(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (cell[0] != null) { + setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight() + cell[0].getMeasuredHeight() + AndroidUtilities.dp(7)); + } + } + }; builder.setView(frameLayout); AvatarDrawable avatarDrawable = new AvatarDrawable(); @@ -751,7 +775,7 @@ public class AlertsCreator { BackupImageView imageView = new BackupImageView(context); imageView.setRoundRadius(AndroidUtilities.dp(20)); - frameLayout.addView(imageView, LayoutHelper.createFrame(40, 40, Gravity.LEFT | Gravity.TOP, 22, 5, 0, 0)); + frameLayout.addView(imageView, LayoutHelper.createFrame(40, 40, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 22, 5, 22, 0)); TextView textView = new TextView(context); textView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem)); @@ -760,41 +784,70 @@ public class AlertsCreator { textView.setLines(1); textView.setMaxLines(1); textView.setSingleLine(true); - textView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); + textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); textView.setEllipsize(TextUtils.TruncateAt.END); if (clear) { - textView.setText(LocaleController.getString("ClearHistory", R.string.ClearHistory)); + if (clearingCache) { + textView.setText(LocaleController.getString("ClearHistoryCache", R.string.ClearHistoryCache)); + } else { + textView.setText(LocaleController.getString("ClearHistory", R.string.ClearHistory)); + } } else { textView.setText(LocaleController.getString("DeleteChatUser", R.string.DeleteChatUser)); } - frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 76, 11, 21, 0)); - - TextView messageTextView = new TextView(context); - messageTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); - messageTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - messageTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); + frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, (LocaleController.isRTL ? 21 : 76), 11, (LocaleController.isRTL ? 76 : 21), 0)); frameLayout.addView(messageTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 24, 57, 24, 9)); - TLRPC.FileLocation avatar = null; + boolean canRevokeInbox = user != null && !user.bot && user.id != selfUserId && MessagesController.getInstance(account).canRevokePmInbox; + int revokeTimeLimit; if (user != null) { - avatarDrawable.setInfo(user); - if (user.photo != null && user.photo.photo_small != null && user.photo.photo_small.volume_id != 0 && user.photo.photo_small.local_id != 0) { - avatar = user.photo.photo_small; + revokeTimeLimit = MessagesController.getInstance(account).revokeTimePmLimit; + } else { + revokeTimeLimit = MessagesController.getInstance(account).revokeTimeLimit; + } + boolean canDeleteInbox = !secret && user != null && canRevokeInbox && revokeTimeLimit == 0x7fffffff; + final boolean[] deleteForAll = new boolean[1]; + + if (canDeleteInbox) { + cell[0] = new CheckBoxCell(context, 1); + cell[0].setBackgroundDrawable(Theme.getSelectorDrawable(false)); + if (clear) { + cell[0].setText(LocaleController.formatString("ClearHistoryOptionAlso", R.string.ClearHistoryOptionAlso, UserObject.getFirstName(user)), "", false, false); + } else { + cell[0].setText(LocaleController.formatString("DeleteMessagesOptionAlso", R.string.DeleteMessagesOptionAlso, UserObject.getFirstName(user)), "", false, false); + } + cell[0].setPadding(LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0, LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0); + frameLayout.addView(cell[0], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 0)); + cell[0].setOnClickListener(v -> { + CheckBoxCell cell1 = (CheckBoxCell) v; + deleteForAll[0] = !deleteForAll[0]; + cell1.setChecked(deleteForAll[0], true); + }); + } + + if (user != null) { + if (user.id == selfUserId) { + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_SAVED_SMALL); + imageView.setImage(null, null, avatarDrawable, user); + } else { + avatarDrawable.setInfo(user); + imageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); } } else if (chat != null) { avatarDrawable.setInfo(chat); - if (chat.photo != null && chat.photo.photo_small != null && chat.photo.photo_small.volume_id != 0 && chat.photo.photo_small.local_id != 0) { - avatar = chat.photo.photo_small; - } + imageView.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, user); } - imageView.setImage(avatar, "50_50", avatarDrawable, user); if (clear) { if (user != null) { if (secret) { messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureClearHistoryWithSecretUser", R.string.AreYouSureClearHistoryWithSecretUser, UserObject.getUserName(user)))); } else { - messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureClearHistoryWithUser", R.string.AreYouSureClearHistoryWithUser, UserObject.getUserName(user)))); + if (user.id == selfUserId) { + messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("AreYouSureClearHistorySavedMessages", R.string.AreYouSureClearHistorySavedMessages))); + } else { + messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureClearHistoryWithUser", R.string.AreYouSureClearHistoryWithUser, UserObject.getUserName(user)))); + } } } else if (chat != null) { if (!ChatObject.isChannel(chat) || chat.megagroup && TextUtils.isEmpty(chat.username)) { @@ -810,7 +863,11 @@ public class AlertsCreator { if (secret) { messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureDeleteThisChatWithSecretUser", R.string.AreYouSureDeleteThisChatWithSecretUser, UserObject.getUserName(user)))); } else { - messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureDeleteThisChatWithUser", R.string.AreYouSureDeleteThisChatWithUser, UserObject.getUserName(user)))); + if (user.id == selfUserId) { + messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("AreYouSureDeleteThisChatSavedMessages", R.string.AreYouSureDeleteThisChatSavedMessages))); + } else { + messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureDeleteThisChatWithUser", R.string.AreYouSureDeleteThisChatWithUser, UserObject.getUserName(user)))); + } } } else if (ChatObject.isChannel(chat)) { if (chat.megagroup) { @@ -822,9 +879,14 @@ public class AlertsCreator { messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureDeleteAndExitName", R.string.AreYouSureDeleteAndExitName, chat.title))); } } + String actionText; if (clear) { - actionText = LocaleController.getString("ClearHistory", R.string.ClearHistory); + if (clearingCache) { + actionText = LocaleController.getString("ClearHistoryCache", R.string.ClearHistoryCache); + } else { + actionText = LocaleController.getString("ClearHistory", R.string.ClearHistory); + } } else { if (ChatObject.isChannel(chat)) { if (chat.megagroup) { @@ -838,7 +900,7 @@ public class AlertsCreator { } builder.setPositiveButton(actionText, (dialogInterface, i) -> { if (onProcessRunnable != null) { - onProcessRunnable.run(); + onProcessRunnable.run(deleteForAll[0]); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); @@ -942,37 +1004,17 @@ public class AlertsCreator { LocaleController.getString("MuteDisable", R.string.MuteDisable) }; builder.setItems(items, (dialogInterface, i) -> { - int untilTime = ConnectionsManager.getInstance(UserConfig.selectedAccount).getCurrentTime(); + int setting; if (i == 0) { - untilTime += 60 * 60; + setting = NotificationsController.SETTING_MUTE_HOUR; } else if (i == 1) { - untilTime += 60 * 60 * 8; + setting = NotificationsController.SETTING_MUTE_8_HOURS; } else if (i == 2) { - untilTime += 60 * 60 * 48; - } else if (i == 3) { - untilTime = Integer.MAX_VALUE; - } - - SharedPreferences preferences = MessagesController.getNotificationsSettings(UserConfig.selectedAccount); - SharedPreferences.Editor editor = preferences.edit(); - long flags; - if (i == 3) { - editor.putInt("notify2_" + dialog_id, 2); - flags = 1; + setting = NotificationsController.SETTING_MUTE_2_DAYS; } else { - editor.putInt("notify2_" + dialog_id, 3); - editor.putInt("notifyuntil_" + dialog_id, untilTime); - flags = ((long) untilTime << 32) | 1; + setting = NotificationsController.SETTING_MUTE_FOREVER; } - NotificationsController.getInstance(UserConfig.selectedAccount).removeNotificationsForDialog(dialog_id); - MessagesStorage.getInstance(UserConfig.selectedAccount).setDialogFlags(dialog_id, flags); - editor.commit(); - TLRPC.TL_dialog dialog = MessagesController.getInstance(UserConfig.selectedAccount).dialogs_dict.get(dialog_id); - if (dialog != null) { - dialog.notify_settings = new TLRPC.TL_peerNotifySettings(); - dialog.notify_settings.mute_until = untilTime; - } - NotificationsController.getInstance(UserConfig.selectedAccount).updateServerNotificationsSettings(dialog_id); + NotificationsController.getInstance(UserConfig.selectedAccount).setDialogNotificationsSettings(dialog_id, setting); } ); return builder.create(); @@ -1198,7 +1240,7 @@ public class AlertsCreator { } final LinearLayout linearLayout = new LinearLayout(parentActivity); linearLayout.setOrientation(LinearLayout.VERTICAL); - String descriptions[] = new String[] {LocaleController.getString("ColorRed", R.string.ColorRed), + String[] descriptions = new String[]{LocaleController.getString("ColorRed", R.string.ColorRed), LocaleController.getString("ColorOrange", R.string.ColorOrange), LocaleController.getString("ColorYellow", R.string.ColorYellow), LocaleController.getString("ColorGreen", R.string.ColorGreen), @@ -1207,7 +1249,7 @@ public class AlertsCreator { LocaleController.getString("ColorViolet", R.string.ColorViolet), LocaleController.getString("ColorPink", R.string.ColorPink), LocaleController.getString("ColorWhite", R.string.ColorWhite)}; - final int selectedColor[] = new int[] {currentColor}; + final int[] selectedColor = new int[]{currentColor}; for (int a = 0; a < 9; a++) { RadioColorCell cell = new RadioColorCell(parentActivity); cell.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); @@ -1287,8 +1329,8 @@ public class AlertsCreator { public static Dialog createVibrationSelectDialog(Activity parentActivity, final long dialog_id, final String prefKeyPrefix, final Runnable onSelect) { SharedPreferences preferences = MessagesController.getNotificationsSettings(UserConfig.selectedAccount); - final int selected[] = new int[1]; - String descriptions[]; + final int[] selected = new int[1]; + String[] descriptions; if (dialog_id != 0) { selected[0] = preferences.getInt(prefKeyPrefix + dialog_id, 0); if (selected[0] == 3) { @@ -1373,7 +1415,7 @@ public class AlertsCreator { } public static Dialog createLocationUpdateDialog(final Activity parentActivity, TLRPC.User user, final MessagesStorage.IntCallback callback) { - final int selected[] = new int[1]; + final int[] selected = new int[1]; String[] descriptions = new String[]{ LocaleController.getString("SendLiveLocationFor15m", R.string.SendLiveLocationFor15m), @@ -1442,7 +1484,7 @@ public class AlertsCreator { } public static Dialog createFreeSpaceDialog(final LaunchActivity parentActivity) { - final int selected[] = new int[1]; + final int[] selected = new int[1]; SharedPreferences preferences = MessagesController.getGlobalMainSettings(); int keepMedia = preferences.getInt("keep_media", 2); @@ -1512,8 +1554,8 @@ public class AlertsCreator { public static Dialog createPrioritySelectDialog(Activity parentActivity, final long dialog_id, final int globalType, final Runnable onSelect) { SharedPreferences preferences = MessagesController.getNotificationsSettings(UserConfig.selectedAccount); - final int selected[] = new int[1]; - String descriptions[]; + final int[] selected = new int[1]; + String[] descriptions; if (dialog_id != 0) { selected[0] = preferences.getInt("priority_" + dialog_id, 3); if (selected[0] == 3) { @@ -1628,7 +1670,7 @@ public class AlertsCreator { public static Dialog createPopupSelectDialog(Activity parentActivity, final int globalType, final Runnable onSelect) { SharedPreferences preferences = MessagesController.getNotificationsSettings(UserConfig.selectedAccount); - final int selected[] = new int[1]; + final int[] selected = new int[1]; if (globalType == NotificationsController.TYPE_PRIVATE) { selected[0] = preferences.getInt("popupAll", 0); } else if (globalType == NotificationsController.TYPE_GROUP) { @@ -1636,7 +1678,7 @@ public class AlertsCreator { } else { selected[0] = preferences.getInt("popupChannel", 0); } - String descriptions[] = new String[]{ + String[] descriptions = new String[]{ LocaleController.getString("NoPopup", R.string.NoPopup), LocaleController.getString("OnlyWhenScreenOn", R.string.OnlyWhenScreenOn), LocaleController.getString("OnlyWhenScreenOff", R.string.OnlyWhenScreenOff), @@ -1846,4 +1888,340 @@ public class AlertsCreator { 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) { + if (fragment == null || user == null && chat == null && encryptedChat == null) { + return; + } + Activity activity = fragment.getParentActivity(); + if (activity == null) { + return; + } + int currentAccount = fragment.getCurrentAccount(); + + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + int count; + if (selectedGroup != null) { + count = selectedGroup.messages.size(); + } else if (selectedMessage != null) { + count = 1; + } else { + count = selectedMessages[0].size() + selectedMessages[1].size(); + } + + final boolean[] checks = new boolean[3]; + final boolean[] deleteForAll = new boolean[1]; + TLRPC.User actionUser = null; + boolean canRevokeInbox = user != null && MessagesController.getInstance(currentAccount).canRevokePmInbox; + int revokeTimeLimit; + if (user != null) { + revokeTimeLimit = MessagesController.getInstance(currentAccount).revokeTimePmLimit; + } else { + revokeTimeLimit = MessagesController.getInstance(currentAccount).revokeTimeLimit; + } + boolean hasDeleteForAllCheck = false; + boolean hasNotOut = false; + int myMessagesCount = 0; + boolean canDeleteInbox = encryptedChat == null && user != null && canRevokeInbox && revokeTimeLimit == 0x7fffffff; + if (chat != null && chat.megagroup) { + boolean canBan = ChatObject.canBlockUsers(chat); + int currentDate = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); + if (selectedMessage != null) { + if (selectedMessage.messageOwner.action == null || selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionEmpty || + selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionChatDeleteUser || + selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByLink || + selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionChatAddUser) { + actionUser = MessagesController.getInstance(currentAccount).getUser(selectedMessage.messageOwner.from_id); + } + boolean hasOutgoing = !selectedMessage.isSendError() && selectedMessage.getDialogId() == mergeDialogId && (selectedMessage.messageOwner.action == null || selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) && selectedMessage.isOut() && (currentDate - selectedMessage.messageOwner.date) <= revokeTimeLimit; + if (hasOutgoing) { + myMessagesCount++; + } + } else { + int from_id = -1; + for (int a = 1; a >= 0; a--) { + int channelId = 0; + for (int b = 0; b < selectedMessages[a].size(); b++) { + MessageObject msg = selectedMessages[a].valueAt(b); + if (from_id == -1) { + from_id = msg.messageOwner.from_id; + } + if (from_id < 0 || from_id != msg.messageOwner.from_id) { + from_id = -2; + break; + } + } + if (from_id == -2) { + break; + } + } + for (int a = 1; a >= 0; a--) { + for (int b = 0; b < selectedMessages[a].size(); b++) { + MessageObject msg = selectedMessages[a].valueAt(b); + if (a == 1) { + if (msg.isOut() && msg.messageOwner.action == null) { + if ((currentDate - msg.messageOwner.date) <= revokeTimeLimit) { + myMessagesCount++; + } + } + } + } + } + if (from_id != -1) { + actionUser = MessagesController.getInstance(currentAccount).getUser(from_id); + } + } + if (actionUser != null && actionUser.id != UserConfig.getInstance(currentAccount).getClientUserId()) { + if (loadParticipant == 1 && !chat.creator) { + final AlertDialog[] progressDialog = new AlertDialog[]{new AlertDialog(activity, 3)}; + + TLRPC.TL_channels_getParticipant req = new TLRPC.TL_channels_getParticipant(); + req.channel = MessagesController.getInputChannel(chat); + req.user_id = MessagesController.getInstance(currentAccount).getInputUser(actionUser); + int requestId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + try { + progressDialog[0].dismiss(); + } catch (Throwable ignore) { + + } + progressDialog[0] = null; + int loadType = 2; + if (response != null) { + TLRPC.TL_channels_channelParticipant participant = (TLRPC.TL_channels_channelParticipant) response; + if (!(participant.participant instanceof TLRPC.TL_channelParticipantAdmin || participant.participant instanceof TLRPC.TL_channelParticipantCreator)) { + loadType = 0; + } + } + createDeleteMessagesAlert(fragment, user, chat, encryptedChat, chatInfo, mergeDialogId, selectedMessage, selectedMessages, selectedGroup, loadType, onDelete); + })); + AndroidUtilities.runOnUIThread(() -> { + if (progressDialog[0] == null) { + return; + } + progressDialog[0].setOnCancelListener(dialog -> ConnectionsManager.getInstance(currentAccount).cancelRequest(requestId, true)); + fragment.showDialog(progressDialog[0]); + }, 1000); + return; + } + FrameLayout frameLayout = new FrameLayout(activity); + int num = 0; + for (int a = 0; a < 3; a++) { + if ((loadParticipant == 2 || !canBan) && a == 0) { + continue; + } + CheckBoxCell cell = new CheckBoxCell(activity, 1); + cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); + cell.setTag(a); + if (a == 0) { + cell.setText(LocaleController.getString("DeleteBanUser", R.string.DeleteBanUser), "", false, false); + } else if (a == 1) { + cell.setText(LocaleController.getString("DeleteReportSpam", R.string.DeleteReportSpam), "", false, false); + } else if (a == 2) { + cell.setText(LocaleController.formatString("DeleteAllFrom", R.string.DeleteAllFrom, ContactsController.formatName(actionUser.first_name, actionUser.last_name)), "", false, false); + } + cell.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0, LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0); + frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 0, 48 * num, 0, 0)); + cell.setOnClickListener(v -> { + if (!v.isEnabled()) { + return; + } + CheckBoxCell cell13 = (CheckBoxCell) v; + Integer num1 = (Integer) cell13.getTag(); + checks[num1] = !checks[num1]; + cell13.setChecked(checks[num1], true); + }); + num++; + } + builder.setView(frameLayout); + } else if (!hasNotOut && myMessagesCount > 0) { + hasDeleteForAllCheck = true; + FrameLayout frameLayout = new FrameLayout(activity); + CheckBoxCell cell = new CheckBoxCell(activity, 1); + cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); + if (chat != null && hasNotOut) { + cell.setText(LocaleController.getString("DeleteForAll", R.string.DeleteForAll), "", false, false); + } else { + cell.setText(LocaleController.getString("DeleteMessagesOption", R.string.DeleteMessagesOption), "", false, false); + } + cell.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0, LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0); + frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0)); + cell.setOnClickListener(v -> { + CheckBoxCell cell12 = (CheckBoxCell) v; + deleteForAll[0] = !deleteForAll[0]; + cell12.setChecked(deleteForAll[0], true); + }); + builder.setView(frameLayout); + builder.setCustomViewOffset(9); + } else { + actionUser = null; + } + } else if (!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) { + boolean hasOutgoing = !selectedMessage.isSendError() && (selectedMessage.messageOwner.action == null || selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionEmpty || selectedMessage.messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall) && (selectedMessage.isOut() || canRevokeInbox || ChatObject.hasAdminRights(chat)) && (currentDate - selectedMessage.messageOwner.date) <= revokeTimeLimit; + if (hasOutgoing) { + myMessagesCount++; + } + hasNotOut = !selectedMessage.isOut(); + } else { + for (int a = 1; a >= 0; a--) { + for (int b = 0; b < selectedMessages[a].size(); b++) { + MessageObject msg = selectedMessages[a].valueAt(b); + if (!(msg.messageOwner.action == null || msg.messageOwner.action instanceof TLRPC.TL_messageActionEmpty || msg.messageOwner.action instanceof TLRPC.TL_messageActionPhoneCall)) { + continue; + } + if ((msg.isOut() || canRevokeInbox) || chat != null && ChatObject.canBlockUsers(chat)) { + if ((currentDate - msg.messageOwner.date) <= revokeTimeLimit) { + myMessagesCount++; + if (!hasNotOut && !msg.isOut()) { + hasNotOut = true; + } + } + } + } + } + } + } + if (myMessagesCount > 0) { + hasDeleteForAllCheck = true; + FrameLayout frameLayout = new FrameLayout(activity); + CheckBoxCell cell = new CheckBoxCell(activity, 1); + cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); + if (canDeleteInbox) { + cell.setText(LocaleController.formatString("DeleteMessagesOptionAlso", R.string.DeleteMessagesOptionAlso, UserObject.getFirstName(user)), "", false, false); + } else if (chat != null && (hasNotOut || myMessagesCount == count)) { + cell.setText(LocaleController.getString("DeleteForAll", R.string.DeleteForAll), "", false, false); + } else { + cell.setText(LocaleController.getString("DeleteMessagesOption", R.string.DeleteMessagesOption), "", false, false); + } + cell.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0, LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0); + frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0)); + cell.setOnClickListener(v -> { + CheckBoxCell cell1 = (CheckBoxCell) v; + deleteForAll[0] = !deleteForAll[0]; + cell1.setChecked(deleteForAll[0], true); + }); + builder.setView(frameLayout); + builder.setCustomViewOffset(9); + } + } + final TLRPC.User userFinal = actionUser; + builder.setPositiveButton(LocaleController.getString("Delete", R.string.Delete), (dialogInterface, i) -> { + ArrayList ids = null; + if (selectedMessage != null) { + ids = new ArrayList<>(); + ArrayList random_ids = null; + if (selectedGroup != null) { + for (int a = 0; a < selectedGroup.messages.size(); a++) { + MessageObject messageObject = selectedGroup.messages.get(a); + ids.add(messageObject.getId()); + if (encryptedChat != null && messageObject.messageOwner.random_id != 0 && messageObject.type != 10) { + if (random_ids == null) { + random_ids = new ArrayList<>(); + } + random_ids.add(messageObject.messageOwner.random_id); + } + } + } else { + ids.add(selectedMessage.getId()); + if (encryptedChat != null && selectedMessage.messageOwner.random_id != 0 && selectedMessage.type != 10) { + random_ids = new ArrayList<>(); + random_ids.add(selectedMessage.messageOwner.random_id); + } + } + MessagesController.getInstance(currentAccount).deleteMessages(ids, random_ids, encryptedChat, selectedMessage.messageOwner.to_id.channel_id, deleteForAll[0]); + } else { + for (int a = 1; a >= 0; a--) { + ids = new ArrayList<>(); + for (int b = 0; b < selectedMessages[a].size(); b++) { + ids.add(selectedMessages[a].keyAt(b)); + } + ArrayList random_ids = null; + int channelId = 0; + if (!ids.isEmpty()) { + MessageObject msg = selectedMessages[a].get(ids.get(0)); + if (channelId == 0 && msg.messageOwner.to_id.channel_id != 0) { + channelId = msg.messageOwner.to_id.channel_id; + } + } + if (encryptedChat != null) { + random_ids = new ArrayList<>(); + for (int b = 0; b < selectedMessages[a].size(); b++) { + MessageObject msg = selectedMessages[a].valueAt(b); + if (msg.messageOwner.random_id != 0 && msg.type != 10) { + random_ids.add(msg.messageOwner.random_id); + } + } + } + MessagesController.getInstance(currentAccount).deleteMessages(ids, random_ids, encryptedChat, channelId, deleteForAll[0]); + selectedMessages[a].clear(); + } + } + if (userFinal != null) { + if (checks[0]) { + MessagesController.getInstance(currentAccount).deleteUserFromChat(chat.id, userFinal, chatInfo); + } + if (checks[1]) { + TLRPC.TL_channels_reportSpam req = new TLRPC.TL_channels_reportSpam(); + req.channel = MessagesController.getInputChannel(chat); + req.user_id = MessagesController.getInstance(currentAccount).getInputUser(userFinal); + req.id = ids; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + + }); + } + if (checks[2]) { + MessagesController.getInstance(currentAccount).deleteUserChannelHistory(chat, userFinal, 0); + } + } + if (onDelete != null) { + onDelete.run(); + } + }); + + if (count == 1) { + builder.setTitle(LocaleController.getString("DeleteSingleMessagesTitle", R.string.DeleteSingleMessagesTitle)); + } else { + builder.setTitle(LocaleController.formatString("DeleteMessagesTitle", R.string.DeleteMessagesTitle, LocaleController.formatPluralString("messages", count))); + } + + if (chat != null && hasNotOut) { + if (hasDeleteForAllCheck && myMessagesCount != count) { + builder.setMessage(LocaleController.formatString("DeleteMessagesTextGroupPart", R.string.DeleteMessagesTextGroupPart, LocaleController.formatPluralString("messages", myMessagesCount))); + } else if (count == 1) { + builder.setMessage(LocaleController.getString("AreYouSureDeleteSingleMessage", R.string.AreYouSureDeleteSingleMessage)); + } else { + builder.setMessage(LocaleController.getString("AreYouSureDeleteFewMessages", R.string.AreYouSureDeleteFewMessages)); + } + } else if (hasDeleteForAllCheck && !canDeleteInbox && myMessagesCount != count) { + if (chat != null) { + builder.setMessage(LocaleController.formatString("DeleteMessagesTextGroup", R.string.DeleteMessagesTextGroup, LocaleController.formatPluralString("messages", myMessagesCount))); + } else { + builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("DeleteMessagesText", R.string.DeleteMessagesText, LocaleController.formatPluralString("messages", myMessagesCount), UserObject.getFirstName(user)))); + } + } else { + if (chat != null && chat.megagroup) { + if (count == 1) { + builder.setMessage(LocaleController.getString("AreYouSureDeleteSingleMessageMega", R.string.AreYouSureDeleteSingleMessageMega)); + } else { + builder.setMessage(LocaleController.getString("AreYouSureDeleteFewMessagesMega", R.string.AreYouSureDeleteFewMessagesMega)); + } + } else { + if (count == 1) { + builder.setMessage(LocaleController.getString("AreYouSureDeleteSingleMessage", R.string.AreYouSureDeleteSingleMessage)); + } else { + builder.setMessage(LocaleController.getString("AreYouSureDeleteFewMessages", R.string.AreYouSureDeleteFewMessages)); + } + } + } + + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + AlertDialog dialog = builder.create(); + fragment.showDialog(dialog); + TextView button = (TextView) dialog.getButton(DialogInterface.BUTTON_POSITIVE); + if (button != null) { + button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedArrowDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedArrowDrawable.java index 55dad6cd2..69b7352a7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedArrowDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedArrowDrawable.java @@ -7,7 +7,7 @@ import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; import android.os.SystemClock; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import org.telegram.messenger.AndroidUtilities; @@ -25,6 +25,8 @@ public class AnimatedArrowDrawable extends Drawable { paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(AndroidUtilities.dp(2)); paint.setColor(color); + paint.setStrokeCap(Paint.Cap.ROUND); + paint.setStrokeJoin(Paint.Join.ROUND); isSmall = small; updatePath(); @@ -44,9 +46,9 @@ public class AnimatedArrowDrawable extends Drawable { path.lineTo(AndroidUtilities.dp(8), AndroidUtilities.dp(6) + AndroidUtilities.dp(2) * p); path.lineTo(AndroidUtilities.dp(13), AndroidUtilities.dp(6) - AndroidUtilities.dp(2) * p); } else { - path.moveTo(AndroidUtilities.dp(3), AndroidUtilities.dp(12) - AndroidUtilities.dp(4) * p); + path.moveTo(AndroidUtilities.dp(4.5f), AndroidUtilities.dp(12) - AndroidUtilities.dp(4) * p); path.lineTo(AndroidUtilities.dp(13), AndroidUtilities.dp(12) + AndroidUtilities.dp(4) * p); - path.lineTo(AndroidUtilities.dp(23), AndroidUtilities.dp(12) - AndroidUtilities.dp(4) * p); + path.lineTo(AndroidUtilities.dp(21.5f), AndroidUtilities.dp(12) - AndroidUtilities.dp(4) * p); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java index 4283955ae..9bfd4838c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java @@ -43,6 +43,18 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { private static native int getVideoFrame(long ptr, Bitmap bitmap, int[] params, int stride); private static native void seekToMs(long ptr, long ms); private static native void prepareToSeek(long ptr); + public static native void getVideoInfo(String src, int[] params); + + public final static int PARAM_NUM_IS_AVC = 0; + public final static int PARAM_NUM_WIDTH = 1; + public final static int PARAM_NUM_HEIGHT = 2; + public final static int PARAM_NUM_BITRATE = 3; + public final static int PARAM_NUM_DURATION = 4; + public final static int PARAM_NUM_AUDIO_FRAME_SIZE = 5; + public final static int PARAM_NUM_VIDEO_FRAME_SIZE = 6; + public final static int PARAM_NUM_FRAMERATE = 7; + public final static int PARAM_NUM_ROTATION = 8; + public final static int PARAM_NUM_COUNT = 9; private long lastFrameTime; private int lastTimeStamp; @@ -78,8 +90,6 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { private BitmapShader backgroundShader; private int roundRadius; - private RectF roundRect = new RectF(); - private RectF bitmapRect = new RectF(); private Matrix shaderMatrix = new Matrix(); private float scaleX = 1.0f; @@ -90,7 +100,6 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { private volatile boolean isRunning; private volatile boolean isRecycled; public volatile long nativePtr; - private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2, new ThreadPoolExecutor.DiscardPolicy()); private DispatchQueue decodeQueue; private View parentView = null; @@ -98,6 +107,10 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { private AnimatedFileDrawableStream stream; + private boolean useSharedQueue; + + private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2, new ThreadPoolExecutor.DiscardPolicy()); + protected final Runnable mInvalidateTask = () -> { if (secondParentView != null) { secondParentView.invalidate(); @@ -216,7 +229,9 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { pendingSeekTo = -1; } seekWas = true; - stream.reset(); + if (stream != null) { + stream.reset(); + } seekToMs(nativePtr, seekTo); } if (backgroundBitmap != null) { @@ -254,6 +269,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { path = file; streamFileSize = streamSize; currentAccount = account; + getPaint().setFlags(Paint.FILTER_BITMAP_FLAG); if (streamSize != 0 && document != null) { stream = new AnimatedFileDrawableStream(document, parentObject, account); } @@ -337,6 +353,10 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { } } + public void setUseSharedQueue(boolean value) { + useSharedQueue = value; + } + @Override protected void finalize() throws Throwable { try { @@ -390,16 +410,20 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { if (lastFrameDecodeTime != 0) { ms = Math.min(invalidateAfter, Math.max(0, invalidateAfter - (System.currentTimeMillis() - lastFrameDecodeTime))); } - if (streamFileSize != 0) { + if (useSharedQueue) { + executor.schedule(loadFrameTask = loadFrameRunnable, ms, TimeUnit.MILLISECONDS); + } else { if (decodeQueue == null) { decodeQueue = new DispatchQueue("decodeQueue" + this); } decodeQueue.postRunnable(loadFrameTask = loadFrameRunnable, ms); - } else { - executor.schedule(loadFrameTask = loadFrameRunnable, ms, TimeUnit.MILLISECONDS); } } + public boolean isLoadingStream() { + return stream != null && stream.isWaitingForLoad(); + } + @Override public void stop() { isRunning = false; @@ -482,13 +506,24 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { if (renderingShader == null) { renderingShader = new BitmapShader(backgroundBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); } - getPaint().setShader(renderingShader); - roundRect.set(dstRect); + Paint paint = getPaint(); + paint.setShader(renderingShader); shaderMatrix.reset(); - bitmapRect.set(0, 0, renderingBitmap.getWidth(), renderingBitmap.getHeight()); - AndroidUtilities.setRectToRect(shaderMatrix, bitmapRect, roundRect, metaData[2], true); + shaderMatrix.setTranslate(dstRect.left, dstRect.top); + if (metaData[2] == 90) { + shaderMatrix.preRotate(90); + shaderMatrix.preTranslate(0, -dstRect.width()); + } else if (metaData[2] == 180) { + shaderMatrix.preRotate(180); + shaderMatrix.preTranslate(-dstRect.width(), -dstRect.height()); + } else if (metaData[2] == 270) { + shaderMatrix.preRotate(270); + shaderMatrix.preTranslate(-dstRect.height(), 0); + } + shaderMatrix.preScale(scaleX, scaleY); + renderingShader.setLocalMatrix(shaderMatrix); - canvas.drawRoundRect(actualDrawRect, roundRadius, roundRadius, getPaint()); + canvas.drawRoundRect(actualDrawRect, roundRadius, roundRadius, paint); } else { canvas.translate(dstRect.left, dstRect.top); if (metaData[2] == 90) { @@ -551,13 +586,13 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { return null; } - public void setActualDrawRect(int x, int y, int width, int height) { + public void setActualDrawRect(float x, float y, float width, float height) { actualDrawRect.set(x, y, x + width, y + height); } public void setRoundRadius(int value) { roundRadius = value; - getPaint().setFlags(Paint.ANTI_ALIAS_FLAG); + getPaint().setFlags(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); } public boolean hasBitmap() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimationProperties.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimationProperties.java index 45692ed51..9f512653e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimationProperties.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimationProperties.java @@ -4,6 +4,7 @@ import android.graphics.Paint; import android.graphics.drawable.ColorDrawable; import android.util.Property; +import org.telegram.ui.Cells.DialogCell; import org.telegram.ui.PhotoViewer; public class AnimationProperties { @@ -34,7 +35,6 @@ public class AnimationProperties { final public void set(T object, Integer value) { setValue(object, value); } - } public static final Property PAINT_ALPHA = new IntProperty("alpha") { @@ -84,4 +84,16 @@ public class AnimationProperties { return object.getAnimationValue(); } }; + + public static final Property CLIP_DIALOG_CELL_PROGRESS = new FloatProperty("clipProgress") { + @Override + public void setValue(DialogCell object, float value) { + object.setClipProgress(value); + } + + @Override + public Float get(DialogCell object) { + return object.getClipProgress(); + } + }; } 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 48d476be5..b3a09d477 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java @@ -23,8 +23,11 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.support.annotation.Keep; -import android.support.v4.content.FileProvider; +import androidx.annotation.Keep; +import androidx.core.content.FileProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; @@ -40,7 +43,6 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildConfig; -import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DownloadController; import org.telegram.messenger.FileLoader; @@ -55,12 +57,8 @@ import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.messenger.audioinfo.AudioInfo; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; -import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; @@ -70,7 +68,6 @@ import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.AudioPlayerCell; -import org.telegram.ui.Cells.CheckBoxCell; import org.telegram.ui.ChatActivity; import org.telegram.ui.DialogsActivity; import org.telegram.ui.LaunchActivity; @@ -148,7 +145,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. private LaunchActivity parentActivity; public AudioPlayerAlert(final Context context) { - super(context, true); + super(context, true, 0); MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); if (messageObject != null) { @@ -220,7 +217,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. panelEndTranslation = getMeasuredHeight() - playerLayout.getMeasuredHeight(); thumbMaxScale = maxSize / (float) placeholderImageView.getMeasuredWidth() - 1.0f; - endTranslation = ActionBar.getCurrentActionBarHeight() + AndroidUtilities.dp(5); + endTranslation = ActionBar.getCurrentActionBarHeight() + (AndroidUtilities.statusBarHeight - AndroidUtilities.dp(19)); int scaledHeight = (int) Math.ceil(placeholderImageView.getMeasuredHeight() * (1.0f + thumbMaxScale)); if (scaledHeight > availableHeight) { endTranslation -= (scaledHeight - availableHeight); @@ -302,11 +299,11 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. actionBar.addView(avatarContainer, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 56, 0, 40, 0)); ActionBarMenu menu = actionBar.createMenu(); + menu.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); menuItem = menu.addItem(0, R.drawable.ic_ab_other); - menuItem.addSubItem(1, LocaleController.getString("Forward", R.string.Forward)); - menuItem.addSubItem(2, LocaleController.getString("ShareFile", R.string.ShareFile)); - //menuItem.addSubItem(3, LocaleController.getString("Delete", R.string.Delete)); - menuItem.addSubItem(4, LocaleController.getString("ShowInChat", R.string.ShowInChat)); + menuItem.addSubItem(1, R.drawable.msg_forward, LocaleController.getString("Forward", R.string.Forward)); + menuItem.addSubItem(2, R.drawable.msg_shareout, LocaleController.getString("ShareFile", R.string.ShareFile)); + menuItem.addSubItem(4, R.drawable.msg_message, LocaleController.getString("ShowInChat", R.string.ShowInChat)); menuItem.setTranslationX(AndroidUtilities.dp(48)); menuItem.setAlpha(0.0f); @@ -350,6 +347,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. } } }); + searchItem.setContentDescription(LocaleController.getString("Search", R.string.Search)); EditTextBoldCursor editText = searchItem.getSearchField(); editText.setHint(LocaleController.getString("Search", R.string.Search)); editText.setTextColor(Theme.getColor(Theme.key_player_actionBarTitle)); @@ -477,12 +475,12 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. optionsButton.setIcon(R.drawable.ic_ab_other); optionsButton.setAdditionalOffset(-AndroidUtilities.dp(120)); playerLayout.addView(optionsButton, LayoutHelper.createFrame(40, 40, Gravity.TOP | Gravity.RIGHT, 0, 19, 10, 0)); - optionsButton.addSubItem(1, LocaleController.getString("Forward", R.string.Forward)); - optionsButton.addSubItem(2, LocaleController.getString("ShareFile", R.string.ShareFile)); - //optionsButton.addSubItem(3, LocaleController.getString("Delete", R.string.Delete)); - optionsButton.addSubItem(4, LocaleController.getString("ShowInChat", R.string.ShowInChat)); + optionsButton.addSubItem(1, R.drawable.msg_forward, LocaleController.getString("Forward", R.string.Forward)); + optionsButton.addSubItem(2, R.drawable.msg_shareout, LocaleController.getString("ShareFile", R.string.ShareFile)); + optionsButton.addSubItem(4, R.drawable.msg_message, LocaleController.getString("ShowInChat", R.string.ShowInChat)); optionsButton.setOnClickListener(v -> optionsButton.toggleSubMenu()); optionsButton.setDelegate(this::onSubItemClick); + optionsButton.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); seekBarView = new SeekBarView(context); seekBarView.setDelegate(progress -> MediaController.getInstance().seekToProgress(MediaController.getInstance().getPlayingMessageObject(), progress)); @@ -549,6 +547,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. prevButton.setImageDrawable(Theme.createSimpleSelectorDrawable(context, R.drawable.pl_previous, Theme.getColor(Theme.key_player_button), Theme.getColor(Theme.key_player_buttonActive))); bottomView.addView(prevButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP)); prevButton.setOnClickListener(v -> MediaController.getInstance().playPreviousMessage()); + prevButton.setContentDescription(LocaleController.getString("AccDescrPrevious", R.string.AccDescrPrevious)); buttons[2] = playButton = new ImageView(context); playButton.setScaleType(ImageView.ScaleType.CENTER); @@ -571,6 +570,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. nextButton.setImageDrawable(Theme.createSimpleSelectorDrawable(context, R.drawable.pl_next, Theme.getColor(Theme.key_player_button), Theme.getColor(Theme.key_player_buttonActive))); bottomView.addView(nextButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP)); nextButton.setOnClickListener(v -> MediaController.getInstance().playNextMessage()); + nextButton.setContentDescription(LocaleController.getString("Next", R.string.Next)); buttons[4] = repeatButton = new ImageView(context); repeatButton.setScaleType(ImageView.ScaleType.CENTER); @@ -639,7 +639,6 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. @Override protected boolean allowSelectChildAtPosition(float x, float y) { - float p = playerLayout.getY() + playerLayout.getMeasuredHeight(); return playerLayout == null || y > playerLayout.getY() + playerLayout.getMeasuredHeight(); } @@ -812,63 +811,6 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. } catch (Exception e) { FileLog.e(e); } - } else if (id == 3) { - AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); - //builder.setMessage(LocaleController.formatString("AreYouSureDeleteAudio", R.string.AreYouSureDeleteAudio)); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - - final boolean deleteForAll[] = new boolean[1]; - int lower_id = (int) messageObject.getDialogId(); - if (lower_id != 0) { - TLRPC.Chat currentChat; - TLRPC.User currentUser; - if (lower_id > 0) { - currentUser = MessagesController.getInstance(currentAccount).getUser(lower_id); - currentChat = null; - } else { - currentUser = null; - currentChat = MessagesController.getInstance(currentAccount).getChat(-lower_id); - } - if (currentUser != null || !ChatObject.isChannel(currentChat)) { - boolean hasOutgoing = false; - int currentDate = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); - if (currentUser != null && currentUser.id != UserConfig.getInstance(currentAccount).getClientUserId() || currentChat != null) { - if ((messageObject.messageOwner.action == null || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) && messageObject.isOut() && (currentDate - messageObject.messageOwner.date) <= 2 * 24 * 60 * 60) { - FrameLayout frameLayout = new FrameLayout(parentActivity); - CheckBoxCell cell = new CheckBoxCell(parentActivity, 1); - cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); - if (currentChat != null) { - cell.setText(LocaleController.getString("DeleteForAll", R.string.DeleteForAll), "", false, false); - } else { - cell.setText(LocaleController.formatString("DeleteForUser", R.string.DeleteForUser, UserObject.getFirstName(currentUser)), "", false, false); - } - cell.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0, LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0); - frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0)); - cell.setOnClickListener(v -> { - CheckBoxCell cell1 = (CheckBoxCell) v; - deleteForAll[0] = !deleteForAll[0]; - cell1.setChecked(deleteForAll[0], true); - }); - builder.setView(frameLayout); - } - } - } - } - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> { - dismiss(); - ArrayList arr = new ArrayList<>(); - arr.add(messageObject.getId()); - ArrayList random_ids = null; - TLRPC.EncryptedChat encryptedChat = null; - if ((int) messageObject.getDialogId() == 0 && messageObject.messageOwner.random_id != 0) { - random_ids = new ArrayList<>(); - random_ids.add(messageObject.messageOwner.random_id); - encryptedChat = MessagesController.getInstance(currentAccount).getEncryptedChat((int) (messageObject.getDialogId() >> 32)); - } - MessagesController.getInstance(currentAccount).deleteMessages(arr, random_ids, encryptedChat, messageObject.messageOwner.to_id.channel_id, deleteForAll[0]); - }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - builder.show(); } else if (id == 4) { if (UserConfig.selectedAccount != currentAccount) { parentActivity.switchToAccount(currentAccount, true); @@ -1066,6 +1008,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. Drawable drawable = getContext().getResources().getDrawable(R.drawable.pl_shuffle).mutate(); drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_player_buttonActive), PorterDuff.Mode.MULTIPLY)); shuffleButton.setIcon(drawable); + shuffleButton.setContentDescription(LocaleController.getString("Shuffle", R.string.Shuffle)); } else { Drawable drawable = getContext().getResources().getDrawable(R.drawable.music_reverse).mutate(); if (SharedConfig.playOrderReversed) { @@ -1074,6 +1017,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_player_button), PorterDuff.Mode.MULTIPLY)); } shuffleButton.setIcon(drawable); + shuffleButton.setContentDescription(LocaleController.getString("ReverseOrder", R.string.ReverseOrder)); } playOrderButtons[0].setColorFilter(new PorterDuffColorFilter(Theme.getColor(SharedConfig.playOrderReversed ? Theme.key_player_buttonActive : Theme.key_player_button), PorterDuff.Mode.MULTIPLY)); @@ -1086,14 +1030,17 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. repeatButton.setImageResource(R.drawable.pl_repeat); repeatButton.setTag(Theme.key_player_button); repeatButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_player_button), PorterDuff.Mode.MULTIPLY)); + repeatButton.setContentDescription(LocaleController.getString("AccDescrRepeatOff", R.string.AccDescrRepeatOff)); } else if (mode == 1) { repeatButton.setImageResource(R.drawable.pl_repeat); repeatButton.setTag(Theme.key_player_buttonActive); repeatButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_player_buttonActive), PorterDuff.Mode.MULTIPLY)); + repeatButton.setContentDescription(LocaleController.getString("AccDescrRepeatList", R.string.AccDescrRepeatList)); } else if (mode == 2) { repeatButton.setImageResource(R.drawable.pl_repeat1); repeatButton.setTag(Theme.key_player_buttonActive); repeatButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_player_buttonActive), PorterDuff.Mode.MULTIPLY)); + repeatButton.setContentDescription(LocaleController.getString("AccDescrRepeatOne", R.string.AccDescrRepeatOne)); } } @@ -1162,8 +1109,10 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. if (MediaController.getInstance().isMessagePaused()) { playButton.setImageDrawable(Theme.createSimpleSelectorDrawable(playButton.getContext(), R.drawable.pl_play, Theme.getColor(Theme.key_player_button), Theme.getColor(Theme.key_player_buttonActive))); + playButton.setContentDescription(LocaleController.getString("AccActionPlay", R.string.AccActionPlay)); } else { playButton.setImageDrawable(Theme.createSimpleSelectorDrawable(playButton.getContext(), R.drawable.pl_pause, Theme.getColor(Theme.key_player_button), Theme.getColor(Theme.key_player_buttonActive))); + playButton.setContentDescription(LocaleController.getString("AccActionPause", R.string.AccActionPause)); } String title = messageObject.getMusicTitle(); String author = messageObject.getMusicAuthor(); @@ -1311,7 +1260,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. if (search1.equals(search2) || search2.length() == 0) { search2 = null; } - String search[] = new String[1 + (search2 != null ? 1 : 0)]; + String[] search = new String[1 + (search2 != null ? 1 : 0)]; search[0] = search1; if (search2 != null) { search[1] = search2; 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 22b87c2dc..154626606 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java @@ -19,6 +19,11 @@ import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; +import com.airbnb.lottie.LottieProperty; +import com.airbnb.lottie.SimpleColorFilter; +import com.airbnb.lottie.model.KeyPath; +import com.airbnb.lottie.value.LottieValueCallback; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLog; import org.telegram.tgnet.TLRPC; @@ -34,9 +39,15 @@ public class AvatarDrawable extends Drawable { private float textLeft; private boolean isProfile; private boolean drawBrodcast; - private int savedMessages; + private int avatarType; + private float archivedAvatarProgress; private StringBuilder stringBuilder = new StringBuilder(5); + public static final int AVATAR_TYPE_NORMAL = 0; + public static final int AVATAR_TYPE_SAVED = 1; + public static final int AVATAR_TYPE_SAVED_SMALL = 2; + public static final int AVATAR_TYPE_ARCHIVED = 3; + public AvatarDrawable() { super(); @@ -114,9 +125,21 @@ public class AvatarDrawable extends Drawable { } } - public void setSavedMessages(int value) { - savedMessages = value; - color = Theme.getColor(Theme.key_avatar_backgroundSaved); + public void setAvatarType(int value) { + avatarType = value; + if (avatarType == AVATAR_TYPE_ARCHIVED) { + color = Theme.getColor(Theme.key_avatar_backgroundArchivedHidden); + } else { + color = Theme.getColor(Theme.key_avatar_backgroundSaved); + } + } + + public void setArchivedAvatarHiddenProgress(float progress) { + archivedAvatarProgress = progress; + } + + public int getAvatarType() { + return avatarType; } public void setInfo(TLRPC.Chat chat) { @@ -149,7 +172,7 @@ public class AvatarDrawable extends Drawable { } drawBrodcast = isBroadcast; - savedMessages = 0; + avatarType = AVATAR_TYPE_NORMAL; if (firstName == null || firstName.length() == 0) { firstName = lastName; @@ -220,10 +243,35 @@ public class AvatarDrawable extends Drawable { canvas.translate(bounds.left, bounds.top); canvas.drawCircle(size / 2.0f, size / 2.0f, size / 2.0f, Theme.avatar_backgroundPaint); - if (savedMessages != 0 && Theme.avatar_savedDrawable != null) { + if (avatarType == AVATAR_TYPE_ARCHIVED) { + if (archivedAvatarProgress != 0) { + Theme.avatar_backgroundPaint.setColor(Theme.getColor(Theme.key_avatar_backgroundArchived)); + canvas.drawCircle(size / 2.0f, size / 2.0f, size / 2.0f * archivedAvatarProgress, Theme.avatar_backgroundPaint); + if (Theme.dialogs_archiveAvatarDrawableRecolored) { + Theme.dialogs_archiveAvatarDrawable.addValueCallback(new KeyPath("Arrow1", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_avatar_backgroundArchived)))); + Theme.dialogs_archiveAvatarDrawable.addValueCallback(new KeyPath("Arrow2", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_avatar_backgroundArchived)))); + Theme.dialogs_archiveAvatarDrawableRecolored = false; + } + } else { + if (!Theme.dialogs_archiveAvatarDrawableRecolored) { + Theme.dialogs_archiveAvatarDrawable.addValueCallback(new KeyPath("Arrow1", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_avatar_backgroundArchivedHidden)))); + Theme.dialogs_archiveAvatarDrawable.addValueCallback(new KeyPath("Arrow2", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_avatar_backgroundArchivedHidden)))); + Theme.dialogs_archiveAvatarDrawableRecolored = true; + } + } + int w = Theme.dialogs_archiveAvatarDrawable.getIntrinsicWidth(); + int h = Theme.dialogs_archiveAvatarDrawable.getIntrinsicHeight(); + int x = (size - w) / 2; + int y = (size - h) / 2; + canvas.save(); + canvas.translate(x, y); + Theme.dialogs_archiveAvatarDrawable.setBounds(x, y, x + w, y + h); + Theme.dialogs_archiveAvatarDrawable.draw(canvas); + canvas.restore(); + } else if (avatarType != 0 && Theme.avatar_savedDrawable != null) { int w = Theme.avatar_savedDrawable.getIntrinsicWidth(); int h = Theme.avatar_savedDrawable.getIntrinsicHeight(); - if (savedMessages == 2) { + if (avatarType == AVATAR_TYPE_SAVED_SMALL) { w *= 0.8f; h *= 0.8f; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java index 2d3ac6036..b1f80b0e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java @@ -18,9 +18,9 @@ import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.SecureDocument; -import org.telegram.tgnet.TLObject; public class BackupImageView extends View { @@ -47,55 +47,55 @@ public class BackupImageView extends View { imageReceiver = new ImageReceiver(this); } - public void setImage(SecureDocument path, String filter) { - setImage(path, filter, null, null, null, null, null, 0, null); - } - - public void setImage(TLObject path, String filter, String ext, Drawable thumb, Object parentObject) { - setImage(path, filter, thumb, null, null, null, ext, 0, parentObject); - } - - public void setImage(TLObject path, String filter, Drawable thumb, Object parentObject) { - setImage(path, filter, thumb, null, null, null, null, 0, parentObject); - } - - public void setImage(TLObject path, String filter, Bitmap thumb, Object parentObject) { - setImage(path, filter, null, thumb, null, null, null, 0, parentObject); - } - - public void setImage(TLObject path, String filter, Drawable thumb, int size, Object parentObject) { - setImage(path, filter, thumb, null, null, null, null, size, parentObject); - } - - public void setImage(TLObject path, String filter, Bitmap thumb, int size, Object parentObject) { - setImage(path, filter, null, thumb, null, null, null, size, parentObject); - } - - public void setImage(TLObject path, String filter, TLObject thumb, int size, Object parentObject) { - setImage(path, filter, null, null, thumb, null, null, size, parentObject); - } - - public void setImage(String path, String filter, Drawable thumb) { - setImage(path, filter, thumb, null, null, null, null, 0, null); - } - - public void setImage(String path, String filter, String thumbPath, String thumbFilter) { - setImage(path, filter, null, null, thumbPath, thumbFilter, null, 0, null); - } - public void setOrientation(int angle, boolean center) { imageReceiver.setOrientation(angle, center); } - public void setImage(Object path, String filter, Drawable thumb, Bitmap thumbBitmap, Object thumbLocation, String thumbFilter, String ext, int size, Object parentObject) { + public void setImage(SecureDocument secureDocument, String filter) { + setImage(ImageLocation.getForSecureDocument(secureDocument), filter, null, null, null, null, null, 0, null); + } + + public void setImage(ImageLocation imageLocation, String imageFilter, String ext, Drawable thumb, Object parentObject) { + setImage(imageLocation, imageFilter, null, null, thumb, null, ext, 0, parentObject); + } + + public void setImage(ImageLocation imageLocation, String imageFilter, Drawable thumb, Object parentObject) { + setImage(imageLocation, imageFilter, null, null, thumb, null, null, 0, parentObject); + } + + public void setImage(ImageLocation imageLocation, String imageFilter, Bitmap thumb, Object parentObject) { + setImage(imageLocation, imageFilter, null, null, null, thumb, null, 0, parentObject); + } + + public void setImage(ImageLocation imageLocation, String imageFilter, Drawable thumb, int size, Object parentObject) { + setImage(imageLocation, imageFilter, null, null, thumb, null, null, size, parentObject); + } + + public void setImage(ImageLocation imageLocation, String imageFilter, Bitmap thumb, int size, Object parentObject) { + setImage(imageLocation, imageFilter, null, null, null, thumb, null, size, parentObject); + } + + public void setImage(ImageLocation imageLocation, String imageFilter, ImageLocation thumbLocation, String thumbFilter, int size, Object parentObject) { + setImage(imageLocation, imageFilter, thumbLocation, thumbFilter, null, null, null, size, parentObject); + } + + public void setImage(String path, String filter, Drawable thumb) { + setImage(ImageLocation.getForPath(path), filter, null, null, thumb, null, null, 0, null); + } + + public void setImage(String path, String filter, String thumbPath, String thumbFilter) { + setImage(ImageLocation.getForPath(path), filter, ImageLocation.getForPath(thumbPath), thumbFilter, null, null, null, 0, null); + } + + public void setImage(ImageLocation imageLocation, String imageFilter, ImageLocation thumbLocation, String thumbFilter, Drawable thumb, Bitmap thumbBitmap, String ext, int size, Object parentObject) { if (thumbBitmap != null) { thumb = new BitmapDrawable(null, thumbBitmap); } - imageReceiver.setImage(path, filter, thumb, thumbLocation, thumbFilter, size, ext, parentObject, 0); + imageReceiver.setImage(imageLocation, imageFilter, thumbLocation, thumbFilter, thumb, size, ext, parentObject, 0); } - public void setImage(TLObject path, String filter, TLObject thumbLocation, String thumbFilter, String ext, int size, int cacheType, Object parentObject) { - imageReceiver.setImage(path, filter, null, thumbLocation, thumbFilter, size, ext, parentObject, cacheType); + public void setImage(ImageLocation imageLocation, String imageFilter, ImageLocation thumbLocation, String thumbFilter, String ext, int size, int cacheType, Object parentObject) { + imageReceiver.setImage(imageLocation, imageFilter, thumbLocation, thumbFilter, null, size, ext, parentObject, cacheType); } public void setImageBitmap(Bitmap bitmap) { 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 778a986e2..fbd12f3dc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BlockingUpdateView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BlockingUpdateView.java @@ -12,7 +12,7 @@ import android.graphics.Canvas; import android.net.Uri; import android.os.Build; import android.provider.Settings; -import android.support.v4.content.FileProvider; +import androidx.core.content.FileProvider; import android.text.SpannableStringBuilder; import android.util.TypedValue; import android.view.Gravity; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomPagesView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomPagesView.java new file mode 100644 index 000000000..1669971c8 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomPagesView.java @@ -0,0 +1,87 @@ +package org.telegram.ui.Components; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.view.View; +import android.view.animation.DecelerateInterpolator; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.ui.ActionBar.Theme; + +import androidx.viewpager.widget.ViewPager; + +public class BottomPagesView extends View { + + private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private float progress; + private int scrollPosition; + private int currentPage; + private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(); + private RectF rect = new RectF(); + private float animatedProgress; + private ViewPager viewPager; + private int pagesCount; + + private String colorKey; + private String selectedColorKey; + + public BottomPagesView(Context context, ViewPager pager, int count) { + super(context); + viewPager = pager; + pagesCount = count; + } + + public void setPageOffset(int position, float offset) { + progress = offset; + scrollPosition = position; + invalidate(); + } + + public void setCurrentPage(int page) { + currentPage = page; + invalidate(); + } + + public void setColor(String key, String selectedKey) { + colorKey = key; + selectedColorKey = selectedKey; + } + + @Override + protected void onDraw(Canvas canvas) { + float d = AndroidUtilities.dp(5); + if (colorKey != null) { + paint.setColor((Theme.getColor(colorKey) & 0x00ffffff) | 0xb4000000); + } else { + paint.setColor(0xffbbbbbb); + } + int x; + currentPage = viewPager.getCurrentItem(); + for (int a = 0; a < pagesCount; a++) { + if (a == currentPage) { + continue; + } + x = a * AndroidUtilities.dp(11); + rect.set(x, 0, x + AndroidUtilities.dp(5), AndroidUtilities.dp(5)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(2.5f), AndroidUtilities.dp(2.5f), paint); + } + if (selectedColorKey != null) { + paint.setColor(Theme.getColor(selectedColorKey)); + } else { + paint.setColor(0xff2ca5e0); + } + x = currentPage * AndroidUtilities.dp(11); + if (progress != 0) { + if (scrollPosition >= currentPage) { + rect.set(x, 0, x + AndroidUtilities.dp(5) + AndroidUtilities.dp(11) * progress, AndroidUtilities.dp(5)); + } else { + rect.set(x - AndroidUtilities.dp(11) * (1.0f - progress), 0, x + AndroidUtilities.dp(5), AndroidUtilities.dp(5)); + } + } else { + rect.set(x, 0, x + AndroidUtilities.dp(5), AndroidUtilities.dp(5)); + } + canvas.drawRoundRect(rect, AndroidUtilities.dp(2.5f), AndroidUtilities.dp(2.5f), paint); + } +} 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 b5a353d13..9b0cdfd58 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -13,6 +13,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.ClipDescription; import android.content.Context; @@ -30,12 +31,18 @@ import android.media.AudioManager; import android.os.Build; import android.os.Bundle; import android.os.PowerManager; -import android.support.annotation.Keep; -import android.support.v13.view.inputmethod.EditorInfoCompat; -import android.support.v13.view.inputmethod.InputConnectionCompat; -import android.support.v4.os.BuildCompat; +import androidx.annotation.Keep; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.view.inputmethod.EditorInfoCompat; +import androidx.core.view.inputmethod.InputConnectionCompat; +import androidx.core.os.BuildCompat; +import androidx.core.view.ViewCompat; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; +import androidx.customview.widget.ExploreByTouchHelper; import android.text.Editable; import android.text.InputFilter; +import android.text.Layout; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextWatcher; @@ -47,6 +54,9 @@ import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.view.inputmethod.EditorInfo; @@ -89,6 +99,8 @@ import org.telegram.ui.StickersActivity; import java.io.File; import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import java.util.Locale; public class ChatActivityEnterView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate, SizeNotifierFrameLayout.SizeNotifierFrameLayoutDelegate, StickersAlert.StickersAlertDelegate { @@ -171,32 +183,50 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } } + @SuppressWarnings("FieldCanBeLocal") + private View.AccessibilityDelegate mediaMessageButtonsDelegate = new View.AccessibilityDelegate() { + @Override + public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(host, info); + info.setClassName("android.widget.ImageButton"); + info.setClickable(true); + info.setLongClickable(true); + } + }; + private EditTextCaption messageEditText; private ImageView sendButton; private ImageView cancelBotButton; - private ImageView emojiButton; + private ImageView[] emojiButton = new ImageView[2]; private ImageView expandStickersButton; private EmojiView emojiView; + private boolean emojiViewVisible; private TextView recordTimeText; private FrameLayout audioVideoButtonContainer; private AnimatorSet audioVideoButtonAnimation; + private AnimatorSet emojiButtonAnimation; private ImageView audioSendButton; private ImageView videoSendButton; private FrameLayout recordPanel; private FrameLayout recordedAudioPanel; private VideoTimelineView videoTimelineView; + @SuppressWarnings("FieldCanBeLocal") private ImageView recordDeleteImageView; private SeekBarWaveformView recordedAudioSeekBar; private View recordedAudioBackground; private ImageView recordedAudioPlayButton; private TextView recordedAudioTimeTextView; private LinearLayout slideText; + @SuppressWarnings("FieldCanBeLocal") private ImageView recordCancelImage; + @SuppressWarnings("FieldCanBeLocal") private TextView recordCancelText; private TextView recordSendText; + @SuppressWarnings("FieldCanBeLocal") private LinearLayout recordTimeContainer; private RecordDot recordDot; private SizeNotifierFrameLayout sizeNotifierLayout; + private int originalViewHeight; private LinearLayout attachLayout; private ImageView attachButton; private ImageView botButton; @@ -207,6 +237,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe private AnimatorSet doneButtonAnimation; private ContextProgressView doneButtonProgress; private View topView; + private View topLineView; private PopupWindow botKeyboardPopup; private BotKeyboardView botKeyboardView; private ImageView notifyButton; @@ -215,7 +246,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe private Paint dotPaint; private Drawable playDrawable; private Drawable pauseDrawable; - private boolean searchingStickers; + private int searchingType; private boolean destroyed; @@ -228,6 +259,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe private boolean hasRecordVideo; private int currentPopupContentType = -1; + private int currentEmojiIcon = -1; private boolean silent; private boolean canWriteToChannel; @@ -302,6 +334,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } }; private Runnable updateExpandabilityRunnable = new Runnable() { + private int lastKnownPage = -1; @Override @@ -312,16 +345,23 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe lastKnownPage = curPage; boolean prevOpen = stickersTabOpen; stickersTabOpen = curPage == 1 || curPage == 2; - if (prevOpen != stickersTabOpen) { - checkSendButton(true); - } - if (!stickersTabOpen && stickersExpanded) { - if (searchingStickers) { - searchingStickers = false; - emojiView.closeSearch(true); - emojiView.hideSearchKeyboard(); + boolean prevOpen2 = emojiTabOpen; + emojiTabOpen = curPage == 0; + if (stickersExpanded) { + if (!stickersTabOpen && searchingType == 0) { + if (searchingType != 0) { + searchingType = 0; + emojiView.closeSearch(true); + emojiView.hideSearchKeyboard(); + } + setStickersExpanded(false, true, false); + } else if (searchingType != 0) { + searchingType = curPage == 0 ? 2 : 1; + checkStickresExpandHeight(); } - setStickersExpanded(false, true, false); + } + if (prevOpen != stickersTabOpen || prevOpen2 != emojiTabOpen) { + checkSendButton(true); } } } @@ -340,9 +380,22 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } }; + private Property recordCircleScale = new Property(Float.class, "scale") { + @Override + public Float get(RecordCircle object) { + return object.getScale(); + } + + @Override + public void set(RecordCircle object, Float value) { + object.setScale(value); + } + }; + private Paint redDotPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private boolean stickersTabOpen; + private boolean emojiTabOpen; private boolean gifsTabOpen; private boolean stickersExpanded; private boolean closeAnimationInProgress; @@ -481,6 +534,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe private boolean sendButtonVisible; private boolean pressed; + private VirtualViewHelper virtualViewHelper; + public RecordCircle(Context context) { super(context); paint.setColor(Theme.getColor(Theme.key_chat_messagePanelVoiceBackground)); @@ -497,14 +552,17 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe lockShadowDrawable = getResources().getDrawable(R.drawable.lock_round_shadow); lockShadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoiceLockShadow), PorterDuff.Mode.MULTIPLY)); - micDrawable = getResources().getDrawable(R.drawable.mic).mutate(); + micDrawable = getResources().getDrawable(R.drawable.input_mic).mutate(); micDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoicePressed), PorterDuff.Mode.MULTIPLY)); - cameraDrawable = getResources().getDrawable(R.drawable.ic_msg_panel_video).mutate(); + cameraDrawable = getResources().getDrawable(R.drawable.input_video).mutate(); cameraDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoicePressed), PorterDuff.Mode.MULTIPLY)); sendDrawable = getResources().getDrawable(R.drawable.ic_send).mutate(); sendDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoicePressed), PorterDuff.Mode.MULTIPLY)); + + virtualViewHelper = new VirtualViewHelper(this); + ViewCompat.setAccessibilityDelegate(this, virtualViewHelper); } public void setAmplitude(double value) { @@ -696,8 +754,57 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe canvas.drawRoundRect(rect, AndroidUtilities.dp(1), AndroidUtilities.dp(1), redDotPaint); } } + + @Override + protected boolean dispatchHoverEvent(MotionEvent event) { + return super.dispatchHoverEvent(event) || virtualViewHelper.dispatchHoverEvent(event); + } + + private class VirtualViewHelper extends ExploreByTouchHelper { + + public VirtualViewHelper(@NonNull View host) { + super(host); + } + + @Override + protected int getVirtualViewAt(float x, float y) { + if (isSendButtonVisible()) { + if (sendDrawable.getBounds().contains((int) x, (int) y)) { + return 1; + } else if (lockBackgroundDrawable.getBounds().contains((int) x, (int) y)) { + return 2; + } + } + return HOST_ID; + } + + @Override + protected void getVisibleVirtualViews(List list) { + if(isSendButtonVisible()) { + list.add(1); + list.add(2); + } + } + + @Override + protected void onPopulateNodeForVirtualView(int id, @NonNull AccessibilityNodeInfoCompat info) { + if (id == 1) { + info.setBoundsInParent(sendDrawable.getBounds()); + info.setText(LocaleController.getString("Send", R.string.Send)); + } else if(id == 2) { + info.setBoundsInParent(lockBackgroundDrawable.getBounds()); + info.setText(LocaleController.getString("Stop", R.string.Stop)); + } + } + + @Override + protected boolean onPerformActionForVirtualView(int id, int action, @Nullable Bundle args) { + return true; + } + } } + @SuppressLint("ClickableViewAccessibility") public ChatActivityEnterView(Activity context, SizeNotifierFrameLayout parent, ChatActivity fragment, final boolean isChat) { super(context); @@ -728,44 +835,48 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe textFieldContainer = new LinearLayout(context); textFieldContainer.setOrientation(LinearLayout.HORIZONTAL); - addView(textFieldContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 2, 0, 0)); + addView(textFieldContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM, 0, 2, 0, 0)); FrameLayout frameLayout = new FrameLayout(context); - textFieldContainer.addView(frameLayout, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, 1.0f)); + textFieldContainer.addView(frameLayout, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, 1.0f, Gravity.BOTTOM)); - emojiButton = new ImageView(context) { - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - if (attachLayout != null && (emojiView == null || emojiView.getVisibility() != VISIBLE) && !DataQuery.getInstance(currentAccount).getUnreadStickerSets().isEmpty() && dotPaint != null) { - int x = getWidth() / 2 + AndroidUtilities.dp(4 + 5); - int y = getHeight() / 2 - AndroidUtilities.dp(13 - 5); - canvas.drawCircle(x, y, AndroidUtilities.dp(5), dotPaint); + for (int a = 0; a < 2; a++) { + emojiButton[a] = new ImageView(context) { + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (getTag() != null && attachLayout != null && !emojiViewVisible && !DataQuery.getInstance(currentAccount).getUnreadStickerSets().isEmpty() && dotPaint != null) { + int x = getWidth() / 2 + AndroidUtilities.dp(4 + 5); + int y = getHeight() / 2 - AndroidUtilities.dp(13 - 5); + canvas.drawCircle(x, y, AndroidUtilities.dp(5), dotPaint); + } } - } - }; - emojiButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); - emojiButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - emojiButton.setPadding(0, AndroidUtilities.dp(1), 0, 0); -// if (Build.VERSION.SDK_INT >= 21) { -// emojiButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.INPUT_FIELD_SELECTOR_COLOR)); -// } - setEmojiButtonImage(); - frameLayout.addView(emojiButton, LayoutHelper.createFrame(48, 48, Gravity.BOTTOM | Gravity.LEFT, 3, 0, 0, 0)); - emojiButton.setOnClickListener(view -> { - if (!isPopupShowing() || currentPopupContentType != 0) { - showPopup(1, 0); - emojiView.onOpen(messageEditText.length() > 0 && !messageEditText.getText().toString().startsWith("@gif")); - } else { - if (searchingStickers) { - searchingStickers = false; - emojiView.closeSearch(false); - messageEditText.requestFocus(); + }; + emojiButton[a].setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); + emojiButton[a].setScaleType(ImageView.ScaleType.CENTER_INSIDE); + frameLayout.addView(emojiButton[a], LayoutHelper.createFrame(48, 48, Gravity.BOTTOM | Gravity.LEFT, 3, 0, 0, 0)); + emojiButton[a].setOnClickListener(view -> { + if (!isPopupShowing() || currentPopupContentType != 0) { + showPopup(1, 0); + emojiView.onOpen(messageEditText.length() > 0); + } else { + if (searchingType != 0) { + searchingType = 0; + emojiView.closeSearch(false); + messageEditText.requestFocus(); + } + openKeyboardInternal(); } - openKeyboardInternal(); - removeGifFromInputField(); + }); + emojiButton[a].setContentDescription(LocaleController.getString("AccDescrEmojiButton", R.string.AccDescrEmojiButton)); + if (a == 1) { + emojiButton[a].setVisibility(INVISIBLE); + emojiButton[a].setAlpha(0.0f); + emojiButton[a].setScaleX(0.1f); + emojiButton[a].setScaleY(0.1f); } - }); + } + setEmojiButtonImage(false, false); messageEditText = new EditTextCaption(context) { @Override @@ -798,8 +909,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe @Override public boolean onTouchEvent(MotionEvent event) { if (isPopupShowing() && event.getAction() == MotionEvent.ACTION_DOWN) { - if (searchingStickers) { - searchingStickers = false; + if (searchingType != 0) { + searchingType = 0; emojiView.closeSearch(false); } showPopup(AndroidUtilities.usingHardwareInput ? 0 : 2, 0); @@ -855,13 +966,12 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe SharedPreferences preferences = MessagesController.getMainSettings(currentAccount); preferences.edit().putInt("hidekeyboard_" + dialog_id, botButtonsMessageObject.getId()).commit(); } - if (searchingStickers) { - searchingStickers = false; + if (searchingType != 0) { + searchingType = 0; emojiView.closeSearch(true); messageEditText.requestFocus(); } else { showPopup(0, 0); - removeGifFromInputField(); } } return true; @@ -966,16 +1076,13 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe botButton = new ImageView(context); botButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); - botButton.setImageResource(R.drawable.bot_keyboard2); + botButton.setImageResource(R.drawable.input_bot2); botButton.setScaleType(ImageView.ScaleType.CENTER); botButton.setVisibility(GONE); -// if (Build.VERSION.SDK_INT >= 21) { -// botButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.INPUT_FIELD_SELECTOR_COLOR)); -// } attachLayout.addView(botButton, LayoutHelper.createLinear(48, 48)); botButton.setOnClickListener(v -> { - if (searchingStickers) { - searchingStickers = false; + if (searchingType != 0) { + searchingType = 0; emojiView.closeSearch(false); messageEditText.requestFocus(); } @@ -1002,13 +1109,11 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe }); notifyButton = new ImageView(context); - notifyButton.setImageResource(silent ? R.drawable.notify_members_off : R.drawable.notify_members_on); + notifyButton.setImageResource(silent ? R.drawable.input_notify_off : R.drawable.input_notify_on); + 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); -// if (Build.VERSION.SDK_INT >= 21) { -// notifyButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.INPUT_FIELD_SELECTOR_COLOR)); -// } attachLayout.addView(notifyButton, LayoutHelper.createLinear(48, 48)); notifyButton.setOnClickListener(new OnClickListener() { @@ -1017,7 +1122,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe @Override public void onClick(View v) { silent = !silent; - notifyButton.setImageResource(silent ? R.drawable.notify_members_off : R.drawable.notify_members_on); + notifyButton.setImageResource(silent ? R.drawable.input_notify_off : R.drawable.input_notify_on); MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("silent_" + dialog_id, silent).commit(); NotificationsController.getInstance(currentAccount).updateServerNotificationsSettings(dialog_id); try { @@ -1034,19 +1139,21 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe visibleToast = Toast.makeText(parentActivity, LocaleController.getString("ChannelNotifyMembersInfoOn", R.string.ChannelNotifyMembersInfoOn), Toast.LENGTH_SHORT); visibleToast.show(); } + notifyButton.setContentDescription(silent ? LocaleController.getString("AccDescrChanSilentOn", R.string.AccDescrChanSilentOn) : LocaleController.getString("AccDescrChanSilentOff", R.string.AccDescrChanSilentOff)); updateFieldHint(); } }); attachButton = new ImageView(context); attachButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); - attachButton.setImageResource(R.drawable.ic_ab_attach); + attachButton.setImageResource(R.drawable.input_attach); attachButton.setScaleType(ImageView.ScaleType.CENTER); // if (Build.VERSION.SDK_INT >= 21) { // attachButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.INPUT_FIELD_SELECTOR_COLOR)); // } attachLayout.addView(attachButton, LayoutHelper.createLinear(48, 48)); attachButton.setOnClickListener(v -> delegate.didPressedAttachButton()); + attachButton.setContentDescription(LocaleController.getString("AccDescrAttachButton", R.string.AccDescrAttachButton)); } recordedAudioPanel = new FrameLayout(context); @@ -1061,6 +1168,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe recordDeleteImageView.setScaleType(ImageView.ScaleType.CENTER); recordDeleteImageView.setImageResource(R.drawable.ic_ab_delete); recordDeleteImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelVoiceDelete), PorterDuff.Mode.MULTIPLY)); + recordDeleteImageView.setContentDescription(LocaleController.getString("Delete", R.string.Delete)); recordedAudioPanel.addView(recordDeleteImageView, LayoutHelper.createFrame(48, 48)); recordDeleteImageView.setOnClickListener(v -> { if (videoToSendMessageObject != null) { @@ -1126,6 +1234,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe recordedAudioPlayButton = new ImageView(context); recordedAudioPlayButton.setImageDrawable(playDrawable); recordedAudioPlayButton.setScaleType(ImageView.ScaleType.CENTER); + recordedAudioPlayButton.setContentDescription(LocaleController.getString("AccActionPlay", R.string.AccActionPlay)); recordedAudioPanel.addView(recordedAudioPlayButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.BOTTOM, 48, 0, 0, 0)); recordedAudioPlayButton.setOnClickListener(v -> { if (audioToSend == null) { @@ -1134,9 +1243,11 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe if (MediaController.getInstance().isPlayingMessage(audioToSendMessageObject) && !MediaController.getInstance().isMessagePaused()) { MediaController.getInstance().pauseMessage(audioToSendMessageObject); recordedAudioPlayButton.setImageDrawable(playDrawable); + recordedAudioPlayButton.setContentDescription(LocaleController.getString("AccActionPlay", R.string.AccActionPlay)); } else { recordedAudioPlayButton.setImageDrawable(pauseDrawable); MediaController.getInstance().playMessage(audioToSendMessageObject); + recordedAudioPlayButton.setContentDescription(LocaleController.getString("AccActionPause", R.string.AccActionPause)); } }); @@ -1247,6 +1358,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe delegate.onSwitchRecordMode(videoSendButton.getTag() == null); setRecordVideoButtonVisible(videoSendButton.getTag() == null, true); performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); } else if (!hasRecordVideo || calledRecordRunnable) { startedDraggingX = -1; if (hasRecordVideo && videoSendButton.getTag() != null) { @@ -1268,10 +1380,10 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe if (recordCircle.setLockTranslation(y) == 2) { AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(ObjectAnimator.ofFloat(recordCircle, "lockAnimatedTranslation", recordCircle.startTranslation), - ObjectAnimator.ofFloat(slideText, "alpha", 0.0f), - ObjectAnimator.ofFloat(slideText, "translationY", AndroidUtilities.dp(20)), - ObjectAnimator.ofFloat(recordSendText, "alpha", 1.0f), - ObjectAnimator.ofFloat(recordSendText, "translationY", -AndroidUtilities.dp(20), 0)); + ObjectAnimator.ofFloat(slideText, View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(slideText, View.TRANSLATION_Y, AndroidUtilities.dp(20)), + ObjectAnimator.ofFloat(recordSendText, View.ALPHA, 1.0f), + ObjectAnimator.ofFloat(recordSendText, View.TRANSLATION_Y, -AndroidUtilities.dp(20), 0)); animatorSet.setInterpolator(new DecelerateInterpolator()); animatorSet.setDuration(150); animatorSet.start(); @@ -1328,16 +1440,22 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe audioSendButton = new ImageView(context); audioSendButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE); audioSendButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); - audioSendButton.setImageResource(R.drawable.mic); + audioSendButton.setImageResource(R.drawable.input_mic); audioSendButton.setPadding(0, 0, AndroidUtilities.dp(4), 0); + audioSendButton.setContentDescription(LocaleController.getString("AccDescrVoiceMessage", R.string.AccDescrVoiceMessage)); + audioSendButton.setFocusable(true); + audioSendButton.setAccessibilityDelegate(mediaMessageButtonsDelegate); audioVideoButtonContainer.addView(audioSendButton, LayoutHelper.createFrame(48, 48)); if (isChat) { videoSendButton = new ImageView(context); videoSendButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE); videoSendButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); - videoSendButton.setImageResource(R.drawable.ic_msg_panel_video); + videoSendButton.setImageResource(R.drawable.input_video); videoSendButton.setPadding(0, 0, AndroidUtilities.dp(4), 0); + videoSendButton.setContentDescription(LocaleController.getString("AccDescrVideoMessage", R.string.AccDescrVideoMessage)); + videoSendButton.setFocusable(true); + videoSendButton.setAccessibilityDelegate(mediaMessageButtonsDelegate); audioVideoButtonContainer.addView(videoSendButton, LayoutHelper.createFrame(48, 48)); } @@ -1349,6 +1467,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe cancelBotButton.setVisibility(INVISIBLE); cancelBotButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE); cancelBotButton.setImageDrawable(progressDrawable = new CloseProgressDrawable2()); + cancelBotButton.setContentDescription(LocaleController.getString("Cancel", R.string.Cancel)); progressDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelCancelInlineBot), PorterDuff.Mode.MULTIPLY)); cancelBotButton.setSoundEffectsEnabled(false); cancelBotButton.setScaleX(0.1f); @@ -1370,6 +1489,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe sendButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE); sendButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelSend), PorterDuff.Mode.MULTIPLY)); sendButton.setImageResource(R.drawable.ic_send); + sendButton.setContentDescription(LocaleController.getString("Send", R.string.Send)); sendButton.setSoundEffectsEnabled(false); sendButton.setScaleX(0.1f); sendButton.setScaleY(0.1f); @@ -1378,6 +1498,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe sendButton.setOnClickListener(view -> sendMessage()); expandStickersButton = new ImageView(context); + expandStickersButton.setPadding(0, 0, AndroidUtilities.dp(4), 0); expandStickersButton.setScaleType(ImageView.ScaleType.CENTER); expandStickersButton.setImageDrawable(stickersArrow = new AnimatedArrowDrawable(Theme.getColor(Theme.key_chat_messagePanelIcons), false)); expandStickersButton.setVisibility(GONE); @@ -1390,10 +1511,13 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe return; } if (stickersExpanded) { - if (searchingStickers) { - searchingStickers = false; + if (searchingType != 0) { + searchingType = 0; emojiView.closeSearch(true); emojiView.hideSearchKeyboard(); + if (emojiTabOpen) { + checkSendButton(true); + } } else if (!stickersDragging) { if (emojiView != null) { emojiView.showSearchField(false); @@ -1406,20 +1530,23 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe setStickersExpanded(!stickersExpanded, true, false); } }); - + expandStickersButton.setContentDescription(LocaleController.getString("AccDescrExpandPanel", R.string.AccDescrExpandPanel)); doneButtonContainer = new FrameLayout(context); doneButtonContainer.setVisibility(GONE); textFieldContainer.addView(doneButtonContainer, LayoutHelper.createLinear(48, 48, Gravity.BOTTOM)); -// if (Build.VERSION.SDK_INT >= 21) { -// doneButtonContainer.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.INPUT_FIELD_SELECTOR_COLOR)); -// } doneButtonContainer.setOnClickListener(view -> doneEditingMessage()); + Drawable drawable = Theme.createCircleDrawable(AndroidUtilities.dp(16), Theme.getColor(Theme.key_chat_messagePanelSend)); + Drawable checkDrawable = context.getResources().getDrawable(R.drawable.input_done).mutate(); + checkDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelBackground), PorterDuff.Mode.MULTIPLY)); + CombinedDrawable combinedDrawable = new CombinedDrawable(drawable, checkDrawable, 0, AndroidUtilities.dp(1)); + combinedDrawable.setCustomSize(AndroidUtilities.dp(32), AndroidUtilities.dp(32)); + doneButtonImage = new ImageView(context); doneButtonImage.setScaleType(ImageView.ScaleType.CENTER); - doneButtonImage.setImageResource(R.drawable.edit_done); - doneButtonImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_editDoneIcon), PorterDuff.Mode.MULTIPLY)); + doneButtonImage.setImageDrawable(combinedDrawable); + doneButtonImage.setContentDescription(LocaleController.getString("Done", R.string.Done)); doneButtonContainer.addView(doneButtonImage, LayoutHelper.createFrame(48, 48)); doneButtonProgress = new ContextProgressView(context, 0); @@ -1485,18 +1612,19 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe preferences.edit().putBoolean(isChannel ? "currentModeVideoChannel" : "currentModeVideo", visible).commit(); audioVideoButtonAnimation = new AnimatorSet(); audioVideoButtonAnimation.playTogether( - ObjectAnimator.ofFloat(videoSendButton, "scaleX", visible ? 1.0f : 0.1f), - ObjectAnimator.ofFloat(videoSendButton, "scaleY", visible ? 1.0f : 0.1f), - ObjectAnimator.ofFloat(videoSendButton, "alpha", visible ? 1.0f : 0.0f), - ObjectAnimator.ofFloat(audioSendButton, "scaleX", visible ? 0.1f : 1.0f), - ObjectAnimator.ofFloat(audioSendButton, "scaleY", visible ? 0.1f : 1.0f), - ObjectAnimator.ofFloat(audioSendButton, "alpha", visible ? 0.0f : 1.0f)); + ObjectAnimator.ofFloat(videoSendButton, View.SCALE_X, visible ? 1.0f : 0.1f), + ObjectAnimator.ofFloat(videoSendButton, View.SCALE_Y, visible ? 1.0f : 0.1f), + ObjectAnimator.ofFloat(videoSendButton, View.ALPHA, visible ? 1.0f : 0.0f), + ObjectAnimator.ofFloat(audioSendButton, View.SCALE_X, visible ? 0.1f : 1.0f), + ObjectAnimator.ofFloat(audioSendButton, View.SCALE_Y, visible ? 0.1f : 1.0f), + ObjectAnimator.ofFloat(audioSendButton, View.ALPHA, visible ? 0.0f : 1.0f)); audioVideoButtonAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (animation.equals(audioVideoButtonAnimation)) { audioVideoButtonAnimation = null; } + (videoSendButton.getTag()==null ? audioSendButton : videoSendButton).sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); } }); audioVideoButtonAnimation.setInterpolator(new DecelerateInterpolator()); @@ -1550,10 +1678,15 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } } - public void addTopView(View view, int height) { + public void addTopView(View view, View lineView, int height) { if (view == null) { return; } + topLineView = lineView; + topLineView.setVisibility(GONE); + topLineView.setAlpha(0.0f); + addView(topLineView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1, Gravity.TOP | Gravity.LEFT, 0, 1 + height, 0, 0)); + topView = view; topView.setVisibility(GONE); topView.setTranslationY(height); @@ -1568,7 +1701,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe public void setAllowStickersAndGifs(boolean value, boolean value2) { if ((allowStickers != value || allowGifs != value2) && emojiView != null) { - if (emojiView.getVisibility() == VISIBLE) { + if (emojiViewVisible) { hidePopup(false); } sizeNotifierLayout.removeView(emojiView); @@ -1576,7 +1709,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } allowStickers = value; allowGifs = value2; - setEmojiButtonImage(); + setEmojiButtonImage(false, !isPaused); } public void addEmojiToRecent(String code) { @@ -1601,47 +1734,35 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe topViewShowed = true; if (allowShowTopView) { topView.setVisibility(VISIBLE); + topLineView.setVisibility(VISIBLE); if (currentTopViewAnimation != null) { currentTopViewAnimation.cancel(); currentTopViewAnimation = null; } resizeForTopView(true); if (animated) { - if (keyboardVisible || isPopupShowing()) { - currentTopViewAnimation = new AnimatorSet(); - currentTopViewAnimation.playTogether(ObjectAnimator.ofFloat(topView, "translationY", 0)); - currentTopViewAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (currentTopViewAnimation != null && currentTopViewAnimation.equals(animation)) { - if (recordedAudioPanel.getVisibility() != VISIBLE && (!forceShowSendButton || openKeyboard)) { - openKeyboard(); - } - currentTopViewAnimation = null; - } + currentTopViewAnimation = new AnimatorSet(); + currentTopViewAnimation.playTogether( + ObjectAnimator.ofFloat(topView, View.TRANSLATION_Y, 0), + ObjectAnimator.ofFloat(topLineView, View.ALPHA, 1.0f)); + currentTopViewAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (currentTopViewAnimation != null && currentTopViewAnimation.equals(animation)) { + currentTopViewAnimation = null; } - - @Override - public void onAnimationCancel(Animator animation) { - if (currentTopViewAnimation != null && currentTopViewAnimation.equals(animation)) { - currentTopViewAnimation = null; - } - } - }); - currentTopViewAnimation.setDuration(200); - currentTopViewAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT); - currentTopViewAnimation.start(); - } else { - topView.setTranslationY(0); - if (recordedAudioPanel.getVisibility() != VISIBLE && (!forceShowSendButton || openKeyboard)) { - openKeyboard(); } - } + }); + currentTopViewAnimation.setDuration(250); + currentTopViewAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT); + currentTopViewAnimation.start(); } else { topView.setTranslationY(0); - if (recordedAudioPanel.getVisibility() != VISIBLE && (!forceShowSendButton || openKeyboard)) { - openKeyboard(); - } + topLineView.setAlpha(1.0f); + } + if (recordedAudioPanel.getVisibility() != VISIBLE && (!forceShowSendButton || openKeyboard)) { + messageEditText.requestFocus(); + openKeyboard(); } } } @@ -1682,22 +1803,22 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe doneButtonProgress.setVisibility(View.VISIBLE); doneButtonContainer.setEnabled(false); doneButtonAnimation.playTogether( - ObjectAnimator.ofFloat(doneButtonImage, "scaleX", 0.1f), - ObjectAnimator.ofFloat(doneButtonImage, "scaleY", 0.1f), - ObjectAnimator.ofFloat(doneButtonImage, "alpha", 0.0f), - ObjectAnimator.ofFloat(doneButtonProgress, "scaleX", 1.0f), - ObjectAnimator.ofFloat(doneButtonProgress, "scaleY", 1.0f), - ObjectAnimator.ofFloat(doneButtonProgress, "alpha", 1.0f)); + ObjectAnimator.ofFloat(doneButtonImage, View.SCALE_X, 0.1f), + ObjectAnimator.ofFloat(doneButtonImage, View.SCALE_Y, 0.1f), + ObjectAnimator.ofFloat(doneButtonImage, View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(doneButtonProgress, View.SCALE_X, 1.0f), + ObjectAnimator.ofFloat(doneButtonProgress, View.SCALE_Y, 1.0f), + ObjectAnimator.ofFloat(doneButtonProgress, View.ALPHA, 1.0f)); } else { doneButtonImage.setVisibility(View.VISIBLE); doneButtonContainer.setEnabled(true); doneButtonAnimation.playTogether( - ObjectAnimator.ofFloat(doneButtonProgress, "scaleX", 0.1f), - ObjectAnimator.ofFloat(doneButtonProgress, "scaleY", 0.1f), - ObjectAnimator.ofFloat(doneButtonProgress, "alpha", 0.0f), - ObjectAnimator.ofFloat(doneButtonImage, "scaleX", 1.0f), - ObjectAnimator.ofFloat(doneButtonImage, "scaleY", 1.0f), - ObjectAnimator.ofFloat(doneButtonImage, "alpha", 1.0f)); + ObjectAnimator.ofFloat(doneButtonProgress, View.SCALE_X, 0.1f), + ObjectAnimator.ofFloat(doneButtonProgress, View.SCALE_Y, 0.1f), + ObjectAnimator.ofFloat(doneButtonProgress, View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(doneButtonImage, View.SCALE_X, 1.0f), + ObjectAnimator.ofFloat(doneButtonImage, View.SCALE_Y, 1.0f), + ObjectAnimator.ofFloat(doneButtonImage, View.ALPHA, 1.0f)); } doneButtonAnimation.addListener(new AnimatorListenerAdapter() { @@ -1738,12 +1859,15 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } if (animated) { currentTopViewAnimation = new AnimatorSet(); - currentTopViewAnimation.playTogether(ObjectAnimator.ofFloat(topView, "translationY", topView.getLayoutParams().height)); + currentTopViewAnimation.playTogether( + ObjectAnimator.ofFloat(topView, View.TRANSLATION_Y, topView.getLayoutParams().height), + ObjectAnimator.ofFloat(topLineView, View.ALPHA, 0.0f)); currentTopViewAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (currentTopViewAnimation != null && currentTopViewAnimation.equals(animation)) { topView.setVisibility(GONE); + topLineView.setVisibility(GONE); resizeForTopView(false); currentTopViewAnimation = null; } @@ -1761,6 +1885,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe currentTopViewAnimation.start(); } else { topView.setVisibility(GONE); + topLineView.setVisibility(GONE); + topLineView.setAlpha(0.0f); resizeForTopView(false); topView.setTranslationY(topView.getLayoutParams().height); } @@ -1785,6 +1911,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe allowShowTopView = false; if (needShowTopView) { topView.setVisibility(GONE); + topLineView.setVisibility(GONE); + topLineView.setAlpha(0.0f); resizeForTopView(false); topView.setTranslationY(topView.getLayoutParams().height); } @@ -1794,6 +1922,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe allowShowTopView = true; if (needShowTopView) { topView.setVisibility(VISIBLE); + topLineView.setVisibility(VISIBLE); + topLineView.setAlpha(1.0f); resizeForTopView(true); topView.setTranslationY(0); } @@ -1806,8 +1936,13 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe LayoutParams layoutParams = (LayoutParams) textFieldContainer.getLayoutParams(); layoutParams.topMargin = AndroidUtilities.dp(2) + (show ? topView.getLayoutParams().height : 0); textFieldContainer.setLayoutParams(layoutParams); + setMinimumHeight(AndroidUtilities.dp(51) + (show ? topView.getLayoutParams().height : 0)); if (stickersExpanded) { - setStickersExpanded(false, true, false); + if (searchingType == 0) { + setStickersExpanded(false, true, false); + } else { + checkStickresExpandHeight(); + } } } @@ -1862,7 +1997,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe isPaused = false; if (showKeyboardOnResume) { showKeyboardOnResume = false; - if (!searchingStickers) { + if (searchingType == 0) { messageEditText.requestFocus(); } AndroidUtilities.showKeyboard(messageEditText); @@ -1908,7 +2043,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe 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.notify_members_off : R.drawable.notify_members_on); + 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) { @@ -2029,7 +2164,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe videoTimelineView.destroy(); AnimatorSet AnimatorSet = new AnimatorSet(); AnimatorSet.playTogether( - ObjectAnimator.ofFloat(recordedAudioPanel, "alpha", 0.0f) + ObjectAnimator.ofFloat(recordedAudioPanel, View.ALPHA, 0.0f) ); AnimatorSet.setDuration(200); AnimatorSet.addListener(new AnimatorListenerAdapter() { @@ -2043,6 +2178,13 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } private void sendMessage() { + if (stickersExpanded) { + setStickersExpanded(false, true, false); + if (searchingType != 0) { + emojiView.closeSearch(false); + emojiView.hideSearchKeyboard(); + } + } if (videoToSendMessageObject != null) { delegate.needStartRecordVideo(4); hideRecordedAudioPanel(); @@ -2132,8 +2274,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe if (attachLayout != null) { runningAnimation2 = new AnimatorSet(); runningAnimation2.playTogether( - ObjectAnimator.ofFloat(attachLayout, "alpha", 0.0f), - ObjectAnimator.ofFloat(attachLayout, "scaleX", 0.0f) + ObjectAnimator.ofFloat(attachLayout, View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(attachLayout, View.SCALE_X, 0.0f) ); runningAnimation2.setDuration(100); runningAnimation2.addListener(new AnimatorListenerAdapter() { @@ -2162,35 +2304,35 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe ArrayList animators = new ArrayList<>(); if (audioVideoButtonContainer.getVisibility() == VISIBLE) { - animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, "scaleX", 0.1f)); - animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, "scaleY", 0.1f)); - animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, View.SCALE_X, 0.1f)); + animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, View.SCALE_Y, 0.1f)); + animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, View.ALPHA, 0.0f)); } if (expandStickersButton.getVisibility() == VISIBLE) { - animators.add(ObjectAnimator.ofFloat(expandStickersButton, "scaleX", 0.1f)); - animators.add(ObjectAnimator.ofFloat(expandStickersButton, "scaleY", 0.1f)); - animators.add(ObjectAnimator.ofFloat(expandStickersButton, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(expandStickersButton, View.SCALE_X, 0.1f)); + animators.add(ObjectAnimator.ofFloat(expandStickersButton, View.SCALE_Y, 0.1f)); + animators.add(ObjectAnimator.ofFloat(expandStickersButton, View.ALPHA, 0.0f)); } if (showBotButton) { - animators.add(ObjectAnimator.ofFloat(sendButton, "scaleX", 0.1f)); - animators.add(ObjectAnimator.ofFloat(sendButton, "scaleY", 0.1f)); - animators.add(ObjectAnimator.ofFloat(sendButton, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(sendButton, View.SCALE_X, 0.1f)); + animators.add(ObjectAnimator.ofFloat(sendButton, View.SCALE_Y, 0.1f)); + animators.add(ObjectAnimator.ofFloat(sendButton, View.ALPHA, 0.0f)); } else if (showSendButton) { - animators.add(ObjectAnimator.ofFloat(cancelBotButton, "scaleX", 0.1f)); - animators.add(ObjectAnimator.ofFloat(cancelBotButton, "scaleY", 0.1f)); - animators.add(ObjectAnimator.ofFloat(cancelBotButton, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(cancelBotButton, View.SCALE_X, 0.1f)); + animators.add(ObjectAnimator.ofFloat(cancelBotButton, View.SCALE_Y, 0.1f)); + animators.add(ObjectAnimator.ofFloat(cancelBotButton, View.ALPHA, 0.0f)); } if (caption != null) { runningAnimationType = 3; - animators.add(ObjectAnimator.ofFloat(cancelBotButton, "scaleX", 1.0f)); - animators.add(ObjectAnimator.ofFloat(cancelBotButton, "scaleY", 1.0f)); - animators.add(ObjectAnimator.ofFloat(cancelBotButton, "alpha", 1.0f)); + animators.add(ObjectAnimator.ofFloat(cancelBotButton, View.SCALE_X, 1.0f)); + animators.add(ObjectAnimator.ofFloat(cancelBotButton, View.SCALE_Y, 1.0f)); + animators.add(ObjectAnimator.ofFloat(cancelBotButton, View.ALPHA, 1.0f)); cancelBotButton.setVisibility(VISIBLE); } else { runningAnimationType = 1; - animators.add(ObjectAnimator.ofFloat(sendButton, "scaleX", 1.0f)); - animators.add(ObjectAnimator.ofFloat(sendButton, "scaleY", 1.0f)); - animators.add(ObjectAnimator.ofFloat(sendButton, "alpha", 1.0f)); + animators.add(ObjectAnimator.ofFloat(sendButton, View.SCALE_X, 1.0f)); + animators.add(ObjectAnimator.ofFloat(sendButton, View.SCALE_Y, 1.0f)); + animators.add(ObjectAnimator.ofFloat(sendButton, View.ALPHA, 1.0f)); sendButton.setVisibility(VISIBLE); } @@ -2255,7 +2397,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } } } - } else if (emojiView != null && emojiView.getVisibility() == VISIBLE && stickersTabOpen && !AndroidUtilities.isInMultiwindow) { + } else if (emojiView != null && emojiViewVisible && (stickersTabOpen || emojiTabOpen && searchingType == 2) && !AndroidUtilities.isInMultiwindow) { if (animated) { if (runningAnimationType == 4) { return; @@ -2274,8 +2416,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe attachLayout.setVisibility(VISIBLE); runningAnimation2 = new AnimatorSet(); runningAnimation2.playTogether( - ObjectAnimator.ofFloat(attachLayout, "alpha", 1.0f), - ObjectAnimator.ofFloat(attachLayout, "scaleX", 1.0f) + ObjectAnimator.ofFloat(attachLayout, View.ALPHA, 1.0f), + ObjectAnimator.ofFloat(attachLayout, View.SCALE_X, 1.0f) ); runningAnimation2.setDuration(100); runningAnimation2.start(); @@ -2290,21 +2432,21 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe runningAnimationType = 4; ArrayList animators = new ArrayList<>(); - animators.add(ObjectAnimator.ofFloat(expandStickersButton, "scaleX", 1.0f)); - animators.add(ObjectAnimator.ofFloat(expandStickersButton, "scaleY", 1.0f)); - animators.add(ObjectAnimator.ofFloat(expandStickersButton, "alpha", 1.0f)); + animators.add(ObjectAnimator.ofFloat(expandStickersButton, View.SCALE_X, 1.0f)); + animators.add(ObjectAnimator.ofFloat(expandStickersButton, View.SCALE_Y, 1.0f)); + animators.add(ObjectAnimator.ofFloat(expandStickersButton, View.ALPHA, 1.0f)); if (cancelBotButton.getVisibility() == VISIBLE) { - animators.add(ObjectAnimator.ofFloat(cancelBotButton, "scaleX", 0.1f)); - animators.add(ObjectAnimator.ofFloat(cancelBotButton, "scaleY", 0.1f)); - animators.add(ObjectAnimator.ofFloat(cancelBotButton, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(cancelBotButton, View.SCALE_X, 0.1f)); + animators.add(ObjectAnimator.ofFloat(cancelBotButton, View.SCALE_Y, 0.1f)); + animators.add(ObjectAnimator.ofFloat(cancelBotButton, View.ALPHA, 0.0f)); } else if (audioVideoButtonContainer.getVisibility() == VISIBLE) { - animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, "scaleX", 0.1f)); - animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, "scaleY", 0.1f)); - animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, View.SCALE_X, 0.1f)); + animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, View.SCALE_Y, 0.1f)); + animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, View.ALPHA, 0.0f)); } else { - animators.add(ObjectAnimator.ofFloat(sendButton, "scaleX", 0.1f)); - animators.add(ObjectAnimator.ofFloat(sendButton, "scaleY", 0.1f)); - animators.add(ObjectAnimator.ofFloat(sendButton, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(sendButton, View.SCALE_X, 0.1f)); + animators.add(ObjectAnimator.ofFloat(sendButton, View.SCALE_Y, 0.1f)); + animators.add(ObjectAnimator.ofFloat(sendButton, View.ALPHA, 0.0f)); } runningAnimation.playTogether(animators); @@ -2379,8 +2521,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe attachLayout.setVisibility(VISIBLE); runningAnimation2 = new AnimatorSet(); runningAnimation2.playTogether( - ObjectAnimator.ofFloat(attachLayout, "alpha", 1.0f), - ObjectAnimator.ofFloat(attachLayout, "scaleX", 1.0f) + ObjectAnimator.ofFloat(attachLayout, View.ALPHA, 1.0f), + ObjectAnimator.ofFloat(attachLayout, View.SCALE_X, 1.0f) ); runningAnimation2.setDuration(100); runningAnimation2.start(); @@ -2395,21 +2537,21 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe runningAnimationType = 2; ArrayList animators = new ArrayList<>(); - animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, "scaleX", 1.0f)); - animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, "scaleY", 1.0f)); - animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, "alpha", 1.0f)); + animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, View.SCALE_X, 1.0f)); + animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, View.SCALE_Y, 1.0f)); + animators.add(ObjectAnimator.ofFloat(audioVideoButtonContainer, View.ALPHA, 1.0f)); if (cancelBotButton.getVisibility() == VISIBLE) { - animators.add(ObjectAnimator.ofFloat(cancelBotButton, "scaleX", 0.1f)); - animators.add(ObjectAnimator.ofFloat(cancelBotButton, "scaleY", 0.1f)); - animators.add(ObjectAnimator.ofFloat(cancelBotButton, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(cancelBotButton, View.SCALE_X, 0.1f)); + animators.add(ObjectAnimator.ofFloat(cancelBotButton, View.SCALE_Y, 0.1f)); + animators.add(ObjectAnimator.ofFloat(cancelBotButton, View.ALPHA, 0.0f)); } else if (expandStickersButton.getVisibility() == VISIBLE) { - animators.add(ObjectAnimator.ofFloat(expandStickersButton, "scaleX", 0.1f)); - animators.add(ObjectAnimator.ofFloat(expandStickersButton, "scaleY", 0.1f)); - animators.add(ObjectAnimator.ofFloat(expandStickersButton, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(expandStickersButton, View.SCALE_X, 0.1f)); + animators.add(ObjectAnimator.ofFloat(expandStickersButton, View.SCALE_Y, 0.1f)); + animators.add(ObjectAnimator.ofFloat(expandStickersButton, View.ALPHA, 0.0f)); } else { - animators.add(ObjectAnimator.ofFloat(sendButton, "scaleX", 0.1f)); - animators.add(ObjectAnimator.ofFloat(sendButton, "scaleY", 0.1f)); - animators.add(ObjectAnimator.ofFloat(sendButton, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(sendButton, View.SCALE_X, 0.1f)); + animators.add(ObjectAnimator.ofFloat(sendButton, View.SCALE_Y, 0.1f)); + animators.add(ObjectAnimator.ofFloat(sendButton, View.ALPHA, 0.0f)); } runningAnimation.playTogether(animators); @@ -2524,9 +2666,9 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe runningAnimationAudio.cancel(); } runningAnimationAudio = new AnimatorSet(); - runningAnimationAudio.playTogether(ObjectAnimator.ofFloat(recordPanel, "translationX", 0), - ObjectAnimator.ofFloat(recordCircle, "scale", 1), - ObjectAnimator.ofFloat(audioVideoButtonContainer, "alpha", 0)); + runningAnimationAudio.playTogether(ObjectAnimator.ofFloat(recordPanel, View.TRANSLATION_X, 0), + ObjectAnimator.ofFloat(recordCircle, recordCircleScale, 1), + ObjectAnimator.ofFloat(audioVideoButtonContainer, View.ALPHA, 0)); runningAnimationAudio.setDuration(300); runningAnimationAudio.addListener(new AnimatorListenerAdapter() { @Override @@ -2558,9 +2700,9 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe runningAnimationAudio.cancel(); } runningAnimationAudio = new AnimatorSet(); - runningAnimationAudio.playTogether(ObjectAnimator.ofFloat(recordPanel, "translationX", AndroidUtilities.displaySize.x), - ObjectAnimator.ofFloat(recordCircle, "scale", 0.0f), - ObjectAnimator.ofFloat(audioVideoButtonContainer, "alpha", 1.0f)); + runningAnimationAudio.playTogether(ObjectAnimator.ofFloat(recordPanel, View.TRANSLATION_X, AndroidUtilities.displaySize.x), + ObjectAnimator.ofFloat(recordCircle, recordCircleScale, 0.0f), + ObjectAnimator.ofFloat(audioVideoButtonContainer, View.ALPHA, 1.0f)); runningAnimationAudio.setDuration(300); runningAnimationAudio.addListener(new AnimatorListenerAdapter() { @Override @@ -2654,7 +2796,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe editingText = editingMessageObject.messageText; } if (editingText != null) { - ArrayList entities = editingMessageObject.messageOwner.entities;//MessagesQuery.getEntities(message); + ArrayList entities = editingMessageObject.messageOwner.entities; DataQuery.sortEntities(entities); SpannableStringBuilder stringBuilder = new SpannableStringBuilder(editingText); Object spansToRemove[] = stringBuilder.getSpans(0, stringBuilder.length(), Object.class); @@ -2748,27 +2890,19 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe return attachButton; } - public ImageView getBotButton() { - return botButton; - } - - public ImageView getEmojiButton() { - return emojiButton; - } - - public ImageView getSendButton() { - return sendButton; - } - public EmojiView getEmojiView() { return emojiView; } public void setFieldText(CharSequence text) { + setFieldText(text, true); + } + + public void setFieldText(CharSequence text, boolean ignoreChange) { if (messageEditText == null) { return; } - ignoreTextChange = true; + ignoreTextChange = ignoreChange; messageEditText.setText(text); messageEditText.setSelection(messageEditText.getText().length()); ignoreTextChange = false; @@ -2818,7 +2952,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } public void setFieldFocused() { - if (messageEditText != null) { + AccessibilityManager am = (AccessibilityManager)parentActivity.getSystemService(Context.ACCESSIBILITY_SERVICE); + if (messageEditText != null && !am.isTouchExplorationEnabled()) { try { messageEditText.requestFocus(); } catch (Exception e) { @@ -2828,11 +2963,12 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } public void setFieldFocused(boolean focus) { - if (messageEditText == null) { + AccessibilityManager am = (AccessibilityManager) parentActivity.getSystemService(Context.ACCESSIBILITY_SERVICE); + if (messageEditText == null || am.isTouchExplorationEnabled()) { return; } if (focus) { - if (!searchingStickers && !messageEditText.isFocused()) { + if (searchingType == 0 && !messageEditText.isFocused()) { messageEditText.postDelayed(() -> { boolean allowFocus; if (AndroidUtilities.isTablet()) { @@ -2875,7 +3011,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } public CharSequence getFieldText() { - if (messageEditText != null && messageEditText.length() > 0) { + if (hasText()) { return messageEditText.getText(); } return null; @@ -2891,12 +3027,15 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } if (botReplyMarkup != null) { if (isPopupShowing() && currentPopupContentType == 1) { - botButton.setImageResource(R.drawable.ic_msg_panel_kb); + botButton.setImageResource(R.drawable.input_keyboard); + botButton.setContentDescription(LocaleController.getString("AccDescrShowKeyboard", R.string.AccDescrShowKeyboard)); } else { - botButton.setImageResource(R.drawable.bot_keyboard2); + botButton.setImageResource(R.drawable.input_bot2); + botButton.setContentDescription(LocaleController.getString("AccDescrBotKeyboard", R.string.AccDescrBotKeyboard)); } } else { - botButton.setImageResource(R.drawable.bot_keyboard); + botButton.setImageResource(R.drawable.input_bot1); + botButton.setContentDescription(LocaleController.getString("AccDescrBotCommands", R.string.AccDescrBotCommands)); } } else { botButton.setVisibility(GONE); @@ -2905,6 +3044,15 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe attachLayout.setPivotX(AndroidUtilities.dp((botButton == null || botButton.getVisibility() == GONE) && (notifyButton == null || notifyButton.getVisibility() == GONE) ? 48 : 96)); } + public boolean isRtlText() { + try { + return messageEditText.getLayout().getParagraphDirection(0) == Layout.DIR_RIGHT_TO_LEFT; + } catch (Throwable ignore) { + + } + return false; + } + public void setBotsCount(int count, boolean hasCommands) { botCount = count; if (hasBotCommands != hasCommands) { @@ -2953,12 +3101,13 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe if (botReplyMarkup != null) { SharedPreferences preferences = MessagesController.getMainSettings(currentAccount); boolean keyboardHidden = preferences.getInt("hidekeyboard_" + dialog_id, 0) == messageObject.getId(); + boolean showPopup = true; if (botButtonsMessageObject != replyingMessageObject && botReplyMarkup.single_use) { if (preferences.getInt("answered_" + dialog_id, 0) == messageObject.getId()) { - return; + showPopup = false; } } - if (!keyboardHidden && messageEditText.length() == 0 && !isPopupShowing()) { + if (showPopup && !keyboardHidden && messageEditText.length() == 0 && !isPopupShowing()) { showPopup(1, 1); } } else { @@ -3075,9 +3224,9 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe if (emojiView != null) { return; } - emojiView = new EmojiView(allowStickers, allowGifs, parentActivity, info); + emojiView = new EmojiView(allowStickers, allowGifs, parentActivity, true, info); emojiView.setVisibility(GONE); - emojiView.setListener(new EmojiView.Listener() { + emojiView.setDelegate(new EmojiView.EmojiViewDelegate() { @Override public boolean onBackspace() { @@ -3110,14 +3259,14 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe @Override public void onStickerSelected(TLRPC.Document sticker, Object parent) { if (stickersExpanded) { - if (searchingStickers) { - searchingStickers = false; + if (searchingType != 0) { + searchingType = 0; emojiView.closeSearch(true, MessageObject.getStickerSetId(sticker)); emojiView.hideSearchKeyboard(); } setStickersExpanded(false, true, false); } - ChatActivityEnterView.this.onStickerSelected(sticker, parent); + ChatActivityEnterView.this.onStickerSelected(sticker, parent, false); if ((int) dialog_id == 0 && MessageObject.isGifDocument(sticker)) { MessagesController.getInstance(currentAccount).saveGif(parent, sticker); } @@ -3131,14 +3280,43 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } @Override - public void onGifSelected(TLRPC.Document gif, Object parent) { + public void onGifSelected(Object gif, Object parent) { if (stickersExpanded) { + if (searchingType != 0) { + emojiView.hideSearchKeyboard(); + } setStickersExpanded(false, true, false); } - SendMessagesHelper.getInstance(currentAccount).sendSticker(gif, dialog_id, replyingMessageObject, parent); - DataQuery.getInstance(currentAccount).addRecentGif(gif, (int) (System.currentTimeMillis() / 1000)); - if ((int) dialog_id == 0) { - MessagesController.getInstance(currentAccount).saveGif(parent, gif); + if (gif instanceof TLRPC.Document) { + TLRPC.Document document = (TLRPC.Document) gif; + SendMessagesHelper.getInstance(currentAccount).sendSticker(document, dialog_id, replyingMessageObject, parent); + DataQuery.getInstance(currentAccount).addRecentGif(document, (int) (System.currentTimeMillis() / 1000)); + if ((int) dialog_id == 0) { + MessagesController.getInstance(currentAccount).saveGif(parent, document); + } + } else if (gif instanceof TLRPC.BotInlineResult) { + TLRPC.BotInlineResult result = (TLRPC.BotInlineResult) gif; + + if (result.document != null) { + DataQuery.getInstance(currentAccount).addRecentGif(result.document, (int) (System.currentTimeMillis() / 1000)); + if ((int) dialog_id == 0) { + MessagesController.getInstance(currentAccount).saveGif(parent, result.document); + } + } + + TLRPC.User bot = (TLRPC.User) parent; + + HashMap params = new HashMap<>(); + params.put("id", result.id); + params.put("query_id", "" + result.query_id); + + SendMessagesHelper.prepareSendingBotContextResult(result, params, dialog_id, replyingMessageObject); + + if (searchingType != 0) { + searchingType = 0; + emojiView.closeSearch(true); + emojiView.hideSearchKeyboard(); + } } if (delegate != null) { delegate.onMessageSend(null); @@ -3146,23 +3324,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } @Override - public void onGifTab(boolean opened) { - post(updateExpandabilityRunnable); - if (!AndroidUtilities.usingHardwareInput) { - if (opened) { - if (messageEditText.length() == 0) { - messageEditText.setText("@gif "); - messageEditText.setSelection(messageEditText.length()); - } - } else if (messageEditText.getText().toString().equals("@gif ")) { - messageEditText.setText(""); - } - } - } - - @Override - public void onStickersTab(boolean opened) { - delegate.onStickersTab(opened); + public void onTabOpened(int type) { + delegate.onStickersTab(type == 3); post(updateExpandabilityRunnable); } @@ -3215,14 +3378,17 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } @Override - public void onSearchOpenClose(boolean open) { - searchingStickers = open; - setStickersExpanded(open, false, false); + public void onSearchOpenClose(int type) { + searchingType = type; + setStickersExpanded(type != 0, false, false); + if (emojiTabOpen && searchingType == 2) { + checkStickresExpandHeight(); + } } @Override public boolean isSearchOpened() { - return searchingStickers; + return searchingType != 0; } @Override @@ -3247,6 +3413,9 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe wasExpanded = stickersExpanded; stickersExpanded = true; stickersExpandedHeight = sizeNotifierLayout.getHeight() - (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? AndroidUtilities.statusBarHeight : 0) - ActionBar.getCurrentActionBarHeight() - getHeight() + Theme.chat_composeShadowDrawable.getIntrinsicHeight(); + if (searchingType == 2) { + stickersExpandedHeight = Math.min(stickersExpandedHeight, AndroidUtilities.dp(120) + (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y ? keyboardHeightLand : keyboardHeight)); + } emojiView.getLayoutParams().height = stickersExpandedHeight; emojiView.setLayerType(LAYER_TYPE_HARDWARE, null); sizeNotifierLayout.requestLayout(); @@ -3302,9 +3471,9 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } @Override - public void onStickerSelected(TLRPC.Document sticker, Object parent) { - if (searchingStickers) { - searchingStickers = false; + public void onStickerSelected(TLRPC.Document sticker, Object parent, boolean clearsInputField) { + if (searchingType != 0) { + searchingType = 0; emojiView.closeSearch(true); emojiView.hideSearchKeyboard(); } @@ -3313,6 +3482,9 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe if (delegate != null) { delegate.onMessageSend(null); } + if (clearsInputField) { + setFieldText(""); + } DataQuery.getInstance(currentAccount).addRecentSticker(DataQuery.TYPE_IMAGE, parent, sticker, (int) (System.currentTimeMillis() / 1000), false); } @@ -3321,6 +3493,12 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe emojiView.addRecentSticker(sticker); } + public void hideEmojiView() { + if (!emojiViewVisible && emojiView != null && emojiView.getVisibility() != GONE) { + emojiView.setVisibility(GONE); + } + } + private void showPopup(int show, int contentType) { if (show == 1) { if (contentType == 0 && emojiView == null) { @@ -3333,6 +3511,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe View currentView = null; if (contentType == 0) { emojiView.setVisibility(VISIBLE); + emojiViewVisible = true; if (botKeyboardView != null && botKeyboardView.getVisibility() != GONE) { botKeyboardView.setVisibility(GONE); } @@ -3340,6 +3519,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } else if (contentType == 1) { if (emojiView != null && emojiView.getVisibility() != GONE) { emojiView.setVisibility(GONE); + emojiViewVisible = false; } botKeyboardView.setVisibility(VISIBLE); currentView = botKeyboardView; @@ -3359,7 +3539,6 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe if (botKeyboardView != null) { botKeyboardView.setPanelHeight(currentHeight); } - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) currentView.getLayoutParams(); layoutParams.height = currentHeight; currentView.setLayoutParams(layoutParams); @@ -3369,21 +3548,20 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe if (sizeNotifierLayout != null) { emojiPadding = currentHeight; sizeNotifierLayout.requestLayout(); - if (contentType == 0) { - emojiButton.setImageResource(R.drawable.ic_msg_panel_kb); - } else if (contentType == 1) { - setEmojiButtonImage(); - } + setEmojiButtonImage(true, true); updateBotButton(); onWindowSizeChanged(); } } else { if (emojiButton != null) { - setEmojiButtonImage(); + setEmojiButtonImage(false, true); } currentPopupContentType = -1; if (emojiView != null) { - emojiView.setVisibility(GONE); + emojiViewVisible = false; + if (AndroidUtilities.usingHardwareInput || AndroidUtilities.isInMultiwindow) { + emojiView.setVisibility(GONE); + } } if (botKeyboardView != null) { botKeyboardView.setVisibility(GONE); @@ -3398,7 +3576,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe updateBotButton(); } - if (stickersTabOpen) { + if (stickersTabOpen || emojiTabOpen) { checkSendButton(true); } if (stickersExpanded && show != 1) { @@ -3406,19 +3584,73 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } } - private void setEmojiButtonImage() { - int currentPage; - if (emojiView == null) { - currentPage = MessagesController.getGlobalEmojiSettings().getInt("selected_page", 0); - } else { - currentPage = emojiView.getCurrentPage(); + private void setEmojiButtonImage(boolean byOpen, boolean animated) { + if (animated && currentEmojiIcon == -1) { + animated = false; } - if (currentPage == 0 || !allowStickers && !allowGifs) { - emojiButton.setImageResource(R.drawable.ic_msg_panel_smiles); - } else if (currentPage == 1) { - emojiButton.setImageResource(R.drawable.ic_msg_panel_stickers); - } else if (currentPage == 2) { - emojiButton.setImageResource(R.drawable.ic_msg_panel_gif); + int nextIcon; + if (byOpen && currentPopupContentType == 0) { + nextIcon = 0; + } else { + int currentPage; + if (emojiView == null) { + currentPage = MessagesController.getGlobalEmojiSettings().getInt("selected_page", 0); + } else { + currentPage = emojiView.getCurrentPage(); + } + if (currentPage == 0 || !allowStickers && !allowGifs) { + nextIcon = 1; + } else if (currentPage == 1) { + nextIcon = 2; + } else { + nextIcon = 3; + } + } + if (currentEmojiIcon == nextIcon) { + return; + } + if (emojiButtonAnimation != null) { + emojiButtonAnimation.cancel(); + emojiButtonAnimation = null; + } + if (nextIcon == 0) { + emojiButton[animated ? 1 : 0].setImageResource(R.drawable.input_keyboard); + } else if (nextIcon == 1) { + emojiButton[animated ? 1 : 0].setImageResource(R.drawable.input_smile); + } else if (nextIcon == 2) { + emojiButton[animated ? 1 : 0].setImageResource(R.drawable.input_sticker); + } else if (nextIcon == 3) { + emojiButton[animated ? 1 : 0].setImageResource(R.drawable.input_gif); + } + emojiButton[animated ? 1 : 0].setTag(nextIcon == 2 ? 1 : null); + currentEmojiIcon = nextIcon; + if (animated) { + emojiButton[1].setVisibility(VISIBLE); + emojiButtonAnimation = new AnimatorSet(); + emojiButtonAnimation.playTogether( + ObjectAnimator.ofFloat(emojiButton[0], View.SCALE_X, 0.1f), + ObjectAnimator.ofFloat(emojiButton[0], View.SCALE_Y, 0.1f), + ObjectAnimator.ofFloat(emojiButton[0], View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(emojiButton[1], View.SCALE_X, 1.0f), + ObjectAnimator.ofFloat(emojiButton[1], View.SCALE_Y, 1.0f), + ObjectAnimator.ofFloat(emojiButton[1], View.ALPHA, 1.0f)); + emojiButtonAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (animation.equals(emojiButtonAnimation)) { + emojiButtonAnimation = null; + ImageView temp = emojiButton[1]; + emojiButton[1] = emojiButton[0]; + emojiButton[0] = temp; + emojiButton[1].setVisibility(INVISIBLE); + emojiButton[1].setAlpha(0.0f); + emojiButton[1].setScaleX(0.1f); + emojiButton[1].setScaleY(0.1f); + } + } + }); + emojiButtonAnimation.setDuration(150); + emojiButtonAnimation.start(); } } @@ -3428,27 +3660,21 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe SharedPreferences preferences = MessagesController.getMainSettings(currentAccount); preferences.edit().putInt("hidekeyboard_" + dialog_id, botButtonsMessageObject.getId()).commit(); } - if (byBackButton && searchingStickers) { - searchingStickers = false; + if (byBackButton && searchingType != 0) { + searchingType = 0; emojiView.closeSearch(true); messageEditText.requestFocus(); setStickersExpanded(false, true, false); + if (emojiTabOpen) { + checkSendButton(true); + } } else { - if (searchingStickers) { - searchingStickers = false; + if (searchingType != 0) { + searchingType = 0; emojiView.closeSearch(false); messageEditText.requestFocus(); } showPopup(0, 0); - removeGifFromInputField(); - } - } - } - - private void removeGifFromInputField() { - if (!AndroidUtilities.usingHardwareInput) { - if (messageEditText.getText().toString().equals("@gif ")) { - messageEditText.setText(""); } } } @@ -3491,7 +3717,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } public boolean isPopupShowing() { - return emojiView != null && emojiView.getVisibility() == VISIBLE || botKeyboardView != null && botKeyboardView.getVisibility() == VISIBLE; + return emojiViewVisible || botKeyboardView != null && botKeyboardView.getVisibility() == VISIBLE; } public boolean isKeyboardVisible() { @@ -3509,7 +3735,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (w != oldw && stickersExpanded) { - searchingStickers = false; + searchingType = 0; emojiView.closeSearch(false); setStickersExpanded(false, false, false); } @@ -3522,7 +3748,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe @Override public void onSizeChanged(int height, boolean isWidthGreater) { - if (searchingStickers) { + if (searchingType != 0) { lastSizeChangeValue1 = height; lastSizeChangeValue2 = isWidthGreater; keyboardVisible = height > 0; @@ -3745,6 +3971,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } else if (id == NotificationCenter.messagePlayingDidReset) { if (audioToSendMessageObject != null && !MediaController.getInstance().isPlayingMessage(audioToSendMessageObject)) { recordedAudioPlayButton.setImageDrawable(playDrawable); + recordedAudioPlayButton.setContentDescription(LocaleController.getString("AccActionPlay", R.string.AccActionPlay)); recordedAudioSeekBar.setProgress(0); } } else if (id == NotificationCenter.messagePlayingProgressDidChanged) { @@ -3759,7 +3986,9 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } } else if (id == NotificationCenter.featuredStickersDidLoad) { if (emojiButton != null) { - emojiButton.invalidate(); + for (int a = 0; a < emojiButton.length; a++) { + emojiButton[a].invalidate(); + } } } } @@ -3776,8 +4005,73 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe } } + private void checkStickresExpandHeight() { + final int origHeight = AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y ? keyboardHeightLand : keyboardHeight; + int newHeight = originalViewHeight - (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? AndroidUtilities.statusBarHeight : 0) - ActionBar.getCurrentActionBarHeight() - getHeight() + Theme.chat_composeShadowDrawable.getIntrinsicHeight(); + if (searchingType == 2) { + newHeight = Math.min(newHeight, AndroidUtilities.dp(120) + origHeight); + } + int currentHeight = emojiView.getLayoutParams().height; + if (currentHeight == newHeight) { + return; + } + if (stickersExpansionAnim != null) { + stickersExpansionAnim.cancel(); + stickersExpansionAnim = null; + } + stickersExpandedHeight = newHeight; + if (currentHeight > newHeight) { + AnimatorSet anims = new AnimatorSet(); + anims.playTogether( + ObjectAnimator.ofInt(this, roundedTranslationYProperty, -(stickersExpandedHeight - origHeight)), + ObjectAnimator.ofInt(emojiView, roundedTranslationYProperty, -(stickersExpandedHeight - origHeight)) + ); + ((ObjectAnimator) anims.getChildAnimations().get(0)).addUpdateListener(animation -> sizeNotifierLayout.invalidate()); + anims.setDuration(400); + anims.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + anims.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + stickersExpansionAnim = null; + if (emojiView != null) { + emojiView.getLayoutParams().height = stickersExpandedHeight; + emojiView.setLayerType(LAYER_TYPE_NONE, null); + } + } + }); + stickersExpansionAnim = anims; + emojiView.setLayerType(LAYER_TYPE_HARDWARE, null); + anims.start(); + } else { + emojiView.getLayoutParams().height = stickersExpandedHeight; + sizeNotifierLayout.requestLayout(); + int start = messageEditText.getSelectionStart(); + int end = messageEditText.getSelectionEnd(); + messageEditText.setText(messageEditText.getText()); // dismiss action mode, if any + messageEditText.setSelection(start, end); + AnimatorSet anims = new AnimatorSet(); + anims.playTogether( + ObjectAnimator.ofInt(this, roundedTranslationYProperty, -(stickersExpandedHeight - origHeight)), + ObjectAnimator.ofInt(emojiView, roundedTranslationYProperty, -(stickersExpandedHeight - origHeight)) + ); + ((ObjectAnimator) anims.getChildAnimations().get(0)).addUpdateListener(animation -> sizeNotifierLayout.invalidate()); + anims.setDuration(400); + anims.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + anims.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + stickersExpansionAnim = null; + emojiView.setLayerType(LAYER_TYPE_NONE, null); + } + }); + stickersExpansionAnim = anims; + emojiView.setLayerType(LAYER_TYPE_HARDWARE, null); + anims.start(); + } + } + private void setStickersExpanded(boolean expanded, boolean animated, boolean byDrag) { - if (emojiView == null || expanded && !emojiView.areThereAnyStickers() || !byDrag && stickersExpanded == expanded) { + if (emojiView == null || !byDrag && stickersExpanded == expanded) { return; } stickersExpanded = expanded; @@ -3790,11 +4084,18 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe stickersExpansionAnim = null; } if (stickersExpanded) { - stickersExpandedHeight = sizeNotifierLayout.getHeight() - (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? AndroidUtilities.statusBarHeight : 0) - ActionBar.getCurrentActionBarHeight() - getHeight() + Theme.chat_composeShadowDrawable.getIntrinsicHeight(); + originalViewHeight = sizeNotifierLayout.getHeight(); + stickersExpandedHeight = originalViewHeight - (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? AndroidUtilities.statusBarHeight : 0) - ActionBar.getCurrentActionBarHeight() - getHeight() + Theme.chat_composeShadowDrawable.getIntrinsicHeight(); + if (searchingType == 2) { + stickersExpandedHeight = Math.min(stickersExpandedHeight, AndroidUtilities.dp(120) + origHeight); + } emojiView.getLayoutParams().height = stickersExpandedHeight; sizeNotifierLayout.requestLayout(); sizeNotifierLayout.setForeground(new ScrimDrawable()); + int start = messageEditText.getSelectionStart(); + int end = messageEditText.getSelectionEnd(); messageEditText.setText(messageEditText.getText()); // dismiss action mode, if any + messageEditText.setSelection(start, end); if (animated) { AnimatorSet anims = new AnimatorSet(); anims.playTogether( @@ -3869,6 +4170,11 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe stickersArrow.setAnimationProgress(0); } } + if (expanded) { + expandStickersButton.setContentDescription(LocaleController.getString("AccDescrCollapsePanel", R.string.AccDescrCollapsePanel)); + } else { + expandStickersButton.setContentDescription(LocaleController.getString("AccDescrExpandPanel", R.string.AccDescrExpandPanel)); + } } private class ScrimDrawable extends Drawable { 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 401aed0f3..445c7c34b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java @@ -30,10 +30,13 @@ import android.media.MediaMetadataRetriever; import android.media.ThumbnailUtils; import android.net.Uri; import android.provider.MediaStore; -import android.support.media.ExifInterface; +import androidx.exifinterface.media.ExifInterface; import android.os.Build; import android.provider.Settings; -import android.support.annotation.Keep; +import androidx.annotation.Keep; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; @@ -45,6 +48,7 @@ import android.view.View; import android.view.ViewAnimationUtils; import android.view.ViewConfiguration; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; @@ -55,6 +59,7 @@ import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; import org.telegram.messenger.DataQuery; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.MessagesController; import org.telegram.messenger.ContactsController; @@ -67,9 +72,7 @@ import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.messenger.VideoEditedInfo; import org.telegram.messenger.camera.*; -import org.telegram.messenger.support.widget.LinearLayoutManager; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; @@ -104,7 +107,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N private BaseFragment baseFragment; private AttachButton sendPhotosButton; private AttachButton sendDocumentsButton; - private View views[] = new View[20]; + private View[] views = new View[20]; private RecyclerListView attachPhotoRecyclerView; private LinearLayoutManager attachPhotoLayoutManager; private PhotoAttachAdapter photoAttachAdapter; @@ -292,7 +295,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index, boolean needPreview) { PhotoAttachPhotoCell cell = getCellForIndex(index); if (cell != null) { - int coords[] = new int[2]; + int[] coords = new int[2]; cell.getImageView().getLocationInWindow(coords); if (Build.VERSION.SDK_INT < 26) { coords[0] -= getLeftInset(); @@ -571,13 +574,9 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N } nameTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray2)); currentUser = user; - TLRPC.FileLocation photo = null; nameTextView.setText(ContactsController.formatName(user.first_name, user.last_name)); avatarDrawable.setInfo(user); - if (user != null && user.photo != null) { - photo = user.photo.photo_small; - } - imageView.setImage(photo, "50_50", avatarDrawable, user); + imageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); requestLayout(); } @@ -641,7 +640,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N } public ChatAttachAlert(Context context, final BaseFragment parentFragment) { - super(context, false); + super(context, false, 0); baseFragment = parentFragment; ciclePaint.setColor(Theme.getColor(Theme.key_dialogBackground)); setDelegate(this); @@ -819,6 +818,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N } }); containerView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0); + containerView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); attachView = new FrameLayout(context) { @Override @@ -912,11 +912,11 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N }); views[11] = mediaBanTooltip = new CorrectlyMeasuringTextView(context); - mediaBanTooltip.setBackgroundDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(3), 0xff464646)); + mediaBanTooltip.setBackgroundDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(3), Theme.getColor(Theme.key_chat_attachMediaBanBackground))); + mediaBanTooltip.setTextColor(Theme.getColor(Theme.key_chat_attachMediaBanText)); mediaBanTooltip.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8)); mediaBanTooltip.setGravity(Gravity.CENTER_VERTICAL); mediaBanTooltip.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - mediaBanTooltip.setTextColor(0xffffffff); mediaBanTooltip.setVisibility(View.INVISIBLE); attachView.addView(mediaBanTooltip, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 14, 0, 14, 0)); @@ -1164,6 +1164,8 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N }); } }); + shutterButton.setFocusable(true); + shutterButton.setContentDescription(LocaleController.getString("AccDescrShutter", R.string.AccDescrShutter)); switchCameraButton = new ImageView(context); switchCameraButton.setScaleType(ImageView.ScaleType.CENTER); @@ -1184,6 +1186,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N }); animator.start(); }); + switchCameraButton.setContentDescription(LocaleController.getString("AccDescrSwitchCamera", R.string.AccDescrSwitchCamera)); for (int a = 0; a < 2; a++) { flashModeButton[a] = new ImageView(context); @@ -1216,10 +1219,12 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N public void onAnimationEnd(Animator animator) { flashAnimationInProgress = false; currentImage.setVisibility(View.INVISIBLE); + nextImage.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); } }); animatorSet.start(); }); + flashModeButton[a].setContentDescription("flash mode "+a); } cameraPhotoRecyclerView = new RecyclerListView(context) { @@ -1557,15 +1562,21 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N attachButtons.get(a).textView.setTextColor(Theme.getColor(Theme.key_dialogTextGray2)); } lineView.setBackgroundColor(Theme.getColor(Theme.key_dialogGrayLine)); - Theme.setDrawableColor(hintTextView.getBackground(), Theme.getColor(Theme.key_chat_gifSaveHintBackground)); if (hintTextView != null) { + Theme.setDrawableColor(hintTextView.getBackground(), Theme.getColor(Theme.key_chat_gifSaveHintBackground)); hintTextView.setTextColor(Theme.getColor(Theme.key_chat_gifSaveHintText)); } + if (mediaBanTooltip != null) { + Theme.setDrawableColor(mediaBanTooltip.getBackground(), Theme.getColor(Theme.key_chat_attachMediaBanBackground)); + mediaBanTooltip.setTextColor(Theme.getColor(Theme.key_chat_attachMediaBanText)); + } if (listView != null) { listView.setGlowColor(Theme.getColor(Theme.key_dialogScrollGlow)); RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(1); if (holder != null) { holder.itemView.setBackgroundColor(Theme.getColor(Theme.key_dialogBackgroundGray)); + } else { + adapter.notifyItemChanged(1); } } if (ciclePaint != null) { @@ -1581,6 +1592,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N ((PhotoAttachCameraCell) holder.itemView).getImageView().setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogCameraIcon), PorterDuff.Mode.MULTIPLY)); } } + containerView.invalidate(); } private void resetRecordState() { @@ -1601,12 +1613,15 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N switch (mode) { case Camera.Parameters.FLASH_MODE_OFF: imageView.setImageResource(R.drawable.flash_off); + imageView.setContentDescription(LocaleController.getString("AccDescrCameraFlashOff", R.string.AccDescrCameraFlashOff)); break; case Camera.Parameters.FLASH_MODE_ON: imageView.setImageResource(R.drawable.flash_on); + imageView.setContentDescription(LocaleController.getString("AccDescrCameraFlashOn", R.string.AccDescrCameraFlashOn)); break; case Camera.Parameters.FLASH_MODE_AUTO: imageView.setImageResource(R.drawable.flash_auto); + imageView.setContentDescription(LocaleController.getString("AccDescrCameraFlashAuto", R.string.AccDescrCameraFlashAuto)); break; } } @@ -1788,12 +1803,12 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N cameraAnimationInProgress = true; ArrayList animators = new ArrayList<>(); animators.add(ObjectAnimator.ofFloat(ChatAttachAlert.this, "cameraOpenProgress", 0.0f, 1.0f)); - animators.add(ObjectAnimator.ofFloat(cameraPanel, "alpha", 1.0f)); - animators.add(ObjectAnimator.ofFloat(counterTextView, "alpha", 1.0f)); - animators.add(ObjectAnimator.ofFloat(cameraPhotoRecyclerView, "alpha", 1.0f)); + animators.add(ObjectAnimator.ofFloat(cameraPanel, View.ALPHA, 1.0f)); + animators.add(ObjectAnimator.ofFloat(counterTextView, View.ALPHA, 1.0f)); + animators.add(ObjectAnimator.ofFloat(cameraPhotoRecyclerView, View.ALPHA, 1.0f)); for (int a = 0; a < 2; a++) { if (flashModeButton[a].getVisibility() == View.VISIBLE) { - animators.add(ObjectAnimator.ofFloat(flashModeButton[a], "alpha", 1.0f)); + animators.add(ObjectAnimator.ofFloat(flashModeButton[a], View.ALPHA, 1.0f)); break; } } @@ -1827,6 +1842,13 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N cameraView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_FULLSCREEN); } cameraOpened = true; + cameraView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); + if (Build.VERSION.SDK_INT >= 19) { + attachPhotoRecyclerView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); + for (AttachButton button : attachButtons) { + button.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); + } + } } public void onActivityResultFragment(int requestCode, Intent data, String currentPicturePath) { @@ -1998,6 +2020,13 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N cameraView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); } } + cameraView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); + if (Build.VERSION.SDK_INT >= 19) { + attachPhotoRecyclerView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); + for (AttachButton button : attachButtons) { + button.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); + } + } } @Keep @@ -2012,10 +2041,10 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N float endWidth; float endHeight; if (isPortrait) { - endWidth = container.getWidth(); - endHeight = container.getHeight()/* - AndroidUtilities.dp(100)*/; + endWidth = container.getWidth() - getLeftInset() - getRightInset(); + endHeight = container.getHeight(); } else { - endWidth = container.getWidth()/* - AndroidUtilities.dp(100)*/; + endWidth = container.getWidth() - getLeftInset() - getRightInset(); endHeight = container.getHeight(); } if (value == 0) { @@ -2155,6 +2184,8 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N } if (cameraView == null) { cameraView = new CameraView(baseFragment.getParentActivity(), openWithFrontFaceCamera); + cameraView.setFocusable(true); + cameraView.setContentDescription(LocaleController.getString("AccDescrInstantCamera", R.string.AccDescrInstantCamera)); container.addView(cameraView, 1, LayoutHelper.createFrame(80, 80)); cameraView.setDelegate(new CameraView.CameraViewDelegate() { @Override @@ -2289,6 +2320,23 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N progressView.showTextView(); photoAttachAdapter.notifyDataSetChanged(); cameraAttachAdapter.notifyDataSetChanged(); + if (!selectedPhotosOrder.isEmpty()) { + MediaController.AlbumEntry albumEntry; + if (baseFragment instanceof ChatActivity) { + albumEntry = MediaController.allMediaAlbumEntry; + } else { + albumEntry = MediaController.allPhotosAlbumEntry; + } + if (albumEntry != null) { + for (int a = 0, N = selectedPhotosOrder.size(); a < N; a++) { + int imageId = (Integer) selectedPhotosOrder.get(a); + MediaController.PhotoEntry entry = albumEntry.photosByIds.get(imageId); + if (entry != null) { + selectedPhotos.put(imageId, entry); + } + } + } + } } } else if (id == NotificationCenter.reloadInlineHints) { if (adapter != null) { @@ -2329,11 +2377,13 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N if (count == 0) { sendPhotosButton.imageView.setBackgroundDrawable(Theme.chat_attachButtonDrawables[7]); sendPhotosButton.textView.setText(""); + sendPhotosButton.textView.setContentDescription(LocaleController.getString("Close", R.string.Close)); if (baseFragment instanceof ChatActivity) { sendDocumentsButton.textView.setText(LocaleController.getString("ChatDocument", R.string.ChatDocument)); } } else { sendPhotosButton.imageView.setBackgroundDrawable(Theme.chat_attachButtonDrawables[8]); + sendPhotosButton.textView.setContentDescription(null); if (baseFragment instanceof ChatActivity) { sendPhotosButton.textView.setText(LocaleController.formatString("SendItems", R.string.SendItems, String.format("(%d)", count))); if (editingMessageObject == null || !editingMessageObject.hasValidGroupId()) { @@ -2439,6 +2489,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N if (open) { checkCamera(true); showHint(); + AndroidUtilities.makeAccessibilityAnnouncement(LocaleController.getString("AccDescrAttachButton", R.string.AccDescrAttachButton)); } } @@ -2821,7 +2872,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N View view = delegate.getRevealView(); if (view.getVisibility() == View.VISIBLE && ((ViewGroup) view.getParent()).getVisibility() == View.VISIBLE) { - final int coords[] = new int[2]; + final int[] coords = new int[2]; view.getLocationInWindow(coords); float top; if (Build.VERSION.SDK_INT <= 19) { @@ -2839,7 +2890,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N revealY = (int) (AndroidUtilities.displaySize.y - containerView.getY()); } - int corners[][] = new int[][]{ + int[][] corners = new int[][]{ {0, 0}, {0, AndroidUtilities.dp(304)}, {containerView.getMeasuredWidth(), 0}, @@ -2867,9 +2918,9 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N animatorSet.setDuration(200); containerView.setPivotX(revealX <= containerView.getMeasuredWidth() ? revealX : containerView.getMeasuredWidth()); containerView.setPivotY(revealY); - animators.add(ObjectAnimator.ofFloat(containerView, "scaleX", 0.0f)); - animators.add(ObjectAnimator.ofFloat(containerView, "scaleY", 0.0f)); - animators.add(ObjectAnimator.ofFloat(containerView, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(containerView, View.SCALE_X, 0.0f)); + animators.add(ObjectAnimator.ofFloat(containerView, View.SCALE_Y, 0.0f)); + animators.add(ObjectAnimator.ofFloat(containerView, View.ALPHA, 0.0f)); } else { animatorSet.setDuration(250); containerView.setScaleX(1); @@ -2943,25 +2994,25 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N animators = new ArrayList<>(); final AnimatorSet animatorSetInner; if (a < 8) { - animators.add(ObjectAnimator.ofFloat(views[a], "scaleX", 0.7f, 1.05f)); - animators.add(ObjectAnimator.ofFloat(views[a], "scaleY", 0.7f, 1.05f)); + animators.add(ObjectAnimator.ofFloat(views[a], View.SCALE_X, 0.7f, 1.05f)); + animators.add(ObjectAnimator.ofFloat(views[a], View.SCALE_Y, 0.7f, 1.05f)); animatorSetInner = new AnimatorSet(); animatorSetInner.playTogether( - ObjectAnimator.ofFloat(views[a], "scaleX", 1.0f), - ObjectAnimator.ofFloat(views[a], "scaleY", 1.0f)); + ObjectAnimator.ofFloat(views[a], View.SCALE_X, 1.0f), + ObjectAnimator.ofFloat(views[a], View.SCALE_Y, 1.0f)); animatorSetInner.setDuration(100); - animatorSetInner.setInterpolator(decelerateInterpolator); + animatorSetInner.setInterpolator(CubicBezierInterpolator.EASE_OUT); } else { animatorSetInner = null; } if (Build.VERSION.SDK_INT <= 19) { - animators.add(ObjectAnimator.ofFloat(views[a], "alpha", 1.0f)); + animators.add(ObjectAnimator.ofFloat(views[a], View.ALPHA, 1.0f)); } innerAnimator.animatorSet = new AnimatorSet(); innerAnimator.animatorSet.playTogether(animators); innerAnimator.animatorSet.setDuration(150); - innerAnimator.animatorSet.setInterpolator(decelerateInterpolator); + innerAnimator.animatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT); innerAnimator.animatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { 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 86463dff1..8c736606d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java @@ -20,6 +20,7 @@ import android.widget.ImageView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; import org.telegram.messenger.FileLog; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; @@ -81,6 +82,7 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent timeItem.setImageDrawable(timerDrawable = new TimerDrawable(context)); addView(timeItem); timeItem.setOnClickListener(v -> parentFragment.showDialog(AlertsCreator.createTTLAlert(getContext(), parentFragment.getCurrentEncryptedChat()).create())); + timeItem.setContentDescription(LocaleController.getString("SetTimer", R.string.SetTimer)); } if (parentFragment != null) { @@ -185,18 +187,28 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent timerDrawable.setTime(value); } - public void setTitleIcons(int leftIcon, int rightIcon) { - titleTextView.setLeftDrawable(leftIcon); - titleTextView.setRightDrawable(rightIcon); - } - public void setTitleIcons(Drawable leftIcon, Drawable rightIcon) { titleTextView.setLeftDrawable(leftIcon); - titleTextView.setRightDrawable(rightIcon); + if (!(titleTextView.getRightDrawable() instanceof ScamDrawable)) { + titleTextView.setRightDrawable(rightIcon); + } } public void setTitle(CharSequence value) { + setTitle(value, false); + } + + public void setTitle(CharSequence value, boolean scam) { titleTextView.setText(value); + if (scam) { + if (!(titleTextView.getRightDrawable() instanceof ScamDrawable)) { + ScamDrawable drawable = new ScamDrawable(11); + drawable.setColor(Theme.getColor(Theme.key_actionBarDefaultSubtitle)); + titleTextView.setRightDrawable(drawable); + } + } else if (titleTextView.getRightDrawable() instanceof ScamDrawable) { + titleTextView.setRightDrawable(null); + } } public void setSubtitle(CharSequence value) { @@ -272,7 +284,7 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent newSubtitle = LocaleController.formatPluralString("Members", info.participants_count); } } else { - int result[] = new int[1]; + int[] result = new int[1]; String shortNumber = LocaleController.formatShortNumber(info.participants_count, result); if (chat.megagroup) { newSubtitle = LocaleController.formatPluralString("Members", result[0]).replace(String.format("%d", result[0]), shortNumber); @@ -341,13 +353,9 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent } public void setChatAvatar(TLRPC.Chat chat) { - TLRPC.FileLocation newPhoto = null; - if (chat.photo != null) { - newPhoto = chat.photo.photo_small; - } avatarDrawable.setInfo(chat); if (avatarImageView != null) { - avatarImageView.setImage(newPhoto, "50_50", avatarDrawable, chat); + avatarImageView.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, chat); } } @@ -355,13 +363,14 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent TLRPC.FileLocation newPhoto = null; avatarDrawable.setInfo(user); if (UserObject.isUserSelf(user)) { - avatarDrawable.setSavedMessages(2); - } else if (user.photo != null) { - newPhoto = user.photo.photo_small; - } - - if (avatarImageView != null) { - avatarImageView.setImage(newPhoto, "50_50", avatarDrawable, user); + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_SAVED_SMALL); + if (avatarImageView != null) { + avatarImageView.setImage(null, null, avatarDrawable, user); + } + } else { + if (avatarImageView != null) { + avatarImageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); + } } } @@ -369,27 +378,25 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent if (parentFragment == null) { return; } - TLRPC.FileLocation newPhoto = null; - Object parentObject = null; TLRPC.User user = parentFragment.getCurrentUser(); TLRPC.Chat chat = parentFragment.getCurrentChat(); if (user != null) { avatarDrawable.setInfo(user); if (UserObject.isUserSelf(user)) { - avatarDrawable.setSavedMessages(2); - } else if (user.photo != null) { - newPhoto = user.photo.photo_small; + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_SAVED_SMALL); + if (avatarImageView != null) { + avatarImageView.setImage(null, null, avatarDrawable, user); + } + } else { + if (avatarImageView != null) { + avatarImageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); + } } - parentObject = user; } else if (chat != null) { - if (chat.photo != null) { - newPhoto = chat.photo.photo_small; - } avatarDrawable.setInfo(chat); - parentObject = chat; - } - if (avatarImageView != null) { - avatarImageView.setImage(newPhoto, "50_50", avatarDrawable, parentObject); + if (avatarImageView != null) { + avatarImageView.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, chat); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox.java index 89ef14a89..d66b16816 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox.java @@ -19,9 +19,10 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; import android.graphics.drawable.Drawable; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.text.TextPaint; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import org.telegram.messenger.AndroidUtilities; @@ -277,4 +278,12 @@ public class CheckBox extends View { canvas.drawBitmap(checkBitmap, 0, 0, null); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.CheckBox"); + info.setCheckable(true); + info.setChecked(isChecked); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox2.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox2.java new file mode 100644 index 000000000..376df801e --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox2.java @@ -0,0 +1,71 @@ +package org.telegram.ui.Components; + +import android.content.Context; +import android.graphics.Canvas; +import android.view.View; + +public class CheckBox2 extends View { + + private CheckBoxBase checkBoxBase; + + public CheckBox2(Context context) { + super(context); + + checkBoxBase = new CheckBoxBase(this); + } + + public void setProgressDelegate(CheckBoxBase.ProgressDelegate delegate) { + checkBoxBase.setProgressDelegate(delegate); + } + + public void setChecked(boolean checked, boolean animated) { + checkBoxBase.setChecked(checked, animated); + } + + public boolean isChecked() { + return checkBoxBase.isChecked(); + } + + public void setColor(String background, String background2, String check) { + checkBoxBase.setColor(background, background2, check); + } + + public void setSize(int size) { + checkBoxBase.setSize(size); + } + + public void setDrawUnchecked(boolean value) { + checkBoxBase.setDrawUnchecked(value); + } + + public void setDrawBackgroundAsArc(int type) { + checkBoxBase.setDrawBackgroundAsArc(type); + } + + public float getProgress() { + return checkBoxBase.getProgress(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + checkBoxBase.onAttachedToWindow(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + checkBoxBase.onDetachedFromWindow(); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + checkBoxBase.setBounds(0, 0, right - left, bottom - top); + } + + @Override + protected void onDraw(Canvas canvas) { + checkBoxBase.draw(canvas); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBoxBase.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBoxBase.java new file mode 100644 index 000000000..de1acb72a --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBoxBase.java @@ -0,0 +1,281 @@ +package org.telegram.ui.Components; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.graphics.RectF; +import androidx.annotation.Keep; +import android.view.View; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.ui.ActionBar.Theme; + +public class CheckBoxBase { + + private View parentView; + private Rect bounds = new Rect(); + private RectF rect = new RectF(); + + private static Paint paint; + private static Paint eraser; + private static Paint checkPaint; + private static Paint backgroundPaint; + + private Path path = new Path(); + + private Bitmap drawBitmap; + private Canvas bitmapCanvas; + + private boolean attachedToWindow; + + private float backgroundAlpha = 1.0f; + + private float progress; + private ObjectAnimator checkAnimator; + + private boolean isChecked; + + private String checkColorKey = Theme.key_checkboxCheck; + private String backgroundColorKey = Theme.key_chat_serviceBackground; + private String background2ColorKey = Theme.key_chat_serviceBackground; + + private boolean drawUnchecked = true; + private int drawBackgroundAsArc; + + private float size = 21; + + private ProgressDelegate progressDelegate; + + public interface ProgressDelegate { + void setProgress(float progress); + } + + public CheckBoxBase(View parent) { + parentView = parent; + if (paint == null) { + paint = new Paint(Paint.ANTI_ALIAS_FLAG); + + eraser = new Paint(Paint.ANTI_ALIAS_FLAG); + eraser.setColor(0); + eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); + + backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + backgroundPaint.setStyle(Paint.Style.STROKE); + + checkPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + checkPaint.setStrokeCap(Paint.Cap.ROUND); + checkPaint.setStyle(Paint.Style.STROKE); + checkPaint.setStrokeJoin(Paint.Join.ROUND); + } + checkPaint.setStrokeWidth(AndroidUtilities.dp(1.9f)); + backgroundPaint.setStrokeWidth(AndroidUtilities.dp(1.2f)); + + drawBitmap = Bitmap.createBitmap(AndroidUtilities.dp(size), AndroidUtilities.dp(size), Bitmap.Config.ARGB_4444); + bitmapCanvas = new Canvas(drawBitmap); + } + + public void onAttachedToWindow() { + attachedToWindow = true; + } + + public void onDetachedFromWindow() { + attachedToWindow = false; + } + + public void setBounds(int x, int y, int width, int height) { + bounds.left = x; + bounds.top = y; + bounds.right = x + width; + bounds.bottom = y + height; + } + + public void setDrawUnchecked(boolean value) { + drawUnchecked = value; + } + + @Keep + public void setProgress(float value) { + if (progress == value) { + return; + } + progress = value; + if (parentView.getParent() != null) { + View parent = (View) parentView.getParent(); + parent.invalidate(); + } + parentView.invalidate(); + if (progressDelegate != null) { + progressDelegate.setProgress(value); + } + } + + public void setProgressDelegate(ProgressDelegate delegate) { + progressDelegate = delegate; + } + + public void setSize(int value) { + size = value; + } + + public float getProgress() { + return progress; + } + + public boolean isChecked() { + return isChecked; + } + + public void setDrawBackgroundAsArc(int type) { + drawBackgroundAsArc = type; + if (type == 4) { + backgroundPaint.setStrokeWidth(AndroidUtilities.dp(1.9f)); + } else if (type == 3) { + backgroundPaint.setStrokeWidth(AndroidUtilities.dp(1.2f)); + } else if (type != 0) { + backgroundPaint.setStrokeWidth(AndroidUtilities.dp(1.5f)); + } + } + + private void cancelCheckAnimator() { + if (checkAnimator != null) { + checkAnimator.cancel(); + checkAnimator = null; + } + } + + private void animateToCheckedState(boolean newCheckedState) { + checkAnimator = ObjectAnimator.ofFloat(this, "progress", newCheckedState ? 1 : 0); + checkAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (animation.equals(checkAnimator)) { + checkAnimator = null; + } + } + }); + checkAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT); + checkAnimator.setDuration(200); + checkAnimator.start(); + } + + public void setColor(String background, String background2, String check) { + backgroundColorKey = background; + background2ColorKey = background2; + checkColorKey = check; + } + + public void setBackgroundAlpha(float alpha) { + backgroundAlpha = alpha; + } + + public void setChecked(boolean checked, boolean animated) { + if (checked == isChecked) { + return; + } + isChecked = checked; + + if (attachedToWindow && animated) { + animateToCheckedState(checked); + } else { + cancelCheckAnimator(); + setProgress(checked ? 1.0f : 0.0f); + } + } + + public void draw(Canvas canvas) { + if (drawBitmap == null) { + return; + } + + drawBitmap.eraseColor(0); + float rad = AndroidUtilities.dp(size / 2); + float outerRad = rad; + if (drawBackgroundAsArc != 0) { + outerRad -= AndroidUtilities.dp(0.2f); + } + + float roundProgress = progress >= 0.5f ? 1.0f : progress / 0.5f; + + int cx = bounds.centerX(); + int cy = bounds.centerY(); + + if (backgroundColorKey != null) { + if (drawUnchecked) { + paint.setColor((Theme.getServiceMessageColor() & 0x00ffffff) | 0x28000000); + backgroundPaint.setColor(Theme.getColor(checkColorKey)); + } else { + backgroundPaint.setColor(AndroidUtilities.getOffsetColor(0x00ffffff, Theme.getColor(background2ColorKey != null ? background2ColorKey : checkColorKey), progress, backgroundAlpha)); + } + } else { + if (drawUnchecked) { + paint.setColor(Color.argb((int) (25 * backgroundAlpha), 0, 0, 0)); + backgroundPaint.setColor(AndroidUtilities.getOffsetColor(0xffffffff, Theme.getColor(checkColorKey), progress, backgroundAlpha)); + } else { + backgroundPaint.setColor(AndroidUtilities.getOffsetColor(0x00ffffff, Theme.getColor(background2ColorKey != null ? background2ColorKey : checkColorKey), progress, backgroundAlpha)); + } + } + + if (drawUnchecked) { + canvas.drawCircle(cx, cy, rad, paint); + } + paint.setColor(Theme.getColor(checkColorKey)); + if (drawBackgroundAsArc == 0) { + canvas.drawCircle(cx, cy, rad, backgroundPaint); + } else { + rect.set(cx - outerRad, cy - outerRad, cx + outerRad, cy + outerRad); + int startAngle; + int sweepAngle; + if (drawBackgroundAsArc == 1) { + startAngle = -90; + sweepAngle = (int) (-270 * progress); + } else { + startAngle = 90; + sweepAngle = (int) (270 * progress); + } + canvas.drawArc(rect, startAngle, sweepAngle, false, backgroundPaint); + } + + if (roundProgress > 0) { + float checkProgress = progress < 0.5f ? 0.0f : (progress - 0.5f) / 0.5f; + + if (!drawUnchecked && backgroundColorKey != null) { + paint.setColor(Theme.getColor(backgroundColorKey)); + } else { + paint.setColor(Theme.getColor(Theme.key_checkbox)); + } + if (checkColorKey != null) { + checkPaint.setColor(Theme.getColor(checkColorKey)); + } else { + checkPaint.setColor(Theme.getColor(Theme.key_checkboxCheck)); + } + + rad -= AndroidUtilities.dp(0.5f); + bitmapCanvas.drawCircle(drawBitmap.getWidth() / 2, drawBitmap.getHeight() / 2, rad, paint); + bitmapCanvas.drawCircle(drawBitmap.getWidth() / 2, drawBitmap.getWidth() / 2, rad * (1.0f - roundProgress), eraser); + canvas.drawBitmap(drawBitmap, cx - drawBitmap.getWidth() / 2, cy - drawBitmap.getHeight() / 2, null); + + if (checkProgress != 0) { + path.reset(); + + float checkSide = AndroidUtilities.dp(9) * checkProgress; + float smallCheckSide = AndroidUtilities.dp(4) * checkProgress; + int x = cx - AndroidUtilities.dp(1.5f); + int y = cy + AndroidUtilities.dp(4); + float side = (float) Math.sqrt(smallCheckSide * smallCheckSide / 2.0f); + path.moveTo(x - side, y - side); + path.lineTo(x, y); + side = (float) Math.sqrt(checkSide * checkSide / 2.0f); + path.lineTo(x + side, y - side); + canvas.drawPath(path, checkPaint); + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBoxSquare.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBoxSquare.java index 21adb94e7..dfeff93cb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBoxSquare.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBoxSquare.java @@ -14,7 +14,7 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.RectF; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.view.View; import org.telegram.messenger.AndroidUtilities; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java index e9f6dac52..77e13b0cd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java @@ -16,7 +16,7 @@ import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Shader; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.view.View; import org.telegram.messenger.AndroidUtilities; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CloseProgressDrawable2.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CloseProgressDrawable2.java index 2ae118263..5bc9ff739 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CloseProgressDrawable2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CloseProgressDrawable2.java @@ -26,6 +26,7 @@ public class CloseProgressDrawable2 extends Drawable { private RectF rect = new RectF(); private float angle; private boolean animating; + private int side; public CloseProgressDrawable2() { super(); @@ -33,6 +34,7 @@ public class CloseProgressDrawable2 extends Drawable { paint.setStrokeWidth(AndroidUtilities.dp(2)); paint.setStrokeCap(Paint.Cap.ROUND); paint.setStyle(Paint.Style.STROKE); + side = AndroidUtilities.dp(8); } public void startAnimation() { @@ -45,10 +47,18 @@ public class CloseProgressDrawable2 extends Drawable { animating = false; } + public boolean isAnimating() { + return animating; + } + public void setColor(int value) { paint.setColor(value); } + public void setSide(int value) { + side = value; + } + @Override public void draw(Canvas canvas) { long newTime = System.currentTimeMillis(); @@ -98,23 +108,23 @@ public class CloseProgressDrawable2 extends Drawable { } if (progress1 != 0) { - canvas.drawLine(0, 0, 0, AndroidUtilities.dp(8) * progress1, paint); + canvas.drawLine(0, 0, 0, side * progress1, paint); } if (progress2 != 0) { - canvas.drawLine(-AndroidUtilities.dp(8) * progress2, 0, 0, 0, paint); + canvas.drawLine(-side * progress2, 0, 0, 0, paint); } if (progress3 != 0) { - canvas.drawLine(0, -AndroidUtilities.dp(8) * progress3, 0, 0, paint); + canvas.drawLine(0, -side * progress3, 0, 0, paint); } if (progress4 != 1) { - canvas.drawLine(AndroidUtilities.dp(8) * progress4, 0, AndroidUtilities.dp(8), 0, paint); + canvas.drawLine(side * progress4, 0, side, 0, paint); } canvas.restore(); int cx = getBounds().centerX(); int cy = getBounds().centerY(); - rect.set(cx - AndroidUtilities.dp(8), cy - AndroidUtilities.dp(8), cx + AndroidUtilities.dp(8), cy + AndroidUtilities.dp(8)); + rect.set(cx - side, cy - side, cx + side, cy + side); canvas.drawArc(rect, (angle < 360 ? 0 : angle - 360) - 45, (angle < 360 ? angle : 720 - angle), false, paint); lastFrameTime = newTime; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CombinedDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CombinedDrawable.java index 1e3b3889b..659d66324 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CombinedDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CombinedDrawable.java @@ -11,7 +11,7 @@ package org.telegram.ui.Components; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; public class CombinedDrawable extends Drawable implements Drawable.Callback { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropAreaView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropAreaView.java index b5ee90865..7809244e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropAreaView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropAreaView.java @@ -13,7 +13,7 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.os.Build; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropGestureDetector.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropGestureDetector.java index 351246c8a..b8632f3bd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropGestureDetector.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropGestureDetector.java @@ -1,7 +1,7 @@ package org.telegram.ui.Components.Crop; import android.content.Context; -import android.support.v4.view.MotionEventCompat; +import androidx.core.view.MotionEventCompat; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.VelocityTracker; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropRotationWheel.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropRotationWheel.java index e3834d3fd..06ad4408f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropRotationWheel.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropRotationWheel.java @@ -14,6 +14,7 @@ import android.widget.ImageView; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.LayoutHelper; @@ -69,6 +70,7 @@ public class CropRotationWheel extends FrameLayout { if (rotationListener != null) rotationListener.aspectRatioPressed(); }); + aspectRatioButton.setContentDescription(LocaleController.getString("AccDescrAspectRatio", R.string.AccDescrAspectRatio)); addView(aspectRatioButton, LayoutHelper.createFrame(70, 64, Gravity.LEFT | Gravity.CENTER_VERTICAL)); ImageView rotation90Button = new ImageView(context); @@ -80,6 +82,7 @@ public class CropRotationWheel extends FrameLayout { rotationListener.rotate90Pressed(); } }); + rotation90Button.setContentDescription(LocaleController.getString("AccDescrRotate", R.string.AccDescrRotate)); addView(rotation90Button, LayoutHelper.createFrame(70, 64, Gravity.RIGHT | Gravity.CENTER_VERTICAL)); degreesLabel = new TextView(context); @@ -136,6 +139,7 @@ public class CropRotationWheel extends FrameLayout { } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { if (rotationListener != null) rotationListener.onEnd(this.rotation); + AndroidUtilities.makeAccessibilityAnnouncement(String.format("%.1f°", this.rotation)); } else if (action == MotionEvent.ACTION_MOVE) { float delta = prevX - x; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/DialogsItemAnimator.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/DialogsItemAnimator.java new file mode 100644 index 000000000..b27ccc3c4 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/DialogsItemAnimator.java @@ -0,0 +1,688 @@ +package org.telegram.ui.Components; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.TimeInterpolator; +import android.os.Build; +import android.view.View; +import android.view.ViewPropertyAnimator; +import android.view.animation.DecelerateInterpolator; + +import org.telegram.ui.Cells.DialogCell; + +import java.util.ArrayList; +import java.util.List; + +import androidx.recyclerview.widget.RecyclerView.ViewHolder; +import androidx.recyclerview.widget.SimpleItemAnimator; + +public class DialogsItemAnimator extends SimpleItemAnimator { + private static final boolean DEBUG = false; + + private static TimeInterpolator sDefaultInterpolator = new DecelerateInterpolator(); + + private ArrayList mPendingRemovals = new ArrayList<>(); + private ArrayList mPendingAdditions = new ArrayList<>(); + private ArrayList mPendingMoves = new ArrayList<>(); + private ArrayList mPendingChanges = new ArrayList<>(); + + ArrayList> mAdditionsList = new ArrayList<>(); + ArrayList> mMovesList = new ArrayList<>(); + ArrayList> mChangesList = new ArrayList<>(); + + ArrayList mAddAnimations = new ArrayList<>(); + ArrayList mMoveAnimations = new ArrayList<>(); + ArrayList mRemoveAnimations = new ArrayList<>(); + ArrayList mChangeAnimations = new ArrayList<>(); + + private DialogCell removingDialog; + private int topClip; + private int bottomClip; + + private final static int deleteDuration = 180; + private final static int changeDuration = 180; + + private static class MoveInfo { + public ViewHolder holder; + public int fromX, fromY, toX, toY; + + MoveInfo(ViewHolder holder, int fromX, int fromY, int toX, int toY) { + this.holder = holder; + this.fromX = fromX; + this.fromY = fromY; + this.toX = toX; + this.toY = toY; + } + } + + private static class ChangeInfo { + public ViewHolder oldHolder, newHolder; + public int fromX, fromY, toX, toY; + + private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder) { + this.oldHolder = oldHolder; + this.newHolder = newHolder; + } + + ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder, + int fromX, int fromY, int toX, int toY) { + this(oldHolder, newHolder); + this.fromX = fromX; + this.fromY = fromY; + this.toX = toX; + this.toY = toY; + } + + @Override + public String toString() { + return "ChangeInfo{" + + "oldHolder=" + oldHolder + + ", newHolder=" + newHolder + + ", fromX=" + fromX + + ", fromY=" + fromY + + ", toX=" + toX + + ", toY=" + toY + + '}'; + } + } + + @Override + public void runPendingAnimations() { + boolean removalsPending = !mPendingRemovals.isEmpty(); + boolean movesPending = !mPendingMoves.isEmpty(); + boolean changesPending = !mPendingChanges.isEmpty(); + boolean additionsPending = !mPendingAdditions.isEmpty(); + if (!removalsPending && !movesPending && !additionsPending && !changesPending) { + // nothing to animate + return; + } + // First, remove stuff + for (ViewHolder holder : mPendingRemovals) { + animateRemoveImpl(holder); + } + mPendingRemovals.clear(); + // Next, move stuff + if (movesPending) { + final ArrayList moves = new ArrayList<>(mPendingMoves); + mMovesList.add(moves); + mPendingMoves.clear(); + Runnable mover = () -> { + for (MoveInfo moveInfo : moves) { + animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY, moveInfo.toX, moveInfo.toY); + } + moves.clear(); + mMovesList.remove(moves); + }; + mover.run(); + } + // Next, change stuff, to run in parallel with move animations + if (changesPending) { + final ArrayList changes = new ArrayList<>(mPendingChanges); + mChangesList.add(changes); + mPendingChanges.clear(); + Runnable changer = () -> { + for (ChangeInfo change : changes) { + animateChangeImpl(change); + } + changes.clear(); + mChangesList.remove(changes); + }; + changer.run(); + } + // Next, add stuff + if (additionsPending) { + final ArrayList additions = new ArrayList<>(mPendingAdditions); + mAdditionsList.add(additions); + mPendingAdditions.clear(); + Runnable adder = () -> { + for (ViewHolder holder : additions) { + animateAddImpl(holder); + } + additions.clear(); + mAdditionsList.remove(additions); + }; + adder.run(); + } + } + + @Override + public boolean animateRemove(final ViewHolder holder) { + resetAnimation(holder); + mPendingRemovals.add(holder); + return true; + } + + public void prepareForRemove() { + topClip = Integer.MAX_VALUE; + bottomClip = Integer.MAX_VALUE; + removingDialog = null; + } + + private void animateRemoveImpl(final ViewHolder holder) { + final View view = holder.itemView; + mRemoveAnimations.add(holder); + if (view instanceof DialogCell) { + DialogCell dialogCell = (DialogCell) view; + removingDialog = dialogCell; + if (topClip != Integer.MAX_VALUE) { + bottomClip = removingDialog.getMeasuredHeight() - topClip; + removingDialog.setTopClip(topClip); + removingDialog.setBottomClip(bottomClip); + } else if (bottomClip != Integer.MAX_VALUE) { + topClip = removingDialog.getMeasuredHeight() - bottomClip; + removingDialog.setTopClip(topClip); + removingDialog.setBottomClip(bottomClip); + } + if (Build.VERSION.SDK_INT >= 21) { + dialogCell.setElevation(-1); + dialogCell.setOutlineProvider(null); + } + final ObjectAnimator animator = ObjectAnimator.ofFloat(dialogCell, AnimationProperties.CLIP_DIALOG_CELL_PROGRESS, 1.0f) + .setDuration(deleteDuration); + animator.setInterpolator(sDefaultInterpolator); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchRemoveStarting(holder); + } + + @Override + public void onAnimationEnd(Animator animator) { + animator.removeAllListeners(); + dialogCell.setClipProgress(0.0f); + if (Build.VERSION.SDK_INT >= 21) { + dialogCell.setElevation(0); + } + dispatchRemoveFinished(holder); + mRemoveAnimations.remove(holder); + dispatchFinishedWhenDone(); + } + }); + animator.start(); + } else { + final ViewPropertyAnimator animation = view.animate(); + animation.setDuration(deleteDuration).alpha(0).setListener( + new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchRemoveStarting(holder); + } + + @Override + public void onAnimationEnd(Animator animator) { + animation.setListener(null); + view.setAlpha(1); + dispatchRemoveFinished(holder); + mRemoveAnimations.remove(holder); + dispatchFinishedWhenDone(); + } + }).start(); + } + } + + @Override + public boolean animateAdd(final ViewHolder holder) { + resetAnimation(holder); + if (holder.itemView instanceof DialogCell) { + ((DialogCell) holder.itemView).setClipProgress(1.0f); + } else { + holder.itemView.setAlpha(0); + } + mPendingAdditions.add(holder); + return true; + } + + void animateAddImpl(final ViewHolder holder) { + final View view = holder.itemView; + mAddAnimations.add(holder); + if (view instanceof DialogCell) { + DialogCell dialogCell = (DialogCell) view; + final ObjectAnimator animator = ObjectAnimator.ofFloat(dialogCell, AnimationProperties.CLIP_DIALOG_CELL_PROGRESS, 0.0f) + .setDuration(deleteDuration); + animator.setInterpolator(sDefaultInterpolator); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchAddStarting(holder); + } + + @Override + public void onAnimationCancel(Animator animator) { + dialogCell.setClipProgress(0.0f); + } + + @Override + public void onAnimationEnd(Animator animator) { + animator.removeAllListeners(); + dispatchAddFinished(holder); + mAddAnimations.remove(holder); + dispatchFinishedWhenDone(); + } + }); + animator.start(); + } else { + final ViewPropertyAnimator animation = view.animate(); + animation.alpha(1).setDuration(deleteDuration) + .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchAddStarting(holder); + } + + @Override + public void onAnimationCancel(Animator animator) { + view.setAlpha(1); + } + + @Override + public void onAnimationEnd(Animator animator) { + animation.setListener(null); + dispatchAddFinished(holder); + mAddAnimations.remove(holder); + dispatchFinishedWhenDone(); + } + }).start(); + } + } + + @Override + public boolean animateMove(final ViewHolder holder, int fromX, int fromY, + int toX, int toY) { + final View view = holder.itemView; + fromX += (int) holder.itemView.getTranslationX(); + fromY += (int) holder.itemView.getTranslationY(); + resetAnimation(holder); + int deltaX = toX - fromX; + int deltaY = toY - fromY; + if (deltaX == 0 && deltaY == 0) { + dispatchMoveFinished(holder); + return false; + } + if (deltaX != 0) { + view.setTranslationX(-deltaX); + } + if (deltaY != 0) { + view.setTranslationY(-deltaY); + } + mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY)); + return true; + } + + void animateMoveImpl(final ViewHolder holder, int fromX, int fromY, int toX, int toY) { + final View view = holder.itemView; + final int deltaX = toX - fromX; + final int deltaY = toY - fromY; + if (deltaX != 0) { + view.animate().translationX(0); + } + if (deltaY != 0) { + view.animate().translationY(0); + } + if (fromY > toY) { + bottomClip = fromY - toY; + } else { + topClip = toY - fromY; + } + if (removingDialog != null) { + if (topClip != Integer.MAX_VALUE) { + bottomClip = removingDialog.getMeasuredHeight() - topClip; + removingDialog.setTopClip(topClip); + removingDialog.setBottomClip(bottomClip); + } else if (bottomClip != Integer.MAX_VALUE) { + topClip = removingDialog.getMeasuredHeight() - bottomClip; + removingDialog.setTopClip(topClip); + removingDialog.setBottomClip(bottomClip); + } + } + // TODO: make EndActions end listeners instead, since end actions aren't called when + // vpas are canceled (and can't end them. why?) + // need listener functionality in VPACompat for this. Ick. + final ViewPropertyAnimator animation = view.animate(); + mMoveAnimations.add(holder); + animation.setDuration(deleteDuration).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchMoveStarting(holder); + } + + @Override + public void onAnimationCancel(Animator animator) { + if (deltaX != 0) { + view.setTranslationX(0); + } + if (deltaY != 0) { + view.setTranslationY(0); + } + } + + @Override + public void onAnimationEnd(Animator animator) { + animation.setListener(null); + dispatchMoveFinished(holder); + mMoveAnimations.remove(holder); + dispatchFinishedWhenDone(); + } + }).start(); + } + + @Override + public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder, int fromX, int fromY, int toX, int toY) { + if (oldHolder.itemView instanceof DialogCell) { + resetAnimation(oldHolder); + resetAnimation(newHolder); + oldHolder.itemView.setAlpha(1.0f); + newHolder.itemView.setAlpha(0.0f); + newHolder.itemView.setTranslationX(0.0f); + mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY)); + return true; + } + return false; + } + + void animateChangeImpl(final ChangeInfo changeInfo) { + final ViewHolder holder = changeInfo.oldHolder; + final ViewHolder newHolder = changeInfo.newHolder; + if (holder == null || newHolder == null) { + return; + } + + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.setDuration(changeDuration); + animatorSet.playTogether( + ObjectAnimator.ofFloat(holder.itemView, View.ALPHA, 0.0f), + ObjectAnimator.ofFloat(newHolder.itemView, View.ALPHA, 1.0f)); + + mChangeAnimations.add(changeInfo.oldHolder); + mChangeAnimations.add(changeInfo.newHolder); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchChangeStarting(changeInfo.oldHolder, true); + dispatchChangeStarting(changeInfo.newHolder, false); + } + + @Override + public void onAnimationEnd(Animator animator) { + holder.itemView.setAlpha(1); + + animatorSet.removeAllListeners(); + + dispatchChangeFinished(changeInfo.oldHolder, true); + mChangeAnimations.remove(changeInfo.oldHolder); + dispatchFinishedWhenDone(); + + dispatchChangeFinished(changeInfo.newHolder, false); + mChangeAnimations.remove(changeInfo.newHolder); + dispatchFinishedWhenDone(); + } + }); + animatorSet.start(); + } + + private void endChangeAnimation(List infoList, ViewHolder item) { + for (int i = infoList.size() - 1; i >= 0; i--) { + ChangeInfo changeInfo = infoList.get(i); + if (endChangeAnimationIfNecessary(changeInfo, item)) { + if (changeInfo.oldHolder == null && changeInfo.newHolder == null) { + infoList.remove(changeInfo); + } + } + } + } + + private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) { + if (changeInfo.oldHolder != null) { + endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder); + } + if (changeInfo.newHolder != null) { + endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder); + } + } + + private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, ViewHolder item) { + boolean oldItem = false; + if (changeInfo.newHolder == item) { + changeInfo.newHolder = null; + } else if (changeInfo.oldHolder == item) { + changeInfo.oldHolder = null; + oldItem = true; + } else { + return false; + } + item.itemView.setAlpha(1); + item.itemView.setTranslationX(0); + item.itemView.setTranslationY(0); + dispatchChangeFinished(item, oldItem); + return true; + } + + @Override + public void endAnimation(ViewHolder item) { + final View view = item.itemView; + // this will trigger end callback which should set properties to their target values. + view.animate().cancel(); + // TODO if some other animations are chained to end, how do we cancel them as well? + for (int i = mPendingMoves.size() - 1; i >= 0; i--) { + MoveInfo moveInfo = mPendingMoves.get(i); + if (moveInfo.holder == item) { + view.setTranslationY(0); + view.setTranslationX(0); + dispatchMoveFinished(item); + mPendingMoves.remove(i); + } + } + endChangeAnimation(mPendingChanges, item); + if (mPendingRemovals.remove(item)) { + if (view instanceof DialogCell) { + ((DialogCell) view).setClipProgress(0.0f); + } else { + view.setAlpha(1); + } + dispatchRemoveFinished(item); + } + if (mPendingAdditions.remove(item)) { + if (view instanceof DialogCell) { + ((DialogCell) view).setClipProgress(0.0f); + } else { + view.setAlpha(1); + } + dispatchAddFinished(item); + } + + for (int i = mChangesList.size() - 1; i >= 0; i--) { + ArrayList changes = mChangesList.get(i); + endChangeAnimation(changes, item); + if (changes.isEmpty()) { + mChangesList.remove(i); + } + } + for (int i = mMovesList.size() - 1; i >= 0; i--) { + ArrayList moves = mMovesList.get(i); + for (int j = moves.size() - 1; j >= 0; j--) { + MoveInfo moveInfo = moves.get(j); + if (moveInfo.holder == item) { + view.setTranslationY(0); + view.setTranslationX(0); + dispatchMoveFinished(item); + moves.remove(j); + if (moves.isEmpty()) { + mMovesList.remove(i); + } + break; + } + } + } + for (int i = mAdditionsList.size() - 1; i >= 0; i--) { + ArrayList additions = mAdditionsList.get(i); + if (additions.remove(item)) { + if (view instanceof DialogCell) { + ((DialogCell) view).setClipProgress(1.0f); + } else { + view.setAlpha(1); + } + dispatchAddFinished(item); + if (additions.isEmpty()) { + mAdditionsList.remove(i); + } + } + } + + if (mRemoveAnimations.remove(item) && DEBUG) { + throw new IllegalStateException("after animation is cancelled, item should not be in " + + "mRemoveAnimations list"); + } + + if (mAddAnimations.remove(item) && DEBUG) { + throw new IllegalStateException("after animation is cancelled, item should not be in " + + "mAddAnimations list"); + } + + if (mChangeAnimations.remove(item) && DEBUG) { + throw new IllegalStateException("after animation is cancelled, item should not be in " + + "mChangeAnimations list"); + } + + if (mMoveAnimations.remove(item) && DEBUG) { + throw new IllegalStateException("after animation is cancelled, item should not be in " + + "mMoveAnimations list"); + } + dispatchFinishedWhenDone(); + } + + private void resetAnimation(ViewHolder holder) { + holder.itemView.animate().setInterpolator(sDefaultInterpolator); + endAnimation(holder); + } + + @Override + public boolean isRunning() { + return (!mPendingAdditions.isEmpty() + || !mPendingChanges.isEmpty() + || !mPendingMoves.isEmpty() + || !mPendingRemovals.isEmpty() + || !mMoveAnimations.isEmpty() + || !mRemoveAnimations.isEmpty() + || !mAddAnimations.isEmpty() + || !mChangeAnimations.isEmpty() + || !mMovesList.isEmpty() + || !mAdditionsList.isEmpty() + || !mChangesList.isEmpty()); + } + + void dispatchFinishedWhenDone() { + if (!isRunning()) { + dispatchAnimationsFinished(); + onAllAnimationsDone(); + } + } + + protected void onAllAnimationsDone() { + + } + + @Override + public void endAnimations() { + int count = mPendingMoves.size(); + for (int i = count - 1; i >= 0; i--) { + MoveInfo item = mPendingMoves.get(i); + View view = item.holder.itemView; + view.setTranslationY(0); + view.setTranslationX(0); + dispatchMoveFinished(item.holder); + mPendingMoves.remove(i); + } + count = mPendingRemovals.size(); + for (int i = count - 1; i >= 0; i--) { + ViewHolder item = mPendingRemovals.get(i); + dispatchRemoveFinished(item); + mPendingRemovals.remove(i); + } + count = mPendingAdditions.size(); + for (int i = count - 1; i >= 0; i--) { + ViewHolder item = mPendingAdditions.get(i); + if (item.itemView instanceof DialogCell) { + ((DialogCell) item.itemView).setClipProgress(0.0f); + } else { + item.itemView.setAlpha(1); + } + dispatchAddFinished(item); + mPendingAdditions.remove(i); + } + count = mPendingChanges.size(); + for (int i = count - 1; i >= 0; i--) { + endChangeAnimationIfNecessary(mPendingChanges.get(i)); + } + mPendingChanges.clear(); + if (!isRunning()) { + return; + } + + int listCount = mMovesList.size(); + for (int i = listCount - 1; i >= 0; i--) { + ArrayList moves = mMovesList.get(i); + count = moves.size(); + for (int j = count - 1; j >= 0; j--) { + MoveInfo moveInfo = moves.get(j); + ViewHolder item = moveInfo.holder; + View view = item.itemView; + view.setTranslationY(0); + view.setTranslationX(0); + dispatchMoveFinished(moveInfo.holder); + moves.remove(j); + if (moves.isEmpty()) { + mMovesList.remove(moves); + } + } + } + listCount = mAdditionsList.size(); + for (int i = listCount - 1; i >= 0; i--) { + ArrayList additions = mAdditionsList.get(i); + count = additions.size(); + for (int j = count - 1; j >= 0; j--) { + ViewHolder item = additions.get(j); + View view = item.itemView; + if (view instanceof DialogCell) { + ((DialogCell) view).setClipProgress(0.0f); + } else { + view.setAlpha(1); + } + dispatchAddFinished(item); + additions.remove(j); + if (additions.isEmpty()) { + mAdditionsList.remove(additions); + } + } + } + listCount = mChangesList.size(); + for (int i = listCount - 1; i >= 0; i--) { + ArrayList changes = mChangesList.get(i); + count = changes.size(); + for (int j = count - 1; j >= 0; j--) { + endChangeAnimationIfNecessary(changes.get(j)); + if (changes.isEmpty()) { + mChangesList.remove(changes); + } + } + } + + cancelAll(mRemoveAnimations); + cancelAll(mMoveAnimations); + cancelAll(mAddAnimations); + cancelAll(mChangeAnimations); + + dispatchAnimationsFinished(); + } + + void cancelAll(List viewHolders) { + for (int i = viewHolders.size() - 1; i >= 0; i--) { + viewHolders.get(i).itemView.animate().cancel(); + } + } + + @Override + public boolean canReuseUpdatedViewHolder(ViewHolder viewHolder, List payloads) { + return false; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java index 3545d14ad..80f5b52f5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java @@ -11,6 +11,7 @@ package org.telegram.ui.Components; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.SuppressLint; +import android.annotation.TargetApi; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; @@ -18,8 +19,9 @@ import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.Rect; +import android.os.Build; import android.os.SystemClock; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; @@ -27,10 +29,12 @@ import android.text.TextUtils; import android.view.Gravity; import android.view.View; import android.view.ViewTreeObserver; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.EditText; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; @@ -45,8 +49,9 @@ public class EditTextBoldCursor extends EditText { private static Field mScrollYField; private static Method getVerticalOffsetMethod; private static Field mCursorDrawableResField; + private static Class editorClass; - private Drawable[] mCursorDrawable; + private Drawable mCursorDrawable; private Object editor; private GradientDrawable gradientDrawable; @@ -63,7 +68,6 @@ public class EditTextBoldCursor extends EditText { private StaticLayout hintLayout; private StaticLayout errorLayout; private CharSequence errorText; - private Class editorClass; private int hintColor; private int headerHintColor; private boolean hintVisible = true; @@ -87,40 +91,73 @@ public class EditTextBoldCursor extends EditText { private boolean fixed; private ViewTreeObserver.OnPreDrawListener listenerFixer; - @SuppressLint("PrivateApi") public EditTextBoldCursor(Context context) { super(context); + if (Build.VERSION.SDK_INT >= 26) { + setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO); + } + init(); + } + @TargetApi(Build.VERSION_CODES.O) + @Override + public int getAutofillType() { + return AUTOFILL_TYPE_NONE; + } + + @SuppressLint("PrivateApi") + private void init() { linePaint = new Paint(); errorPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); errorPaint.setTextSize(AndroidUtilities.dp(11)); + if (Build.VERSION.SDK_INT >= 26) { + setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO); + } - if (mCursorDrawableField == null) { - try { + try { + if (mScrollYField == null) { mScrollYField = View.class.getDeclaredField("mScrollY"); mScrollYField.setAccessible(true); + } + } catch (Throwable ignore) { + + } + try { + if (mCursorDrawableResField == null) { mCursorDrawableResField = TextView.class.getDeclaredField("mCursorDrawableRes"); mCursorDrawableResField.setAccessible(true); - if (editorClass == null) { - mEditor = TextView.class.getDeclaredField("mEditor"); - mEditor.setAccessible(true); - editorClass = Class.forName("android.widget.Editor"); - } + } + } catch (Throwable ignore) { + + } + try { + if (editorClass == null) { + mEditor = TextView.class.getDeclaredField("mEditor"); + mEditor.setAccessible(true); + editorClass = Class.forName("android.widget.Editor"); + mShowCursorField = editorClass.getDeclaredField("mShowCursor"); + mShowCursorField.setAccessible(true); + if (Build.VERSION.SDK_INT >= 28) { + mCursorDrawableField = editorClass.getDeclaredField("mDrawableForCursor"); + mCursorDrawableField.setAccessible(true); + } else { + mCursorDrawableField = editorClass.getDeclaredField("mCursorDrawable"); + mCursorDrawableField.setAccessible(true); + } + getVerticalOffsetMethod = TextView.class.getDeclaredMethod("getVerticalOffset", boolean.class); + getVerticalOffsetMethod.setAccessible(true); mShowCursorField = editorClass.getDeclaredField("mShowCursor"); mShowCursorField.setAccessible(true); - mCursorDrawableField = editorClass.getDeclaredField("mCursorDrawable"); - mCursorDrawableField.setAccessible(true); getVerticalOffsetMethod = TextView.class.getDeclaredMethod("getVerticalOffset", boolean.class); getVerticalOffsetMethod.setAccessible(true); - } catch (Throwable ignore) { - } + } catch (Throwable e) { + FileLog.e(e); } try { gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[] {0xff54a1db, 0xff54a1db}); editor = mEditor.get(this); if (mCursorDrawableField != null) { - mCursorDrawable = (Drawable[]) mCursorDrawableField.get(editor); mCursorDrawableResField.set(this, R.drawable.field_carret_empty); } } catch (Throwable ignore) { @@ -167,6 +204,7 @@ public class EditTextBoldCursor extends EditText { public void setAllowDrawCursor(boolean value) { allowDrawCursor = value; + invalidate(); } public void setCursorWidth(float width) { @@ -420,7 +458,17 @@ public class EditTextBoldCursor extends EditText { canvas.restore(); } try { - if (allowDrawCursor && mShowCursorField != null && mCursorDrawable != null && mCursorDrawable[0] != null) { + if (allowDrawCursor && mShowCursorField != null) { + if (mCursorDrawable == null) { + if (Build.VERSION.SDK_INT >= 28) { + mCursorDrawable = (Drawable) mCursorDrawableField.get(editor); + } else { + mCursorDrawable = ((Drawable[]) mCursorDrawableField.get(editor))[0]; + } + } + if (mCursorDrawable == null) { + return; + } long mShowCursor = mShowCursorField.getLong(editor); boolean showCursor = (SystemClock.uptimeMillis() - mShowCursor) % (2 * 500) < 500 && isFocused(); if (showCursor) { @@ -433,7 +481,7 @@ public class EditTextBoldCursor extends EditText { Layout layout = getLayout(); int line = layout.getLineForOffset(getSelectionStart()); int lineCount = layout.getLineCount(); - Rect bounds = mCursorDrawable[0].getBounds(); + Rect bounds = mCursorDrawable.getBounds(); rect.left = bounds.left; rect.right = bounds.left + AndroidUtilities.dp(cursorWidth); rect.bottom = bounds.bottom; @@ -448,8 +496,8 @@ public class EditTextBoldCursor extends EditText { canvas.restore(); } } - } catch (Throwable e) { - //ignore + } catch (Throwable ignore) { + } if (lineColor != 0 && hintLayout != null) { int h; @@ -472,4 +520,12 @@ public class EditTextBoldCursor extends EditText { canvas.restore(); }*/ } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.EditText"); + if (hintLayout != null) + info.setContentDescription(hintLayout.getText()); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java index 5d62f65bc..cb63b1a54 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java @@ -28,6 +28,7 @@ import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.inputmethod.EditorInfo; import android.widget.FrameLayout; @@ -350,4 +351,15 @@ public class EditTextCaption extends EditTextBoldCursor { FileLog.e(e); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (!TextUtils.isEmpty(caption)) { + if (Build.VERSION.SDK_INT >= 26) + info.setHintText(caption); + else + info.setText(info.getText()+", "+caption); + } + } } 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 4fdbfe647..887e99fc1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java @@ -1,6 +1,6 @@ package org.telegram.ui.Components; -import android.app.Activity; +import android.content.Context; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.text.Editable; @@ -22,7 +22,6 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; -import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; @@ -32,8 +31,8 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not private EditTextBoldCursor editText; private ImageView emojiButton; private EmojiView emojiView; + private boolean emojiViewVisible; private SizeNotifierFrameLayout sizeNotifierLayout; - private Activity parentActivity; private BaseFragment parentFragment; private int keyboardHeight; @@ -49,6 +48,11 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not private EditTextEmojiDelegate delegate; + private int currentStyle; + + public static final int STYLE_FRAGMENT = 0; + public static final int STYLE_DIALOG = 1; + private boolean waitingForKeyboardOpen; private Runnable openKeyboardRunnable = new Runnable() { @Override @@ -66,11 +70,11 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not void onWindowSizeChanged(int size); } - public EditTextEmoji(Activity context, SizeNotifierFrameLayout parent, BaseFragment fragment) { + public EditTextEmoji(Context context, SizeNotifierFrameLayout parent, BaseFragment fragment, int style) { super(context); + currentStyle = style; NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiDidLoad); - parentActivity = context; parentFragment = fragment; sizeNotifierLayout = parent; sizeNotifierLayout.setDelegate(this); @@ -90,26 +94,40 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not return false; } }; - editText.setGravity(Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - editText.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); - editText.setBackgroundDrawable(Theme.createEditTextDrawable(context, false)); editText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI); editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES); - editText.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(40) : 0, 0, LocaleController.isRTL ? 0 : AndroidUtilities.dp(40), AndroidUtilities.dp(8)); editText.setFocusable(editText.isEnabled()); - editText.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); editText.setCursorSize(AndroidUtilities.dp(20)); editText.setCursorWidth(1.5f); - editText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - 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)); + 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)); + } else { + editText.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); + editText.setHintTextColor(Theme.getColor(Theme.key_dialogTextHint)); + editText.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + editText.setBackgroundDrawable(null); + editText.setPadding(0, 0, 0, 0); + addView(editText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 48, 0, 0, 0)); + } emojiButton = new ImageView(context); emojiButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.MULTIPLY)); emojiButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - emojiButton.setImageResource(R.drawable.ic_smile_small); - emojiButton.setPadding(0, 0, 0, AndroidUtilities.dp(7)); - addView(emojiButton, LayoutHelper.createFrame(48, 48, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT), 0, 0, 0, 0)); + if (style == STYLE_FRAGMENT) { + emojiButton.setPadding(0, 0, 0, AndroidUtilities.dp(7)); + emojiButton.setImageResource(R.drawable.smiles_tab_smiles); + addView(emojiButton, LayoutHelper.createFrame(48, 48, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT), 0, 0, 0, 0)); + } else { + emojiButton.setImageResource(R.drawable.input_smile); + addView(emojiButton, LayoutHelper.createFrame(48, 48, Gravity.CENTER_VERTICAL | Gravity.LEFT, 0, 0, 0, 0)); + } emojiButton.setOnClickListener(view -> { if (!emojiButton.isEnabled()) { return; @@ -121,6 +139,7 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not openKeyboardInternal(); } }); + emojiButton.setContentDescription(LocaleController.getString("Emoji", R.string.Emoji)); } @Override @@ -148,6 +167,12 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not editText.setFocusable(focusable); } + public void hideEmojiView() { + if (!emojiViewVisible && emojiView != null && emojiView.getVisibility() != GONE) { + emojiView.setVisibility(GONE); + } + } + public void setDelegate(EditTextEmojiDelegate editTextEmojiDelegate) { delegate = editTextEmojiDelegate; } @@ -214,6 +239,9 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not if (isPopupShowing()) { showPopup(0); } + if (byBackButton) { + hideEmojiView(); + } } public void openKeyboard() { @@ -225,7 +253,7 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not } public boolean isPopupShowing() { - return emojiView != null && emojiView.getVisibility() == VISIBLE; + return emojiViewVisible; } public boolean isKeyboardVisible() { @@ -252,6 +280,7 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not } emojiView.setVisibility(VISIBLE); + emojiViewVisible = true; View currentView = emojiView; if (keyboardHeight <= 0) { @@ -279,15 +308,22 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not if (sizeNotifierLayout != null) { emojiPadding = currentHeight; sizeNotifierLayout.requestLayout(); - emojiButton.setImageResource(R.drawable.ic_msg_panel_kb); + emojiButton.setImageResource(R.drawable.input_keyboard); onWindowSizeChanged(); } } else { if (emojiButton != null) { - emojiButton.setImageResource(R.drawable.ic_smile_small); + if (currentStyle == STYLE_FRAGMENT) { + emojiButton.setImageResource(R.drawable.smiles_tab_smiles); + } else { + emojiButton.setImageResource(R.drawable.input_smile); + } } if (emojiView != null) { - emojiView.setVisibility(GONE); + emojiViewVisible = false; + if (AndroidUtilities.usingHardwareInput || AndroidUtilities.isInMultiwindow) { + emojiView.setVisibility(GONE); + } } if (sizeNotifierLayout != null) { if (show == 0) { @@ -313,13 +349,12 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not if (emojiView != null) { return; } - emojiView = new EmojiView(false, false, parentActivity, null); + emojiView = new EmojiView(false, false, getContext(), false, null); emojiView.setVisibility(GONE); if (AndroidUtilities.isTablet()) { emojiView.setForseMultiwindowLayout(true); } - emojiView.setListener(new EmojiView.Listener() { - + emojiView.setDelegate(new EmojiView.EmojiViewDelegate() { @Override public boolean onBackspace() { if (editText.length() == 0) { @@ -348,77 +383,18 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not } } - @Override - public void onStickerSelected(TLRPC.Document sticker, Object parent) { - - } - - @Override - public void onStickersSettingsClick() { - - } - - @Override - public void onGifSelected(TLRPC.Document gif, Object parent) { - - } - - @Override - public void onGifTab(boolean opened) { - - } - - @Override - public void onStickersTab(boolean opened) { - - } - @Override public void onClearEmojiRecent() { - if (parentFragment == null || parentActivity == null) { - return; - } - AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setMessage(LocaleController.getString("ClearRecentEmoji", R.string.ClearRecentEmoji)); builder.setPositiveButton(LocaleController.getString("ClearButton", R.string.ClearButton).toUpperCase(), (dialogInterface, i) -> emojiView.clearRecentEmoji()); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - parentFragment.showDialog(builder.create()); - } - - @Override - public void onShowStickerSet(TLRPC.StickerSet stickerSet, TLRPC.InputStickerSet inputStickerSet) { - - } - - @Override - public void onStickerSetAdd(TLRPC.StickerSetCovered stickerSet) { - - } - - @Override - public void onStickerSetRemove(TLRPC.StickerSetCovered stickerSet) { - - } - - @Override - public void onStickersGroupClick(int chatId) { - - } - - @Override - public void onSearchOpenClose(boolean open) { - - } - - @Override - public boolean isSearchOpened() { - return false; - } - - @Override - public boolean isExpanded() { - return false; + if (parentFragment != null) { + parentFragment.showDialog(builder.create()); + } else { + builder.show(); + } } }); sizeNotifierLayout.addView(emojiView); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmbedBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmbedBottomSheet.java index 0ddcc40ef..96e3c7d95 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmbedBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmbedBottomSheet.java @@ -245,7 +245,7 @@ public class EmbedBottomSheet extends BottomSheet { @SuppressLint("SetJavaScriptEnabled") private EmbedBottomSheet(Context context, String title, String description, String originalUrl, final String url, int w, int h) { - super(context, false); + super(context, false, 0); fullWidth = true; setApplyTopPadding(false); setApplyBottomPadding(false); 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 f9918da95..c458a458a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java @@ -12,6 +12,8 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.animation.StateListAnimator; +import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.content.Context; import android.database.DataSetObserver; @@ -24,8 +26,11 @@ import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.graphics.drawable.ShapeDrawable; import android.os.Build; -import android.support.v4.view.PagerAdapter; -import android.support.v4.view.ViewPager; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; import android.text.Editable; import android.text.SpannableStringBuilder; import android.text.TextUtils; @@ -46,9 +51,7 @@ import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; import android.view.WindowManager; import android.view.inputmethod.EditorInfo; -import android.widget.BaseAdapter; import android.widget.FrameLayout; -import android.widget.GridView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.PopupWindow; @@ -59,19 +62,21 @@ import org.telegram.messenger.ChatObject; import org.telegram.messenger.DataQuery; import org.telegram.messenger.Emoji; import org.telegram.messenger.EmojiData; -import org.telegram.messenger.EmojiSuggestion; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.support.widget.GridLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; +import org.telegram.messenger.browser.Browser; import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.AlertDialog; +import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.ContextLinkCell; import org.telegram.ui.Cells.EmptyCell; @@ -79,43 +84,210 @@ import org.telegram.ui.Cells.FeaturedStickerSetInfoCell; import org.telegram.ui.Cells.StickerEmojiCell; import org.telegram.ui.Cells.StickerSetGroupInfoCell; import org.telegram.ui.Cells.StickerSetNameCell; -import org.telegram.ui.StickerPreviewViewer; +import org.telegram.ui.ContentPreviewViewer; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; public class EmojiView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { - public interface Listener { - boolean onBackspace(); - void onEmojiSelected(String emoji); - void onStickerSelected(TLRPC.Document sticker, Object parent); - void onStickersSettingsClick(); - void onStickersGroupClick(int chatId); - void onGifSelected(TLRPC.Document gif, Object parent); - void onGifTab(boolean opened); - void onStickersTab(boolean opened); - void onClearEmojiRecent(); - void onShowStickerSet(TLRPC.StickerSet stickerSet, TLRPC.InputStickerSet inputStickerSet); - void onStickerSetAdd(TLRPC.StickerSetCovered stickerSet); - void onStickerSetRemove(TLRPC.StickerSetCovered stickerSet); - void onSearchOpenClose(boolean open); - boolean isSearchOpened(); - boolean isExpanded(); + private ArrayList views = new ArrayList<>(); + private ViewPager pager; + private FrameLayout bottomTabContainer; + private View bottomTabContainerBackground; + private ImageView floatingButton; + private PagerSlidingTabStrip typeTabs; + private ImageView backspaceButton; + private ImageView stickerSettingsButton; + private ImageView searchButton; + private View shadowLine; + private View topShadow; + private AnimatorSet bottomTabContainerAnimation; + private AnimatorSet backspaceButtonAnimation; + private AnimatorSet stickersButtonAnimation; + private float lastBottomScrollDy; + + private ScrollSlidingTabStrip emojiTabs; + private FrameLayout emojiContainer; + private View emojiTabsShadow; + private RecyclerListView emojiGridView; + private GridLayoutManager emojiLayoutManager; + private EmojiGridAdapter emojiAdapter; + private EmojiSearchAdapter emojiSearchAdapter; + private SearchField emojiSearchField; + private AnimatorSet emojiTabShadowAnimator; + private int emojiMinusDy; + private boolean firstEmojiAttach = true; + private boolean needEmojiSearch; + private int hasRecentEmoji = -1; + + private FrameLayout gifContainer; + private RecyclerListView gifGridView; + private ExtendedGridLayoutManager gifLayoutManager; + private GifSearchAdapter gifSearchAdapter; + private RecyclerListView.OnItemClickListener gifOnItemClickListener; + private GifAdapter gifAdapter; + private SearchField gifSearchField; + private boolean firstGifAttach = true; + + private FrameLayout stickersContainer; + private StickersGridAdapter stickersGridAdapter; + private StickersSearchGridAdapter stickersSearchGridAdapter; + private RecyclerListView.OnItemClickListener stickersOnItemClickListener; + private ScrollSlidingTabStrip stickersTab; + private RecyclerListView stickersGridView; + private GridLayoutManager stickersLayoutManager; + private TextView stickersCounter; + private SearchField stickersSearchField; + private int stickersMinusDy; + private boolean firstStickersAttach = true; + + private AnimatorSet searchAnimation; + + private RecyclerListView trendingGridView; + private GridLayoutManager trendingLayoutManager; + private TrendingGridAdapter trendingGridAdapter; + + private TextView mediaBanTooltip; + private DragListener dragListener; + + private String[] lastSearchKeyboardLanguage; + + private Drawable[] tabIcons; + private Drawable[] emojiIcons; + private Drawable[] stickerIcons; + private String[] emojiTitles; + + private int searchFieldHeight; + + private int currentAccount = UserConfig.selectedAccount; + private ArrayList stickerSets = new ArrayList<>(); + private int groupStickerPackNum; + private int groupStickerPackPosition; + private boolean groupStickersHidden; + private TLRPC.TL_messages_stickerSet groupStickerSet; + + private ArrayList recentGifs = new ArrayList<>(); + private ArrayList recentStickers = new ArrayList<>(); + private ArrayList favouriteStickers = new ArrayList<>(); + + private Paint dotPaint; + + private EmojiViewDelegate delegate; + + private int currentChatId; + + private LongSparseArray installingStickerSets = new LongSparseArray<>(); + private LongSparseArray removingStickerSets = new LongSparseArray<>(); + private boolean trendingLoaded; + private int featuredStickersHash; + + private int currentPage; + + private EmojiColorPickerView pickerView; + private EmojiPopupWindow pickerViewPopup; + private int popupWidth; + private int popupHeight; + private int emojiSize; + private int location[] = new int[2]; + private int stickersTabOffset; + private int recentTabBum = -2; + private int favTabBum = -2; + private int trendingTabNum = -2; + private int scrolledToTrending; + + private TLRPC.ChatFull info; + + private boolean isLayout; + private int currentBackgroundType = -1; + private Object outlineProvider; + private boolean forseMultiwindowLayout; + + private int lastNotifyWidth; + private int lastNotifyHeight; + private int lastNotifyHeight2; + + private boolean backspacePressed; + private boolean backspaceOnce; + private boolean showGifs; + + private ImageViewEmoji emojiTouchedView; + private float emojiLastX; + private float emojiLastY; + private float emojiTouchedX; + private float emojiTouchedY; + + public interface EmojiViewDelegate { + default boolean onBackspace() { + return false; + } + + default void onEmojiSelected(String emoji) { + + } + + default void onStickerSelected(TLRPC.Document sticker, Object parent) { + + } + + default void onStickersSettingsClick() { + + } + + default void onStickersGroupClick(int chatId) { + + } + + default void onGifSelected(Object gif, Object parent) { + + } + + default void onTabOpened(int type) { + + } + + default void onClearEmojiRecent() { + + } + + default void onShowStickerSet(TLRPC.StickerSet stickerSet, TLRPC.InputStickerSet inputStickerSet){ + + } + + default void onStickerSetAdd(TLRPC.StickerSetCovered stickerSet) { + + } + + default void onStickerSetRemove(TLRPC.StickerSetCovered stickerSet) { + + } + + default void onSearchOpenClose(int type) { + + } + + default boolean isSearchOpened() { + return false; + } + + default boolean isExpanded() { + return false; + } } - public interface DragListener{ + public interface DragListener { void onDragStart(); void onDragEnd(float velocity); void onDragCancel(); void onDrag(int offset); } - private StickerPreviewViewer.StickerPreviewViewerDelegate stickerPreviewViewerDelegate = new StickerPreviewViewer.StickerPreviewViewerDelegate() { + private ContentPreviewViewer.ContentPreviewViewerDelegate contentPreviewViewerDelegate = new ContentPreviewViewer.ContentPreviewViewerDelegate() { @Override public void sendSticker(TLRPC.Document sticker, Object parent) { - listener.onStickerSelected(sticker, parent); + delegate.onStickerSelected(sticker, parent); } @Override @@ -124,11 +296,28 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } @Override - public void openSet(TLRPC.InputStickerSet set) { + public void openSet(TLRPC.InputStickerSet set, boolean clearsInputField) { if (set == null) { return; } - listener.onShowStickerSet(null, set); + delegate.onShowStickerSet(null, set); + } + + @Override + public void sendGif(TLRPC.Document gif) { + if (gifGridView.getAdapter() == gifAdapter) { + delegate.onGifSelected(gif, "gif"); + } else if (gifGridView.getAdapter() == gifSearchAdapter) { + delegate.onGifSelected(gif, gifSearchAdapter.bot); + } + } + + @Override + public void gifAddedOrDeleted() { + recentGifs = DataQuery.getInstance(currentAccount).getRecentGifs(); + if (gifAdapter != null) { + gifAdapter.notifyDataSetChanged(); + } } }; @@ -143,248 +332,201 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } superListenerField = f; } + private static final ViewTreeObserver.OnScrollChangedListener NOP = () -> { /* do nothing */ }; - private static String addColorToCode(String code, String color) { - String end = null; - int length = code.length(); - if (length > 2 && code.charAt(code.length() - 2) == '\u200D') { - end = code.substring(code.length() - 2); - code = code.substring(0, code.length() - 2); - } else if (length > 3 && code.charAt(code.length() - 3) == '\u200D') { - end = code.substring(code.length() - 3); - code = code.substring(0, code.length() - 3); - } - code += color; - if (end != null) { - code += end; - } - return code; - } + private class SearchField extends FrameLayout { - public void addEmojiToRecent(String code) { - if (!Emoji.isValidEmoji(code)) { - return; + private View searchBackground; + private ImageView searchIconImageView; + private ImageView clearSearchImageView; + private CloseProgressDrawable2 progressDrawable; + private EditTextBoldCursor searchEditText; + private View shadowView; + private View backgroundView; + private AnimatorSet shadowAnimator; + + public SearchField(Context context, int type) { + super(context); + + shadowView = new View(context); + shadowView.setAlpha(0.0f); + shadowView.setTag(1); + shadowView.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelShadowLine)); + addView(shadowView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.getShadowHeight(), Gravity.BOTTOM | Gravity.LEFT)); + + backgroundView = new View(context); + backgroundView.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + addView(backgroundView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, searchFieldHeight)); + + searchBackground = new View(context); + searchBackground.setBackgroundDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(18), Theme.getColor(Theme.key_chat_emojiSearchBackground))); + addView(searchBackground, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 14, 14, 14, 0)); + + searchIconImageView = new ImageView(context); + searchIconImageView.setScaleType(ImageView.ScaleType.CENTER); + searchIconImageView.setImageResource(R.drawable.smiles_inputsearch); + searchIconImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiSearchIcon), PorterDuff.Mode.MULTIPLY)); + addView(searchIconImageView, LayoutHelper.createFrame(36, 36, Gravity.LEFT | Gravity.TOP, 16, 14, 0, 0)); + + clearSearchImageView = new ImageView(context); + clearSearchImageView.setScaleType(ImageView.ScaleType.CENTER); + clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2()); + progressDrawable.setSide(AndroidUtilities.dp(7)); + clearSearchImageView.setScaleX(0.1f); + clearSearchImageView.setScaleY(0.1f); + clearSearchImageView.setAlpha(0.0f); + clearSearchImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiSearchIcon), PorterDuff.Mode.MULTIPLY)); + addView(clearSearchImageView, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP, 14, 14, 14, 0)); + clearSearchImageView.setOnClickListener(v -> { + searchEditText.setText(""); + AndroidUtilities.showKeyboard(searchEditText); + }); + + searchEditText = new EditTextBoldCursor(context) { + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (!delegate.isSearchOpened()) { + openSearch(SearchField.this); + } + delegate.onSearchOpenClose(type == 1 ? 2 : 1); + searchEditText.requestFocus(); + AndroidUtilities.showKeyboard(searchEditText); + if (trendingGridView != null && trendingGridView.getVisibility() == VISIBLE) { + showTrendingTab(false); + } + } + return super.onTouchEvent(event); + } + }; + searchEditText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + searchEditText.setHintTextColor(Theme.getColor(Theme.key_chat_emojiSearchIcon)); + searchEditText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + searchEditText.setBackgroundDrawable(null); + searchEditText.setPadding(0, 0, 0, 0); + searchEditText.setMaxLines(1); + searchEditText.setLines(1); + searchEditText.setSingleLine(true); + searchEditText.setImeOptions(EditorInfo.IME_ACTION_SEARCH | EditorInfo.IME_FLAG_NO_EXTRACT_UI); + if (type == 0) { + searchEditText.setHint(LocaleController.getString("SearchStickersHint", R.string.SearchStickersHint)); + } else if (type == 1) { + searchEditText.setHint(LocaleController.getString("SearchEmojiHint", R.string.SearchEmojiHint)); + } else if (type == 2) { + searchEditText.setHint(LocaleController.getString("SearchGifsTitle", R.string.SearchGifsTitle)); + } + searchEditText.setCursorColor(Theme.getColor(Theme.key_featuredStickers_addedIcon)); + searchEditText.setCursorSize(AndroidUtilities.dp(20)); + searchEditText.setCursorWidth(1.5f); + addView(searchEditText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 40, Gravity.LEFT | Gravity.TOP, 16 + 38, 12, 16 + 30, 0)); + searchEditText.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) { + boolean show = searchEditText.length() > 0; + boolean showed = clearSearchImageView.getAlpha() != 0; + if (show != showed) { + clearSearchImageView.animate() + .alpha(show ? 1.0f : 0.0f) + .setDuration(150) + .scaleX(show ? 1.0f : 0.1f) + .scaleY(show ? 1.0f : 0.1f) + .start(); + } + if (type == 0) { + stickersSearchGridAdapter.search(searchEditText.getText().toString()); + } else if (type == 1) { + emojiSearchAdapter.search(searchEditText.getText().toString()); + } else if (type == 2) { + gifSearchAdapter.search(searchEditText.getText().toString()); + } + } + }); } - Emoji.addRecentEmoji(code); - if (getVisibility() != VISIBLE || pager.getCurrentItem() != 0) { - Emoji.sortEmoji(); + + public void hideKeyboard() { + AndroidUtilities.hideKeyboard(searchEditText); + } + + private void showShadow(boolean show, boolean animated) { + if (show && shadowView.getTag() == null || !show && shadowView.getTag() != null) { + return; + } + if (shadowAnimator != null) { + shadowAnimator.cancel(); + shadowAnimator = null; + } + shadowView.setTag(show ? null : 1); + if (animated) { + shadowAnimator = new AnimatorSet(); + shadowAnimator.playTogether(ObjectAnimator.ofFloat(shadowView, View.ALPHA, show ? 1.0f : 0.0f)); + shadowAnimator.setDuration(200); + shadowAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT); + shadowAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + shadowAnimator = null; + } + }); + shadowAnimator.start(); + } else { + shadowView.setAlpha(show ? 1.0f : 0.0f); + } } - Emoji.saveRecentEmoji(); - adapters.get(0).notifyDataSetChanged(); } private class ImageViewEmoji extends ImageView { - - private boolean touched; - private float lastX; - private float lastY; - private float touchedX; - private float touchedY; + private boolean isRecent; public ImageViewEmoji(Context context) { super(context); - setOnClickListener(v -> sendEmoji(null)); - setOnLongClickListener(view -> { - String code = (String) view.getTag(); - - String color = null; - - String toCheck = code.replace("\uD83C\uDFFB", ""); - if (toCheck != code) { - color = "\uD83C\uDFFB"; - } - if (color == null) { - toCheck = code.replace("\uD83C\uDFFC", ""); - if (toCheck != code) { - color = "\uD83C\uDFFC"; - } - } - if (color == null) { - toCheck = code.replace("\uD83C\uDFFD", ""); - if (toCheck != code) { - color = "\uD83C\uDFFD"; - } - } - if (color == null) { - toCheck = code.replace("\uD83C\uDFFE", ""); - if (toCheck != code) { - color = "\uD83C\uDFFE"; - } - } - if (color == null) { - toCheck = code.replace("\uD83C\uDFFF", ""); - if (toCheck != code) { - color = "\uD83C\uDFFF"; - } - } - - if (EmojiData.emojiColoredMap.containsKey(toCheck)) { - touched = true; - touchedX = lastX; - touchedY = lastY; - - if (color == null && pager.getCurrentItem() != 0) { - color = Emoji.emojiColor.get(toCheck); - } - - if (color != null) { - switch (color) { - case "\uD83C\uDFFB": - pickerView.setSelection(1); - break; - case "\uD83C\uDFFC": - pickerView.setSelection(2); - break; - case "\uD83C\uDFFD": - pickerView.setSelection(3); - break; - case "\uD83C\uDFFE": - pickerView.setSelection(4); - break; - case "\uD83C\uDFFF": - pickerView.setSelection(5); - break; - } - } else { - pickerView.setSelection(0); - } - view.getLocationOnScreen(location); - int x = emojiSize * pickerView.getSelection() + AndroidUtilities.dp(4 * pickerView.getSelection() - (AndroidUtilities.isTablet() ? 5 : 1)); - if (location[0] - x < AndroidUtilities.dp(5)) { - x += (location[0] - x) - AndroidUtilities.dp(5); - } else if (location[0] - x + popupWidth > AndroidUtilities.displaySize.x - AndroidUtilities.dp(5)) { - x += (location[0] - x + popupWidth) - (AndroidUtilities.displaySize.x - AndroidUtilities.dp(5)); - } - int xOffset = -x; - int yOffset = view.getTop() < 0 ? view.getTop() : 0; - - pickerView.setEmoji(toCheck, AndroidUtilities.dp(AndroidUtilities.isTablet() ? 30 : 22) - xOffset + (int) AndroidUtilities.dpf2(0.5f)); - - pickerViewPopup.setFocusable(true); - pickerViewPopup.showAsDropDown(view, xOffset, -view.getMeasuredHeight() - popupHeight + (view.getMeasuredHeight() - emojiSize) / 2 - yOffset); - view.getParent().requestDisallowInterceptTouchEvent(true); - return true; - } else if (pager.getCurrentItem() == 0) { - listener.onClearEmojiRecent(); - } - return false; - }); - setBackgroundDrawable(Theme.getSelectorDrawable(false)); setScaleType(ImageView.ScaleType.CENTER); } private void sendEmoji(String override) { + showBottomTab(true, true); String code = override != null ? override : (String) getTag(); SpannableStringBuilder builder = new SpannableStringBuilder(); builder.append(code); if (override == null) { - if (pager.getCurrentItem() != 0) { + if (!isRecent) { String color = Emoji.emojiColor.get(code); if (color != null) { code = addColorToCode(code, color); } } addEmojiToRecent(code); - if (listener != null) { - listener.onEmojiSelected(Emoji.fixEmoji(code)); + if (delegate != null) { + delegate.onEmojiSelected(Emoji.fixEmoji(code)); } } else { - if (listener != null) { - listener.onEmojiSelected(Emoji.fixEmoji(override)); + if (delegate != null) { + delegate.onEmojiSelected(Emoji.fixEmoji(override)); } } } + public void setImageDrawable(Drawable drawable, boolean recent) { + super.setImageDrawable(drawable); + isRecent = recent; + } + @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(View.MeasureSpec.getSize(widthMeasureSpec), View.MeasureSpec.getSize(widthMeasureSpec)); } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (touched) { - if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { - if (pickerViewPopup != null && pickerViewPopup.isShowing()) { - pickerViewPopup.dismiss(); - - String color = null; - switch (pickerView.getSelection()) { - case 1: - color = "\uD83C\uDFFB"; - break; - case 2: - color = "\uD83C\uDFFC"; - break; - case 3: - color = "\uD83C\uDFFD"; - break; - case 4: - color = "\uD83C\uDFFE"; - break; - case 5: - color = "\uD83C\uDFFF"; - break; - } - String code = (String) getTag(); - if (pager.getCurrentItem() != 0) { - if (color != null) { - Emoji.emojiColor.put(code, color); - code = addColorToCode(code, color); - } else { - Emoji.emojiColor.remove(code); - } - setImageDrawable(Emoji.getEmojiBigDrawable(code)); - sendEmoji(null); - Emoji.saveEmojiColors(); - } else { - code = code.replace("\uD83C\uDFFB", "") - .replace("\uD83C\uDFFC", "") - .replace("\uD83C\uDFFD", "") - .replace("\uD83C\uDFFE", "") - .replace("\uD83C\uDFFF", ""); - - if (color != null) { - sendEmoji(addColorToCode(code, color)); - } else { - sendEmoji(code); - } - } - } - touched = false; - touchedX = -10000; - touchedY = -10000; - } else if (event.getAction() == MotionEvent.ACTION_MOVE) { - boolean ignore = false; - if (touchedX != -10000) { - if (Math.abs(touchedX - event.getX()) > AndroidUtilities.getPixelsInCM(0.2f, true) || Math.abs(touchedY - event.getY()) > AndroidUtilities.getPixelsInCM(0.2f, false)) { - touchedX = -10000; - touchedY = -10000; - } else { - ignore = true; - } - } - if (!ignore) { - getLocationOnScreen(location); - float x = location[0] + event.getX(); - pickerView.getLocationOnScreen(location); - x -= location[0] + AndroidUtilities.dp(3); - int position = (int) (x / (emojiSize + AndroidUtilities.dp(4))); - if (position < 0) { - position = 0; - } else if (position > 5) { - position = 5; - } - pickerView.setSelection(position); - } - } - } - lastX = event.getX(); - lastY = event.getY(); - return super.onTouchEvent(event); - } } private class EmojiPopupWindow extends PopupWindow { @@ -489,8 +631,8 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific setFocusable(false); try { super.dismiss(); - } catch (Exception e) { - //don't promt + } catch (Exception ignore) { + } unregisterListener(); } @@ -587,114 +729,45 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } - private int searchFieldHeight; - - private int currentAccount = UserConfig.selectedAccount; - private ArrayList adapters = new ArrayList<>(); - private ArrayList stickerSets = new ArrayList<>(); - private int groupStickerPackNum; - private int groupStickerPackPosition; - private boolean groupStickersHidden; - private TLRPC.TL_messages_stickerSet groupStickerSet; - - private ArrayList recentGifs = new ArrayList<>(); - private ArrayList recentStickers = new ArrayList<>(); - private ArrayList favouriteStickers = new ArrayList<>(); - - private Paint dotPaint; - - private Drawable[] icons; - private Drawable stickersDrawable; - - private boolean firstAttach = true; - - private Listener listener; - private ViewPager pager; - private FrameLayout stickersWrap; - private ArrayList views = new ArrayList<>(); - private ArrayList emojiGrids = new ArrayList<>(); - private ImageView backspaceButton; - private View shadowLine; - private TextView noRecentTextView; - private StickersGridAdapter stickersGridAdapter; - private StickersSearchGridAdapter stickersSearchGridAdapter; - private LinearLayout emojiTab; - private ScrollSlidingTabStrip stickersTab; - private RecyclerListView stickersGridView; - private GridLayoutManager stickersLayoutManager; - private TextView stickersEmptyView; - private RecyclerListView gifsGridView; - private ExtendedGridLayoutManager flowLayoutManager; - private GifsAdapter gifsAdapter; - private RecyclerListView trendingGridView; - private GridLayoutManager trendingLayoutManager; - private TrendingGridAdapter trendingGridAdapter; - private RecyclerListView.OnItemClickListener stickersOnItemClickListener; - private PagerSlidingTabStrip pagerSlidingTabStrip; - private TextView mediaBanTooltip; - private DragListener dragListener; - private FrameLayout searchEditTextContainer; - private View searchBackground; - private ImageView searchIconImageView; - private ImageView clearSearchImageView; - private CloseProgressDrawable2 progressDrawable; - private EditTextBoldCursor searchEditText; - private AnimatorSet searchAnimation; - private TextView stickersCounter; - - private int currentChatId; - - private LongSparseArray installingStickerSets = new LongSparseArray<>(); - private LongSparseArray removingStickerSets = new LongSparseArray<>(); - private boolean trendingLoaded; - private int featuredStickersHash; - - private int currentPage; - - private EmojiColorPickerView pickerView; - private EmojiPopupWindow pickerViewPopup; - private int popupWidth; - private int popupHeight; - private int emojiSize; - private int location[] = new int[2]; - private int stickersTabOffset; - private int recentTabBum = -2; - private int favTabBum = -2; - private int gifTabNum = -2; - private int trendingTabNum = -2; - private boolean switchToGifTab; - - private TLRPC.ChatFull info; - - private boolean isLayout; - private int currentBackgroundType = -1; - private Object outlineProvider; - private boolean forseMultiwindowLayout; - - private int oldWidth; - private int lastNotifyWidth; - - private boolean backspacePressed; - private boolean backspaceOnce; - private boolean showGifs; - - private int minusDy; - - public EmojiView(boolean needStickers, boolean needGif, final Context context, final TLRPC.ChatFull chatFull) { + public EmojiView(boolean needStickers, boolean needGif, final Context context, boolean needSearch, final TLRPC.ChatFull chatFull) { super(context); searchFieldHeight = AndroidUtilities.dp(64); + needEmojiSearch = needSearch; - stickersDrawable = context.getResources().getDrawable(R.drawable.ic_smiles2_stickers); - Theme.setDrawableColorByKey(stickersDrawable, Theme.key_chat_emojiPanelIcon); - icons = new Drawable[] { - Theme.createEmojiIconSelectorDrawable(context, R.drawable.ic_smiles2_recent, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.ic_smiles2_smile, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.ic_smiles2_nature, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.ic_smiles2_food, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.ic_smiles2_car, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.ic_smiles2_objects, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), - stickersDrawable + tabIcons = new Drawable[]{ + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_tab_smiles, Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_tab_gif, Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_tab_stickers, Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)) + }; + + emojiIcons = new Drawable[]{ + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_recent, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_smiles, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_cat, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_food, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_activities, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_travel, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_objects, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_other, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_flags, Theme.getColor(Theme.key_chat_emojiPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + }; + + stickerIcons = new Drawable[]{ + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_recent, Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_faves, Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.smiles_panel_trending, Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), Theme.getColor(Theme.key_chat_emojiPanelIconSelected)) + }; + + emojiTitles = new String[]{ + LocaleController.getString("Emoji1", R.string.Emoji1), + LocaleController.getString("Emoji2", R.string.Emoji2), + LocaleController.getString("Emoji3", R.string.Emoji3), + LocaleController.getString("Emoji4", R.string.Emoji4), + LocaleController.getString("Emoji5", R.string.Emoji5), + LocaleController.getString("Emoji6", R.string.Emoji6), + LocaleController.getString("Emoji7", R.string.Emoji7), + LocaleController.getString("Emoji8", R.string.Emoji8) }; showGifs = needGif; @@ -713,26 +786,505 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific }; } - for (int i = 0; i < EmojiData.dataColored.length + 1; i++) { - GridView gridView = new GridView(context); - if (AndroidUtilities.isTablet()) { - gridView.setColumnWidth(AndroidUtilities.dp(60)); - } else { - gridView.setColumnWidth(AndroidUtilities.dp(45)); - } - gridView.setNumColumns(-1); - EmojiGridAdapter emojiGridAdapter = new EmojiGridAdapter(i - 1); - gridView.setAdapter(emojiGridAdapter); - adapters.add(emojiGridAdapter); - emojiGrids.add(gridView); - FrameLayout frameLayout = new FrameLayout(context); - frameLayout.addView(gridView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 48, 0, 0)); + emojiContainer = new FrameLayout(context); + views.add(emojiContainer); - views.add(frameLayout); + emojiGridView = new RecyclerListView(context) { + + private boolean ignoreLayout; + + @Override + protected void onMeasure(int widthSpec, int heightSpec) { + ignoreLayout = true; + int width = MeasureSpec.getSize(widthSpec); + emojiLayoutManager.setSpanCount(width / AndroidUtilities.dp(AndroidUtilities.isTablet() ? 60 : 45)); + ignoreLayout = false; + super.onMeasure(widthSpec, heightSpec); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + if (needEmojiSearch && firstEmojiAttach) { + ignoreLayout = true; + emojiLayoutManager.scrollToPositionWithOffset(1, 0); + firstEmojiAttach = false; + ignoreLayout = false; + } + super.onLayout(changed, l, t, r, b); + checkEmojiSearchFieldScroll(true); + } + + @Override + public void requestLayout() { + if (ignoreLayout) { + return; + } + super.requestLayout(); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (emojiTouchedView != null) { + if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { + if (pickerViewPopup != null && pickerViewPopup.isShowing()) { + pickerViewPopup.dismiss(); + + String color = null; + switch (pickerView.getSelection()) { + case 1: + color = "\uD83C\uDFFB"; + break; + case 2: + color = "\uD83C\uDFFC"; + break; + case 3: + color = "\uD83C\uDFFD"; + break; + case 4: + color = "\uD83C\uDFFE"; + break; + case 5: + color = "\uD83C\uDFFF"; + break; + } + String code = (String) emojiTouchedView.getTag(); + if (!emojiTouchedView.isRecent) { + if (color != null) { + Emoji.emojiColor.put(code, color); + code = addColorToCode(code, color); + } else { + Emoji.emojiColor.remove(code); + } + emojiTouchedView.setImageDrawable(Emoji.getEmojiBigDrawable(code), emojiTouchedView.isRecent); + emojiTouchedView.sendEmoji(null); + Emoji.saveEmojiColors(); + } else { + code = code.replace("\uD83C\uDFFB", "") + .replace("\uD83C\uDFFC", "") + .replace("\uD83C\uDFFD", "") + .replace("\uD83C\uDFFE", "") + .replace("\uD83C\uDFFF", ""); + + if (color != null) { + emojiTouchedView.sendEmoji(addColorToCode(code, color)); + } else { + emojiTouchedView.sendEmoji(code); + } + } + } + emojiTouchedView = null; + emojiTouchedX = -10000; + emojiTouchedY = -10000; + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + boolean ignore = false; + if (emojiTouchedX != -10000) { + if (Math.abs(emojiTouchedX - event.getX()) > AndroidUtilities.getPixelsInCM(0.2f, true) || Math.abs(emojiTouchedY - event.getY()) > AndroidUtilities.getPixelsInCM(0.2f, false)) { + emojiTouchedX = -10000; + emojiTouchedY = -10000; + } else { + ignore = true; + } + } + if (!ignore) { + getLocationOnScreen(location); + float x = location[0] + event.getX(); + pickerView.getLocationOnScreen(location); + x -= location[0] + AndroidUtilities.dp(3); + int position = (int) (x / (emojiSize + AndroidUtilities.dp(4))); + if (position < 0) { + position = 0; + } else if (position > 5) { + position = 5; + } + pickerView.setSelection(position); + } + } + return true; + } + emojiLastX = event.getX(); + emojiLastY = event.getY(); + return super.onTouchEvent(event); + } + }; + emojiGridView.setInstantClick(true); + emojiGridView.setLayoutManager(emojiLayoutManager = new GridLayoutManager(context, 8)); + emojiGridView.setTopGlowOffset(AndroidUtilities.dp(38)); + emojiGridView.setBottomGlowOffset(AndroidUtilities.dp(48)); + emojiGridView.setPadding(0, AndroidUtilities.dp(38), 0, 0); + emojiGridView.setGlowColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + emojiGridView.setClipToPadding(false); + emojiLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + if (emojiGridView.getAdapter() == emojiSearchAdapter) { + if (position == 0 || position == 1 && emojiSearchAdapter.searchWas && emojiSearchAdapter.result.isEmpty()) { + return emojiLayoutManager.getSpanCount(); + } + } else { + if (needEmojiSearch && position == 0 || emojiAdapter.positionToSection.indexOfKey(position) >= 0) { + return emojiLayoutManager.getSpanCount(); + } + } + return 1; + } + }); + emojiGridView.setAdapter(emojiAdapter = new EmojiGridAdapter()); + emojiSearchAdapter = new EmojiSearchAdapter(); + emojiContainer.addView(emojiGridView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + emojiGridView.setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + if (newState == RecyclerView.SCROLL_STATE_DRAGGING && emojiSearchField != null) { + emojiSearchField.hideKeyboard(); + } + } + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + int position = emojiLayoutManager.findFirstVisibleItemPosition(); + if (position != RecyclerView.NO_POSITION) { + int tab = 0; + int count = Emoji.recentEmoji.size() + (needEmojiSearch ? 1 : 0); + if (position >= count) { + for (int a = 0; a < EmojiData.dataColored.length; a++) { + int size = EmojiData.dataColored[a].length + 1; + if (position < count + size) { + tab = a + (Emoji.recentEmoji.isEmpty() ? 0 : 1); + break; + } + count += size; + } + } + emojiTabs.onPageScrolled(tab, 0); + } + checkEmojiTabY(recyclerView, dy); + checkEmojiSearchFieldScroll(false); + checkBottomTabScroll(dy); + } + }); + emojiGridView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { + @Override + public void onItemClick(View view, int position) { + if (view instanceof ImageViewEmoji) { + ImageViewEmoji viewEmoji = (ImageViewEmoji) view; + viewEmoji.sendEmoji(null); + } + } + }); + emojiGridView.setOnItemLongClickListener(new RecyclerListView.OnItemLongClickListener() { + @Override + public boolean onItemClick(View view, int position) { + if (view instanceof ImageViewEmoji) { + ImageViewEmoji viewEmoji = (ImageViewEmoji) view; + String code = (String) viewEmoji.getTag(); + + String color = null; + + String toCheck = code.replace("\uD83C\uDFFB", ""); + if (toCheck != code) { + color = "\uD83C\uDFFB"; + } + if (color == null) { + toCheck = code.replace("\uD83C\uDFFC", ""); + if (toCheck != code) { + color = "\uD83C\uDFFC"; + } + } + if (color == null) { + toCheck = code.replace("\uD83C\uDFFD", ""); + if (toCheck != code) { + color = "\uD83C\uDFFD"; + } + } + if (color == null) { + toCheck = code.replace("\uD83C\uDFFE", ""); + if (toCheck != code) { + color = "\uD83C\uDFFE"; + } + } + if (color == null) { + toCheck = code.replace("\uD83C\uDFFF", ""); + if (toCheck != code) { + color = "\uD83C\uDFFF"; + } + } + + if (EmojiData.emojiColoredMap.containsKey(toCheck)) { + emojiTouchedView = viewEmoji; + emojiTouchedX = emojiLastX; + emojiTouchedY = emojiLastY; + + if (color == null && !viewEmoji.isRecent) { + color = Emoji.emojiColor.get(toCheck); + } + + if (color != null) { + switch (color) { + case "\uD83C\uDFFB": + pickerView.setSelection(1); + break; + case "\uD83C\uDFFC": + pickerView.setSelection(2); + break; + case "\uD83C\uDFFD": + pickerView.setSelection(3); + break; + case "\uD83C\uDFFE": + pickerView.setSelection(4); + break; + case "\uD83C\uDFFF": + pickerView.setSelection(5); + break; + } + } else { + pickerView.setSelection(0); + } + viewEmoji.getLocationOnScreen(location); + int x = emojiSize * pickerView.getSelection() + AndroidUtilities.dp(4 * pickerView.getSelection() - (AndroidUtilities.isTablet() ? 5 : 1)); + if (location[0] - x < AndroidUtilities.dp(5)) { + x += (location[0] - x) - AndroidUtilities.dp(5); + } else if (location[0] - x + popupWidth > AndroidUtilities.displaySize.x - AndroidUtilities.dp(5)) { + x += (location[0] - x + popupWidth) - (AndroidUtilities.displaySize.x - AndroidUtilities.dp(5)); + } + int xOffset = -x; + int yOffset = viewEmoji.getTop() < 0 ? viewEmoji.getTop() : 0; + + pickerView.setEmoji(toCheck, AndroidUtilities.dp(AndroidUtilities.isTablet() ? 30 : 22) - xOffset + (int) AndroidUtilities.dpf2(0.5f)); + + pickerViewPopup.setFocusable(true); + pickerViewPopup.showAsDropDown(view, xOffset, -view.getMeasuredHeight() - popupHeight + (view.getMeasuredHeight() - emojiSize) / 2 - yOffset); + pager.requestDisallowInterceptTouchEvent(true); + emojiGridView.hideSelector(); + return true; + } else if (viewEmoji.isRecent) { + RecyclerListView.ViewHolder holder = emojiGridView.findContainingViewHolder(view); + if (holder != null && holder.getAdapterPosition() <= Emoji.recentEmoji.size()) { + delegate.onClearEmojiRecent(); + } + return true; + } + } + return false; + } + }); + + emojiTabs = new ScrollSlidingTabStrip(context); + if (needSearch) { + emojiSearchField = new SearchField(context, 1); + emojiContainer.addView(emojiSearchField, new FrameLayout.LayoutParams(LayoutHelper.MATCH_PARENT, searchFieldHeight + AndroidUtilities.getShadowHeight())); + emojiSearchField.searchEditText.setOnFocusChangeListener(new OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) { + lastSearchKeyboardLanguage = AndroidUtilities.getCurrentKeyboardLanguage(); + DataQuery.getInstance(currentAccount).fetchNewEmojiKeywords(lastSearchKeyboardLanguage); + } + } + }); } + emojiTabs.setShouldExpand(true); + emojiTabs.setIndicatorHeight(-1); + emojiTabs.setUnderlineHeight(-1); + emojiTabs.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + emojiContainer.addView(emojiTabs, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38)); + emojiTabs.setDelegate(new ScrollSlidingTabStrip.ScrollSlidingTabStripDelegate() { + @Override + public void onPageSelected(int page) { + if (!Emoji.recentEmoji.isEmpty()) { + if (page == 0) { + emojiLayoutManager.scrollToPositionWithOffset(needEmojiSearch ? 1 : 0, 0); + return; + } else { + page--; + } + } + emojiGridView.stopScroll(); + emojiLayoutManager.scrollToPositionWithOffset(emojiAdapter.sectionToPosition.get(page), 0); + checkEmojiTabY(null, 0); + } + }); + + emojiTabsShadow = new View(context); + emojiTabsShadow.setAlpha(0.0f); + emojiTabsShadow.setTag(1); + emojiTabsShadow.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelShadowLine)); + FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.getShadowHeight(), Gravity.TOP | Gravity.LEFT); + layoutParams.topMargin = AndroidUtilities.dp(38); + emojiContainer.addView(emojiTabsShadow, layoutParams); + if (needStickers) { - stickersWrap = new FrameLayout(context); + if (needGif) { + gifContainer = new FrameLayout(context); + views.add(gifContainer); + + gifGridView = new RecyclerListView(context) { + + private boolean ignoreLayout; + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + boolean result = ContentPreviewViewer.getInstance().onInterceptTouchEvent(event, gifGridView, 0, contentPreviewViewerDelegate); + return super.onInterceptTouchEvent(event) || result; + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + if (firstGifAttach && gifAdapter.getItemCount() > 1) { + ignoreLayout = true; + gifLayoutManager.scrollToPositionWithOffset(1, 0); + firstGifAttach = false; + ignoreLayout = false; + } + super.onLayout(changed, l, t, r, b); + checkGifSearchFieldScroll(true); + } + + @Override + public void requestLayout() { + if (ignoreLayout) { + return; + } + super.requestLayout(); + } + }; + gifGridView.setClipToPadding(false); + gifGridView.setLayoutManager(gifLayoutManager = new ExtendedGridLayoutManager(context, 100) { + + private Size size = new Size(); + + @Override + protected Size getSizeForItem(int i) { + TLRPC.Document document; + ArrayList attributes; + if (gifGridView.getAdapter() == gifAdapter) { + document = recentGifs.get(i); + attributes = document.attributes; + } else if (!gifSearchAdapter.results.isEmpty()) { + TLRPC.BotInlineResult result = gifSearchAdapter.results.get(i); + document = result.document; + if (document != null) { + attributes = document.attributes; + } else if (result.content != null) { + attributes = result.content.attributes; + } else if (result.thumb != null) { + attributes = result.thumb.attributes; + } else { + attributes = null; + } + } else { + document = null; + attributes = null; + } + size.width = size.height = 100; + if (document != null) { + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); + if (thumb != null && thumb.w != 0 && thumb.h != 0) { + size.width = thumb.w; + size.height = thumb.h; + } + } + if (attributes != null) { + for (int b = 0; b < attributes.size(); b++) { + TLRPC.DocumentAttribute attribute = attributes.get(b); + if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { + size.width = attribute.w; + size.height = attribute.h; + break; + } + } + } + return size; + } + + @Override + protected int getFlowItemCount() { + if (gifGridView.getAdapter() == gifSearchAdapter && gifSearchAdapter.results.isEmpty()) { + return 0; + } + return getItemCount() - 1; + } + }); + gifLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + if (position == 0 || gifGridView.getAdapter() == gifSearchAdapter && gifSearchAdapter.results.isEmpty()) { + return gifLayoutManager.getSpanCount(); + } + return gifLayoutManager.getSpanSizeForItem(position - 1); + } + }); + gifGridView.addItemDecoration(new RecyclerView.ItemDecoration() { + @Override + public void getItemOffsets(android.graphics.Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + int position = parent.getChildAdapterPosition(view); + if (position != 0) { + outRect.left = 0; + outRect.bottom = 0; + if (!gifLayoutManager.isFirstRow(position - 1)) { + outRect.top = AndroidUtilities.dp(2); + } else { + outRect.top = 0; + } + outRect.right = gifLayoutManager.isLastInRow(position - 1) ? 0 : AndroidUtilities.dp(2); + } else { + outRect.left = 0; + outRect.top = 0; + outRect.bottom = 0; + outRect.right = 0; + } + } + }); + gifGridView.setOverScrollMode(RecyclerListView.OVER_SCROLL_NEVER); + gifGridView.setAdapter(gifAdapter = new GifAdapter(context)); + gifSearchAdapter = new GifSearchAdapter(context); + gifGridView.setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { + gifSearchField.hideKeyboard(); + } + } + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + //checkEmojiTabY(recyclerView, dy); + checkGifSearchFieldScroll(false); + checkBottomTabScroll(dy); + } + }); + + gifGridView.setOnTouchListener((v, event) -> ContentPreviewViewer.getInstance().onTouch(event, gifGridView, 0, gifOnItemClickListener, contentPreviewViewerDelegate)); + gifOnItemClickListener = (view, position) -> { + if (delegate == null) { + return; + } + position--; + if (gifGridView.getAdapter() == gifAdapter) { + if (position < 0 || position >= recentGifs.size()) { + return; + } + delegate.onGifSelected(recentGifs.get(position), "gif"); + } else if (gifGridView.getAdapter() == gifSearchAdapter) { + if (position < 0 || position >= gifSearchAdapter.results.size()) { + return; + } + delegate.onGifSelected(gifSearchAdapter.results.get(position), gifSearchAdapter.bot); + recentGifs = DataQuery.getInstance(currentAccount).getRecentGifs(); + if (gifAdapter != null) { + gifAdapter.notifyDataSetChanged(); + } + } + }; + + gifGridView.setOnItemClickListener(gifOnItemClickListener); + gifContainer.addView(gifGridView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + + gifSearchField = new SearchField(context, 2); + gifContainer.addView(gifSearchField, new FrameLayout.LayoutParams(LayoutHelper.MATCH_PARENT, searchFieldHeight + AndroidUtilities.getShadowHeight())); + } + + stickersContainer = new FrameLayout(context); DataQuery.getInstance(currentAccount).checkStickers(DataQuery.TYPE_IMAGE); DataQuery.getInstance(currentAccount).checkFeaturedStickers(); @@ -742,13 +1294,13 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific @Override public boolean onInterceptTouchEvent(MotionEvent event) { - boolean result = StickerPreviewViewer.getInstance().onInterceptTouchEvent(event, stickersGridView, EmojiView.this.getMeasuredHeight(), stickerPreviewViewerDelegate); + boolean result = ContentPreviewViewer.getInstance().onInterceptTouchEvent(event, stickersGridView, EmojiView.this.getMeasuredHeight(), contentPreviewViewerDelegate); return super.onInterceptTouchEvent(event) || result; } @Override public void setVisibility(int visibility) { - if (gifsGridView != null && gifsGridView.getVisibility() == VISIBLE || trendingGridView != null && trendingGridView.getVisibility() == VISIBLE) { + if (trendingGridView != null && trendingGridView.getVisibility() == VISIBLE) { super.setVisibility(GONE); return; } @@ -757,14 +1309,14 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { - if (firstAttach && stickersGridAdapter.getItemCount() > 0) { + if (firstStickersAttach && stickersGridAdapter.getItemCount() > 0) { ignoreLayout = true; stickersLayoutManager.scrollToPositionWithOffset(1, 0); - firstAttach = false; + firstStickersAttach = false; ignoreLayout = false; } super.onLayout(changed, l, t, r, b); - checkSearchFieldScroll(); + checkStickersSearchFieldScroll(true); } @Override @@ -804,280 +1356,32 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific }); stickersGridView.setPadding(0, AndroidUtilities.dp(4 + 48), 0, 0); stickersGridView.setClipToPadding(false); - views.add(stickersWrap); + views.add(stickersContainer); stickersSearchGridAdapter = new StickersSearchGridAdapter(context); stickersGridView.setAdapter(stickersGridAdapter = new StickersGridAdapter(context)); - stickersGridView.setOnTouchListener((v, event) -> StickerPreviewViewer.getInstance().onTouch(event, stickersGridView, EmojiView.this.getMeasuredHeight(), stickersOnItemClickListener, stickerPreviewViewerDelegate)); + stickersGridView.setOnTouchListener((v, event) -> ContentPreviewViewer.getInstance().onTouch(event, stickersGridView, EmojiView.this.getMeasuredHeight(), stickersOnItemClickListener, contentPreviewViewerDelegate)); stickersOnItemClickListener = (view, position) -> { if (stickersGridView.getAdapter() == stickersSearchGridAdapter) { TLRPC.StickerSetCovered pack = stickersSearchGridAdapter.positionsToSets.get(position); if (pack != null) { - listener.onShowStickerSet(pack.set, null); + delegate.onShowStickerSet(pack.set, null); return; } } if (!(view instanceof StickerEmojiCell)) { return; } - StickerPreviewViewer.getInstance().reset(); + ContentPreviewViewer.getInstance().reset(); StickerEmojiCell cell = (StickerEmojiCell) view; if (cell.isDisabled()) { return; } cell.disable(); - listener.onStickerSelected(cell.getSticker(), cell.getParentObject()); + delegate.onStickerSelected(cell.getSticker(), cell.getParentObject()); }; stickersGridView.setOnItemClickListener(stickersOnItemClickListener); stickersGridView.setGlowColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); - stickersWrap.addView(stickersGridView); - - searchEditTextContainer = new FrameLayout(context); - searchEditTextContainer.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); - stickersWrap.addView(searchEditTextContainer, new RecyclerView.LayoutParams(LayoutHelper.MATCH_PARENT, searchFieldHeight)); - - searchBackground = new View(context); - searchBackground.setBackgroundDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(3), Theme.getColor(Theme.key_chat_emojiSearchBackground))); - searchEditTextContainer.addView(searchBackground, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 14, 14, 14, 0)); - - searchIconImageView = new ImageView(context); - searchIconImageView.setScaleType(ImageView.ScaleType.CENTER); - searchIconImageView.setImageResource(R.drawable.sticker_search); - searchIconImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelIcon), PorterDuff.Mode.MULTIPLY)); - searchEditTextContainer.addView(searchIconImageView, LayoutHelper.createFrame(36, 36, Gravity.LEFT | Gravity.TOP, 14, 14, 0, 0)); - - clearSearchImageView = new ImageView(context); - clearSearchImageView.setScaleType(ImageView.ScaleType.CENTER); - clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2()); - clearSearchImageView.setScaleX(0.1f); - clearSearchImageView.setScaleY(0.1f); - clearSearchImageView.setAlpha(0.0f); - clearSearchImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelIcon), PorterDuff.Mode.MULTIPLY)); - searchEditTextContainer.addView(clearSearchImageView, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP, 14, 14, 14, 0)); - clearSearchImageView.setOnClickListener(v -> { - searchEditText.setText(""); - AndroidUtilities.showKeyboard(searchEditText); - }); - - searchEditText = new EditTextBoldCursor(context) { - @Override - public boolean onTouchEvent(MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_DOWN) { - if (!listener.isSearchOpened()) { - if (searchAnimation != null) { - searchAnimation.cancel(); - searchAnimation = null; - } - if (listener != null && listener.isExpanded()) { - searchAnimation = new AnimatorSet(); - searchAnimation.playTogether(ObjectAnimator.ofFloat(stickersTab, "translationY", -AndroidUtilities.dp(47)), - ObjectAnimator.ofFloat(stickersGridView, "translationY", -AndroidUtilities.dp(48)), - ObjectAnimator.ofFloat(searchEditTextContainer, "translationY", AndroidUtilities.dp(0))); - searchAnimation.setDuration(200); - searchAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); - searchAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (animation.equals(searchAnimation)) { - stickersGridView.setTranslationY(0); - stickersGridView.setPadding(0, AndroidUtilities.dp(4), 0, 0); - searchAnimation = null; - } - } - - @Override - public void onAnimationCancel(Animator animation) { - if (animation.equals(searchAnimation)) { - searchAnimation = null; - } - } - }); - searchAnimation.start(); - } else { - searchEditTextContainer.setTranslationY(AndroidUtilities.dp(0)); - stickersTab.setTranslationY(-AndroidUtilities.dp(47)); - stickersGridView.setPadding(0, AndroidUtilities.dp(4), 0, 0); - } - } - listener.onSearchOpenClose(true); - searchEditText.requestFocus(); - AndroidUtilities.showKeyboard(searchEditText); - } - return super.onTouchEvent(event); - } - }; - searchEditText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - searchEditText.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); - searchEditText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - searchEditText.setBackgroundDrawable(null); - searchEditText.setPadding(0, 0, 0, 0); - searchEditText.setMaxLines(1); - searchEditText.setLines(1); - searchEditText.setSingleLine(true); - searchEditText.setImeOptions(EditorInfo.IME_ACTION_SEARCH | EditorInfo.IME_FLAG_NO_EXTRACT_UI); - searchEditText.setHint(LocaleController.getString("SearchStickersHint", R.string.SearchStickersHint)); - searchEditText.setCursorColor(Theme.getColor(Theme.key_featuredStickers_addedIcon)); - searchEditText.setCursorSize(AndroidUtilities.dp(20)); - searchEditText.setCursorWidth(1.5f); - searchEditTextContainer.addView(searchEditText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 40, Gravity.LEFT | Gravity.TOP, 16 + 30, 12, 16 + 30, 0)); - searchEditText.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) { - boolean show = searchEditText.length() > 0; - boolean showed = clearSearchImageView.getAlpha() != 0; - if (show != showed) { - clearSearchImageView.animate() - .alpha(show ? 1.0f : 0.0f) - .setDuration(150) - .scaleX(show ? 1.0f : 0.1f) - .scaleY(show ? 1.0f : 0.1f) - .start(); - } - stickersSearchGridAdapter.search(searchEditText.getText().toString()); - } - }); - - trendingGridView = new RecyclerListView(context); - trendingGridView.setItemAnimator(null); - trendingGridView.setLayoutAnimation(null); - trendingGridView.setLayoutManager(trendingLayoutManager = new GridLayoutManager(context, 5) { - @Override - public boolean supportsPredictiveItemAnimations() { - return false; - } - }); - trendingLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { - @Override - public int getSpanSize(int position) { - if (trendingGridAdapter.cache.get(position) instanceof Integer || position == trendingGridAdapter.totalItems) { - return trendingGridAdapter.stickersPerRow; - } - return 1; - } - }); - trendingGridView.setOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - checkStickersTabY(recyclerView, dy); - } - }); - trendingGridView.setClipToPadding(false); - trendingGridView.setPadding(0, AndroidUtilities.dp(48), 0, 0); - trendingGridView.setAdapter(trendingGridAdapter = new TrendingGridAdapter(context)); - trendingGridView.setOnItemClickListener((view, position) -> { - TLRPC.StickerSetCovered pack = trendingGridAdapter.positionsToSets.get(position); - if (pack != null) { - listener.onShowStickerSet(pack.set, null); - } - }); - trendingGridAdapter.notifyDataSetChanged(); - trendingGridView.setGlowColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); - trendingGridView.setVisibility(GONE); - stickersWrap.addView(trendingGridView); - - if (needGif) { - gifsGridView = new RecyclerListView(context); - gifsGridView.setClipToPadding(false); - gifsGridView.setPadding(0, AndroidUtilities.dp(48), 0, 0); - gifsGridView.setLayoutManager(flowLayoutManager = new ExtendedGridLayoutManager(context, 100) { - - private Size size = new Size(); - - @Override - protected Size getSizeForItem(int i) { - TLRPC.Document document = recentGifs.get(i); - TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); - size.width = thumb != null && thumb.w != 0 ? thumb.w : 100; - size.height = thumb != null && thumb.h != 0 ? thumb.h : 100; - for (int b = 0; b < document.attributes.size(); b++) { - TLRPC.DocumentAttribute attribute = document.attributes.get(b); - if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { - size.width = attribute.w; - size.height = attribute.h; - break; - } - } - return size; - } - }); - flowLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { - @Override - public int getSpanSize(int position) { - return flowLayoutManager.getSpanSizeForItem(position); - } - }); - gifsGridView.addItemDecoration(new RecyclerView.ItemDecoration() { - @Override - public void getItemOffsets(android.graphics.Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { - outRect.left = 0; - outRect.top = 0; - outRect.bottom = 0; - int position = parent.getChildAdapterPosition(view); - if (!flowLayoutManager.isFirstRow(position)) { - outRect.top = AndroidUtilities.dp(2); - } - outRect.right = flowLayoutManager.isLastInRow(position) ? 0 : AndroidUtilities.dp(2); - } - }); - gifsGridView.setOverScrollMode(RecyclerListView.OVER_SCROLL_NEVER); - gifsGridView.setAdapter(gifsAdapter = new GifsAdapter(context)); - gifsGridView.setOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - checkStickersTabY(recyclerView, dy); - } - }); - gifsGridView.setOnItemClickListener((view, position) -> { - if (position < 0 || position >= recentGifs.size() || listener == null) { - return; - } - listener.onGifSelected(recentGifs.get(position), "gif"); - }); - gifsGridView.setOnItemLongClickListener((view, position) -> { - if (position < 0 || position >= recentGifs.size()) { - return false; - } - final TLRPC.Document searchImage = recentGifs.get(position); - AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setMessage(LocaleController.getString("DeleteGif", R.string.DeleteGif)); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK).toUpperCase(), (dialogInterface, i) -> { - DataQuery.getInstance(currentAccount).removeRecentGif(searchImage); - recentGifs = DataQuery.getInstance(currentAccount).getRecentGifs(); - if (gifsAdapter != null) { - gifsAdapter.notifyDataSetChanged(); - } - if (recentGifs.isEmpty()) { - updateStickerTabs(); - if (stickersGridAdapter != null) { - stickersGridAdapter.notifyDataSetChanged(); - } - } - }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - builder.show().setCanceledOnTouchOutside(true); - return true; - }); - gifsGridView.setVisibility(GONE); - stickersWrap.addView(gifsGridView); - } - - stickersEmptyView = new TextView(context); - stickersEmptyView.setText(LocaleController.getString("NoStickers", R.string.NoStickers)); - stickersEmptyView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - stickersEmptyView.setTextColor(Theme.getColor(Theme.key_chat_emojiPanelEmptyText)); - stickersEmptyView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - stickersWrap.addView(stickersEmptyView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 48, 0, 0)); - stickersGridView.setEmptyView(stickersEmptyView); + stickersContainer.addView(stickersGridView); stickersTab = new ScrollSlidingTabStrip(context) { @@ -1180,13 +1484,13 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (startedScroll) { int dx = (int) (ev.getX() - lastX + newTranslationX - lastTranslateX); try { - pager.fakeDragBy(dx); + //pager.fakeDragBy(dx); lastTranslateX = newTranslationX; } catch (Exception e) { try { pager.endFakeDrag(); - } catch (Exception e2) { - //don't promt + } catch (Exception ignore) { + } startedScroll = false; FileLog.e(e); @@ -1204,84 +1508,101 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific return startedScroll || super.onTouchEvent(ev); } }; - stickersTab.setUnderlineHeight(AndroidUtilities.dp(1)); - stickersTab.setIndicatorColor(Theme.getColor(Theme.key_chat_emojiPanelStickerPackSelector)); - stickersTab.setUnderlineColor(Theme.getColor(Theme.key_chat_emojiPanelStickerPackSelector)); + + stickersSearchField = new SearchField(context, 0); + stickersContainer.addView(stickersSearchField, new FrameLayout.LayoutParams(LayoutHelper.MATCH_PARENT, searchFieldHeight + AndroidUtilities.getShadowHeight())); + + trendingGridView = new RecyclerListView(context); + trendingGridView.setItemAnimator(null); + trendingGridView.setLayoutAnimation(null); + trendingGridView.setLayoutManager(trendingLayoutManager = new GridLayoutManager(context, 5) { + @Override + public boolean supportsPredictiveItemAnimations() { + return false; + } + }); + trendingLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + if (trendingGridAdapter.cache.get(position) instanceof Integer || position == trendingGridAdapter.totalItems) { + return trendingGridAdapter.stickersPerRow; + } + return 1; + } + }); + trendingGridView.setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + checkStickersTabY(recyclerView, dy); + checkBottomTabScroll(dy); + } + }); + trendingGridView.setClipToPadding(false); + trendingGridView.setPadding(0, AndroidUtilities.dp(48), 0, 0); + trendingGridView.setAdapter(trendingGridAdapter = new TrendingGridAdapter(context)); + trendingGridView.setOnItemClickListener((view, position) -> { + TLRPC.StickerSetCovered pack = trendingGridAdapter.positionsToSets.get(position); + if (pack != null) { + delegate.onShowStickerSet(pack.set, null); + } + }); + trendingGridAdapter.notifyDataSetChanged(); + trendingGridView.setGlowColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + trendingGridView.setVisibility(GONE); + stickersContainer.addView(trendingGridView); + + stickersTab.setUnderlineHeight(AndroidUtilities.getShadowHeight()); + stickersTab.setIndicatorHeight(AndroidUtilities.dp(2)); + stickersTab.setIndicatorColor(Theme.getColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)); + stickersTab.setUnderlineColor(Theme.getColor(Theme.key_chat_emojiPanelShadowLine)); stickersTab.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); - stickersTab.setVisibility(INVISIBLE); - addView(stickersTab, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); - stickersTab.setTranslationX(AndroidUtilities.displaySize.x); + stickersContainer.addView(stickersTab, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); updateStickerTabs(); stickersTab.setDelegate(page -> { - if (gifsGridView != null) { - if (page == gifTabNum + 1) { - if (gifsGridView.getVisibility() != VISIBLE) { - listener.onGifTab(true); - showGifTab(); - } - } else if (page == trendingTabNum + 1) { - if (trendingGridView.getVisibility() != VISIBLE) { - showTrendingTab(); - } - } else { - if (gifsGridView.getVisibility() == VISIBLE) { - listener.onGifTab(false); - gifsGridView.setVisibility(GONE); - stickersGridView.setVisibility(VISIBLE); - searchEditTextContainer.setVisibility(VISIBLE); - int vis = stickersGridView.getVisibility(); - stickersEmptyView.setVisibility(stickersGridAdapter.getItemCount() != 0 ? GONE : VISIBLE); - checkScroll(); - saveNewPage(); - } else if (trendingGridView.getVisibility() == VISIBLE) { - trendingGridView.setVisibility(GONE); - stickersGridView.setVisibility(VISIBLE); - searchEditTextContainer.setVisibility(VISIBLE); - stickersEmptyView.setVisibility(stickersGridAdapter.getItemCount() != 0 ? GONE : VISIBLE); - saveNewPage(); - } + if (page == trendingTabNum) { + if (trendingGridView.getVisibility() != VISIBLE) { + showTrendingTab(true); } + } else if (trendingGridView.getVisibility() == VISIBLE) { + showTrendingTab(false); + saveNewPage(); } - if (page == 0) { - pager.setCurrentItem(0); + + if (page == trendingTabNum) { + return; + } else if (page == recentTabBum) { + stickersGridView.stopScroll(); + stickersLayoutManager.scrollToPositionWithOffset(stickersGridAdapter.getPositionForPack("recent"), 0); + checkStickersTabY(null, 0); + stickersTab.onPageScrolled(recentTabBum, recentTabBum > 0 ? recentTabBum : stickersTabOffset); + return; + } else if (page == favTabBum) { + stickersGridView.stopScroll(); + stickersLayoutManager.scrollToPositionWithOffset(stickersGridAdapter.getPositionForPack("fav"), 0); + checkStickersTabY(null, 0); + stickersTab.onPageScrolled(favTabBum, favTabBum > 0 ? favTabBum : stickersTabOffset); return; - } else { - if (page == gifTabNum + 1 || page == trendingTabNum + 1) { - return; - } else if (page == recentTabBum + 1) { - stickersLayoutManager.scrollToPositionWithOffset(stickersGridAdapter.getPositionForPack("recent"), 0); - checkStickersTabY(null, 0); - stickersTab.onPageScrolled(recentTabBum + 1, (recentTabBum > 0 ? recentTabBum : stickersTabOffset) + 1); - return; - } else if (page == favTabBum + 1) { - stickersLayoutManager.scrollToPositionWithOffset(stickersGridAdapter.getPositionForPack("fav"), 0); - checkStickersTabY(null, 0); - stickersTab.onPageScrolled(favTabBum + 1, (favTabBum > 0 ? favTabBum : stickersTabOffset) + 1); - return; - } } - int index = page - 1 - stickersTabOffset; + + int index = page - stickersTabOffset; if (index >= stickerSets.size()) { - if (listener != null) { - listener.onStickersSettingsClick(); - } return; } if (index >= stickerSets.size()) { index = stickerSets.size() - 1; } - firstAttach = false; + firstStickersAttach = false; + stickersGridView.stopScroll(); stickersLayoutManager.scrollToPositionWithOffset(stickersGridAdapter.getPositionForPack(stickerSets.get(index)), 0); checkStickersTabY(null, 0); checkScroll(); }); stickersGridView.setOnScrollListener(new RecyclerView.OnScrollListener() { - @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { - AndroidUtilities.hideKeyboard(searchEditText); + stickersSearchField.hideKeyboard(); } } @@ -1289,7 +1610,8 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific public void onScrolled(RecyclerView recyclerView, int dx, int dy) { checkScroll(); checkStickersTabY(recyclerView, dy); - checkSearchFieldScroll(); + checkStickersSearchFieldScroll(false); + checkBottomTabScroll(dy); } }); } @@ -1302,48 +1624,28 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } return super.onInterceptTouchEvent(ev); } + + @Override + public void setCurrentItem(int item, boolean smoothScroll) { + startStopVisibleGifs(item == 1); + if (item == getCurrentItem()) { + if (item == 0) { + emojiGridView.smoothScrollToPosition(needEmojiSearch ? 1 : 0); + } else if (item == 1) { + gifGridView.smoothScrollToPosition(1); + } else { + stickersGridView.smoothScrollToPosition(1); + } + return; + } + super.setCurrentItem(item, smoothScroll); + } }; pager.setAdapter(new EmojiPagesAdapter()); - emojiTab = new LinearLayout(context) { - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - if (getParent() != null) { - getParent().requestDisallowInterceptTouchEvent(true); - } - return super.onInterceptTouchEvent(ev); - } - }; - emojiTab.setOrientation(LinearLayout.HORIZONTAL); - addView(emojiTab, LayoutHelper.createFrame(LayoutParams.MATCH_PARENT, 48)); - - pagerSlidingTabStrip = new PagerSlidingTabStrip(context); - pagerSlidingTabStrip.setViewPager(pager); - pagerSlidingTabStrip.setShouldExpand(true); - pagerSlidingTabStrip.setIndicatorHeight(AndroidUtilities.dp(2)); - pagerSlidingTabStrip.setUnderlineHeight(AndroidUtilities.dp(1)); - pagerSlidingTabStrip.setIndicatorColor(Theme.getColor(Theme.key_chat_emojiPanelIconSelector)); - pagerSlidingTabStrip.setUnderlineColor(Theme.getColor(Theme.key_chat_emojiPanelShadowLine)); - emojiTab.addView(pagerSlidingTabStrip, LayoutHelper.createLinear(0, 48, 1.0f)); - pagerSlidingTabStrip.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - EmojiView.this.onPageScrolled(position, getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), positionOffsetPixels); - } - - @Override - public void onPageSelected(int position) { - saveNewPage(); - } - - @Override - public void onPageScrollStateChanged(int state) { - - } - }); - - FrameLayout frameLayout = new FrameLayout(context); - emojiTab.addView(frameLayout, LayoutHelper.createLinear(52, 48)); + topShadow = new View(context); + topShadow.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, 0xffe2e5e7)); + addView(topShadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 6)); backspaceButton = new ImageView(context) { @Override @@ -1355,7 +1657,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } else if (event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_UP) { backspacePressed = false; if (!backspaceOnce) { - if (listener != null && listener.onBackspace()) { + if (delegate != null && delegate.onBackspace()) { backspaceButton.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); } } @@ -1364,25 +1666,178 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific return true; } }; - backspaceButton.setImageResource(R.drawable.ic_smiles_backspace); + backspaceButton.setImageResource(R.drawable.smiles_tab_clear); backspaceButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelBackspace), PorterDuff.Mode.MULTIPLY)); backspaceButton.setScaleType(ImageView.ScaleType.CENTER); - frameLayout.addView(backspaceButton, LayoutHelper.createFrame(52, 48)); + backspaceButton.setContentDescription(LocaleController.getString("AccDescrBackspace", R.string.AccDescrBackspace)); + backspaceButton.setFocusable(true); + + bottomTabContainer = new FrameLayout(context) { + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (getParent() != null) { + getParent().requestDisallowInterceptTouchEvent(true); + } + return super.onInterceptTouchEvent(ev); + } + }; shadowLine = new View(context); shadowLine.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelShadowLine)); - frameLayout.addView(shadowLine, LayoutHelper.createFrame(52, 1, Gravity.LEFT | Gravity.BOTTOM)); + bottomTabContainer.addView(shadowLine, new FrameLayout.LayoutParams(LayoutHelper.MATCH_PARENT, AndroidUtilities.getShadowHeight())); - noRecentTextView = new TextView(context); - noRecentTextView.setText(LocaleController.getString("NoRecent", R.string.NoRecent)); - noRecentTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - noRecentTextView.setTextColor(Theme.getColor(Theme.key_chat_emojiPanelEmptyText)); - noRecentTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - noRecentTextView.setGravity(Gravity.CENTER); - noRecentTextView.setClickable(false); - noRecentTextView.setFocusable(false); - ((FrameLayout) views.get(0)).addView(noRecentTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 48, 0, 0)); - emojiGrids.get(0).setEmptyView(noRecentTextView); + bottomTabContainerBackground = new View(context); + bottomTabContainer.addView(bottomTabContainerBackground, new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, AndroidUtilities.dp(44), Gravity.LEFT | Gravity.BOTTOM)); + + if (needSearch) { + addView(bottomTabContainer, new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, AndroidUtilities.dp(44) + AndroidUtilities.getShadowHeight(), Gravity.LEFT | Gravity.BOTTOM)); + bottomTabContainer.addView(backspaceButton, LayoutHelper.createFrame(52, 44, Gravity.BOTTOM | Gravity.RIGHT)); + + stickerSettingsButton = new ImageView(context); + stickerSettingsButton.setImageResource(R.drawable.smiles_tab_settings); + stickerSettingsButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelBackspace), PorterDuff.Mode.MULTIPLY)); + stickerSettingsButton.setScaleType(ImageView.ScaleType.CENTER); + stickerSettingsButton.setFocusable(true); + stickerSettingsButton.setContentDescription(LocaleController.getString("Settings", R.string.Settings)); + bottomTabContainer.addView(stickerSettingsButton, LayoutHelper.createFrame(52, 44, Gravity.BOTTOM | Gravity.RIGHT)); + stickerSettingsButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (delegate != null) { + delegate.onStickersSettingsClick(); + } + } + }); + + typeTabs = new PagerSlidingTabStrip(context); + typeTabs.setViewPager(pager); + typeTabs.setShouldExpand(false); + typeTabs.setIndicatorHeight(0); + typeTabs.setUnderlineHeight(0); + typeTabs.setTabPaddingLeftRight(AndroidUtilities.dp(10)); + bottomTabContainer.addView(typeTabs, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 44, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM)); + typeTabs.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + EmojiView.this.onPageScrolled(position, getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), positionOffsetPixels); + showBottomTab(true, true); + SearchField currentField; + int p = pager.getCurrentItem(); + if (p == 0) { + currentField = emojiSearchField; + } else if (p == 1) { + currentField = gifSearchField; + } else { + currentField = stickersSearchField; + } + String currentFieldText = currentField.searchEditText.getText().toString(); + for (int a = 0; a < 3; a++) { + SearchField field; + if (a == 0) { + field = emojiSearchField; + } else if (a == 1) { + field = gifSearchField; + } else { + field = stickersSearchField; + } + if (field == null || field == currentField || field.searchEditText == null || field.searchEditText.getText().toString().equals(currentFieldText)) { + continue; + } + field.searchEditText.setText(currentFieldText); + field.searchEditText.setSelection(currentFieldText.length()); + } + } + + @Override + public void onPageSelected(int position) { + saveNewPage(); + showBackspaceButton(position == 0, true); + showStickerSettingsButton(position == 2, true); + if (delegate.isSearchOpened()) { + if (position == 0) { + if (emojiSearchField != null) { + emojiSearchField.searchEditText.requestFocus(); + } + } else if (position == 1) { + if (gifSearchField != null) { + gifSearchField.searchEditText.requestFocus(); + } + } else { + if (stickersSearchField != null) { + stickersSearchField.searchEditText.requestFocus(); + } + } + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + searchButton = new ImageView(context); + searchButton.setImageResource(R.drawable.smiles_tab_search); + searchButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelBackspace), PorterDuff.Mode.MULTIPLY)); + searchButton.setScaleType(ImageView.ScaleType.CENTER); + searchButton.setContentDescription(LocaleController.getString("Search", R.string.Search)); + searchButton.setFocusable(true); + bottomTabContainer.addView(searchButton, LayoutHelper.createFrame(52, 44, Gravity.BOTTOM | Gravity.LEFT)); + searchButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + SearchField currentField; + int currentItem = pager.getCurrentItem(); + if (currentItem == 0) { + currentField = emojiSearchField; + } else if (currentItem == 1) { + currentField = gifSearchField; + } else { + currentField = stickersSearchField; + } + if (currentField == null) { + return; + } + currentField.searchEditText.requestFocus(); + MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0); + currentField.searchEditText.onTouchEvent(event); + event.recycle(); + event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0); + currentField.searchEditText.onTouchEvent(event); + event.recycle(); + } + }); + } else { + addView(bottomTabContainer, LayoutHelper.createFrame((Build.VERSION.SDK_INT >= 21 ? 40 : 44) + 20, (Build.VERSION.SDK_INT >= 21 ? 40 : 44) + 12, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.BOTTOM, 0, 0, 2, 0)); + + Drawable drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), Theme.getColor(Theme.key_chat_emojiPanelBackground), Theme.getColor(Theme.key_chat_emojiPanelBackground)); + if (Build.VERSION.SDK_INT < 21) { + Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.floating_shadow).mutate(); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); + CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); + combinedDrawable.setIconSize(AndroidUtilities.dp(40), AndroidUtilities.dp(40)); + drawable = combinedDrawable; + } else { + StateListAnimator animator = new StateListAnimator(); + animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(floatingButton, View.TRANSLATION_Z, AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); + animator.addState(new int[]{}, ObjectAnimator.ofFloat(floatingButton, View.TRANSLATION_Z, AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200)); + backspaceButton.setStateListAnimator(animator); + backspaceButton.setOutlineProvider(new ViewOutlineProvider() { + @SuppressLint("NewApi") + @Override + public void getOutline(View view, Outline outline) { + outline.setOval(0, 0, AndroidUtilities.dp(40), AndroidUtilities.dp(40)); + } + }); + } + backspaceButton.setPadding(0, 0, AndroidUtilities.dp(2), 0); + backspaceButton.setBackgroundDrawable(drawable); + backspaceButton.setContentDescription(LocaleController.getString("AccDescrBackspace", R.string.AccDescrBackspace)); + backspaceButton.setFocusable(true); + bottomTabContainer.addView(backspaceButton, LayoutHelper.createFrame((Build.VERSION.SDK_INT >= 21 ? 40 : 44), (Build.VERSION.SDK_INT >= 21 ? 40 : 44), Gravity.LEFT | Gravity.TOP, 10, 0, 10, 0)); + shadowLine.setVisibility(GONE); + bottomTabContainerBackground.setVisibility(GONE); + } addView(pager, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP)); @@ -1393,7 +1848,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific mediaBanTooltip.setGravity(Gravity.CENTER_VERTICAL); mediaBanTooltip.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); mediaBanTooltip.setVisibility(INVISIBLE); - addView(mediaBanTooltip, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.RIGHT | Gravity.TOP, 30, 48 + 5, 5, 0)); + addView(mediaBanTooltip, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 5, 0, 5, 48 + 5)); emojiSize = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 40 : 32); pickerView = new EmojiColorPickerView(context); @@ -1412,25 +1867,247 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific }); currentPage = MessagesController.getGlobalEmojiSettings().getInt("selected_page", 0); Emoji.loadRecentEmoji(); - adapters.get(0).notifyDataSetChanged(); + emojiAdapter.notifyDataSetChanged(); + + if (typeTabs != null) { + if (views.size() == 1 && typeTabs.getVisibility() == VISIBLE) { + typeTabs.setVisibility(INVISIBLE); + } else if (views.size() != 1 && typeTabs.getVisibility() != VISIBLE) { + typeTabs.setVisibility(VISIBLE); + } + } + } + + private static String addColorToCode(String code, String color) { + String end = null; + int length = code.length(); + if (length > 2 && code.charAt(code.length() - 2) == '\u200D') { + end = code.substring(code.length() - 2); + code = code.substring(0, code.length() - 2); + } else if (length > 3 && code.charAt(code.length() - 3) == '\u200D') { + end = code.substring(code.length() - 3); + code = code.substring(0, code.length() - 3); + } + code += color; + if (end != null) { + code += end; + } + return code; + } + + @Override + public void setTranslationY(float translationY) { + super.setTranslationY(translationY); + if (bottomTabContainer.getTag() == null && (delegate == null || !delegate.isSearchOpened())) { + View parent = (View) getParent(); + if (parent != null) { + float y = getY() + getMeasuredHeight() - parent.getHeight(); + bottomTabContainer.setTranslationY(-y); + } + } + } + + private void startStopVisibleGifs(boolean start) { + if (gifGridView == null) { + return; + } + int count = gifGridView.getChildCount(); + for (int a = 0; a < count; a++) { + View child = gifGridView.getChildAt(a); + if (child instanceof ContextLinkCell) { + ContextLinkCell cell = (ContextLinkCell) child; + ImageReceiver imageReceiver = cell.getPhotoImage(); + if (start) { + imageReceiver.setAllowStartAnimation(true); + imageReceiver.startAnimation(); + } else { + imageReceiver.setAllowStartAnimation(false); + imageReceiver.stopAnimation(); + } + } + } + } + + public void addEmojiToRecent(String code) { + if (!Emoji.isValidEmoji(code)) { + return; + } + int oldCount = Emoji.recentEmoji.size(); + Emoji.addRecentEmoji(code); + if (getVisibility() != VISIBLE || pager.getCurrentItem() != 0) { + Emoji.sortEmoji(); + emojiAdapter.notifyDataSetChanged(); + } + Emoji.saveRecentEmoji(); + /*int addedCount = Emoji.recentEmoji.size() - oldCount; + int position = emojiLayoutManager.findLastVisibleItemPosition(); + int top = Integer.MAX_VALUE; + if (position != RecyclerView.NO_POSITION) { + View view = emojiLayoutManager.findViewByPosition(position); + if (view != null) { + top = view.getTop(); + } + } + emojiAdapter.notifyDataSetChanged(); + if (top != Integer.MAX_VALUE) { + emojiLayoutManager.scrollToPositionWithOffset(position + addedCount, top - emojiGridView.getPaddingTop()); + }*/ } public void showSearchField(boolean show) { - int position = stickersLayoutManager.findFirstVisibleItemPosition(); - if (show) { - if (position == 1 || position == 2) { - stickersLayoutManager.scrollToPosition(0); - stickersTab.setTranslationY(0); + GridLayoutManager layoutManager; + ScrollSlidingTabStrip tabStrip; + for (int a = 0; a < 3; a++) { + if (a == 0) { + layoutManager = emojiLayoutManager; + tabStrip = emojiTabs; + } else if (a == 1) { + layoutManager = gifLayoutManager; + tabStrip = null; + } else { + layoutManager = stickersLayoutManager; + tabStrip = stickersTab; } - } else { - if (position == 0) { - stickersLayoutManager.scrollToPositionWithOffset(1, 0); + if (layoutManager == null) { + continue; + } + int position = layoutManager.findFirstVisibleItemPosition(); + if (show) { + if (position == 1 || position == 2) { + layoutManager.scrollToPosition(0); + if (tabStrip != null) { + tabStrip.setTranslationY(0); + } + } + } else { + if (position == 0) { + layoutManager.scrollToPositionWithOffset(1, 0); + } } } } public void hideSearchKeyboard() { - AndroidUtilities.hideKeyboard(searchEditText); + if (stickersSearchField != null) { + stickersSearchField.hideKeyboard(); + } + if (gifSearchField != null) { + gifSearchField.hideKeyboard(); + } + if (emojiSearchField != null) { + emojiSearchField.hideKeyboard(); + } + } + + private void openSearch(SearchField searchField) { + if (searchAnimation != null) { + searchAnimation.cancel(); + searchAnimation = null; + } + + firstStickersAttach = false; + firstGifAttach = false; + firstEmojiAttach = false; + for (int a = 0; a < 3; a++) { + RecyclerListView gridView; + ScrollSlidingTabStrip tabStrip; + SearchField currentField; + GridLayoutManager layoutManager; + if (a == 0) { + currentField = emojiSearchField; + gridView = emojiGridView; + tabStrip = emojiTabs; + layoutManager = emojiLayoutManager; + } else if (a == 1) { + currentField = gifSearchField; + gridView = gifGridView; + tabStrip = null; + layoutManager = gifLayoutManager; + } else { + currentField = stickersSearchField; + gridView = stickersGridView; + tabStrip = stickersTab; + layoutManager = stickersLayoutManager; + } + if (currentField == null) { + continue; + } + + if (currentField != gifSearchField && searchField == currentField && delegate != null && delegate.isExpanded()) { + searchAnimation = new AnimatorSet(); + if (tabStrip != null) { + searchAnimation.playTogether( + ObjectAnimator.ofFloat(tabStrip, View.TRANSLATION_Y, -AndroidUtilities.dp(48)), + ObjectAnimator.ofFloat(gridView, View.TRANSLATION_Y, -AndroidUtilities.dp(48)), + ObjectAnimator.ofFloat(currentField, View.TRANSLATION_Y, AndroidUtilities.dp(0))); + } else { + searchAnimation.playTogether( + ObjectAnimator.ofFloat(gridView, View.TRANSLATION_Y, -AndroidUtilities.dp(48)), + ObjectAnimator.ofFloat(currentField, View.TRANSLATION_Y, AndroidUtilities.dp(0))); + } + searchAnimation.setDuration(200); + searchAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + searchAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (animation.equals(searchAnimation)) { + gridView.setTranslationY(0); + if (gridView == stickersGridView) { + gridView.setPadding(0, AndroidUtilities.dp(4), 0, 0); + } else if (gridView == emojiGridView) { + gridView.setPadding(0, 0, 0, 0); + } + searchAnimation = null; + } + } + + @Override + public void onAnimationCancel(Animator animation) { + if (animation.equals(searchAnimation)) { + searchAnimation = null; + } + } + }); + searchAnimation.start(); + } else { + currentField.setTranslationY(AndroidUtilities.dp(0)); + if (tabStrip != null) { + tabStrip.setTranslationY(-AndroidUtilities.dp(48)); + } + if (gridView == stickersGridView) { + gridView.setPadding(0, AndroidUtilities.dp(4), 0, 0); + } else if (gridView == emojiGridView) { + gridView.setPadding(0, 0, 0, 0); + } + layoutManager.scrollToPositionWithOffset(0, 0); + } + } + } + + private void showEmojiShadow(boolean show, boolean animated) { + if (show && emojiTabsShadow.getTag() == null || !show && emojiTabsShadow.getTag() != null) { + return; + } + if (emojiTabShadowAnimator != null) { + emojiTabShadowAnimator.cancel(); + emojiTabShadowAnimator = null; + } + emojiTabsShadow.setTag(show ? null : 1); + if (animated) { + emojiTabShadowAnimator = new AnimatorSet(); + emojiTabShadowAnimator.playTogether(ObjectAnimator.ofFloat(emojiTabsShadow, View.ALPHA, show ? 1.0f : 0.0f)); + emojiTabShadowAnimator.setDuration(200); + emojiTabShadowAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT); + emojiTabShadowAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + emojiTabShadowAnimator = null; + } + }); + emojiTabShadowAnimator.start(); + } else { + emojiTabsShadow.setAlpha(show ? 1.0f : 0.0f); + } } public void closeSearch(boolean animated) { @@ -1442,8 +2119,9 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific searchAnimation.cancel(); searchAnimation = null; } - searchEditText.setText(""); - if (scrollToSet != -1) { + + int currentItem = pager.getCurrentItem(); + if (currentItem == 2 && scrollToSet != -1) { TLRPC.TL_messages_stickerSet set = DataQuery.getInstance(currentAccount).getStickerSetById(scrollToSet); if (set != null) { int pos = stickersGridAdapter.getPositionForPack(set); @@ -1452,59 +2130,252 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } } + + for (int a = 0; a < 3; a++) { + SearchField currentField; + RecyclerListView gridView; + GridLayoutManager layoutManager; + ScrollSlidingTabStrip tabStrip; + + if (a == 0) { + currentField = emojiSearchField; + gridView = emojiGridView; + layoutManager = emojiLayoutManager; + tabStrip = emojiTabs; + } else if (a == 1) { + currentField = gifSearchField; + gridView = gifGridView; + layoutManager = gifLayoutManager; + tabStrip = null; + } else { + currentField = stickersSearchField; + gridView = stickersGridView; + layoutManager = stickersLayoutManager; + tabStrip = stickersTab; + } + + if (currentField == null) { + continue; + } + + currentField.searchEditText.setText(""); + + if (a == currentItem && animated) { + searchAnimation = new AnimatorSet(); + if (tabStrip != null) { + searchAnimation.playTogether( + ObjectAnimator.ofFloat(tabStrip, View.TRANSLATION_Y, 0), + ObjectAnimator.ofFloat(gridView, View.TRANSLATION_Y, AndroidUtilities.dp(48) - searchFieldHeight), + ObjectAnimator.ofFloat(currentField, View.TRANSLATION_Y, AndroidUtilities.dp(48) - searchFieldHeight)); + } else { + searchAnimation.playTogether( + ObjectAnimator.ofFloat(gridView, View.TRANSLATION_Y, -searchFieldHeight), + ObjectAnimator.ofFloat(currentField, View.TRANSLATION_Y, -searchFieldHeight)); + } + searchAnimation.setDuration(200); + searchAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + searchAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (animation.equals(searchAnimation)) { + int pos = layoutManager.findFirstVisibleItemPosition(); + int firstVisPos = layoutManager.findFirstVisibleItemPosition(); + int top = 0; + if (firstVisPos != RecyclerView.NO_POSITION) { + View firstVisView = layoutManager.findViewByPosition(firstVisPos); + top = (int) (firstVisView.getTop() + gridView.getTranslationY()); + } + gridView.setTranslationY(0); + if (gridView == stickersGridView) { + gridView.setPadding(0, AndroidUtilities.dp(48 + 4), 0, 0); + } else if (gridView == emojiGridView) { + gridView.setPadding(0, AndroidUtilities.dp(38), 0, 0); + } + if (gridView == gifGridView) { + layoutManager.scrollToPositionWithOffset(1, 0); + } else { + if (firstVisPos != RecyclerView.NO_POSITION) { + layoutManager.scrollToPositionWithOffset(firstVisPos, top - gridView.getPaddingTop()); + } + } + searchAnimation = null; + } + } + + @Override + public void onAnimationCancel(Animator animation) { + if (animation.equals(searchAnimation)) { + searchAnimation = null; + } + } + }); + searchAnimation.start(); + } else { + layoutManager.scrollToPositionWithOffset(1, 0); + currentField.setTranslationY(AndroidUtilities.dp(48) - searchFieldHeight); + if (tabStrip != null) { + tabStrip.setTranslationY(0); + } + if (gridView == stickersGridView) { + gridView.setPadding(0, AndroidUtilities.dp(48 + 4), 0, 0); + } else if (gridView == emojiGridView) { + gridView.setPadding(0, AndroidUtilities.dp(38), 0, 0); + } + } + } + if (!animated) { + delegate.onSearchOpenClose(0); + } + showBottomTab(true, animated); + } + + private void checkStickersSearchFieldScroll(boolean isLayout) { + if (delegate != null && delegate.isSearchOpened()) { + RecyclerView.ViewHolder holder = stickersGridView.findViewHolderForAdapterPosition(0); + if (holder == null) { + stickersSearchField.showShadow(true, !isLayout); + } else { + stickersSearchField.showShadow(holder.itemView.getTop() < stickersGridView.getPaddingTop(), !isLayout); + } + return; + } + if (stickersSearchField == null || stickersGridView == null) { + return; + } + RecyclerView.ViewHolder holder = stickersGridView.findViewHolderForAdapterPosition(0); + if (holder != null) { + stickersSearchField.setTranslationY(holder.itemView.getTop()); + } else { + stickersSearchField.setTranslationY(-searchFieldHeight); + } + stickersSearchField.showShadow(false, !isLayout); + } + + private void checkBottomTabScroll(float dy) { + lastBottomScrollDy += dy; + int offset; + if (pager.getCurrentItem() == 0) { + offset = AndroidUtilities.dp(38); + } else { + offset = AndroidUtilities.dp(48); + } + if (lastBottomScrollDy >= offset) { + showBottomTab(false, true); + } else if (lastBottomScrollDy <= -offset) { + showBottomTab(true, true); + } else if (bottomTabContainer.getTag() == null && lastBottomScrollDy < 0 || bottomTabContainer.getTag() != null && lastBottomScrollDy > 0) { + lastBottomScrollDy = 0; + } + } + + private void showBackspaceButton(boolean show, boolean animated) { + if (show && backspaceButton.getTag() == null || !show && backspaceButton.getTag() != null) { + return; + } + if (backspaceButtonAnimation != null) { + backspaceButtonAnimation.cancel(); + backspaceButtonAnimation = null; + } + backspaceButton.setTag(show ? null : 1); if (animated) { - searchAnimation = new AnimatorSet(); - searchAnimation.playTogether(ObjectAnimator.ofFloat(stickersTab, "translationY", 0), - ObjectAnimator.ofFloat(stickersGridView, "translationY", AndroidUtilities.dp(48) - searchFieldHeight), - ObjectAnimator.ofFloat(searchEditTextContainer, "translationY", AndroidUtilities.dp(48) - searchFieldHeight)); - searchAnimation.setDuration(200); - searchAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); - searchAnimation.addListener(new AnimatorListenerAdapter() { + if (show) { + backspaceButton.setVisibility(VISIBLE); + } + backspaceButtonAnimation = new AnimatorSet(); + backspaceButtonAnimation.playTogether(ObjectAnimator.ofFloat(backspaceButton, View.ALPHA, show ? 1.0f : 0.0f), + ObjectAnimator.ofFloat(backspaceButton, View.SCALE_X, show ? 1.0f : 0.0f), + ObjectAnimator.ofFloat(backspaceButton, View.SCALE_Y, show ? 1.0f : 0.0f)); + backspaceButtonAnimation.setDuration(200); + backspaceButtonAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT); + backspaceButtonAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - if (animation.equals(searchAnimation)) { - int pos = stickersLayoutManager.findFirstVisibleItemPosition(); - int firstVisPos = stickersLayoutManager.findFirstVisibleItemPosition(); - int top = 0; - if (firstVisPos != RecyclerView.NO_POSITION) { - View firstVisView = stickersLayoutManager.findViewByPosition(firstVisPos); - top = (int) (firstVisView.getTop() + stickersGridView.getTranslationY()); - } - stickersGridView.setTranslationY(0); - stickersGridView.setPadding(0, AndroidUtilities.dp(48 + 4), 0, 0); - if (firstVisPos != RecyclerView.NO_POSITION) { - stickersLayoutManager.scrollToPositionWithOffset(firstVisPos, top - stickersGridView.getPaddingTop()); - } - searchAnimation = null; - } - } - - @Override - public void onAnimationCancel(Animator animation) { - if (animation.equals(searchAnimation)) { - searchAnimation = null; + if (!show) { + backspaceButton.setVisibility(INVISIBLE); } } }); - searchAnimation.start(); + backspaceButtonAnimation.start(); } else { - stickersLayoutManager.scrollToPositionWithOffset(1, 0); - searchEditTextContainer.setTranslationY(AndroidUtilities.dp(48) - searchFieldHeight); - stickersTab.setTranslationY(0); - stickersGridView.setPadding(0, AndroidUtilities.dp(48 + 4), 0, 0); - listener.onSearchOpenClose(false); + backspaceButton.setAlpha(show ? 1.0f : 0.0f); + backspaceButton.setScaleX(show ? 1.0f : 0.0f); + backspaceButton.setScaleY(show ? 1.0f : 0.0f); + backspaceButton.setVisibility(show ? VISIBLE : INVISIBLE); + } + } + + private void showStickerSettingsButton(boolean show, boolean animated) { + if (stickerSettingsButton == null) { + return; + } + if (show && stickerSettingsButton.getTag() == null || !show && stickerSettingsButton.getTag() != null) { + return; + } + if (stickersButtonAnimation != null) { + stickersButtonAnimation.cancel(); + stickersButtonAnimation = null; + } + stickerSettingsButton.setTag(show ? null : 1); + if (animated) { + if (show) { + stickerSettingsButton.setVisibility(VISIBLE); + } + stickersButtonAnimation = new AnimatorSet(); + stickersButtonAnimation.playTogether(ObjectAnimator.ofFloat(stickerSettingsButton, View.ALPHA, show ? 1.0f : 0.0f), + ObjectAnimator.ofFloat(stickerSettingsButton, View.SCALE_X, show ? 1.0f : 0.0f), + ObjectAnimator.ofFloat(stickerSettingsButton, View.SCALE_Y, show ? 1.0f : 0.0f)); + stickersButtonAnimation.setDuration(200); + stickersButtonAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT); + stickersButtonAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (!show) { + stickerSettingsButton.setVisibility(INVISIBLE); + } + } + }); + stickersButtonAnimation.start(); + } else { + stickerSettingsButton.setAlpha(show ? 1.0f : 0.0f); + stickerSettingsButton.setScaleX(show ? 1.0f : 0.0f); + stickerSettingsButton.setScaleY(show ? 1.0f : 0.0f); + stickerSettingsButton.setVisibility(show ? VISIBLE : INVISIBLE); + } + } + + private void showBottomTab(boolean show, boolean animated) { + lastBottomScrollDy = 0; + if (show && bottomTabContainer.getTag() == null || !show && bottomTabContainer.getTag() != null || delegate != null && delegate.isSearchOpened()) { + return; + } + if (bottomTabContainerAnimation != null) { + bottomTabContainerAnimation.cancel(); + bottomTabContainerAnimation = null; + } + bottomTabContainer.setTag(show ? null : 1); + if (animated) { + bottomTabContainerAnimation = new AnimatorSet(); + bottomTabContainerAnimation.playTogether( + ObjectAnimator.ofFloat(bottomTabContainer, View.TRANSLATION_Y, show ? 0 : AndroidUtilities.dp(needEmojiSearch ? 49 : 54)), + ObjectAnimator.ofFloat(shadowLine, View.TRANSLATION_Y, show ? 0 : AndroidUtilities.dp(49))); + bottomTabContainerAnimation.setDuration(200); + bottomTabContainerAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT); + bottomTabContainerAnimation.start(); + } else { + bottomTabContainer.setTranslationY(show ? 0 : AndroidUtilities.dp(needEmojiSearch ? 49 : 54)); + shadowLine.setTranslationY(show ? 0 : AndroidUtilities.dp(49)); } } private void checkStickersTabY(View list, int dy) { if (list == null) { - stickersTab.setTranslationY(minusDy = 0); + stickersTab.setTranslationY(stickersMinusDy = 0); return; } if (list.getVisibility() != VISIBLE) { return; } - if (listener != null && listener.isSearchOpened()) { + if (delegate != null && delegate.isSearchOpened()) { return; } if (dy > 0 && stickersGridView != null && stickersGridView.getVisibility() == VISIBLE) { @@ -1513,25 +2384,93 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific return; } } - minusDy -= dy; - if (minusDy > 0) { - minusDy = 0; - } else if (minusDy < -AndroidUtilities.dp(48 * 6)) { - minusDy = -AndroidUtilities.dp(48 * 6); + stickersMinusDy -= dy; + if (stickersMinusDy > 0) { + stickersMinusDy = 0; + } else if (stickersMinusDy < -AndroidUtilities.dp(48 * 6)) { + stickersMinusDy = -AndroidUtilities.dp(48 * 6); } - stickersTab.setTranslationY(Math.max(-AndroidUtilities.dp(47), minusDy)); + stickersTab.setTranslationY(Math.max(-AndroidUtilities.dp(48), stickersMinusDy)); } - private void checkSearchFieldScroll() { - if (stickersGridView == null || listener != null && listener.isSearchOpened()) { + private void checkEmojiSearchFieldScroll(boolean isLayout) { + if (delegate != null && delegate.isSearchOpened()) { + RecyclerView.ViewHolder holder = emojiGridView.findViewHolderForAdapterPosition(0); + if (holder == null) { + emojiSearchField.showShadow(true, !isLayout); + } else { + emojiSearchField.showShadow(holder.itemView.getTop() < emojiGridView.getPaddingTop(), !isLayout); + } + showEmojiShadow(false, !isLayout); return; } - RecyclerView.ViewHolder holder = stickersGridView.findViewHolderForAdapterPosition(0); - if (holder != null) { - searchEditTextContainer.setTranslationY(holder.itemView.getTop()); - } else { - searchEditTextContainer.setTranslationY(-searchFieldHeight); + if (emojiSearchField == null || emojiGridView == null) { + return; } + RecyclerView.ViewHolder holder = emojiGridView.findViewHolderForAdapterPosition(0); + if (holder != null) { + emojiSearchField.setTranslationY(holder.itemView.getTop()); + } else { + emojiSearchField.setTranslationY(-searchFieldHeight); + } + emojiSearchField.showShadow(false, !isLayout); + showEmojiShadow(holder == null || holder.itemView.getTop() < AndroidUtilities.dp(38) - searchFieldHeight + emojiTabs.getTranslationY(), !isLayout); + } + + private void checkEmojiTabY(View list, int dy) { + if (list == null) { + emojiTabs.setTranslationY(emojiMinusDy = 0); + emojiTabsShadow.setTranslationY(emojiMinusDy); + return; + } + if (list.getVisibility() != VISIBLE) { + return; + } + if (delegate != null && delegate.isSearchOpened()) { + return; + } + if (dy > 0 && emojiGridView != null && emojiGridView.getVisibility() == VISIBLE) { + RecyclerView.ViewHolder holder = emojiGridView.findViewHolderForAdapterPosition(0); + if (holder != null && holder.itemView.getTop() + (needEmojiSearch ? searchFieldHeight : 0) >= emojiGridView.getPaddingTop()) { + return; + } + } + emojiMinusDy -= dy; + if (emojiMinusDy > 0) { + emojiMinusDy = 0; + } else if (emojiMinusDy < -AndroidUtilities.dp(48 * 6)) { + emojiMinusDy = -AndroidUtilities.dp(48 * 6); + } + emojiTabs.setTranslationY(Math.max(-AndroidUtilities.dp(38), emojiMinusDy)); + emojiTabsShadow.setTranslationY(emojiTabs.getTranslationY()); + } + + private void checkGifSearchFieldScroll(boolean isLayout) { + if (gifGridView != null && gifGridView.getAdapter() == gifSearchAdapter && !gifSearchAdapter.searchEndReached && gifSearchAdapter.reqId == 0 && !gifSearchAdapter.results.isEmpty()) { + int position = gifLayoutManager.findLastVisibleItemPosition(); + if (position != RecyclerView.NO_POSITION && position > gifLayoutManager.getItemCount() - 5) { + gifSearchAdapter.search(gifSearchAdapter.lastSearchImageString, gifSearchAdapter.nextSearchOffset, true); + } + } + if (delegate != null && delegate.isSearchOpened()) { + RecyclerView.ViewHolder holder = gifGridView.findViewHolderForAdapterPosition(0); + if (holder == null) { + gifSearchField.showShadow(true, !isLayout); + } else { + gifSearchField.showShadow(holder.itemView.getTop() < gifGridView.getPaddingTop(), !isLayout); + } + return; + } + if (gifSearchField == null || gifGridView == null) { + return; + } + RecyclerView.ViewHolder holder = gifGridView.findViewHolderForAdapterPosition(0); + if (holder != null) { + gifSearchField.setTranslationY(holder.itemView.getTop()); + } else { + gifSearchField.setTranslationY(-searchFieldHeight); + } + gifSearchField.showShadow(false, !isLayout); } private void checkScroll() { @@ -1550,27 +2489,19 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } else { firstTab = stickersTabOffset; } - if (stickersGridView.getVisibility() != VISIBLE) { - if (gifsGridView != null && gifsGridView.getVisibility() != VISIBLE) { - gifsGridView.setVisibility(VISIBLE); - } - if (stickersEmptyView != null && stickersEmptyView.getVisibility() == VISIBLE) { - stickersEmptyView.setVisibility(GONE); - } - stickersTab.onPageScrolled(gifTabNum + 1, firstTab + 1); - return; - } - stickersTab.onPageScrolled(stickersGridAdapter.getTabForPosition(firstVisibleItem) + 1, firstTab + 1); + stickersTab.onPageScrolled(stickersGridAdapter.getTabForPosition(firstVisibleItem), firstTab); } private void saveNewPage() { + if (pager == null) { + return; + } int newPage; - if (pager.getCurrentItem() == 6) { - if (gifsGridView != null && gifsGridView.getVisibility() == VISIBLE) { - newPage = 2; - } else { - newPage = 1; - } + int currentItem = pager.getCurrentItem(); + if (currentItem == 2) { + newPage = 1; + } else if (currentItem == 1) { + newPage = 2; } else { newPage = 0; } @@ -1582,61 +2513,33 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific public void clearRecentEmoji() { Emoji.clearRecentEmoji(); - adapters.get(0).notifyDataSetChanged(); + emojiAdapter.notifyDataSetChanged(); } - private void showTrendingTab() { - trendingGridView.setVisibility(VISIBLE); - stickersGridView.setVisibility(GONE); - firstAttach = true; - searchEditTextContainer.setVisibility(GONE); - stickersEmptyView.setVisibility(GONE); - gifsGridView.setVisibility(GONE); - stickersTab.onPageScrolled(trendingTabNum + 1, (recentTabBum > 0 ? recentTabBum : stickersTabOffset) + 1); - saveNewPage(); - } - - private void showGifTab() { - gifsGridView.setVisibility(VISIBLE); - stickersGridView.setVisibility(GONE); - firstAttach = true; - searchEditTextContainer.setVisibility(GONE); - stickersEmptyView.setVisibility(GONE); - trendingGridView.setVisibility(GONE); - stickersTab.onPageScrolled(gifTabNum + 1, (recentTabBum > 0 ? recentTabBum : stickersTabOffset) + 1); - saveNewPage(); + private void showTrendingTab(boolean show) { + if (show) { + trendingGridView.setVisibility(VISIBLE); + stickersGridView.setVisibility(GONE); + stickersSearchField.setVisibility(GONE); + stickersTab.onPageScrolled(trendingTabNum, recentTabBum > 0 ? recentTabBum : stickersTabOffset); + saveNewPage(); + } else { + trendingGridView.setVisibility(GONE); + stickersGridView.setVisibility(VISIBLE); + stickersSearchField.setVisibility(VISIBLE); + } } private void onPageScrolled(int position, int width, int positionOffsetPixels) { - if (stickersTab == null) { + if (delegate == null) { return; } - - if (width == 0) { - width = AndroidUtilities.displaySize.x; - } - - int margin = 0; - if (position == 5) { - margin = -positionOffsetPixels; - if (listener != null) { - listener.onStickersTab(positionOffsetPixels != 0); - } - } else if (position == 6) { - margin = -width; - if (listener != null) { - listener.onStickersTab(true); - } + if (position == 1) { + delegate.onTabOpened(positionOffsetPixels != 0 ? 2 : 0); + } else if (position == 2) { + delegate.onTabOpened(3); } else { - if (listener != null) { - listener.onStickersTab(false); - } - } - - if (emojiTab.getTranslationX() != margin) { - emojiTab.setTranslationX(margin); - stickersTab.setTranslationX(width + margin); - stickersTab.setVisibility(margin < 0 ? VISIBLE : INVISIBLE); + delegate.onTabOpened(0); } } @@ -1645,7 +2548,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (!backspacePressed) { return; } - if (listener != null && listener.onBackspace()) { + if (delegate != null && delegate.onBackspace()) { backspaceButton.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); } backspaceOnce = true; @@ -1654,12 +2557,36 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } public void switchToGifRecent() { - if (gifTabNum >= 0 && !recentGifs.isEmpty()) { - stickersTab.selectTab(gifTabNum + 1); - } else { - switchToGifTab = true; + showBackspaceButton(false, false); + showStickerSettingsButton(false, false); + pager.setCurrentItem(1, false); + } + + private void updateEmojiTabs() { + int newHas = Emoji.recentEmoji.isEmpty() ? 0 : 1; + if (hasRecentEmoji != -1 && hasRecentEmoji == newHas) { + return; } - pager.setCurrentItem(6); + hasRecentEmoji = newHas; + emojiTabs.removeTabs(); + String[] descriptions={ + LocaleController.getString("RecentStickers", R.string.RecentStickers), + LocaleController.getString("Emoji1", R.string.Emoji1), + LocaleController.getString("Emoji2", R.string.Emoji2), + LocaleController.getString("Emoji3", R.string.Emoji3), + LocaleController.getString("Emoji4", R.string.Emoji4), + LocaleController.getString("Emoji5", R.string.Emoji5), + LocaleController.getString("Emoji6", R.string.Emoji6), + LocaleController.getString("Emoji7", R.string.Emoji7), + LocaleController.getString("Emoji8", R.string.Emoji8), + }; + for (int a = 0; a < emojiIcons.length; a++) { + if (a == 0 && Emoji.recentEmoji.isEmpty()) { + continue; + } + emojiTabs.addIconTab(emojiIcons[a]).setContentDescription(descriptions[a]); + } + emojiTabs.updateTabStyles(); } private void updateStickerTabs() { @@ -1668,30 +2595,17 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } recentTabBum = -2; favTabBum = -2; - gifTabNum = -2; trendingTabNum = -2; stickersTabOffset = 0; int lastPosition = stickersTab.getCurrentPosition(); stickersTab.removeTabs(); - Drawable drawable = getContext().getResources().getDrawable(R.drawable.ic_smiles2_smile); - Theme.setDrawableColorByKey(drawable, Theme.key_chat_emojiPanelIcon); - stickersTab.addIconTab(drawable); - - if (showGifs && !recentGifs.isEmpty()) { - drawable = getContext().getResources().getDrawable(R.drawable.ic_smiles_gif); - Theme.setDrawableColorByKey(drawable, Theme.key_chat_emojiPanelIcon); - stickersTab.addIconTab(drawable); - gifTabNum = stickersTabOffset; - stickersTabOffset++; - } ArrayList unread = DataQuery.getInstance(currentAccount).getUnreadStickerSets(); + boolean hasStickers = false; if (trendingGridAdapter != null && trendingGridAdapter.getItemCount() != 0 && !unread.isEmpty()) { - drawable = getContext().getResources().getDrawable(R.drawable.ic_smiles_trend); - Theme.setDrawableColorByKey(drawable, Theme.key_chat_emojiPanelIcon); - stickersCounter = stickersTab.addIconTabWithCounter(drawable); + stickersCounter = stickersTab.addIconTabWithCounter(stickerIcons[2]); trendingTabNum = stickersTabOffset; stickersTabOffset++; stickersCounter.setText(String.format("%d", unread.size())); @@ -1700,17 +2614,15 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (!favouriteStickers.isEmpty()) { favTabBum = stickersTabOffset; stickersTabOffset++; - drawable = getContext().getResources().getDrawable(R.drawable.staredstickerstab); - Theme.setDrawableColorByKey(drawable, Theme.key_chat_emojiPanelIcon); - stickersTab.addIconTab(drawable); + stickersTab.addIconTab(stickerIcons[1]).setContentDescription(LocaleController.getString("FavoriteStickers", R.string.FavoriteStickers)); + hasStickers = true; } if (!recentStickers.isEmpty()) { recentTabBum = stickersTabOffset; stickersTabOffset++; - drawable = getContext().getResources().getDrawable(R.drawable.ic_smiles2_recent); - Theme.setDrawableColorByKey(drawable, Theme.key_chat_emojiPanelIcon); - stickersTab.addIconTab(drawable); + stickersTab.addIconTab(stickerIcons[0]).setContentDescription(LocaleController.getString("RecentStickers", R.string.RecentStickers)); + hasStickers = true; } stickerSets.clear(); @@ -1724,6 +2636,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific continue; } stickerSets.add(pack); + hasStickers = true; } if (info != null) { long hiddenStickerSetId = MessagesController.getEmojiSettings(currentAccount).getLong("group_hide_stickers_" + info.id, -1); @@ -1768,32 +2681,40 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific a--; } else { stickersTab.addStickerTab(chat); + hasStickers = true; } } else { TLRPC.TL_messages_stickerSet stickerSet = stickerSets.get(a); - stickersTab.addStickerTab(stickerSet.documents.get(0), stickerSet); + TLObject thumb; + TLRPC.Document document = stickerSet.documents.get(0); + if (stickerSet.set.thumb instanceof TLRPC.TL_photoSize) { + thumb = stickerSet.set.thumb; + } else { + thumb = document; + } + stickersTab.addStickerTab(thumb, document, stickerSet).setContentDescription(stickerSet.set.title + ", " + LocaleController.getString("AccDescrStickerSet", R.string.AccDescrStickerSet)); + hasStickers = true; } } if (trendingGridAdapter != null && trendingGridAdapter.getItemCount() != 0 && unread.isEmpty()) { - drawable = getContext().getResources().getDrawable(R.drawable.ic_smiles_trend); - Theme.setDrawableColorByKey(drawable, Theme.key_chat_emojiPanelIcon); trendingTabNum = stickersTabOffset + stickerSets.size(); - stickersTab.addIconTab(drawable); + stickersTab.addIconTab(stickerIcons[2]).setContentDescription(LocaleController.getString("FeaturedStickers", R.string.FeaturedStickers)); } - drawable = getContext().getResources().getDrawable(R.drawable.ic_smiles_settings); - Theme.setDrawableColorByKey(drawable, Theme.key_chat_emojiPanelIcon); - stickersTab.addIconTab(drawable); stickersTab.updateTabStyles(); if (lastPosition != 0) { stickersTab.onPageScrolled(lastPosition, lastPosition); } - if (switchToGifTab) { - if (gifTabNum >= 0 && gifsGridView.getVisibility() != VISIBLE) { - showGifTab(); - switchToGifTab = false; - } - } checkPanels(); + if ((!hasStickers || trendingTabNum == 0 && DataQuery.getInstance(currentAccount).areAllTrendingStickerSetsUnread()) && trendingTabNum >= 0) { + if (scrolledToTrending == 0) { + showTrendingTab(true); + scrolledToTrending = hasStickers ? 2 : 1; + } + } else if (scrolledToTrending == 1) { + showTrendingTab(false); + checkScroll(); + stickersTab.cancelPositionAnimation(); + } } private void checkPanels() { @@ -1801,37 +2722,24 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific return; } if (trendingTabNum == -2 && trendingGridView != null && trendingGridView.getVisibility() == VISIBLE) { - gifsGridView.setVisibility(GONE); trendingGridView.setVisibility(GONE); stickersGridView.setVisibility(VISIBLE); - searchEditTextContainer.setVisibility(VISIBLE); - stickersEmptyView.setVisibility(stickersGridAdapter.getItemCount() != 0 ? GONE : VISIBLE); + stickersSearchField.setVisibility(VISIBLE); } - if (gifTabNum == -2 && gifsGridView != null && gifsGridView.getVisibility() == VISIBLE) { - listener.onGifTab(false); - gifsGridView.setVisibility(GONE); - trendingGridView.setVisibility(GONE); - stickersGridView.setVisibility(VISIBLE); - searchEditTextContainer.setVisibility(VISIBLE); - stickersEmptyView.setVisibility(stickersGridAdapter.getItemCount() != 0 ? GONE : VISIBLE); - } else if (gifTabNum != -2) { - if (gifsGridView != null && gifsGridView.getVisibility() == VISIBLE) { - stickersTab.onPageScrolled(gifTabNum + 1, (recentTabBum > 0 ? recentTabBum : stickersTabOffset) + 1); - } else if (trendingGridView != null && trendingGridView.getVisibility() == VISIBLE) { - stickersTab.onPageScrolled(trendingTabNum + 1, (recentTabBum > 0 ? recentTabBum : stickersTabOffset) + 1); - } else { - int position = stickersLayoutManager.findFirstVisibleItemPosition(); - if (position != RecyclerView.NO_POSITION) { - int firstTab; - if (favTabBum > 0) { - firstTab = favTabBum; - } else if (recentTabBum > 0) { - firstTab = recentTabBum; - } else { - firstTab = stickersTabOffset; - } - stickersTab.onPageScrolled(stickersGridAdapter.getTabForPosition(position) + 1, firstTab + 1); + if (trendingGridView != null && trendingGridView.getVisibility() == VISIBLE) { + stickersTab.onPageScrolled(trendingTabNum, recentTabBum > 0 ? recentTabBum : stickersTabOffset); + } else { + int position = stickersLayoutManager.findFirstVisibleItemPosition(); + if (position != RecyclerView.NO_POSITION) { + int firstTab; + if (favTabBum > 0) { + firstTab = favTabBum; + } else if (recentTabBum > 0) { + firstTab = recentTabBum; + } else { + firstTab = stickersTabOffset; } + stickersTab.onPageScrolled(stickersGridAdapter.getTabForPosition(position), firstTab); } } } @@ -1857,8 +2765,8 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } boolean wasEmpty = recentGifs.isEmpty(); recentGifs = DataQuery.getInstance(currentAccount).getRecentGifs(); - if (gifsAdapter != null) { - gifsAdapter.notifyDataSetChanged(); + if (gifAdapter != null) { + gifAdapter.notifyDataSetChanged(); } if (wasEmpty) { updateStickerTabs(); @@ -1881,45 +2789,65 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } else { setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); - emojiTab.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + if (needEmojiSearch) { + bottomTabContainerBackground.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + } } - if (searchEditTextContainer != null) { - searchEditTextContainer.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + if (emojiTabs != null) { + emojiTabs.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + emojiTabsShadow.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelShadowLine)); + } + for (int a = 0; a < 3; a++) { + SearchField searchField; + if (a == 0) { + searchField = stickersSearchField; + } else if (a == 1) { + searchField = emojiSearchField; + } else { + searchField = gifSearchField; + } + if (searchField == null) { + continue; + } + searchField.backgroundView.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + searchField.shadowView.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelShadowLine)); + searchField.clearSearchImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiSearchIcon), PorterDuff.Mode.MULTIPLY)); + searchField.searchIconImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiSearchIcon), PorterDuff.Mode.MULTIPLY)); + Theme.setDrawableColorByKey(searchField.searchBackground.getBackground(), Theme.key_chat_emojiSearchBackground); + searchField.searchBackground.invalidate(); + searchField.searchEditText.setHintTextColor(Theme.getColor(Theme.key_chat_emojiSearchIcon)); + searchField.searchEditText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); } if (dotPaint != null) { dotPaint.setColor(Theme.getColor(Theme.key_chat_emojiPanelNewTrending)); } + if (emojiGridView != null) { + emojiGridView.setGlowColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + } if (stickersGridView != null) { stickersGridView.setGlowColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); } if (trendingGridView != null) { trendingGridView.setGlowColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); } - if (stickersEmptyView != null) { - stickersEmptyView.setTextColor(Theme.getColor(Theme.key_chat_emojiPanelEmptyText)); - } if (stickersTab != null) { - stickersTab.setIndicatorColor(Theme.getColor(Theme.key_chat_emojiPanelStickerPackSelector)); - stickersTab.setUnderlineColor(Theme.getColor(Theme.key_chat_emojiPanelStickerPackSelector)); + stickersTab.setIndicatorColor(Theme.getColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)); + stickersTab.setUnderlineColor(Theme.getColor(Theme.key_chat_emojiPanelShadowLine)); stickersTab.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); } - if (pagerSlidingTabStrip != null) { - pagerSlidingTabStrip.setIndicatorColor(Theme.getColor(Theme.key_chat_emojiPanelIconSelector)); - pagerSlidingTabStrip.setUnderlineColor(Theme.getColor(Theme.key_chat_emojiPanelShadowLine)); - } if (backspaceButton != null) { backspaceButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelBackspace), PorterDuff.Mode.MULTIPLY)); } - if (searchIconImageView != null) { - clearSearchImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelIcon), PorterDuff.Mode.MULTIPLY)); + if (stickerSettingsButton != null) { + stickerSettingsButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelBackspace), PorterDuff.Mode.MULTIPLY)); + } + if (searchButton != null) { + searchButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelBackspace), PorterDuff.Mode.MULTIPLY)); } if (shadowLine != null) { shadowLine.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelShadowLine)); } - if (noRecentTextView != null) { - noRecentTextView.setTextColor(Theme.getColor(Theme.key_chat_emojiPanelEmptyText)); - } if (mediaBanTooltip != null) { ((ShapeDrawable) mediaBanTooltip.getBackground()).getPaint().setColor(Theme.getColor(Theme.key_chat_gifSaveHintBackground)); mediaBanTooltip.setTextColor(Theme.getColor(Theme.key_chat_gifSaveHintText)); @@ -1930,14 +2858,17 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific stickersCounter.invalidate(); } - Theme.setDrawableColorByKey(stickersDrawable, Theme.key_chat_emojiPanelIcon); - for (int a = 0; a < icons.length - 1; a++) { - Theme.setEmojiDrawableColor(icons[a], Theme.getColor(Theme.key_chat_emojiPanelIcon), false); - Theme.setEmojiDrawableColor(icons[a], Theme.getColor(Theme.key_chat_emojiPanelIconSelected), true); + for (int a = 0; a < tabIcons.length; a++) { + Theme.setEmojiDrawableColor(tabIcons[a], Theme.getColor(Theme.key_chat_emojiBottomPanelIcon), false); + Theme.setEmojiDrawableColor(tabIcons[a], Theme.getColor(Theme.key_chat_emojiPanelIconSelected), true); } - if (searchBackground != null) { - Theme.setDrawableColorByKey(searchBackground.getBackground(), Theme.key_chat_emojiSearchBackground); - searchBackground.invalidate(); + for (int a = 0; a < emojiIcons.length; a++) { + Theme.setEmojiDrawableColor(emojiIcons[a], Theme.getColor(Theme.key_chat_emojiPanelIcon), false); + Theme.setEmojiDrawableColor(emojiIcons[a], Theme.getColor(Theme.key_chat_emojiPanelIconSelected), true); + } + for (int a = 0; a < stickerIcons.length; a++) { + Theme.setEmojiDrawableColor(stickerIcons[a], Theme.getColor(Theme.key_chat_emojiPanelIcon), false); + Theme.setEmojiDrawableColor(stickerIcons[a], Theme.getColor(Theme.key_chat_emojiPanelIconSelected), true); } } @@ -1953,7 +2884,9 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } setBackgroundResource(R.drawable.smiles_popup); getBackground().setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelBackground), PorterDuff.Mode.MULTIPLY)); - emojiTab.setBackgroundDrawable(null); + if (needEmojiSearch) { + bottomTabContainerBackground.setBackgroundDrawable(null); + } currentBackgroundType = 1; } } else { @@ -1964,29 +2897,13 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific setElevation(0); } setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); - emojiTab.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + if (needEmojiSearch) { + bottomTabContainerBackground.setBackgroundColor(Theme.getColor(Theme.key_chat_emojiPanelBackground)); + } currentBackgroundType = 0; } } - - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) emojiTab.getLayoutParams(); - FrameLayout.LayoutParams layoutParams1 = null; - layoutParams.width = View.MeasureSpec.getSize(widthMeasureSpec); - if (stickersTab != null) { - layoutParams1 = (FrameLayout.LayoutParams) stickersTab.getLayoutParams(); - if (layoutParams1 != null) { - layoutParams1.width = layoutParams.width; - } - } - if (layoutParams.width != oldWidth) { - if (stickersTab != null && layoutParams1 != null) { - onPageScrolled(pager.getCurrentItem(), layoutParams.width - getPaddingLeft() - getPaddingRight(), 0); - stickersTab.setLayoutParams(layoutParams1); - } - emojiTab.setLayoutParams(layoutParams); - oldWidth = layoutParams.width; - } - super.onMeasure(View.MeasureSpec.makeMeasureSpec(layoutParams.width, MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(View.MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY)); + super.onMeasure(View.MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(View.MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY)); isLayout = false; } @@ -1996,6 +2913,27 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific lastNotifyWidth = right - left; reloadStickersAdapter(); } + View parent = (View) getParent(); + if (parent != null) { + int newHeight = bottom - top; + int newHeight2 = parent.getHeight(); + if (lastNotifyHeight != newHeight || lastNotifyHeight2 != newHeight2) { + if (delegate != null && delegate.isSearchOpened()) { + bottomTabContainer.setTranslationY(AndroidUtilities.dp(49)); + } else { + if (bottomTabContainer.getTag() == null) { + if (newHeight < lastNotifyHeight) { + bottomTabContainer.setTranslationY(0); + } else { + float y = getY() + getMeasuredHeight() - parent.getHeight(); + bottomTabContainer.setTranslationY(-y); + } + } + } + lastNotifyHeight = newHeight; + lastNotifyHeight2 = newHeight2; + } + } super.onLayout(changed, left, top, right, bottom); } @@ -2009,18 +2947,18 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (stickersSearchGridAdapter != null) { stickersSearchGridAdapter.notifyDataSetChanged(); } - if (StickerPreviewViewer.getInstance().isVisible()) { - StickerPreviewViewer.getInstance().close(); + if (ContentPreviewViewer.getInstance().isVisible()) { + ContentPreviewViewer.getInstance().close(); } - StickerPreviewViewer.getInstance().reset(); + ContentPreviewViewer.getInstance().reset(); } - public void setListener(Listener value) { - listener = value; + public void setDelegate(EmojiViewDelegate emojiViewDelegate) { + delegate = emojiViewDelegate; } - public void setDragListener(DragListener dragListener) { - this.dragListener = dragListener; + public void setDragListener(DragListener listener) { + dragListener = listener; } public void setChatInfo(TLRPC.ChatFull chatInfo) { @@ -2029,9 +2967,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } public void invalidateViews() { - for (int a = 0; a < emojiGrids.size(); a++) { - emojiGrids.get(a).invalidateViews(); - } + emojiGridView.invalidateViews(); } public void setForseMultiwindowLayout(boolean value) { @@ -2039,49 +2975,47 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } public void onOpen(boolean forceEmoji) { - if (stickersTab != null) { - if (currentPage != 0 && currentChatId != 0) { - currentPage = 0; + if (currentPage != 0 && currentChatId != 0) { + currentPage = 0; + } + if (currentPage == 0 || forceEmoji || views.size() == 1) { + showBackspaceButton(true, false); + showStickerSettingsButton(false, false); + if (pager.getCurrentItem() != 0) { + pager.setCurrentItem(0, !forceEmoji); } - if (currentPage == 0 || forceEmoji) { - if (pager.getCurrentItem() == 6) { - pager.setCurrentItem(0, !forceEmoji); - } - } else if (currentPage == 1) { - if (pager.getCurrentItem() != 6) { - pager.setCurrentItem(6); - } - if (stickersTab.getCurrentPosition() == gifTabNum + 1) { - if (recentTabBum >= 0) { - stickersTab.selectTab(recentTabBum + 1); - } else if (favTabBum >= 0) { - stickersTab.selectTab(favTabBum + 1); - } else if (gifTabNum >= 0) { - stickersTab.selectTab(gifTabNum + 2); - } else { - stickersTab.selectTab(1); - } - } - } else if (currentPage == 2) { - if (pager.getCurrentItem() != 6) { - pager.setCurrentItem(6); - } - if (stickersTab.getCurrentPosition() != gifTabNum + 1) { - if (gifTabNum >= 0 && !recentGifs.isEmpty()) { - stickersTab.selectTab(gifTabNum + 1); - } else { - switchToGifTab = true; - } + } else if (currentPage == 1) { + showBackspaceButton(false, false); + showStickerSettingsButton(true, false); + if (pager.getCurrentItem() != 2) { + pager.setCurrentItem(2, false); + } + if (stickersTab != null) { + if (trendingTabNum == 0 && DataQuery.getInstance(currentAccount).areAllTrendingStickerSetsUnread()) { + showTrendingTab(true); + } else if (recentTabBum >= 0) { + stickersTab.selectTab(recentTabBum); + } else if (favTabBum >= 0) { + stickersTab.selectTab(favTabBum); + } else { + stickersTab.selectTab(stickersTabOffset); } } + } else if (currentPage == 2) { + showBackspaceButton(false, false); + showStickerSettingsButton(false, false); + if (pager.getCurrentItem() != 1) { + pager.setCurrentItem(1, false); + } } } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiDidLoad); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.newEmojiSuggestionsAvailable); if (stickersGridAdapter != null) { - NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.stickersDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.recentImagesDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.featuredStickersDidLoad); @@ -2098,15 +3032,15 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific super.setVisibility(visibility); if (visibility != GONE) { Emoji.sortEmoji(); - adapters.get(0).notifyDataSetChanged(); + emojiAdapter.notifyDataSetChanged(); if (stickersGridAdapter != null) { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.stickersDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.recentDocumentsDidLoad); updateStickerTabs(); reloadStickersAdapter(); - if (gifsGridView != null && gifsGridView.getVisibility() == VISIBLE && listener != null) { - listener.onGifTab(pager != null && pager.getCurrentItem() >= 6); - } + /*if (gifGridView != null && delegate != null) { + delegate.onTabOpened(pager != null && pager.getCurrentItem() == 1 ? 1 : ); + }*/ } if (trendingGridAdapter != null) { trendingLoaded = false; @@ -2125,8 +3059,9 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } public void onDestroy() { + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiDidLoad); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.newEmojiSuggestionsAvailable); if (stickersGridAdapter != null) { - NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.stickersDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.recentDocumentsDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.featuredStickersDidLoad); @@ -2144,16 +3079,9 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private void checkDocuments(boolean isGif) { if (isGif) { - int previousCount = recentGifs.size(); recentGifs = DataQuery.getInstance(currentAccount).getRecentGifs(); - if (gifsAdapter != null) { - gifsAdapter.notifyDataSetChanged(); - } - if (previousCount != recentGifs.size()) { - updateStickerTabs(); - } - if (stickersGridAdapter != null) { - stickersGridAdapter.notifyDataSetChanged(); + if (gifAdapter != null) { + gifAdapter.notifyDataSetChanged(); } } else { int previousCount = recentStickers.size(); @@ -2181,21 +3109,26 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } public void setStickersBanned(boolean value, int chatId) { + if (typeTabs == null) { + return; + } if (value) { currentChatId = chatId; } else { currentChatId = 0; } - View view = pagerSlidingTabStrip.getTab(6); + View view = typeTabs.getTab(2); if (view != null) { view.setAlpha(currentChatId != 0 ? 0.5f : 1.0f); - if (currentChatId != 0 && pager.getCurrentItem() == 6) { - pager.setCurrentItem(0); + if (currentChatId != 0 && pager.getCurrentItem() != 0) { + showBackspaceButton(true, true); + showStickerSettingsButton(false, true); + pager.setCurrentItem(0, false); } } } - public void showStickerBanHint() { + public void showStickerBanHint(boolean gif) { if (mediaBanTooltip.getVisibility() == VISIBLE) { return; } @@ -2206,21 +3139,33 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific String text; if (!ChatObject.hasAdminRights(chat) && chat.default_banned_rights != null && chat.default_banned_rights.send_stickers) { - mediaBanTooltip.setText(LocaleController.getString("GlobalAttachStickersRestricted", R.string.GlobalAttachStickersRestricted)); + if (gif) { + mediaBanTooltip.setText(LocaleController.getString("GlobalAttachGifRestricted", R.string.GlobalAttachGifRestricted)); + } else { + mediaBanTooltip.setText(LocaleController.getString("GlobalAttachStickersRestricted", R.string.GlobalAttachStickersRestricted)); + } } else { if (chat.banned_rights == null) { return; } if (AndroidUtilities.isBannedForever(chat.banned_rights)) { - mediaBanTooltip.setText(LocaleController.getString("AttachStickersRestrictedForever", R.string.AttachStickersRestrictedForever)); + if (gif) { + mediaBanTooltip.setText(LocaleController.getString("AttachGifRestrictedForever", R.string.AttachGifRestrictedForever)); + } else { + mediaBanTooltip.setText(LocaleController.getString("AttachStickersRestrictedForever", R.string.AttachStickersRestrictedForever)); + } } else { - mediaBanTooltip.setText(LocaleController.formatString("AttachStickersRestricted", R.string.AttachStickersRestricted, LocaleController.formatDateForBan(chat.banned_rights.until_date))); + if (gif) { + mediaBanTooltip.setText(LocaleController.formatString("AttachGifRestricted", R.string.AttachGifRestricted, LocaleController.formatDateForBan(chat.banned_rights.until_date))); + } else { + mediaBanTooltip.setText(LocaleController.formatString("AttachStickersRestricted", R.string.AttachStickersRestricted, LocaleController.formatDateForBan(chat.banned_rights.until_date))); + } } } mediaBanTooltip.setVisibility(View.VISIBLE); AnimatorSet AnimatorSet = new AnimatorSet(); AnimatorSet.playTogether( - ObjectAnimator.ofFloat(mediaBanTooltip, "alpha", 0.0f, 1.0f) + ObjectAnimator.ofFloat(mediaBanTooltip, View.ALPHA, 0.0f, 1.0f) ); AnimatorSet.addListener(new AnimatorListenerAdapter() { @Override @@ -2231,7 +3176,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } AnimatorSet AnimatorSet1 = new AnimatorSet(); AnimatorSet1.playTogether( - ObjectAnimator.ofFloat(mediaBanTooltip, "alpha", 0.0f) + ObjectAnimator.ofFloat(mediaBanTooltip, View.ALPHA, 0.0f) ); AnimatorSet1.addListener(new AnimatorListenerAdapter() { @Override @@ -2255,34 +3200,37 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific return; } try { - int count = trendingGridView.getChildCount(); - for (int a = 0; a < count; a++) { - View child = trendingGridView.getChildAt(a); - if (child instanceof FeaturedStickerSetInfoCell) { - RecyclerListView.Holder holder = (RecyclerListView.Holder) trendingGridView.getChildViewHolder(child); - if (holder == null) { - continue; - } - FeaturedStickerSetInfoCell cell = (FeaturedStickerSetInfoCell) child; - ArrayList unreadStickers = DataQuery.getInstance(currentAccount).getUnreadStickerSets(); - TLRPC.StickerSetCovered stickerSetCovered = cell.getStickerSet(); - boolean unread = unreadStickers != null && unreadStickers.contains(stickerSetCovered.set.id); - cell.setStickerSet(stickerSetCovered, unread); - if (unread) { - DataQuery.getInstance(currentAccount).markFaturedStickersByIdAsRead(stickerSetCovered.set.id); - } - boolean installing = installingStickerSets.indexOfKey(stickerSetCovered.set.id) >= 0; - boolean removing = removingStickerSets.indexOfKey(stickerSetCovered.set.id) >= 0; - if (installing || removing) { - if (installing && cell.isInstalled()) { - installingStickerSets.remove(stickerSetCovered.set.id); - installing = false; - } else if (removing && !cell.isInstalled()) { - removingStickerSets.remove(stickerSetCovered.set.id); - removing = false; + for (int b = 0; b < 2; b++) { + RecyclerListView gridView = b == 0 ? trendingGridView : stickersGridView; + int count = gridView.getChildCount(); + for (int a = 0; a < count; a++) { + View child = gridView.getChildAt(a); + if (child instanceof FeaturedStickerSetInfoCell) { + RecyclerListView.Holder holder = (RecyclerListView.Holder) gridView.getChildViewHolder(child); + if (holder == null) { + continue; } + FeaturedStickerSetInfoCell cell = (FeaturedStickerSetInfoCell) child; + ArrayList unreadStickers = DataQuery.getInstance(currentAccount).getUnreadStickerSets(); + TLRPC.StickerSetCovered stickerSetCovered = cell.getStickerSet(); + boolean unread = unreadStickers != null && unreadStickers.contains(stickerSetCovered.set.id); + cell.setStickerSet(stickerSetCovered, unread); + if (unread) { + DataQuery.getInstance(currentAccount).markFaturedStickersByIdAsRead(stickerSetCovered.set.id); + } + boolean installing = installingStickerSets.indexOfKey(stickerSetCovered.set.id) >= 0; + boolean removing = removingStickerSets.indexOfKey(stickerSetCovered.set.id) >= 0; + if (installing || removing) { + if (installing && cell.isInstalled()) { + installingStickerSets.remove(stickerSetCovered.set.id); + installing = false; + } else if (removing && !cell.isInstalled()) { + removingStickerSets.remove(stickerSetCovered.set.id); + removing = false; + } + } + cell.setDrawProgress(installing || removing); } - cell.setDrawProgress(installing || removing); } } } catch (Exception e) { @@ -2327,10 +3275,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific trendingGridAdapter.notifyDataSetChanged(); } } - if (pagerSlidingTabStrip != null) { - int count = pagerSlidingTabStrip.getChildCount(); + if (typeTabs != null) { + int count = typeTabs.getChildCount(); for (int a = 0; a < count; a++) { - pagerSlidingTabStrip.getChildAt(a).invalidate(); + typeTabs.getChildAt(a).invalidate(); } } updateStickerTabs(); @@ -2343,11 +3291,15 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific int count = stickersGridView.getChildCount(); for (int a = 0; a < count; a++) { View child = stickersGridView.getChildAt(a); - if (child instanceof StickerSetNameCell) { + if (child instanceof StickerSetNameCell || child instanceof StickerEmojiCell) { child.invalidate(); } } } + } else if (id == NotificationCenter.newEmojiSuggestionsAvailable) { + if (emojiGridView != null && needEmojiSearch && (emojiSearchField.progressDrawable.isAnimating() || emojiGridView.getAdapter() == emojiSearchAdapter) && !TextUtils.isEmpty(emojiSearchAdapter.lastSearchEmojiString)) { + emojiSearchAdapter.search(emojiSearchAdapter.lastSearchEmojiString); + } } } @@ -2415,10 +3367,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } if (parent1.isInstalled()) { removingStickerSets.put(pack.set.id, pack); - listener.onStickerSetRemove(parent1.getStickerSet()); + delegate.onStickerSetRemove(parent1.getStickerSet()); } else { installingStickerSets.put(pack.set.id, pack); - listener.onStickerSetAdd(parent1.getStickerSet()); + delegate.onStickerSetAdd(parent1.getStickerSet()); } parent1.setDrawProgress(true); }); @@ -2625,11 +3577,11 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific view = new EmptyCell(context); break; case 2: - view = new StickerSetNameCell(context); + view = new StickerSetNameCell(context, false); ((StickerSetNameCell) view).setOnIconClickListener(v -> { if (groupStickerSet != null) { - if (listener != null) { - listener.onStickersGroupClick(info.id); + if (delegate != null) { + delegate.onStickersGroupClick(info.id); } } else { MessagesController.getEmojiSettings(currentAccount).edit().putLong("group_hide_stickers_" + info.id, info.stickerset != null ? info.stickerset.id : 0).commit(); @@ -2643,8 +3595,8 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific case 3: view = new StickerSetGroupInfoCell(context); ((StickerSetGroupInfoCell) view).setAddOnClickListener(v -> { - if (listener != null) { - listener.onStickersGroupClick(info.id); + if (delegate != null) { + delegate.onStickersGroupClick(info.id); } }); view.setLayoutParams(new RecyclerView.LayoutParams(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); @@ -2819,25 +3771,15 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } - private class EmojiGridAdapter extends BaseAdapter { + private class EmojiGridAdapter extends RecyclerListView.SelectionAdapter { - private int emojiPage; - - public EmojiGridAdapter(int page) { - emojiPage = page; - } + private SparseIntArray positionToSection = new SparseIntArray(); + private SparseIntArray sectionToPosition = new SparseIntArray(); + private int itemCount; @Override - public Object getItem(int position) { - return null; - } - - @Override - public int getCount() { - if (emojiPage == -1) { - return Emoji.recentEmoji.size(); - } - return EmojiData.dataColored[emojiPage].length; + public int getItemCount() { + return itemCount; } @Override @@ -2846,31 +3788,324 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } @Override - public View getView(int position, View view, ViewGroup paramViewGroup) { - ImageViewEmoji imageView = (ImageViewEmoji) view; - if (imageView == null) { - imageView = new ImageViewEmoji(getContext()); - } - String code; - String coloredCode; - if (emojiPage == -1) { - coloredCode = code = Emoji.recentEmoji.get(position); - } else { - coloredCode = code = EmojiData.dataColored[emojiPage][position]; - String color = Emoji.emojiColor.get(code); - if (color != null) { - coloredCode = addColorToCode(coloredCode, color); - } - } - imageView.setImageDrawable(Emoji.getEmojiBigDrawable(coloredCode)); - imageView.setTag(code); - return imageView; + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return holder.getItemViewType() == 0; } @Override - public void unregisterDataSetObserver(DataSetObserver observer) { - if (observer != null) { - super.unregisterDataSetObserver(observer); + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view; + switch (viewType) { + case 0: + view = new ImageViewEmoji(getContext()); + break; + case 1: + view = new StickerSetNameCell(getContext(), true); + break; + case 2: + default: + view = new View(getContext()); + view.setLayoutParams(new RecyclerView.LayoutParams(LayoutHelper.MATCH_PARENT, searchFieldHeight)); + break; + } + return new RecyclerListView.Holder(view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + switch (holder.getItemViewType()) { + case 0: { + ImageViewEmoji imageView = (ImageViewEmoji) holder.itemView; + + String code; + String coloredCode; + boolean recent; + if (needEmojiSearch) { + position--; + } + + int count = Emoji.recentEmoji.size(); + if (position < count) { + coloredCode = code = Emoji.recentEmoji.get(position); + recent = true; + } else { + code = null; + coloredCode = null; + for (int a = 0; a < EmojiData.dataColored.length; a++) { + int size = EmojiData.dataColored[a].length + 1; + if (position < count + size) { + coloredCode = code = EmojiData.dataColored[a][position - count - 1]; + String color = Emoji.emojiColor.get(code); + if (color != null) { + coloredCode = addColorToCode(coloredCode, color); + } + break; + } + count += size; + } + recent = false; + } + imageView.setImageDrawable(Emoji.getEmojiBigDrawable(coloredCode), recent); + imageView.setTag(code); + imageView.setContentDescription(coloredCode); + break; + } + case 1: { + StickerSetNameCell cell = (StickerSetNameCell) holder.itemView; + cell.setText(emojiTitles[positionToSection.get(position)], 0); + break; + } + } + } + + @Override + public int getItemViewType(int position) { + if (needEmojiSearch && position == 0) { + return 2; + } else if (positionToSection.indexOfKey(position) >= 0) { + return 1; + } + return 0; + } + + @Override + public void notifyDataSetChanged() { + positionToSection.clear(); + itemCount = Emoji.recentEmoji.size() + (needEmojiSearch ? 1 : 0); + for (int a = 0; a < EmojiData.dataColored.length; a++) { + positionToSection.put(itemCount, a); + sectionToPosition.put(a, itemCount); + itemCount += EmojiData.dataColored[a].length + 1; + } + updateEmojiTabs(); + super.notifyDataSetChanged(); + } + } + + private class EmojiSearchAdapter extends RecyclerListView.SelectionAdapter { + + private ArrayList result = new ArrayList<>(); + private String lastSearchEmojiString; + private String lastSearchAlias; + private Runnable searchRunnable; + private boolean searchWas; + + @Override + public int getItemCount() { + if (result.isEmpty() && !searchWas) { + return Emoji.recentEmoji.size() + 1; + } + if (!result.isEmpty()) { + return result.size() + 1; + } + return 2; + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return holder.getItemViewType() == 0; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view; + switch (viewType) { + case 0: + view = new ImageViewEmoji(getContext()); + break; + case 1: + view = new View(getContext()); + view.setLayoutParams(new RecyclerView.LayoutParams(LayoutHelper.MATCH_PARENT, searchFieldHeight)); + break; + case 2: + default: + FrameLayout frameLayout = new FrameLayout(getContext()) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int parentHeight; + View parent = (View) EmojiView.this.getParent(); + if (parent != null) { + parentHeight = (int) (parent.getMeasuredHeight() - EmojiView.this.getY()); + } else { + parentHeight = AndroidUtilities.dp(120); + } + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(parentHeight - searchFieldHeight, MeasureSpec.EXACTLY)); + } + }; + + TextView textView = new TextView(getContext()); + textView.setText(LocaleController.getString("NoEmojiFound", R.string.NoEmojiFound)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + textView.setTextColor(Theme.getColor(Theme.key_chat_emojiPanelEmptyText)); + frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 10, 0, 0)); + + ImageView imageView = new ImageView(getContext()); + imageView.setScaleType(ImageView.ScaleType.CENTER); + imageView.setImageResource(R.drawable.smiles_panel_question); + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelEmptyText), PorterDuff.Mode.MULTIPLY)); + frameLayout.addView(imageView, LayoutHelper.createFrame(48, 48, Gravity.BOTTOM | Gravity.RIGHT)); + imageView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + boolean loadingUrl[] = new boolean[1]; + BottomSheet.Builder builder = new BottomSheet.Builder(getContext()); + + LinearLayout linearLayout = new LinearLayout(getContext()); + linearLayout.setOrientation(LinearLayout.VERTICAL); + linearLayout.setPadding(AndroidUtilities.dp(21), 0, AndroidUtilities.dp(21), 0); + + ImageView imageView1 = new ImageView(getContext()); + imageView1.setImageResource(R.drawable.smiles_info); + linearLayout.addView(imageView1, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 15, 0, 0)); + + TextView textView = new TextView(getContext()); + textView.setText(LocaleController.getString("EmojiSuggestions", R.string.EmojiSuggestions)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); + textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 24, 0, 0)); + + textView = new TextView(getContext()); + textView.setText(AndroidUtilities.replaceTags(LocaleController.getString("EmojiSuggestionsInfo", R.string.EmojiSuggestionsInfo))); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 11, 0, 0)); + + textView = new TextView(getContext()); + textView.setText(LocaleController.formatString("EmojiSuggestionsUrl", R.string.EmojiSuggestionsUrl, lastSearchAlias != null ? lastSearchAlias : lastSearchKeyboardLanguage)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + textView.setTextColor(Theme.getColor(Theme.key_dialogTextLink)); + textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 18, 0, 16)); + textView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (loadingUrl[0]) { + return; + } + loadingUrl[0] = true; + final AlertDialog progressDialog[] = new AlertDialog[]{new AlertDialog(getContext(), 3)}; + + TLRPC.TL_messages_getEmojiURL req = new TLRPC.TL_messages_getEmojiURL(); + req.lang_code = lastSearchAlias != null ? lastSearchAlias : lastSearchKeyboardLanguage[0]; + int requestId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + AndroidUtilities.runOnUIThread(() -> { + try { + progressDialog[0].dismiss(); + } catch (Throwable ignore) { + + } + progressDialog[0] = null; + + if (response instanceof TLRPC.TL_emojiURL) { + Browser.openUrl(getContext(), ((TLRPC.TL_emojiURL) response).url); + builder.getDismissRunnable().run(); + } + }); + } + ); + + AndroidUtilities.runOnUIThread(() -> { + if (progressDialog[0] == null) { + return; + } + progressDialog[0].setOnCancelListener(dialog -> ConnectionsManager.getInstance(currentAccount).cancelRequest(requestId, true)); + progressDialog[0].show(); + }, 1000); + } + }); + + builder.setCustomView(linearLayout); + builder.show(); + } + }); + + view = frameLayout; + view.setLayoutParams(new RecyclerView.LayoutParams(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + break; + } + return new RecyclerListView.Holder(view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + switch (holder.getItemViewType()) { + case 0: { + ImageViewEmoji imageView = (ImageViewEmoji) holder.itemView; + + String code; + String coloredCode; + boolean recent; + position--; + + if (result.isEmpty() && !searchWas) { + coloredCode = code = Emoji.recentEmoji.get(position); + recent = true; + } else { + coloredCode = code = result.get(position).emoji; + recent = false; + } + imageView.setImageDrawable(Emoji.getEmojiBigDrawable(coloredCode), recent); + imageView.setTag(code); + break; + } + } + } + + @Override + public int getItemViewType(int position) { + if (position == 0) { + return 1; + } else if (position == 1 && searchWas && result.isEmpty()) { + return 2; + } + return 0; + } + + public void search(String text) { + if (TextUtils.isEmpty(text)) { + lastSearchEmojiString = null; + if (emojiGridView.getAdapter() != emojiAdapter) { + emojiGridView.setAdapter(emojiAdapter); + searchWas = false; + } + notifyDataSetChanged(); + } else { + lastSearchEmojiString = text.toLowerCase(); + } + if (searchRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(searchRunnable); + } + if (!TextUtils.isEmpty(lastSearchEmojiString)) { + AndroidUtilities.runOnUIThread(searchRunnable = new Runnable() { + @Override + public void run() { + emojiSearchField.progressDrawable.startAnimation(); + String query = lastSearchEmojiString; + String[] newLanguage = AndroidUtilities.getCurrentKeyboardLanguage(); + if (!Arrays.equals(lastSearchKeyboardLanguage, newLanguage)) { + DataQuery.getInstance(currentAccount).fetchNewEmojiKeywords(newLanguage); + } + lastSearchKeyboardLanguage = newLanguage; + DataQuery.getInstance(currentAccount).getEmojiSuggestions(lastSearchKeyboardLanguage, lastSearchEmojiString, false, new DataQuery.KeywordResultCallback() { + @Override + public void run(ArrayList param, String alias) { + if (query.equals(lastSearchEmojiString)) { + lastSearchAlias = alias; + emojiSearchField.progressDrawable.stopAnimation(); + searchWas = true; + if (emojiGridView.getAdapter() != emojiSearchAdapter) { + emojiGridView.setAdapter(emojiSearchAdapter); + } + result = param; + notifyDataSetChanged(); + } + } + }); + } + }, 300); } } } @@ -2878,19 +4113,13 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private class EmojiPagesAdapter extends PagerAdapter implements PagerSlidingTabStrip.IconTabProvider { public void destroyItem(ViewGroup viewGroup, int position, Object object) { - View view; - if (position == 6) { - view = stickersWrap; - } else { - view = views.get(position); - } - viewGroup.removeView(view); + viewGroup.removeView(views.get(position)); } @Override public boolean canScrollToTab(int position) { - if (position == 6 && currentChatId != 0) { - showStickerBanHint(); + if ((position == 1 || position == 2) && currentChatId != 0) { + showStickerBanHint(position == 1); return false; } return true; @@ -2901,12 +4130,24 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } public Drawable getPageIconDrawable(int position) { - return icons[position]; + return tabIcons[position]; + } + + public CharSequence getPageTitle(int position) { + switch(position) { + case 0: + return LocaleController.getString("Emoji", R.string.Emoji); + case 1: + return LocaleController.getString("AccDescrGIFs", R.string.AccDescrGIFs); + case 2: + return LocaleController.getString("AccDescrStickers", R.string.AccDescrStickers); + } + return null; } @Override public void customOnDraw(Canvas canvas, int position) { - if (position == 6 && !DataQuery.getInstance(currentAccount).getUnreadStickerSets().isEmpty() && dotPaint != null) { + if (position == 2 && !DataQuery.getInstance(currentAccount).getUnreadStickerSets().isEmpty() && dotPaint != null) { int x = canvas.getWidth() / 2 + AndroidUtilities.dp(4 + 5); int y = canvas.getHeight() / 2 - AndroidUtilities.dp(13 - 5); canvas.drawCircle(x, y, AndroidUtilities.dp(5), dotPaint); @@ -2914,12 +4155,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } public Object instantiateItem(ViewGroup viewGroup, int position) { - View view; - if (position == 6) { - view = stickersWrap; - } else { - view = views.get(position); - } + View view = views.get(position); viewGroup.addView(view); return view; } @@ -2936,11 +4172,11 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } - private class GifsAdapter extends RecyclerListView.SelectionAdapter { + private class GifAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; - public GifsAdapter(Context context) { + public GifAdapter(Context context) { mContext = context; } @@ -2951,7 +4187,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific @Override public int getItemCount() { - return recentGifs.size(); + return recentGifs.size() + 1; } @Override @@ -2960,18 +4196,280 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { - ContextLinkCell view = new ContextLinkCell(mContext); + public int getItemViewType(int position) { + if (position == 0) { + return 1; + } + return 0; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view; + switch (viewType) { + case 0: + ContextLinkCell cell = new ContextLinkCell(mContext); + cell.setContentDescription(LocaleController.getString("AttachGif", R.string.AttachGif)); + cell.setCanPreviewGif(true); + view = cell; + break; + case 1: + default: + view = new View(getContext()); + view.setLayoutParams(new RecyclerView.LayoutParams(LayoutHelper.MATCH_PARENT, searchFieldHeight)); + break; + } return new RecyclerListView.Holder(view); } @Override - public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) { - TLRPC.Document document = recentGifs.get(i); - if (document != null) { - ((ContextLinkCell) viewHolder.itemView).setGif(document, false); + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + switch (holder.getItemViewType()) { + case 0: { + TLRPC.Document document = recentGifs.get(position - 1); + if (document != null) { + ((ContextLinkCell) holder.itemView).setGif(document, false); + } + break; + } } } + + @Override + public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { + if (holder.itemView instanceof ContextLinkCell) { + ContextLinkCell cell = (ContextLinkCell) holder.itemView; + ImageReceiver imageReceiver = cell.getPhotoImage(); + if (pager.getCurrentItem() == 1) { + imageReceiver.setAllowStartAnimation(true); + imageReceiver.startAnimation(); + } else { + imageReceiver.setAllowStartAnimation(false); + imageReceiver.stopAnimation(); + } + } + } + } + + private class GifSearchAdapter extends RecyclerListView.SelectionAdapter { + + private Context mContext; + private int reqId; + private String lastSearchImageString; + private String nextSearchOffset; + private boolean searchingUser; + private boolean searchEndReached; + private ArrayList results = new ArrayList<>(); + private HashMap resultsMap = new HashMap<>(); + private Runnable searchRunnable; + private TLRPC.User bot; + + public GifSearchAdapter(Context context) { + mContext = context; + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return false; + } + + @Override + public int getItemCount() { + return (results.isEmpty() ? 1 : results.size()) + 1; + } + + @Override + public int getItemViewType(int position) { + if (position == 0) { + return 1; + } else if (results.isEmpty()) { + return 2; + } + return 0; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view; + switch (viewType) { + case 0: + ContextLinkCell cell = new ContextLinkCell(mContext); + cell.setContentDescription(LocaleController.getString("AttachGif", R.string.AttachGif)); + cell.setCanPreviewGif(true); + view = cell; + break; + case 1: + view = new View(getContext()); + view.setLayoutParams(new RecyclerView.LayoutParams(LayoutHelper.MATCH_PARENT, searchFieldHeight)); + break; + case 2: + default: + FrameLayout frameLayout = new FrameLayout(getContext()) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int height = gifGridView.getMeasuredHeight(); + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec((int) ((height - searchFieldHeight - AndroidUtilities.dp(8)) / 3 * 1.7f), MeasureSpec.EXACTLY)); + } + }; + + ImageView imageView = new ImageView(getContext()); + imageView.setScaleType(ImageView.ScaleType.CENTER); + imageView.setImageResource(R.drawable.gif_empty); + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelEmptyText), PorterDuff.Mode.MULTIPLY)); + frameLayout.addView(imageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 0, 0, 59)); + + TextView textView = new TextView(getContext()); + textView.setText(LocaleController.getString("NoGIFsFound", R.string.NoGIFsFound)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + textView.setTextColor(Theme.getColor(Theme.key_chat_emojiPanelEmptyText)); + frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 0, 0, 9)); + + view = frameLayout; + view.setLayoutParams(new RecyclerView.LayoutParams(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + break; + } + return new RecyclerListView.Holder(view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + switch (holder.getItemViewType()) { + case 0: { + TLRPC.BotInlineResult result = results.get(position - 1); + + ContextLinkCell cell = (ContextLinkCell) holder.itemView; + cell.setLink(result, true, false, false); + break; + } + } + } + + public void search(String text) { + if (reqId != 0) { + ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true); + reqId = 0; + } + if (TextUtils.isEmpty(text)) { + lastSearchImageString = null; + if (gifGridView.getAdapter() != gifAdapter) { + gifGridView.setAdapter(gifAdapter); + } + notifyDataSetChanged(); + } else { + lastSearchImageString = text.toLowerCase(); + } + if (searchRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(searchRunnable); + } + if (!TextUtils.isEmpty(lastSearchImageString)) { + AndroidUtilities.runOnUIThread(searchRunnable = new Runnable() { + @Override + public void run() { + search(text, "", true); + } + }, 300); + } + } + + private void searchBotUser() { + if (searchingUser) { + return; + } + searchingUser = true; + TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); + req.username = MessagesController.getInstance(currentAccount).gifSearchBot; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + if (response != null) { + AndroidUtilities.runOnUIThread(() -> { + TLRPC.TL_contacts_resolvedPeer res = (TLRPC.TL_contacts_resolvedPeer) response; + MessagesController.getInstance(currentAccount).putUsers(res.users, false); + MessagesController.getInstance(currentAccount).putChats(res.chats, false); + MessagesStorage.getInstance(currentAccount).putUsersAndChats(res.users, res.chats, true, true); + String str = lastSearchImageString; + lastSearchImageString = null; + search(str, "", false); + }); + } + }); + } + + private void search(final String query, final String offset, boolean searchUser) { + if (reqId != 0) { + ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true); + reqId = 0; + } + + lastSearchImageString = query; + + TLObject object = MessagesController.getInstance(currentAccount).getUserOrChat(MessagesController.getInstance(currentAccount).gifSearchBot); + if (!(object instanceof TLRPC.User)) { + if (searchUser) { + searchBotUser(); + gifSearchField.progressDrawable.startAnimation(); + } + return; + } + if (TextUtils.isEmpty(offset)) { + gifSearchField.progressDrawable.startAnimation(); + } + + bot = (TLRPC.User) object; + + TLRPC.TL_messages_getInlineBotResults req = new TLRPC.TL_messages_getInlineBotResults(); + req.query = query == null ? "" : query; + req.bot = MessagesController.getInstance(currentAccount).getInputUser(bot); + req.offset = offset; + req.peer = new TLRPC.TL_inputPeerEmpty(); + + reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + AndroidUtilities.runOnUIThread(() -> { + if (req.query.equals(lastSearchImageString)) { + if (gifGridView.getAdapter() != gifSearchAdapter) { + gifGridView.setAdapter(gifSearchAdapter); + } + if (TextUtils.isEmpty(offset)) { + results.clear(); + resultsMap.clear(); + gifSearchField.progressDrawable.stopAnimation(); + } + + reqId = 0; + if (response instanceof TLRPC.messages_BotResults) { + int addedCount = 0; + int oldCount = results.size(); + TLRPC.messages_BotResults res = (TLRPC.messages_BotResults) response; + nextSearchOffset = res.next_offset; + for (int a = 0; a < res.results.size(); a++) { + TLRPC.BotInlineResult result = res.results.get(a); + if (resultsMap.containsKey(result.id)) { + continue; + } + result.query_id = res.query_id; + results.add(result); + resultsMap.put(result.id, result); + addedCount++; + } + searchEndReached = oldCount == results.size(); + if (addedCount != 0) { + if (oldCount != 0) { + notifyItemChanged(oldCount); + } + notifyItemRangeInserted(oldCount + 1, addedCount); + } else if (results.isEmpty()) { + notifyDataSetChanged(); + } + } else { + notifyDataSetChanged(); + } + } + }); + }, ConnectionsManager.RequestFlagFailOnServerErrors); + } + + @Override + public void notifyDataSetChanged() { + super.notifyDataSetChanged(); + } } private class StickersSearchGridAdapter extends RecyclerListView.SelectionAdapter { @@ -2981,6 +4479,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private SparseArray cache = new SparseArray<>(); private SparseArray cacheParent = new SparseArray<>(); private SparseIntArray positionToRow = new SparseIntArray(); + private SparseArray positionToEmoji = new SparseArray<>(); private int totalItems; private ArrayList serverPacks = new ArrayList<>(); @@ -2994,6 +4493,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private int reqId; private int reqId2; + private int emojiSearchId; boolean cleared; private String searchQuery; private Runnable searchRunnable = new Runnable() { @@ -3016,8 +4516,9 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (TextUtils.isEmpty(searchQuery)) { return; } - progressDrawable.startAnimation(); + stickersSearchField.progressDrawable.startAnimation(); cleared = false; + int lastId = ++emojiSearchId; final ArrayList emojiStickersArray = new ArrayList<>(0); final LongSparseArray emojiStickersMap = new LongSparseArray<>(0); @@ -3049,21 +4550,35 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } if (allStickers != null && !allStickers.isEmpty() && searchQuery.length() > 1) { - Object[] suggestions = Emoji.getSuggestion(searchQuery.startsWith(":") ? searchQuery : ":" + searchQuery); - if (suggestions != null) { - for (int a = 0, size = Math.min(10, suggestions.length); a < size; a++) { - EmojiSuggestion suggestion = (EmojiSuggestion) suggestions[a]; - suggestion.emoji = suggestion.emoji.replace("\ufe0f", ""); - ArrayList newStickers = allStickers != null ? allStickers.get(suggestion.emoji) : null; - if (newStickers != null && !newStickers.isEmpty()) { - clear(); - if (!emojiStickers.containsKey(newStickers)) { - emojiStickers.put(newStickers, suggestion.emoji); - emojiArrays.add(newStickers); + String[] newLanguage = AndroidUtilities.getCurrentKeyboardLanguage(); + if (!Arrays.equals(lastSearchKeyboardLanguage, newLanguage)) { + DataQuery.getInstance(currentAccount).fetchNewEmojiKeywords(newLanguage); + } + lastSearchKeyboardLanguage = newLanguage; + DataQuery.getInstance(currentAccount).getEmojiSuggestions(lastSearchKeyboardLanguage, searchQuery, false, new DataQuery.KeywordResultCallback() { + @Override + public void run(ArrayList param, String alias) { + if (lastId != emojiSearchId) { + return; + } + boolean added = false; + for (int a = 0, size = param.size(); a < size; a++) { + String emoji = param.get(a).emoji; + ArrayList newStickers = allStickers != null ? allStickers.get(emoji) : null; + if (newStickers != null && !newStickers.isEmpty()) { + clear(); + if (!emojiStickers.containsKey(newStickers)) { + emojiStickers.put(newStickers, emoji); + emojiArrays.add(newStickers); + added = true; + } } } + if (added) { + notifyDataSetChanged(); + } } - } + }); } ArrayList local = DataQuery.getInstance(currentAccount).getStickerSets(DataQuery.TYPE_IMAGE); int index; @@ -3110,7 +4625,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific AndroidUtilities.runOnUIThread(() -> { if (req.q.equals(searchQuery)) { clear(); - progressDrawable.stopAnimation(); + stickersSearchField.progressDrawable.stopAnimation(); reqId = 0; if (stickersGridView.getAdapter() != stickersSearchGridAdapter) { stickersGridView.setAdapter(stickersSearchGridAdapter); @@ -3238,7 +4753,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific view = new EmptyCell(context); break; case 2: - view = new StickerSetNameCell(context); + view = new StickerSetNameCell(context, false); break; case 3: view = new FeaturedStickerSetInfoCell(context, 17); @@ -3250,10 +4765,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } if (parent1.isInstalled()) { removingStickerSets.put(pack.set.id, pack); - listener.onStickerSetRemove(parent1.getStickerSet()); + delegate.onStickerSetRemove(parent1.getStickerSet()); } else { installingStickerSets.put(pack.set.id, pack); - listener.onStickerSetAdd(parent1.getStickerSet()); + delegate.onStickerSetAdd(parent1.getStickerSet()); } parent1.setDrawProgress(true); }); @@ -3273,16 +4788,15 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific ImageView imageView = new ImageView(context); imageView.setScaleType(ImageView.ScaleType.CENTER); - imageView.setImageResource(R.drawable.stickers_none); + imageView.setImageResource(R.drawable.stickers_empty); imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelEmptyText), PorterDuff.Mode.MULTIPLY)); - frameLayout.addView(imageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 0, 0, 48)); + frameLayout.addView(imageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 0, 0, 59)); TextView textView = new TextView(context); textView.setText(LocaleController.getString("NoStickersFound", R.string.NoStickersFound)); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); textView.setTextColor(Theme.getColor(Theme.key_chat_emojiPanelEmptyText)); - textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 30, 0, 0)); + frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 0, 0, 9)); view = frameLayout; view.setLayoutParams(new RecyclerView.LayoutParams(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); @@ -3299,7 +4813,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific case 0: { TLRPC.Document sticker = (TLRPC.Document) cache.get(position); StickerEmojiCell cell = (StickerEmojiCell) holder.itemView; - cell.setSticker(sticker, cacheParent.get(position), false); + cell.setSticker(sticker, cacheParent.get(position), positionToEmoji.get(position), false); cell.setRecent(recentStickers.contains(sticker) || favouriteStickers.contains(sticker)); break; } @@ -3310,22 +4824,22 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (row == Integer.MIN_VALUE) { cell.setHeight(1); } else { - ArrayList documents; Object pack = rowStartPack.get(row); + Integer count; if (pack instanceof TLRPC.TL_messages_stickerSet) { - documents = ((TLRPC.TL_messages_stickerSet) pack).documents; - } else if (pack instanceof ArrayList) { - documents = (ArrayList) pack; + count = ((TLRPC.TL_messages_stickerSet) pack).documents.size(); + } else if (pack instanceof Integer) { + count = (Integer) pack; } else { - documents = null; + count = null; } - if (documents == null) { + if (count == null) { cell.setHeight(1); } else { - if (documents.isEmpty()) { + if (count == 0) { cell.setHeight(AndroidUtilities.dp(8)); } else { - int height = pager.getHeight() - (int) Math.ceil(documents.size() / (float) stickersGridAdapter.stickersPerRow) * AndroidUtilities.dp(82); + int height = pager.getHeight() - (int) Math.ceil(count / (float) stickersGridAdapter.stickersPerRow) * AndroidUtilities.dp(82); cell.setHeight(height > 0 ? height : 1); } } @@ -3352,9 +4866,6 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } cell.setUrl(null, 0); } - } else if (object instanceof ArrayList) { - cell.setText(emojiStickers.get(object), 0); - cell.setUrl(null, 0); } break; } @@ -3393,9 +4904,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific positionToRow.clear(); cache.clear(); positionsToSets.clear(); + positionToEmoji.clear(); totalItems = 0; int startRow = 0; - for (int a = -1, serverSize = serverPacks.size(), localSize = localPacks.size(), emojiSize = emojiArrays.size(); a < serverSize + localSize + emojiSize; a++) { + for (int a = -1, serverCount = serverPacks.size(), localCount = localPacks.size(), emojiCount = (emojiArrays.isEmpty() ? 0 : 1); a < serverCount + localCount + emojiCount; a++) { ArrayList documents; Object pack = null; String key; @@ -3405,16 +4917,48 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific continue; } else { int idx = a; - if (idx < localSize) { + if (idx < localCount) { TLRPC.TL_messages_stickerSet set = localPacks.get(idx); documents = set.documents; pack = set; } else { - idx -= localSize; - if (idx < emojiSize) { - documents = emojiArrays.get(idx); + idx -= localCount; + if (idx < emojiCount) { + int documentsCount = 0; + String lastEmoji = ""; + for (int i = 0, N = emojiArrays.size(); i < N; i++) { + documents = emojiArrays.get(i); + String emoji = emojiStickers.get(documents); + if (emoji != null && !lastEmoji.equals(emoji)) { + lastEmoji = emoji; + positionToEmoji.put(totalItems + documentsCount, lastEmoji); + } + for (int b = 0, size = documents.size(); b < size; b++) { + int num = documentsCount + totalItems; + int row = startRow + documentsCount / stickersGridAdapter.stickersPerRow; + + TLRPC.Document document = documents.get(b); + cache.put(num, document); + Object parent = DataQuery.getInstance(currentAccount).getStickerSetById(DataQuery.getStickerSetId(document)); + if (parent != null) { + cacheParent.put(num, parent); + } + positionToRow.put(num, row); + if (a >= localCount && pack instanceof TLRPC.StickerSetCovered) { + positionsToSets.put(num, (TLRPC.StickerSetCovered) pack); + } + documentsCount++; + } + } + int count = (int) Math.ceil(documentsCount / (float) stickersGridAdapter.stickersPerRow); + for (int b = 0, N = count; b < N; b++) { + rowStartPack.put(startRow + b, documentsCount); + } + totalItems += count * stickersGridAdapter.stickersPerRow; + startRow += count; + continue; } else { - idx -= emojiSize; + idx -= emojiCount; TLRPC.StickerSetCovered set = serverPacks.get(idx); documents = set.covers; pack = set; @@ -3425,34 +4969,28 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific continue; } int count = (int) Math.ceil(documents.size() / (float) stickersGridAdapter.stickersPerRow); - if (pack != null) { - cache.put(totalItems, pack); - } else { - cache.put(totalItems, documents); - } - if (a >= localSize && pack instanceof TLRPC.StickerSetCovered) { + cache.put(totalItems, pack); + if (a >= localCount && pack instanceof TLRPC.StickerSetCovered) { positionsToSets.put(totalItems, (TLRPC.StickerSetCovered) pack); } positionToRow.put(totalItems, startRow); for (int b = 0, size = documents.size(); b < size; b++) { int num = 1 + b + totalItems; - cache.put(num, documents.get(b)); + int row = startRow + 1 + b / stickersGridAdapter.stickersPerRow; + TLRPC.Document document = documents.get(b); + cache.put(num, document); if (pack != null) { cacheParent.put(num, pack); } - positionToRow.put(1 + b + totalItems, startRow + 1 + b / stickersGridAdapter.stickersPerRow); - if (a >= localSize && pack instanceof TLRPC.StickerSetCovered) { - positionsToSets.put(1 + b + totalItems, (TLRPC.StickerSetCovered) pack); + positionToRow.put(num, row); + if (a >= localCount && pack instanceof TLRPC.StickerSetCovered) { + positionsToSets.put(num, (TLRPC.StickerSetCovered) pack); } } - for (int b = 0; b < count + 1; b++) { - if (pack != null) { - rowStartPack.put(startRow + b, pack); - } else { - rowStartPack.put(startRow + b, documents); - } + for (int b = 0, N = count + 1; b < N; b++) { + rowStartPack.put(startRow + b, pack); } - totalItems += count * stickersGridAdapter.stickersPerRow + 1; + totalItems += 1 + count * stickersGridAdapter.stickersPerRow; startRow += count + 1; } super.notifyDataSetChanged(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java index 91c43777a..adf4cc8f6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java @@ -9,6 +9,9 @@ package org.telegram.ui.Components; import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.Drawable; import android.util.TypedValue; import android.view.Gravity; import android.view.View; @@ -68,6 +71,19 @@ public class EmptyTextProgressView extends FrameLayout { progressBar.setProgressColor(color); } + public void setTopImage(int resId) { + if (resId == 0) { + textView.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null); + } else { + Drawable drawable = getContext().getResources().getDrawable(resId).mutate(); + if (drawable != null) { + drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_emptyListPlaceholder), PorterDuff.Mode.MULTIPLY)); + } + textView.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null); + textView.setCompoundDrawablePadding(AndroidUtilities.dp(1)); + } + } + public void setTextSize(int size) { textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, size); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ExtendedGridLayoutManager.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ExtendedGridLayoutManager.java index 9681a088c..5d20d3eeb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ExtendedGridLayoutManager.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ExtendedGridLayoutManager.java @@ -12,7 +12,8 @@ import android.content.Context; import android.util.SparseIntArray; import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.support.widget.GridLayoutManager; + +import androidx.recyclerview.widget.GridLayoutManager; public class ExtendedGridLayoutManager extends GridLayoutManager { 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 d4e8fbb77..922ba114b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java @@ -18,7 +18,7 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Typeface; import android.os.Bundle; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; @@ -131,6 +131,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent playbackSpeedButton = new ImageView(context); playbackSpeedButton.setScaleType(ImageView.ScaleType.CENTER); playbackSpeedButton.setImageResource(R.drawable.voice2x); + playbackSpeedButton.setContentDescription(LocaleController.getString("AccDescrPlayerSpeed", R.string.AccDescrPlayerSpeed)); if (AndroidUtilities.density >= 3.0f) { playbackSpeedButton.setPadding(0, 1, 0, 0); } @@ -345,9 +346,11 @@ public class FragmentContextView extends FrameLayout implements NotificationCent if (playbackSpeedButton != null) { playbackSpeedButton.setVisibility(VISIBLE); } + closeButton.setContentDescription(LocaleController.getString("AccDescrClosePlayer", R.string.AccDescrClosePlayer)); } else if (style == 2) { playButton.setLayoutParams(LayoutHelper.createFrame(36, 36, Gravity.TOP | Gravity.LEFT, 8, 0, 0, 0)); titleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 35 + 16, 0, 36, 0)); + closeButton.setContentDescription(LocaleController.getString("AccDescrStopLiveLocation", R.string.AccDescrStopLiveLocation)); } } else if (style == 1) { titleTextView.setText(LocaleController.getString("ReturnToCall", R.string.ReturnToCall)); @@ -708,8 +711,10 @@ public class FragmentContextView extends FrameLayout implements NotificationCent } if (MediaController.getInstance().isMessagePaused()) { playButton.setImageResource(R.drawable.miniplayer_play); + playButton.setContentDescription(LocaleController.getString("AccActionPlay", R.string.AccActionPlay)); } else { playButton.setImageResource(R.drawable.miniplayer_pause); + playButton.setContentDescription(LocaleController.getString("AccActionPause", R.string.AccActionPause)); } if (lastMessageObject != messageObject || prevStyle != 0) { lastMessageObject = messageObject; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateCheckBox.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateCheckBox.java index 4b990eab5..edf157caf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateCheckBox.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateCheckBox.java @@ -15,7 +15,7 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.view.View; import org.telegram.messenger.AndroidUtilities; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateDividerItemDecoration.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateDividerItemDecoration.java index fd4954dab..df58d462d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateDividerItemDecoration.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateDividerItemDecoration.java @@ -13,9 +13,10 @@ import android.view.View; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.ui.ActionBar.Theme; +import androidx.recyclerview.widget.RecyclerView; + public class GroupCreateDividerItemDecoration extends RecyclerView.ItemDecoration { private boolean searching; 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 71e3a6dbe..584ce9e15 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java @@ -16,15 +16,19 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.RectF; import android.graphics.drawable.Drawable; +import android.os.Build; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; import org.telegram.messenger.UserObject; import org.telegram.tgnet.TLRPC; @@ -102,12 +106,7 @@ public class GroupCreateSpan extends View { textWidth = (int) Math.ceil(nameLayout.getLineWidth(0)); textX = -nameLayout.getLineLeft(0); } - - TLRPC.FileLocation photo = null; - if (user != null && user.photo != null) { - photo = user.photo.photo_small; - } - imageReceiver.setImage(photo, "50_50", avatarDrawable, null, null, 0, null, user, 1); + imageReceiver.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, 0, null, user, 1); updateColors(); } @@ -212,4 +211,12 @@ public class GroupCreateSpan extends View { nameLayout.draw(canvas); canvas.restore(); } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setText(nameLayout.getText()); + if (isDeleting() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) + info.addAction(new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.getId(), LocaleController.getString("Delete", R.string.Delete))); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java index 069854dd9..2f5ed96f7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java @@ -10,9 +10,9 @@ import android.widget.Scroller; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.MessageObject; -import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import java.util.ArrayList; @@ -22,7 +22,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes private Paint backgroundPaint = new Paint(); private ArrayList unusedReceivers = new ArrayList<>(); private ArrayList imagesToDraw = new ArrayList<>(); - public ArrayList currentPhotos = new ArrayList<>(); + public ArrayList currentPhotos = new ArrayList<>(); private ArrayList currentObjects = new ArrayList<>(); private int currentImage; private long currentGroupId; @@ -55,7 +55,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes int getCurrentAccount(); int getAvatarsDialogId(); int getSlideshowMessageId(); - ArrayList getImagesArrLocations(); + ArrayList getImagesArrLocations(); ArrayList getImagesArr(); ArrayList getPageBlockArr(); Object getParentObject(); @@ -86,16 +86,17 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes } int currentIndex = delegate.getCurrentIndex(); - ArrayList imagesArrLocations = delegate.getImagesArrLocations(); + ArrayList imagesArrLocations = delegate.getImagesArrLocations(); ArrayList imagesArr = delegate.getImagesArr(); ArrayList pageBlockArr = delegate.getPageBlockArr(); int slideshowMessageId = delegate.getSlideshowMessageId(); + int currentAccount = delegate.getCurrentAccount(); boolean changed = false; int newCount = 0; Object currentObject = null; if (imagesArrLocations != null && !imagesArrLocations.isEmpty()) { - TLRPC.FileLocation location = imagesArrLocations.get(currentIndex); + ImageLocation location = imagesArrLocations.get(currentIndex); newCount = imagesArrLocations.size(); currentObject = location; } else if (imagesArr != null && !imagesArr.isEmpty()) { @@ -190,7 +191,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes MessageObject object = imagesArr.get(a); if (slideshowMessageId != 0 || object.getGroupIdForUse() == currentGroupId) { currentObjects.add(object); - currentPhotos.add(FileLoader.getClosestPhotoSizeWithSize(object.photoThumbs, 56, true)); + currentPhotos.add(ImageLocation.getForObject(FileLoader.getClosestPhotoSizeWithSize(object.photoThumbs, 56, true), object.photoThumbsObject)); } else { break; } @@ -202,7 +203,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes MessageObject object = imagesArr.get(a); if (slideshowMessageId != 0 || object.getGroupIdForUse() == currentGroupId) { currentObjects.add(0, object); - currentPhotos.add(0, FileLoader.getClosestPhotoSizeWithSize(object.photoThumbs, 56, true)); + currentPhotos.add(0, ImageLocation.getForObject(FileLoader.getClosestPhotoSizeWithSize(object.photoThumbs, 56, true), object.photoThumbsObject)); currentImage++; } else { break; @@ -215,7 +216,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes TLRPC.PageBlock object = pageBlockArr.get(a); if (object.groupId == currentGroupId) { currentObjects.add(object); - currentPhotos.add(object.thumb); + currentPhotos.add(ImageLocation.getForObject(object.thumb, object.thumbObject)); } else { break; } @@ -226,7 +227,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes TLRPC.PageBlock object = pageBlockArr.get(a); if (object.groupId == currentGroupId) { currentObjects.add(0, object); - currentPhotos.add(0, object.thumb); + currentPhotos.add(0, ImageLocation.getForObject(object.thumb, object.thumbObject)); currentImage++; } else { break; @@ -324,7 +325,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes for (int a = addRightIndex; a < count; a++) { int x = startX + (a - currentImage) * (itemWidth + itemSpacing) + dx; if (x < width) { - TLObject location = currentPhotos.get(a); + ImageLocation location = currentPhotos.get(a); ImageReceiver receiver = getFreeReceiver(); receiver.setImageCoords(x, itemY, itemWidth, itemHeight); Object parent; @@ -335,7 +336,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes } else { parent = "avatar_" + delegate.getAvatarsDialogId(); } - receiver.setImage(null, null, null, location, "80_80", 0, null, parent, 1); + receiver.setImage(null, null, location, "80_80", 0, null, parent, 1); receiver.setParam(a); } else { break; @@ -346,7 +347,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes for (int a = addLeftIndex; a >= 0; a--) { int x = startX + (a - currentImage) * (itemWidth + itemSpacing) + dx + itemWidth; if (x > 0) { - TLObject location = currentPhotos.get(a); + ImageLocation location = currentPhotos.get(a); ImageReceiver receiver = getFreeReceiver(); receiver.setImageCoords(x, itemY, itemWidth, itemHeight); Object parent; @@ -357,7 +358,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes } else { parent = "avatar_" + delegate.getAvatarsDialogId(); } - receiver.setImage(null, null, null, location, "80_80", 0, null, parent, 1); + receiver.setImage(null, null, location, "80_80", 0, null, parent, 1); receiver.setParam(a); } else { break; @@ -383,7 +384,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes @Override public boolean onSingleTapUp(MotionEvent e) { int currentIndex = delegate.getCurrentIndex(); - ArrayList imagesArrLocations = delegate.getImagesArrLocations(); + ArrayList imagesArrLocations = delegate.getImagesArrLocations(); ArrayList imagesArr = delegate.getImagesArr(); ArrayList pageBlockArr = delegate.getPageBlockArr(); @@ -415,7 +416,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes animateAllLine = true; delegate.setCurrentIndex(idx); } else if (imagesArrLocations != null && !imagesArrLocations.isEmpty()) { - TLRPC.FileLocation location = (TLRPC.FileLocation) currentObjects.get(num); + ImageLocation location = (ImageLocation) currentObjects.get(num); int idx = imagesArrLocations.indexOf(location); if (currentIndex == idx) { return true; @@ -446,7 +447,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes nextPhotoScrolling = currentImage - indexChange; int currentIndex = delegate.getCurrentIndex(); - ArrayList imagesArrLocations = delegate.getImagesArrLocations(); + ArrayList imagesArrLocations = delegate.getImagesArrLocations(); ArrayList imagesArr = delegate.getImagesArr(); ArrayList pageBlockArr = delegate.getPageBlockArr(); @@ -460,7 +461,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes TLRPC.PageBlock pageBlock = (TLRPC.PageBlock) photo; nextPhoto = pageBlockArr.indexOf(pageBlock); } else if (imagesArrLocations != null && !imagesArrLocations.isEmpty()) { - TLRPC.FileLocation location = (TLRPC.FileLocation) photo; + ImageLocation location = (ImageLocation) photo; nextPhoto = imagesArrLocations.indexOf(location); } if (nextPhoto >= 0) { @@ -559,12 +560,11 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes int maxItemWidth = (int) (itemWidth * 2.0f); int padding = AndroidUtilities.dp(8); - TLObject object = currentPhotos.get(currentImage); + ImageLocation object = currentPhotos.get(currentImage); int trueWidth; int currentPaddings; - if (object instanceof TLRPC.PhotoSize) { - TLRPC.PhotoSize photoSize = (TLRPC.PhotoSize) object; - trueWidth = Math.max(itemWidth, (int) (photoSize.w * (itemHeight / (float) photoSize.h))); + if (object != null && object.photoSize != null) { + trueWidth = Math.max(itemWidth, (int) (object.photoSize.w * (itemHeight / (float) object.photoSize.h))); } else { trueWidth = itemHeight; } @@ -576,9 +576,8 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes int nextPaddings; if (nextImage >= 0 && nextImage < currentPhotos.size()) { object = currentPhotos.get(nextImage); - if (object instanceof TLRPC.PhotoSize) { - TLRPC.PhotoSize photoSize = (TLRPC.PhotoSize) object; - nextTrueWidth = Math.max(itemWidth, (int) (photoSize.w * (itemHeight / (float) photoSize.h))); + if (object != null && object.photoSize != null) { + nextTrueWidth = Math.max(itemWidth, (int) (object.photoSize.w * (itemHeight / (float) object.photoSize.h))); } else { nextTrueWidth = itemHeight; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/HintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/HintView.java new file mode 100644 index 000000000..53c486885 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/HintView.java @@ -0,0 +1,221 @@ +package org.telegram.ui.Components; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.ChatMessageCell; + + +@SuppressWarnings("FieldCanBeLocal") +public class HintView extends FrameLayout { + + private TextView textView; + private ImageView imageView; + private ImageView arrowImageView; + private ChatMessageCell messageCell; + private AnimatorSet animatorSet; + private Runnable hideRunnable; + private int currentType; + private boolean isTopArrow; + private String overrideText; + + public HintView(Context context, int type) { + this(context, type, false); + } + + public HintView(Context context, int type, boolean topArrow) { + super(context); + + currentType = type; + isTopArrow = topArrow; + + textView = new CorrectlyMeasuringTextView(context); + textView.setTextColor(Theme.getColor(Theme.key_chat_gifSaveHintText)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setMaxLines(2); + textView.setMaxWidth(AndroidUtilities.dp(250)); + textView.setGravity(Gravity.LEFT | Gravity.TOP); + textView.setBackgroundDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(3), Theme.getColor(Theme.key_chat_gifSaveHintBackground))); + textView.setPadding(AndroidUtilities.dp(currentType == 0 ? 54 : 5), AndroidUtilities.dp(6), AndroidUtilities.dp(5), AndroidUtilities.dp(7)); + addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, topArrow ? 6 : 0, 0, topArrow ? 0 : 6)); + + if (type == 0) { + textView.setText(LocaleController.getString("AutoplayVideoInfo", R.string.AutoplayVideoInfo)); + + imageView = new ImageView(context); + imageView.setImageResource(R.drawable.tooltip_sound); + imageView.setScaleType(ImageView.ScaleType.CENTER); + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_gifSaveHintText), PorterDuff.Mode.MULTIPLY)); + addView(imageView, LayoutHelper.createFrame(38, 34, Gravity.LEFT | Gravity.TOP, 7, 7, 0, 0)); + } + + arrowImageView = new ImageView(context); + arrowImageView.setImageResource(topArrow ? R.drawable.tooltip_arrow_up : R.drawable.tooltip_arrow); + arrowImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_gifSaveHintBackground), PorterDuff.Mode.MULTIPLY)); + addView(arrowImageView, LayoutHelper.createFrame(14, 6, Gravity.LEFT | (topArrow ? Gravity.TOP : Gravity.BOTTOM), 0, 0, 0, 0)); + } + + public void setOverrideText(String text) { + overrideText = text; + textView.setText(text); + if (messageCell != null) { + ChatMessageCell cell = messageCell; + messageCell = null; + showForMessageCell(cell, false); + } + } + + public boolean showForMessageCell(ChatMessageCell cell, boolean animated) { + if (currentType == 0 && getTag() != null || messageCell == cell) { + return false; + } + if (hideRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(hideRunnable); + hideRunnable = null; + } + int top = cell.getTop(); + int centerX; + View parentView = (View) cell.getParent(); + if (currentType == 0) { + ImageReceiver imageReceiver = cell.getPhotoImage(); + top += imageReceiver.getImageY(); + int height = imageReceiver.getImageHeight(); + int bottom = top + height; + int parentHeight = parentView.getMeasuredHeight(); + if (top <= getMeasuredHeight() + AndroidUtilities.dp(10) || bottom > parentHeight + height / 4) { + return false; + } + centerX = cell.getNoSoundIconCenterX(); + } else { + MessageObject messageObject = cell.getMessageObject(); + if (overrideText == null) { + textView.setText(LocaleController.getString("HidAccount", R.string.HidAccount)); + } else { + textView.setText(overrideText); + } + measure(MeasureSpec.makeMeasureSpec(1000, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(1000, MeasureSpec.AT_MOST)); + + top += AndroidUtilities.dp(22); + if (!messageObject.isOutOwner() && cell.isDrawNameLayout()) { + top += AndroidUtilities.dp(20); + } + if (!isTopArrow && top <= getMeasuredHeight() + AndroidUtilities.dp(10)) { + return false; + } + centerX = cell.getForwardNameCenterX(); + } + + int parentWidth = parentView.getMeasuredWidth(); + if (isTopArrow) { + setTranslationY(AndroidUtilities.dp(44)); + } else { + setTranslationY(top - getMeasuredHeight()); + } + int iconX = cell.getLeft() + centerX; + int left = AndroidUtilities.dp(19); + if (iconX > parentView.getMeasuredWidth() / 2) { + int offset = parentWidth - getMeasuredWidth() - AndroidUtilities.dp(38); + setTranslationX(offset); + left += offset; + } else { + setTranslationX(0); + } + float arrowX = cell.getLeft() + centerX - left - arrowImageView.getMeasuredWidth() / 2; + arrowImageView.setTranslationX(arrowX); + if (iconX > parentView.getMeasuredWidth() / 2) { + if (arrowX < AndroidUtilities.dp(10)) { + float diff = arrowX - AndroidUtilities.dp(10); + setTranslationX(getTranslationX() + diff); + arrowImageView.setTranslationX(arrowX - diff); + } + } else { + if (arrowX > getMeasuredWidth() - AndroidUtilities.dp(14 + 10)) { + float diff = arrowX - getMeasuredWidth() + AndroidUtilities.dp(14 + 10); + setTranslationX(diff); + arrowImageView.setTranslationX(arrowX - diff); + } else if (arrowX < AndroidUtilities.dp(10)) { + float diff = arrowX - AndroidUtilities.dp(10); + setTranslationX(getTranslationX() + diff); + arrowImageView.setTranslationX(arrowX - diff); + } + } + + messageCell = cell; + if (animatorSet != null) { + animatorSet.cancel(); + animatorSet = null; + } + + setTag(1); + setVisibility(VISIBLE); + if (animated) { + animatorSet = new AnimatorSet(); + animatorSet.playTogether( + ObjectAnimator.ofFloat(this, "alpha", 0.0f, 1.0f) + ); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + animatorSet = null; + AndroidUtilities.runOnUIThread(hideRunnable = () -> hide(), currentType == 0 ? 10000 : 2000); + } + }); + animatorSet.setDuration(300); + animatorSet.start(); + } else { + setAlpha(1.0f); + } + + return true; + } + + public void hide() { + if (getTag() == null) { + return; + } + setTag(null); + if (hideRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(hideRunnable); + hideRunnable = null; + } + if (animatorSet != null) { + animatorSet.cancel(); + animatorSet = null; + } + animatorSet = new AnimatorSet(); + animatorSet.playTogether( + ObjectAnimator.ofFloat(this, "alpha", 0.0f) + ); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + setVisibility(View.INVISIBLE); + messageCell = null; + animatorSet = null; + } + }); + animatorSet.setDuration(300); + animatorSet.start(); + } + + public ChatMessageCell getMessageCell() { + return messageCell; + } +} 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 c5c7fccc7..62e708105 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java @@ -16,18 +16,19 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; -import android.support.media.ExifInterface; +import androidx.exifinterface.media.ExifInterface; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.MediaStore; -import android.support.v4.content.FileProvider; +import androidx.core.content.FileProvider; import android.util.TypedValue; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BuildConfig; import org.telegram.messenger.ImageLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; @@ -135,9 +136,11 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega BottomSheet sheet = builder.create(); parentFragment.showDialog(sheet); TextView titleView = sheet.getTitleView(); - titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - titleView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + if (titleView != null) { + titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + titleView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + } sheet.setItemColor(searchAvailable ? 3 : 2, Theme.getColor(Theme.key_dialogTextRed2), Theme.getColor(Theme.key_dialogRedIcon)); } @@ -225,7 +228,7 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega NotificationCenter.getInstance(currentAccount).addObserver(ImageUpdater.this, NotificationCenter.fileDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(ImageUpdater.this, NotificationCenter.fileDidFailedLoad); uploadingImage = FileLoader.getAttachFileName(photoSize.location); - imageReceiver.setImage(photoSize, null, null, "jpg", null, 1); + imageReceiver.setImage(ImageLocation.getForPhoto(photoSize, info.searchImage.photo), null, null, "jpg", null, 1); } } } else if (info.searchImage.imageUrl != null) { @@ -426,7 +429,7 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.FileDidUpload) { String location = (String) args[0]; - if (uploadingImage != null && location.equals(uploadingImage)) { + if (location.equals(uploadingImage)) { NotificationCenter.getInstance(currentAccount).removeObserver(ImageUpdater.this, NotificationCenter.FileDidUpload); NotificationCenter.getInstance(currentAccount).removeObserver(ImageUpdater.this, NotificationCenter.FileDidFailUpload); if (delegate != null) { @@ -441,7 +444,7 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega } } else if (id == NotificationCenter.FileDidFailUpload) { String location = (String) args[0]; - if (uploadingImage != null && location.equals(uploadingImage)) { + if (location.equals(uploadingImage)) { NotificationCenter.getInstance(currentAccount).removeObserver(ImageUpdater.this, NotificationCenter.FileDidUpload); NotificationCenter.getInstance(currentAccount).removeObserver(ImageUpdater.this, NotificationCenter.FileDidFailUpload); uploadingImage = null; @@ -453,7 +456,7 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega } } else if (id == NotificationCenter.fileDidLoad || id == NotificationCenter.fileDidFailedLoad || id == NotificationCenter.httpFileDidLoad || id == NotificationCenter.httpFileDidFailedLoad) { String path = (String) args[0]; - if (uploadingImage != null && path.equals(uploadingImage)) { + 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.httpFileDidLoad); 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 05f391335..9b8e8bf00 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java @@ -43,7 +43,7 @@ import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; @@ -64,6 +64,7 @@ import org.telegram.messenger.BuildVars; import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; @@ -316,6 +317,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter switchCameraButton = new ImageView(context); switchCameraButton.setScaleType(ImageView.ScaleType.CENTER); + switchCameraButton.setContentDescription(LocaleController.getString("AccDescrSwitchCamera", R.string.AccDescrSwitchCamera)); addView(switchCameraButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.BOTTOM, 20, 0, 0, 14)); switchCameraButton.setOnClickListener(v -> { if (!cameraReady || cameraSession == null || !cameraSession.isInitied() || cameraThread == null) { @@ -1941,7 +1943,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter for (int a = 0; a < 3; a++) { buffers.add(new AudioBufferInfo()); } - audioRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); + audioRecorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, 44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); audioRecorder.startRecording(); if (BuildVars.LOGS_ENABLED) { FileLog.d("initied audio record with channels " + audioRecorder.getChannelCount() + " sample rate = " + audioRecorder.getSampleRate() + " bufferSize = " + bufferSize); 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 5ed6b6b42..9aca0a8a8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java @@ -19,14 +19,12 @@ import android.widget.LinearLayout; 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.MessagesController; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; -import org.telegram.tgnet.RequestDelegate; -import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; @@ -34,6 +32,9 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.JoinSheetUserCell; import org.telegram.ui.ChatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class JoinGroupAlert extends BottomSheet { private TLRPC.ChatInvite chatInvite; @@ -41,7 +42,7 @@ public class JoinGroupAlert extends BottomSheet { private BaseFragment fragment; public JoinGroupAlert(final Context context, TLRPC.ChatInvite invite, String group, BaseFragment parentFragment) { - super(context, false); + super(context, false, 0); setApplyBottomPadding(false); setApplyTopPadding(false); @@ -56,31 +57,26 @@ public class JoinGroupAlert extends BottomSheet { String title; AvatarDrawable avatarDrawable; - TLRPC.FileLocation photo = null; int participants_count; - if (invite.chat != null) { - avatarDrawable = new AvatarDrawable(invite.chat); - if (chatInvite.chat.photo != null) { - photo = chatInvite.chat.photo.photo_small; - } - title = invite.chat.title; - participants_count = invite.chat.participants_count; - } else { - avatarDrawable = new AvatarDrawable(); - avatarDrawable.setInfo(0, invite.title, null, false); - if (chatInvite.photo != null) { - photo = chatInvite.photo.photo_small; - } - title = invite.title; - participants_count = invite.participants_count; - } - BackupImageView avatarImageView = new BackupImageView(context); avatarImageView.setRoundRadius(AndroidUtilities.dp(35)); - avatarImageView.setImage(photo, "50_50", avatarDrawable, invite); linearLayout.addView(avatarImageView, LayoutHelper.createLinear(70, 70, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 12, 0, 0)); + if (invite.chat != null) { + avatarDrawable = new AvatarDrawable(invite.chat); + title = invite.chat.title; + participants_count = invite.chat.participants_count; + avatarImageView.setImage(ImageLocation.getForChat(invite.chat, false), "50_50", avatarDrawable, invite); + } else { + avatarDrawable = new AvatarDrawable(); + avatarDrawable.setInfo(0, invite.title, null, false); + title = invite.title; + participants_count = invite.participants_count; + TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(invite.photo.sizes, 50); + avatarImageView.setImage(ImageLocation.getForPhoto(size, invite.photo), "50_50", avatarDrawable, invite); + } + TextView textView = new TextView(context); textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17); @@ -114,67 +110,53 @@ public class JoinGroupAlert extends BottomSheet { } View shadow = new View(context); - shadow.setBackgroundResource(R.drawable.header_shadow_reverse); - linearLayout.addView(shadow, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 3)); + shadow.setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine)); + linearLayout.addView(shadow, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.getShadowHeight())); PickerBottomLayout pickerBottomLayout = new PickerBottomLayout(context, false); linearLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); pickerBottomLayout.cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase()); - pickerBottomLayout.cancelButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - dismiss(); - } - }); + pickerBottomLayout.cancelButton.setOnClickListener(view -> dismiss()); pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); pickerBottomLayout.doneButton.setVisibility(View.VISIBLE); pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE); pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("JoinGroup", R.string.JoinGroup)); - pickerBottomLayout.doneButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - dismiss(); - final TLRPC.TL_messages_importChatInvite req = new TLRPC.TL_messages_importChatInvite(); - req.hash = hash; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, new RequestDelegate() { - @Override - public void run(final TLObject response, final TLRPC.TL_error error) { - if (error == null) { - TLRPC.Updates updates = (TLRPC.Updates) response; - MessagesController.getInstance(currentAccount).processUpdates(updates, false); - } - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (fragment == null || fragment.getParentActivity() == null) { - return; - } - if (error == null) { - TLRPC.Updates updates = (TLRPC.Updates) response; - if (!updates.chats.isEmpty()) { - TLRPC.Chat chat = updates.chats.get(0); - chat.left = false; - chat.kicked = false; - MessagesController.getInstance(currentAccount).putUsers(updates.users, false); - MessagesController.getInstance(currentAccount).putChats(updates.chats, false); - Bundle args = new Bundle(); - args.putInt("chat_id", chat.id); - if (MessagesController.getInstance(currentAccount).checkCanOpenChat(args, fragment)) { - ChatActivity chatActivity = new ChatActivity(args); - fragment.presentFragment(chatActivity, fragment instanceof ChatActivity); - } - } - } else { - AlertsCreator.processError(currentAccount, error, fragment, req); - } - } - }); + pickerBottomLayout.doneButton.setOnClickListener(v -> { + dismiss(); + final TLRPC.TL_messages_importChatInvite req = new TLRPC.TL_messages_importChatInvite(); + req.hash = hash; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + if (error == null) { + TLRPC.Updates updates = (TLRPC.Updates) response; + MessagesController.getInstance(currentAccount).processUpdates(updates, false); + } + AndroidUtilities.runOnUIThread(() -> { + if (fragment == null || fragment.getParentActivity() == null) { + return; } - }, ConnectionsManager.RequestFlagFailOnServerErrors); - } + if (error == null) { + TLRPC.Updates updates = (TLRPC.Updates) response; + if (!updates.chats.isEmpty()) { + TLRPC.Chat chat = updates.chats.get(0); + chat.left = false; + chat.kicked = false; + MessagesController.getInstance(currentAccount).putUsers(updates.users, false); + MessagesController.getInstance(currentAccount).putChats(updates.chats, false); + Bundle args = new Bundle(); + args.putInt("chat_id", chat.id); + if (MessagesController.getInstance(currentAccount).checkCanOpenChat(args, fragment)) { + ChatActivity chatActivity = new ChatActivity(args); + fragment.presentFragment(chatActivity, fragment instanceof ChatActivity); + } + } + } else { + AlertsCreator.processError(currentAccount, error, fragment, req); + } + }); + }, ConnectionsManager.RequestFlagFailOnServerErrors); }); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java index 309e259f8..80366c3fe 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java @@ -51,6 +51,10 @@ public class LayoutHelper { return new FrameLayout.LayoutParams(getSize(width), getSize(height)); } + public static FrameLayout.LayoutParams createFrame(float width, float height, int gravity) { + return new FrameLayout.LayoutParams(getSize(width), getSize(height), gravity); + } + public static RelativeLayout.LayoutParams createRelative(float width, float height, int leftMargin, int topMargin, int rightMargin, int bottomMargin, int alignParent, int alignRelative, int anchorRelative) { RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(getSize(width), getSize(height)); if (alignParent >= 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActionDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActionDrawable.java index fe7c76d77..246e7374b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActionDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActionDrawable.java @@ -37,6 +37,7 @@ public class MediaActionDrawable extends Drawable { private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint paint2 = new Paint(Paint.ANTI_ALIAS_FLAG); + private Paint paint3 = new Paint(Paint.ANTI_ALIAS_FLAG); private Path path1 = new Path(); private Path path2 = new Path(); private RectF rect = new RectF(); @@ -97,6 +98,8 @@ public class MediaActionDrawable extends Drawable { paint.setStrokeWidth(AndroidUtilities.dp(3)); paint.setStyle(Paint.Style.STROKE); + paint3.setColor(0xffffffff); + textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); textPaint.setTextSize(AndroidUtilities.dp(13)); textPaint.setColor(0xffffffff); @@ -118,12 +121,14 @@ public class MediaActionDrawable extends Drawable { public void setColorFilter(ColorFilter colorFilter) { paint.setColorFilter(colorFilter); paint2.setColorFilter(colorFilter); + paint3.setColorFilter(colorFilter); textPaint.setColorFilter(colorFilter); } public void setColor(int value) { paint.setColor(value | 0xff000000); paint2.setColor(value | 0xff000000); + paint3.setColor(value | 0xff000000); textPaint.setColor(value | 0xff000000); colorFilter = new PorterDuffColorFilter(value, PorterDuff.Mode.MULTIPLY); } @@ -147,7 +152,7 @@ public class MediaActionDrawable extends Drawable { } public boolean setIcon(int icon, boolean animated) { - if (animated && currentIcon == icon && nextIcon != icon) { + if (currentIcon == icon && nextIcon != icon) { currentIcon = nextIcon; transitionProgress = 1.0f; } @@ -324,7 +329,12 @@ public class MediaActionDrawable extends Drawable { x1 = x2 = cx; if (currentProgress2 > 0) { - float rotation = -45 * (1.0f - currentProgress2); + float rotation; + if (nextIcon == ICON_CANCEL_FILL) { + rotation = 0; + } else { + rotation = -45 * (1.0f - currentProgress2); + } d = AndroidUtilities.dp(7) * currentProgress2 * scale; int alpha = (int) (255 * currentProgress2); if (nextIcon != ICON_CANCEL && nextIcon != ICON_CANCEL_FILL && nextIcon != ICON_DOWNLOAD) { @@ -339,14 +349,19 @@ public class MediaActionDrawable extends Drawable { } if (alpha != 0) { paint.setAlpha(alpha); - canvas.drawLine(cx - d, cy - d, cx + d, cy + d, paint); - canvas.drawLine(cx + d, cy - d, cx - d, cy + d, paint); if (nextIcon == ICON_CANCEL_FILL) { + paint3.setAlpha(alpha); + rect.set(cx - AndroidUtilities.dp(3.5f), cy - AndroidUtilities.dp(3.5f), cx + AndroidUtilities.dp(3.5f), cy + AndroidUtilities.dp(3.5f)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(2), AndroidUtilities.dp(2), paint3); + paint.setAlpha((int) (alpha * 0.15f)); int diff = AndroidUtilities.dp(isMini ? 2 : 4); rect.set(bounds.left + diff, bounds.top + diff, bounds.right - diff, bounds.bottom - diff); canvas.drawArc(rect, 0, 360, false, paint); paint.setAlpha(alpha); + } else { + canvas.drawLine(cx - d, cy - d, cx + d, cy + d, paint); + canvas.drawLine(cx + d, cy - d, cx - d, cy + d, paint); } } if (rotation != 0) { @@ -370,10 +385,12 @@ public class MediaActionDrawable extends Drawable { } } - if (currentIcon == ICON_CANCEL || currentIcon == ICON_CANCEL_FILL || currentIcon == ICON_NONE && nextIcon == ICON_CANCEL_FILL) { + if (currentIcon == ICON_CANCEL || currentIcon == ICON_CANCEL_FILL || currentIcon == ICON_NONE && (nextIcon == ICON_CANCEL_FILL || nextIcon == ICON_CANCEL)) { float d; float rotation; float iconScale = 1.0f; + float iconScaleX = 0; + float iconScaleY = 0; int alpha; if (nextIcon == ICON_DOWNLOAD) { if (transitionProgress <= DOWNLOAD_TO_CANCEL_STAGE3 + DOWNLOAD_TO_CANCEL_STAGE2) { @@ -411,7 +428,7 @@ public class MediaActionDrawable extends Drawable { rotation = 45 * progress; iconScale = 1.0f; } - } else if (nextIcon == ICON_CANCEL_FILL) { + } else if (nextIcon == ICON_CANCEL_FILL || nextIcon == ICON_CANCEL) { float progress = transitionProgress; float backProgress = 1.0f - progress; if (currentIcon == ICON_NONE) { @@ -423,6 +440,13 @@ public class MediaActionDrawable extends Drawable { } d = AndroidUtilities.dp(7) * scale; alpha = (int) (255 * progress); + if (nextIcon == ICON_CANCEL_FILL) { + iconScaleX = bounds.left; + iconScaleY = bounds.top; + } else { + iconScaleX = bounds.centerX(); + iconScaleY = bounds.centerY(); + } } else { rotation = 0; d = AndroidUtilities.dp(7) * scale; @@ -430,7 +454,7 @@ public class MediaActionDrawable extends Drawable { } if (iconScale != 1.0f) { canvas.save(); - canvas.scale(iconScale, iconScale, bounds.left, bounds.top); + canvas.scale(iconScale, iconScale, iconScaleX, iconScaleY); } if (rotation != 0) { canvas.save(); @@ -438,18 +462,24 @@ public class MediaActionDrawable extends Drawable { } if (alpha != 0) { paint.setAlpha((int) (alpha * overrideAlpha)); - canvas.drawLine(cx - d, cy - d, cx + d, cy + d, paint); - canvas.drawLine(cx + d, cy - d, cx - d, cy + d, paint); + if (currentIcon == ICON_CANCEL_FILL || nextIcon == ICON_CANCEL_FILL) { + paint3.setAlpha((int) (alpha * overrideAlpha)); + rect.set(cx - AndroidUtilities.dp(3.5f), cy - AndroidUtilities.dp(3.5f), cx + AndroidUtilities.dp(3.5f), cy + AndroidUtilities.dp(3.5f)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(2), AndroidUtilities.dp(2), paint3); + } else { + canvas.drawLine(cx - d, cy - d, cx + d, cy + d, paint); + canvas.drawLine(cx + d, cy - d, cx - d, cy + d, paint); + } } if (rotation != 0) { canvas.restore(); } - if ((currentIcon == ICON_CANCEL || currentIcon == ICON_CANCEL_FILL || currentIcon == ICON_NONE && nextIcon == ICON_CANCEL_FILL) && alpha != 0) { + if ((currentIcon == ICON_CANCEL || currentIcon == ICON_CANCEL_FILL || currentIcon == ICON_NONE && (nextIcon == ICON_CANCEL_FILL || nextIcon == ICON_CANCEL)) && alpha != 0) { float rad = Math.max(4, 360 * animatedDownloadProgress); int diff = AndroidUtilities.dp(isMini ? 2 : 4); rect.set(bounds.left + diff, bounds.top + diff, bounds.right - diff, bounds.bottom - diff); - if (currentIcon == ICON_CANCEL_FILL || currentIcon == ICON_NONE && nextIcon == ICON_CANCEL_FILL) { + if (currentIcon == ICON_CANCEL_FILL || currentIcon == ICON_NONE && (nextIcon == ICON_CANCEL_FILL || nextIcon == ICON_CANCEL)) { paint.setAlpha((int) (alpha * 0.15f * overrideAlpha)); canvas.drawArc(rect, 0, 360, false, paint); paint.setAlpha(alpha); @@ -485,6 +515,9 @@ public class MediaActionDrawable extends Drawable { float previowsDrawableScale; if (currentIcon == nextIcon) { drawableScale = previowsDrawableScale = 1.0f; + } else if (currentIcon == ICON_NONE) { + drawableScale = transitionProgress; + previowsDrawableScale = 1.0f - transitionProgress; } else { drawableScale = Math.min(1.0f, transitionProgress / 0.5f); previowsDrawableScale = Math.max(0.0f, 1.0f - transitionProgress / 0.5f); @@ -658,7 +691,11 @@ public class MediaActionDrawable extends Drawable { path2.lineTo(AndroidUtilities.dp(p2[a * 2]) * scale, AndroidUtilities.dp(p2[a * 2 + 1]) * scale); } } - paint2.setAlpha(currentIcon == nextIcon ? 255 : (int) (transitionProgress * 255)); + if (nextIcon == ICON_NONE) { + paint2.setAlpha((int) (255 * (1.0f - transitionProgress))); + } else { + paint2.setAlpha(currentIcon == nextIcon ? 255 : (int) (transitionProgress * 255)); + } } else { for (int a = 0; a < 5; a++) { if (a == 0) { @@ -678,7 +715,7 @@ public class MediaActionDrawable extends Drawable { canvas.save(); canvas.translate(bounds.left, bounds.top); canvas.rotate(rotation1 + (rotation2 - rotation1) * p, cx - bounds.left, cy - bounds.top); - if (currentIcon != ICON_PLAY && currentIcon != ICON_PAUSE) { + if (currentIcon != ICON_PLAY && currentIcon != ICON_PAUSE || currentIcon == ICON_NONE) { canvas.scale(drawableScale, drawableScale, cx - bounds.left, cy - bounds.top); } canvas.drawPath(path1, paint2); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MessageBackgroundDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MessageBackgroundDrawable.java new file mode 100644 index 000000000..57e04f81a --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MessageBackgroundDrawable.java @@ -0,0 +1,167 @@ +package org.telegram.ui.Components; + +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.SystemClock; + +public class MessageBackgroundDrawable extends Drawable { + + private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private long lastAnimationTime; + private float currentAnimationProgress; + private boolean isSelected; + private boolean animationInProgress; + private int finalRadius; + private float touchX = -1; + private float touchY = -1; + + public final static float ANIMATION_DURATION = 200.0f; + + public MessageBackgroundDrawable(int color) { + paint.setColor(color); + } + + public void setColor(int color) { + paint.setColor(color); + } + + public void setSelected(boolean selected, boolean animated) { + animated = false; + if (isSelected == selected) { + if (animationInProgress != animated && !animated) { + currentAnimationProgress = selected ? 1.0f : 0.0f; + animationInProgress = false; + } + return; + } + isSelected = selected; + animationInProgress = animated; + if (animated) { + lastAnimationTime = SystemClock.uptimeMillis(); + } else { + currentAnimationProgress = selected ? 1.0f : 0.0f; + } + calcRadius(); + invalidateSelf(); + } + + private void calcRadius() { + Rect bounds = getBounds(); + float x1; + float y1; + if (touchX >= 0 && touchY >= 0) { + x1 = touchX; + y1 = touchY; + } else { + x1 = bounds.centerX(); + y1 = bounds.centerY(); + } + finalRadius = 0; + for (int a = 0; a < 4; a++) { + float x2; + float y2; + switch (a) { + case 0: + x2 = bounds.left; + y2 = bounds.top; + break; + case 1: + x2 = bounds.left; + y2 = bounds.bottom; + break; + case 2: + x2 = bounds.right; + y2 = bounds.top; + break; + case 3: + default: + x2 = bounds.right; + y2 = bounds.bottom; + break; + } + finalRadius = Math.max(finalRadius, (int) Math.ceil(Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)))); + } + } + + public void setTouchCoords(float x, float y) { + touchX = x; + touchY = y; + calcRadius(); + invalidateSelf(); + } + + @Override + public void setBounds(int left, int top, int right, int bottom) { + super.setBounds(left, top, right, bottom); + calcRadius(); + } + + @Override + public void setBounds(Rect bounds) { + super.setBounds(bounds); + calcRadius(); + } + + @Override + public void setColorFilter(ColorFilter colorFilter) { + paint.setColorFilter(colorFilter); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } + + @Override + public void setAlpha(int alpha) { + paint.setAlpha(alpha); + } + + @Override + public void draw(Canvas canvas) { + if (animationInProgress) { + long newTime = SystemClock.uptimeMillis(); + long dt = newTime - lastAnimationTime; + lastAnimationTime = newTime; + + if (isSelected) { + currentAnimationProgress += dt / ANIMATION_DURATION; + if (currentAnimationProgress >= 1.0f) { + touchX = -1; + touchY = -1; + currentAnimationProgress = 1.0f; + animationInProgress = false; + } + invalidateSelf(); + } else { + currentAnimationProgress -= dt / ANIMATION_DURATION; + if (currentAnimationProgress <= 0.0f) { + touchX = -1; + touchY = -1; + currentAnimationProgress = 0.0f; + animationInProgress = false; + } + invalidateSelf(); + } + } + if (currentAnimationProgress == 1.0f) { + canvas.drawRect(getBounds(), paint); + } else if (currentAnimationProgress != 0.0f) { + float x1; + float y1; + if (touchX >= 0 && touchY >= 0) { + x1 = touchX; + y1 = touchY; + } else { + Rect bounds = getBounds(); + x1 = bounds.centerX(); + y1 = bounds.centerY(); + } + canvas.drawCircle(x1, y1, finalRadius * CubicBezierInterpolator.EASE_OUT.getInterpolation(currentAnimationProgress), paint); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/NoSoundHintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/NoSoundHintView.java deleted file mode 100644 index 7ff60f07d..000000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/NoSoundHintView.java +++ /dev/null @@ -1,142 +0,0 @@ -package org.telegram.ui.Components; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; -import android.content.Context; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.TextView; - -import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.ImageReceiver; -import org.telegram.messenger.LocaleController; -import org.telegram.messenger.R; -import org.telegram.ui.ActionBar.Theme; -import org.telegram.ui.Cells.ChatMessageCell; - - -@SuppressWarnings("FieldCanBeLocal") -public class NoSoundHintView extends FrameLayout { - - private TextView textView; - private ImageView imageView; - private ImageView arrowImageView; - private ChatMessageCell messageCell; - private AnimatorSet animatorSet; - private Runnable hideRunnable; - - public NoSoundHintView(Context context) { - super(context); - - textView = new CorrectlyMeasuringTextView(context); - textView.setTextColor(Theme.getColor(Theme.key_chat_gifSaveHintText)); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - textView.setMaxLines(2); - textView.setMaxWidth(AndroidUtilities.dp(250)); - textView.setGravity(Gravity.LEFT | Gravity.TOP); - textView.setText(LocaleController.getString("AutoplayVideoInfo", R.string.AutoplayVideoInfo)); - textView.setBackgroundDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(3), Theme.getColor(Theme.key_chat_gifSaveHintBackground))); - textView.setPadding(AndroidUtilities.dp(54), AndroidUtilities.dp(6), AndroidUtilities.dp(5), AndroidUtilities.dp(7)); - addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 6)); - - imageView = new ImageView(context); - imageView.setImageResource(R.drawable.tooltip_sound); - imageView.setScaleType(ImageView.ScaleType.CENTER); - imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_gifSaveHintText), PorterDuff.Mode.MULTIPLY)); - addView(imageView, LayoutHelper.createFrame(38, 34, Gravity.LEFT | Gravity.TOP, 7, 7, 0, 0)); - - arrowImageView = new ImageView(context); - arrowImageView.setImageResource(R.drawable.tooltip_arrow); - arrowImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_gifSaveHintBackground), PorterDuff.Mode.MULTIPLY)); - addView(arrowImageView, LayoutHelper.createFrame(14, 6, Gravity.LEFT | Gravity.BOTTOM, 0, 0, 0, 0)); - } - - public boolean showForMessageCell(ChatMessageCell cell) { - if (getTag() != null) { - return false; - } - ImageReceiver imageReceiver = cell.getPhotoImage(); - int top = cell.getTop() + imageReceiver.getImageY(); - int height = imageReceiver.getImageHeight(); - int bottom = top + height; - View parentView = (View) cell.getParent(); - int parentHeight = parentView.getMeasuredHeight(); - if (top <= getMeasuredHeight() + AndroidUtilities.dp(10) || bottom > parentHeight + height / 4) { - return false; - } - int parentWidth = parentView.getMeasuredWidth(); - setTranslationY(top - getMeasuredHeight()); - int iconX = cell.getLeft() + cell.getNoSoundIconCenterX(); - int left = getLeft(); - if (iconX > parentView.getMeasuredWidth() / 2) { - int offset = parentWidth - getMeasuredWidth() - AndroidUtilities.dp(38); - setTranslationX(offset); - left += offset; - } else { - setTranslationX(0); - } - arrowImageView.setTranslationX(cell.getLeft() + cell.getNoSoundIconCenterX() - left - arrowImageView.getMeasuredWidth() / 2); - messageCell = cell; - if (animatorSet != null) { - animatorSet.cancel(); - animatorSet = null; - } - - setTag(1); - setVisibility(VISIBLE); - animatorSet = new AnimatorSet(); - animatorSet.playTogether( - ObjectAnimator.ofFloat(this, "alpha", 0.0f, 1.0f) - ); - animatorSet.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - animatorSet = null; - AndroidUtilities.runOnUIThread(hideRunnable = () -> hide(), 10000); - } - }); - animatorSet.setDuration(300); - animatorSet.start(); - - return true; - } - - public void hide() { - if (getTag() == null) { - return; - } - setTag(null); - if (hideRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(hideRunnable); - hideRunnable = null; - } - if (animatorSet != null) { - animatorSet.cancel(); - animatorSet = null; - } - animatorSet = new AnimatorSet(); - animatorSet.playTogether( - ObjectAnimator.ofFloat(this, "alpha", 0.0f) - ); - animatorSet.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - setVisibility(View.INVISIBLE); - animatorSet = null; - } - }); - animatorSet.setDuration(300); - animatorSet.start(); - } - - public ChatMessageCell getMessageCell() { - return messageCell; - } -} 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 8d35baba6..4bb97e77b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java @@ -33,6 +33,8 @@ import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; import android.view.animation.DecelerateInterpolator; import android.widget.LinearLayout; import android.widget.TextView; @@ -829,6 +831,16 @@ public class NumberPicker extends LinearLayout { if (mOnScrollListener != null) { mOnScrollListener.onScrollStateChange(this, scrollState); } + if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) { + AccessibilityManager am = (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); + if(am.isTouchExplorationEnabled()){ + String text=(mDisplayedValues==null) ? formatNumber(mValue) : mDisplayedValues[mValue-mMinValue]; + AccessibilityEvent event = AccessibilityEvent.obtain(); + event.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT); + event.getText().add(text); + am.sendAccessibilityEvent(event); + } + } } private void fling(int velocityY) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PacmanAnimation.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PacmanAnimation.java new file mode 100644 index 000000000..ff9c6f1a7 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PacmanAnimation.java @@ -0,0 +1,167 @@ +package org.telegram.ui.Components; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.view.View; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.SharedConfig; +import org.telegram.ui.ActionBar.Theme; + +public class PacmanAnimation { + + private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private Paint edgePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private View parentView; + private Runnable finishRunnable; + + private long lastUpdateTime = 0; + private RectF rect = new RectF(); + private float progress; + private float translationProgress; + private float ghostProgress; + private Path ghostPath; + private boolean ghostWalk; + private boolean currentGhostWalk; + + public PacmanAnimation(View parent) { + edgePaint.setStyle(Paint.Style.STROKE); + edgePaint.setStrokeWidth(AndroidUtilities.dp(2)); + parentView = parent; + } + + public void setFinishRunnable(Runnable onAnimationFinished) { + finishRunnable = onAnimationFinished; + } + + private void update() { + long newTime = System.currentTimeMillis(); + long dt = newTime - lastUpdateTime; + lastUpdateTime = newTime; + if (dt > 17) { + dt = 17; + } + if (progress >= 1.0f) { + progress = 0.0f; + } + progress += dt / 400.0f; + if (progress > 1.0f) { + progress = 1.0f; + } + translationProgress += dt / 2000.0f; + if (translationProgress > 1.0f) { + translationProgress = 1.0f; + } + ghostProgress += dt / 200.0f; + if (ghostProgress >= 1.0f) { + ghostWalk = !ghostWalk; + ghostProgress = 0.0f; + } + parentView.invalidate(); + } + + public void start() { + translationProgress = 0.0f; + progress = 0.0f; + lastUpdateTime = System.currentTimeMillis(); + parentView.invalidate(); + } + + private void drawGhost(Canvas canvas, int num) { + if (ghostPath == null || ghostWalk != currentGhostWalk) { + if (ghostPath == null) { + ghostPath = new Path(); + } + ghostPath.reset(); + currentGhostWalk = ghostWalk; + if (currentGhostWalk) { + ghostPath.moveTo(0, AndroidUtilities.dp(50)); + ghostPath.lineTo(0, AndroidUtilities.dp(24)); + rect.set(0, 0, AndroidUtilities.dp(42), AndroidUtilities.dp(24)); + ghostPath.arcTo(rect, 180, 180, false); + ghostPath.lineTo(AndroidUtilities.dp(42), AndroidUtilities.dp(50)); + ghostPath.lineTo(AndroidUtilities.dp(35), AndroidUtilities.dp(43)); + ghostPath.lineTo(AndroidUtilities.dp(28), AndroidUtilities.dp(50)); + ghostPath.lineTo(AndroidUtilities.dp(21), AndroidUtilities.dp(43)); + ghostPath.lineTo(AndroidUtilities.dp(14), AndroidUtilities.dp(50)); + ghostPath.lineTo(AndroidUtilities.dp(7), AndroidUtilities.dp(43)); + } else { + ghostPath.moveTo(0, AndroidUtilities.dp(43)); + ghostPath.lineTo(0, AndroidUtilities.dp(24)); + rect.set(0, 0, AndroidUtilities.dp(42), AndroidUtilities.dp(24)); + ghostPath.arcTo(rect, 180, 180, false); + ghostPath.lineTo(AndroidUtilities.dp(42), AndroidUtilities.dp(43)); + ghostPath.lineTo(AndroidUtilities.dp(35), AndroidUtilities.dp(50)); + ghostPath.lineTo(AndroidUtilities.dp(28), AndroidUtilities.dp(43)); + ghostPath.lineTo(AndroidUtilities.dp(21), AndroidUtilities.dp(50)); + ghostPath.lineTo(AndroidUtilities.dp(14), AndroidUtilities.dp(43)); + ghostPath.lineTo(AndroidUtilities.dp(7), AndroidUtilities.dp(50)); + } + ghostPath.close(); + } + canvas.drawPath(ghostPath, edgePaint); + if (num == 0) { + paint.setColor(0xfffea000); + } else if (num == 1) { + paint.setColor(0xfffeb2b2); + } else { + paint.setColor(0xff00dedf); + } + canvas.drawPath(ghostPath, paint); + paint.setColor(0xffffffff); + rect.set(AndroidUtilities.dp(8), AndroidUtilities.dp(14), AndroidUtilities.dp(20), AndroidUtilities.dp(28)); + canvas.drawOval(rect, paint); + rect.set(AndroidUtilities.dp(8 + 16), AndroidUtilities.dp(14), AndroidUtilities.dp(20 + 16), AndroidUtilities.dp(28)); + canvas.drawOval(rect, paint); + + paint.setColor(0xff000000); + rect.set(AndroidUtilities.dp(14), AndroidUtilities.dp(18), AndroidUtilities.dp(19), AndroidUtilities.dp(24)); + canvas.drawOval(rect, paint); + rect.set(AndroidUtilities.dp(14 + 16), AndroidUtilities.dp(18), AndroidUtilities.dp(19 + 16), AndroidUtilities.dp(24)); + canvas.drawOval(rect, paint); + } + + public void draw(Canvas canvas, int cy) { + int size = AndroidUtilities.dp(110); + int height = AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 78 : 72); + int additionalSize = size + AndroidUtilities.dp(42 + 20) * 3; + int width = parentView.getMeasuredWidth() + additionalSize; + float translation = width * translationProgress - additionalSize; + + int y = cy - size / 2; + + paint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + canvas.drawRect(0, cy - height / 2, translation + size / 2, cy + height / 2 + 1, paint); + + paint.setColor(0xfffef200); + rect.set(translation, y, translation + size, y + size); + int rad; + if (progress < 0.5f) { + rad = (int) (35 * (1.0f - progress / 0.5f)); + } else { + rad = (int) (35 * (progress - 0.5f) / 0.5f); + } + + canvas.drawArc(rect, rad, 360 - rad * 2, true, edgePaint); + canvas.drawArc(rect, rad, 360 - rad * 2, true, paint); + + paint.setColor(0xff000000); + canvas.drawCircle(translation + size / 2 - AndroidUtilities.dp(8), y + size / 4, AndroidUtilities.dp(8), paint); + + canvas.save(); + canvas.translate(translation + size + AndroidUtilities.dp(20), cy - AndroidUtilities.dp(25)); + for (int a = 0; a < 3; a++) { + drawGhost(canvas, a); + canvas.translate(AndroidUtilities.dp(42 + 20), 0); + } + canvas.restore(); + + if (translationProgress >= 1.0f) { + finishRunnable.run(); + } + + update(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java index 781a8ff79..471a5baa4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java @@ -13,9 +13,10 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.drawable.Drawable; -import android.support.v4.view.ViewPager; -import android.support.v4.view.ViewPager.OnPageChangeListener; +import androidx.viewpager.widget.ViewPager; +import androidx.viewpager.widget.ViewPager.OnPageChangeListener; import android.view.View; +import android.view.ViewGroup; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.widget.FrameLayout; import android.widget.HorizontalScrollView; @@ -96,7 +97,7 @@ public class PagerSlidingTabStrip extends HorizontalScrollView { tabCount = pager.getAdapter().getCount(); for (int i = 0; i < tabCount; i++) { if (pager.getAdapter() instanceof IconTabProvider) { - addIconTab(i, ((IconTabProvider) pager.getAdapter()).getPageIconDrawable(i)); + addIconTab(i, ((IconTabProvider) pager.getAdapter()).getPageIconDrawable(i), pager.getAdapter().getPageTitle(i)); } } updateTabStyles(); @@ -117,7 +118,7 @@ public class PagerSlidingTabStrip extends HorizontalScrollView { return tabsContainer.getChildAt(position); } - private void addIconTab(final int position, Drawable drawable) { + private void addIconTab(final int position, Drawable drawable, CharSequence contentDescription) { ImageView tab = new ImageView(getContext()) { @Override protected void onDraw(Canvas canvas) { @@ -130,19 +131,17 @@ public class PagerSlidingTabStrip extends HorizontalScrollView { tab.setFocusable(true); tab.setImageDrawable(drawable); tab.setScaleType(ImageView.ScaleType.CENTER); - tab.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (pager.getAdapter() instanceof IconTabProvider) { - if (!((IconTabProvider) pager.getAdapter()).canScrollToTab(position)) { - return; - } + tab.setOnClickListener(v -> { + if (pager.getAdapter() instanceof IconTabProvider) { + if (!((IconTabProvider) pager.getAdapter()).canScrollToTab(position)) { + return; } - pager.setCurrentItem(position); } + pager.setCurrentItem(position, false); }); tabsContainer.addView(tab); tab.setSelected(position == currentPosition); + tab.setContentDescription(contentDescription); } private void updateTabStyles() { @@ -151,7 +150,7 @@ public class PagerSlidingTabStrip extends HorizontalScrollView { v.setLayoutParams(defaultTabLayoutParams); if (shouldExpand) { v.setPadding(0, 0, 0, 0); - v.setLayoutParams(new LinearLayout.LayoutParams(-1, -1, 1.0F)); + v.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 1.0F)); } else { v.setPadding(tabPadding, 0, tabPadding, 0); } @@ -192,18 +191,16 @@ public class PagerSlidingTabStrip extends HorizontalScrollView { final int height = getHeight(); - // draw underline - rectPaint.setColor(underlineColor); - canvas.drawRect(0, height - underlineHeight, tabsContainer.getWidth(), height, rectPaint); + if (underlineHeight != 0) { + rectPaint.setColor(underlineColor); + canvas.drawRect(0, height - underlineHeight, tabsContainer.getWidth(), height, rectPaint); + } - // default: line below current tab View currentTab = tabsContainer.getChildAt(currentPosition); float lineLeft = currentTab.getLeft(); float lineRight = currentTab.getRight(); - // if there is an offset, start interpolating left and right coordinates between current and next tab if (currentPositionOffset > 0f && currentPosition < tabCount - 1) { - View nextTab = tabsContainer.getChildAt(currentPosition + 1); final float nextTabLeft = nextTab.getLeft(); final float nextTabRight = nextTab.getRight(); @@ -212,9 +209,10 @@ public class PagerSlidingTabStrip extends HorizontalScrollView { lineRight = (currentPositionOffset * nextTabRight + (1f - currentPositionOffset) * lineRight); } - // draw indicator line - rectPaint.setColor(indicatorColor); - canvas.drawRect(lineLeft, height - indicatorHeight, lineRight, height, rectPaint); + if (indicatorHeight != 0) { + rectPaint.setColor(indicatorColor); + canvas.drawRect(lineLeft, height - indicatorHeight, lineRight, height, rectPaint); + } } private class PageListener implements OnPageChangeListener { @@ -253,11 +251,7 @@ public class PagerSlidingTabStrip extends HorizontalScrollView { public void onSizeChanged(int paramInt1, int paramInt2, int paramInt3, int paramInt4) { if (!shouldExpand) { - post(new Runnable() { - public void run() { - PagerSlidingTabStrip.this.notifyDataSetChanged(); - } - }); + post(PagerSlidingTabStrip.this::notifyDataSetChanged); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerView.java index 0d830e385..afe5da956 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/StickerView.java @@ -10,6 +10,7 @@ import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Components.LayoutHelper; @@ -69,7 +70,7 @@ public class StickerView extends EntityView { centerImage.setInvalidateAll(true); centerImage.setParentView(containerView); TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(sticker.thumbs, 90); - centerImage.setImage(sticker, null, thumb, null, "webp", parentObject, 1); + centerImage.setImage(ImageLocation.getForDocument(sticker), null, ImageLocation.getForDocument(thumb, sticker), null, "webp", parentObject, 1); updatePosition(); } 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 06d0b562a..bc9e1572f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java @@ -23,7 +23,8 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.os.SystemClock; import android.os.Vibrator; -import android.support.v4.os.CancellationSignal; +import androidx.annotation.IdRes; +import androidx.core.os.CancellationSignal; import android.text.Editable; import android.text.InputFilter; import android.text.InputType; @@ -36,6 +37,7 @@ import android.view.HapticFeedbackConstants; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.inputmethod.EditorInfo; import android.widget.FrameLayout; import android.widget.ImageView; @@ -420,6 +422,21 @@ public class PasscodeView extends FrameLayout { private final static int id_fingerprint_textview = 1000; private final static int id_fingerprint_imageview = 1001; + private static final @IdRes + int[] ids = { + R.id.passcode_btn_0, + R.id.passcode_btn_1, + R.id.passcode_btn_2, + R.id.passcode_btn_3, + R.id.passcode_btn_4, + R.id.passcode_btn_5, + R.id.passcode_btn_6, + R.id.passcode_btn_7, + R.id.passcode_btn_8, + R.id.passcode_btn_9, + R.id.passcode_btn_backspace + }; + public PasscodeView(final Context context) { super(context); @@ -555,6 +572,7 @@ public class PasscodeView extends FrameLayout { layoutParams.rightMargin = AndroidUtilities.dp(10); layoutParams.gravity = Gravity.BOTTOM | Gravity.RIGHT; checkImage.setLayoutParams(layoutParams); + checkImage.setContentDescription(LocaleController.getString("Done", R.string.Done)); checkImage.setOnClickListener(v -> processDone(false)); FrameLayout lineFrameLayout = new FrameLayout(context); @@ -591,6 +609,7 @@ public class PasscodeView extends FrameLayout { layoutParams.height = AndroidUtilities.dp(50); layoutParams.gravity = Gravity.TOP | Gravity.LEFT; textView.setLayoutParams(layoutParams); + textView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); numberTextViews.add(textView); textView = new TextView(context); @@ -603,6 +622,7 @@ public class PasscodeView extends FrameLayout { layoutParams.height = AndroidUtilities.dp(20); layoutParams.gravity = Gravity.TOP | Gravity.LEFT; textView.setLayoutParams(layoutParams); + textView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); switch (a) { case 0: textView.setText("+"); @@ -646,7 +666,13 @@ public class PasscodeView extends FrameLayout { layoutParams.gravity = Gravity.TOP | Gravity.LEFT; eraseView.setLayoutParams(layoutParams); for (int a = 0; a < 11; a++) { - FrameLayout frameLayout = new FrameLayout(context); + FrameLayout frameLayout = new FrameLayout(context) { + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.Button"); + } + }; frameLayout.setBackgroundResource(R.drawable.bar_selector_lock); frameLayout.setTag(a); if (a == 10) { @@ -655,7 +681,19 @@ public class PasscodeView extends FrameLayout { passwordEditText2.eraseAllCharacters(true); return true; }); + frameLayout.setContentDescription(LocaleController.getString("AccDescrBackspace", R.string.AccDescrBackspace)); + setNextFocus(frameLayout, R.id.passcode_btn_1); + } else { + frameLayout.setContentDescription(a + ""); + if (a == 0) { + setNextFocus(frameLayout, R.id.passcode_btn_backspace); + } else if (a == 9) { + setNextFocus(frameLayout, R.id.passcode_btn_0); + } else { + setNextFocus(frameLayout, ids[a + 1]); + } } + frameLayout.setId(ids[a]); frameLayout.setOnClickListener(v -> { int tag = (Integer) v.getTag(); switch (tag) { @@ -710,6 +748,13 @@ public class PasscodeView extends FrameLayout { } } + private void setNextFocus(View view, @IdRes int nextId) { + view.setNextFocusForwardId(nextId); + if (Build.VERSION.SDK_INT >= 22) { + view.setAccessibilityTraversalBefore(nextId); + } + } + public void setDelegate(PasscodeViewDelegate delegate) { this.delegate = delegate; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java index bc8a56752..24f1ea6b7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java @@ -35,8 +35,6 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BuildVars; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; @@ -59,6 +57,9 @@ import javax.microedition.khronos.egl.EGLSurface; import javax.microedition.khronos.opengles.GL; import javax.microedition.khronos.opengles.GL10; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + @SuppressLint("NewApi") public class PhotoFilterView extends FrameLayout { @@ -935,7 +936,7 @@ public class PhotoFilterView extends FrameLayout { gl = eglContext.getGL(); - float squareCoordinates[] = { + float[] squareCoordinates = { -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, @@ -947,7 +948,7 @@ public class PhotoFilterView extends FrameLayout { vertexBuffer.put(squareCoordinates); vertexBuffer.position(0); - float squareCoordinates2[] = { + float[] squareCoordinates2 = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, @@ -959,7 +960,7 @@ public class PhotoFilterView extends FrameLayout { vertexInvertBuffer.put(squareCoordinates2); vertexInvertBuffer.position(0); - float textureCoordinates[] = { + float[] textureCoordinates = { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, @@ -1517,7 +1518,7 @@ public class PhotoFilterView extends FrameLayout { return null; } final CountDownLatch countDownLatch = new CountDownLatch(1); - final Bitmap object[] = new Bitmap[1]; + final Bitmap[] object = new Bitmap[1]; try { postRunnable(() -> { GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[1]); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java index 9583d7b09..76b1b77f8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java @@ -13,6 +13,7 @@ import android.animation.ObjectAnimator; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; +import android.graphics.drawable.Drawable; import android.os.Build; import android.text.Editable; import android.text.InputFilter; @@ -41,7 +42,6 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; -import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import java.lang.reflect.Field; @@ -107,7 +107,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica textFieldContainer.addView(frameLayout, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, 1.0f)); emojiButton = new ImageView(context); - emojiButton.setImageResource(R.drawable.ic_smile_w); + emojiButton.setImageResource(R.drawable.input_smile); emojiButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE); emojiButton.setPadding(AndroidUtilities.dp(4), AndroidUtilities.dp(1), 0, 0); frameLayout.addView(emojiButton, LayoutHelper.createFrame(48, 48, Gravity.BOTTOM | Gravity.LEFT)); @@ -118,6 +118,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica openKeyboardInternal(); } }); + emojiButton.setContentDescription(LocaleController.getString("Emoji", R.string.Emoji)); lengthTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); lengthTextPaint.setTextSize(AndroidUtilities.dp(13)); @@ -283,14 +284,17 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica } }); + Drawable drawable = Theme.createCircleDrawable(AndroidUtilities.dp(16), 0xff66bffa); + Drawable checkDrawable = context.getResources().getDrawable(R.drawable.input_done).mutate(); + CombinedDrawable combinedDrawable = new CombinedDrawable(drawable, checkDrawable, 0, AndroidUtilities.dp(1)); + combinedDrawable.setCustomSize(AndroidUtilities.dp(32), AndroidUtilities.dp(32)); + ImageView doneButton = new ImageView(context); doneButton.setScaleType(ImageView.ScaleType.CENTER); - doneButton.setImageResource(R.drawable.ic_done); + doneButton.setImageDrawable(combinedDrawable); textFieldContainer.addView(doneButton, LayoutHelper.createLinear(48, 48, Gravity.BOTTOM)); - if (Build.VERSION.SDK_INT >= 21) { - doneButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); - } doneButton.setOnClickListener(view -> delegate.onCaptionEnter()); + doneButton.setContentDescription(LocaleController.getString("Done", R.string.Done)); } float animationProgress = 0.0f; @@ -437,9 +441,8 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica if (emojiView != null) { return; } - emojiView = new EmojiView(false, false, getContext(), null); - emojiView.setListener(new EmojiView.Listener() { - + emojiView = new EmojiView(false, false, getContext(), false, null); + emojiView.setDelegate(new EmojiView.EmojiViewDelegate() { @Override public boolean onBackspace() { if (messageEditText.length() == 0) { @@ -470,71 +473,6 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica innerTextChange = false; } } - - @Override - public void onStickerSelected(TLRPC.Document sticker, Object parent) { - - } - - @Override - public void onStickersSettingsClick() { - - } - - @Override - public void onGifSelected(TLRPC.Document gif, Object parent) { - - } - - @Override - public void onGifTab(boolean opened) { - - } - - @Override - public void onStickersTab(boolean opened) { - - } - - @Override - public void onClearEmojiRecent() { - - } - - @Override - public void onShowStickerSet(TLRPC.StickerSet stickerSet, TLRPC.InputStickerSet inputStickerSet) { - - } - - @Override - public void onStickerSetAdd(TLRPC.StickerSetCovered stickerSet) { - - } - - @Override - public void onStickerSetRemove(TLRPC.StickerSetCovered stickerSet) { - - } - - @Override - public void onStickersGroupClick(int chatId) { - - } - - @Override - public void onSearchOpenClose(boolean open) { - - } - - @Override - public boolean isSearchOpened() { - return false; - } - - @Override - public boolean isExpanded() { - return false; - } }); sizeNotifierLayout.addView(emojiView); } @@ -623,12 +561,12 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica if (sizeNotifierLayout != null) { emojiPadding = currentHeight; sizeNotifierLayout.requestLayout(); - emojiButton.setImageResource(R.drawable.ic_keyboard_w); + emojiButton.setImageResource(R.drawable.input_keyboard); onWindowSizeChanged(); } } else { if (emojiButton != null) { - emojiButton.setImageResource(R.drawable.ic_smile_w); + emojiButton.setImageResource(R.drawable.input_smile); } if (emojiView != null) { emojiView.setVisibility(GONE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PipRoundVideoView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PipRoundVideoView.java index 21f7d1eaf..64a790408 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PipRoundVideoView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PipRoundVideoView.java @@ -27,7 +27,7 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.os.Build; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.view.Gravity; import android.view.MotionEvent; import android.view.TextureView; @@ -174,6 +174,7 @@ public class PipRoundVideoView implements NotificationCenter.NotificationCenterD Theme.chat_roundVideoShadow.draw(canvas); Theme.chat_docBackPaint.setColor(Theme.getColor(Theme.key_chat_inBubble)); + Theme.chat_docBackPaint.setAlpha((int) (getAlpha() * 255)); canvas.drawCircle(AndroidUtilities.dp(3 + 60), AndroidUtilities.dp(3 + 60), AndroidUtilities.dp(59.5f), Theme.chat_docBackPaint); } } @@ -380,9 +381,9 @@ public class PipRoundVideoView implements NotificationCenter.NotificationCenterD } hideShowAnimation = new AnimatorSet(); hideShowAnimation.playTogether( - ObjectAnimator.ofFloat(windowView, "alpha", show ? 1.0f : 0.0f), - ObjectAnimator.ofFloat(windowView, "scaleX", show ? 1.0f : 0.8f), - ObjectAnimator.ofFloat(windowView, "scaleY", show ? 1.0f : 0.8f)); + ObjectAnimator.ofFloat(windowView, View.ALPHA, show ? 1.0f : 0.0f), + ObjectAnimator.ofFloat(windowView, View.SCALE_X, show ? 1.0f : 0.8f), + ObjectAnimator.ofFloat(windowView, View.SCALE_Y, show ? 1.0f : 0.8f)); hideShowAnimation.setDuration(150); if (decelerateInterpolator == null) { decelerateInterpolator = new DecelerateInterpolator(); @@ -405,9 +406,9 @@ public class PipRoundVideoView implements NotificationCenter.NotificationCenterD } hideShowAnimation = new AnimatorSet(); hideShowAnimation.playTogether( - ObjectAnimator.ofFloat(windowView, "alpha", show ? 1.0f : 0.0f), - ObjectAnimator.ofFloat(windowView, "scaleX", show ? 1.0f : 0.8f), - ObjectAnimator.ofFloat(windowView, "scaleY", show ? 1.0f : 0.8f)); + ObjectAnimator.ofFloat(windowView, View.ALPHA, show ? 1.0f : 0.0f), + ObjectAnimator.ofFloat(windowView, View.SCALE_X, show ? 1.0f : 0.8f), + ObjectAnimator.ofFloat(windowView, View.SCALE_Y, show ? 1.0f : 0.8f)); hideShowAnimation.setDuration(150); if (decelerateInterpolator == null) { decelerateInterpolator = new DecelerateInterpolator(); @@ -449,7 +450,7 @@ public class PipRoundVideoView implements NotificationCenter.NotificationCenterD } editor.putInt("sidex", 0); if (windowView.getAlpha() != 1.0f) { - animators.add(ObjectAnimator.ofFloat(windowView, "alpha", 1.0f)); + animators.add(ObjectAnimator.ofFloat(windowView, View.ALPHA, 1.0f)); } animators.add(ObjectAnimator.ofInt(this, "x", startX)); } else if (Math.abs(endX - windowLayoutParams.x) <= maxDiff || windowLayoutParams.x > AndroidUtilities.displaySize.x - videoWidth && windowLayoutParams.x < AndroidUtilities.displaySize.x - videoWidth / 4 * 3) { @@ -458,7 +459,7 @@ public class PipRoundVideoView implements NotificationCenter.NotificationCenterD } editor.putInt("sidex", 1); if (windowView.getAlpha() != 1.0f) { - animators.add(ObjectAnimator.ofFloat(windowView, "alpha", 1.0f)); + animators.add(ObjectAnimator.ofFloat(windowView, View.ALPHA, 1.0f)); } animators.add(ObjectAnimator.ofInt(this, "x", endX)); } else if (windowView.getAlpha() != 1.0f) { @@ -502,7 +503,7 @@ public class PipRoundVideoView implements NotificationCenter.NotificationCenterD animatorSet.setInterpolator(decelerateInterpolator); animatorSet.setDuration(150); if (slideOut) { - animators.add(ObjectAnimator.ofFloat(windowView, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(windowView, View.ALPHA, 0.0f)); animatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PipVideoView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PipVideoView.java index 0f73a6d63..c86ef9254 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PipVideoView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PipVideoView.java @@ -19,7 +19,7 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PixelFormat; import android.os.Build; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.view.Gravity; import android.view.MotionEvent; import android.view.TextureView; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PlayingGameDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PlayingGameDrawable.java index 42ac98f83..2d4740081 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PlayingGameDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PlayingGameDrawable.java @@ -13,7 +13,6 @@ import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.RectF; -import android.view.animation.DecelerateInterpolator; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.NotificationCenter; @@ -28,7 +27,6 @@ public class PlayingGameDrawable extends StatusDrawable { private long lastUpdateTime = 0; private boolean started = false; - private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(); private RectF rect = new RectF(); private float progress; @@ -111,12 +109,7 @@ public class PlayingGameDrawable extends StatusDrawable { if (!NotificationCenter.getInstance(currentAccount).isAnimationInProgress()) { update(); } else { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - checkUpdate(); - } - }, 100); + AndroidUtilities.runOnUIThread(this::checkUpdate, 100); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress2.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress2.java index 848d012b5..1298a1aa8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress2.java @@ -16,8 +16,9 @@ import android.graphics.RectF; import android.view.View; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; -import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import java.util.Locale; @@ -85,8 +86,8 @@ public class RadialProgress2 { overlayImageView.setRoundRadius(circleRadius); } - public void setImageOverlay(TLObject image, Object parentObject) { - overlayImageView.setImage(image, image != null ? String.format(Locale.US, "%d_%d", circleRadius * 2, circleRadius * 2) : null, null, null, parentObject, 1); + public void setImageOverlay(TLRPC.PhotoSize image, TLRPC.Document document, Object parentObject) { + overlayImageView.setImage(ImageLocation.getForDocument(image, document), String.format(Locale.US, "%d_%d", circleRadius * 2, circleRadius * 2), null, null, parentObject, 1); } public void setImageOverlay(String url) { @@ -231,7 +232,7 @@ public class RadialProgress2 { int prevIcon = mediaActionDrawable.getPreviousIcon(); float wholeAlpha; - if ((currentIcon == MediaActionDrawable.ICON_CHECK || currentIcon == MediaActionDrawable.ICON_EMPTY) && prevIcon == MediaActionDrawable.ICON_NONE) { + if ((currentIcon == MediaActionDrawable.ICON_CANCEL || currentIcon == MediaActionDrawable.ICON_CHECK || currentIcon == MediaActionDrawable.ICON_EMPTY || currentIcon == MediaActionDrawable.ICON_GIF || currentIcon == MediaActionDrawable.ICON_PLAY) && prevIcon == MediaActionDrawable.ICON_NONE) { wholeAlpha = mediaActionDrawable.getTransitionProgress(); } else { wholeAlpha = currentIcon != MediaActionDrawable.ICON_NONE ? 1.0f : 1.0f - mediaActionDrawable.getTransitionProgress(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgressView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgressView.java index 0c2a7703a..0aaec16e2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgressView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgressView.java @@ -13,7 +13,7 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.drawable.Drawable; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.view.View; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadioButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadioButton.java index b4bada73d..42679ccfd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadioButton.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadioButton.java @@ -16,7 +16,7 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.view.View; import org.telegram.messenger.AndroidUtilities; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java index aba36452e..4ed854f24 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java @@ -8,6 +8,7 @@ package org.telegram.ui.Components; +import android.annotation.SuppressLint; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; @@ -31,11 +32,10 @@ import android.view.SoundEffectConstants; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.messenger.FileLog; import org.telegram.ui.ActionBar.Theme; @@ -43,6 +43,9 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class RecyclerListView extends RecyclerView { private OnItemClickListener onItemClickListener; @@ -57,6 +60,8 @@ public class RecyclerListView extends RecyclerView { private FastScroll fastScroll; private SectionsAdapter sectionsAdapter; + private boolean disableHighlightState; + private Drawable pinnedHeaderShadowDrawable; private float pinnedHeaderShadowAlpha; private float pinnedHeaderShadowTargetAlpha; @@ -93,6 +98,9 @@ public class RecyclerListView extends RecyclerView { private boolean scrollEnabled = true; + private IntReturnCallback pendingHighlightPosition; + private Runnable removeHighlighSelectionRunnable; + private static int[] attributes; private static boolean gotAttributes; @@ -133,6 +141,10 @@ public class RecyclerListView extends RecyclerView { public abstract int getPositionForScrollProgress(float progress); } + public interface IntReturnCallback { + int run(); + } + public abstract static class SectionsAdapter extends FastScrollAdapter { private SparseIntArray sectionPositionCache; @@ -496,7 +508,7 @@ public class RecyclerListView extends RecyclerView { private class RecyclerListViewItemClickListener implements OnItemTouchListener { public RecyclerListViewItemClickListener(Context context) { - gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { + gestureDetector = new GestureDetector(context, new GestureDetector.OnGestureListener() { @Override public boolean onSingleTapUp(MotionEvent e) { if (currentChildView != null && (onItemClickListener != null || onItemClickListenerExtended != null)) { @@ -507,10 +519,11 @@ public class RecyclerListView extends RecyclerView { final float y = e.getY(); if (instantClick && position != -1) { view.playSoundEffect(SoundEffectConstants.CLICK); + view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); if (onItemClickListener != null) { onItemClickListener.onItemClick(view, position); } else if (onItemClickListenerExtended != null) { - onItemClickListenerExtended.onItemClick(view, position, x, y); + onItemClickListenerExtended.onItemClick(view, position, x - view.getX(), y - view.getY()); } } AndroidUtilities.runOnUIThread(clickRunnable = new Runnable() { @@ -523,11 +536,12 @@ public class RecyclerListView extends RecyclerView { onChildPressed(view, false); if (!instantClick) { view.playSoundEffect(SoundEffectConstants.CLICK); + view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); if (position != -1) { if (onItemClickListener != null) { onItemClickListener.onItemClick(view, position); } else if (onItemClickListenerExtended != null) { - onItemClickListenerExtended.onItemClick(view, position, x, y); + onItemClickListenerExtended.onItemClick(view, position, x - view.getX(), y - view.getY()); } } } @@ -556,14 +570,36 @@ public class RecyclerListView extends RecyclerView { if (onItemLongClickListener != null) { if (onItemLongClickListener.onItemClick(currentChildView, currentChildPosition)) { child.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + child.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); } } else if (onItemLongClickListenerExtended != null) { - if (onItemLongClickListenerExtended.onItemClick(currentChildView, currentChildPosition, event.getX(), event.getY())) { + if (onItemLongClickListenerExtended.onItemClick(currentChildView, currentChildPosition, event.getX() - currentChildView.getX(), event.getY() - currentChildView.getY())) { child.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + child.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); longPressCalled = true; } } } + + @Override + public boolean onDown(MotionEvent e) { + return false; + } + + @Override + public void onShowPress(MotionEvent e) { + + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + return false; + } + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + return false; + } }); gestureDetector.setIsLongpressEnabled(false); } @@ -578,7 +614,7 @@ public class RecyclerListView extends RecyclerView { float ey = event.getY(); longPressCalled = false; if (allowSelectChildAtPosition(ex, ey)) { - currentChildView = view.findChildViewUnder(ex, ey); + currentChildView = findChildViewUnder(ex, ey); } if (currentChildView instanceof ViewGroup) { float x = event.getX() - currentChildView.getLeft(); @@ -629,7 +665,7 @@ public class RecyclerListView extends RecyclerView { positionSelector(currentChildPosition, currentChildView); if (selectorDrawable != null) { final Drawable d = selectorDrawable.getCurrent(); - if (d != null && d instanceof TransitionDrawable) { + if (d instanceof TransitionDrawable) { if (onItemLongClickListener != null || onItemClickListenerExtended != null) { ((TransitionDrawable) d).startTransition(ViewConfiguration.getLongPressTimeout()); } else { @@ -677,11 +713,37 @@ public class RecyclerListView extends RecyclerView { } } + @Override + public View findChildViewUnder(float x, float y) { + final int count = getChildCount(); + for (int a = 0; a < 2; a++) { + for (int i = count - 1; i >= 0; i--) { + final View child = getChildAt(i); + final float translationX = a == 0 ? child.getTranslationX() : 0; + final float translationY = a == 0 ? child.getTranslationY() : 0; + if (x >= child.getLeft() + translationX + && x <= child.getRight() + translationX + && y >= child.getTop() + translationY + && y <= child.getBottom() + translationY) { + return child; + } + } + } + return null; + } + + public void setDisableHighlightState(boolean value) { + disableHighlightState = value; + } + protected View getPressedChildView() { return currentChildView; } protected void onChildPressed(View child, boolean pressed) { + if (disableHighlightState) { + return; + } child.setPressed(pressed); } @@ -697,7 +759,7 @@ public class RecyclerListView extends RecyclerView { positionSelector(currentChildPosition, pressedChild); if (selectorDrawable != null) { Drawable d = selectorDrawable.getCurrent(); - if (d != null && d instanceof TransitionDrawable) { + if (d instanceof TransitionDrawable) { ((TransitionDrawable) d).resetTransition(); } if (event != null && Build.VERSION.SDK_INT >= 21) { @@ -735,7 +797,9 @@ public class RecyclerListView extends RecyclerView { public void onChanged() { checkIfEmpty(); currentFirst = -1; - selectorRect.setEmpty(); + if (removeHighlighSelectionRunnable == null) { + selectorRect.setEmpty(); + } invalidate(); } @@ -762,6 +826,7 @@ public class RecyclerListView extends RecyclerView { return null; } + @SuppressLint("PrivateApi") public RecyclerListView(Context context) { super(context); @@ -857,6 +922,9 @@ public class RecyclerListView extends RecyclerView { selfOnLayout = false; } checkSection(); + if (pendingHighlightPosition != null) { + highlightRowInternal(pendingHighlightPosition, false); + } } public void checkSection() { @@ -892,10 +960,7 @@ public class RecyclerListView extends RecyclerView { sectionsCount = 1; startSection = sectionsAdapter.getSectionForPosition(firstVisibleItem); int itemNum = firstVisibleItem + sectionsAdapter.getCountForSection(startSection) - sectionsAdapter.getPositionInSectionForPosition(firstVisibleItem); - while (true) { - if (itemNum >= firstVisibleItem + visibleItemCount) { - break; - } + while (itemNum < firstVisibleItem + visibleItemCount) { itemNum += sectionsAdapter.getCountForSection(startSection + sectionsCount); sectionsCount++; } @@ -1051,6 +1116,10 @@ public class RecyclerListView extends RecyclerView { onItemClickListenerExtended = listener; } + public OnItemClickListener getOnItemClickListener() { + return onItemClickListener; + } + public void setOnItemLongClickListener(OnItemLongClickListener listener) { onItemLongClickListener = listener; gestureDetector.setIsLongpressEnabled(listener != null); @@ -1099,6 +1168,54 @@ public class RecyclerListView extends RecyclerView { scrollEnabled = value; } + public void highlightRow(RecyclerListView.IntReturnCallback callback) { + highlightRowInternal(callback, true); + } + + private void highlightRowInternal(RecyclerListView.IntReturnCallback callback, boolean canHighlightLater) { + if (removeHighlighSelectionRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(removeHighlighSelectionRunnable); + removeHighlighSelectionRunnable = null; + } + RecyclerView.ViewHolder holder = findViewHolderForAdapterPosition(callback.run()); + if (holder != null) { + positionSelector(holder.getLayoutPosition(), holder.itemView); + if (selectorDrawable != null) { + final Drawable d = selectorDrawable.getCurrent(); + if (d instanceof TransitionDrawable) { + if (onItemLongClickListener != null || onItemClickListenerExtended != null) { + ((TransitionDrawable) d).startTransition(ViewConfiguration.getLongPressTimeout()); + } else { + ((TransitionDrawable) d).resetTransition(); + } + } + if (Build.VERSION.SDK_INT >= 21) { + selectorDrawable.setHotspot(holder.itemView.getMeasuredWidth() / 2, holder.itemView.getMeasuredHeight() / 2); + } + } + if (selectorDrawable != null && selectorDrawable.isStateful()) { + if (selectorDrawable.setState(getDrawableStateForSelector())) { + invalidateDrawable(selectorDrawable); + } + } + AndroidUtilities.runOnUIThread(removeHighlighSelectionRunnable = () -> { + removeHighlighSelectionRunnable = null; + pendingHighlightPosition = null; + if (selectorDrawable != null) { + Drawable d = selectorDrawable.getCurrent(); + if (d instanceof TransitionDrawable) { + ((TransitionDrawable) d).resetTransition(); + } + } + if (selectorDrawable != null && selectorDrawable.isStateful()) { + selectorDrawable.setState(StateSet.NOTHING); + } + }, 700); + } else if (canHighlightLater) { + pendingHighlightPosition = callback; + } + } + @Override public boolean onInterceptTouchEvent(MotionEvent e) { if (!isEnabled()) { @@ -1181,6 +1298,11 @@ public class RecyclerListView extends RecyclerView { } private void positionSelector(int position, View sel, boolean manageHotspot, float x, float y) { + if (removeHighlighSelectionRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(removeHighlighSelectionRunnable); + removeHighlighSelectionRunnable = null; + pendingHighlightPosition = null; + } if (selectorDrawable == null) { return; } @@ -1217,13 +1339,22 @@ public class RecyclerListView extends RecyclerView { } } + public void hideSelector() { + if (currentChildView != null) { + View child = currentChildView; + onChildPressed(currentChildView, false); + currentChildView = null; + removeSelection(child, null); + } + } + private void updateSelectorState() { if (selectorDrawable != null && selectorDrawable.isStateful()) { if (currentChildView != null) { if (selectorDrawable.setState(getDrawableStateForSelector())) { invalidateDrawable(selectorDrawable); } - } else { + } else if (removeHighlighSelectionRunnable == null) { selectorDrawable.setState(StateSet.NOTHING); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScamDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScamDrawable.java new file mode 100644 index 000000000..ac5026397 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScamDrawable.java @@ -0,0 +1,79 @@ +package org.telegram.ui.Components; + +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.text.TextPaint; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; + +public class ScamDrawable extends Drawable { + + private RectF rect = new RectF(); + private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + private int textWidth; + private String text; + + public ScamDrawable(int textSize) { + super(); + textPaint.setTextSize(AndroidUtilities.dp(textSize)); + textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(AndroidUtilities.dp(1)); + + text = LocaleController.getString("ScamMessage", R.string.ScamMessage); + textWidth = (int) Math.ceil(textPaint.measureText(text)); + } + + public void checkText() { + String newText = LocaleController.getString("ScamMessage", R.string.ScamMessage); + if (!newText.equals(text)) { + text = newText; + textWidth = (int) Math.ceil(textPaint.measureText(text)); + } + } + + public void setColor(int color) { + textPaint.setColor(color); + paint.setColor(color); + } + + @Override + public void setAlpha(int alpha) { + + } + + @Override + public int getIntrinsicWidth() { + return textWidth + AndroidUtilities.dp(5 * 2); + } + + @Override + public int getIntrinsicHeight() { + return AndroidUtilities.dp(16); + } + + @Override + public void draw(Canvas canvas) { + rect.set(getBounds()); + canvas.drawRoundRect(rect, AndroidUtilities.dp(2), AndroidUtilities.dp(2), paint); + canvas.drawText(text, rect.left + AndroidUtilities.dp(5), rect.top + AndroidUtilities.dp(12), textPaint); + } + + @Override + public void setColorFilter(ColorFilter colorFilter) { + + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java index 5fecd621f..5d24acb48 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java @@ -13,9 +13,11 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.drawable.Drawable; +import android.os.SystemClock; import android.util.TypedValue; import android.view.Gravity; import android.view.View; +import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.HorizontalScrollView; import android.widget.ImageView; @@ -24,7 +26,9 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.R; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; @@ -35,12 +39,19 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { } private LinearLayout.LayoutParams defaultTabLayoutParams; + private LinearLayout.LayoutParams defaultExpandLayoutParams; private LinearLayout tabsContainer; private ScrollSlidingTabStripDelegate delegate; + private boolean shouldExpand; + private int tabCount; private int currentPosition; + private boolean animateFromPosition; + private float startAnimationPosition; + private float positionAnimationProgress; + private long lastAnimationTime; private Paint rectPaint; @@ -72,6 +83,7 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { rectPaint.setStyle(Style.FILL); defaultTabLayoutParams = new LinearLayout.LayoutParams(AndroidUtilities.dp(52), LayoutHelper.MATCH_PARENT); + defaultExpandLayoutParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1.0F); } public void setDelegate(ScrollSlidingTabStripDelegate scrollSlidingTabStripDelegate) { @@ -82,6 +94,7 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { tabsContainer.removeAllViews(); tabCount = 0; currentPosition = 0; + animateFromPosition = false; } public void selectTab(int num) { @@ -119,7 +132,7 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { return textView; } - public void addIconTab(Drawable drawable) { + public ImageView addIconTab(Drawable drawable) { final int position = tabCount++; ImageView tab = new ImageView(getContext()); tab.setFocusable(true); @@ -128,6 +141,8 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { tab.setOnClickListener(v -> delegate.onPageSelected(position)); tabsContainer.addView(tab); tab.setSelected(position == currentPosition); + + return tab; } public void addStickerTab(TLRPC.Chat chat) { @@ -139,25 +154,22 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { tab.setSelected(position == currentPosition); BackupImageView imageView = new BackupImageView(getContext()); imageView.setRoundRadius(AndroidUtilities.dp(15)); - TLRPC.FileLocation photo = null; AvatarDrawable avatarDrawable = new AvatarDrawable(); - if (chat.photo != null) { - photo = chat.photo.photo_small; - } avatarDrawable.setTextSize(AndroidUtilities.dp(14)); avatarDrawable.setInfo(chat); - imageView.setImage(photo, "50_50", avatarDrawable, chat); + imageView.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, chat); imageView.setAspectFit(true); tab.addView(imageView, LayoutHelper.createFrame(30, 30, Gravity.CENTER)); } - public void addStickerTab(TLRPC.Document sticker, Object parentObject) { + public View addStickerTab(TLObject thumb, TLRPC.Document sticker, Object parentObject) { final int position = tabCount++; FrameLayout tab = new FrameLayout(getContext()); - tab.setTag(sticker); + tab.setTag(thumb); tab.setTag(R.id.parent_tag, parentObject); + tab.setTag(R.id.object_tag, sticker); tab.setFocusable(true); tab.setOnClickListener(v -> delegate.onPageSelected(position)); tabsContainer.addView(tab); @@ -165,12 +177,18 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { BackupImageView imageView = new BackupImageView(getContext()); imageView.setAspectFit(true); tab.addView(imageView, LayoutHelper.createFrame(30, 30, Gravity.CENTER)); + + return tab; } public void updateTabStyles() { for (int i = 0; i < tabCount; i++) { View v = tabsContainer.getChildAt(i); - v.setLayoutParams(defaultTabLayoutParams); + if (shouldExpand) { + v.setLayoutParams(defaultExpandLayoutParams); + } else { + v.setLayoutParams(defaultTabLayoutParams); + } } } @@ -209,13 +227,19 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { View child = tabsContainer.getChildAt(a); Object object = child.getTag(); Object parentObject = child.getTag(R.id.parent_tag); - if (!(object instanceof TLRPC.Document)) { + TLRPC.Document sticker = (TLRPC.Document) child.getTag(R.id.object_tag); + ImageLocation imageLocation; + if (object instanceof TLRPC.Document) { + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(sticker.thumbs, 90); + imageLocation = ImageLocation.getForDocument(thumb, sticker); + } else if (object instanceof TLRPC.PhotoSize) { + TLRPC.PhotoSize thumb = (TLRPC.PhotoSize) object; + imageLocation = ImageLocation.getForSticker(thumb, sticker); + } else { continue; } BackupImageView imageView = (BackupImageView) ((FrameLayout) child).getChildAt(0); - TLRPC.Document sticker = (TLRPC.Document) object; - TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(sticker.thumbs, 90); - imageView.setImage(thumb, null, "webp", null, parentObject); + imageView.setImage(imageLocation, null, "webp", null, parentObject); } } @@ -238,16 +262,22 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { } Object object = child.getTag(); Object parentObject = child.getTag(R.id.parent_tag); - if (!(object instanceof TLRPC.Document)) { + TLRPC.Document sticker = (TLRPC.Document) child.getTag(R.id.object_tag); + ImageLocation imageLocation; + if (object instanceof TLRPC.Document) { + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(sticker.thumbs, 90); + imageLocation = ImageLocation.getForDocument(thumb, sticker); + } else if (object instanceof TLRPC.PhotoSize) { + TLRPC.PhotoSize thumb = (TLRPC.PhotoSize) object; + imageLocation = ImageLocation.getForSticker(thumb, sticker); + } else { continue; } BackupImageView imageView = (BackupImageView) ((FrameLayout) child).getChildAt(0); if (a < newStart || a >= newStart + count) { imageView.setImageDrawable(null); } else { - TLRPC.Document sticker = (TLRPC.Document) object; - TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(sticker.thumbs, 90); - imageView.setImage(thumb, null, "webp", null, parentObject); + imageView.setImage(imageLocation, null, "webp", null, parentObject); } } } @@ -262,37 +292,75 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { final int height = getHeight(); - rectPaint.setColor(underlineColor); - canvas.drawRect(0, height - underlineHeight, tabsContainer.getWidth(), height, rectPaint); - - View currentTab = tabsContainer.getChildAt(currentPosition); - float lineLeft = 0; - float lineRight = 0; - if (currentTab != null) { - lineLeft = currentTab.getLeft(); - lineRight = currentTab.getRight(); + if (underlineHeight > 0) { + rectPaint.setColor(underlineColor); + canvas.drawRect(0, height - underlineHeight, tabsContainer.getWidth(), height, rectPaint); } - rectPaint.setColor(indicatorColor); - if (indicatorHeight == 0) { - canvas.drawRect(lineLeft, 0, lineRight, height, rectPaint); - } else { - canvas.drawRect(lineLeft, height - indicatorHeight, lineRight, height, rectPaint); + if (indicatorHeight >= 0) { + View currentTab = tabsContainer.getChildAt(currentPosition); + float lineLeft = 0; + int width = 0; + if (currentTab != null) { + lineLeft = currentTab.getLeft(); + width = currentTab.getMeasuredWidth(); + } + if (animateFromPosition) { + long newTime = SystemClock.uptimeMillis(); + long dt = newTime - lastAnimationTime; + lastAnimationTime = newTime; + + positionAnimationProgress += dt / 150.0f; + if (positionAnimationProgress >= 1.0f) { + positionAnimationProgress = 1.0f; + animateFromPosition = false; + } + lineLeft = startAnimationPosition + (lineLeft - startAnimationPosition) * CubicBezierInterpolator.EASE_OUT_QUINT.getInterpolation(positionAnimationProgress); + invalidate(); + } + + rectPaint.setColor(indicatorColor); + if (indicatorHeight == 0) { + canvas.drawRect(lineLeft, 0, lineLeft + width, height, rectPaint); + } else { + canvas.drawRect(lineLeft, height - indicatorHeight, lineLeft + width, height, rectPaint); + } } } + public void setShouldExpand(boolean value) { + shouldExpand = value; + requestLayout(); + } + public int getCurrentPosition() { return currentPosition; } + public void cancelPositionAnimation() { + animateFromPosition = false; + positionAnimationProgress = 1.0f; + } + public void onPageScrolled(int position, int first) { if (currentPosition == position) { return; } + + View currentTab = tabsContainer.getChildAt(currentPosition); + if (currentTab != null) { + startAnimationPosition = currentTab.getLeft(); + positionAnimationProgress = 0.0f; + animateFromPosition = true; + lastAnimationTime = SystemClock.uptimeMillis(); + } else { + animateFromPosition = false; + } currentPosition = position; if (position >= tabsContainer.getChildCount()) { return; } + positionAnimationProgress = 0.0f; for (int a = 0; a < tabsContainer.getChildCount(); a++) { tabsContainer.getChildAt(a).setSelected(a == position); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java index cd067c39a..aa9ae66ef 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java @@ -11,10 +11,11 @@ package org.telegram.ui.Components; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Paint.Style; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; import android.os.SystemClock; -import android.support.annotation.Keep; +import androidx.annotation.Keep; +import android.text.Layout; import android.util.SparseIntArray; import android.util.TypedValue; import android.view.Gravity; @@ -41,7 +42,6 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { private int tabCount; private int currentPosition; private int selectedTabId = -1; - private Paint rectPaint; private int allTextWidth; private int indicatorX; @@ -56,6 +56,8 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { private boolean animatingIndicator; private float animationIdicatorProgress; + private GradientDrawable selectorDrawable; + private CubicBezierInterpolator interpolator = CubicBezierInterpolator.EASE_OUT_QUINT; private SparseIntArray positionToId = new SparseIntArray(5); @@ -97,6 +99,11 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { public ScrollSlidingTextTabStrip(Context context) { super(context); + selectorDrawable = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, null); + float rad = AndroidUtilities.dpf2(3); + selectorDrawable.setCornerRadii(new float[]{rad, rad, rad, rad, 0, 0, 0, 0}); + selectorDrawable.setColor(Theme.getColor(Theme.key_actionBarDefaultTitle)); + setFillViewport(true); setWillNotDraw(false); @@ -105,11 +112,6 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { tabsContainer.setOrientation(LinearLayout.HORIZONTAL); tabsContainer.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); addView(tabsContainer); - - rectPaint = new Paint(); - rectPaint.setAntiAlias(true); - rectPaint.setStyle(Style.FILL); - rectPaint.setColor(Theme.getColor(Theme.key_actionBarDefaultTitle)); } public void setDelegate(ScrollSlidingTabStripDelegate scrollSlidingTabStripDelegate) { @@ -158,8 +160,8 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { useSameWidth = value; } - public Paint getRectPaint() { - return rectPaint; + public Drawable getSelectorDrawable() { + return selectorDrawable; } public View getTabsContainer() { @@ -205,7 +207,7 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { TextView tab = new TextView(getContext()); tab.setGravity(Gravity.CENTER); tab.setText(text); - tab.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarDefaultSelector), 2)); + tab.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarDefaultSelector), 3)); tab.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); tab.setSingleLine(true); tab.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); @@ -230,8 +232,9 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { animateIndicatorStartX = indicatorX; animateIndicatorStartWidth = indicatorWidth; - animateIndicatorToX = v.getLeft(); - animateIndicatorToWidth = v.getMeasuredWidth(); + TextView nextChild = (TextView) v; + animateIndicatorToWidth = getChildWidth(nextChild); + animateIndicatorToX = nextChild.getLeft() + (nextChild.getMeasuredWidth() - animateIndicatorToWidth) / 2; setEnabled(false); AndroidUtilities.runOnUIThread(animationRunnable, 16); @@ -273,7 +276,8 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { boolean result = super.drawChild(canvas, child, drawingTime); if (child == tabsContainer) { final int height = getMeasuredHeight(); - canvas.drawRect(indicatorX, height - AndroidUtilities.dp(2), indicatorX + indicatorWidth, height, rectPaint); + selectorDrawable.setBounds(indicatorX, height - AndroidUtilities.dpr(4), indicatorX + indicatorWidth, height); + selectorDrawable.draw(canvas); } return result; } @@ -309,7 +313,7 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { if (tabCount == 0) { return; } - View child = tabsContainer.getChildAt(position); + TextView child = (TextView) tabsContainer.getChildAt(position); if (child == null) { return; } @@ -337,10 +341,10 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { delegate.onPageScrolled(1.0f); } } - View child = tabsContainer.getChildAt(currentPosition); + TextView child = (TextView) tabsContainer.getChildAt(currentPosition); if (child != null) { - indicatorX = child.getLeft(); - indicatorWidth = child.getMeasuredWidth(); + indicatorWidth = getChildWidth(child); + indicatorX = child.getLeft() + (child.getMeasuredWidth() - indicatorWidth) / 2; } } } @@ -372,10 +376,10 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { TextView child = (TextView) tabsContainer.getChildAt(currentPosition); TextView nextChild = (TextView) tabsContainer.getChildAt(position); if (child != null && nextChild != null) { - animateIndicatorStartX = child.getLeft(); - animateIndicatorStartWidth = child.getMeasuredWidth(); - animateIndicatorToX = nextChild.getLeft(); - animateIndicatorToWidth = nextChild.getMeasuredWidth(); + animateIndicatorStartWidth = getChildWidth(child); + animateIndicatorStartX = child.getLeft() + (child.getMeasuredWidth() - animateIndicatorStartWidth) / 2; + animateIndicatorToWidth = getChildWidth(nextChild); + animateIndicatorToX = nextChild.getLeft() + (nextChild.getMeasuredWidth() - animateIndicatorToWidth) / 2; setAnimationProgressInernal(nextChild, child, progress); } if (progress >= 1.0f) { @@ -384,6 +388,15 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { } } + private int getChildWidth(TextView child) { + Layout layout = child.getLayout(); + if (layout != null) { + return (int) Math.ceil(layout.getLineWidth(0)) + AndroidUtilities.dp(2); + } else { + return child.getMeasuredWidth(); + } + } + public void onPageScrolled(int position, int first) { if (currentPosition == position) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarWaveform.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarWaveform.java index fa81a5660..9e7b284ed 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarWaveform.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarWaveform.java @@ -116,7 +116,7 @@ public class SeekBarWaveform { } public void setProgress(float progress) { - thumbX = (int)Math.ceil(width * progress); + thumbX = (int) Math.ceil(width * progress); if (thumbX < 0) { thumbX = 0; } else if (thumbX > width) { 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 03973a305..984ca2804 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java @@ -15,25 +15,31 @@ import android.animation.ObjectAnimator; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; +import android.graphics.Color; +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.InputType; +import android.text.TextPaint; import android.text.TextUtils; import android.text.TextWatcher; import android.util.LongSparseArray; import android.util.TypedValue; import android.view.Gravity; +import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.ViewOutlineProvider; import android.view.animation.DecelerateInterpolator; +import android.view.animation.OvershootInterpolator; import android.view.inputmethod.EditorInfo; import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; @@ -51,8 +57,7 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.support.widget.GridLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; +import org.telegram.messenger.Utilities; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.NativeByteBuffer; import org.telegram.tgnet.TLObject; @@ -65,20 +70,18 @@ import org.telegram.ui.DialogsActivity; import java.util.ArrayList; import java.util.Collections; import java.util.Locale; -import java.util.Timer; -import java.util.TimerTask; + +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; public class ShareAlert extends BottomSheet implements NotificationCenter.NotificationCenterDelegate { private FrameLayout frameLayout; private FrameLayout frameLayout2; - private TextView doneButtonBadgeTextView; - private TextView doneButtonTextView; - private LinearLayout doneButton; - private EditTextBoldCursor nameTextView; - private EditTextBoldCursor commentTextView; - private View shadow; - private View shadow2; + private EditTextEmoji commentTextView; + private FrameLayout writeButtonContainer; + private View selectedCountView; + private TextView pickerBottomLayout; private AnimatorSet animatorSet; private RecyclerListView gridView; private GridLayoutManager layoutManager; @@ -88,7 +91,13 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi private String sendingText; private EmptyTextProgressView searchEmptyView; private Drawable shadowDrawable; - private LongSparseArray selectedDialogs = new LongSparseArray<>(); + private View[] shadow = new View[2]; + private AnimatorSet[] shadowAnimation = new AnimatorSet[2]; + private LongSparseArray selectedDialogs = new LongSparseArray<>(); + + private RectF rect = new RectF(); + private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); private int currentAccount = UserConfig.selectedAccount; @@ -96,14 +105,136 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi private boolean loadingLink; private boolean copyLinkOnEnd; - private boolean isPublicChannel; + private boolean isChannel; private String linkToCopy; private int scrollOffsetY; private int topBeforeSwitch; + private class SearchField extends FrameLayout { - public static ShareAlert createShareAlert(final Context context, MessageObject messageObject, final String text, boolean publicChannel, final String copyLink, boolean fullScreen) { + 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); + searchBackground.setBackgroundDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(18), Theme.getColor(Theme.key_dialogSearchBackground))); + addView(searchBackground, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 14, 11, 14, 0)); + + searchIconImageView = new ImageView(context); + searchIconImageView.setScaleType(ImageView.ScaleType.CENTER); + searchIconImageView.setImageResource(R.drawable.smiles_inputsearch); + searchIconImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogSearchIcon), PorterDuff.Mode.MULTIPLY)); + addView(searchIconImageView, LayoutHelper.createFrame(36, 36, Gravity.LEFT | Gravity.TOP, 16, 11, 0, 0)); + + clearSearchImageView = new ImageView(context); + clearSearchImageView.setScaleType(ImageView.ScaleType.CENTER); + clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2()); + progressDrawable.setSide(AndroidUtilities.dp(7)); + clearSearchImageView.setScaleX(0.1f); + clearSearchImageView.setScaleY(0.1f); + clearSearchImageView.setAlpha(0.0f); + clearSearchImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogSearchIcon), PorterDuff.Mode.MULTIPLY)); + addView(clearSearchImageView, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP, 14, 11, 14, 0)); + clearSearchImageView.setOnClickListener(v -> { + searchEditText.setText(""); + AndroidUtilities.showKeyboard(searchEditText); + }); + + searchEditText = new EditTextBoldCursor(context) { + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + MotionEvent e = MotionEvent.obtain(event); + e.setLocation(e.getRawX(), e.getRawY() - containerView.getTranslationY()); + gridView.dispatchTouchEvent(e); + e.recycle(); + return super.dispatchTouchEvent(event); + } + }; + searchEditText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + searchEditText.setHintTextColor(Theme.getColor(Theme.key_dialogSearchHint)); + searchEditText.setTextColor(Theme.getColor(Theme.key_dialogSearchText)); + searchEditText.setBackgroundDrawable(null); + searchEditText.setPadding(0, 0, 0, 0); + searchEditText.setMaxLines(1); + searchEditText.setLines(1); + searchEditText.setSingleLine(true); + searchEditText.setImeOptions(EditorInfo.IME_ACTION_SEARCH | EditorInfo.IME_FLAG_NO_EXTRACT_UI); + searchEditText.setHint(LocaleController.getString("ShareSendTo", R.string.ShareSendTo)); + searchEditText.setCursorColor(Theme.getColor(Theme.key_featuredStickers_addedIcon)); + searchEditText.setCursorSize(AndroidUtilities.dp(20)); + searchEditText.setCursorWidth(1.5f); + addView(searchEditText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 40, Gravity.LEFT | Gravity.TOP, 16 + 38, 9, 16 + 30, 0)); + searchEditText.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) { + boolean show = searchEditText.length() > 0; + boolean showed = clearSearchImageView.getAlpha() != 0; + if (show != showed) { + clearSearchImageView.animate() + .alpha(show ? 1.0f : 0.0f) + .setDuration(150) + .scaleX(show ? 1.0f : 0.1f) + .scaleY(show ? 1.0f : 0.1f) + .start(); + } + String text = searchEditText.getText().toString(); + if (text.length() != 0) { + if (searchEmptyView != null) { + searchEmptyView.setText(LocaleController.getString("NoResult", R.string.NoResult)); + } + } else { + if (gridView.getAdapter() != listAdapter) { + int top = getCurrentTop(); + searchEmptyView.setText(LocaleController.getString("NoChats", R.string.NoChats)); + searchEmptyView.showTextView(); + gridView.setAdapter(listAdapter); + listAdapter.notifyDataSetChanged(); + if (top > 0) { + layoutManager.scrollToPositionWithOffset(0, -top); + } + } + } + if (searchAdapter != null) { + searchAdapter.searchDialogs(text); + } + } + }); + searchEditText.setOnEditorActionListener((v, actionId, event) -> { + if (event != null && (event.getAction() == KeyEvent.ACTION_UP && event.getKeyCode() == KeyEvent.KEYCODE_SEARCH || event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) { + AndroidUtilities.hideKeyboard(searchEditText); + } + return false; + }); + } + + public void hideKeyboard() { + AndroidUtilities.hideKeyboard(searchEditText); + } + + @Override + public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { + super.requestDisallowInterceptTouchEvent(disallowIntercept); + } + } + + public static ShareAlert createShareAlert(final Context context, MessageObject messageObject, final String text, boolean channel, final String copyLink, boolean fullScreen) { ArrayList arrayList; if (messageObject != null) { arrayList = new ArrayList<>(); @@ -111,23 +242,23 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi } else { arrayList = null; } - return new ShareAlert(context, arrayList, text, publicChannel, copyLink, fullScreen); + return new ShareAlert(context, arrayList, text, channel, copyLink, fullScreen); } - public ShareAlert(final Context context, ArrayList messages, final String text, boolean publicChannel, final String copyLink, boolean fullScreen) { - super(context, true); + public ShareAlert(final Context context, ArrayList messages, final String text, boolean channel, final String copyLink, boolean fullScreen) { + super(context, true, 1); - shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow).mutate(); + shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow_round).mutate(); shadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); - this.fullscreen = fullScreen; + isFullscreen = fullScreen; linkToCopy = copyLink; sendingMessageObjects = messages; searchAdapter = new ShareSearchAdapter(context); - isPublicChannel = publicChannel; + isChannel = channel; sendingText = text; - if (publicChannel) { + if (channel) { loadingLink = true; TLRPC.TL_channels_exportMessageLink req = new TLRPC.TL_channels_exportMessageLink(); req.id = messages.get(0).getId(); @@ -143,13 +274,162 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi })); } - containerView = new FrameLayout(context) { + + SizeNotifierFrameLayout sizeNotifierFrameLayout = new SizeNotifierFrameLayout(context) { private boolean ignoreLayout = false; + private RectF rect1 = new RectF(); + private boolean fullHeight; + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int totalHeight = MeasureSpec.getSize(heightMeasureSpec); + if (Build.VERSION.SDK_INT >= 21 && !fullScreen) { + ignoreLayout = true; + setPadding(backgroundPaddingLeft, AndroidUtilities.statusBarHeight, backgroundPaddingLeft, 0); + ignoreLayout = false; + } + int availableHeight = totalHeight - getPaddingTop(); + int keyboardSize = getKeyboardHeight(); + if (!AndroidUtilities.isInMultiwindow && keyboardSize <= AndroidUtilities.dp(20)) { + availableHeight -= commentTextView.getEmojiPadding(); + } + + int size = Math.max(searchAdapter.getItemCount(), listAdapter.getItemCount()); + int contentSize = AndroidUtilities.dp(48) + Math.max(3, (int) Math.ceil(size / 4.0f)) * AndroidUtilities.dp(103) + backgroundPaddingTop; + int padding = (contentSize < availableHeight ? 0 : availableHeight - (availableHeight / 5 * 3)) + AndroidUtilities.dp(8); + if (gridView.getPaddingTop() != padding) { + ignoreLayout = true; + gridView.setPadding(0, padding, 0, AndroidUtilities.dp(48)); + ignoreLayout = false; + } + fullHeight = contentSize >= totalHeight; + onMeasureInternal(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Math.min(contentSize, totalHeight), MeasureSpec.EXACTLY)); + } + + private void onMeasureInternal(int widthMeasureSpec, int heightMeasureSpec) { + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + setMeasuredDimension(widthSize, heightSize); + widthSize -= backgroundPaddingLeft * 2; + + int keyboardSize = getKeyboardHeight(); + if (keyboardSize <= AndroidUtilities.dp(20)) { + if (!AndroidUtilities.isInMultiwindow) { + heightSize -= commentTextView.getEmojiPadding(); + heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY); + } + ignoreLayout = true; + int visibility = commentTextView.isPopupShowing() ? GONE : VISIBLE; + if (pickerBottomLayout != null) { + pickerBottomLayout.setVisibility(visibility); + shadow[1].setAlpha(frameLayout2.getVisibility() == VISIBLE || visibility == VISIBLE ? 1.0f : 0.0f); + } + ignoreLayout = false; + } else { + ignoreLayout = true; + commentTextView.hideEmojiView(); + if (pickerBottomLayout != null) { + pickerBottomLayout.setVisibility(GONE); + shadow[1].setAlpha(frameLayout2.getVisibility() == VISIBLE ? 1.0f : 0.0f); + } + 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) { + 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() - backgroundPaddingLeft; + 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(); + updateLayout(); + } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { - if (ev.getAction() == MotionEvent.ACTION_DOWN && scrollOffsetY != 0 && ev.getY() < scrollOffsetY) { + if (ev.getAction() == MotionEvent.ACTION_DOWN && scrollOffsetY != 0 && ev.getY() < scrollOffsetY - AndroidUtilities.dp(30)) { dismiss(); return true; } @@ -161,29 +441,6 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi return !isDismissed() && super.onTouchEvent(e); } - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int height = MeasureSpec.getSize(heightMeasureSpec); - if (Build.VERSION.SDK_INT >= 21 && !fullScreen) { - height -= AndroidUtilities.statusBarHeight; - } - int size = Math.max(searchAdapter.getItemCount(), listAdapter.getItemCount()); - int contentSize = AndroidUtilities.dp(48) + Math.max(3, (int) Math.ceil(size / 4.0f)) * AndroidUtilities.dp(100) + backgroundPaddingTop; - int padding = contentSize < height ? 0 : height - (height / 5 * 3) + AndroidUtilities.dp(8); - if (gridView.getPaddingTop() != padding) { - ignoreLayout = true; - gridView.setPadding(0, padding, 0, AndroidUtilities.dp(frameLayout2.getTag() != null ? 56 : 8)); - ignoreLayout = false; - } - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Math.min(contentSize, height), MeasureSpec.EXACTLY)); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - updateLayout(); - } - @Override public void requestLayout() { if (ignoreLayout) { @@ -194,137 +451,81 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi @Override protected void onDraw(Canvas canvas) { - shadowDrawable.setBounds(0, scrollOffsetY - backgroundPaddingTop, getMeasuredWidth(), getMeasuredHeight()); + int y = scrollOffsetY - backgroundPaddingTop + AndroidUtilities.dp(6); + int top = scrollOffsetY - backgroundPaddingTop - AndroidUtilities.dp(13); + int height = getMeasuredHeight() + AndroidUtilities.dp(30) + backgroundPaddingTop; + int statusBarHeight = 0; + float radProgress = 1.0f; + if (!fullScreen && Build.VERSION.SDK_INT >= 21) { + top += AndroidUtilities.statusBarHeight; + y += AndroidUtilities.statusBarHeight; + height -= AndroidUtilities.statusBarHeight; + + if (fullHeight) { + if (top + backgroundPaddingTop < AndroidUtilities.statusBarHeight * 2) { + int diff = Math.min(AndroidUtilities.statusBarHeight, AndroidUtilities.statusBarHeight * 2 - top - backgroundPaddingTop); + top -= diff; + height += diff; + radProgress = 1.0f - Math.min(1.0f, (diff * 2) / (float) AndroidUtilities.statusBarHeight); + } + if (top + backgroundPaddingTop < AndroidUtilities.statusBarHeight) { + statusBarHeight = Math.min(AndroidUtilities.statusBarHeight, AndroidUtilities.statusBarHeight - top - backgroundPaddingTop); + } + } + } + + shadowDrawable.setBounds(0, top, getMeasuredWidth(), height); shadowDrawable.draw(canvas); + + if (radProgress != 1.0f) { + Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_dialogBackground)); + rect1.set(backgroundPaddingLeft, backgroundPaddingTop + top, getMeasuredWidth() - backgroundPaddingLeft, backgroundPaddingTop + top + AndroidUtilities.dp(24)); + canvas.drawRoundRect(rect1, AndroidUtilities.dp(12) * radProgress, AndroidUtilities.dp(12) * radProgress, Theme.dialogs_onlineCirclePaint); + } + + int w = AndroidUtilities.dp(36); + rect1.set((getMeasuredWidth() - w) / 2, y, (getMeasuredWidth() + w) / 2, y + AndroidUtilities.dp(4)); + Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_sheet_scrollUp)); + canvas.drawRoundRect(rect1, AndroidUtilities.dp(2), AndroidUtilities.dp(2), Theme.dialogs_onlineCirclePaint); + + if (statusBarHeight > 0) { + int color1 = Theme.getColor(Theme.key_dialogBackground); + int finalColor = Color.argb(0xff, (int) (Color.red(color1) * 0.8f), (int) (Color.green(color1) * 0.8f), (int) (Color.blue(color1) * 0.8f)); + Theme.dialogs_onlineCirclePaint.setColor(finalColor); + canvas.drawRect(backgroundPaddingLeft, AndroidUtilities.statusBarHeight - statusBarHeight, getMeasuredWidth() - backgroundPaddingLeft, AndroidUtilities.statusBarHeight, Theme.dialogs_onlineCirclePaint); + } } }; + containerView = sizeNotifierFrameLayout; containerView.setWillNotDraw(false); containerView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0); frameLayout = new FrameLayout(context); frameLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); - frameLayout.setOnTouchListener((v, event) -> true); + //frameLayout.setOnTouchListener((v, event) -> true); - doneButton = new LinearLayout(context); - doneButton.setOrientation(LinearLayout.HORIZONTAL); - doneButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_dialogButtonSelector), 0)); - doneButton.setPadding(AndroidUtilities.dp(21), 0, AndroidUtilities.dp(21), 0); - frameLayout.addView(doneButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.RIGHT)); - doneButton.setOnClickListener(v -> { - if (selectedDialogs.size() == 0 && (isPublicChannel || linkToCopy != null)) { - if (linkToCopy == null && loadingLink) { - copyLinkOnEnd = true; - Toast.makeText(ShareAlert.this.getContext(), LocaleController.getString("Loading", R.string.Loading), Toast.LENGTH_SHORT).show(); - } else { - copyLink(ShareAlert.this.getContext()); - } - dismiss(); - } else { - if (sendingMessageObjects != 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(sendingMessageObjects, key); - } - } 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(sendingText, key, null, null, true, null, null, null); - } - } - dismiss(); - } - }); + SearchField searchView = new SearchField(context); + frameLayout.addView(searchView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); - doneButtonBadgeTextView = new TextView(context); - doneButtonBadgeTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - doneButtonBadgeTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); - doneButtonBadgeTextView.setTextColor(Theme.getColor(Theme.key_dialogBadgeText)); - doneButtonBadgeTextView.setGravity(Gravity.CENTER); - doneButtonBadgeTextView.setBackgroundDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(12.5f), Theme.getColor(Theme.key_dialogBadgeBackground))); - doneButtonBadgeTextView.setMinWidth(AndroidUtilities.dp(23)); - doneButtonBadgeTextView.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), AndroidUtilities.dp(1)); - doneButton.addView(doneButtonBadgeTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 23, Gravity.CENTER_VERTICAL, 0, 0, 10, 0)); - - doneButtonTextView = new TextView(context); - doneButtonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - doneButtonTextView.setGravity(Gravity.CENTER); - doneButtonTextView.setCompoundDrawablePadding(AndroidUtilities.dp(8)); - doneButtonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - doneButton.addView(doneButtonTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL)); - - ImageView imageView = new ImageView(context); - imageView.setImageResource(R.drawable.ic_ab_search); - imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogIcon), PorterDuff.Mode.MULTIPLY)); - imageView.setScaleType(ImageView.ScaleType.CENTER); - imageView.setPadding(0, AndroidUtilities.dp(2), 0, 0); - frameLayout.addView(imageView, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.CENTER_VERTICAL)); - - nameTextView = new EditTextBoldCursor(context); - nameTextView.setHint(LocaleController.getString("ShareSendTo", R.string.ShareSendTo)); - nameTextView.setMaxLines(1); - nameTextView.setSingleLine(true); - nameTextView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); - nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - nameTextView.setBackgroundDrawable(null); - nameTextView.setHintTextColor(Theme.getColor(Theme.key_dialogTextHint)); - nameTextView.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI); - nameTextView.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES); - nameTextView.setCursorColor(Theme.getColor(Theme.key_dialogTextBlack)); - nameTextView.setCursorSize(AndroidUtilities.dp(20)); - nameTextView.setCursorWidth(1.5f); - nameTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); - frameLayout.addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 48, 2, 96, 0)); - nameTextView.addTextChangedListener(new TextWatcher() { + gridView = new RecyclerListView(context) { @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - + protected boolean allowSelectChildAtPosition(float x, float y) { + return y >= scrollOffsetY + AndroidUtilities.dp(48) + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0); } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - - } - - @Override - public void afterTextChanged(Editable s) { - String text = nameTextView.getText().toString(); - if (text.length() != 0) { - if (gridView.getAdapter() != searchAdapter) { - topBeforeSwitch = getCurrentTop(); - gridView.setAdapter(searchAdapter); - searchAdapter.notifyDataSetChanged(); - } - if (searchEmptyView != null) { - searchEmptyView.setText(LocaleController.getString("NoResult", R.string.NoResult)); - } - } else { - if (gridView.getAdapter() != listAdapter) { - int top = getCurrentTop(); - searchEmptyView.setText(LocaleController.getString("NoChats", R.string.NoChats)); - gridView.setAdapter(listAdapter); - listAdapter.notifyDataSetChanged(); - if (top > 0) { - layoutManager.scrollToPositionWithOffset(0, -top); - } - } - } - if (searchAdapter != null) { - searchAdapter.searchDialogs(text); - } - } - }); - - gridView = new RecyclerListView(context); + }; gridView.setTag(13); - gridView.setPadding(0, 0, 0, AndroidUtilities.dp(8)); + gridView.setPadding(0, 0, 0, AndroidUtilities.dp(48)); gridView.setClipToPadding(false); gridView.setLayoutManager(layoutManager = new GridLayoutManager(getContext(), 4)); + layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + if (position == 0) { + return layoutManager.getSpanCount(); + } + return 1; + } + }); gridView.setHorizontalScrollBarEnabled(false); gridView.setVerticalScrollBarEnabled(false); gridView.addItemDecoration(new RecyclerView.ItemDecoration() { @@ -341,14 +542,14 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi } } }); - containerView.addView(gridView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 48, 0, 0)); + containerView.addView(gridView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0)); gridView.setAdapter(listAdapter = new ShareDialogsAdapter(context)); gridView.setGlowColor(Theme.getColor(Theme.key_dialogScrollGlow)); gridView.setOnItemClickListener((view, position) -> { if (position < 0) { return; } - TLRPC.TL_dialog dialog; + TLRPC.Dialog dialog; if (gridView.getAdapter() == listAdapter) { dialog = listAdapter.getItem(position); } else { @@ -361,11 +562,12 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi if (selectedDialogs.indexOfKey(dialog.id) >= 0) { selectedDialogs.remove(dialog.id); cell.setChecked(false, true); + updateSelectedCount(1); } else { selectedDialogs.put(dialog.id, dialog); cell.setChecked(true, true); + updateSelectedCount(2); } - updateSelectedCount(); }); gridView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override @@ -379,45 +581,149 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi searchEmptyView.showTextView(); searchEmptyView.setText(LocaleController.getString("NoChats", R.string.NoChats)); gridView.setEmptyView(searchEmptyView); - containerView.addView(searchEmptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 48, 0, 0)); + containerView.addView(searchEmptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 52, 0, 0)); - containerView.addView(frameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); + FrameLayout.LayoutParams frameLayoutParams = new FrameLayout.LayoutParams(LayoutHelper.MATCH_PARENT, AndroidUtilities.getShadowHeight(), Gravity.TOP | Gravity.LEFT); + frameLayoutParams.topMargin = AndroidUtilities.dp(58); + shadow[0] = new View(context); + shadow[0].setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine)); + shadow[0].setAlpha(0.0f); + shadow[0].setTag(1); + containerView.addView(shadow[0], frameLayoutParams); - shadow = new View(context); - shadow.setBackgroundResource(R.drawable.header_shadow); - containerView.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.TOP | Gravity.LEFT, 0, 48, 0, 0)); + containerView.addView(frameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 58, Gravity.LEFT | Gravity.TOP)); + + frameLayoutParams = new FrameLayout.LayoutParams(LayoutHelper.MATCH_PARENT, AndroidUtilities.getShadowHeight(), Gravity.BOTTOM | Gravity.LEFT); + frameLayoutParams.bottomMargin = AndroidUtilities.dp(48); + shadow[1] = new View(context); + shadow[1].setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine)); + containerView.addView(shadow[1], frameLayoutParams); + + if (isChannel || linkToCopy != null) { + pickerBottomLayout = new TextView(context); + pickerBottomLayout.setBackgroundDrawable(Theme.createSelectorWithBackgroundDrawable(Theme.getColor(Theme.key_dialogBackground), Theme.getColor(Theme.key_listSelector))); + pickerBottomLayout.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); + pickerBottomLayout.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + pickerBottomLayout.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); + pickerBottomLayout.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + pickerBottomLayout.setGravity(Gravity.CENTER); + pickerBottomLayout.setText(LocaleController.getString("CopyLink", R.string.CopyLink).toUpperCase()); + pickerBottomLayout.setOnClickListener(v -> { + if (selectedDialogs.size() == 0 && (isChannel || linkToCopy != null)) { + if (linkToCopy == null && loadingLink) { + copyLinkOnEnd = true; + Toast.makeText(ShareAlert.this.getContext(), LocaleController.getString("Loading", R.string.Loading), Toast.LENGTH_SHORT).show(); + } else { + copyLink(ShareAlert.this.getContext()); + } + dismiss(); + } + }); + containerView.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); + } else { + shadow[1].setAlpha(0.0f); + } frameLayout2 = new FrameLayout(context); frameLayout2.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); - frameLayout2.setTranslationY(AndroidUtilities.dp(53)); + frameLayout2.setAlpha(0.0f); + frameLayout2.setVisibility(View.INVISIBLE); containerView.addView(frameLayout2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); frameLayout2.setOnTouchListener((v, event) -> true); - commentTextView = new EditTextBoldCursor(context); + commentTextView = new EditTextEmoji(context, sizeNotifierFrameLayout, null, EditTextEmoji.STYLE_DIALOG); commentTextView.setHint(LocaleController.getString("ShareComment", R.string.ShareComment)); - commentTextView.setMaxLines(1); - commentTextView.setSingleLine(true); - commentTextView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); - commentTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - commentTextView.setBackgroundDrawable(null); - commentTextView.setHintTextColor(Theme.getColor(Theme.key_dialogTextHint)); - commentTextView.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI); - commentTextView.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES); - commentTextView.setCursorColor(Theme.getColor(Theme.key_dialogTextBlack)); - commentTextView.setCursorSize(AndroidUtilities.dp(20)); - commentTextView.setCursorWidth(1.5f); - commentTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); - frameLayout2.addView(commentTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 8, 1, 8, 0)); + 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)); - shadow2 = new View(context); - shadow2.setBackgroundResource(R.drawable.header_shadow_reverse); - shadow2.setTranslationY(AndroidUtilities.dp(53)); - containerView.addView(shadow2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 48)); + 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)); + containerView.addView(writeButtonContainer, LayoutHelper.createFrame(60, 60, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 6, 10)); + writeButtonContainer.setOnClickListener(v -> { + if (sendingMessageObjects != 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(sendingMessageObjects, key); + } + } 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(sendingText, key, null, null, true, null, null, null); + } + } + dismiss(); + }); - updateSelectedCount(); + ImageView writeButton = new ImageView(context); + Drawable drawable = 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, drawable, 0, 0); + combinedDrawable.setIconSize(AndroidUtilities.dp(56), AndroidUtilities.dp(56)); + drawable = combinedDrawable; + } + writeButton.setBackgroundDrawable(drawable); + 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, selectedDialogs.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); + containerView.addView(selectedCountView, LayoutHelper.createFrame(42, 24, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, -8, 9)); + + updateSelectedCount(0); if (!DialogsActivity.dialogsLoaded[currentAccount]) { - MessagesController.getInstance(currentAccount).loadDialogs(0, 100, true); + MessagesController.getInstance(currentAccount).loadDialogs(0, 0, 100, true); ContactsController.getInstance(currentAccount).checkInviteText(); DialogsActivity.dialogsLoaded[currentAccount] = true; } @@ -437,6 +743,22 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi return -1000; } + @Override + public void dismissInternal() { + super.dismissInternal(); + if (commentTextView != null) { + commentTextView.onDestroy(); + } + } + + @Override + public void onBackPressed() { + if (commentTextView != null && commentTextView.isPopupShowing()) { + commentTextView.hidePopup(true); + return; + } + super.onBackPressed(); + } @Override public void didReceivedNotification(int id, int account, Object... args) { @@ -462,15 +784,54 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi RecyclerListView.Holder holder = (RecyclerListView.Holder) gridView.findContainingViewHolder(child); int top = child.getTop() - AndroidUtilities.dp(8); int newOffset = top > 0 && holder != null && holder.getAdapterPosition() == 0 ? top : 0; + if (top >= 0 && holder != null && holder.getAdapterPosition() == 0) { + newOffset = top; + runShadowAnimation(0, false); + } else { + runShadowAnimation(0, true); + } if (scrollOffsetY != newOffset) { gridView.setTopGlowOffset(scrollOffsetY = newOffset); frameLayout.setTranslationY(scrollOffsetY); - shadow.setTranslationY(scrollOffsetY); searchEmptyView.setTranslationY(scrollOffsetY); containerView.invalidate(); } } + private void runShadowAnimation(final int num, final boolean show) { + if (show && shadow[num].getTag() != null || !show && shadow[num].getTag() == null) { + shadow[num].setTag(show ? null : 1); + if (show) { + shadow[num].setVisibility(View.VISIBLE); + } + if (shadowAnimation[num] != null) { + shadowAnimation[num].cancel(); + } + shadowAnimation[num] = new AnimatorSet(); + shadowAnimation[num].playTogether(ObjectAnimator.ofFloat(shadow[num], View.ALPHA, show ? 1.0f : 0.0f)); + shadowAnimation[num].setDuration(150); + shadowAnimation[num].addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (shadowAnimation[num] != null && shadowAnimation[num].equals(animation)) { + if (!show) { + shadow[num].setVisibility(View.INVISIBLE); + } + shadowAnimation[num] = null; + } + } + + @Override + public void onAnimationCancel(Animator animation) { + if (shadowAnimation[num] != null && shadowAnimation[num].equals(animation)) { + shadowAnimation[num] = null; + } + } + }); + shadowAnimation[num].start(); + } + } + private void copyLink(Context context) { if (exportedMessageLink == null && linkToCopy == null) { return; @@ -479,32 +840,56 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); android.content.ClipData clip = android.content.ClipData.newPlainText("label", linkToCopy != null ? linkToCopy : exportedMessageLink.link); clipboard.setPrimaryClip(clip); - Toast.makeText(context, LocaleController.getString("LinkCopied", R.string.LinkCopied), Toast.LENGTH_SHORT).show(); + if (exportedMessageLink != null && exportedMessageLink.link.contains("/c/")) { + Toast.makeText(ApplicationLoader.applicationContext, LocaleController.getString("LinkCopiedPrivate", R.string.LinkCopiedPrivate), Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(ApplicationLoader.applicationContext, LocaleController.getString("LinkCopied", R.string.LinkCopied), Toast.LENGTH_SHORT).show(); + } } catch (Exception e) { FileLog.e(e); } } - private void showCommentTextView(final boolean show) { + private boolean showCommentTextView(final boolean show) { if (show == (frameLayout2.getTag() != null)) { - return; + return false; } if (animatorSet != null) { animatorSet.cancel(); } frameLayout2.setTag(show ? 1 : null); - AndroidUtilities.hideKeyboard(commentTextView); + if (commentTextView.getEditText().isFocused()) { + AndroidUtilities.hideKeyboard(commentTextView.getEditText()); + } + commentTextView.hidePopup(true); + if (show) { + frameLayout2.setVisibility(View.VISIBLE); + writeButtonContainer.setVisibility(View.VISIBLE); + } animatorSet = new AnimatorSet(); - animatorSet.playTogether( - ObjectAnimator.ofFloat(shadow2, "translationY", AndroidUtilities.dp(show ? 0 : 53)), - ObjectAnimator.ofFloat(frameLayout2, "translationY", AndroidUtilities.dp(show ? 0 : 53))); + ArrayList animators = new ArrayList<>(); + animators.add(ObjectAnimator.ofFloat(frameLayout2, View.ALPHA, show ? 1.0f : 0.0f)); + 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)); + if (pickerBottomLayout == null || pickerBottomLayout.getVisibility() != View.VISIBLE) { + animators.add(ObjectAnimator.ofFloat(shadow[1], View.ALPHA, show ? 1.0f : 0.0f)); + } + + animatorSet.playTogether(animators); animatorSet.setInterpolator(new DecelerateInterpolator()); animatorSet.setDuration(180); animatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (animation.equals(animatorSet)) { - gridView.setPadding(0, 0, 0, AndroidUtilities.dp(show ? 56 : 8)); + if (!show) { + frameLayout2.setVisibility(View.INVISIBLE); + writeButtonContainer.setVisibility(View.INVISIBLE); + } animatorSet = null; } } @@ -517,34 +902,38 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi } }); animatorSet.start(); + return true; } - public void updateSelectedCount() { + public void updateSelectedCount(int animated) { if (selectedDialogs.size() == 0) { + selectedCountView.setPivotX(0); + selectedCountView.setPivotY(0); showCommentTextView(false); - doneButtonBadgeTextView.setVisibility(View.GONE); - if (!isPublicChannel && linkToCopy == null) { - doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray4)); - doneButton.setEnabled(false); - doneButtonTextView.setText(LocaleController.getString("Send", R.string.Send).toUpperCase()); - } else { - doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); - doneButton.setEnabled(true); - doneButtonTextView.setText(LocaleController.getString("CopyLink", R.string.CopyLink).toUpperCase()); - } } else { - showCommentTextView(true); - doneButtonTextView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); - doneButtonBadgeTextView.setVisibility(View.VISIBLE); - doneButtonBadgeTextView.setText(String.format("%d", selectedDialogs.size())); - doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue3)); - doneButton.setEnabled(true); - doneButtonTextView.setText(LocaleController.getString("Send", R.string.Send).toUpperCase()); + selectedCountView.invalidate(); + if (animated != 0 && !showCommentTextView(true)) { + 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); + } } } @Override public void dismiss() { + if (commentTextView != null) { + AndroidUtilities.hideKeyboard(commentTextView.getEditText()); + } super.dismiss(); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.dialogsNeedReload); } @@ -553,7 +942,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi private Context context; private int currentCount; - private ArrayList dialogs = new ArrayList<>(); + private ArrayList dialogs = new ArrayList<>(); public ShareDialogsAdapter(Context context) { this.context = context; @@ -566,8 +955,12 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi if (!MessagesController.getInstance(currentAccount).dialogsForward.isEmpty()) { dialogs.add(MessagesController.getInstance(currentAccount).dialogsForward.get(0)); } - for (int a = 0; a < MessagesController.getInstance(currentAccount).dialogs.size(); a++) { - TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogs.get(a); + ArrayList allDialogs = MessagesController.getInstance(currentAccount).getAllDialogs(); + for (int a = 0; a < allDialogs.size(); a++) { + TLRPC.Dialog dialog = allDialogs.get(a); + if (!(dialog instanceof TLRPC.TL_dialog)) { + continue; + } int lower_id = (int) dialog.id; if (lower_id == selfUserId) { continue; @@ -589,37 +982,62 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi @Override public int getItemCount() { - return dialogs.size(); + int count = dialogs.size(); + if (count != 0) { + count++; + } + return count; } - public TLRPC.TL_dialog getItem(int i) { - if (i < 0 || i >= dialogs.size()) { + public TLRPC.Dialog getItem(int position) { + position--; + if (position < 0 || position >= dialogs.size()) { return null; } - return dialogs.get(i); + return dialogs.get(position); } @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { + if (holder.getItemViewType() == 1) { + return false; + } return true; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view = new ShareDialogCell(context); - view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(100))); + View view; + switch (viewType) { + case 0: { + view = new ShareDialogCell(context); + view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(100))); + break; + } + case 1: + default: { + view = new View(context); + view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(56))); + break; + } + } return new RecyclerListView.Holder(view); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { - ShareDialogCell cell = (ShareDialogCell) holder.itemView; - TLRPC.TL_dialog dialog = getItem(position); - cell.setDialog((int) dialog.id, selectedDialogs.indexOfKey(dialog.id) >= 0, null); + if (holder.getItemViewType() == 0) { + ShareDialogCell cell = (ShareDialogCell) holder.itemView; + TLRPC.Dialog dialog = getItem(position); + cell.setDialog((int) dialog.id, selectedDialogs.indexOfKey(dialog.id) >= 0, null); + } } @Override - public int getItemViewType(int i) { + public int getItemViewType(int position) { + if (position == 0) { + return 1; + } return 0; } } @@ -627,15 +1045,15 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi public class ShareSearchAdapter extends RecyclerListView.SelectionAdapter { private Context context; - private Timer searchTimer; private ArrayList searchResult = new ArrayList<>(); + private Runnable searchRunnable; private String lastSearchText; - private int reqId = 0; + private int reqId; private int lastReqId; - private int lastSearchId = 0; + private int lastSearchId; private class DialogSearchResult { - public TLRPC.TL_dialog dialog = new TLRPC.TL_dialog(); + public TLRPC.Dialog dialog = new TLRPC.TL_dialog(); public TLObject object; public int date; public CharSequence name; @@ -658,7 +1076,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi if (search1.equals(search2) || search2.length() == 0) { search2 = null; } - String search[] = new String[1 + (search2 != null ? 1 : 0)]; + String[] search = new String[1 + (search2 != null ? 1 : 0)]; search[0] = search1; if (search2 != null) { search[1] = search2; @@ -843,6 +1261,11 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi if (searchId != lastSearchId) { return; } + if (gridView.getAdapter() != searchAdapter) { + topBeforeSwitch = getCurrentTop(); + gridView.setAdapter(searchAdapter); + searchAdapter.notifyDataSetChanged(); + } for (int a = 0; a < result.size(); a++) { DialogSearchResult obj = result.get(a); if (obj.object instanceof TLRPC.User) { @@ -864,83 +1287,89 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi layoutManager.scrollToPositionWithOffset(0, -topBeforeSwitch); topBeforeSwitch = -1000; } + searchEmptyView.showTextView(); }); } public void searchDialogs(final String query) { - if (query != null && lastSearchText != null && query.equals(lastSearchText)) { + if (query != null && query.equals(lastSearchText)) { return; } lastSearchText = query; - try { - if (searchTimer != null) { - searchTimer.cancel(); - searchTimer = null; - } - } catch (Exception e) { - FileLog.e(e); + if (searchRunnable != null) { + Utilities.searchQueue.cancelRunnable(searchRunnable); + searchRunnable = null; } if (query == null || query.length() == 0) { searchResult.clear(); topBeforeSwitch = getCurrentTop(); + lastSearchId = -1; notifyDataSetChanged(); } else { final int searchId = ++lastSearchId; - searchTimer = new Timer(); - searchTimer.schedule(new TimerTask() { - @Override - public void run() { - try { - cancel(); - searchTimer.cancel(); - searchTimer = null; - } catch (Exception e) { - FileLog.e(e); - } - searchDialogsInternal(query, searchId); - } - }, 200, 300); + searchRunnable = () -> searchDialogsInternal(query, searchId); + Utilities.globalQueue.postRunnable(searchRunnable, 300); } } @Override public int getItemCount() { - return searchResult.size(); + int count = searchResult.size(); + if (count != 0) { + count++; + } + return count; } - public TLRPC.TL_dialog getItem(int i) { - if (i < 0 || i >= searchResult.size()) { + public TLRPC.Dialog getItem(int position) { + position--; + if (position < 0 || position >= searchResult.size()) { return null; } - return searchResult.get(i).dialog; - } - - @Override - public long getItemId(int i) { - return i; + return searchResult.get(position).dialog; } @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { + if (holder.getItemViewType() == 1) { + return false; + } return true; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view = new ShareDialogCell(context); - view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(100))); + View view; + switch (viewType) { + case 0: { + view = new ShareDialogCell(context); + view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(100))); + break; + } + case 1: + default: { + view = new View(context); + view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(56))); + break; + } + } return new RecyclerListView.Holder(view); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { - ShareDialogCell cell = (ShareDialogCell) holder.itemView; - DialogSearchResult result = searchResult.get(position); - cell.setDialog((int) result.dialog.id, selectedDialogs.indexOfKey(result.dialog.id) >= 0, result.name); + if (holder.getItemViewType() == 0) { + ShareDialogCell cell = (ShareDialogCell) holder.itemView; + DialogSearchResult result = searchResult.get(position - 1); + cell.setDialog((int) result.dialog.id, selectedDialogs.indexOfKey(result.dialog.id) >= 0, result.name); + } } @Override - public int getItemViewType(int i) { + public int getItemViewType(int position) { + if (position == 0) { + return 1; + } return 0; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharingLocationsAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharingLocationsAlert.java index c82d38e3e..9bd2f8919 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharingLocationsAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharingLocationsAlert.java @@ -29,16 +29,17 @@ import org.telegram.messenger.LocationController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.SharingLiveLocationCell; -import org.telegram.ui.StickerPreviewViewer; +import org.telegram.ui.ContentPreviewViewer; import java.util.ArrayList; import java.util.regex.Pattern; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class SharingLocationsAlert extends BottomSheet implements NotificationCenter.NotificationCenterDelegate { private Pattern urlPattern; @@ -58,7 +59,7 @@ public class SharingLocationsAlert extends BottomSheet implements NotificationCe } public SharingLocationsAlert(Context context, SharingLocationsAlertDelegate sharingLocationsAlertDelegate) { - super(context, false); + super(context, false, 0); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.liveLocationsChanged); delegate = sharingLocationsAlertDelegate; @@ -134,7 +135,7 @@ public class SharingLocationsAlert extends BottomSheet implements NotificationCe listView = new RecyclerListView(context) { @Override public boolean onInterceptTouchEvent(MotionEvent event) { - boolean result = StickerPreviewViewer.getInstance().onInterceptTouchEvent(event, listView, 0, null); + boolean result = ContentPreviewViewer.getInstance().onInterceptTouchEvent(event, listView, 0, null); return super.onInterceptTouchEvent(event) || result; } @@ -158,16 +159,13 @@ public class SharingLocationsAlert extends BottomSheet implements NotificationCe updateLayout(); } }); - listView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { - @Override - public void onItemClick(View view, int position) { - position -= 1; - if (position < 0 || position >= LocationController.getLocationsCount()) { - return; - } - delegate.didSelectLocation(getLocation(position)); - dismiss(); + listView.setOnItemClickListener((view, position) -> { + position -= 1; + if (position < 0 || position >= LocationController.getLocationsCount()) { + return; } + delegate.didSelectLocation(getLocation(position)); + dismiss(); }); containerView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 48)); @@ -181,24 +179,16 @@ public class SharingLocationsAlert extends BottomSheet implements NotificationCe pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextRed)); pickerBottomLayout.cancelButton.setText(LocaleController.getString("StopAllLocationSharings", R.string.StopAllLocationSharings)); - pickerBottomLayout.cancelButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { - LocationController.getInstance(a).removeAllLocationSharings(); - } - dismiss(); + pickerBottomLayout.cancelButton.setOnClickListener(view -> { + for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { + LocationController.getInstance(a).removeAllLocationSharings(); } + dismiss(); }); pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("Close", R.string.Close).toUpperCase()); pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); - pickerBottomLayout.doneButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - dismiss(); - } - }); + pickerBottomLayout.doneButton.setOnClickListener(view -> dismiss()); pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE); adapter.notifyDataSetChanged(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShutterButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShutterButton.java index 27cbe220b..eaf3ddb74 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShutterButton.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShutterButton.java @@ -14,11 +14,14 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.drawable.Drawable; +import android.os.Build; import android.view.MotionEvent; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.DecelerateInterpolator; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; public class ShutterButton extends View { @@ -199,4 +202,16 @@ public class ShutterButton extends View { invalidate(); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.Button"); + info.setClickable(true); + info.setLongClickable(true); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + info.addAction(new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.getId(), LocaleController.getString("AccActionTakePicture", R.string.AccActionTakePicture))); + info.addAction(new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK.getId(), LocaleController.getString("AccActionRecordVideo", R.string.AccActionRecordVideo))); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java index d4646900e..cd1ac3dde 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java @@ -17,6 +17,7 @@ import android.text.TextDirectionHeuristics; import android.text.TextPaint; import android.text.TextUtils; +import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLog; import java.lang.reflect.Constructor; @@ -74,6 +75,23 @@ public class StaticLayoutEx { } } + public static StaticLayout createStaticLayout2(CharSequence source, TextPaint paint, int width, Layout.Alignment align, float spacingmult, float spacingadd, boolean includepad, TextUtils.TruncateAt ellipsize, int ellipsisWidth, int maxLines) { + if (Build.VERSION.SDK_INT >= 23) { + StaticLayout.Builder builder = StaticLayout.Builder.obtain(source, 0, source.length(), paint, ellipsisWidth) + .setAlignment(align) + .setLineSpacing(spacingadd, spacingmult) + .setIncludePad(includepad) + .setEllipsize(TextUtils.TruncateAt.END) + .setEllipsizedWidth(ellipsisWidth) + .setMaxLines(maxLines) + .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY) + .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE); + return builder.build(); + } else { + return createStaticLayout(source, 0, source.length(), paint, width, align, spacingmult, spacingadd, includepad, ellipsize, ellipsisWidth, maxLines, true); + } + } + public static StaticLayout createStaticLayout(CharSequence source, TextPaint paint, int width, Layout.Alignment align, float spacingmult, float spacingadd, boolean includepad, TextUtils.TruncateAt ellipsize, int ellipsisWidth, int maxLines) { return createStaticLayout(source, 0, source.length(), paint, width, align, spacingmult, spacingadd, includepad, ellipsize, ellipsisWidth, maxLines, true); } @@ -117,6 +135,7 @@ public class StaticLayoutEx { .setIncludePad(includePad) .setEllipsize(null) .setEllipsizedWidth(ellipsisWidth) + .setMaxLines(maxLines) .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY) .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE); layout = builder.build(); @@ -127,11 +146,16 @@ public class StaticLayoutEx { return layout; } else { int off; + int start; float left = layout.getLineLeft(maxLines - 1); + float lineWidth = layout.getLineWidth(maxLines - 1); if (left != 0) { off = layout.getOffsetForHorizontal(maxLines - 1, left); } else { - off = layout.getOffsetForHorizontal(maxLines - 1, layout.getLineWidth(maxLines - 1)); + off = layout.getOffsetForHorizontal(maxLines - 1, lineWidth); + } + if (lineWidth < ellipsisWidth - AndroidUtilities.dp(10)) { + off += 3; } SpannableStringBuilder stringBuilder = new SpannableStringBuilder(source.subSequence(0, Math.max(0, off - 3))); stringBuilder.append("\u2026"); @@ -140,8 +164,9 @@ public class StaticLayoutEx { .setAlignment(align) .setLineSpacing(spacingAdd, spacingMult) .setIncludePad(includePad) - .setEllipsize(null) + .setEllipsize(TextUtils.TruncateAt.END) .setEllipsizedWidth(ellipsisWidth) + .setMaxLines(maxLines) .setBreakStrategy(canContainUrl ? StaticLayout.BREAK_STRATEGY_HIGH_QUALITY : StaticLayout.BREAK_STRATEGY_SIMPLE) .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE); return builder.build(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerMasksView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerMasksView.java index 919de3bf3..abd78c087 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerMasksView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerMasksView.java @@ -26,17 +26,18 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.support.widget.GridLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.EmptyCell; import org.telegram.ui.Cells.StickerEmojiCell; -import org.telegram.ui.StickerPreviewViewer; +import org.telegram.ui.ContentPreviewViewer; import java.util.ArrayList; import java.util.HashMap; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + @SuppressWarnings("unchecked") public class StickerMasksView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { @@ -46,8 +47,8 @@ public class StickerMasksView extends FrameLayout implements NotificationCenter. } private int currentAccount = UserConfig.selectedAccount; - private ArrayList stickerSets[] = new ArrayList[] {new ArrayList<>(), new ArrayList<>()}; - private ArrayList recentStickers[] = new ArrayList[] {new ArrayList<>(), new ArrayList<>()}; + private ArrayList[] stickerSets = new ArrayList[]{new ArrayList<>(), new ArrayList<>()}; + private ArrayList[] recentStickers = new ArrayList[]{new ArrayList<>(), new ArrayList<>()}; private int currentType = DataQuery.TYPE_MASK; private Listener listener; @@ -73,7 +74,7 @@ public class StickerMasksView extends FrameLayout implements NotificationCenter. stickersGridView = new RecyclerListView(context) { @Override public boolean onInterceptTouchEvent(MotionEvent event) { - boolean result = StickerPreviewViewer.getInstance().onInterceptTouchEvent(event, stickersGridView, StickerMasksView.this.getMeasuredHeight(), null); + boolean result = ContentPreviewViewer.getInstance().onInterceptTouchEvent(event, stickersGridView, StickerMasksView.this.getMeasuredHeight(), null); return super.onInterceptTouchEvent(event) || result; } }; @@ -91,12 +92,12 @@ public class StickerMasksView extends FrameLayout implements NotificationCenter. stickersGridView.setPadding(0, AndroidUtilities.dp(4), 0, 0); stickersGridView.setClipToPadding(false); stickersGridView.setAdapter(stickersGridAdapter = new StickersGridAdapter(context)); - stickersGridView.setOnTouchListener((v, event) -> StickerPreviewViewer.getInstance().onTouch(event, stickersGridView, StickerMasksView.this.getMeasuredHeight(), stickersOnItemClickListener, null)); + stickersGridView.setOnTouchListener((v, event) -> ContentPreviewViewer.getInstance().onTouch(event, stickersGridView, StickerMasksView.this.getMeasuredHeight(), stickersOnItemClickListener, null)); stickersOnItemClickListener = (view, position) -> { if (!(view instanceof StickerEmojiCell)) { return; } - StickerPreviewViewer.getInstance().reset(); + ContentPreviewViewer.getInstance().reset(); StickerEmojiCell cell = (StickerEmojiCell) view; if (cell.isDisabled()) { return; @@ -220,7 +221,8 @@ public class StickerMasksView extends FrameLayout implements NotificationCenter. } for (int a = 0; a < stickerSets[currentType].size(); a++) { TLRPC.TL_messages_stickerSet set = stickerSets[currentType].get(a); - scrollSlidingTabStrip.addStickerTab(set.documents.get(0), set); + TLRPC.Document document = set.documents.get(0); + scrollSlidingTabStrip.addStickerTab(document, document, set); } scrollSlidingTabStrip.updateTabStyles(); if (lastPosition != 0) { @@ -267,10 +269,10 @@ public class StickerMasksView extends FrameLayout implements NotificationCenter. if (stickersGridAdapter != null) { stickersGridAdapter.notifyDataSetChanged(); } - if (StickerPreviewViewer.getInstance().isVisible()) { - StickerPreviewViewer.getInstance().close(); + if (ContentPreviewViewer.getInstance().isVisible()) { + ContentPreviewViewer.getInstance().close(); } - StickerPreviewViewer.getInstance().reset(); + ContentPreviewViewer.getInstance().reset(); } public void setListener(Listener value) { @@ -321,7 +323,6 @@ public class StickerMasksView extends FrameLayout implements NotificationCenter. } } - @SuppressWarnings("unchecked") @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.stickersDidLoad) { 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 5250ccf56..4920c1d56 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java @@ -31,41 +31,44 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; -import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.DataQuery; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.FileRefController; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.GridLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.EmptyCell; import org.telegram.ui.Cells.FeaturedStickerSetInfoCell; import org.telegram.ui.Cells.StickerEmojiCell; -import org.telegram.ui.StickerPreviewViewer; +import org.telegram.ui.ContentPreviewViewer; import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class StickersAlert extends BottomSheet implements NotificationCenter.NotificationCenterDelegate { public interface StickersAlertDelegate { - void onStickerSelected(TLRPC.Document sticker, Object parent); + void onStickerSelected(TLRPC.Document sticker, Object parent, boolean clearsInputField); } public interface StickersAlertInstallDelegate { @@ -93,17 +96,17 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not private RecyclerListView gridView; private GridAdapter adapter; private TextView titleTextView; - private PickerBottomLayout pickerBottomLayout; + private ActionBarMenuItem optionsButton; + private TextView pickerBottomLayout; private FrameLayout stickerPreviewLayout; private TextView previewSendButton; - private ImageView previewFavButton; private View previewSendButtonShadow; private BackupImageView stickerImageView; private TextView stickerEmojiTextView; private RecyclerListView.OnItemClickListener stickersOnItemClickListener; private Drawable shadowDrawable; - private AnimatorSet shadowAnimation[] = new AnimatorSet[2]; - private View shadow[] = new View[2]; + private AnimatorSet[] shadowAnimation = new AnimatorSet[2]; + private View[] shadow = new View[2]; private FrameLayout emptyView; private BaseFragment parentFragment; private GridLayoutManager layoutManager; @@ -123,15 +126,17 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not private boolean ignoreLayout; private boolean showEmoji; - private StickerPreviewViewer.StickerPreviewViewerDelegate previewDelegate = new StickerPreviewViewer.StickerPreviewViewerDelegate() { + private boolean clearsInputField; + + private ContentPreviewViewer.ContentPreviewViewerDelegate previewDelegate = new ContentPreviewViewer.ContentPreviewViewerDelegate() { @Override public void sendSticker(TLRPC.Document sticker, Object parent) { - delegate.onStickerSelected(sticker, parent); + delegate.onStickerSelected(sticker, parent, clearsInputField); dismiss(); } @Override - public void openSet(TLRPC.InputStickerSet set) { + public void openSet(TLRPC.InputStickerSet set, boolean clearsInputField) { } @@ -147,7 +152,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not }; public StickersAlert(Context context, Object parentObject, TLRPC.Photo photo) { - super(context, false); + super(context, false, 1); parentActivity = (Activity) context; final TLRPC.TL_messages_getAttachedStickers req = new TLRPC.TL_messages_getAttachedStickers(); TLRPC.TL_inputStickeredMediaPhoto inputStickeredMediaPhoto = new TLRPC.TL_inputStickeredMediaPhoto(); @@ -197,7 +202,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not } public StickersAlert(Context context, BaseFragment baseFragment, TLRPC.InputStickerSet set, TLRPC.TL_messages_stickerSet loadedSet, StickersAlertDelegate stickersAlertDelegate) { - super(context, false); + super(context, false, 1); delegate = stickersAlertDelegate; inputStickerSet = set; stickerSet = loadedSet; @@ -206,6 +211,14 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not init(context); } + public void setClearsInputField(boolean value) { + clearsInputField = value; + } + + public boolean isClearsInputField() { + return clearsInputField; + } + private void loadStickerSet() { if (inputStickerSet != null) { if (stickerSet == null && inputStickerSet.short_name != null) { @@ -220,6 +233,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { reqId = 0; if (error == null) { + optionsButton.setVisibility(View.VISIBLE); stickerSet = (TLRPC.TL_messages_stickerSet) response; showEmoji = !stickerSet.set.masks; updateSendButton(); @@ -242,12 +256,14 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not } private void init(Context context) { - shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow).mutate(); + shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow_round).mutate(); shadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); containerView = new FrameLayout(context) { private int lastNotifyWidth; + private RectF rect = new RectF(); + private boolean fullHeight; @Override public boolean onInterceptTouchEvent(MotionEvent ev) { @@ -267,15 +283,17 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int height = MeasureSpec.getSize(heightMeasureSpec); if (Build.VERSION.SDK_INT >= 21) { - height -= AndroidUtilities.statusBarHeight; + ignoreLayout = true; + setPadding(backgroundPaddingLeft, AndroidUtilities.statusBarHeight, backgroundPaddingLeft, 0); + ignoreLayout = false; } int measuredWidth = getMeasuredWidth(); itemSize = (MeasureSpec.getSize(widthMeasureSpec) - AndroidUtilities.dp(36)) / 5; int contentSize; if (stickerSetCovereds != null) { - contentSize = AndroidUtilities.dp(48 + 8) + AndroidUtilities.dp(60) * stickerSetCovereds.size() + adapter.stickersRowCount * AndroidUtilities.dp(82); + contentSize = AndroidUtilities.dp(48 + 8) + AndroidUtilities.dp(60) * stickerSetCovereds.size() + adapter.stickersRowCount * AndroidUtilities.dp(82) + backgroundPaddingTop + AndroidUtilities.dp(24); } else { - contentSize = AndroidUtilities.dp(48 + 48) + Math.max(3, (stickerSet != null ? (int) Math.ceil(stickerSet.documents.size() / 5.0f) : 0)) * AndroidUtilities.dp(82) + backgroundPaddingTop; + contentSize = AndroidUtilities.dp(48 + 48) + Math.max(3, (stickerSet != null ? (int) Math.ceil(stickerSet.documents.size() / 5.0f) : 0)) * AndroidUtilities.dp(82) + backgroundPaddingTop + AndroidUtilities.dp(16); } int padding = contentSize < (height / 5 * 3.2) ? 0 : (height / 5 * 2); if (padding != 0 && contentSize < height) { @@ -293,6 +311,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not emptyView.setPadding(0, padding, 0, 0); ignoreLayout = false; } + fullHeight = contentSize >= height; super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Math.min(contentSize, height), MeasureSpec.EXACTLY)); } @@ -318,24 +337,67 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not @Override protected void onDraw(Canvas canvas) { - shadowDrawable.setBounds(0, scrollOffsetY - backgroundPaddingTop, getMeasuredWidth(), getMeasuredHeight()); + int y = scrollOffsetY - backgroundPaddingTop + AndroidUtilities.dp(6); + int top = scrollOffsetY - backgroundPaddingTop - AndroidUtilities.dp(13); + int height = getMeasuredHeight() + AndroidUtilities.dp(15) + backgroundPaddingTop; + int statusBarHeight = 0; + float radProgress = 1.0f; + if (Build.VERSION.SDK_INT >= 21) { + top += AndroidUtilities.statusBarHeight; + y += AndroidUtilities.statusBarHeight; + height -= AndroidUtilities.statusBarHeight; + + if (fullHeight) { + if (top + backgroundPaddingTop < AndroidUtilities.statusBarHeight * 2) { + int diff = Math.min(AndroidUtilities.statusBarHeight, AndroidUtilities.statusBarHeight * 2 - top - backgroundPaddingTop); + top -= diff; + height += diff; + radProgress = 1.0f - Math.min(1.0f, (diff * 2) / (float) AndroidUtilities.statusBarHeight); + } + if (top + backgroundPaddingTop < AndroidUtilities.statusBarHeight) { + statusBarHeight = Math.min(AndroidUtilities.statusBarHeight, AndroidUtilities.statusBarHeight - top - backgroundPaddingTop); + } + } + } + + shadowDrawable.setBounds(0, top, getMeasuredWidth(), height); shadowDrawable.draw(canvas); + + if (radProgress != 1.0f) { + Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_dialogBackground)); + rect.set(backgroundPaddingLeft, backgroundPaddingTop + top, getMeasuredWidth() - backgroundPaddingLeft, backgroundPaddingTop + top + AndroidUtilities.dp(24)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(12) * radProgress, AndroidUtilities.dp(12) * radProgress, Theme.dialogs_onlineCirclePaint); + } + + int w = AndroidUtilities.dp(36); + rect.set((getMeasuredWidth() - w) / 2, y, (getMeasuredWidth() + w) / 2, y + AndroidUtilities.dp(4)); + Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_sheet_scrollUp)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(2), AndroidUtilities.dp(2), Theme.dialogs_onlineCirclePaint); + + if (statusBarHeight > 0) { + int color1 = Theme.getColor(Theme.key_dialogBackground); + int finalColor = Color.argb(0xff, (int) (Color.red(color1) * 0.8f), (int) (Color.green(color1) * 0.8f), (int) (Color.blue(color1) * 0.8f)); + Theme.dialogs_onlineCirclePaint.setColor(finalColor); + canvas.drawRect(backgroundPaddingLeft, AndroidUtilities.statusBarHeight - statusBarHeight, getMeasuredWidth() - backgroundPaddingLeft, AndroidUtilities.statusBarHeight, Theme.dialogs_onlineCirclePaint); + } } }; containerView.setWillNotDraw(false); containerView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0); + FrameLayout.LayoutParams frameLayoutParams = new FrameLayout.LayoutParams(LayoutHelper.MATCH_PARENT, AndroidUtilities.getShadowHeight(), Gravity.TOP | Gravity.LEFT); + frameLayoutParams.topMargin = AndroidUtilities.dp(48); shadow[0] = new View(context); - shadow[0].setBackgroundResource(R.drawable.header_shadow); + shadow[0].setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine)); shadow[0].setAlpha(0.0f); shadow[0].setVisibility(View.INVISIBLE); shadow[0].setTag(1); - containerView.addView(shadow[0], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.TOP | Gravity.LEFT, 0, 48, 0, 0)); + containerView.addView(shadow[0], frameLayoutParams); gridView = new RecyclerListView(context) { @Override public boolean onInterceptTouchEvent(MotionEvent event) { - boolean result = StickerPreviewViewer.getInstance().onInterceptTouchEvent(event, gridView, 0, previewDelegate); + boolean result = ContentPreviewViewer.getInstance().onInterceptTouchEvent(event, gridView, 0, previewDelegate); return super.onInterceptTouchEvent(event) || result; } @@ -373,7 +435,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not gridView.setClipToPadding(false); gridView.setEnabled(true); gridView.setGlowColor(Theme.getColor(Theme.key_dialogScrollGlow)); - gridView.setOnTouchListener((v, event) -> StickerPreviewViewer.getInstance().onTouch(event, gridView, 0, stickersOnItemClickListener, previewDelegate)); + gridView.setOnTouchListener((v, event) -> ContentPreviewViewer.getInstance().onTouch(event, gridView, 0, stickersOnItemClickListener, previewDelegate)); gridView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { @@ -411,21 +473,15 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not if (!set) { stickerEmojiTextView.setText(Emoji.replaceEmoji(DataQuery.getInstance(currentAccount).getEmojiForSticker(selectedSticker.id), stickerEmojiTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(30), false)); } - boolean fav = DataQuery.getInstance(currentAccount).isStickerInFavorites(selectedSticker); - previewFavButton.setImageResource(fav ? R.drawable.stickers_unfavorite : R.drawable.stickers_favorite); - previewFavButton.setTag(fav ? 1 : null); - if (previewFavButton.getVisibility() != View.GONE) { - previewFavButton.setVisibility(fav || DataQuery.getInstance(currentAccount).canAddStickerToFavorites() ? View.VISIBLE : View.INVISIBLE); - } TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(selectedSticker.thumbs, 90); - stickerImageView.getImageReceiver().setImage(selectedSticker, null, thumb, null, "webp", stickerSet, 1); + stickerImageView.getImageReceiver().setImage(ImageLocation.getForDocument(selectedSticker), null, ImageLocation.getForDocument(thumb, selectedSticker), null, "webp", stickerSet, 1); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) stickerPreviewLayout.getLayoutParams(); layoutParams.topMargin = scrollOffsetY; stickerPreviewLayout.setLayoutParams(layoutParams); stickerPreviewLayout.setVisibility(View.VISIBLE); AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.playTogether(ObjectAnimator.ofFloat(stickerPreviewLayout, "alpha", 0.0f, 1.0f)); + animatorSet.playTogether(ObjectAnimator.ofFloat(stickerPreviewLayout, View.ALPHA, 0.0f, 1.0f)); animatorSet.setDuration(200); animatorSet.start(); } @@ -453,28 +509,42 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); titleTextView.setLinkTextColor(Theme.getColor(Theme.key_dialogTextLink)); titleTextView.setHighlightColor(Theme.getColor(Theme.key_dialogLinkSelection)); - titleTextView.setEllipsize(TextUtils.TruncateAt.MIDDLE); + titleTextView.setEllipsize(TextUtils.TruncateAt.END); titleTextView.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); titleTextView.setGravity(Gravity.CENTER_VERTICAL); titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - containerView.addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 50)); + containerView.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 50, Gravity.LEFT | Gravity.TOP, 0, 0, 40, 0)); + + optionsButton = new ActionBarMenuItem(context, null, 0, Theme.getColor(Theme.key_sheet_other)); + optionsButton.setLongClickEnabled(false); + optionsButton.setSubMenuOpenSide(2); + optionsButton.setIcon(R.drawable.ic_ab_other); + optionsButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_player_actionBarSelector), 1)); + containerView.addView(optionsButton, LayoutHelper.createFrame(40, 40, Gravity.TOP | Gravity.RIGHT, 0, 5, 5, 0)); + optionsButton.addSubItem(1, R.drawable.msg_shareout, LocaleController.getString("StickersShare", R.string.StickersShare)); + optionsButton.addSubItem(2, R.drawable.msg_link, LocaleController.getString("CopyLink", R.string.CopyLink)); + optionsButton.setOnClickListener(v -> optionsButton.toggleSubMenu()); + optionsButton.setDelegate(this::onSubItemClick); + optionsButton.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); + optionsButton.setVisibility(inputStickerSet != null ? View.VISIBLE : View.GONE); RadialProgressView progressView = new RadialProgressView(context); emptyView.addView(progressView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); + frameLayoutParams = new FrameLayout.LayoutParams(LayoutHelper.MATCH_PARENT, AndroidUtilities.getShadowHeight(), Gravity.BOTTOM | Gravity.LEFT); + frameLayoutParams.bottomMargin = AndroidUtilities.dp(48); shadow[1] = new View(context); - shadow[1].setBackgroundResource(R.drawable.header_shadow_reverse); - containerView.addView(shadow[1], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 48)); + shadow[1].setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine)); + containerView.addView(shadow[1], frameLayoutParams); - pickerBottomLayout = new PickerBottomLayout(context, false); - pickerBottomLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); + pickerBottomLayout = new TextView(context); + pickerBottomLayout.setBackgroundDrawable(Theme.createSelectorWithBackgroundDrawable(Theme.getColor(Theme.key_dialogBackground), Theme.getColor(Theme.key_listSelector))); + pickerBottomLayout.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); + pickerBottomLayout.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + pickerBottomLayout.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); + pickerBottomLayout.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + pickerBottomLayout.setGravity(Gravity.CENTER); containerView.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); - pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); - pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); - pickerBottomLayout.cancelButton.setText(LocaleController.getString("Close", R.string.Close).toUpperCase()); - pickerBottomLayout.cancelButton.setOnClickListener(view -> dismiss()); - pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); - pickerBottomLayout.doneButtonBadgeTextView.setBackgroundDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(12.5f), Theme.getColor(Theme.key_dialogBadgeBackground))); stickerPreviewLayout = new FrameLayout(context); stickerPreviewLayout.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground) & 0xdfffffff); @@ -483,13 +553,6 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not containerView.addView(stickerPreviewLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); stickerPreviewLayout.setOnClickListener(v -> hidePreview()); - ImageView closeButton = new ImageView(context); - closeButton.setImageResource(R.drawable.msg_panel_clear); - closeButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogTextGray3), PorterDuff.Mode.MULTIPLY)); - closeButton.setScaleType(ImageView.ScaleType.CENTER); - stickerPreviewLayout.addView(closeButton, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP)); - closeButton.setOnClickListener(v -> hidePreview()); - stickerImageView = new BackupImageView(context); stickerImageView.setAspectFit(true); stickerPreviewLayout.addView(stickerImageView); @@ -508,28 +571,16 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not 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); + delegate.onStickerSelected(selectedSticker, stickerSet, clearsInputField); dismiss(); }); - previewFavButton = new ImageView(context); - previewFavButton.setScaleType(ImageView.ScaleType.CENTER); - stickerPreviewLayout.addView(previewFavButton, LayoutHelper.createFrame(48, 48, Gravity.BOTTOM | Gravity.RIGHT, 0, 0, 4, 0)); - previewFavButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogIcon), PorterDuff.Mode.MULTIPLY)); - previewFavButton.setOnClickListener(v -> { - DataQuery.getInstance(currentAccount).addRecentSticker(DataQuery.TYPE_FAVE, stickerSet, selectedSticker, (int) (System.currentTimeMillis() / 1000), previewFavButton.getTag() != null); - if (previewFavButton.getTag() == null) { - previewFavButton.setTag(1); - previewFavButton.setImageResource(R.drawable.stickers_unfavorite); - } else { - previewFavButton.setTag(null); - previewFavButton.setImageResource(R.drawable.stickers_favorite); - } - }); - + frameLayoutParams = new FrameLayout.LayoutParams(LayoutHelper.MATCH_PARENT, AndroidUtilities.getShadowHeight(), Gravity.BOTTOM | Gravity.LEFT); + frameLayoutParams.bottomMargin = AndroidUtilities.dp(48); previewSendButtonShadow = new View(context); - previewSendButtonShadow.setBackgroundResource(R.drawable.header_shadow_reverse); - stickerPreviewLayout.addView(previewSendButtonShadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 48)); + previewSendButtonShadow.setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine)); + stickerPreviewLayout.addView(previewSendButtonShadow, frameLayoutParams); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiDidLoad); updateFields(); @@ -544,14 +595,12 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not stickerImageView.setLayoutParams(LayoutHelper.createFrame(size, size, Gravity.CENTER, 0, 0, 0, 30)); stickerEmojiTextView.setLayoutParams(LayoutHelper.createFrame(size, size, Gravity.CENTER, 0, 0, 0, 30)); previewSendButton.setVisibility(View.VISIBLE); - previewFavButton.setVisibility(View.VISIBLE); previewSendButtonShadow.setVisibility(View.VISIBLE); } else { previewSendButton.setText(LocaleController.getString("Close", R.string.Close).toUpperCase()); stickerImageView.setLayoutParams(LayoutHelper.createFrame(size, size, Gravity.CENTER)); stickerEmojiTextView.setLayoutParams(LayoutHelper.createFrame(size, size, Gravity.CENTER)); previewSendButton.setVisibility(View.GONE); - previewFavButton.setVisibility(View.GONE); previewSendButtonShadow.setVisibility(View.GONE); } } @@ -560,6 +609,28 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not installDelegate = stickersAlertInstallDelegate; } + private void onSubItemClick(int id) { + if (stickerSet == null) { + return; + } + String stickersUrl = "https://" + MessagesController.getInstance(currentAccount).linkPrefix + "/addstickers/" + stickerSet.set.short_name; + if (id == 1) { + ShareAlert alert = new ShareAlert(getContext(), null, stickersUrl, false, stickersUrl, false); + if (parentFragment != null) { + parentFragment.showDialog(alert); + } else { + alert.show(); + } + } else if (id == 2) { + try { + AndroidUtilities.addToClipboard(stickersUrl); + Toast.makeText(ApplicationLoader.applicationContext, LocaleController.getString("LinkCopied", R.string.LinkCopied), Toast.LENGTH_SHORT).show(); + } catch (Exception e) { + FileLog.e(e); + } + } + } + private void updateFields() { if (titleTextView == null) { return; @@ -598,7 +669,13 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not titleTextView.setText(stringBuilder != null ? stringBuilder : stickerSet.set.title); if (stickerSet.set == null || !DataQuery.getInstance(currentAccount).isStickerPackInstalled(stickerSet.set.id)) { - setRightButton(v -> { + String text; + if (stickerSet.set.masks) { + text = LocaleController.formatString("AddStickersCount", R.string.AddStickersCount, LocaleController.formatPluralString("MasksCount", stickerSet.documents.size())).toUpperCase(); + } else { + text = LocaleController.formatString("AddStickersCount", R.string.AddStickersCount, LocaleController.formatPluralString("Stickers", stickerSet.documents.size())).toUpperCase(); + } + setButton(v -> { dismiss(); if (installDelegate != null) { installDelegate.onStickerSetInstalled(); @@ -628,29 +705,36 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not } DataQuery.getInstance(currentAccount).loadStickers(stickerSet.set.masks ? DataQuery.TYPE_MASK : DataQuery.TYPE_IMAGE, false, true); })); - }, stickerSet != null && stickerSet.set.masks ? LocaleController.getString("AddMasks", R.string.AddMasks) : LocaleController.getString("AddStickers", R.string.AddStickers), Theme.getColor(Theme.key_dialogTextBlue2), true); + }, text, Theme.getColor(Theme.key_dialogTextBlue2)); } else { + String text; + if (stickerSet.set.masks) { + text = LocaleController.formatString("RemoveStickersCount", R.string.RemoveStickersCount, LocaleController.formatPluralString("MasksCount", stickerSet.documents.size())).toUpperCase(); + } else { + text = LocaleController.formatString("RemoveStickersCount", R.string.RemoveStickersCount, LocaleController.formatPluralString("Stickers", stickerSet.documents.size())).toUpperCase(); + } if (stickerSet.set.official) { - setRightButton(v -> { + setButton(v -> { if (installDelegate != null) { installDelegate.onStickerSetUninstalled(); } dismiss(); DataQuery.getInstance(currentAccount).removeStickersSet(getContext(), stickerSet.set, 1, parentFragment, true); - }, LocaleController.getString("StickersRemove", R.string.StickersHide), Theme.getColor(Theme.key_dialogTextRed), false); + }, text, Theme.getColor(Theme.key_dialogTextRed)); } else { - setRightButton(v -> { + setButton(v -> { if (installDelegate != null) { installDelegate.onStickerSetUninstalled(); } dismiss(); DataQuery.getInstance(currentAccount).removeStickersSet(getContext(), stickerSet.set, 0, parentFragment, true); - }, LocaleController.getString("StickersRemove", R.string.StickersRemove), Theme.getColor(Theme.key_dialogTextRed), false); + }, text, Theme.getColor(Theme.key_dialogTextRed)); } } adapter.notifyDataSetChanged(); } else { - setRightButton(null, null, Theme.getColor(Theme.key_dialogTextRed), false); + String text = LocaleController.getString("Close", R.string.Close).toUpperCase(); + setButton((v) -> dismiss(), text, Theme.getColor(Theme.key_dialogTextBlue2)); } } @@ -665,6 +749,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not gridView.setTopGlowOffset(scrollOffsetY = gridView.getPaddingTop()); if (stickerSetCovereds == null) { titleTextView.setTranslationY(scrollOffsetY); + optionsButton.setTranslationY(scrollOffsetY); shadow[0].setTranslationY(scrollOffsetY); } containerView.invalidate(); @@ -684,6 +769,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not gridView.setTopGlowOffset(scrollOffsetY = newOffset); if (stickerSetCovereds == null) { titleTextView.setTranslationY(scrollOffsetY); + optionsButton.setTranslationY(scrollOffsetY); shadow[0].setTranslationY(scrollOffsetY); } containerView.invalidate(); @@ -692,7 +778,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not private void hidePreview() { AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.playTogether(ObjectAnimator.ofFloat(stickerPreviewLayout, "alpha", 0.0f)); + animatorSet.playTogether(ObjectAnimator.ofFloat(stickerPreviewLayout, View.ALPHA, 0.0f)); animatorSet.setDuration(200); animatorSet.addListener(new AnimatorListenerAdapter() { @Override @@ -716,7 +802,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not shadowAnimation[num].cancel(); } shadowAnimation[num] = new AnimatorSet(); - shadowAnimation[num].playTogether(ObjectAnimator.ofFloat(shadow[num], "alpha", show ? 1.0f : 0.0f)); + shadowAnimation[num].playTogether(ObjectAnimator.ofFloat(shadow[num], View.ALPHA, show ? 1.0f : 0.0f)); shadowAnimation[num].setDuration(150); shadowAnimation[num].addListener(new AnimatorListenerAdapter() { @Override @@ -760,28 +846,17 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not gridView.getChildAt(a).invalidate(); } } - if (StickerPreviewViewer.getInstance().isVisible()) { - StickerPreviewViewer.getInstance().close(); + if (ContentPreviewViewer.getInstance().isVisible()) { + ContentPreviewViewer.getInstance().close(); } - StickerPreviewViewer.getInstance().reset(); + ContentPreviewViewer.getInstance().reset(); } } - private void setRightButton(View.OnClickListener onClickListener, String title, int color, boolean showCircle) { - if (title == null) { - pickerBottomLayout.doneButton.setVisibility(View.GONE); - } else { - pickerBottomLayout.doneButton.setVisibility(View.VISIBLE); - if (showCircle) { - pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.VISIBLE); - pickerBottomLayout.doneButtonBadgeTextView.setText(String.format("%d", stickerSet.documents.size())); - } else { - pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE); - } - pickerBottomLayout.doneButtonTextView.setTextColor(color); - pickerBottomLayout.doneButtonTextView.setText(title.toUpperCase()); - pickerBottomLayout.doneButton.setOnClickListener(onClickListener); - } + private void setButton(View.OnClickListener onClickListener, String title, int color) { + pickerBottomLayout.setTextColor(color); + pickerBottomLayout.setText(title.toUpperCase()); + pickerBottomLayout.setOnClickListener(onClickListener); } private class GridAdapter extends RecyclerListView.SelectionAdapter { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersArchiveAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersArchiveAlert.java index 31b280c46..b9972eb08 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersArchiveAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersArchiveAlert.java @@ -9,7 +9,6 @@ package org.telegram.ui.Components; import android.content.Context; -import android.content.DialogInterface; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; @@ -20,8 +19,6 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DataQuery; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; @@ -31,6 +28,9 @@ import org.telegram.ui.StickersActivity; import java.util.ArrayList; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class StickersArchiveAlert extends AlertDialog.Builder { private ArrayList stickerSets; @@ -78,19 +78,11 @@ public class StickersArchiveAlert extends AlertDialog.Builder { listView.setGlowColor(0xfff5f6f7); container.addView(listView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 10, 0, 0)); - setNegativeButton(LocaleController.getString("Close", R.string.Close), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }); + setNegativeButton(LocaleController.getString("Close", R.string.Close), (dialog, which) -> dialog.dismiss()); if (parentFragment != null) { - setPositiveButton(LocaleController.getString("Settings", R.string.Settings), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - parentFragment.presentFragment(new StickersActivity(currentType)); - dialog.dismiss(); - } + setPositiveButton(LocaleController.getString("Settings", R.string.Settings), (dialog, which) -> { + parentFragment.presentFragment(new StickersActivity(currentType)); + dialog.dismiss(); }); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java index 991e910ed..66cd0f5e1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java @@ -26,9 +26,10 @@ import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.graphics.drawable.RippleDrawable; import android.os.Build; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.util.StateSet; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.ActionBar.Theme; @@ -62,7 +63,7 @@ public class Switch extends View { private boolean drawRipple; private RippleDrawable rippleDrawable; private Paint ripplePaint; - private int pressedState[] = new int[] {android.R.attr.state_enabled, android.R.attr.state_pressed}; + private int pressedState[] = new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}; private int colorSet; private boolean bitmapsCreated; @@ -148,33 +149,41 @@ public class Switch extends View { if (rippleDrawable == null) { ripplePaint = new Paint(Paint.ANTI_ALIAS_FLAG); ripplePaint.setColor(0xffffffff); - Drawable maskDrawable = new Drawable() { - @Override - public void draw(Canvas canvas) { - android.graphics.Rect bounds = getBounds(); - canvas.drawCircle(bounds.centerX(), bounds.centerY(), AndroidUtilities.dp(18), ripplePaint); - } + Drawable maskDrawable; + if (Build.VERSION.SDK_INT >= 23) { + maskDrawable = null; + } else { + maskDrawable = new Drawable() { + @Override + public void draw(Canvas canvas) { + android.graphics.Rect bounds = getBounds(); + canvas.drawCircle(bounds.centerX(), bounds.centerY(), AndroidUtilities.dp(18), ripplePaint); + } - @Override - public void setAlpha(int alpha) { + @Override + public void setAlpha(int alpha) { - } + } - @Override - public void setColorFilter(ColorFilter colorFilter) { + @Override + public void setColorFilter(ColorFilter colorFilter) { - } + } - @Override - public int getOpacity() { - return PixelFormat.UNKNOWN; - } - }; + @Override + public int getOpacity() { + return PixelFormat.UNKNOWN; + } + }; + } ColorStateList colorStateList = new ColorStateList( new int[][]{StateSet.WILD_CARD}, new int[]{0} ); rippleDrawable = new RippleDrawable(colorStateList, null, maskDrawable); + if (Build.VERSION.SDK_INT >= 23) { + rippleDrawable.setRadius(AndroidUtilities.dp(18)); + } rippleDrawable.setCallback(this); } if (isChecked && colorSet != 2 || !isChecked && colorSet != 1) { @@ -346,7 +355,7 @@ public class Switch extends View { int width = AndroidUtilities.dp(31); int thumb = AndroidUtilities.dp(20); int x = (getMeasuredWidth() - width) / 2; - int y = (getMeasuredHeight() - AndroidUtilities.dp(14)) / 2; + float y = (getMeasuredHeight() - AndroidUtilities.dpf2(14)) / 2; int tx = x + AndroidUtilities.dp(7) + (int) (AndroidUtilities.dp(17) * progress); int ty = getMeasuredHeight() / 2; @@ -411,9 +420,9 @@ public class Switch extends View { paint.setColor(color); paint2.setColor(color); - rectF.set(x, y, x + width, y + AndroidUtilities.dp(14)); - canvasToDraw.drawRoundRect(rectF, AndroidUtilities.dp(7), AndroidUtilities.dp(7), paint); - canvasToDraw.drawCircle(tx, ty, AndroidUtilities.dp(10), paint); + rectF.set(x, y, x + width, y + AndroidUtilities.dpf2(14)); + canvasToDraw.drawRoundRect(rectF, AndroidUtilities.dpf2(7), AndroidUtilities.dpf2(7), paint); + canvasToDraw.drawCircle(tx, ty, AndroidUtilities.dpf2(10), paint); if (a == 0 && rippleDrawable != null) { rippleDrawable.setBounds(tx - AndroidUtilities.dp(18), ty - AndroidUtilities.dp(18), tx + AndroidUtilities.dp(18), ty + AndroidUtilities.dp(18)); @@ -507,4 +516,13 @@ public class Switch extends View { canvas.drawBitmap(overlayBitmap[1], 0, 0, null); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.Switch"); + info.setCheckable(true); + info.setChecked(isChecked); + //info.setContentDescription(isChecked ? LocaleController.getString("NotificationsOn", R.string.NotificationsOn) : LocaleController.getString("NotificationsOff", R.string.NotificationsOff)); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TextPaintImageReceiverSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TextPaintImageReceiverSpan.java index 8f95a0b0d..546245259 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TextPaintImageReceiverSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TextPaintImageReceiverSpan.java @@ -16,6 +16,7 @@ import android.view.View; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.tgnet.TLRPC; @@ -49,7 +50,7 @@ public class TextPaintImageReceiverSpan extends ReplacementSpan { }); } TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); - imageReceiver.setImage(document, filter, thumb, filter, -1, null, parentObject, 1); + imageReceiver.setImage(ImageLocation.getForDocument(document), filter, ImageLocation.getForDocument(thumb, document), filter, -1, null, parentObject, 1); alignTop = top; } 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 77817681f..84ff516a0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeEditorView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeEditorView.java @@ -30,7 +30,10 @@ import android.graphics.Shader; import android.graphics.SweepGradient; import android.graphics.drawable.Drawable; import android.os.Build; -import android.support.annotation.Keep; +import androidx.annotation.Keep; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import android.text.Editable; import android.text.InputFilter; import android.text.InputType; @@ -53,8 +56,6 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; import org.telegram.messenger.Utilities; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarLayout; import org.telegram.ui.ActionBar.BaseFragment; @@ -157,7 +158,7 @@ public class ThemeEditorView { private Bitmap colorWheelBitmap; - private EditTextBoldCursor colorEditText[] = new EditTextBoldCursor[4]; + private EditTextBoldCursor[] colorEditText = new EditTextBoldCursor[4]; private int colorWheelRadius; @@ -348,8 +349,8 @@ public class ThemeEditorView { int colorCount = 12; int colorAngleStep = 360 / 12; - int colors[] = new int[colorCount + 1]; - float hsv[] = new float[] { 0.0f, 1.0f, 1.0f }; + 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); @@ -493,7 +494,7 @@ public class ThemeEditorView { } public EditorAlert(final Context context, ThemeDescription[] items) { - super(context, true); + super(context, true, 0); shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow).mutate(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypefaceSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypefaceSpan.java index 3fc2f53ab..ba256842d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypefaceSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypefaceSpan.java @@ -32,7 +32,9 @@ public class TypefaceSpan extends MetricAffectingSpan { public TypefaceSpan(Typeface tf, int size, int textColor) { typeface = tf; - textSize = size; + if (size > 0) { + textSize = size; + } color = textColor; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java index c13c6dbde..2f18a131c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java @@ -10,8 +10,10 @@ import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.RectF; +import android.graphics.Typeface; import android.os.SystemClock; import android.text.TextPaint; +import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; import android.view.View; @@ -21,6 +23,12 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import com.airbnb.lottie.LottieAnimationView; +import com.airbnb.lottie.LottieProperty; +import com.airbnb.lottie.SimpleColorFilter; +import com.airbnb.lottie.model.KeyPath; +import com.airbnb.lottie.value.LottieValueCallback; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; import org.telegram.messenger.LocaleController; @@ -34,8 +42,11 @@ import org.telegram.ui.ActionBar.Theme; public class UndoView extends FrameLayout { private TextView infoTextView; + private TextView subinfoTextView; private TextView undoTextView; private ImageView undoImageView; + private LottieAnimationView leftImageView; + private LinearLayout undoButton; private int currentAccount = UserConfig.selectedAccount; @@ -48,25 +59,67 @@ public class UndoView extends FrameLayout { private String timeLeftString; private int textWidth; - private boolean currentClear; + private int currentAction; private long currentDialogId; private Runnable currentActionRunnable; private Runnable currentCancelRunnable; private long lastUpdateTime; + private boolean isShowed; + + public final static int ACTION_CLEAR = 0; + public final static int ACTION_DELETE = 1; + public final static int ACTION_ARCHIVE = 2; + public final static int ACTION_ARCHIVE_HINT = 3; + public final static int ACTION_ARCHIVE_FEW = 4; + public final static int ACTION_ARCHIVE_FEW_HINT = 5; + public final static int ACTION_ARCHIVE_HIDDEN = 6; + public final static int ACTION_ARCHIVE_PINNED = 7; + public UndoView(Context context) { super(context); infoTextView = new TextView(context); infoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); infoTextView.setTextColor(Theme.getColor(Theme.key_undo_infoColor)); - addView(infoTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.LEFT, 45, 0, 0, 0)); + addView(infoTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 45, 13, 0, 0)); - LinearLayout undoButton = new LinearLayout(context); + subinfoTextView = new TextView(context); + subinfoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + subinfoTextView.setTextColor(Theme.getColor(Theme.key_undo_infoColor)); + subinfoTextView.setSingleLine(true); + subinfoTextView.setEllipsize(TextUtils.TruncateAt.END); + addView(subinfoTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 58, 27, 8, 0)); + + leftImageView = new LottieAnimationView(context); + leftImageView.setScaleType(ImageView.ScaleType.CENTER); + leftImageView.addValueCallback(new KeyPath("info1", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_undo_background) | 0xff000000))); + leftImageView.addValueCallback(new KeyPath("info2", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_undo_background) | 0xff000000))); + leftImageView.addValueCallback(new KeyPath("luc12", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_undo_infoColor)))); + leftImageView.addValueCallback(new KeyPath("luc11", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_undo_infoColor)))); + leftImageView.addValueCallback(new KeyPath("luc10", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_undo_infoColor)))); + leftImageView.addValueCallback(new KeyPath("luc9", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_undo_infoColor)))); + leftImageView.addValueCallback(new KeyPath("luc8", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_undo_infoColor)))); + leftImageView.addValueCallback(new KeyPath("luc7", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_undo_infoColor)))); + leftImageView.addValueCallback(new KeyPath("luc6", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_undo_infoColor)))); + leftImageView.addValueCallback(new KeyPath("luc5", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_undo_infoColor)))); + leftImageView.addValueCallback(new KeyPath("luc4", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_undo_infoColor)))); + leftImageView.addValueCallback(new KeyPath("luc3", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_undo_infoColor)))); + leftImageView.addValueCallback(new KeyPath("luc2", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_undo_infoColor)))); + leftImageView.addValueCallback(new KeyPath("luc1", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_undo_infoColor)))); + leftImageView.addValueCallback(new KeyPath("Oval", "**"), LottieProperty.COLOR_FILTER, new LottieValueCallback<>(new SimpleColorFilter(Theme.getColor(Theme.key_undo_infoColor)))); + addView(leftImageView, LayoutHelper.createFrame(54, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.LEFT, 3, 0, 0, 0)); + + undoButton = new LinearLayout(context); undoButton.setOrientation(LinearLayout.HORIZONTAL); addView(undoButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER_VERTICAL | Gravity.RIGHT, 0, 0, 19, 0)); - undoButton.setOnClickListener(v -> hide(false, true)); + undoButton.setOnClickListener(v -> { + if (!canUndo()) { + return; + } + hide(false, 1); + }); undoImageView = new ImageView(context); undoImageView.setImageResource(R.drawable.chats_undo); @@ -78,7 +131,6 @@ public class UndoView extends FrameLayout { undoTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); undoTextView.setTextColor(Theme.getColor(Theme.key_undo_cancelColor)); undoTextView.setText(LocaleController.getString("Undo", R.string.Undo)); - undoTextView.setCompoundDrawablePadding(AndroidUtilities.dp(6)); undoButton.addView(undoTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.LEFT, 6, 0, 0, 0)); rect = new RectF(AndroidUtilities.dp(15), AndroidUtilities.dp(15), AndroidUtilities.dp(15 + 18), AndroidUtilities.dp(15 + 18)); @@ -94,17 +146,22 @@ public class UndoView extends FrameLayout { textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); textPaint.setColor(Theme.getColor(Theme.key_undo_infoColor)); - setBackgroundColor(Theme.getColor(Theme.key_undo_background)); + setBackgroundDrawable(Theme.createRoundRectDrawable(AndroidUtilities.dp(6), Theme.getColor(Theme.key_undo_background))); setOnTouchListener((v, event) -> true); setVisibility(INVISIBLE); } - public void hide(boolean apply, boolean animated) { - if (getVisibility() != VISIBLE || currentActionRunnable == null) { + private boolean isTooltipAction() { + return currentAction == ACTION_ARCHIVE_HIDDEN || currentAction == ACTION_ARCHIVE_HINT || currentAction == ACTION_ARCHIVE_FEW_HINT || currentAction == ACTION_ARCHIVE_PINNED; + } + + public void hide(boolean apply, int animated) { + if (getVisibility() != VISIBLE || !isShowed) { return; } + isShowed = false; if (currentActionRunnable != null) { if (apply) { currentActionRunnable.run(); @@ -117,91 +174,176 @@ public class UndoView extends FrameLayout { } currentCancelRunnable = null; } - MessagesController.getInstance(currentAccount).removeDialogAction(currentDialogId, currentClear, apply); - if (animated) { + if (currentAction == ACTION_CLEAR || currentAction == ACTION_DELETE) { + MessagesController.getInstance(currentAccount).removeDialogAction(currentDialogId, currentAction == ACTION_CLEAR, apply); + } + if (animated != 0) { AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.playTogether(ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, AndroidUtilities.dp(48))); + if (animated == 1) { + animatorSet.playTogether(ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, AndroidUtilities.dp(8 + (isTooltipAction() ? 52 : 48)))); + animatorSet.setDuration(250); + } else { + animatorSet.playTogether( + ObjectAnimator.ofFloat(this, View.SCALE_X, 0.8f), + ObjectAnimator.ofFloat(this, View.SCALE_Y, 0.8f), + ObjectAnimator.ofFloat(this, View.ALPHA, 0.0f)); + animatorSet.setDuration(180); + } animatorSet.setInterpolator(new DecelerateInterpolator()); - animatorSet.setDuration(180); animatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { setVisibility(INVISIBLE); + setScaleX(1.0f); + setScaleY(1.0f); + setAlpha(1.0f); } }); animatorSet.start(); } else { - setTranslationY(AndroidUtilities.dp(48)); + setTranslationY(AndroidUtilities.dp(8 + (isTooltipAction() ? 52 : 48))); setVisibility(INVISIBLE); } } - public void showWithAction(long did, boolean clear, Runnable actionRunnable) { - showWithAction(did, clear, actionRunnable, null); + public void showWithAction(long did, int action, Runnable actionRunnable) { + showWithAction(did, action, actionRunnable, null); } - public void showWithAction(long did, boolean clear, Runnable actionRunnable, Runnable cancelRunnable) { - if (actionRunnable == null) { - return; - } - if (clear) { - infoTextView.setText(LocaleController.getString("HistoryClearedUndo", R.string.HistoryClearedUndo)); - } else { - int lowerId = (int) did; - if (lowerId < 0) { - TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lowerId); - if (ChatObject.isChannel(chat) && !chat.megagroup) { - infoTextView.setText(LocaleController.getString("ChannelDeletedUndo", R.string.ChannelDeletedUndo)); - } else { - infoTextView.setText(LocaleController.getString("GroupDeletedUndo", R.string.GroupDeletedUndo)); - } - } else { - infoTextView.setText(LocaleController.getString("ChatDeletedUndo", R.string.ChatDeletedUndo)); - } - } + public void showWithAction(long did, int action, Runnable actionRunnable, Runnable cancelRunnable) { if (currentActionRunnable != null) { currentActionRunnable.run(); } + isShowed = true; currentActionRunnable = actionRunnable; currentCancelRunnable = cancelRunnable; currentDialogId = did; - currentClear = clear; + currentAction = action; timeLeft = 5000; lastUpdateTime = SystemClock.uptimeMillis(); - MessagesController.getInstance(currentAccount).addDialogAction(did, clear); + + if (isTooltipAction()) { + if (action == ACTION_ARCHIVE_HIDDEN) { + infoTextView.setText(LocaleController.getString("ArchiveHidden", R.string.ArchiveHidden)); + subinfoTextView.setText(LocaleController.getString("ArchiveHiddenInfo", R.string.ArchiveHiddenInfo)); + leftImageView.setAnimation(R.raw.chats_swipearchive); + } else if (action == ACTION_ARCHIVE_PINNED) { + infoTextView.setText(LocaleController.getString("ArchivePinned", R.string.ArchivePinned)); + subinfoTextView.setText(LocaleController.getString("ArchivePinnedInfo", R.string.ArchivePinnedInfo)); + leftImageView.setAnimation(R.raw.chats_infotip); + } else { + if (action == ACTION_ARCHIVE_HINT) { + infoTextView.setText(LocaleController.getString("ChatArchived", R.string.ChatArchived)); + } else { + infoTextView.setText(LocaleController.getString("ChatsArchived", R.string.ChatsArchived)); + } + subinfoTextView.setText(LocaleController.getString("ChatArchivedInfo", R.string.ChatArchivedInfo)); + leftImageView.setAnimation(R.raw.chats_infotip); + } + + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) infoTextView.getLayoutParams(); + layoutParams.leftMargin = AndroidUtilities.dp(58); + layoutParams.topMargin = AndroidUtilities.dp(6); + + infoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + infoTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + subinfoTextView.setVisibility(VISIBLE); + undoButton.setVisibility(GONE); + + leftImageView.setVisibility(VISIBLE); + + leftImageView.setProgress(0); + leftImageView.playAnimation(); + } else if (currentAction == ACTION_ARCHIVE || currentAction == ACTION_ARCHIVE_FEW) { + if (action == ACTION_ARCHIVE) { + infoTextView.setText(LocaleController.getString("ChatArchived", R.string.ChatArchived)); + } else { + infoTextView.setText(LocaleController.getString("ChatsArchived", R.string.ChatsArchived)); + } + + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) infoTextView.getLayoutParams(); + layoutParams.leftMargin = AndroidUtilities.dp(58); + layoutParams.topMargin = AndroidUtilities.dp(13); + + infoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + undoButton.setVisibility(VISIBLE); + infoTextView.setTypeface(Typeface.DEFAULT); + subinfoTextView.setVisibility(GONE); + + leftImageView.setVisibility(VISIBLE); + leftImageView.setAnimation(R.raw.chats_archived); + leftImageView.setProgress(0); + leftImageView.playAnimation(); + } else { + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) infoTextView.getLayoutParams(); + layoutParams.leftMargin = AndroidUtilities.dp(45); + layoutParams.topMargin = AndroidUtilities.dp(13); + + infoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + undoButton.setVisibility(VISIBLE); + infoTextView.setTypeface(Typeface.DEFAULT); + subinfoTextView.setVisibility(GONE); + leftImageView.setVisibility(GONE); + + if (currentAction == ACTION_CLEAR) { + infoTextView.setText(LocaleController.getString("HistoryClearedUndo", R.string.HistoryClearedUndo)); + } else { + int lowerId = (int) did; + if (lowerId < 0) { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lowerId); + if (ChatObject.isChannel(chat) && !chat.megagroup) { + infoTextView.setText(LocaleController.getString("ChannelDeletedUndo", R.string.ChannelDeletedUndo)); + } else { + infoTextView.setText(LocaleController.getString("GroupDeletedUndo", R.string.GroupDeletedUndo)); + } + } else { + infoTextView.setText(LocaleController.getString("ChatDeletedUndo", R.string.ChatDeletedUndo)); + } + } + MessagesController.getInstance(currentAccount).addDialogAction(did, currentAction == ACTION_CLEAR); + } + + AndroidUtilities.makeAccessibilityAnnouncement(infoTextView.getText() + (subinfoTextView.getVisibility() == VISIBLE ? ". " + subinfoTextView.getText() : "")); + if (getVisibility() != VISIBLE) { setVisibility(VISIBLE); - setTranslationY(AndroidUtilities.dp(48)); + setTranslationY(AndroidUtilities.dp(8 + (isTooltipAction() ? 52 : 48))); AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.playTogether(ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, AndroidUtilities.dp(48), 0)); + animatorSet.playTogether(ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, AndroidUtilities.dp(8 + (isTooltipAction() ? 52 : 48)), 0)); animatorSet.setInterpolator(new DecelerateInterpolator()); animatorSet.setDuration(180); animatorSet.start(); } } + protected boolean canUndo() { + return true; + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY)); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(isTooltipAction() ? 52 : 48), MeasureSpec.EXACTLY)); } @Override protected void onDraw(Canvas canvas) { - int newSeconds = timeLeft > 0 ? (int) Math.ceil(timeLeft / 1000.0f) : 0; - if (prevSeconds != newSeconds) { - prevSeconds = newSeconds; - timeLeftString = String.format("%d", Math.max(1, newSeconds)); - textWidth = (int) Math.ceil(textPaint.measureText(timeLeftString)); + if (currentAction == ACTION_DELETE || currentAction == ACTION_CLEAR) { + int newSeconds = timeLeft > 0 ? (int) Math.ceil(timeLeft / 1000.0f) : 0; + if (prevSeconds != newSeconds) { + prevSeconds = newSeconds; + timeLeftString = String.format("%d", Math.max(1, newSeconds)); + textWidth = (int) Math.ceil(textPaint.measureText(timeLeftString)); + } + canvas.drawText(timeLeftString, rect.centerX() - textWidth / 2, AndroidUtilities.dp(28.2f), textPaint); + canvas.drawArc(rect, -90, -360 * (timeLeft / 5000.0f), false, progressPaint); } - canvas.drawText(timeLeftString, rect.centerX() - textWidth / 2, AndroidUtilities.dp(28.2f), textPaint); - canvas.drawArc(rect, -90, -360 * (timeLeft / 5000.0f), false, progressPaint); long newTime = SystemClock.uptimeMillis(); long dt = newTime - lastUpdateTime; timeLeft -= dt; lastUpdateTime = newTime; - if (timeLeft <= 0 && currentActionRunnable != null) { - hide(true, true); + if (timeLeft <= 0) { + hide(true, 1); } invalidate(); 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 8407a6a3a..2577e9213 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperUpdater.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/WallpaperUpdater.java @@ -17,7 +17,7 @@ import android.graphics.Point; import android.net.Uri; import android.os.Build; import android.provider.MediaStore; -import android.support.v4.content.FileProvider; +import androidx.core.content.FileProvider; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BuildConfig; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/WebPlayerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/WebPlayerView.java index c578d14be..3994b7ae4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/WebPlayerView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/WebPlayerView.java @@ -54,6 +54,7 @@ import org.telegram.messenger.Bitmaps; import org.telegram.messenger.BuildVars; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.R; import org.telegram.messenger.Utilities; @@ -527,7 +528,7 @@ public class WebPlayerView extends ViewGroup implements VideoPlayer.VideoPlayerD if (canRetry) { try { - if (httpConnection != null && httpConnection instanceof HttpURLConnection) { + if (httpConnection instanceof HttpURLConnection) { int code = ((HttpURLConnection) httpConnection).getResponseCode(); if (code != HttpURLConnection.HTTP_OK && code != HttpURLConnection.HTTP_ACCEPTED && code != HttpURLConnection.HTTP_NOT_MODIFIED) { //canRetry = false; @@ -2203,7 +2204,7 @@ public class WebPlayerView extends ViewGroup implements VideoPlayer.VideoPlayerD if (thumb != null) { TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(thumb.sizes, 80, true); if (photoSize != null) { - controlsView.imageReceiver.setImage(null, null, thumb, "80_80_b", 0, null, parentObject, 1); + controlsView.imageReceiver.setImage(null, null, ImageLocation.getForPhoto(photoSize, thumb), "80_80_b", 0, null, parentObject, 1); drawImage = true; } } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/CallSwipeView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/CallSwipeView.java index 619574581..de550331f 100755 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/CallSwipeView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/CallSwipeView.java @@ -17,8 +17,10 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; +import android.os.Bundle; import android.view.MotionEvent; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BuildVars; @@ -224,6 +226,20 @@ public class CallSwipeView extends View { } } + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info){ + super.onInitializeAccessibilityNodeInfo(info); + info.addAction(AccessibilityNodeInfo.ACTION_CLICK); + } + + @Override + public boolean performAccessibilityAction(int action, Bundle arguments){ + if(action==AccessibilityNodeInfo.ACTION_CLICK && isEnabled()){ + listener.onDragComplete(); + } + return super.performAccessibilityAction(action, arguments); + } + public interface Listener { void onDragComplete(); void onDragStart(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/CheckableImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/CheckableImageView.java index 796920784..6476d451b 100755 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/CheckableImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/CheckableImageView.java @@ -10,6 +10,7 @@ package org.telegram.ui.Components.voip; import android.content.Context; import android.util.AttributeSet; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.Checkable; import android.widget.ImageView; @@ -56,4 +57,11 @@ public class CheckableImageView extends ImageView implements Checkable { refreshDrawableState(); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info){ + super.onInitializeAccessibilityNodeInfo(info); + info.setCheckable(true); + info.setChecked(isChecked()); + } } \ No newline at end of file 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 541fece9b..c874daaac 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 @@ -59,7 +59,7 @@ public class VoIPHelper{ private static final int VOIP_SUPPORT_ID=4244000; - public static void startCall(TLRPC.User user, final Activity activity, TLRPC.TL_userFull userFull){ + public static void startCall(TLRPC.User user, final Activity activity, TLRPC.UserFull userFull){ if(userFull!=null && userFull.phone_calls_private){ new AlertDialog.Builder(activity) .setTitle(LocaleController.getString("VoipFailed", R.string.VoipFailed)) diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java index 027caf953..4decaa9e3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java @@ -26,6 +26,7 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.ContactsController; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.MessagesController; @@ -219,12 +220,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent } nameTextView.setText(PhoneFormat.getInstance().format("+" + user.phone)); onlineTextView.setText(LocaleController.formatUserStatus(currentAccount, user)); - - TLRPC.FileLocation photo = null; - if (user.photo != null) { - photo = user.photo.photo_small; - } - avatarImage.setImage(photo, "50_50", avatarDrawable = new AvatarDrawable(user), user); + avatarImage.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable = new AvatarDrawable(user), user); } public void didReceivedNotification(int id, int account, Object... args) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java index 62f8f3d95..c4be415d9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java @@ -30,6 +30,7 @@ import android.os.Build; import android.os.Bundle; import android.text.Editable; import android.text.InputType; +import android.text.TextUtils; import android.text.TextWatcher; import android.util.SparseArray; import android.util.TypedValue; @@ -54,8 +55,6 @@ import org.telegram.messenger.SecretChatHelper; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.ContactsController; import org.telegram.messenger.FileLog; @@ -85,6 +84,9 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class ContactsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ContactsAdapter listViewAdapter; @@ -116,7 +118,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter private boolean needForwardCount = true; private boolean needFinishFragment = true; private int channelId; - private int chat_id; + private int chatId; private String selectAlertString = null; private SparseArray ignoreUsers; private boolean allowUsernameSearch = true; @@ -138,7 +140,6 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter super(args); } - @SuppressWarnings("unchecked") @Override public boolean onFragmentCreate() { super.onFragmentCreate(); @@ -158,7 +159,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter allowBots = arguments.getBoolean("allowBots", true); channelId = arguments.getInt("channelId", 0); needFinishFragment = arguments.getBoolean("needFinishFragment", true); - chat_id = arguments.getInt("chat_id", 0); + chatId = arguments.getInt("chat_id", 0); } else { needPhonebook = true; } @@ -277,17 +278,22 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter } }); item.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); + item.setContentDescription(LocaleController.getString("Search", R.string.Search)); if (!createSecretChat && !returnAsResult) { sortItem = menu.addItem(sort_button, sortByName ? R.drawable.contacts_sort_time : R.drawable.contacts_sort_name); + sortItem.setContentDescription(LocaleController.getString("AccDescrContactSorting", R.string.AccDescrContactSorting)); } searchListViewAdapter = new SearchAdapter(context, ignoreUsers, allowUsernameSearch, false, false, allowBots, 0); - boolean inviteViaLink; - if (chat_id != 0) { - TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(chat_id); - inviteViaLink = ChatObject.canUserDoAdminAction(chat, ChatObject.ACTION_INVITE); + int inviteViaLink; + if (chatId != 0) { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(chatId); + inviteViaLink = ChatObject.canUserDoAdminAction(chat, ChatObject.ACTION_INVITE) ? 1 : 0; + } else if (channelId != 0) { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(channelId); + inviteViaLink = ChatObject.canUserDoAdminAction(chat, ChatObject.ACTION_INVITE) && TextUtils.isEmpty(chat.username) ? 2 : 0; } else { - inviteViaLink = false; + inviteViaLink = 0; } listViewAdapter = new ContactsAdapter(context, onlyUsers ? 1 : 0, needPhonebook, ignoreUsers, inviteViaLink) { @Override @@ -374,14 +380,14 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter if (row < 0 || section < 0) { return; } - if ((!onlyUsers || chat_id != 0 && inviteViaLink) && section == 0) { + if ((!onlyUsers || inviteViaLink != 0) && section == 0) { if (needPhonebook) { if (row == 0) { presentFragment(new InviteContactsActivity()); } - } else if (chat_id != 0) { + } else if (inviteViaLink != 0) { if (row == 0) { - presentFragment(new GroupInviteActivity(chat_id)); + presentFragment(new GroupInviteActivity(chatId != 0 ? chatId : channelId)); } } else { if (row == 0) { @@ -523,6 +529,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter floatingButton.setBackgroundDrawable(drawable); floatingButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_actionIcon), PorterDuff.Mode.MULTIPLY)); floatingButton.setImageResource(R.drawable.add_contact_new); + floatingButtonContainer.setContentDescription(LocaleController.getString("CreateNewContact", R.string.CreateNewContact)); if (Build.VERSION.SDK_INT >= 21) { StateListAnimator animator = new StateListAnimator(); animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(floatingButton, View.TRANSLATION_Z, AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); @@ -741,14 +748,12 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter if (grantResults.length <= a) { continue; } - switch (permissions[a]) { - case Manifest.permission.READ_CONTACTS: - if (grantResults[a] == PackageManager.PERMISSION_GRANTED) { - ContactsController.getInstance(currentAccount).forceImportContacts(); - } else { - MessagesController.getGlobalNotificationsSettings().edit().putBoolean("askAboutContacts", askAboutContacts = false).commit(); - } - break; + if (Manifest.permission.READ_CONTACTS.equals(permissions[a])) { + if (grantResults[a] == PackageManager.PERMISSION_GRANTED) { + ContactsController.getInstance(currentAccount).forceImportContacts(); + } else { + MessagesController.getGlobalNotificationsSettings().edit().putBoolean("askAboutContacts", askAboutContacts = false).commit(); + } } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java new file mode 100644 index 000000000..f56db2a9d --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java @@ -0,0 +1,805 @@ +/* + * 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.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowInsets; +import android.view.WindowManager; +import android.widget.FrameLayout; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.DataQuery; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.BottomSheet; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.ContextLinkCell; +import org.telegram.ui.Cells.StickerCell; +import org.telegram.ui.Cells.StickerEmojiCell; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RecyclerListView; + +import java.util.ArrayList; + +public class ContentPreviewViewer { + + private class FrameLayoutDrawer extends FrameLayout { + public FrameLayoutDrawer(Context context) { + super(context); + setWillNotDraw(false); + } + + @Override + protected void onDraw(Canvas canvas) { + ContentPreviewViewer.this.onDraw(canvas); + } + } + + public interface ContentPreviewViewerDelegate { + void sendSticker(TLRPC.Document sticker, Object parent); + void openSet(TLRPC.InputStickerSet set, boolean clearInputField); + boolean needSend(); + default boolean needOpen() { + return true; + } + + default void sendGif(TLRPC.Document gif) { + + } + + default void gifAddedOrDeleted() { + + } + } + + private final static int CONTENT_TYPE_NONE = -1; + private final static int CONTENT_TYPE_STICKER = 0; + private final static int CONTENT_TYPE_GIF = 1; + + private static TextPaint textPaint; + + private int startX; + private int startY; + private float lastTouchY; + private float currentMoveY; + private float moveY = 0; + private float finalMoveY; + private float startMoveY; + private boolean animateY; + private float currentMoveYProgress; + private View currentPreviewCell; + private boolean clearsInputField; + private Runnable openPreviewRunnable; + private BottomSheet visibleDialog; + private ContentPreviewViewerDelegate delegate; + + private WindowInsets lastInsets; + + private int currentAccount; + + private ColorDrawable backgroundDrawable = new ColorDrawable(0x71000000); + private Activity parentActivity; + private WindowManager.LayoutParams windowLayoutParams; + private FrameLayout windowView; + private FrameLayoutDrawer containerView; + private ImageReceiver centerImage = new ImageReceiver(); + private boolean isVisible = false; + private float showProgress; + private StaticLayout stickerEmojiLayout; + private long lastUpdateTime; + private int keyboardHeight = AndroidUtilities.dp(200); + private Drawable slideUpDrawable; + + private Runnable showSheetRunnable = new Runnable() { + @Override + public void run() { + if (parentActivity == null) { + return; + } + if (currentContentType == CONTENT_TYPE_STICKER) { + if (currentStickerSet == null) { + return; + } + final boolean inFavs = DataQuery.getInstance(currentAccount).isStickerInFavorites(currentDocument); + BottomSheet.Builder builder = new BottomSheet.Builder(parentActivity); + ArrayList items = new ArrayList<>(); + final ArrayList actions = new ArrayList<>(); + ArrayList icons = new ArrayList<>(); + if (delegate != null) { + if (delegate.needSend()) { + items.add(LocaleController.getString("SendStickerPreview", R.string.SendStickerPreview)); + icons.add(R.drawable.outline_send); + actions.add(0); + } + if (delegate.needOpen()) { + items.add(LocaleController.formatString("ViewPackPreview", R.string.ViewPackPreview)); + icons.add(R.drawable.outline_pack); + actions.add(1); + } + } + if (!MessageObject.isMaskDocument(currentDocument) && (inFavs || DataQuery.getInstance(currentAccount).canAddStickerToFavorites())) { + items.add(inFavs ? LocaleController.getString("DeleteFromFavorites", R.string.DeleteFromFavorites) : LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); + icons.add(inFavs ? R.drawable.outline_unfave : R.drawable.outline_fave); + actions.add(2); + } + if (items.isEmpty()) { + return; + } + int[] ic = new int[icons.size()]; + for (int a = 0; a < icons.size(); a++) { + ic[a] = icons.get(a); + } + builder.setItems(items.toArray(new CharSequence[0]), ic, (dialog, which) -> { + if (parentActivity == null) { + return; + } + if (actions.get(which) == 0) { + if (delegate != null) { + delegate.sendSticker(currentDocument, currentStickerSet); + } + } else if (actions.get(which) == 1) { + if (delegate != null) { + delegate.openSet(currentStickerSet, clearsInputField); + } + } else if (actions.get(which) == 2) { + DataQuery.getInstance(currentAccount).addRecentSticker(DataQuery.TYPE_FAVE, currentStickerSet, currentDocument, (int) (System.currentTimeMillis() / 1000), inFavs); + } + }); + builder.setDimBehind(false); + visibleDialog = builder.create(); + visibleDialog.setOnDismissListener(dialog -> { + visibleDialog = null; + close(); + }); + visibleDialog.show(); + containerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + } else if (delegate != null) { + animateY = true; + visibleDialog = new BottomSheet(parentActivity, false, 0) { + @Override + protected void onContainerTranslationYChanged(float translationY) { + if (animateY) { + ViewGroup container = getSheetContainer(); + if (finalMoveY == 0) { + finalMoveY = 0;//-container.getMeasuredHeight() / 2; + startMoveY = moveY; + } + currentMoveYProgress = 1.0f - Math.min(1.0f, translationY / containerView.getMeasuredHeight()); + moveY = startMoveY + (finalMoveY - startMoveY) * currentMoveYProgress; + ContentPreviewViewer.this.containerView.invalidate(); + if (currentMoveYProgress == 1.0f) { + animateY = false; + } + } + } + }; + ArrayList items = new ArrayList<>(); + final ArrayList actions = new ArrayList<>(); + ArrayList icons = new ArrayList<>(); + + if (delegate.needSend()) { + items.add(LocaleController.getString("SendGifPreview", R.string.SendGifPreview)); + icons.add(R.drawable.outline_send); + actions.add(0); + } + + boolean canDelete; + if (canDelete = DataQuery.getInstance(currentAccount).hasRecentGif(currentDocument)) { + items.add(LocaleController.formatString("Delete", R.string.Delete)); + icons.add(R.drawable.chats_delete); + actions.add(1); + } else { + items.add(LocaleController.formatString("SaveToGIFs", R.string.SaveToGIFs)); + icons.add(R.drawable.outline_add_gif); + actions.add(2); + } + + int[] ic = new int[icons.size()]; + for (int a = 0; a < icons.size(); a++) { + ic[a] = icons.get(a); + } + visibleDialog.setItems(items.toArray(new CharSequence[0]), ic, (dialog, which) -> { + if (parentActivity == null) { + return; + } + if (actions.get(which) == 0) { + if (delegate != null) { + delegate.sendGif(currentDocument); + } + } else if (actions.get(which) == 1) { + DataQuery.getInstance(currentAccount).removeRecentGif(currentDocument); + delegate.gifAddedOrDeleted(); + } else if (actions.get(which) == 2) { + DataQuery.getInstance(currentAccount).addRecentGif(currentDocument, (int) (System.currentTimeMillis() / 1000)); + MessagesController.getInstance(currentAccount).saveGif("gif", currentDocument); + delegate.gifAddedOrDeleted(); + } + }); + visibleDialog.setDimBehind(false); + visibleDialog.setOnDismissListener(dialog -> { + visibleDialog = null; + close(); + }); + visibleDialog.show(); + containerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + if (canDelete) { + visibleDialog.setItemColor(items.size() - 1, Theme.getColor(Theme.key_dialogTextRed2), Theme.getColor(Theme.key_dialogRedIcon)); + } + } + } + }; + + private int currentContentType; + private TLRPC.Document currentDocument; + private TLRPC.InputStickerSet currentStickerSet; + + @SuppressLint("StaticFieldLeak") + private static volatile ContentPreviewViewer Instance = null; + public static ContentPreviewViewer getInstance() { + ContentPreviewViewer localInstance = Instance; + if (localInstance == null) { + synchronized (PhotoViewer.class) { + localInstance = Instance; + if (localInstance == null) { + Instance = localInstance = new ContentPreviewViewer(); + } + } + } + return localInstance; + } + + public static boolean hasInstance() { + return Instance != null; + } + + public void reset() { + if (openPreviewRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(openPreviewRunnable); + openPreviewRunnable = null; + } + if (currentPreviewCell != null) { + if (currentPreviewCell instanceof StickerEmojiCell) { + ((StickerEmojiCell) currentPreviewCell).setScaled(false); + } else if (currentPreviewCell instanceof StickerCell) { + ((StickerCell) currentPreviewCell).setScaled(false); + } else if (currentPreviewCell instanceof ContextLinkCell) { + ((ContextLinkCell) currentPreviewCell).setScaled(false); + } + currentPreviewCell = null; + } + } + + public boolean onTouch(MotionEvent event, final RecyclerListView listView, final int height, final Object listener, ContentPreviewViewerDelegate contentPreviewViewerDelegate) { + delegate = contentPreviewViewerDelegate; + if (openPreviewRunnable != null || isVisible()) { + if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_POINTER_UP) { + AndroidUtilities.runOnUIThread(() -> { + if (listView instanceof RecyclerListView) { + listView.setOnItemClickListener((RecyclerListView.OnItemClickListener) listener); + } + }, 150); + if (openPreviewRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(openPreviewRunnable); + openPreviewRunnable = null; + } else if (isVisible()) { + close(); + if (currentPreviewCell != null) { + if (currentPreviewCell instanceof StickerEmojiCell) { + ((StickerEmojiCell) currentPreviewCell).setScaled(false); + } else if (currentPreviewCell instanceof StickerCell) { + ((StickerCell) currentPreviewCell).setScaled(false); + } else if (currentPreviewCell instanceof ContextLinkCell) { + ((ContextLinkCell) currentPreviewCell).setScaled(false); + } + currentPreviewCell = null; + } + } + } else if (event.getAction() != MotionEvent.ACTION_DOWN) { + if (isVisible) { + if (event.getAction() == MotionEvent.ACTION_MOVE) { + if (currentContentType == CONTENT_TYPE_GIF) { + if (visibleDialog == null && showProgress == 1.0f) { + if (lastTouchY == -10000) { + lastTouchY = event.getY(); + currentMoveY = 0; + moveY = 0; + } else { + float newY = event.getY(); + currentMoveY += newY - lastTouchY; + lastTouchY = newY; + if (currentMoveY > 0) { + currentMoveY = 0; + } else if (currentMoveY < -AndroidUtilities.dp(60)) { + currentMoveY = -AndroidUtilities.dp(60); + } + moveY = rubberYPoisition(currentMoveY, AndroidUtilities.dp(200)); + containerView.invalidate(); + if (currentMoveY <= -AndroidUtilities.dp(55)) { + AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); + showSheetRunnable.run(); + return true; + } + } + } + return true; + } + int x = (int) event.getX(); + int y = (int) event.getY(); + int count = listView.getChildCount(); + for (int a = 0; a < count; a++) { + View view = null; + if (listView instanceof RecyclerListView) { + view = listView.getChildAt(a); + } + if (view == null) { + return false; + } + int top = view.getTop(); + int bottom = view.getBottom(); + int left = view.getLeft(); + int right = view.getRight(); + if (top > y || bottom < y || left > x || right < x) { + continue; + } + int contentType = CONTENT_TYPE_NONE; + if (view instanceof StickerEmojiCell) { + contentType = CONTENT_TYPE_STICKER; + centerImage.setRoundRadius(0); + } else if (view instanceof StickerCell) { + contentType = CONTENT_TYPE_STICKER; + centerImage.setRoundRadius(0); + } else if (view instanceof ContextLinkCell) { + ContextLinkCell cell = (ContextLinkCell) view; + if (cell.isSticker()) { + contentType = CONTENT_TYPE_STICKER; + centerImage.setRoundRadius(0); + } else if (cell.isGif()) { + contentType = CONTENT_TYPE_GIF; + centerImage.setRoundRadius(AndroidUtilities.dp(6)); + } + } + if (contentType == CONTENT_TYPE_NONE || view == currentPreviewCell) { + break; + } + if (currentPreviewCell instanceof StickerEmojiCell) { + ((StickerEmojiCell) currentPreviewCell).setScaled(false); + } else if (currentPreviewCell instanceof StickerCell) { + ((StickerCell) currentPreviewCell).setScaled(false); + } else if (currentPreviewCell instanceof ContextLinkCell) { + ((ContextLinkCell) currentPreviewCell).setScaled(false); + } + currentPreviewCell = view; + setKeyboardHeight(height); + clearsInputField = false; + if (currentPreviewCell instanceof StickerEmojiCell) { + StickerEmojiCell stickerEmojiCell = (StickerEmojiCell) currentPreviewCell; + open(stickerEmojiCell.getSticker(), contentType, ((StickerEmojiCell) currentPreviewCell).isRecent()); + stickerEmojiCell.setScaled(true); + } else if (currentPreviewCell instanceof StickerCell) { + StickerCell stickerCell = (StickerCell) currentPreviewCell; + open(stickerCell.getSticker(), contentType, false); + stickerCell.setScaled(true); + clearsInputField = stickerCell.isClearsInputField(); + } else if (currentPreviewCell instanceof ContextLinkCell) { + ContextLinkCell contextLinkCell = (ContextLinkCell) currentPreviewCell; + open(contextLinkCell.getDocument(), contentType, false); + if (contentType != CONTENT_TYPE_GIF) { + contextLinkCell.setScaled(true); + } + } + return true; + } + } + return true; + } else if (openPreviewRunnable != null) { + if (event.getAction() == MotionEvent.ACTION_MOVE) { + if (Math.hypot(startX - event.getX(), startY - event.getY()) > AndroidUtilities.dp(10)) { + AndroidUtilities.cancelRunOnUIThread(openPreviewRunnable); + openPreviewRunnable = null; + } + } else { + AndroidUtilities.cancelRunOnUIThread(openPreviewRunnable); + openPreviewRunnable = null; + } + } + } + } + return false; + } + + public boolean onInterceptTouchEvent(MotionEvent event, final RecyclerListView listView, final int height, ContentPreviewViewerDelegate contentPreviewViewerDelegate) { + delegate = contentPreviewViewerDelegate; + if (event.getAction() == MotionEvent.ACTION_DOWN) { + int x = (int) event.getX(); + int y = (int) event.getY(); + int count = listView.getChildCount(); + for (int a = 0; a < count; a++) { + View view = null; + if (listView instanceof RecyclerListView) { + view = listView.getChildAt(a); + } + if (view == null) { + return false; + } + int top = view.getTop(); + int bottom = view.getBottom(); + int left = view.getLeft(); + int right = view.getRight(); + if (top > y || bottom < y || left > x || right < x) { + continue; + } + int contentType = CONTENT_TYPE_NONE; + if (view instanceof StickerEmojiCell) { + if (((StickerEmojiCell) view).showingBitmap()) { + contentType = CONTENT_TYPE_STICKER; + centerImage.setRoundRadius(0); + } + } else if (view instanceof StickerCell) { + if (((StickerCell) view).showingBitmap()) { + contentType = CONTENT_TYPE_STICKER; + centerImage.setRoundRadius(0); + } + } else if (view instanceof ContextLinkCell) { + ContextLinkCell cell = (ContextLinkCell) view; + if (cell.showingBitmap()) { + if (cell.isSticker()) { + contentType = CONTENT_TYPE_STICKER; + centerImage.setRoundRadius(0); + } else if (cell.isGif()) { + contentType = CONTENT_TYPE_GIF; + centerImage.setRoundRadius(AndroidUtilities.dp(6)); + } + } + } + if (contentType == CONTENT_TYPE_NONE) { + return false; + } + startX = x; + startY = y; + currentPreviewCell = view; + int contentTypeFinal = contentType; + openPreviewRunnable = () -> { + if (openPreviewRunnable == null) { + return; + } + listView.setOnItemClickListener((RecyclerListView.OnItemClickListener) null); + listView.requestDisallowInterceptTouchEvent(true); + openPreviewRunnable = null; + setParentActivity((Activity) listView.getContext()); + setKeyboardHeight(height); + clearsInputField = false; + if (currentPreviewCell instanceof StickerEmojiCell) { + StickerEmojiCell stickerEmojiCell = (StickerEmojiCell) currentPreviewCell; + open(stickerEmojiCell.getSticker(), contentTypeFinal, ((StickerEmojiCell) currentPreviewCell).isRecent()); + stickerEmojiCell.setScaled(true); + } else if (currentPreviewCell instanceof StickerCell) { + StickerCell stickerCell = (StickerCell) currentPreviewCell; + open(stickerCell.getSticker(), contentTypeFinal, false); + stickerCell.setScaled(true); + clearsInputField = stickerCell.isClearsInputField(); + } else if (currentPreviewCell instanceof ContextLinkCell) { + ContextLinkCell contextLinkCell = (ContextLinkCell) currentPreviewCell; + open(contextLinkCell.getDocument(), contentTypeFinal, false); + if (contentTypeFinal != CONTENT_TYPE_GIF) { + contextLinkCell.setScaled(true); + } + } + }; + AndroidUtilities.runOnUIThread(openPreviewRunnable, 200); + return true; + } + } + return false; + } + + public void setDelegate(ContentPreviewViewerDelegate contentPreviewViewerDelegate) { + delegate = contentPreviewViewerDelegate; + } + + public void setParentActivity(Activity activity) { + currentAccount = UserConfig.selectedAccount; + centerImage.setCurrentAccount(currentAccount); + if (parentActivity == activity) { + return; + } + parentActivity = activity; + + slideUpDrawable = parentActivity.getResources().getDrawable(R.drawable.preview_arrow); + + windowView = new FrameLayout(activity); + windowView.setFocusable(true); + windowView.setFocusableInTouchMode(true); + if (Build.VERSION.SDK_INT >= 21) { + windowView.setFitsSystemWindows(true); + windowView.setOnApplyWindowInsetsListener((v, insets) -> { + lastInsets = insets; + return insets; + }); + } + + containerView = new FrameLayoutDrawer(activity); + containerView.setFocusable(false); + windowView.addView(containerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); + containerView.setOnTouchListener((v, event) -> { + if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_POINTER_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { + close(); + } + return true; + }); + + windowLayoutParams = new WindowManager.LayoutParams(); + windowLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT; + windowLayoutParams.format = PixelFormat.TRANSLUCENT; + windowLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT; + windowLayoutParams.gravity = Gravity.TOP; + windowLayoutParams.type = WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; + if (Build.VERSION.SDK_INT >= 21) { + windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; + } else { + windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; + } + centerImage.setAspectFit(true); + centerImage.setInvalidateAll(true); + centerImage.setParentView(containerView); + } + + public void setKeyboardHeight(int height) { + keyboardHeight = height; + } + + public void open(TLRPC.Document document, int contentType, boolean isRecent) { + if (parentActivity == null || document == null || windowView == null) { + return; + } + stickerEmojiLayout = null; + if (contentType == CONTENT_TYPE_STICKER) { + if (textPaint == null) { + textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + textPaint.setTextSize(AndroidUtilities.dp(24)); + } + + TLRPC.InputStickerSet newSet = null; + for (int a = 0; a < document.attributes.size(); a++) { + TLRPC.DocumentAttribute attribute = document.attributes.get(a); + if (attribute instanceof TLRPC.TL_documentAttributeSticker && attribute.stickerset != null) { + newSet = attribute.stickerset; + break; + } + } + if (newSet != null) { + try { + if (visibleDialog != null) { + visibleDialog.setOnDismissListener(null); + visibleDialog.dismiss(); + visibleDialog = null; + } + } catch (Exception e) { + FileLog.e(e); + } + AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); + AndroidUtilities.runOnUIThread(showSheetRunnable, 1300); + } + currentStickerSet = newSet; + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); + centerImage.setImage(ImageLocation.getForDocument(document), null, ImageLocation.getForDocument(thumb, document), null, "webp", currentStickerSet, 1); + for (int a = 0; a < document.attributes.size(); a++) { + TLRPC.DocumentAttribute attribute = document.attributes.get(a); + if (attribute instanceof TLRPC.TL_documentAttributeSticker) { + if (!TextUtils.isEmpty(attribute.alt)) { + CharSequence emoji = Emoji.replaceEmoji(attribute.alt, textPaint.getFontMetricsInt(), AndroidUtilities.dp(24), false); + stickerEmojiLayout = new StaticLayout(emoji, textPaint, AndroidUtilities.dp(100), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + break; + } + } + } + } else { + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); + centerImage.setImage(ImageLocation.getForDocument(document), null, ImageLocation.getForDocument(thumb, document), "90_90_b", document.size, null, "gif" + document, 0); + AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); + AndroidUtilities.runOnUIThread(showSheetRunnable, 2000); + } + + currentContentType = contentType; + currentDocument = document; + containerView.invalidate(); + + if (!isVisible) { + AndroidUtilities.lockOrientation(parentActivity); + try { + if (windowView.getParent() != null) { + WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); + wm.removeView(windowView); + } + } catch (Exception e) { + FileLog.e(e); + } + WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); + wm.addView(windowView, windowLayoutParams); + isVisible = true; + showProgress = 0.0f; + lastTouchY = -10000; + currentMoveYProgress = 0.0f; + finalMoveY = 0; + currentMoveY = 0; + moveY = 0; + lastUpdateTime = System.currentTimeMillis(); + } + } + + public boolean isVisible() { + return isVisible; + } + + public void close() { + if (parentActivity == null || visibleDialog != null) { + return; + } + AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); + showProgress = 1.0f; + lastUpdateTime = System.currentTimeMillis(); + containerView.invalidate(); + try { + if (visibleDialog != null) { + visibleDialog.dismiss(); + visibleDialog = null; + } + } catch (Exception e) { + FileLog.e(e); + } + currentDocument = null; + currentStickerSet = null; + delegate = null; + isVisible = false; + } + + public void destroy() { + isVisible = false; + delegate = null; + currentDocument = null; + currentStickerSet = null; + try { + if (visibleDialog != null) { + visibleDialog.dismiss(); + visibleDialog = null; + } + } catch (Exception e) { + FileLog.e(e); + } + if (parentActivity == null || windowView == null) { + return; + } + try { + if (windowView.getParent() != null) { + WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); + wm.removeViewImmediate(windowView); + } + windowView = null; + } catch (Exception e) { + FileLog.e(e); + } + Instance = null; + } + + private float rubberYPoisition(float offset, float factor) { + float delta = Math.abs(offset); + return (-((1.0f - (1.0f / ((delta * 0.55f / factor) + 1.0f))) * factor)) * (offset < 0.0f ? 1.0f : -1.0f); + } + + @SuppressLint("DrawAllocation") + private void onDraw(Canvas canvas) { + if (containerView == null || backgroundDrawable == null) { + return; + } + backgroundDrawable.setAlpha((int) (180 * showProgress)); + backgroundDrawable.setBounds(0, 0, containerView.getWidth(), containerView.getHeight()); + backgroundDrawable.draw(canvas); + + canvas.save(); + int size; + int insets = 0; + int top; + if (Build.VERSION.SDK_INT >= 21 && lastInsets != null) { + insets = lastInsets.getStableInsetBottom() + lastInsets.getStableInsetTop(); + top = lastInsets.getStableInsetTop(); + } else { + top = AndroidUtilities.statusBarHeight; + } + + if (currentContentType == CONTENT_TYPE_GIF) { + size = Math.min(containerView.getWidth(), containerView.getHeight() - insets) - AndroidUtilities.dp(40f); + } else { + size = (int) (Math.min(containerView.getWidth(), containerView.getHeight() - insets) / 1.8f); + } + + canvas.translate(containerView.getWidth() / 2, moveY + Math.max(size / 2 + top + (stickerEmojiLayout != null ? AndroidUtilities.dp(40) : 0), (containerView.getHeight() - insets - keyboardHeight) / 2)); + Bitmap bitmap = centerImage.getBitmap(); + if (bitmap != null) { + float scale = 0.8f * showProgress / 0.8f; + size = (int) (size * scale); + centerImage.setAlpha(showProgress); + centerImage.setImageCoords(-size / 2, -size / 2, size, size); + centerImage.draw(canvas); + + if (currentContentType == CONTENT_TYPE_GIF && slideUpDrawable != null) { + int w = slideUpDrawable.getIntrinsicWidth(); + int h = slideUpDrawable.getIntrinsicHeight(); + int y = (int) (centerImage.getDrawRegion().top - AndroidUtilities.dp(17 + 6 * (currentMoveY / (float) AndroidUtilities.dp(60)))); + slideUpDrawable.setAlpha((int) (255 * (1.0f - currentMoveYProgress))); + slideUpDrawable.setBounds(-w / 2, -h + y, w / 2, y); + slideUpDrawable.draw(canvas); + } + } + if (stickerEmojiLayout != null) { + canvas.translate(-AndroidUtilities.dp(50), -centerImage.getImageHeight() / 2 - AndroidUtilities.dp(30)); + stickerEmojiLayout.draw(canvas); + } + canvas.restore(); + if (isVisible) { + if (showProgress != 1) { + long newTime = System.currentTimeMillis(); + long dt = newTime - lastUpdateTime; + lastUpdateTime = newTime; + showProgress += dt / 120.0f; + containerView.invalidate(); + if (showProgress > 1.0f) { + showProgress = 1.0f; + } + } + } else if (showProgress != 0) { + long newTime = System.currentTimeMillis(); + long dt = newTime - lastUpdateTime; + lastUpdateTime = newTime; + showProgress -= dt / 120.0f; + containerView.invalidate(); + if (showProgress < 0.0f) { + showProgress = 0.0f; + } + if (showProgress == 0) { + centerImage.setImageBitmap((Drawable) null); + AndroidUtilities.unlockOrientation(parentActivity); + AndroidUtilities.runOnUIThread(() -> centerImage.setImageBitmap((Bitmap) null)); + try { + if (windowView.getParent() != null) { + WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); + wm.removeView(windowView); + } + } catch (Exception e) { + FileLog.e(e); + } + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java index f6397307a..8020c4efd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java @@ -20,8 +20,6 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; import org.telegram.messenger.Utilities; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.ActionBar.ActionBar; @@ -44,6 +42,9 @@ import java.util.HashMap; import java.util.Timer; import java.util.TimerTask; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class CountrySelectActivity extends BaseFragment { public interface CountrySelectActivityDelegate { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DataAutoDownloadActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DataAutoDownloadActivity.java index 726ff703d..5128111b9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DataAutoDownloadActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DataAutoDownloadActivity.java @@ -32,9 +32,6 @@ import org.telegram.messenger.DownloadController; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.DefaultItemAnimator; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; @@ -54,10 +51,16 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; import java.util.Collections; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class DataAutoDownloadActivity extends BaseFragment { private ListAdapter listAdapter; private RecyclerListView listView; + @SuppressWarnings("FieldCanBeLocal") + private LinearLayoutManager layoutManager; private ArrayList presets = new ArrayList<>(); private int selectedPreset = 1; @@ -275,7 +278,7 @@ public class DataAutoDownloadActivity extends BaseFragment { } else if (a == presets.size() - 1) { canvas.drawText(text, getMeasuredWidth() - size - AndroidUtilities.dp(22), AndroidUtilities.dp(28), textPaint); } else { - canvas.drawText(text, cx - customSize / 2, AndroidUtilities.dp(28), textPaint); + canvas.drawText(text, cx - size / 2, AndroidUtilities.dp(28), textPaint); } } } @@ -350,7 +353,7 @@ public class DataAutoDownloadActivity extends BaseFragment { listView = new RecyclerListView(context); listView.setVerticalScrollBarEnabled(false); ((DefaultItemAnimator) listView.getItemAnimator()).setDelayAnimations(false); - listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); + listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); listView.setAdapter(listAdapter); listView.setOnItemClickListener((view, position, x, y) -> { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DataSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DataSettingsActivity.java index ad37f82c8..9e6c2456f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DataSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DataSettingsActivity.java @@ -24,8 +24,6 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.messenger.voip.VoIPController; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.AlertDialog; @@ -43,10 +41,15 @@ import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.voip.VoIPHelper; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class DataSettingsActivity extends BaseFragment { private ListAdapter listAdapter; private RecyclerListView listView; + @SuppressWarnings("FieldCanBeLocal") + private LinearLayoutManager layoutManager; private AnimatorSet animatorSet; private int mediaDownloadSectionRow; @@ -146,12 +149,14 @@ public class DataSettingsActivity extends BaseFragment { listView = new RecyclerListView(context); listView.setVerticalScrollBarEnabled(false); - listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); + listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); listView.setAdapter(listAdapter); listView.setOnItemClickListener((view, position, x, y) -> { if (position == mobileRow || position == roamingRow || position == wifiRow) { if (LocaleController.isRTL && x <= AndroidUtilities.dp(76) || !LocaleController.isRTL && x >= view.getMeasuredWidth() - AndroidUtilities.dp(76)) { + boolean wasEnabled = listAdapter.isRowEnabled(resetDownloadRow); + NotificationsCheckCell cell = (NotificationsCheckCell) view; boolean checked = cell.isChecked(); @@ -196,6 +201,9 @@ public class DataSettingsActivity extends BaseFragment { } DownloadController.getInstance(currentAccount).checkAutodownloadSettings(); DownloadController.getInstance(currentAccount).savePresetToServer(num); + if (wasEnabled != listAdapter.isRowEnabled(resetDownloadRow)) { + listAdapter.notifyItemChanged(resetDownloadRow); + } } else { int type; if (position == mobileRow) { @@ -235,6 +243,7 @@ public class DataSettingsActivity extends BaseFragment { key = "roamingPreset"; } preset.set(defaultPreset); + preset.enabled = defaultPreset.isEnabled(); editor.putInt("currentMobilePreset", DownloadController.getInstance(currentAccount).currentMobilePreset = 3); editor.putInt("currentWifiPreset", DownloadController.getInstance(currentAccount).currentWifiPreset = 3); editor.putInt("currentRoamingPreset", DownloadController.getInstance(currentAccount).currentRoamingPreset = 3); @@ -253,19 +262,19 @@ public class DataSettingsActivity extends BaseFragment { presentFragment(new CacheControlActivity()); } else if (position == useLessDataForCallsRow) { final SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - int selected=0; - switch(preferences.getInt("VoipDataSaving", VoIPHelper.getDataSavingDefault())){ + int selected = 0; + switch (preferences.getInt("VoipDataSaving", VoIPHelper.getDataSavingDefault())) { case VoIPController.DATA_SAVING_NEVER: - selected=0; + selected = 0; + break; + case VoIPController.DATA_SAVING_ROAMING: + selected = 1; break; - case VoIPController.DATA_SAVING_ROAMING: - selected=1; - break; case VoIPController.DATA_SAVING_MOBILE: - selected=2; + selected = 2; break; case VoIPController.DATA_SAVING_ALWAYS: - selected=3; + selected = 3; break; } Dialog dlg = AlertsCreator.createSingleChoiceDialog(getParentActivity(), new String[]{ @@ -280,7 +289,7 @@ public class DataSettingsActivity extends BaseFragment { val = VoIPController.DATA_SAVING_NEVER; break; case 1: - val=VoIPController.DATA_SAVING_ROAMING; + val = VoIPController.DATA_SAVING_ROAMING; break; case 2: val = VoIPController.DATA_SAVING_MOBILE; @@ -492,20 +501,20 @@ public class DataSettingsActivity extends BaseFragment { } if (preset.enabled && count != 0) { if (photos) { - builder.append(LocaleController.getString("AutoDownloadPhotos", R.string.AutoDownloadPhotos)); + builder.append(LocaleController.getString("AutoDownloadPhotosOn", R.string.AutoDownloadPhotosOn)); } if (videos) { if (builder.length() > 0) { builder.append(", "); } - builder.append(LocaleController.getString("AutoDownloadVideos", R.string.AutoDownloadVideos)); + builder.append(LocaleController.getString("AutoDownloadVideosOn", R.string.AutoDownloadVideosOn)); builder.append(String.format(" (%1$s)", AndroidUtilities.formatFileSize(preset.sizes[DownloadController.typeToIndex(DownloadController.AUTODOWNLOAD_TYPE_VIDEO)], true))); } if (files) { if (builder.length() > 0) { builder.append(", "); } - builder.append(LocaleController.getString("AutoDownloadFiles", R.string.AutoDownloadFiles)); + builder.append(LocaleController.getString("AutoDownloadFilesOn", R.string.AutoDownloadFilesOn)); builder.append(String.format(" (%1$s)", AndroidUtilities.formatFileSize(preset.sizes[DownloadController.typeToIndex(DownloadController.AUTODOWNLOAD_TYPE_DOCUMENT)], true))); } } else { @@ -539,19 +548,22 @@ public class DataSettingsActivity extends BaseFragment { } } - @Override - public boolean isEnabled(RecyclerView.ViewHolder holder) { - int position = holder.getAdapterPosition(); + public boolean isRowEnabled(int position) { if (position == resetDownloadRow) { DownloadController controller = DownloadController.getInstance(currentAccount); - return !controller.lowPreset.equals(controller.getCurrentRoamingPreset()) || - !controller.mediumPreset.equals(controller.getCurrentMobilePreset()) || - !controller.highPreset.equals(controller.getCurrentWiFiPreset()); + return !controller.lowPreset.equals(controller.getCurrentRoamingPreset()) || controller.lowPreset.isEnabled() != controller.roamingPreset.enabled || + !controller.mediumPreset.equals(controller.getCurrentMobilePreset()) || controller.mediumPreset.isEnabled() != controller.mobilePreset.enabled || + !controller.highPreset.equals(controller.getCurrentWiFiPreset()) || controller.highPreset.isEnabled() != controller.wifiPreset.enabled; } return position == mobileRow || position == roamingRow || position == wifiRow || position == storageUsageRow || position == useLessDataForCallsRow || position == dataUsageRow || position == proxyRow || position == enableCacheStreamRow || position == enableStreamRow || position == enableAllStreamRow || position == enableMkvRow || position == quickRepliesRow || position == autoplayVideoRow || position == autoplayGifsRow; } + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return isRowEnabled(holder.getAdapterPosition()); + } + @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = null; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DataUsageActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DataUsageActivity.java index 57d908425..78c630944 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DataUsageActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DataUsageActivity.java @@ -15,6 +15,7 @@ import android.animation.ObjectAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.drawable.Drawable; import android.view.Gravity; import android.view.MotionEvent; import android.view.VelocityTracker; @@ -29,8 +30,6 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; import org.telegram.messenger.StatsController; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; @@ -46,6 +45,9 @@ import org.telegram.ui.Components.ScrollSlidingTextTabStrip; import java.util.ArrayList; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class DataUsageActivity extends BaseFragment { private class ViewPage extends FrameLayout { @@ -477,9 +479,20 @@ public class DataUsageActivity extends BaseFragment { } }); viewPages[a].listView.setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - + if (newState != RecyclerView.SCROLL_STATE_DRAGGING) { + int scrollY = (int) -actionBar.getTranslationY(); + int actionBarHeight = ActionBar.getCurrentActionBarHeight(); + if (scrollY != 0 && scrollY != actionBarHeight) { + if (scrollY < actionBarHeight / 2) { + viewPages[0].listView.smoothScrollBy(0, -scrollY); + } else { + viewPages[0].listView.smoothScrollBy(0, actionBarHeight - scrollY); + } + } + } } @Override @@ -830,7 +843,7 @@ public class DataUsageActivity extends BaseFragment { public int getItemViewType(int position) { if (position == resetSection2Row) { return 3; - } else if (position == resetSection2Row || position == callsSection2Row || position == filesSection2Row || position == audiosSection2Row || position == videosSection2Row || position == photosSection2Row || position == messagesSection2Row || position == totalSection2Row) { + } else if (position == callsSection2Row || position == filesSection2Row || position == audiosSection2Row || position == videosSection2Row || position == photosSection2Row || position == messagesSection2Row || position == totalSection2Row) { return 0; } else if (position == totalSectionRow || position == callsSectionRow || position == filesSectionRow || position == audiosSectionRow || position == videosSectionRow || position == photosSectionRow || position == messagesSectionRow) { return 2; @@ -853,7 +866,7 @@ public class DataUsageActivity extends BaseFragment { arrayList.add(new ThemeDescription(scrollSlidingTextTabStrip.getTabsContainer(), ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{TextView.class}, null, null, null, Theme.key_actionBarDefaultTitle)); arrayList.add(new ThemeDescription(scrollSlidingTextTabStrip.getTabsContainer(), ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{TextView.class}, null, null, null, Theme.key_actionBarDefaultSubtitle)); arrayList.add(new ThemeDescription(scrollSlidingTextTabStrip.getTabsContainer(), ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, new Class[]{TextView.class}, null, null, null, Theme.key_actionBarDefaultSelector)); - arrayList.add(new ThemeDescription(null, 0, null, scrollSlidingTextTabStrip.getRectPaint(), null, null, Theme.key_actionBarDefaultTitle)); + arrayList.add(new ThemeDescription(null, 0, null, null, new Drawable[]{scrollSlidingTextTabStrip.getSelectorDrawable()}, null, Theme.key_actionBarDefaultTitle)); for (int a = 0; a < viewPages.length; a++) { arrayList.add(new ThemeDescription(viewPages[a].listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{TextSettingsCell.class, HeaderCell.class}, null, null, null, Theme.key_windowBackgroundWhite)); @@ -873,7 +886,7 @@ public class DataUsageActivity extends BaseFragment { arrayList.add(new ThemeDescription(viewPages[a].listView, 0, new Class[]{TextSettingsCell.class}, new String[]{"valueTextView"}, null, null, null, Theme.key_windowBackgroundWhiteValueText)); arrayList.add(new ThemeDescription(viewPages[a].listView, ThemeDescription.FLAG_CHECKTAG, new Class[]{TextSettingsCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteRedText2)); } - + return arrayList.toArray(new ThemeDescription[0]); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index a5b06cb5f..4af062c98 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -19,19 +19,34 @@ import android.annotation.TargetApi; import android.app.Activity; import android.app.Dialog; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.res.Configuration; +import android.graphics.Canvas; import android.graphics.Outline; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.Vibrator; + +import androidx.core.view.NestedScrollingParent3; +import androidx.core.view.NestedScrollingParentHelper; +import androidx.core.view.ViewCompat; +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.LinearSmoothScrollerMiddle; +import androidx.recyclerview.widget.RecyclerView; + import android.text.TextUtils; import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.view.MotionEvent; import android.view.View; import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; @@ -40,7 +55,11 @@ import android.view.animation.DecelerateInterpolator; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.TextView; +import com.airbnb.lottie.LottieDrawable; + +import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildVars; @@ -48,14 +67,14 @@ import org.telegram.messenger.ChatObject; import org.telegram.messenger.DataQuery; import org.telegram.messenger.DialogObject; import org.telegram.messenger.ImageLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; +import org.telegram.messenger.NotificationsController; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserObject; +import org.telegram.messenger.Utilities; import org.telegram.messenger.XiaomiUtilities; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.LinearSmoothScrollerMiddle; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.messenger.FileLog; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; @@ -65,12 +84,14 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; import org.telegram.ui.ActionBar.AlertDialog; -import org.telegram.ui.ActionBar.BottomSheet; +import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Adapters.DialogsAdapter; import org.telegram.ui.Adapters.DialogsSearchAdapter; import org.telegram.ui.Cells.AccountSelectCell; +import org.telegram.ui.Cells.ArchiveHintInnerCell; import org.telegram.ui.Cells.DialogsEmptyCell; import org.telegram.ui.Cells.DividerCell; import org.telegram.ui.Cells.DrawerActionCell; @@ -82,6 +103,7 @@ import org.telegram.ui.Cells.HashtagSearchCell; import org.telegram.ui.Cells.HintDialogCell; import org.telegram.ui.Cells.LoadingCell; import org.telegram.ui.Cells.ProfileSearchCell; +import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.UserCell; import org.telegram.ui.Cells.DialogCell; import org.telegram.ui.ActionBar.ActionBar; @@ -95,10 +117,14 @@ import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.ChatActivityEnterView; import org.telegram.ui.Components.CombinedDrawable; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.DialogsItemAnimator; import org.telegram.ui.Components.FragmentContextView; import org.telegram.ui.Components.EmptyTextProgressView; import org.telegram.ui.Components.JoinGroupAlert; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.NumberTextView; +import org.telegram.ui.Components.PacmanAnimation; import org.telegram.ui.Components.ProxyDrawable; import org.telegram.ui.Components.RadialProgressView; import org.telegram.ui.Components.RecyclerListView; @@ -122,7 +148,32 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. private ProxyDrawable proxyDrawable; private ImageView floatingButton; private FrameLayout floatingButtonContainer; - private UndoView undoView; + private UndoView[] undoView = new UndoView[2]; + private SwipeController swipeController; + private ItemTouchHelper itemTouchhelper; + + private int lastItemsCount; + + private PacmanAnimation pacmanAnimation; + + private DialogCell slidingView; + private DialogCell movingView; + private boolean allowMoving; + private boolean movingWas; + private boolean waitingForScrollFinished; + private boolean allowSwipeDuringCurrentTouch; + + private MenuDrawable menuDrawable; + private BackDrawable backDrawable; + + private NumberTextView selectedDialogsCountTextView; + private ArrayList actionModeViews = new ArrayList<>(); + private ActionBarMenuItem deleteItem; + private ActionBarMenuItem pinItem; + private ActionBarMenuItem archiveItem; + private ActionBarMenuSubItem clearItem; + private ActionBarMenuSubItem readItem; + private ActionBarMenuSubItem muteItem; private float additionalFloatingTranslation; @@ -136,6 +187,13 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. private ChatActivityEnterView commentView; private ActionBarMenuItem switchItem; + private static ArrayList frozenDialogsList; + private boolean dialogsListFrozen; + private int dialogRemoveFinished; + private int dialogInsertFinished; + private int dialogChangeFinished; + private DialogsItemAnimator dialogsItemAnimator; + private AlertDialog permissionDialog; private boolean askAboutContacts = true; @@ -159,7 +217,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. private String addToGroupAlertString; private int dialogsType; - public static boolean dialogsLoaded[] = new boolean[UserConfig.MAX_ACCOUNT_COUNT]; + public static boolean[] dialogsLoaded = new boolean[UserConfig.MAX_ACCOUNT_COUNT]; private boolean searching; private boolean searchWas; private boolean onlySelect; @@ -171,6 +229,482 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. private DialogsActivityDelegate delegate; + private int canReadCount; + private int canPinCount; + private int canMuteCount; + private int canUnmuteCount; + private int canClearCacheCount; + + private int folderId; + + private final static int pin = 100; + private final static int read = 101; + private final static int delete = 102; + private final static int clear = 103; + private final static int mute = 104; + private final static int archive = 105; + + private boolean allowScrollToHiddenView; + + private class ContentView extends SizeNotifierFrameLayout implements NestedScrollingParent3 { + + private NestedScrollingParentHelper nestedScrollingParentHelper; + private int inputFieldHeight; + private int totalConsumedAmount; + private boolean startedScrollAtTop; + + public ContentView(Context context) { + super(context); + nestedScrollingParentHelper = new NestedScrollingParentHelper(this); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthSize = View.MeasureSpec.getSize(widthMeasureSpec); + int heightSize = View.MeasureSpec.getSize(heightMeasureSpec); + + setMeasuredDimension(widthSize, heightSize); + heightSize -= getPaddingTop(); + + measureChildWithMargins(actionBar, widthMeasureSpec, 0, heightMeasureSpec, 0); + + int keyboardSize = getKeyboardHeight(); + int childCount = getChildCount(); + + if (commentView != null) { + measureChildWithMargins(commentView, widthMeasureSpec, 0, heightMeasureSpec, 0); + Object tag = commentView.getTag(); + if (tag != null && tag.equals(2)) { + if (keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow) { + heightSize -= commentView.getEmojiPadding(); + } + inputFieldHeight = commentView.getMeasuredHeight(); + } else { + inputFieldHeight = 0; + } + } + + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + if (child == null || child.getVisibility() == GONE || child == commentView || child == actionBar) { + continue; + } + if (child == listView || child == progressView || child == searchEmptyView) { + int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); + int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(Math.max(AndroidUtilities.dp(10), heightSize - inputFieldHeight + AndroidUtilities.dp(2)), View.MeasureSpec.EXACTLY); + child.measure(contentWidthSpec, contentHeightSpec); + } else if (commentView != null && commentView.isPopupView(child)) { + if (AndroidUtilities.isInMultiwindow) { + if (AndroidUtilities.isTablet()) { + child.measure(View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(Math.min(AndroidUtilities.dp(320), heightSize - inputFieldHeight - AndroidUtilities.statusBarHeight + getPaddingTop()), View.MeasureSpec.EXACTLY)); + } else { + child.measure(View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(heightSize - inputFieldHeight - AndroidUtilities.statusBarHeight + getPaddingTop(), View.MeasureSpec.EXACTLY)); + } + } else { + child.measure(View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(child.getLayoutParams().height, View.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; + Object tag = commentView != null ? commentView.getTag() : null; + if (tag != null && tag.equals(2)) { + paddingBottom = getKeyboardHeight() <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow ? commentView.getEmojiPadding() : 0; + } else { + paddingBottom = 0; + } + setBottomClip(paddingBottom); + + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == GONE) { + continue; + } + final FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) child.getLayoutParams(); + + final int width = child.getMeasuredWidth(); + final int height = child.getMeasuredHeight(); + + int childLeft; + int childTop; + + int gravity = lp.gravity; + if (gravity == -1) { + gravity = Gravity.TOP | Gravity.LEFT; + } + + final int absoluteGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK; + + switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { + case Gravity.CENTER_HORIZONTAL: + childLeft = (r - l - width) / 2 + lp.leftMargin - lp.rightMargin; + break; + case Gravity.RIGHT: + childLeft = r - width - lp.rightMargin; + break; + case Gravity.LEFT: + default: + childLeft = lp.leftMargin; + } + + switch (verticalGravity) { + case Gravity.TOP: + childTop = lp.topMargin + getPaddingTop(); + break; + case Gravity.CENTER_VERTICAL: + childTop = ((b - paddingBottom) - t - height) / 2 + lp.topMargin - lp.bottomMargin; + break; + case Gravity.BOTTOM: + childTop = ((b - paddingBottom) - t) - height - lp.bottomMargin; + break; + default: + childTop = lp.topMargin; + } + + if (commentView != null && commentView.isPopupView(child)) { + if (AndroidUtilities.isInMultiwindow) { + childTop = commentView.getTop() - child.getMeasuredHeight() + AndroidUtilities.dp(1); + } else { + childTop = commentView.getBottom(); + } + } + child.layout(childLeft, childTop, childLeft + width, childTop + height); + } + + notifyHeightChanged(); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + int action = ev.getActionMasked(); + if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { + if (action == MotionEvent.ACTION_DOWN) { + int currentPosition = layoutManager.findFirstVisibleItemPosition(); + startedScrollAtTop = currentPosition <= 1; + } else { + if (actionBar.isActionModeShowed()) { + allowMoving = true; + } + } + totalConsumedAmount = 0; + allowScrollToHiddenView = false; + } + return super.onInterceptTouchEvent(ev); + } + + @Override + public boolean onStartNestedScroll(View child, View target, int axes, int type) { + return !onlySelect && dialogsType == 0 && folderId == 0 && child == listView && listView.getAdapter() == dialogsAdapter && axes == ViewCompat.SCROLL_AXIS_VERTICAL; + } + + @Override + public void onNestedScrollAccepted(View child, View target, int axes, int type) { + nestedScrollingParentHelper.onNestedScrollAccepted(child, target, axes); + } + + @Override + public void onStopNestedScroll(View target, int type) { + nestedScrollingParentHelper.onStopNestedScroll(target); + } + + @Override + public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) { + + } + + @Override + public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type, int[] consumed) { + + } + + @Override + public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { + + } + + @Override + public boolean onNestedPreFling(View target, float velocityX, float velocityY) { + return false; + } + + @Override + public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) { + return false; + } + + @Override + public void onNestedPreScroll(View target, int dx, int dy, int[] consumed, int type) { + if (allowScrollToHiddenView && type == ViewCompat.TYPE_TOUCH) { + consumed[1] = dy; + int currentPosition = layoutManager.findFirstVisibleItemPosition(); + if (currentPosition == 0) { + View view = layoutManager.findViewByPosition(currentPosition); + if (view != null && view.getTop() >= 0) { + allowScrollToHiddenView = false; + totalConsumedAmount = 0; + } + } + } + if (!allowScrollToHiddenView && folderId == 0 && dy < 0 && getMessagesController().hasHiddenArchive()) { + int currentPosition = layoutManager.findFirstVisibleItemPosition(); + if (currentPosition == 0) { + View view = layoutManager.findViewByPosition(currentPosition); + if (view != null && view.getBottom() <= AndroidUtilities.dp(1)) { + currentPosition = 1; + } + } + if (currentPosition == 0 || currentPosition == RecyclerView.NO_POSITION) { + return; + } + View view = layoutManager.findViewByPosition(currentPosition); + if (view == null) { + return; + } + int dialogHeight = AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 78 : 72) + 1; + int canScrollDy = -view.getTop() + (currentPosition - 1) * dialogHeight; + int positiveDy = Math.abs(dy); + if (canScrollDy >= positiveDy) { + return; + } + consumed[1] = canScrollDy - positiveDy; + totalConsumedAmount += Math.abs(consumed[1]); + if (startedScrollAtTop && totalConsumedAmount >= AndroidUtilities.dp(150)) { + listView.smoothScrollBy(0, -dialogHeight, CubicBezierInterpolator.EASE_OUT_QUINT); + allowScrollToHiddenView = true; + try { + performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + } catch (Exception ignore) { + + } + } + } + } + } + + class SwipeController extends ItemTouchHelper.Callback { + + private RectF buttonInstance; + private RecyclerView.ViewHolder currentItemViewHolder; + private boolean swipingFolder; + private boolean swipeFolderBack; + + @Override + public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + if (waitingForDialogsAnimationEnd() || parentLayout != null && parentLayout.isInPreviewMode()) { + return 0; + } + if (swipingFolder && swipeFolderBack) { + swipingFolder = false; + return 0; + } + if (!onlySelect && dialogsType == 0 && slidingView == null && recyclerView.getAdapter() == dialogsAdapter && viewHolder.itemView instanceof DialogCell) { + DialogCell dialogCell = (DialogCell) viewHolder.itemView; + long dialogId = dialogCell.getDialogId(); + if (actionBar.isActionModeShowed()) { + TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(dialogId); + if (!allowMoving || dialog == null || !dialog.pinned || DialogObject.isFolderDialogId(dialogId)) { + return 0; + } + movingView = (DialogCell) viewHolder.itemView; + movingView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + return makeMovementFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0); + } else { + if (!allowSwipeDuringCurrentTouch || dialogId == getUserConfig().clientUserId || dialogId == 777000 || getMessagesController().isProxyDialog(dialogId)) { + return 0; + } + swipeFolderBack = false; + swipingFolder = SharedConfig.archiveHidden && DialogObject.isFolderDialogId(dialogCell.getDialogId()); + dialogCell.setSliding(true); + return makeMovementFlags(0, ItemTouchHelper.LEFT); + } + } + return 0; + } + + @Override + public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) { + if (!(target.itemView instanceof DialogCell)) { + return false; + } + DialogCell dialogCell = (DialogCell) target.itemView; + long dialogId = dialogCell.getDialogId(); + TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(dialogId); + if (dialog == null || !dialog.pinned || DialogObject.isFolderDialogId(dialogId)) { + return false; + } + int fromIndex = source.getAdapterPosition(); + int toIndex = target.getAdapterPosition(); + dialogsAdapter.notifyItemMoved(fromIndex, toIndex); + updateDialogIndices(); + movingWas = true; + return true; + } + + @Override + public int convertToAbsoluteDirection(int flags, int layoutDirection) { + if (swipeFolderBack) { + return 0; + } + return super.convertToAbsoluteDirection(flags, layoutDirection); + } + + @Override + public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { + if (viewHolder != null) { + DialogCell dialogCell = (DialogCell) viewHolder.itemView; + long dialogId = dialogCell.getDialogId(); + if (DialogObject.isFolderDialogId(dialogId)) { + SharedConfig.toggleArchiveHidden(); + if (SharedConfig.archiveHidden) { + waitingForScrollFinished = true; + listView.smoothScrollBy(0, (dialogCell.getMeasuredHeight() + dialogCell.getTop()), CubicBezierInterpolator.EASE_OUT); + getUndoView().showWithAction(0, UndoView.ACTION_ARCHIVE_HIDDEN, null, null); + } + return; + } + + slidingView = dialogCell; + int position = viewHolder.getAdapterPosition(); + int dialogIndex = dialogsAdapter.fixPosition(position); + int count = dialogsAdapter.getItemCount(); + Runnable finishRunnable = () -> { + TLRPC.Dialog dialog = frozenDialogsList.remove(dialogIndex); + int pinnedNum = dialog.pinnedNum; + slidingView = null; + listView.invalidate(); + int added = getMessagesController().addDialogToFolder(dialog.id, folderId == 0 ? 1 : 0, -1, 0); + if (added == 2) { + dialogsAdapter.notifyItemChanged(count - 1); + } + if (added != 2 || position != 0) { + dialogsItemAnimator.prepareForRemove(); + lastItemsCount--; + dialogsAdapter.notifyItemRemoved(position); + dialogRemoveFinished = 2; + } + if (folderId == 0) { + if (added == 2) { + dialogsItemAnimator.prepareForRemove(); + if (position == 0) { + dialogChangeFinished = 2; + setDialogsListFrozen(true); + dialogsAdapter.notifyItemChanged(0); + } else { + lastItemsCount++; + dialogsAdapter.notifyItemInserted(0); + } + ArrayList dialogs = getDialogsArray(currentAccount, dialogsType, folderId, false); + frozenDialogsList.add(0, dialogs.get(0)); + } else if (added == 1) { + RecyclerView.ViewHolder holder = listView.findViewHolderForAdapterPosition(0); + if (holder != null && holder.itemView instanceof DialogCell) { + DialogCell cell = (DialogCell) holder.itemView; + cell.checkCurrentDialogIndex(true); + cell.animateArchiveAvatar(); + } + } + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + boolean hintShowed = preferences.getBoolean("archivehint_l", false); + preferences.edit().putBoolean("archivehint_l", true).commit(); + getUndoView().showWithAction(dialog.id, hintShowed ? UndoView.ACTION_ARCHIVE : UndoView.ACTION_ARCHIVE_HINT, null, () -> { + dialogsListFrozen = true; + getMessagesController().addDialogToFolder(dialog.id, 0, pinnedNum, 0); + dialogsListFrozen = false; + ArrayList dialogs = getMessagesController().getDialogs(0); + int index = dialogs.indexOf(dialog); + if (index >= 0) { + ArrayList archivedDialogs = getMessagesController().getDialogs(1); + if (!archivedDialogs.isEmpty() || index != 1) { + dialogInsertFinished = 2; + setDialogsListFrozen(true); + dialogsItemAnimator.prepareForRemove(); + lastItemsCount++; + dialogsAdapter.notifyItemInserted(index); + } + if (archivedDialogs.isEmpty()) { + dialogs.remove(0); + if (index == 1) { + dialogChangeFinished = 2; + setDialogsListFrozen(true); + dialogsAdapter.notifyItemChanged(0); + } else { + frozenDialogsList.remove(0); + dialogsItemAnimator.prepareForRemove(); + lastItemsCount--; + dialogsAdapter.notifyItemRemoved(0); + } + } + } else { + dialogsAdapter.notifyDataSetChanged(); + } + }); + } + if (folderId != 0 && frozenDialogsList.isEmpty()) { + listView.setEmptyView(null); + progressView.setVisibility(View.INVISIBLE); + } + }; + setDialogsListFrozen(true); + if (Utilities.random.nextInt(1000) == 1) { + if (pacmanAnimation == null) { + pacmanAnimation = new PacmanAnimation(listView); + } + pacmanAnimation.setFinishRunnable(finishRunnable); + pacmanAnimation.start(); + } else { + finishRunnable.run(); + } + } else { + slidingView = null; + } + } + + @Override + public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { + if (viewHolder != null) { + listView.hideSelector(); + } + super.onSelectedChanged(viewHolder, actionState); + } + + @Override + public long getAnimationDuration(RecyclerView recyclerView, int animationType, float animateDx, float animateDy) { + if (animationType == ItemTouchHelper.ANIMATION_TYPE_SWIPE_CANCEL) { + return 200; + } else if (animationType == ItemTouchHelper.ANIMATION_TYPE_DRAG) { + if (movingView != null) { + View view = movingView; + AndroidUtilities.runOnUIThread(() -> view.setBackgroundDrawable(null), dialogsItemAnimator.getMoveDuration()); + movingView = null; + } + } + return super.getAnimationDuration(recyclerView, animationType, animateDx, animateDy); + } + + @Override + public float getSwipeThreshold(RecyclerView.ViewHolder viewHolder) { + return 0.3f; + } + + @Override + public float getSwipeEscapeVelocity(float defaultValue) { + return 3500; + } + + @Override + public float getSwipeVelocityThreshold(float defaultValue) { + return Float.MAX_VALUE; + } + } + public interface DialogsActivityDelegate { void didSelectDialogs(DialogsActivity fragment, ArrayList dids, CharSequence message, boolean param); } @@ -192,6 +726,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. addToGroupAlertString = arguments.getString("addToGroupAlertString"); allowSwitchAccount = arguments.getBoolean("allowSwitchAccount"); checkCanWrite = arguments.getBoolean("checkCanWrite", true); + folderId = arguments.getInt("folderId", 0); } if (dialogsType == 0) { @@ -200,43 +735,44 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } if (searchString == null) { - currentConnectionState = ConnectionsManager.getInstance(currentAccount).getConnectionState(); + currentConnectionState = getConnectionsManager().getConnectionState(); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.dialogsNeedReload); + getNotificationCenter().addObserver(this, NotificationCenter.dialogsNeedReload); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiDidLoad); if (!onlySelect) { NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.closeSearchByActiveAction); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.proxySettingsChanged); } - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.updateInterfaces); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.encryptedChatUpdated); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.contactsDidLoad); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.appDidLogout); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.openedChatChanged); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.notificationsSettingsUpdated); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messageReceivedByAck); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messageReceivedByServer); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messageSendError); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.needReloadRecentDialogsSearch); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.replyMessagesDidLoad); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.reloadHints); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.didUpdateConnectionState); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.dialogsUnreadCounterChanged); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.needDeleteDialog); + getNotificationCenter().addObserver(this, NotificationCenter.updateInterfaces); + getNotificationCenter().addObserver(this, NotificationCenter.encryptedChatUpdated); + getNotificationCenter().addObserver(this, NotificationCenter.contactsDidLoad); + getNotificationCenter().addObserver(this, NotificationCenter.appDidLogout); + getNotificationCenter().addObserver(this, NotificationCenter.openedChatChanged); + getNotificationCenter().addObserver(this, NotificationCenter.notificationsSettingsUpdated); + getNotificationCenter().addObserver(this, NotificationCenter.messageReceivedByAck); + getNotificationCenter().addObserver(this, NotificationCenter.messageReceivedByServer); + getNotificationCenter().addObserver(this, NotificationCenter.messageSendError); + getNotificationCenter().addObserver(this, NotificationCenter.needReloadRecentDialogsSearch); + getNotificationCenter().addObserver(this, NotificationCenter.replyMessagesDidLoad); + getNotificationCenter().addObserver(this, NotificationCenter.reloadHints); + getNotificationCenter().addObserver(this, NotificationCenter.didUpdateConnectionState); + getNotificationCenter().addObserver(this, NotificationCenter.dialogsUnreadCounterChanged); + getNotificationCenter().addObserver(this, NotificationCenter.needDeleteDialog); + getNotificationCenter().addObserver(this, NotificationCenter.folderBecomeEmpty); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didSetPasscode); } if (!dialogsLoaded[currentAccount]) { - MessagesController.getInstance(currentAccount).loadGlobalNotificationsSettings(); - MessagesController.getInstance(currentAccount).loadDialogs(0, 100, true); - MessagesController.getInstance(currentAccount).loadHintDialogs(); - ContactsController.getInstance(currentAccount).checkInviteText(); - MessagesController.getInstance(currentAccount).loadPinnedDialogs(0, null); - DataQuery.getInstance(currentAccount).loadRecents(DataQuery.TYPE_FAVE, false, true, false); - DataQuery.getInstance(currentAccount).checkFeaturedStickers(); + getMessagesController().loadGlobalNotificationsSettings(); + getMessagesController().loadDialogs(folderId, 0, 100, true); + getMessagesController().loadHintDialogs(); + getContactsController().checkInviteText(); + getDataQuery().loadRecents(DataQuery.TYPE_FAVE, false, true, false); + getDataQuery().checkFeaturedStickers(); dialogsLoaded[currentAccount] = true; } + getMessagesController().loadPinnedDialogs(folderId, 0, null); return true; } @@ -244,35 +780,36 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. public void onFragmentDestroy() { super.onFragmentDestroy(); if (searchString == null) { - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.dialogsNeedReload); + getNotificationCenter().removeObserver(this, NotificationCenter.dialogsNeedReload); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiDidLoad); if (!onlySelect) { NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.closeSearchByActiveAction); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.proxySettingsChanged); } - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.updateInterfaces); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.encryptedChatUpdated); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.contactsDidLoad); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.appDidLogout); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.openedChatChanged); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.notificationsSettingsUpdated); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messageReceivedByAck); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messageReceivedByServer); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messageSendError); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.needReloadRecentDialogsSearch); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.replyMessagesDidLoad); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.reloadHints); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.didUpdateConnectionState); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.dialogsUnreadCounterChanged); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.needDeleteDialog); + getNotificationCenter().removeObserver(this, NotificationCenter.updateInterfaces); + getNotificationCenter().removeObserver(this, NotificationCenter.encryptedChatUpdated); + getNotificationCenter().removeObserver(this, NotificationCenter.contactsDidLoad); + getNotificationCenter().removeObserver(this, NotificationCenter.appDidLogout); + getNotificationCenter().removeObserver(this, NotificationCenter.openedChatChanged); + getNotificationCenter().removeObserver(this, NotificationCenter.notificationsSettingsUpdated); + getNotificationCenter().removeObserver(this, NotificationCenter.messageReceivedByAck); + getNotificationCenter().removeObserver(this, NotificationCenter.messageReceivedByServer); + getNotificationCenter().removeObserver(this, NotificationCenter.messageSendError); + getNotificationCenter().removeObserver(this, NotificationCenter.needReloadRecentDialogsSearch); + getNotificationCenter().removeObserver(this, NotificationCenter.replyMessagesDidLoad); + getNotificationCenter().removeObserver(this, NotificationCenter.reloadHints); + getNotificationCenter().removeObserver(this, NotificationCenter.didUpdateConnectionState); + getNotificationCenter().removeObserver(this, NotificationCenter.dialogsUnreadCounterChanged); + getNotificationCenter().removeObserver(this, NotificationCenter.needDeleteDialog); + getNotificationCenter().removeObserver(this, NotificationCenter.folderBecomeEmpty); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didSetPasscode); } if (commentView != null) { commentView.onDestroy(); } - if (undoView != null) { - undoView.hide(true, false); + if (undoView[0] != null) { + undoView[0].hide(true, 0); } delegate = null; } @@ -281,13 +818,15 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. public View createView(final Context context) { searching = false; searchWas = false; + pacmanAnimation = null; AndroidUtilities.runOnUIThread(() -> Theme.createChatResources(context, false)); ActionBarMenu menu = actionBar.createMenu(); - if (!onlySelect && searchString == null) { + if (!onlySelect && searchString == null && folderId == 0) { proxyDrawable = new ProxyDrawable(context); proxyItem = menu.addItem(2, proxyDrawable); + proxyItem.setContentDescription(LocaleController.getString("ProxySettings", R.string.ProxySettings)); passcodeItem = menu.addItem(1, R.drawable.lock_close); updatePasscodeButton(); updateProxyButton(false); @@ -313,6 +852,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } updatePasscodeButton(); + actionBar.setBackButtonContentDescription(LocaleController.getString("AccDescrGoBack", R.string.AccDescrGoBack)); } @Override @@ -335,7 +875,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. searching = false; searchWas = false; if (listView != null) { - listView.setEmptyView(progressView); + listView.setEmptyView(folderId == 0 ? progressView : null); searchEmptyView.setVisibility(View.GONE); if (!onlySelect) { floatingButtonContainer.setVisibility(View.VISIBLE); @@ -356,6 +896,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. dialogsSearchAdapter.searchDialogs(null); } updatePasscodeButton(); + if (menuDrawable != null) { + actionBar.setBackButtonContentDescription(LocaleController.getString("AccDescrOpenMenu", R.string.AccDescrOpenMenu)); + } } @Override @@ -369,9 +912,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } if (searchEmptyView != null && listView.getEmptyView() != searchEmptyView) { progressView.setVisibility(View.GONE); - searchEmptyView.showTextView(); listView.setEmptyView(searchEmptyView); } + searchEmptyView.showProgress(); } if (dialogsSearchAdapter != null) { dialogsSearchAdapter.searchDialogs(text); @@ -379,6 +922,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } }); item.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); + item.setContentDescription(LocaleController.getString("Search", R.string.Search)); if (onlySelect) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); if (dialogsType == 3 && selectAlertString == null) { @@ -387,21 +931,26 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. actionBar.setTitle(LocaleController.getString("SelectChat", R.string.SelectChat)); } } else { - if (searchString != null) { - actionBar.setBackButtonImage(R.drawable.ic_ab_back); + if (searchString != null || folderId != 0) { + actionBar.setBackButtonDrawable(backDrawable = new BackDrawable(false)); } else { - actionBar.setBackButtonDrawable(new MenuDrawable()); + actionBar.setBackButtonDrawable(menuDrawable = new MenuDrawable()); + actionBar.setBackButtonContentDescription(LocaleController.getString("AccDescrOpenMenu", R.string.AccDescrOpenMenu)); } - if (BuildVars.DEBUG_VERSION) { - actionBar.setTitle("Telegram Beta"/*LocaleController.getString("AppNameBeta", R.string.AppNameBeta)*/); + if (folderId != 0) { + actionBar.setTitle(LocaleController.getString("ArchivedChats", R.string.ArchivedChats)); } else { - actionBar.setTitle(LocaleController.getString("AppName", R.string.AppName)); + if (BuildVars.DEBUG_VERSION) { + actionBar.setTitle("Telegram Beta"/*LocaleController.getString("AppNameBeta", R.string.AppNameBeta)*/); + } else { + actionBar.setTitle(LocaleController.getString("AppName", R.string.AppName)); + } } actionBar.setSupportsHolidayImage(true); } actionBar.setTitleActionRunnable(() -> { hideFloatingButton(false); - listView.smoothScrollToPosition(0); + listView.smoothScrollToPosition(hasHiddenArchive() ? 1 : 0); }); if (allowSwitchAccount && UserConfig.getActivatedAccountsCount() > 1) { @@ -413,19 +962,13 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. imageView.setRoundRadius(AndroidUtilities.dp(18)); switchItem.addView(imageView, LayoutHelper.createFrame(36, 36, Gravity.CENTER)); - TLRPC.User user = UserConfig.getInstance(currentAccount).getCurrentUser(); + TLRPC.User user = getUserConfig().getCurrentUser(); avatarDrawable.setInfo(user); - TLRPC.FileLocation avatar; - if (user.photo != null && user.photo.photo_small != null && user.photo.photo_small.volume_id != 0 && user.photo.photo_small.local_id != 0) { - avatar = user.photo.photo_small; - } else { - avatar = null; - } imageView.getImageReceiver().setCurrentAccount(currentAccount); - imageView.setImage(avatar, "50_50", avatarDrawable, user); + imageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { - TLRPC.User u = UserConfig.getInstance(a).getCurrentUser(); + TLRPC.User u = AccountInstance.getInstance(a).getUserConfig().getCurrentUser(); if (u != null) { AccountSelectCell cell = new AccountSelectCell(context); cell.setAccount(a, true); @@ -439,7 +982,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. @Override public void onItemClick(int id) { if (id == -1) { - if (onlySelect) { + if (actionBar.isActionModeShowed()) { + hideActionMode(true); + } else if (onlySelect || folderId != 0) { finishFragment(); } else if (parentLayout != null) { parentLayout.getDrawerLayoutContainer().openDrawer(false); @@ -461,6 +1006,8 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. DialogsActivity dialogsActivity = new DialogsActivity(arguments); dialogsActivity.setDelegate(oldDelegate); launchActivity.presentFragment(dialogsActivity, false, true); + } else if (id == pin || id == read || id == delete || id == clear || id == mute || id == archive) { + perfromSelectedDialogsAction(id, true); } } }); @@ -471,153 +1018,159 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. sideMenu.getAdapter().notifyDataSetChanged(); } - SizeNotifierFrameLayout contentView = new SizeNotifierFrameLayout(context) { + final ActionBarMenu actionMode = actionBar.createActionMode(); - int inputFieldHeight = 0; + selectedDialogsCountTextView = new NumberTextView(actionMode.getContext()); + selectedDialogsCountTextView.setTextSize(18); + selectedDialogsCountTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + selectedDialogsCountTextView.setTextColor(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon)); + actionMode.addView(selectedDialogsCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 72, 0, 0, 0)); + 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)); + 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)); + 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(deleteItem); + actionModeViews.add(otherItem); + + ContentView contentView = new ContentView(context); + fragmentView = contentView; + + listView = new RecyclerListView(context) { + + private boolean firstLayout = true; + private boolean ignoreLayout; @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int widthSize = MeasureSpec.getSize(widthMeasureSpec); - int heightSize = MeasureSpec.getSize(heightMeasureSpec); - - setMeasuredDimension(widthSize, heightSize); - heightSize -= getPaddingTop(); - - measureChildWithMargins(actionBar, widthMeasureSpec, 0, heightMeasureSpec, 0); - - int keyboardSize = getKeyboardHeight(); - int childCount = getChildCount(); - - if (commentView != null) { - measureChildWithMargins(commentView, widthMeasureSpec, 0, heightMeasureSpec, 0); - Object tag = commentView.getTag(); - if (tag != null && tag.equals(2)) { - if (keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow) { - heightSize -= commentView.getEmojiPadding(); - } - inputFieldHeight = commentView.getMeasuredHeight(); - } else { - inputFieldHeight = 0; - } + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (slidingView != null && pacmanAnimation != null) { + pacmanAnimation.draw(canvas, slidingView.getTop() + slidingView.getMeasuredHeight() / 2); } + } - for (int i = 0; i < childCount; i++) { - View child = getChildAt(i); - if (child == null || child.getVisibility() == GONE || child == commentView || child == actionBar) { - continue; - } - if (child == listView || child == progressView || child == searchEmptyView) { - int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); - int contentHeightSpec = MeasureSpec.makeMeasureSpec(Math.max(AndroidUtilities.dp(10), heightSize - inputFieldHeight + AndroidUtilities.dp(2)), MeasureSpec.EXACTLY); - child.measure(contentWidthSpec, contentHeightSpec); - } else if (commentView != null && commentView.isPopupView(child)) { - if (AndroidUtilities.isInMultiwindow) { - if (AndroidUtilities.isTablet()) { - child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(Math.min(AndroidUtilities.dp(320), heightSize - inputFieldHeight - AndroidUtilities.statusBarHeight + getPaddingTop()), MeasureSpec.EXACTLY)); - } else { - child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(heightSize - inputFieldHeight - 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 + public void setAdapter(Adapter adapter) { + super.setAdapter(adapter); + firstLayout = true; + } + + private void checkIfAdapterValid() { + if (listView != null && dialogsAdapter != null && listView.getAdapter() == dialogsAdapter && lastItemsCount != dialogsAdapter.getItemCount()) { + ignoreLayout = true; + dialogsAdapter.notifyDataSetChanged(); + ignoreLayout = false; } } + @Override + protected void onMeasure(int widthSpec, int heightSpec) { + if (firstLayout && getMessagesController().dialogsLoaded) { + if (hasHiddenArchive()) { + ignoreLayout = true; + layoutManager.scrollToPositionWithOffset(1, 0); + ignoreLayout = false; + } + firstLayout = false; + } + checkIfAdapterValid(); + super.onMeasure(widthSpec, heightSpec); + } + @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { - final int count = getChildCount(); - - int paddingBottom; - Object tag = commentView != null ? commentView.getTag() : null; - if (tag != null && tag.equals(2)) { - paddingBottom = getKeyboardHeight() <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow ? commentView.getEmojiPadding() : 0; - } else { - paddingBottom = 0; + super.onLayout(changed, l, t, r, b); + if ((dialogRemoveFinished != 0 || dialogInsertFinished != 0 || dialogChangeFinished != 0) && !dialogsItemAnimator.isRunning()) { + onDialogAnimationFinished(); } - setBottomClip(paddingBottom); + } - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - if (child.getVisibility() == GONE) { - continue; - } - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - - final int width = child.getMeasuredWidth(); - final int height = child.getMeasuredHeight(); - - int childLeft; - int childTop; - - int gravity = lp.gravity; - if (gravity == -1) { - gravity = Gravity.TOP | Gravity.LEFT; - } - - final int absoluteGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK; - final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK; - - switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { - case Gravity.CENTER_HORIZONTAL: - childLeft = (r - l - width) / 2 + lp.leftMargin - lp.rightMargin; - break; - case Gravity.RIGHT: - childLeft = r - width - lp.rightMargin; - break; - case Gravity.LEFT: - default: - childLeft = lp.leftMargin; - } - - switch (verticalGravity) { - case Gravity.TOP: - childTop = lp.topMargin + getPaddingTop(); - break; - case Gravity.CENTER_VERTICAL: - childTop = ((b - paddingBottom) - t - height) / 2 + lp.topMargin - lp.bottomMargin; - break; - case Gravity.BOTTOM: - childTop = ((b - paddingBottom) - t) - height - lp.bottomMargin; - break; - default: - childTop = lp.topMargin; - } - - if (commentView != null && commentView.isPopupView(child)) { - if (AndroidUtilities.isInMultiwindow) { - childTop = commentView.getTop() - child.getMeasuredHeight() + AndroidUtilities.dp(1); - } else { - childTop = commentView.getBottom(); - } - } - child.layout(childLeft, childTop, childLeft + width, childTop + height); + @Override + public void requestLayout() { + if (ignoreLayout) { + return; } + super.requestLayout(); + } - notifyHeightChanged(); + @Override + public boolean onTouchEvent(MotionEvent e) { + if (waitingForScrollFinished || dialogRemoveFinished != 0 || dialogInsertFinished != 0 || dialogChangeFinished != 0) { + return false; + } + int action = e.getAction(); + if (!itemTouchhelper.isIdle() && swipeController.swipingFolder && (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP)) { + swipeController.swipeFolderBack = true; + if (itemTouchhelper.checkHorizontalSwipe(null, ItemTouchHelper.LEFT) != 0) { + SharedConfig.toggleArchiveHidden(); + getUndoView().showWithAction(0, UndoView.ACTION_ARCHIVE_PINNED, null, null); + } + } + return super.onTouchEvent(e); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent e) { + if (waitingForScrollFinished || dialogRemoveFinished != 0 || dialogInsertFinished != 0 || dialogChangeFinished != 0) { + return false; + } + if (e.getAction() == MotionEvent.ACTION_DOWN) { + allowSwipeDuringCurrentTouch = !actionBar.isActionModeShowed(); + checkIfAdapterValid(); + } + return super.onInterceptTouchEvent(e); } }; - fragmentView = contentView; - - listView = new RecyclerListView(context); + dialogsItemAnimator = new DialogsItemAnimator() { + @Override + public void onRemoveFinished(RecyclerView.ViewHolder item) { + if (dialogRemoveFinished == 2) { + dialogRemoveFinished = 1; + } + } + + @Override + public void onAddFinished(RecyclerView.ViewHolder item) { + if (dialogInsertFinished == 2) { + dialogInsertFinished = 1; + } + } + + @Override + public void onChangeFinished(RecyclerView.ViewHolder item, boolean oldItem) { + if (dialogChangeFinished == 2) { + dialogChangeFinished = 1; + } + } + + @Override + protected void onAllAnimationsDone() { + if (dialogRemoveFinished == 1 || dialogInsertFinished == 1 || dialogChangeFinished == 1) { + onDialogAnimationFinished(); + } + } + }; + listView.setItemAnimator(dialogsItemAnimator); listView.setVerticalScrollBarEnabled(true); - listView.setItemAnimator(null); listView.setInstantClick(true); - listView.setLayoutAnimation(null); listView.setTag(4); layoutManager = new LinearLayoutManager(context) { - @Override - public boolean supportsPredictiveItemAnimations() { - return false; - } - @Override public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { - LinearSmoothScrollerMiddle linearSmoothScroller = new LinearSmoothScrollerMiddle(recyclerView.getContext()); - linearSmoothScroller.setTargetPosition(position); - startSmoothScroll(linearSmoothScroller); + if (hasHiddenArchive() && position == 1) { + super.smoothScrollToPosition(recyclerView, state, position); + } else { + LinearSmoothScrollerMiddle linearSmoothScroller = new LinearSmoothScrollerMiddle(recyclerView.getContext()); + linearSmoothScroller.setTargetPosition(position); + startSmoothScroll(linearSmoothScroller); + } } }; layoutManager.setOrientation(LinearLayoutManager.VERTICAL); @@ -637,8 +1190,23 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. TLObject object = dialogsAdapter.getItem(position); if (object instanceof TLRPC.User) { dialog_id = ((TLRPC.User) object).id; - } else if (object instanceof TLRPC.TL_dialog) { - dialog_id = ((TLRPC.TL_dialog) object).id; + } else if (object instanceof TLRPC.Dialog) { + TLRPC.Dialog dialog = (TLRPC.Dialog) object; + if (dialog instanceof TLRPC.TL_dialogFolder) { + if (actionBar.isActionModeShowed()) { + return; + } + TLRPC.TL_dialogFolder dialogFolder = (TLRPC.TL_dialogFolder) dialog; + Bundle args = new Bundle(); + args.putInt("folderId", dialogFolder.folder.id); + presentFragment(new DialogsActivity(args)); + return; + } + dialog_id = dialog.id; + if (actionBar.isActionModeShowed()) { + showOrUpdateActionMode(dialog, view); + return; + } } else if (object instanceof TLRPC.TL_recentMeUrlChat) { dialog_id = -((TLRPC.TL_recentMeUrlChat) object).chat_id; } else if (object instanceof TLRPC.TL_recentMeUrlUser) { @@ -731,7 +1299,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. args.putInt("user_id", lower_part); } else if (lower_part < 0) { if (message_id != 0) { - TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_part); + 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; @@ -763,12 +1331,12 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } if (searchString != null) { - if (MessagesController.getInstance(currentAccount).checkCanOpenChat(args, DialogsActivity.this)) { - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats); + if (getMessagesController().checkCanOpenChat(args, DialogsActivity.this)) { + getNotificationCenter().postNotificationName(NotificationCenter.closeChats); presentFragment(new ChatActivity(args)); } } else { - if (MessagesController.getInstance(currentAccount).checkCanOpenChat(args, DialogsActivity.this)) { + if (getMessagesController().checkCanOpenChat(args, DialogsActivity.this)) { presentFragment(new ChatActivity(args)); } } @@ -780,7 +1348,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (getParentActivity() == null) { return false; } - if (!AndroidUtilities.isTablet() && !onlySelect && view instanceof DialogCell) { + if (!actionBar.isActionModeShowed() && !AndroidUtilities.isTablet() && !onlySelect && view instanceof DialogCell) { DialogCell cell = (DialogCell) view; if (cell.isPointInsideAvatar(x, y)) { long dialog_id = cell.getDialogId(); @@ -796,7 +1364,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. args.putInt("user_id", lower_part); } else if (lower_part < 0) { if (message_id != 0) { - TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_part); + 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; @@ -813,12 +1381,12 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. args.putInt("message_id", message_id); } if (searchString != null) { - if (MessagesController.getInstance(currentAccount).checkCanOpenChat(args, DialogsActivity.this)) { - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats); + if (getMessagesController().checkCanOpenChat(args, DialogsActivity.this)) { + getNotificationCenter().postNotificationName(NotificationCenter.closeChats); presentFragmentAsPreview(new ChatActivity(args)); } } else { - if (MessagesController.getInstance(currentAccount).checkCanOpenChat(args, DialogsActivity.this)) { + if (getMessagesController().checkCanOpenChat(args, DialogsActivity.this)) { presentFragmentAsPreview(new ChatActivity(args)); } } @@ -845,8 +1413,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } return false; } - final TLRPC.TL_dialog dialog; - ArrayList dialogs = getDialogsArray(dialogsType, currentAccount); + final TLRPC.Dialog dialog; + ArrayList dialogs = getDialogsArray(currentAccount, dialogsType, folderId, dialogsListFrozen); + position = dialogsAdapter.fixPosition(position); if (position < 0 || position >= dialogs.size()) { return false; } @@ -858,154 +1427,13 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. dialogsAdapter.addOrRemoveSelectedDialog(dialog.id, view); updateSelectedCount(); } else { - final long selectedDialog = dialog.id; - final boolean pinned = dialog.pinned; - - BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity()); - int lower_id = (int) selectedDialog; - int high_id = (int) (selectedDialog >> 32); - - final boolean hasUnread = dialog.unread_count != 0 || dialog.unread_mark; - - if (DialogObject.isChannel(dialog)) { - final TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_id); - CharSequence items[]; - int icons[] = new int[]{ - dialog.pinned ? R.drawable.chats_unpin : R.drawable.chats_pin, - hasUnread ? R.drawable.menu_read : R.drawable.menu_unread, - R.drawable.chats_clear, - R.drawable.chats_leave - }; - if (MessagesController.getInstance(currentAccount).isProxyDialog(dialog.id)) { - items = new CharSequence[]{ - null, - hasUnread ? LocaleController.getString("MarkAsRead", R.string.MarkAsRead) : LocaleController.getString("MarkAsUnread", R.string.MarkAsUnread), - LocaleController.getString("ClearHistoryCache", R.string.ClearHistoryCache), - null}; - } else if (chat != null && chat.megagroup) { - items = new CharSequence[]{ - dialog.pinned ? LocaleController.getString("UnpinFromTop", R.string.UnpinFromTop) : LocaleController.getString("PinToTop", R.string.PinToTop), - hasUnread ? LocaleController.getString("MarkAsRead", R.string.MarkAsRead) : LocaleController.getString("MarkAsUnread", R.string.MarkAsUnread), - TextUtils.isEmpty(chat.username) ? LocaleController.getString("ClearHistory", R.string.ClearHistory) : LocaleController.getString("ClearHistoryCache", R.string.ClearHistoryCache), - LocaleController.getString("LeaveMegaMenu", R.string.LeaveMegaMenu)}; - } else { - items = new CharSequence[]{ - dialog.pinned ? LocaleController.getString("UnpinFromTop", R.string.UnpinFromTop) : LocaleController.getString("PinToTop", R.string.PinToTop), - hasUnread ? LocaleController.getString("MarkAsRead", R.string.MarkAsRead) : LocaleController.getString("MarkAsUnread", R.string.MarkAsUnread), - LocaleController.getString("ClearHistoryCache", R.string.ClearHistoryCache), - LocaleController.getString("LeaveChannelMenu", R.string.LeaveChannelMenu)}; - } - builder.setItems(items, icons, (d, which) -> { - if (which == 0) { - if (!dialog.pinned && !MessagesController.getInstance(currentAccount).canPinDialog(false)) { - AlertsCreator.showSimpleAlert(DialogsActivity.this, LocaleController.formatString("PinToTopLimitReached", R.string.PinToTopLimitReached, LocaleController.formatPluralString("Chats", MessagesController.getInstance(currentAccount).maxPinnedDialogsCount))); - return; - } - if (MessagesController.getInstance(currentAccount).pinDialog(selectedDialog, !pinned, null, 0) && !pinned) { - hideFloatingButton(false); - listView.smoothScrollToPosition(0); - } - } else if (which == 1) { - if (hasUnread) { - MessagesController.getInstance(currentAccount).markMentionsAsRead(selectedDialog); - MessagesController.getInstance(currentAccount).markDialogAsRead(selectedDialog, dialog.top_message, dialog.top_message, dialog.last_message_date, false, 0, true); - } else { - MessagesController.getInstance(currentAccount).markDialogAsUnread(selectedDialog, null, 0); - } - } else { - AlertsCreator.createClearOrDeleteDialogAlert(DialogsActivity.this, which == 2, chat, null, lower_id == 0, () -> { - if (which == 2 && (!chat.megagroup || !TextUtils.isEmpty(chat.username))) { - MessagesController.getInstance(currentAccount).deleteDialog(selectedDialog, 2); - } else { - undoView.showWithAction(selectedDialog, which == 2, () -> { - if (which == 2) { - MessagesController.getInstance(currentAccount).deleteDialog(selectedDialog, 1); - } else { - MessagesController.getInstance(currentAccount).deleteUserFromChat((int) -selectedDialog, UserConfig.getInstance(currentAccount).getCurrentUser(), null); - if (AndroidUtilities.isTablet()) { - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats, selectedDialog); - } - } - }); - } - }); - } - }); - BottomSheet sheet = builder.create(); - showDialog(sheet); - sheet.setItemColor(3, Theme.getColor(Theme.key_dialogTextRed2), Theme.getColor(Theme.key_dialogRedIcon)); - } else { - final boolean isChat = lower_id < 0 && high_id != 1; - TLRPC.User user; - TLRPC.Chat chat = isChat ? MessagesController.getInstance(currentAccount).getChat(-lower_id) : null; - if (lower_id == 0) { - TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance(currentAccount).getEncryptedChat(high_id); - if (encryptedChat != null) { - user = MessagesController.getInstance(currentAccount).getUser(encryptedChat.user_id); - } else { - user = new TLRPC.TL_userEmpty(); - } - } else { - user = !isChat && lower_id > 0 && high_id != 1 ? MessagesController.getInstance(currentAccount).getUser(lower_id) : null; - } - final boolean isBot = user != null && user.bot && !MessagesController.isSupportUser(user); - - builder.setItems(new CharSequence[]{ - dialog.pinned ? LocaleController.getString("UnpinFromTop", R.string.UnpinFromTop) : LocaleController.getString("PinToTop", R.string.PinToTop), - hasUnread ? LocaleController.getString("MarkAsRead", R.string.MarkAsRead) : LocaleController.getString("MarkAsUnread", R.string.MarkAsUnread), - LocaleController.getString("ClearHistory", R.string.ClearHistory), - isChat ? LocaleController.getString("DeleteChat", R.string.DeleteChat) : isBot ? LocaleController.getString("DeleteAndStop", R.string.DeleteAndStop) : LocaleController.getString("Delete", R.string.Delete) - }, new int[]{ - dialog.pinned ? R.drawable.chats_unpin : R.drawable.chats_pin, - hasUnread ? R.drawable.menu_read : R.drawable.menu_unread, - R.drawable.chats_clear, - isChat ? R.drawable.chats_leave : R.drawable.chats_delete - }, (d, which) -> { - if (which == 0) { - if (!dialog.pinned && !MessagesController.getInstance(currentAccount).canPinDialog(lower_id == 0)) { - AlertsCreator.showSimpleAlert(DialogsActivity.this, LocaleController.formatString("PinToTopLimitReached", R.string.PinToTopLimitReached, LocaleController.formatPluralString("Chats", MessagesController.getInstance(currentAccount).maxPinnedDialogsCount))); - return; - } - if (MessagesController.getInstance(currentAccount).pinDialog(selectedDialog, !pinned, null, 0) && !pinned) { - hideFloatingButton(false); - listView.smoothScrollToPosition(0); - } - } else if (which == 1) { - if (hasUnread) { - MessagesController.getInstance(currentAccount).markMentionsAsRead(selectedDialog); - MessagesController.getInstance(currentAccount).markDialogAsRead(selectedDialog, dialog.top_message, dialog.top_message, dialog.last_message_date, false, 0, true); - } else { - MessagesController.getInstance(currentAccount).markDialogAsUnread(selectedDialog, null, 0); - } - } else { - AlertsCreator.createClearOrDeleteDialogAlert(DialogsActivity.this, which == 2, chat, user, lower_id == 0, () -> undoView.showWithAction(selectedDialog, which == 2, () -> { - if (which != 2) { - if (isChat) { - TLRPC.Chat currentChat = MessagesController.getInstance(currentAccount).getChat((int) -selectedDialog); - if (currentChat != null && ChatObject.isNotInChat(currentChat)) { - MessagesController.getInstance(currentAccount).deleteDialog(selectedDialog, 0); - } else { - MessagesController.getInstance(currentAccount).deleteUserFromChat((int) -selectedDialog, MessagesController.getInstance(currentAccount).getUser(UserConfig.getInstance(currentAccount).getClientUserId()), null); - } - } else { - MessagesController.getInstance(currentAccount).deleteDialog(selectedDialog, 0); - } - if (isBot) { - MessagesController.getInstance(currentAccount).blockUser((int) selectedDialog); - } - if (AndroidUtilities.isTablet()) { - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats, selectedDialog); - } - } else { - MessagesController.getInstance(currentAccount).deleteDialog(selectedDialog, 1); - } - })); - } - }); - BottomSheet sheet = builder.create(); - showDialog(sheet); - sheet.setItemColor(3, Theme.getColor(Theme.key_dialogTextRed2), Theme.getColor(Theme.key_dialogRedIcon)); + if (dialog instanceof TLRPC.TL_dialogFolder) { + return false; } + if (actionBar.isActionModeShowed() && dialog.pinned) { + return false; + } + showOrUpdateActionMode(dialog, view); } return true; } @@ -1020,6 +1448,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. movePreviewFragment(dy); } }); + swipeController = new SwipeController(); + + itemTouchhelper = new ItemTouchHelper(swipeController); + itemTouchhelper.attachToRecyclerView(listView); searchEmptyView = new EmptyTextProgressView(context); searchEmptyView.setVisibility(View.GONE); @@ -1032,7 +1464,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. contentView.addView(progressView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); floatingButtonContainer = new FrameLayout(context); - floatingButtonContainer.setVisibility(onlySelect ? View.GONE : View.VISIBLE); + floatingButtonContainer.setVisibility(onlySelect || folderId != 0 ? View.GONE : View.VISIBLE); contentView.addView(floatingButtonContainer, LayoutHelper.createFrame((Build.VERSION.SDK_INT >= 21 ? 56 : 60) + 20, (Build.VERSION.SDK_INT >= 21 ? 56 : 60) + 14, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.BOTTOM, LocaleController.isRTL ? 4 : 0, 0, LocaleController.isRTL ? 0 : 4, 0)); floatingButtonContainer.setOnClickListener(v -> { Bundle args = new Bundle(); @@ -1066,6 +1498,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } }); } + floatingButtonContainer.setContentDescription(LocaleController.getString("NewMessageTitle", R.string.NewMessageTitle)); floatingButtonContainer.addView(floatingButton, LayoutHelper.createFrame((Build.VERSION.SDK_INT >= 21 ? 56 : 60), (Build.VERSION.SDK_INT >= 21 ? 56 : 60), Gravity.LEFT | Gravity.TOP, 10, 0, 10, 0)); /*unreadFloatingButtonContainer = new FrameLayout(context); @@ -1080,10 +1513,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (listView.getAdapter() == dialogsAdapter) { int firstVisibleItem = layoutManager.findFirstVisibleItemPosition(); if (firstVisibleItem == 0) { - ArrayList array = getDialogsArray(); + ArrayList array = getDialogsArray(); for (int a = array.size() - 1; a >= 0; a--) { - TLRPC.TL_dialog dialog = array.get(a); - if ((dialog.unread_count != 0 || dialog.unread_mark) && !MessagesController.getInstance(currentAccount).isDialogMuted(dialog.id)) { + TLRPC.Dialog dialog = array.get(a); + if ((dialog.unread_count != 0 || dialog.unread_mark) && !getMessagesController().isDialogMuted(dialog.id)) { listView.smoothScrollToPosition(a); break; } @@ -1097,10 +1530,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (child.getTop() <= middle && child.getBottom() >= middle) { RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findContainingViewHolder(child); if (holder != null) { - ArrayList array = getDialogsArray(); + ArrayList array = getDialogsArray(); for (int a = Math.min(holder.getAdapterPosition(), array.size()) - 1; a >= 0; a--) { - TLRPC.TL_dialog dialog = array.get(a); - if ((dialog.unread_count != 0 || dialog.unread_mark) && !MessagesController.getInstance(currentAccount).isDialogMuted(dialog.id)) { + TLRPC.Dialog dialog = array.get(a); + if ((dialog.unread_count != 0 || dialog.unread_mark) && !getMessagesController().isDialogMuted(dialog.id)) { found = true; listView.smoothScrollToPosition(a); break; @@ -1187,6 +1620,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } else { scrollingManually = false; } + if (waitingForScrollFinished && newState == RecyclerView.SCROLL_STATE_IDLE) { + waitingForScrollFinished = false; + } } @Override @@ -1202,10 +1638,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. return; } if (visibleItemCount > 0) { - if (layoutManager.findLastVisibleItemPosition() >= getDialogsArray(dialogsType, currentAccount).size() - 10) { - boolean fromCache = !MessagesController.getInstance(currentAccount).dialogsEndReached; - if (fromCache || !MessagesController.getInstance(currentAccount).serverDialogsEndReached) { - MessagesController.getInstance(currentAccount).loadDialogs(-1, 100, fromCache); + if (layoutManager.findLastVisibleItemPosition() >= getDialogsArray(currentAccount, dialogsType, folderId, dialogsListFrozen).size() - 10) { + boolean fromCache = !getMessagesController().isDialogsEndReached(folderId); + if (fromCache || !getMessagesController().isServerDialogsEndReached(folderId)) { + AndroidUtilities.runOnUIThread(() -> getMessagesController().loadDialogs(folderId, -1, 100, fromCache)); } } } @@ -1238,7 +1674,13 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. }); if (searchString == null) { - dialogsAdapter = new DialogsAdapter(context, dialogsType, onlySelect); + dialogsAdapter = new DialogsAdapter(context, dialogsType, folderId, onlySelect) { + @Override + public void notifyDataSetChanged() { + lastItemsCount = getItemCount(); + super.notifyDataSetChanged(); + } + }; if (AndroidUtilities.isTablet() && openedDialogId != 0) { dialogsAdapter.setOpenedDialogId(openedDialogId); } @@ -1289,12 +1731,12 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } if (searchString != null) { - if (MessagesController.getInstance(currentAccount).checkCanOpenChat(args, DialogsActivity.this)) { - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats); + if (getMessagesController().checkCanOpenChat(args, DialogsActivity.this)) { + getNotificationCenter().postNotificationName(NotificationCenter.closeChats); presentFragment(new ChatActivity(args)); } } else { - if (MessagesController.getInstance(currentAccount).checkCanOpenChat(args, DialogsActivity.this)) { + if (getMessagesController().checkCanOpenChat(args, DialogsActivity.this)) { presentFragment(new ChatActivity(args)); } } @@ -1306,20 +1748,20 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (getParentActivity() == null) { return; } - TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(did); + TLRPC.User user = getMessagesController().getUser(did); if (user == null) { return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setMessage(LocaleController.formatString("ChatHintsDelete", R.string.ChatHintsDelete, ContactsController.formatName(user.first_name, user.last_name))); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> DataQuery.getInstance(currentAccount).removePeer(did)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> getDataQuery().removePeer(did)); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); } }); - listView.setEmptyView(progressView); + listView.setEmptyView(folderId == 0 ? progressView : null); if (searchString != null) { actionBar.openSearchField(searchString, false); } @@ -1442,30 +1884,49 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. }); } - undoView = new UndoView(context) { - @Override - public void setTranslationY(float translationY) { - super.setTranslationY(translationY); - float diff = getMeasuredHeight() - translationY; - if (!floatingHidden) { - floatingButtonContainer.setTranslationY(floatingButtonContainer.getTranslationY() + additionalFloatingTranslation - diff); + for (int a = 0; a < 2; a++) { + undoView[a] = new UndoView(context) { + @Override + public void setTranslationY(float translationY) { + super.setTranslationY(translationY); + if (this == undoView[0] && undoView[1].getVisibility() != VISIBLE) { + float diff = getMeasuredHeight() + AndroidUtilities.dp(8) - translationY; + if (!floatingHidden) { + floatingButtonContainer.setTranslationY(floatingButtonContainer.getTranslationY() + additionalFloatingTranslation - diff); + } + additionalFloatingTranslation = diff; + } } - additionalFloatingTranslation = diff; - } - }; - contentView.addView(undoView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT)); + + @Override + protected boolean canUndo() { + return !dialogsItemAnimator.isRunning(); + } + }; + contentView.addView(undoView[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT, 8, 0, 8, 8)); + } /*if (!onlySelect) { checkUnreadCount(false); }*/ + if (folderId != 0) { + actionBar.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultArchived)); + listView.setGlowColor(Theme.getColor(Theme.key_actionBarDefaultArchived)); + actionBar.setTitleColor(Theme.getColor(Theme.key_actionBarDefaultArchivedTitle)); + actionBar.setItemsColor(Theme.getColor(Theme.key_actionBarDefaultArchivedIcon), false); + actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultArchivedSelector), false); + actionBar.setSearchTextColor(Theme.getColor(Theme.key_actionBarDefaultArchivedSearch), false); + actionBar.setSearchTextColor(Theme.getColor(Theme.key_actionBarDefaultArchivedSearchPlaceholder), true); + } + return fragmentView; } @Override public void onResume() { super.onResume(); - if (dialogsAdapter != null) { + if (dialogsAdapter != null && !dialogsListFrozen) { dialogsAdapter.notifyDataSetChanged(); } if (commentView != null) { @@ -1478,15 +1939,17 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. Activity activity = getParentActivity(); if (activity != null) { checkPermission = false; - if (activity.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED || activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { - if (askAboutContacts && UserConfig.getInstance(currentAccount).syncContacts && activity.shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)) { + boolean hasNotContactsPermission = activity.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED; + boolean hasNotStoragePermission = activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED; + if (hasNotContactsPermission || hasNotStoragePermission) { + if (hasNotContactsPermission && askAboutContacts && getUserConfig().syncContacts && activity.shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)) { AlertDialog.Builder builder = AlertsCreator.createContactsPermissionDialog(activity, param -> { askAboutContacts = param != 0; MessagesController.getGlobalNotificationsSettings().edit().putBoolean("askAboutContacts", askAboutContacts).commit(); askForPermissons(false); }); showDialog(permissionDialog = builder.create()); - } else if (activity.shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + } else if (hasNotStoragePermission && activity.shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setMessage(LocaleController.getString("PermissionStorage", R.string.PermissionStorage)); @@ -1534,11 +1997,23 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (commentView != null) { commentView.onResume(); } - if (undoView != null) { - undoView.hide(true, false); + if (undoView[0] != null) { + undoView[0].hide(true, 0); } } + @Override + public boolean onBackPressed() { + if (actionBar != null && actionBar.isActionModeShowed()) { + hideActionMode(true); + return false; + } else if (commentView != null && commentView.isPopupShowing()) { + commentView.hidePopup(true); + return false; + } + return super.onBackPressed(); + } + @Override protected void onBecomeFullyHidden() { if (closeSearchFieldOnHide) { @@ -1551,11 +2026,519 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } closeSearchFieldOnHide = false; } - if (undoView != null) { - undoView.hide(true, false); + if (undoView[0] != null) { + undoView[0].hide(true, 0); } } + private boolean hasHiddenArchive() { + return !onlySelect && dialogsType == 0 && folderId == 0 && getMessagesController().hasHiddenArchive(); + } + + private boolean waitingForDialogsAnimationEnd() { + return dialogsItemAnimator.isRunning() || dialogRemoveFinished != 0 || dialogInsertFinished != 0 || dialogChangeFinished != 0; + } + + private void onDialogAnimationFinished() { + dialogRemoveFinished = 0; + dialogInsertFinished = 0; + dialogChangeFinished = 0; + AndroidUtilities.runOnUIThread(() -> { + if (folderId != 0 && frozenDialogsList.isEmpty()) { + listView.setEmptyView(null); + progressView.setVisibility(View.INVISIBLE); + finishFragment(); + } + setDialogsListFrozen(false); + updateDialogIndices(); + }); + } + + private void hideActionMode(boolean animateCheck) { + actionBar.hideActionMode(); + if (menuDrawable != null) { + actionBar.setBackButtonContentDescription(LocaleController.getString("AccDescrOpenMenu", R.string.AccDescrOpenMenu)); + } + dialogsAdapter.getSelectedDialogs().clear(); + if (menuDrawable != null) { + menuDrawable.setRotation(0, true); + } else if (backDrawable != null) { + backDrawable.setRotation(0, true); + } + allowMoving = false; + if (movingWas) { + getMessagesController().reorderPinnedDialogs(folderId, null, 0); + movingWas = false; + } + updateCounters(true); + dialogsAdapter.onReorderStateChanged(false); + updateVisibleRows(MessagesController.UPDATE_MASK_REORDER | MessagesController.UPDATE_MASK_CHECK | (animateCheck ? MessagesController.UPDATE_MASK_CHAT : 0)); + } + + private int getPinnedCount() { + int pinnedCount = 0; + ArrayList dialogs = getMessagesController().getDialogs(folderId); + for (int a = 0, N = dialogs.size(); a < N; a++) { + TLRPC.Dialog dialog = dialogs.get(a); + if (dialog instanceof TLRPC.TL_dialogFolder) { + continue; + } + int lower_id = (int) dialog.id; + if (dialog.pinned) { + pinnedCount++; + } else { + break; + } + } + return pinnedCount; + } + + private void perfromSelectedDialogsAction(int action, boolean alert) { + if (getParentActivity() == null) { + return; + } + ArrayList selectedDialogs = dialogsAdapter.getSelectedDialogs(); + int count = selectedDialogs.size(); + if (action == archive) { + ArrayList copy = new ArrayList<>(selectedDialogs); + getMessagesController().addDialogToFolder(copy, folderId == 0 ? 1 : 0, -1, null, 0); + hideActionMode(false); + if (folderId == 0) { + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + boolean hintShowed = preferences.getBoolean("archivehint_l", false); + preferences.edit().putBoolean("archivehint_l", true).commit(); + int undoAction; + if (hintShowed) { + undoAction = copy.size() > 1 ? UndoView.ACTION_ARCHIVE_FEW : UndoView.ACTION_ARCHIVE; + } else { + undoAction = copy.size() > 1 ? UndoView.ACTION_ARCHIVE_FEW_HINT : UndoView.ACTION_ARCHIVE_HINT; + } + getUndoView().showWithAction(0, undoAction, null, () -> getMessagesController().addDialogToFolder(copy, folderId == 0 ? 0 : 1, -1, null, 0)); + } else { + ArrayList dialogs = getMessagesController().getDialogs(folderId); + if (dialogs.isEmpty()) { + listView.setEmptyView(null); + progressView.setVisibility(View.INVISIBLE); + finishFragment(); + } + } + return; + } else if (action == pin && canPinCount != 0) { + int pinnedCount = 0; + int pinnedSecretCount = 0; + int newPinnedCount = 0; + int newPinnedSecretCount = 0; + ArrayList dialogs = getMessagesController().getDialogs(folderId); + for (int a = 0, N = dialogs.size(); a < N; a++) { + TLRPC.Dialog dialog = dialogs.get(a); + if (dialog instanceof TLRPC.TL_dialogFolder) { + continue; + } + int lower_id = (int) dialog.id; + if (dialog.pinned) { + if (lower_id == 0) { + pinnedSecretCount++; + } else { + pinnedCount++; + } + } else { + break; + } + } + for (int a = 0; a < count; a++) { + long selectedDialog = selectedDialogs.get(a); + TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(selectedDialog); + if (dialog == null || dialog.pinned) { + continue; + } + int lower_id = (int) selectedDialog; + if (lower_id == 0) { + newPinnedSecretCount++; + } else { + newPinnedCount++; + } + } + int maxPinnedCount; + if (folderId != 0) { + maxPinnedCount = getMessagesController().maxFolderPinnedDialogsCount; + } else { + maxPinnedCount = getMessagesController().maxPinnedDialogsCount; + } + if (newPinnedSecretCount + pinnedSecretCount > maxPinnedCount || newPinnedCount + pinnedCount > maxPinnedCount) { + AlertsCreator.showSimpleToast(DialogsActivity.this, LocaleController.formatString("PinToTopLimitReached", R.string.PinToTopLimitReached, LocaleController.formatPluralString("Chats", maxPinnedCount))); + AndroidUtilities.shakeView(pinItem, 2, 0); + Vibrator v = (Vibrator) getParentActivity().getSystemService(Context.VIBRATOR_SERVICE); + if (v != null) { + v.vibrate(200); + } + return; + } + } else if ((action == delete || action == clear) && count > 1 && alert) { + if (alert) { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + if (action == delete) { + builder.setTitle(LocaleController.formatString("DeleteFewChatsTitle", R.string.DeleteFewChatsTitle, LocaleController.formatPluralString("ChatsSelected", count))); + builder.setMessage(LocaleController.getString("AreYouSureDeleteFewChats", R.string.AreYouSureDeleteFewChats)); + builder.setPositiveButton(LocaleController.getString("Delete", R.string.Delete), (dialog1, which) -> { + getMessagesController().setDialogsInTransaction(true); + perfromSelectedDialogsAction(action, false); + getMessagesController().setDialogsInTransaction(false); + MessagesController.getInstance(currentAccount).checkIfFolderEmpty(folderId); + if (folderId != 0 && getDialogsArray(currentAccount, dialogsType, folderId, false).size() == 0) { + listView.setEmptyView(null); + progressView.setVisibility(View.INVISIBLE); + finishFragment(); + } + }); + } else { + if (canClearCacheCount != 0) { + builder.setTitle(LocaleController.formatString("ClearCacheFewChatsTitle", R.string.ClearCacheFewChatsTitle, LocaleController.formatPluralString("ChatsSelectedClearCache", count))); + builder.setMessage(LocaleController.getString("AreYouSureClearHistoryCacheFewChats", R.string.AreYouSureClearHistoryCacheFewChats)); + builder.setPositiveButton(LocaleController.getString("ClearHistoryCache", R.string.ClearHistoryCache), (dialog1, which) -> perfromSelectedDialogsAction(action, false)); + } else { + builder.setTitle(LocaleController.formatString("ClearFewChatsTitle", R.string.ClearFewChatsTitle, LocaleController.formatPluralString("ChatsSelectedClear", count))); + builder.setMessage(LocaleController.getString("AreYouSureClearHistoryFewChats", R.string.AreYouSureClearHistoryFewChats)); + builder.setPositiveButton(LocaleController.getString("ClearHistory", R.string.ClearHistory), (dialog1, which) -> perfromSelectedDialogsAction(action, false)); + } + } + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + AlertDialog alertDialog = builder.create(); + showDialog(alertDialog); + TextView button = (TextView) alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); + if (button != null) { + button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); + } + return; + } + } + boolean scrollToTop = false; + for (int a = 0; a < count; a++) { + long selectedDialog = selectedDialogs.get(a); + TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(selectedDialog); + if (dialog == null) { + continue; + } + TLRPC.Chat chat; + TLRPC.User user = null; + int lower_id = (int) selectedDialog; + int high_id = (int) (selectedDialog >> 32); + if (lower_id != 0) { + if (lower_id > 0) { + user = getMessagesController().getUser(lower_id); + chat = null; + } else { + chat = getMessagesController().getChat(-lower_id); + } + } else { + TLRPC.EncryptedChat encryptedChat = getMessagesController().getEncryptedChat(high_id); + chat = null; + if (encryptedChat != null) { + user = getMessagesController().getUser(encryptedChat.user_id); + } else { + user = new TLRPC.TL_userEmpty(); + } + } + if (chat == null && user == null) { + continue; + } + boolean isBot = user != null && user.bot && !MessagesController.isSupportUser(user); + if (action == pin) { + if (canPinCount != 0) { + if (dialog.pinned) { + continue; + } + if (getMessagesController().pinDialog(selectedDialog, true, null, -1)) { + scrollToTop = true; + } + } else { + if (!dialog.pinned) { + continue; + } + if (getMessagesController().pinDialog(selectedDialog, false, null, -1)) { + scrollToTop = true; + } + } + } 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); + } else { + getMessagesController().markDialogAsUnread(selectedDialog, null, 0); + } + } else if (action == delete || action == clear) { + if (count == 1) { + AlertsCreator.createClearOrDeleteDialogAlert(DialogsActivity.this, action == clear, chat, user, lower_id == 0, (param) -> { + hideActionMode(false); + if (action == clear && ChatObject.isChannel(chat) && (!chat.megagroup || !TextUtils.isEmpty(chat.username))) { + getMessagesController().deleteDialog(selectedDialog, 2, param); + } else { + if (action == delete && folderId != 0 && getDialogsArray(currentAccount, dialogsType, folderId, false).size() == 1) { + progressView.setVisibility(View.INVISIBLE); + } + getUndoView().showWithAction(selectedDialog, action == clear ? UndoView.ACTION_CLEAR : UndoView.ACTION_DELETE, () -> { + if (action == clear) { + getMessagesController().deleteDialog(selectedDialog, 1, param); + } else { + if (chat != null) { + if (ChatObject.isNotInChat(chat)) { + getMessagesController().deleteDialog(selectedDialog, 0, param); + } else { + TLRPC.User currentUser = getMessagesController().getUser(getUserConfig().getClientUserId()); + getMessagesController().deleteUserFromChat((int) -selectedDialog, currentUser, null); + } + } else { + getMessagesController().deleteDialog(selectedDialog, 0, param); + if (isBot) { + getMessagesController().blockUser((int) selectedDialog); + } + } + if (AndroidUtilities.isTablet()) { + getNotificationCenter().postNotificationName(NotificationCenter.closeChats, selectedDialog); + } + MessagesController.getInstance(currentAccount).checkIfFolderEmpty(folderId); + } + }); + } + }); + return; + } else { + if (action == clear && canClearCacheCount != 0) { + getMessagesController().deleteDialog(selectedDialog, 2, false); + } else { + if (action == clear) { + getMessagesController().deleteDialog(selectedDialog, 1, false); + } else { + if (chat != null) { + if (ChatObject.isNotInChat(chat)) { + getMessagesController().deleteDialog(selectedDialog, 0, false); + } else { + TLRPC.User currentUser = getMessagesController().getUser(getUserConfig().getClientUserId()); + getMessagesController().deleteUserFromChat((int) -selectedDialog, currentUser, null); + } + } else { + getMessagesController().deleteDialog(selectedDialog, 0, false); + if (isBot) { + getMessagesController().blockUser((int) selectedDialog); + } + } + if (AndroidUtilities.isTablet()) { + getNotificationCenter().postNotificationName(NotificationCenter.closeChats, selectedDialog); + } + } + } + } + } else if (action == mute) { + if (count == 1 && canMuteCount == 1) { + showDialog(AlertsCreator.createMuteAlert(getParentActivity(), selectedDialog), dialog12 -> hideActionMode(true)); + return; + } else { + if (canUnmuteCount != 0) { + if (!getMessagesController().isDialogMuted(selectedDialog)) { + continue; + } + getNotificationsController().setDialogNotificationsSettings(selectedDialog, NotificationsController.SETTING_MUTE_UNMUTE); + } else { + if (getMessagesController().isDialogMuted(selectedDialog)) { + continue; + } + getNotificationsController().setDialogNotificationsSettings(selectedDialog, NotificationsController.SETTING_MUTE_FOREVER); + } + } + } + } + if (action == pin) { + getMessagesController().reorderPinnedDialogs(folderId, null, 0); + } + if (scrollToTop) { + hideFloatingButton(false); + listView.smoothScrollToPosition(hasHiddenArchive() ? 1 : 0); + } + hideActionMode(action != pin && action != delete); + } + + private void updateCounters(boolean hide) { + int canClearHistoryCount = 0; + int canDeleteCount = 0; + int canUnpinCount = 0; + int canArchiveCount = 0; + int canUnarchiveCount = 0; + canUnmuteCount = 0; + canMuteCount = 0; + canPinCount = 0; + canReadCount = 0; + canClearCacheCount = 0; + if (hide) { + return; + } + ArrayList selectedDialogs = dialogsAdapter.getSelectedDialogs(); + int count = selectedDialogs.size(); + for (int a = 0; a < count; a++) { + TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(selectedDialogs.get(a)); + if (dialog == null) { + continue; + } + + long selectedDialog = dialog.id; + boolean pinned = dialog.pinned; + boolean hasUnread = dialog.unread_count != 0 || dialog.unread_mark; + if (getMessagesController().isDialogMuted(selectedDialog)) { + canUnmuteCount++; + } else { + canMuteCount++; + } + + if (hasUnread) { + canReadCount++; + } + + if (folderId == 1) { + canUnarchiveCount++; + } else if (selectedDialog != getUserConfig().getClientUserId() && selectedDialog != 777000) { + canArchiveCount++; + } + + int lower_id = (int) selectedDialog; + int high_id = (int) (selectedDialog >> 32); + + if (DialogObject.isChannel(dialog)) { + final TLRPC.Chat chat = getMessagesController().getChat(-lower_id); + CharSequence[] items; + if (getMessagesController().isProxyDialog(dialog.id)) { + canClearCacheCount++; + } else { + if (pinned) { + canUnpinCount++; + } else { + canPinCount++; + } + if (chat != null && chat.megagroup) { + if (TextUtils.isEmpty(chat.username)) { + canClearHistoryCount++; + } else { + canClearCacheCount++; + } + canDeleteCount++; + } else { + canClearCacheCount++; + canDeleteCount++; + } + } + } else { + final boolean isChat = lower_id < 0 && high_id != 1; + TLRPC.User user; + TLRPC.Chat chat = isChat ? getMessagesController().getChat(-lower_id) : null; + if (lower_id == 0) { + TLRPC.EncryptedChat encryptedChat = getMessagesController().getEncryptedChat(high_id); + if (encryptedChat != null) { + user = getMessagesController().getUser(encryptedChat.user_id); + } else { + user = new TLRPC.TL_userEmpty(); + } + } else { + user = !isChat && lower_id > 0 && high_id != 1 ? getMessagesController().getUser(lower_id) : null; + } + final boolean isBot = user != null && user.bot && !MessagesController.isSupportUser(user); + + if (pinned) { + canUnpinCount++; + } else { + canPinCount++; + } + canClearHistoryCount++; + canDeleteCount++; + } + } + if (canDeleteCount != count) { + deleteItem.setVisibility(View.GONE); + } else { + deleteItem.setVisibility(View.VISIBLE); + } + if (canClearCacheCount != 0 && canClearCacheCount != count || canClearHistoryCount != 0 && canClearHistoryCount != count) { + clearItem.setVisibility(View.GONE); + } else { + clearItem.setVisibility(View.VISIBLE); + if (canClearCacheCount != 0) { + clearItem.setText(LocaleController.getString("ClearHistoryCache", R.string.ClearHistoryCache)); + } else { + clearItem.setText(LocaleController.getString("ClearHistory", R.string.ClearHistory)); + } + } + if (canUnarchiveCount != 0) { + archiveItem.setIcon(R.drawable.msg_unarchive); + archiveItem.setContentDescription(LocaleController.getString("Unarchive", R.string.Unarchive)); + } 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); + } + if (canPinCount + canUnpinCount != count) { + pinItem.setVisibility(View.GONE); + } else { + pinItem.setVisibility(View.VISIBLE); + } + if (canUnmuteCount != 0) { + muteItem.setTextAndIcon(LocaleController.getString("ChatsUnmute", R.string.ChatsUnmute), R.drawable.msg_unmute); + } else { + muteItem.setTextAndIcon(LocaleController.getString("ChatsMute", R.string.ChatsMute), R.drawable.msg_mute); + } + if (canReadCount != 0) { + readItem.setTextAndIcon(LocaleController.getString("MarkAsRead", R.string.MarkAsRead), R.drawable.msg_markread); + } else { + readItem.setTextAndIcon(LocaleController.getString("MarkAsUnread", R.string.MarkAsUnread), R.drawable.msg_markunread); + } + if (canPinCount != 0) { + pinItem.setIcon(R.drawable.msg_pin); + pinItem.setContentDescription(LocaleController.getString("PinToTop", R.string.PinToTop)); + } else { + pinItem.setIcon(R.drawable.msg_unpin); + pinItem.setContentDescription(LocaleController.getString("UnpinFromTop", R.string.UnpinFromTop)); + } + } + + private void showOrUpdateActionMode(TLRPC.Dialog dialog, View cell) { + dialogsAdapter.addOrRemoveSelectedDialog(dialog.id, cell); + ArrayList selectedDialogs = dialogsAdapter.getSelectedDialogs(); + boolean updateAnimated = false; + if (actionBar.isActionModeShowed()) { + if (selectedDialogs.isEmpty()) { + hideActionMode(true); + return; + } + updateAnimated = true; + } else { + final ActionBarMenu actionMode = actionBar.createActionMode(); + actionBar.showActionMode(); + if (menuDrawable != null) { + actionBar.setBackButtonContentDescription(LocaleController.getString("AccDescrGoBack", R.string.AccDescrGoBack)); + } + if (getPinnedCount() > 1) { + dialogsAdapter.onReorderStateChanged(true); + updateVisibleRows(MessagesController.UPDATE_MASK_REORDER); + } + + AnimatorSet animatorSet = new AnimatorSet(); + ArrayList animators = new ArrayList<>(); + for (int a = 0; a < actionModeViews.size(); a++) { + View view = actionModeViews.get(a); + view.setPivotY(ActionBar.getCurrentActionBarHeight() / 2); + AndroidUtilities.clearDrawableAnimation(view); + animators.add(ObjectAnimator.ofFloat(view, View.SCALE_Y, 0.1f, 1.0f)); + } + animatorSet.playTogether(animators); + animatorSet.setDuration(250); + animatorSet.start(); + if (menuDrawable != null) { + menuDrawable.setRotateToBack(false); + menuDrawable.setRotation(1, true); + } else if (backDrawable != null) { + backDrawable.setRotation(1, true); + } + } + updateCounters(false); + selectedDialogsCountTextView.setNumber(selectedDialogs.size(), updateAnimated); + } + private void closeSearch() { if (AndroidUtilities.isTablet()) { if (actionBar != null) { @@ -1574,7 +2557,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (!BuildVars.DEBUG_PRIVATE_VERSION) { return; } - int newCount = MessagesController.getInstance(currentAccount).unreadUnmutedDialogs; + int newCount = getMessagesController().unreadUnmutedDialogs; if (newCount != currentUnreadCount) { currentUnreadCount = newCount; if (unreadFloatingButtonContainer != null) { @@ -1608,12 +2591,12 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (child.getTop() <= middle && child.getBottom() >= middle) { RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findContainingViewHolder(child); if (holder != null) { - ArrayList array = getDialogsArray(); + ArrayList array = getDialogsArray(); if (firstVisibleItem == 0) { if (unreadOnScreen != currentUnreadCount) { for (int a = holder.getAdapterPosition() + 1, size = array.size(); a < size; a++) { - TLRPC.TL_dialog dialog = array.get(a); - if ((dialog.unread_count != 0 || dialog.unread_mark) && !MessagesController.getInstance(currentAccount).isDialogMuted(dialog.id)) { + TLRPC.Dialog dialog = array.get(a); + if ((dialog.unread_count != 0 || dialog.unread_mark) && !getMessagesController().isDialogMuted(dialog.id)) { arrowDrawable.setAnimationProgressAnimated(1.0f); found = true; break; @@ -1635,7 +2618,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. unreadFloatingButtonContainer.setTag(1); unreadFloatingButtonContainer.setVisibility(View.VISIBLE); if (animated) { - unreadFloatingButtonContainer.animate().alpha(1.0f).setDuration(200).setInterpolator(new DecelerateInterpolator()).setListener(null).start(); + unreadFloatingButtonContainer.animate().alpha(1.0f).setDuration(200).setInterpolator(new DecelerateInterpolator()).setDelegate(null).start(); } else { unreadFloatingButtonContainer.setAlpha(1.0f); } @@ -1644,7 +2627,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (unreadFloatingButtonContainer.getTag() != null) { unreadFloatingButtonContainer.setTag(null); if (animated) { - unreadFloatingButtonContainer.animate().alpha(0.0f).setDuration(200).setInterpolator(new DecelerateInterpolator()).setListener(new AnimatorListenerAdapter() { + unreadFloatingButtonContainer.animate().alpha(0.0f).setDuration(200).setInterpolator(new DecelerateInterpolator()).setDelegate(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { unreadFloatingButtonContainer.setVisibility(View.INVISIBLE); @@ -1659,6 +2642,19 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } }*/ + private UndoView getUndoView() { + if (undoView[0].getVisibility() == View.VISIBLE) { + UndoView old = undoView[0]; + undoView[0] = undoView[1]; + undoView[1] = old; + old.hide(true, 2); + ContentView contentView = (ContentView) fragmentView; + contentView.removeView(undoView[0]); + contentView.addView(undoView[0]); + } + return undoView[0]; + } + private void updateProxyButton(boolean animated) { if (proxyDrawable == null) { return; @@ -1666,7 +2662,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); String proxyAddress = preferences.getString("proxy_ip", ""); boolean proxyEnabled; - if ((proxyEnabled = preferences.getBoolean("proxy_enabled", false) && !TextUtils.isEmpty(proxyAddress)) || MessagesController.getInstance(currentAccount).blockedCountry && !SharedConfig.proxyList.isEmpty()) { + if ((proxyEnabled = preferences.getBoolean("proxy_enabled", false) && !TextUtils.isEmpty(proxyAddress)) || getMessagesController().blockedCountry && !SharedConfig.proxyList.isEmpty()) { if (!actionBar.isSearchFieldVisible()) { proxyItem.setVisibility(View.VISIBLE); } @@ -1717,6 +2713,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. @Override public void onAnimationEnd(Animator animation) { commentView.setTag(2); + commentView.requestLayout(); } }); animatorSet.start(); @@ -1733,7 +2730,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. return; } ArrayList permissons = new ArrayList<>(); - if (UserConfig.getInstance(currentAccount).syncContacts && askAboutContacts && activity.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { + if (getUserConfig().syncContacts && askAboutContacts && activity.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { if (alert) { AlertDialog.Builder builder = AlertsCreator.createContactsPermissionDialog(activity, param -> { askAboutContacts = param != 0; @@ -1754,7 +2751,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (permissons.isEmpty()) { return; } - String[] items = permissons.toArray(new String[permissons.size()]); + String[] items = permissons.toArray(new String[0]); try { activity.requestPermissions(items, 1); } catch (Exception ignore) { @@ -1764,7 +2761,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. @Override protected void onDialogDismiss(Dialog dialog) { super.onDialogDismiss(dialog); - if (permissionDialog != null && dialog == permissionDialog && getParentActivity() != null && askAboutContacts) { + if (permissionDialog != null && dialog == permissionDialog && getParentActivity() != null) { askForPermissons(false); } } @@ -1797,7 +2794,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. switch (permissions[a]) { case Manifest.permission.READ_CONTACTS: if (grantResults[a] == PackageManager.PERMISSION_GRANTED) { - ContactsController.getInstance(currentAccount).forceImportContacts(); + getContactsController().forceImportContacts(); } else { MessagesController.getGlobalNotificationsSettings().edit().putBoolean("askAboutContacts", askAboutContacts = false).commit(); } @@ -1813,9 +2810,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } @Override - @SuppressWarnings("unchecked") public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.dialogsNeedReload) { + if (dialogsListFrozen) { + return; + } //checkUnreadCount(true); if (dialogsAdapter != null) { if (dialogsAdapter.isDataSetChanged() || args.length > 0) { @@ -1828,7 +2827,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. try { if (listView.getAdapter() == dialogsAdapter) { searchEmptyView.setVisibility(View.GONE); - listView.setEmptyView(progressView); + listView.setEmptyView(folderId == 0 ? progressView : null); } else { if (searching && searchWas) { listView.setEmptyView(searchEmptyView); @@ -1853,15 +2852,18 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } else if (id == NotificationCenter.updateInterfaces) { Integer mask = (Integer) args[0]; updateVisibleRows(mask); - if ((mask & MessagesController.UPDATE_MASK_NEW_MESSAGE) != 0 || (mask & MessagesController.UPDATE_MASK_READ_DIALOG_MESSAGE) != 0) { - //checkUnreadCount(true); - } + /*if ((mask & MessagesController.UPDATE_MASK_NEW_MESSAGE) != 0 || (mask & MessagesController.UPDATE_MASK_READ_DIALOG_MESSAGE) != 0) { + checkUnreadCount(true); + }*/ } else if (id == NotificationCenter.appDidLogout) { dialogsLoaded[currentAccount] = false; } else if (id == NotificationCenter.encryptedChatUpdated) { updateVisibleRows(0); } else if (id == NotificationCenter.contactsDidLoad) { - if (dialogsType == 0 && MessagesController.getInstance(currentAccount).dialogs.isEmpty()) { + if (dialogsListFrozen) { + return; + } + if (dialogsType == 0 && getMessagesController().getDialogs(folderId).isEmpty()) { if (dialogsAdapter != null) { dialogsAdapter.notifyDataSetChanged(); } @@ -1901,7 +2903,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. dialogsSearchAdapter.notifyDataSetChanged(); } } else if (id == NotificationCenter.didUpdateConnectionState) { - int state = ConnectionsManager.getInstance(account).getConnectionState(); + int state = AccountInstance.getInstance(account).getConnectionsManager().getConnectionState(); if (currentConnectionState != state) { currentConnectionState = state; updateProxyButton(true); @@ -1914,10 +2916,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. unreadFloatingButtonCounter.setText(String.format("%d", count)); unreadFloatingButtonContainer.setVisibility(View.VISIBLE); unreadFloatingButtonContainer.setTag(1); - unreadFloatingButtonContainer.animate().alpha(1.0f).setDuration(200).setInterpolator(new DecelerateInterpolator()).setListener(null).start(); + unreadFloatingButtonContainer.animate().alpha(1.0f).setDuration(200).setInterpolator(new DecelerateInterpolator()).setDelegate(null).start(); } else { unreadFloatingButtonContainer.setTag(null); - unreadFloatingButtonContainer.animate().alpha(0.0f).setDuration(200).setInterpolator(new DecelerateInterpolator()).setListener(new AnimatorListenerAdapter() { + unreadFloatingButtonContainer.animate().alpha(0.0f).setDuration(200).setInterpolator(new DecelerateInterpolator()).setDelegate(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { unreadFloatingButtonContainer.setVisibility(View.INVISIBLE); @@ -1926,40 +2928,69 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } }*/ } else if (id == NotificationCenter.needDeleteDialog) { - if (undoView != null) { - long dialogId = (Long) args[0]; - TLRPC.User user = (TLRPC.User) args[1]; - TLRPC.Chat chat = (TLRPC.Chat) args[2]; - undoView.showWithAction(dialogId, false, () -> { - if (chat != null) { - if (ChatObject.isNotInChat(chat)) { - MessagesController.getInstance(currentAccount).deleteDialog(dialogId, 0); - } else { - MessagesController.getInstance(currentAccount).deleteUserFromChat((int) -dialogId, MessagesController.getInstance(currentAccount).getUser(UserConfig.getInstance(currentAccount).getClientUserId()), null); - } + long dialogId = (Long) args[0]; + TLRPC.User user = (TLRPC.User) args[1]; + TLRPC.Chat chat = (TLRPC.Chat) args[2]; + boolean revoke = (Boolean) args[3]; + Runnable deleteRunnable = () -> { + if (chat != null) { + if (ChatObject.isNotInChat(chat)) { + getMessagesController().deleteDialog(dialogId, 0, revoke); } else { - MessagesController.getInstance(currentAccount).deleteDialog(dialogId, 0); + getMessagesController().deleteUserFromChat((int) -dialogId, getMessagesController().getUser(getUserConfig().getClientUserId()), null, false, revoke); } - }); + } else { + getMessagesController().deleteDialog(dialogId, 0, revoke); + } + }; + if (undoView[0] != null) { + getUndoView().showWithAction(dialogId, UndoView.ACTION_DELETE, deleteRunnable); + } else { + deleteRunnable.run(); + } + } else if (id == NotificationCenter.folderBecomeEmpty) { + int fid = (Integer) args[0]; + if (folderId == fid && folderId != 0) { + finishFragment(); } } } - public static ArrayList getDialogsArray(int dialogsType, int currentAccount) { + private void setDialogsListFrozen(boolean frozen) { + if (dialogsListFrozen == frozen) { + return; + } + if (frozen) { + frozenDialogsList = new ArrayList<>(getDialogsArray(currentAccount, dialogsType, folderId, false)); + } else { + frozenDialogsList = null; + } + dialogsListFrozen = frozen; + dialogsAdapter.setDialogsListFrozen(frozen); + if (!frozen) { + dialogsAdapter.notifyDataSetChanged(); + } + } + + public static ArrayList getDialogsArray(int currentAccount, int dialogsType, int folderId, boolean frozen) { + if (frozen && frozenDialogsList != null) { + return frozenDialogsList; + } + MessagesController messagesController = AccountInstance.getInstance(currentAccount).getMessagesController(); if (dialogsType == 0) { - return MessagesController.getInstance(currentAccount).dialogs; + return messagesController.getDialogs(folderId); } else if (dialogsType == 1) { - return MessagesController.getInstance(currentAccount).dialogsServerOnly; + return messagesController.dialogsServerOnly; } else if (dialogsType == 2) { - return MessagesController.getInstance(currentAccount).dialogsCanAddUsers; + return messagesController.dialogsCanAddUsers; } else if (dialogsType == 3) { - return MessagesController.getInstance(currentAccount).dialogsForward; + return messagesController.dialogsForward; } else if (dialogsType == 4) { - return MessagesController.getInstance(currentAccount).dialogsUsersOnly; + return messagesController.dialogsUsersOnly; } else if (dialogsType == 5) { - return MessagesController.getInstance(currentAccount).dialogsChannelsOnly; + return messagesController.dialogsChannelsOnly; } else if (dialogsType == 6) { - return MessagesController.getInstance(currentAccount).dialogsGroupsOnly; + return messagesController.dialogsGroupsOnly; } return null; } @@ -1978,8 +3009,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. passcodeItem.setVisibility(View.VISIBLE); if (SharedConfig.appLocked) { passcodeItem.setIcon(R.drawable.lock_close); + passcodeItem.setContentDescription(LocaleController.getString("AccDescrPasscodeUnlock", R.string.AccDescrPasscodeUnlock)); } else { passcodeItem.setIcon(R.drawable.lock_open); + passcodeItem.setContentDescription(LocaleController.getString("AccDescrPasscodeLock", R.string.AccDescrPasscodeLock)); } } else { passcodeItem.setVisibility(View.GONE); @@ -2000,8 +3033,31 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. animatorSet.start(); } + private void updateDialogIndices() { + if (listView == null || listView.getAdapter() != dialogsAdapter) { + return; + } + ArrayList dialogs = getDialogsArray(currentAccount, dialogsType, folderId, false); + int count = listView.getChildCount(); + for (int a = 0; a < count; a++) { + View child = listView.getChildAt(a); + if (child instanceof DialogCell) { + DialogCell dialogCell = (DialogCell) child; + TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(dialogCell.getDialogId()); + if (dialog == null) { + continue; + } + int index = dialogs.indexOf(dialog); + if (index < 0) { + continue; + } + dialogCell.setDialogIndex(index); + } + } + } + private void updateVisibleRows(int mask) { - if (listView == null) { + if (listView == null || dialogsListFrozen) { return; } int count = listView.getChildCount(); @@ -2010,17 +3066,28 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (child instanceof DialogCell) { if (listView.getAdapter() != dialogsSearchAdapter) { DialogCell cell = (DialogCell) child; - if ((mask & MessagesController.UPDATE_MASK_NEW_MESSAGE) != 0) { - cell.checkCurrentDialogIndex(); - if (dialogsType == 0 && AndroidUtilities.isTablet()) { - cell.setDialogSelected(cell.getDialogId() == openedDialogId); - } - } else if ((mask & MessagesController.UPDATE_MASK_SELECT_DIALOG) != 0) { - if (dialogsType == 0 && AndroidUtilities.isTablet()) { - cell.setDialogSelected(cell.getDialogId() == openedDialogId); - } + if ((mask & MessagesController.UPDATE_MASK_REORDER) != 0) { + cell.onReorderStateChanged(actionBar.isActionModeShowed(), true); + } + if ((mask & MessagesController.UPDATE_MASK_CHECK) != 0) { + cell.setChecked(false, (mask & MessagesController.UPDATE_MASK_CHAT) != 0); } else { - cell.update(mask); + if ((mask & MessagesController.UPDATE_MASK_NEW_MESSAGE) != 0) { + cell.checkCurrentDialogIndex(dialogsListFrozen); + if (dialogsType == 0 && AndroidUtilities.isTablet()) { + cell.setDialogSelected(cell.getDialogId() == openedDialogId); + } + } else if ((mask & MessagesController.UPDATE_MASK_SELECT_DIALOG) != 0) { + if (dialogsType == 0 && AndroidUtilities.isTablet()) { + cell.setDialogSelected(cell.getDialogId() == openedDialogId); + } + } else { + cell.update(mask); + } + ArrayList selectedDialogs = dialogsAdapter.getSelectedDialogs(); + if (selectedDialogs != null) { + cell.setChecked(selectedDialogs.contains(cell.getDialogId()), false); + } } } } else if (child instanceof UserCell) { @@ -2055,7 +3122,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. private void didSelectResult(final long dialog_id, boolean useAlert, final boolean param) { if (addToGroupAlertString == null && checkCanWrite) { if ((int) dialog_id < 0) { - TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-(int) dialog_id); + TLRPC.Chat chat = getMessagesController().getChat(-(int) dialog_id); if (ChatObject.isChannel(chat) && !chat.megagroup && (cantSendToChannels || !ChatObject.isCanWriteToChannel(-(int) dialog_id, currentAccount))) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); @@ -2076,22 +3143,22 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. int high_id = (int) (dialog_id >> 32); if (lower_part != 0) { if (high_id == 1) { - TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(lower_part); + TLRPC.Chat chat = getMessagesController().getChat(lower_part); if (chat == null) { return; } builder.setMessage(LocaleController.formatStringSimple(selectAlertStringGroup, chat.title)); } else { - if (lower_part == UserConfig.getInstance(currentAccount).getClientUserId()) { + if (lower_part == getUserConfig().getClientUserId()) { builder.setMessage(LocaleController.formatStringSimple(selectAlertStringGroup, LocaleController.getString("SavedMessages", R.string.SavedMessages))); } else if (lower_part > 0) { - TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(lower_part); + 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 = MessagesController.getInstance(currentAccount).getChat(-lower_part); + TLRPC.Chat chat = getMessagesController().getChat(-lower_part); if (chat == null) { return; } @@ -2103,8 +3170,8 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } } else { - TLRPC.EncryptedChat chat = MessagesController.getInstance(currentAccount).getEncryptedChat(high_id); - TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(chat.user_id); + TLRPC.EncryptedChat chat = getMessagesController().getEncryptedChat(high_id); + TLRPC.User user = getMessagesController().getUser(chat.user_id); if (user == null) { return; } @@ -2153,181 +3220,305 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } }; - return new ThemeDescription[]{ - new ThemeDescription(fragmentView, 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), - new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon), - new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, new Drawable[]{Theme.dialogs_holidayDrawable}, null, Theme.key_actionBarDefaultTitle), - new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector), - new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCH, null, null, null, null, Theme.key_actionBarDefaultSearch), - new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCHPLACEHOLDER, null, null, null, null, Theme.key_actionBarDefaultSearchPlaceholder), + ArrayList arrayList = new ArrayList<>(); - new ThemeDescription(listView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector), + arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite)); - new ThemeDescription(listView, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider), + if (movingView != null) { + arrayList.add(new ThemeDescription(movingView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite)); + } - new ThemeDescription(searchEmptyView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_emptyListPlaceholder), - new ThemeDescription(searchEmptyView, ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_progressCircle), + if (folderId == 0) { + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault)); + arrayList.add(new ThemeDescription(listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, new Drawable[]{Theme.dialogs_holidayDrawable}, null, Theme.key_actionBarDefaultTitle)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCH, null, null, null, null, Theme.key_actionBarDefaultSearch)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCHPLACEHOLDER, null, null, null, null, Theme.key_actionBarDefaultSearchPlaceholder)); + } else { + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefaultArchived)); + arrayList.add(new ThemeDescription(listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefaultArchived)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultArchivedIcon)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, new Drawable[]{Theme.dialogs_holidayDrawable}, null, Theme.key_actionBarDefaultArchivedTitle)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultArchivedSelector)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCH, null, null, null, null, Theme.key_actionBarDefaultArchivedSearch)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCHPLACEHOLDER, null, null, null, null, Theme.key_actionBarDefaultArchivedSearchPlaceholder)); + } - new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{DialogsEmptyCell.class}, new String[]{"emptyTextView1"}, null, null, null, Theme.key_emptyListPlaceholder), - new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{DialogsEmptyCell.class}, new String[]{"emptyTextView2"}, null, null, null, Theme.key_emptyListPlaceholder), + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_AM_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarActionModeDefaultIcon)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_AM_BACKGROUND, null, null, null, null, Theme.key_actionBarActionModeDefault)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_AM_TOPBACKGROUND, null, null, null, null, Theme.key_actionBarActionModeDefaultTop)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_AM_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarActionModeDefaultSelector)); + arrayList.add(new ThemeDescription(selectedDialogsCountTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_actionBarActionModeDefaultIcon)); - new ThemeDescription(floatingButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chats_actionIcon), - new ThemeDescription(floatingButton, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chats_actionBackground), - new ThemeDescription(floatingButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_chats_actionPressedBackground), + arrayList.add(new ThemeDescription(listView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector)); - /*new ThemeDescription(unreadFloatingButtonCounter, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chat_goDownButtonCounterBackground), - new ThemeDescription(unreadFloatingButtonCounter, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_goDownButtonCounter), - new ThemeDescription(unreadFloatingButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chats_actionUnreadIcon), - 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[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider)); - new ThemeDescription(listView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.avatar_broadcastDrawable, 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), - new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundGreen), - new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundCyan), - new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundBlue), - new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundPink), - new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundSaved), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_countPaint, null, null, Theme.key_chats_unreadCounter), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_countGrayPaint, null, null, Theme.key_chats_unreadCounterMuted), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_countTextPaint, null, null, Theme.key_chats_unreadCounterText), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, Theme.dialogs_namePaint, null, null, Theme.key_chats_name), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, Theme.dialogs_nameEncryptedPaint, null, null, Theme.key_chats_secretName), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_lockDrawable}, null, Theme.key_chats_secretIcon), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_groupDrawable, Theme.dialogs_broadcastDrawable, Theme.dialogs_botDrawable}, null, Theme.key_chats_nameIcon), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_pinnedDrawable}, null, Theme.key_chats_pinnedIcon), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_messagePaint, null, null, Theme.key_chats_message), - new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_chats_nameMessage), - new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_chats_draft), - new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_chats_attachMessage), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_messagePrintingPaint, null, null, Theme.key_chats_actionMessage), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_timePaint, null, null, Theme.key_chats_date), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_pinnedPaint, null, null, Theme.key_chats_pinnedOverlay), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_tabletSeletedPaint, null, null, Theme.key_chats_tabletSelectedOverlay), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_checkDrawable, Theme.dialogs_halfCheckDrawable}, null, Theme.key_chats_sentCheck), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_clockDrawable}, null, Theme.key_chats_sentClock), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_errorPaint, null, null, Theme.key_chats_sentError), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_errorDrawable}, null, Theme.key_chats_sentErrorIcon), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_verifiedCheckDrawable}, null, Theme.key_chats_verifiedCheck), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_verifiedDrawable}, null, Theme.key_chats_verifiedBackground), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_muteDrawable}, null, Theme.key_chats_muteIcon), - new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_mentionDrawable}, null, Theme.key_chats_mentionIcon), + arrayList.add(new ThemeDescription(searchEmptyView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_emptyListPlaceholder)); + arrayList.add(new ThemeDescription(searchEmptyView, ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_progressCircle)); - new ThemeDescription(sideMenu, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_chats_menuBackground), - new ThemeDescription(sideMenu, 0, new Class[]{DrawerProfileCell.class}, null, null, null, Theme.key_chats_menuName), - new ThemeDescription(sideMenu, 0, new Class[]{DrawerProfileCell.class}, null, null, null, Theme.key_chats_menuPhone), - new ThemeDescription(sideMenu, 0, new Class[]{DrawerProfileCell.class}, null, null, null, Theme.key_chats_menuPhoneCats), - new ThemeDescription(sideMenu, 0, new Class[]{DrawerProfileCell.class}, null, null, null, Theme.key_chats_menuCloudBackgroundCats), - new ThemeDescription(sideMenu, 0, new Class[]{DrawerProfileCell.class}, null, null, null, Theme.key_chat_serviceBackground), - new ThemeDescription(sideMenu, 0, new Class[]{DrawerProfileCell.class}, null, null, null, Theme.key_chats_menuTopShadow), - new ThemeDescription(sideMenu, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{DrawerProfileCell.class}, null, null, null, Theme.key_avatar_backgroundActionBarBlue), + arrayList.add(new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{DialogsEmptyCell.class}, new String[]{"emptyTextView1"}, null, null, null, Theme.key_chats_nameMessage_threeLines)); + arrayList.add(new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{DialogsEmptyCell.class}, new String[]{"emptyTextView2"}, null, null, null, Theme.key_chats_message)); - new ThemeDescription(sideMenu, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{DrawerActionCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chats_menuItemIcon), - new ThemeDescription(sideMenu, 0, new Class[]{DrawerActionCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chats_menuItemText), + arrayList.add(new ThemeDescription(floatingButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chats_actionIcon)); + arrayList.add(new ThemeDescription(floatingButton, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chats_actionBackground)); + arrayList.add(new ThemeDescription(floatingButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_chats_actionPressedBackground)); - new ThemeDescription(sideMenu, 0, new Class[]{DrawerUserCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chats_menuItemText), - new ThemeDescription(sideMenu, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{DrawerUserCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_chats_unreadCounterText), - new ThemeDescription(sideMenu, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{DrawerUserCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_chats_unreadCounter), - new ThemeDescription(sideMenu, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{DrawerUserCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_chats_menuBackground), - new ThemeDescription(sideMenu, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{DrawerAddCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chats_menuItemIcon), - new ThemeDescription(sideMenu, 0, new Class[]{DrawerAddCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chats_menuItemText), + /*new ThemeDescription(unreadFloatingButtonCounter, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chat_goDownButtonCounterBackground)); + new ThemeDescription(unreadFloatingButtonCounter, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_goDownButtonCounter)); + new ThemeDescription(unreadFloatingButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chats_actionUnreadIcon)); + 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));*/ - new ThemeDescription(sideMenu, 0, new Class[]{DividerCell.class}, Theme.dividerPaint, null, null, Theme.key_divider), + 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(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)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundGreen)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundCyan)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundBlue)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundPink)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundSaved)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundArchived)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundArchivedHidden)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_countPaint, null, null, Theme.key_chats_unreadCounter)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_countGrayPaint, null, null, Theme.key_chats_unreadCounterMuted)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_countTextPaint, null, null, Theme.key_chats_unreadCounterText)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, Theme.dialogs_namePaint, null, null, Theme.key_chats_name)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, Theme.dialogs_nameEncryptedPaint, null, null, Theme.key_chats_secretName)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_lockDrawable}, null, Theme.key_chats_secretIcon)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_groupDrawable, Theme.dialogs_broadcastDrawable, Theme.dialogs_botDrawable}, null, Theme.key_chats_nameIcon)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_scamDrawable}, null, Theme.key_chats_draft)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_pinnedDrawable, Theme.dialogs_reorderDrawable}, null, Theme.key_chats_pinnedIcon)); + if (SharedConfig.useThreeLinesLayout) { + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_messagePaint, null, null, Theme.key_chats_message_threeLines)); + } else { + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_messagePaint, null, null, Theme.key_chats_message)); + } + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_messageNamePaint, null, null, Theme.key_chats_nameMessage_threeLines)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, null, null, Theme.key_chats_draft)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_chats_nameMessage)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_chats_draft)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_chats_attachMessage)); - new ThemeDescription(listView, 0, new Class[]{LoadingCell.class}, new String[]{"progressBar"}, null, null, null, Theme.key_progressCircle), + arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_chats_nameArchived)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_chats_nameMessageArchived)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_chats_nameMessageArchived_threeLines)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_chats_messageArchived)); - new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, Theme.dialogs_offlinePaint, null, null, Theme.key_windowBackgroundWhiteGrayText3), - new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, Theme.dialogs_onlinePaint, null, null, Theme.key_windowBackgroundWhiteBlueText3), + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, Theme.dialogs_messagePrintingPaint, null, null, Theme.key_chats_actionMessage)); + 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_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)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_verifiedCheckDrawable}, null, Theme.key_chats_verifiedCheck)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_verifiedDrawable}, null, Theme.key_chats_verifiedBackground)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_muteDrawable}, null, Theme.key_chats_muteIcon)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_mentionDrawable}, null, Theme.key_chats_mentionIcon)); - 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), + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, null, null, Theme.key_chats_archivePinBackground)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, null, null, Theme.key_chats_archiveBackground)); - new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{HashtagSearchCell.class}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), + if (SharedConfig.archiveHidden) { + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{Theme.dialogs_archiveAvatarDrawable}, "Arrow1", Theme.key_avatar_backgroundArchivedHidden)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{Theme.dialogs_archiveAvatarDrawable}, "Arrow2", Theme.key_avatar_backgroundArchivedHidden)); + } else { + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{Theme.dialogs_archiveAvatarDrawable}, "Arrow1", Theme.key_avatar_backgroundArchived)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{Theme.dialogs_archiveAvatarDrawable}, "Arrow2", Theme.key_avatar_backgroundArchived)); + } + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{Theme.dialogs_archiveAvatarDrawable}, "Box2", Theme.key_avatar_text)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{Theme.dialogs_archiveAvatarDrawable}, "Box1", Theme.key_avatar_text)); - new ThemeDescription(progressView, ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_progressCircle), + if (Theme.dialogs_pinArchiveDrawable instanceof LottieDrawable) { + LottieDrawable lottieDrawable = (LottieDrawable) Theme.dialogs_pinArchiveDrawable; + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{lottieDrawable}, "Arrow", Theme.key_chats_archiveIcon)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{lottieDrawable}, "Line", Theme.key_chats_archiveIcon)); + } else { + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_pinArchiveDrawable}, null, Theme.key_chats_archiveIcon)); + } - new ThemeDescription(dialogsSearchAdapter != null ? dialogsSearchAdapter.getInnerListView() : null, 0, new Class[]{HintDialogCell.class}, Theme.dialogs_countPaint, null, null, Theme.key_chats_unreadCounter), - new ThemeDescription(dialogsSearchAdapter != null ? dialogsSearchAdapter.getInnerListView() : null, 0, new Class[]{HintDialogCell.class}, Theme.dialogs_countGrayPaint, null, null, Theme.key_chats_unreadCounterMuted), - new ThemeDescription(dialogsSearchAdapter != null ? dialogsSearchAdapter.getInnerListView() : null, 0, new Class[]{HintDialogCell.class}, Theme.dialogs_countTextPaint, null, null, Theme.key_chats_unreadCounterText), - new ThemeDescription(dialogsSearchAdapter != null ? dialogsSearchAdapter.getInnerListView() : null, 0, new Class[]{HintDialogCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), - new ThemeDescription(dialogsSearchAdapter != null ? dialogsSearchAdapter.getInnerListView() : null, 0, new Class[]{HintDialogCell.class}, null, null, null, Theme.key_chats_onlineCircle), + if (Theme.dialogs_unpinArchiveDrawable instanceof LottieDrawable) { + LottieDrawable lottieDrawable = (LottieDrawable) Theme.dialogs_unpinArchiveDrawable; + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{lottieDrawable}, "Arrow", Theme.key_chats_archiveIcon)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{lottieDrawable}, "Line", Theme.key_chats_archiveIcon)); + } else { + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_unpinArchiveDrawable}, null, Theme.key_chats_archiveIcon)); + } - new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"frameLayout"}, null, null, null, Theme.key_inappPlayerBackground), - new ThemeDescription(fragmentView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{FragmentContextView.class}, new String[]{"playButton"}, null, null, null, Theme.key_inappPlayerPlayPause), - new ThemeDescription(fragmentView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_inappPlayerTitle), - new ThemeDescription(fragmentView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_FASTSCROLL, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_inappPlayerPerformer), - new ThemeDescription(fragmentView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{FragmentContextView.class}, new String[]{"closeButton"}, null, null, null, Theme.key_inappPlayerClose), + if (Theme.dialogs_archiveDrawable instanceof LottieDrawable) { + LottieDrawable lottieDrawable = (LottieDrawable) Theme.dialogs_archiveDrawable; + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{lottieDrawable}, "Arrow", Theme.key_chats_archiveBackground)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{lottieDrawable}, "Box2", Theme.key_chats_archiveIcon)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{lottieDrawable}, "Box1", Theme.key_chats_archiveIcon)); + } else { + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_archiveDrawable}, null, Theme.key_chats_archiveIcon)); + } - new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"frameLayout"}, null, null, null, Theme.key_returnToCallBackground), - new ThemeDescription(fragmentView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_returnToCallText), + if (Theme.dialogs_unarchiveDrawable instanceof LottieDrawable) { + LottieDrawable lottieDrawable = (LottieDrawable) Theme.dialogs_unarchiveDrawable; + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{lottieDrawable}, "Arrow1", Theme.key_chats_archiveIcon)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{lottieDrawable}, "Arrow2", Theme.key_chats_archivePinBackground)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{lottieDrawable}, "Box2", Theme.key_chats_archiveIcon)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, new LottieDrawable[]{lottieDrawable}, "Box1", Theme.key_chats_archiveIcon)); + } else { + arrayList.add(new ThemeDescription(listView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_unarchiveDrawable}, null, Theme.key_chats_archiveIcon)); + } - new ThemeDescription(undoView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_undo_background), - new ThemeDescription(undoView, 0, new Class[]{UndoView.class}, new String[]{"undoImageView"}, null, null, null, Theme.key_undo_cancelColor), - new ThemeDescription(undoView, 0, new Class[]{UndoView.class}, new String[]{"undoTextView"}, null, null, null, Theme.key_undo_cancelColor), - new ThemeDescription(undoView, 0, new Class[]{UndoView.class}, new String[]{"infoTextView"}, null, null, null, Theme.key_undo_infoColor), - new ThemeDescription(undoView, 0, new Class[]{UndoView.class}, new String[]{"textPaint"}, null, null, null, Theme.key_undo_infoColor), - new ThemeDescription(undoView, 0, new Class[]{UndoView.class}, new String[]{"progressPaint"}, null, null, null, Theme.key_undo_infoColor), + arrayList.add(new ThemeDescription(sideMenu, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_chats_menuBackground)); + arrayList.add(new ThemeDescription(sideMenu, 0, new Class[]{DrawerProfileCell.class}, null, null, null, Theme.key_chats_menuName)); + arrayList.add(new ThemeDescription(sideMenu, 0, new Class[]{DrawerProfileCell.class}, null, null, null, Theme.key_chats_menuPhone)); + arrayList.add(new ThemeDescription(sideMenu, 0, new Class[]{DrawerProfileCell.class}, null, null, null, Theme.key_chats_menuPhoneCats)); + arrayList.add(new ThemeDescription(sideMenu, 0, new Class[]{DrawerProfileCell.class}, null, null, null, Theme.key_chats_menuCloudBackgroundCats)); + arrayList.add(new ThemeDescription(sideMenu, 0, new Class[]{DrawerProfileCell.class}, null, null, null, Theme.key_chat_serviceBackground)); + arrayList.add(new ThemeDescription(sideMenu, 0, new Class[]{DrawerProfileCell.class}, null, null, null, Theme.key_chats_menuTopShadow)); + arrayList.add(new ThemeDescription(sideMenu, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{DrawerProfileCell.class}, null, null, null, Theme.key_avatar_backgroundActionBarBlue)); - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogBackground), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogBackgroundGray), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextBlack), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextLink), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogLinkSelection), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextBlue), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextBlue2), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextBlue3), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextBlue4), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextRed), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextRed2), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextGray), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextGray2), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextGray3), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextGray4), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogIcon), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogRedIcon), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextHint), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogInputField), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogInputFieldActivated), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogCheckboxSquareBackground), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogCheckboxSquareCheck), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogCheckboxSquareUnchecked), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogCheckboxSquareDisabled), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogRadioBackground), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogRadioBackgroundChecked), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogProgressCircle), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogButton), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogButtonSelector), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogScrollGlow), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogRoundCheckBox), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogRoundCheckBoxCheck), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogBadgeBackground), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogBadgeText), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogLineProgress), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogLineProgressBackground), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogGrayLine), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialog_inlineProgressBackground), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialog_inlineProgress), + arrayList.add(new ThemeDescription(sideMenu, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{DrawerActionCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chats_menuItemIcon)); + arrayList.add(new ThemeDescription(sideMenu, 0, new Class[]{DrawerActionCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chats_menuItemText)); - new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_actionBar), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_actionBarSelector), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_actionBarTitle), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_actionBarTop), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_actionBarSubtitle), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_actionBarItems), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_background), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_time), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_progressBackground), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_progressCachedBackground), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_progress), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_placeholder), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_placeholderBackground), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_button), - new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_buttonActive), - }; + arrayList.add(new ThemeDescription(sideMenu, 0, new Class[]{DrawerUserCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chats_menuItemText)); + arrayList.add(new ThemeDescription(sideMenu, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{DrawerUserCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_chats_unreadCounterText)); + arrayList.add(new ThemeDescription(sideMenu, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{DrawerUserCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_chats_unreadCounter)); + arrayList.add(new ThemeDescription(sideMenu, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{DrawerUserCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_chats_menuBackground)); + arrayList.add(new ThemeDescription(sideMenu, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{DrawerAddCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chats_menuItemIcon)); + arrayList.add(new ThemeDescription(sideMenu, 0, new Class[]{DrawerAddCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chats_menuItemText)); + + arrayList.add(new ThemeDescription(sideMenu, 0, new Class[]{DividerCell.class}, Theme.dividerPaint, null, null, Theme.key_divider)); + + arrayList.add(new ThemeDescription(listView, 0, new Class[]{LoadingCell.class}, new String[]{"progressBar"}, null, null, null, Theme.key_progressCircle)); + + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, Theme.dialogs_offlinePaint, null, null, Theme.key_windowBackgroundWhiteGrayText3)); + arrayList.add(new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, Theme.dialogs_onlinePaint, null, null, Theme.key_windowBackgroundWhiteBlueText3)); + + arrayList.add(new ThemeDescription(listView, 0, new Class[]{GraySectionCell.class}, new String[]{"textView"}, null, null, null, Theme.key_graySectionText)); + arrayList.add(new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{GraySectionCell.class}, null, null, null, Theme.key_graySection)); + + arrayList.add(new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{HashtagSearchCell.class}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); + + arrayList.add(new ThemeDescription(progressView, ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_progressCircle)); + + arrayList.add(new ThemeDescription(dialogsAdapter != null ? dialogsAdapter.getArchiveHintCellPager() : null, 0, new Class[]{ArchiveHintInnerCell.class}, new String[]{"imageView"}, null, null, null, Theme.key_chats_nameMessage_threeLines)); + arrayList.add(new ThemeDescription(dialogsAdapter != null ? dialogsAdapter.getArchiveHintCellPager() : null, 0, new Class[]{ArchiveHintInnerCell.class}, new String[]{"imageView2"}, null, null, null, Theme.key_chats_unreadCounter)); + arrayList.add(new ThemeDescription(dialogsAdapter != null ? dialogsAdapter.getArchiveHintCellPager() : null, 0, new Class[]{ArchiveHintInnerCell.class}, new String[]{"headerTextView"}, null, null, null, Theme.key_chats_nameMessage_threeLines)); + arrayList.add(new ThemeDescription(dialogsAdapter != null ? dialogsAdapter.getArchiveHintCellPager() : null, 0, new Class[]{ArchiveHintInnerCell.class}, new String[]{"messageTextView"}, null, null, null, Theme.key_chats_message)); + arrayList.add(new ThemeDescription(dialogsAdapter != null ? dialogsAdapter.getArchiveHintCellPager() : null, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefaultArchived)); + + arrayList.add(new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow)); + arrayList.add(new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGray)); + + arrayList.add(new ThemeDescription(dialogsSearchAdapter != null ? dialogsSearchAdapter.getInnerListView() : null, 0, new Class[]{HintDialogCell.class}, Theme.dialogs_countPaint, null, null, Theme.key_chats_unreadCounter)); + arrayList.add(new ThemeDescription(dialogsSearchAdapter != null ? dialogsSearchAdapter.getInnerListView() : null, 0, new Class[]{HintDialogCell.class}, Theme.dialogs_countGrayPaint, null, null, Theme.key_chats_unreadCounterMuted)); + arrayList.add(new ThemeDescription(dialogsSearchAdapter != null ? dialogsSearchAdapter.getInnerListView() : null, 0, new Class[]{HintDialogCell.class}, Theme.dialogs_countTextPaint, null, null, Theme.key_chats_unreadCounterText)); + arrayList.add(new ThemeDescription(dialogsSearchAdapter != null ? dialogsSearchAdapter.getInnerListView() : null, 0, new Class[]{HintDialogCell.class}, Theme.dialogs_archiveTextPaint, null, null, Theme.key_chats_archiveText)); + arrayList.add(new ThemeDescription(dialogsSearchAdapter != null ? dialogsSearchAdapter.getInnerListView() : null, 0, new Class[]{HintDialogCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); + arrayList.add(new ThemeDescription(dialogsSearchAdapter != null ? dialogsSearchAdapter.getInnerListView() : null, 0, new Class[]{HintDialogCell.class}, null, null, null, Theme.key_chats_onlineCircle)); + + arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"frameLayout"}, null, null, null, Theme.key_inappPlayerBackground)); + arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{FragmentContextView.class}, new String[]{"playButton"}, null, null, null, Theme.key_inappPlayerPlayPause)); + arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_inappPlayerTitle)); + arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_FASTSCROLL, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_inappPlayerPerformer)); + arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{FragmentContextView.class}, new String[]{"closeButton"}, null, null, null, Theme.key_inappPlayerClose)); + + arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"frameLayout"}, null, null, null, Theme.key_returnToCallBackground)); + arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_returnToCallText)); + + for (int a = 0; a < undoView.length; a++) { + arrayList.add(new ThemeDescription(undoView[a], ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_undo_background)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"undoImageView"}, null, null, null, Theme.key_undo_cancelColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"undoTextView"}, null, null, null, Theme.key_undo_cancelColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"infoTextView"}, null, null, null, Theme.key_undo_infoColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"subinfoTextView"}, null, null, null, Theme.key_undo_infoColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"textPaint"}, null, null, null, Theme.key_undo_infoColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"progressPaint"}, null, null, null, Theme.key_undo_infoColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "info1", Theme.key_undo_background)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "info2", Theme.key_undo_background)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "luc12", Theme.key_undo_infoColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "luc11", Theme.key_undo_infoColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "luc10", Theme.key_undo_infoColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "luc9", Theme.key_undo_infoColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "luc8", Theme.key_undo_infoColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "luc7", Theme.key_undo_infoColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "luc6", Theme.key_undo_infoColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "luc5", Theme.key_undo_infoColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "luc4", Theme.key_undo_infoColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "luc3", Theme.key_undo_infoColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "luc2", Theme.key_undo_infoColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "luc1", Theme.key_undo_infoColor)); + arrayList.add(new ThemeDescription(undoView[a], 0, new Class[]{UndoView.class}, new String[]{"leftImageView"}, "Oval", Theme.key_undo_infoColor)); + } + + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogBackground)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogBackgroundGray)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextBlack)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextLink)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogLinkSelection)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextBlue)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextBlue2)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextBlue3)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextBlue4)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextRed)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextRed2)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextGray)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextGray2)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextGray3)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextGray4)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogIcon)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogRedIcon)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogTextHint)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogInputField)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogInputFieldActivated)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogCheckboxSquareBackground)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogCheckboxSquareCheck)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogCheckboxSquareUnchecked)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogCheckboxSquareDisabled)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogRadioBackground)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogRadioBackgroundChecked)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogProgressCircle)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogButton)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogButtonSelector)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogScrollGlow)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogRoundCheckBox)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogRoundCheckBoxCheck)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogBadgeBackground)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogBadgeText)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogLineProgress)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogLineProgressBackground)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogGrayLine)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialog_inlineProgressBackground)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialog_inlineProgress)); + + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogSearchBackground)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogSearchHint)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogSearchIcon)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogSearchText)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogFloatingButton)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogFloatingIcon)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_dialogShadowLine)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_sheet_scrollUp)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_sheet_other)); + + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_actionBar)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_actionBarSelector)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_actionBarTitle)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_actionBarTop)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_actionBarSubtitle)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_actionBarItems)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_background)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_time)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_progressBackground)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_progressCachedBackground)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_progress)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_placeholder)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_placeholderBackground)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_button)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, null, Theme.key_player_buttonActive)); + + return arrayList.toArray(new ThemeDescription[0]); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java index b2096d3c3..514c5c4bd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java @@ -30,8 +30,6 @@ import org.telegram.messenger.BuildVars; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.Theme; @@ -56,6 +54,9 @@ import java.util.HashMap; import java.util.HashSet; import java.util.StringTokenizer; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class DocumentSelectActivity extends BaseFragment { public interface DocumentSelectActivityDelegate { @@ -385,7 +386,7 @@ public class DocumentSelectActivity extends BaseFragment { public void loadRecentFiles() { try { - File[] files = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).listFiles(); + File[] files = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).listFiles(); //TODO android Q for (int a = 0; a < files.length; a++) { File file = files[a]; if (file.isDirectory()) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FeaturedStickersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/FeaturedStickersActivity.java index e92a96a9d..76ef178aa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FeaturedStickersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FeaturedStickersActivity.java @@ -18,8 +18,6 @@ import org.telegram.messenger.DataQuery; import org.telegram.messenger.LocaleController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; @@ -33,6 +31,9 @@ import org.telegram.ui.Components.StickersAlert; import java.util.ArrayList; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class FeaturedStickersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListAdapter listAdapter; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java index 6cbffeed9..bfb3791f4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java @@ -23,7 +23,10 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; -import android.support.annotation.Keep; +import androidx.annotation.Keep; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import android.text.Editable; import android.text.InputType; import android.text.SpannableStringBuilder; @@ -52,8 +55,6 @@ import org.telegram.messenger.ContactsController; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.Utilities; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; @@ -684,6 +685,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen floatingButton.setScaleY(0.0f); floatingButton.setAlpha(0.0f); } + floatingButton.setContentDescription(LocaleController.getString("Next", R.string.Next)); } else { ActionBarMenu menu = actionBar.createMenu(); doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)); @@ -1101,7 +1103,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen if (search1.equals(search2) || search2.length() == 0) { search2 = null; } - String search[] = new String[1 + (search2 != null ? 1 : 0)]; + String[] search = new String[1 + (search2 != null ? 1 : 0)]; search[0] = search1; if (search2 != null) { search[1] = search2; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java index 491dfa533..2b5cae35b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java @@ -14,7 +14,6 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.StateListAnimator; import android.annotation.SuppressLint; -import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Canvas; @@ -38,10 +37,9 @@ import android.widget.LinearLayout; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesStorage; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.FileLog; @@ -70,6 +68,9 @@ import org.telegram.ui.Components.SizeNotifierFrameLayout; import java.util.ArrayList; import java.util.concurrent.CountDownLatch; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class GroupCreateFinalActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, ImageUpdater.ImageUpdaterDelegate { private GroupCreateAdapter adapter; @@ -109,7 +110,6 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati avatarDrawable = new AvatarDrawable(); } - @SuppressWarnings("unchecked") @Override public boolean onFragmentCreate() { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.updateInterfaces); @@ -218,6 +218,8 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati SizeNotifierFrameLayout sizeNotifierFrameLayout = new SizeNotifierFrameLayout(context) { + private boolean ignoreLayout; + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSize = MeasureSpec.getSize(widthMeasureSpec); @@ -229,8 +231,13 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati measureChildWithMargins(actionBar, widthMeasureSpec, 0, heightMeasureSpec, 0); int keyboardSize = getKeyboardHeight(); - int childCount = getChildCount(); + if (keyboardSize > AndroidUtilities.dp(20)) { + ignoreLayout = true; + editText.hideEmojiView(); + ignoreLayout = false; + } + int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); if (child == null || child.getVisibility() == GONE || child == actionBar) { @@ -318,6 +325,14 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati notifyHeightChanged(); } + + @Override + public void requestLayout() { + if (ignoreLayout) { + return; + } + super.requestLayout(); + } }; fragmentView = sizeNotifierFrameLayout; fragmentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); @@ -363,6 +378,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati avatarImage.setRoundRadius(AndroidUtilities.dp(32)); avatarDrawable.setInfo(5, null, null, chatType == ChatObject.CHAT_TYPE_BROADCAST); 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)); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -383,7 +399,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati avatarBig = null; uploadedAvatar = null; showAvatarProgress(false, true); - avatarImage.setImage(avatar, "50_50", avatarDrawable, null); + avatarImage.setImage(null, null, avatarDrawable, null); avatarEditor.setImageResource(R.drawable.actions_setphoto); })); @@ -420,7 +436,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati showAvatarProgress(false, false); - editText = new EditTextEmoji((Activity) context, sizeNotifierFrameLayout, this); + editText = new EditTextEmoji(context, sizeNotifierFrameLayout, this, EditTextEmoji.STYLE_FRAGMENT); editText.setHint(chatType == ChatObject.CHAT_TYPE_CHAT ? LocaleController.getString("EnterGroupNamePlaceholder", R.string.EnterGroupNamePlaceholder) : LocaleController.getString("EnterListName", R.string.EnterListName)); if (nameToSet != null) { editText.setText(nameToSet); @@ -504,6 +520,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati floatingButtonIcon.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_actionIcon), PorterDuff.Mode.MULTIPLY)); floatingButtonIcon.setImageResource(R.drawable.checkbig); floatingButtonIcon.setPadding(0, AndroidUtilities.dp(2), 0, 0); + floatingButtonContainer.setContentDescription(LocaleController.getString("Done", R.string.Done)); floatingButtonContainer.addView(floatingButtonIcon, LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 56 : 60, Build.VERSION.SDK_INT >= 21 ? 56 : 60)); progressView = new ContextProgressView(context, 1); @@ -529,7 +546,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati } else { avatar = smallSize.location; avatarBig = bigSize.location; - avatarImage.setImage(avatar, "50_50", avatarDrawable, null); + avatarImage.setImage(ImageLocation.getForLocal(avatar), "50_50", avatarDrawable, null); showAvatarProgress(true, false); } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java index dbee34d9b..9affe86ab 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java @@ -24,8 +24,6 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; @@ -40,6 +38,9 @@ import org.telegram.ui.Components.EmptyTextProgressView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class GroupInviteActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListAdapter listAdapter; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java index 0cd85365e..c97bcfbc0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java @@ -43,11 +43,7 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; -import org.telegram.tgnet.RequestDelegate; -import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; @@ -70,6 +66,9 @@ import org.telegram.ui.Components.URLSpanNoUnderline; import java.util.ArrayList; import java.util.List; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class GroupStickersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private RecyclerListView listView; @@ -271,14 +270,11 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC eraseImageView.setPadding(AndroidUtilities.dp(16), 0, 0, 0); eraseImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText3), PorterDuff.Mode.MULTIPLY)); eraseImageView.setVisibility(View.INVISIBLE); - eraseImageView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - searchWas = false; - selectedStickerSet = null; - usernameTextView.setText(""); - updateRows(); - } + eraseImageView.setOnClickListener(v -> { + searchWas = false; + selectedStickerSet = null; + usernameTextView.setText(""); + updateRows(); }); nameContainer.addView(eraseImageView, LayoutHelper.createLinear(42, 42, 0.0f)); @@ -315,35 +311,32 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); listView.setAdapter(listAdapter); - listView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { - @Override - public void onItemClick(View view, int position) { - if (getParentActivity() == null) { + listView.setOnItemClickListener((view, position) -> { + if (getParentActivity() == null) { + return; + } + if (position == selectedStickerRow) { + if (selectedStickerSet == null) { return; } - if (position == selectedStickerRow) { - if (selectedStickerSet == null) { - return; - } - showDialog(new StickersAlert(getParentActivity(), GroupStickersActivity.this, null, selectedStickerSet, null)); - } else if (position >= stickersStartRow && position < stickersEndRow) { - boolean needScroll = selectedStickerRow == -1; - int row = layoutManager.findFirstVisibleItemPosition(); - int top = Integer.MAX_VALUE; - RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findViewHolderForAdapterPosition(row); - if (holder != null) { - top = holder.itemView.getTop(); - } - selectedStickerSet = DataQuery.getInstance(currentAccount).getStickerSets(DataQuery.TYPE_IMAGE).get(position - stickersStartRow); - ignoreTextChanges = true; - usernameTextView.setText(selectedStickerSet.set.short_name); - usernameTextView.setSelection(usernameTextView.length()); - ignoreTextChanges = false; - AndroidUtilities.hideKeyboard(usernameTextView); - updateRows(); - if (needScroll && top != Integer.MAX_VALUE) { - layoutManager.scrollToPositionWithOffset(row + 1, top); - } + showDialog(new StickersAlert(getParentActivity(), GroupStickersActivity.this, null, selectedStickerSet, null)); + } else if (position >= stickersStartRow && position < stickersEndRow) { + boolean needScroll = selectedStickerRow == -1; + int row = layoutManager.findFirstVisibleItemPosition(); + int top = Integer.MAX_VALUE; + RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findViewHolderForAdapterPosition(row); + if (holder != null) { + top = holder.itemView.getTop(); + } + selectedStickerSet = DataQuery.getInstance(currentAccount).getStickerSets(DataQuery.TYPE_IMAGE).get(position - stickersStartRow); + ignoreTextChanges = true; + usernameTextView.setText(selectedStickerSet.set.short_name); + usernameTextView.setSelection(usernameTextView.length()); + ignoreTextChanges = false; + AndroidUtilities.hideKeyboard(usernameTextView); + updateRows(); + if (needScroll && top != Integer.MAX_VALUE) { + layoutManager.scrollToPositionWithOffset(row + 1, top); } } }); @@ -431,64 +424,50 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC searching = false; return; } - AndroidUtilities.runOnUIThread(queryRunnable = new Runnable() { - @Override - public void run() { - if (queryRunnable == null) { - return; - } - TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet(); - req.stickerset = new TLRPC.TL_inputStickerSetShortName(); - req.stickerset.short_name = query; - reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, new RequestDelegate() { - @Override - public void run(final TLObject response, final TLRPC.TL_error error) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - searching = false; - if (response instanceof TLRPC.TL_messages_stickerSet) { - selectedStickerSet = (TLRPC.TL_messages_stickerSet) response; - if (donePressed) { - saveStickerSet(); - } else { - if (selectedStickerRow != -1) { - listAdapter.notifyItemChanged(selectedStickerRow); - } else { - updateRows(); - } - } - } else { - if (selectedStickerRow != -1) { - listAdapter.notifyItemChanged(selectedStickerRow); - } - if (donePressed) { - donePressed = false; - showEditDoneProgress(false); - if (getParentActivity() != null) { - Toast.makeText(getParentActivity(), LocaleController.getString("AddStickersNotFound", R.string.AddStickersNotFound), Toast.LENGTH_SHORT).show(); - } - } - } - reqId = 0; - } - }); - } - }); + AndroidUtilities.runOnUIThread(queryRunnable = () -> { + if (queryRunnable == null) { + return; } + TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet(); + req.stickerset = new TLRPC.TL_inputStickerSetShortName(); + req.stickerset.short_name = query; + reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + searching = false; + if (response instanceof TLRPC.TL_messages_stickerSet) { + selectedStickerSet = (TLRPC.TL_messages_stickerSet) response; + if (donePressed) { + saveStickerSet(); + } else { + if (selectedStickerRow != -1) { + listAdapter.notifyItemChanged(selectedStickerRow); + } else { + updateRows(); + } + } + } else { + if (selectedStickerRow != -1) { + listAdapter.notifyItemChanged(selectedStickerRow); + } + if (donePressed) { + donePressed = false; + showEditDoneProgress(false); + if (getParentActivity() != null) { + Toast.makeText(getParentActivity(), LocaleController.getString("AddStickersNotFound", R.string.AddStickersNotFound), Toast.LENGTH_SHORT).show(); + } + } + } + reqId = 0; + })); }, 500); } @Override public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { if (isOpen) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (usernameTextView != null) { - usernameTextView.requestFocus(); - AndroidUtilities.showKeyboard(usernameTextView); - } + AndroidUtilities.runOnUIThread(() -> { + if (usernameTextView != null) { + usernameTextView.requestFocus(); + AndroidUtilities.showKeyboard(usernameTextView); } }, 100); } @@ -510,36 +489,28 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC req.stickerset.id = selectedStickerSet.set.id; req.stickerset.access_hash = selectedStickerSet.set.access_hash; } - ConnectionsManager.getInstance(currentAccount).sendRequest(req, new RequestDelegate() { - @Override - public void run(final TLObject response, final TLRPC.TL_error error) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (error == null) { - if (selectedStickerSet == null) { - info.stickerset = null; - } else { - info.stickerset = selectedStickerSet.set; - DataQuery.getInstance(currentAccount).putGroupStickerSet(selectedStickerSet); - } - if (info.stickerset == null) { - info.flags |= 256; - } else { - info.flags = info.flags &~ 256; - } - MessagesStorage.getInstance(currentAccount).updateChatInfo(info, false); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, true, null); - finishFragment(); - } else { - Toast.makeText(getParentActivity(), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text, Toast.LENGTH_SHORT).show(); - donePressed = false; - showEditDoneProgress(false); - } - } - }); + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (error == null) { + if (selectedStickerSet == null) { + info.stickerset = null; + } else { + info.stickerset = selectedStickerSet.set; + DataQuery.getInstance(currentAccount).putGroupStickerSet(selectedStickerSet); + } + if (info.stickerset == null) { + info.flags |= 256; + } else { + info.flags = info.flags &~ 256; + } + MessagesStorage.getInstance(currentAccount).updateChatInfo(info, false); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, true, null); + finishFragment(); + } else { + Toast.makeText(getParentActivity(), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text, Toast.LENGTH_SHORT).show(); + donePressed = false; + showEditDoneProgress(false); } - }); + })); } private void updateRows() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java index 57a5af01d..8a674de38 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java @@ -11,15 +11,11 @@ package org.telegram.ui; import android.animation.ObjectAnimator; import android.animation.StateListAnimator; import android.app.Activity; -import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.database.DataSetObserver; import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.RectF; import android.graphics.Shader; import android.graphics.SurfaceTexture; import android.graphics.drawable.BitmapDrawable; @@ -30,15 +26,14 @@ import android.os.Build; import android.os.Bundle; import android.os.Looper; import android.os.Parcelable; -import android.support.v4.view.PagerAdapter; -import android.support.v4.view.ViewPager; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; import android.util.TypedValue; import android.view.Gravity; import android.view.TextureView; import android.view.View; import android.view.ViewGroup; import android.view.Window; -import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ScrollView; @@ -56,6 +51,7 @@ import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.Components.BottomPagesView; import org.telegram.ui.Components.LayoutHelper; import javax.microedition.khronos.egl.EGL10; @@ -68,60 +64,6 @@ import javax.microedition.khronos.opengles.GL10; public class IntroActivity extends Activity implements NotificationCenter.NotificationCenterDelegate { - private class BottomPagesView extends View { - - private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); - private float progress; - private int scrollPosition; - private int currentPage; - private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(); - private RectF rect = new RectF(); - private float animatedProgress; - - public BottomPagesView(Context context) { - super(context); - } - - public void setPageOffset(int position, float offset) { - progress = offset; - scrollPosition = position; - invalidate(); - } - - public void setCurrentPage(int page) { - currentPage = page; - invalidate(); - } - - @Override - protected void onDraw(Canvas canvas) { - float d = AndroidUtilities.dp(5); - paint.setColor(0xffbbbbbb); - int x; - currentPage = viewPager.getCurrentItem(); - for (int a = 0; a < 6; a++) { - if (a == currentPage) { - continue; - } - x = a * AndroidUtilities.dp(11); - rect.set(x, 0, x + AndroidUtilities.dp(5), AndroidUtilities.dp(5)); - canvas.drawRoundRect(rect, AndroidUtilities.dp(2.5f), AndroidUtilities.dp(2.5f), paint); - } - paint.setColor(0xff2ca5e0); - x = currentPage * AndroidUtilities.dp(11); - if (progress != 0) { - if (scrollPosition >= currentPage) { - rect.set(x, 0, x + AndroidUtilities.dp(5) + AndroidUtilities.dp(11) * progress, AndroidUtilities.dp(5)); - } else { - rect.set(x - AndroidUtilities.dp(11) * (1.0f - progress), 0, x + AndroidUtilities.dp(5), AndroidUtilities.dp(5)); - } - } else { - rect.set(x, 0, x + AndroidUtilities.dp(5), AndroidUtilities.dp(5)); - } - canvas.drawRoundRect(rect, AndroidUtilities.dp(2.5f), AndroidUtilities.dp(2.5f), paint); - } - } - private int currentAccount = UserConfig.selectedAccount; private ViewPager viewPager; @@ -284,7 +226,7 @@ public class IntroActivity extends Activity implements NotificationCenter.Notifi }); } - bottomPages = new BottomPagesView(this); + bottomPages = new BottomPagesView(this, viewPager, 6); frameLayout.addView(bottomPages, LayoutHelper.createFrame(66, 5, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 350, 0, 0)); textView = new TextView(this); @@ -378,7 +320,7 @@ public class IntroActivity extends Activity implements NotificationCenter.Notifi if (info.shortName.equals("en")) { englishInfo = info; } - if (info.shortName.replace("_", "-").equals(systemLang) || info.shortName.equals(arg) || alias != null && info.shortName.equals(alias)) { + if (info.shortName.replace("_", "-").equals(systemLang) || info.shortName.equals(arg) || info.shortName.equals(alias)) { systemInfo = info; } if (englishInfo != null && systemInfo != null) { @@ -500,7 +442,7 @@ public class IntroActivity extends Activity implements NotificationCenter.Notifi private EGLSurface eglSurface; private GL gl; private boolean initied; - private int textures[] = new int[23]; + private int[] textures = new int[23]; private int surfaceWidth; private int surfaceHeight; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/InviteContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/InviteContactsActivity.java index c694c9dc1..2f96b3bcf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/InviteContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/InviteContactsActivity.java @@ -18,7 +18,10 @@ import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.net.Uri; -import android.support.annotation.Keep; +import androidx.annotation.Keep; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import android.text.Editable; import android.text.InputType; import android.text.TextWatcher; @@ -41,13 +44,10 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; -import org.telegram.messenger.MediaController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; @@ -825,7 +825,7 @@ public class InviteContactsActivity extends BaseFragment implements Notification if (search1.equals(search2) || search2.length() == 0) { search2 = null; } - String search[] = new String[1 + (search2 != null ? 1 : 0)]; + String[] search = new String[1 + (search2 != null ? 1 : 0)]; search[0] = search1; if (search2 != null) { search[1] = search2; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java index 86671f740..9cb3f5a98 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java @@ -20,8 +20,6 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.Utilities; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; @@ -41,6 +39,9 @@ import java.util.Comparator; import java.util.Timer; import java.util.TimerTask; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class LanguageSelectActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListAdapter listAdapter; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index af4671c08..f2d41ab83 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -63,8 +63,6 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.browser.Browser; import org.telegram.messenger.camera.CameraController; -import org.telegram.messenger.support.widget.DefaultItemAnimator; -import org.telegram.messenger.support.widget.LinearLayoutManager; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.UserConfig; @@ -98,6 +96,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; + public class LaunchActivity extends Activity implements ActionBarLayout.ActionBarLayoutDelegate, NotificationCenter.NotificationCenterDelegate, DialogsActivity.DialogsActivityDelegate { private boolean finished; @@ -116,6 +117,8 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa private static ArrayList rightFragmentsStack = new ArrayList<>(); private ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener; + private ActionMode visibleActionMode; + private ActionBarLayout actionBarLayout; private ActionBarLayout layersActionBarLayout; private ActionBarLayout rightActionBarLayout; @@ -228,6 +231,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa actionBarLayout = new ActionBarLayout(this); drawerLayoutContainer = new DrawerLayoutContainer(this); + drawerLayoutContainer.setBehindKeyboardColor(Theme.getColor(Theme.key_windowBackgroundWhite)); setContentView(drawerLayoutContainer, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); if (AndroidUtilities.isTablet()) { @@ -813,12 +817,24 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa passcodeSaveIntent = null; } drawerLayoutContainer.setAllowOpenDrawer(true, false); + actionBarLayout.setVisibility(View.VISIBLE); actionBarLayout.showLastFragment(); if (AndroidUtilities.isTablet()) { layersActionBarLayout.showLastFragment(); rightActionBarLayout.showLastFragment(); + if (layersActionBarLayout.getVisibility() == View.INVISIBLE) { + layersActionBarLayout.setVisibility(View.VISIBLE); + } + rightActionBarLayout.setVisibility(View.VISIBLE); } }); + actionBarLayout.setVisibility(View.INVISIBLE); + if (AndroidUtilities.isTablet()) { + if (layersActionBarLayout.getVisibility() == View.VISIBLE) { + layersActionBarLayout.setVisibility(View.INVISIBLE); + } + rightActionBarLayout.setVisibility(View.INVISIBLE); + } } private boolean handleIntent(Intent intent, boolean isNew, boolean restore, boolean fromPassword) { @@ -854,8 +870,12 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa int open_settings = 0; int open_new_dialog = 0; long dialogId = 0; - if (SharedConfig.directShare) { - dialogId = intent != null && intent.getExtras() != null ? intent.getExtras().getLong("dialogId", 0) : 0; + if (SharedConfig.directShare && intent != null && intent.getExtras() != null) { + dialogId = intent.getExtras().getLong("dialogId", 0); + long hash = intent.getExtras().getLong("hash", 0); + if (hash != SharedConfig.directShareHash) { + dialogId = 0; + } } boolean showDialogsList = false; boolean showPlayer = false; @@ -1057,6 +1077,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa String code = null; TLRPC.TL_wallPaper wallPaper = null; Integer messageId = null; + Integer channelId = null; boolean hasUrl = false; String scheme = data.getScheme(); if (scheme != null) { @@ -1092,11 +1113,18 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } } } - wallPaper.settings.intensity = Utilities.parseInt(data.getQueryParameter("intensity")); + String intensity = data.getQueryParameter("intensity"); + if (!TextUtils.isEmpty(intensity)) { + wallPaper.settings.intensity = Utilities.parseInt(intensity); + } else { + wallPaper.settings.intensity = 50; + } try { String bgColor = data.getQueryParameter("bg_color"); if (!TextUtils.isEmpty(bgColor)) { wallPaper.settings.background_color = Integer.parseInt(bgColor, 16) | 0xff000000; + } else { + wallPaper.settings.background_color = 0xffffffff; } } catch (Exception ignore) { @@ -1131,6 +1159,16 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa phoneHash = data.getQueryParameter("hash"); } else if (path.startsWith("setlanguage/")) { lang = path.substring(12); + } else if (path.startsWith("c/")) { + List segments = data.getPathSegments(); + if (segments.size() == 3) { + channelId = Utilities.parseInt(segments.get(1)); + messageId = Utilities.parseInt(segments.get(2)); + if (messageId == 0 || channelId == 0) { + messageId = null; + channelId = null; + } + } } else if (path.length() >= 1) { List segments = data.getPathSegments(); if (segments.size() > 0) { @@ -1176,6 +1214,15 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa messageId = null; } } + } else if (url.startsWith("tg:privatepost") || url.startsWith("tg://privatepost")) { + url = url.replace("tg:privatepost", "tg://telegram.org").replace("tg://privatepost", "tg://telegram.org"); + data = Uri.parse(url); + messageId = Utilities.parseInt(data.getQueryParameter("post")); + channelId = Utilities.parseInt(data.getQueryParameter("channel_id")); + if (messageId == 0 || channelId == 0) { + messageId = null; + channelId = null; + } } else if (url.startsWith("tg:bg") || url.startsWith("tg://bg")) { url = url.replace("tg:bg", "tg://telegram.org").replace("tg://bg", "tg://telegram.org"); data = Uri.parse(url); @@ -1313,11 +1360,11 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa 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) { + } else if (username != null || group != null || sticker != null || message != null || game != null || auth != null || unsupportedUrl != null || lang != null || code != null || wallPaper != null || channelId != null) { if (message != null && message.startsWith("@")) { message = " " + message; } - runLinkRequest(intentAccount[0], username, group, sticker, botUser, botChat, message, hasUrl, messageId, 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, 0); } else { try (Cursor cursor = getContentResolver().query(intent.getData(), null, null, null, null)) { if (cursor != null) { @@ -1557,6 +1604,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa final String message, final boolean hasUrl, final Integer messageId, + final Integer channelId, final String game, final HashMap auth, final String lang, @@ -1569,7 +1617,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (account != intentAccount) { switchToAccount(account, true); } - runLinkRequest(account, username, group, sticker, botUser, botChat, message, hasUrl, messageId, game, auth, lang, unsupportedUrl, code, wallPaper, 1); + runLinkRequest(account, username, group, sticker, botUser, botChat, message, hasUrl, messageId, channelId, game, auth, lang, unsupportedUrl, code, wallPaper, 1); }).show(); return; } else if (code != null) { @@ -1758,7 +1806,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa 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, 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, 1)); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showAlertDialog(builder); } @@ -1970,7 +2018,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (response instanceof TLRPC.TL_wallPaper) { TLRPC.TL_wallPaper res = (TLRPC.TL_wallPaper) response; Object object; - if (wallPaper.settings.background_color != 0) { + if (res.pattern) { WallpapersListActivity.ColorWallpaper colorWallpaper = new WallpapersListActivity.ColorWallpaper(-1, wallPaper.settings.background_color, res.id, wallPaper.settings.intensity / 100.0f, wallPaper.settings.motion, null); colorWallpaper.pattern = res; object = colorWallpaper; @@ -1985,6 +2033,43 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } })); } + } else if (channelId != null && messageId != null) { + Bundle args = new Bundle(); + args.putInt("chat_id", channelId); + args.putInt("message_id", messageId); + BaseFragment lastFragment = !mainFragmentsStack.isEmpty() ? mainFragmentsStack.get(mainFragmentsStack.size() - 1) : null; + if (lastFragment == null || MessagesController.getInstance(intentAccount).checkCanOpenChat(args, lastFragment)) { + AndroidUtilities.runOnUIThread(() -> { + if (!actionBarLayout.presentFragment(new ChatActivity(args))) { + TLRPC.TL_channels_getChannels req = new TLRPC.TL_channels_getChannels(); + TLRPC.TL_inputChannel inputChannel = new TLRPC.TL_inputChannel(); + inputChannel.channel_id = channelId; + req.id.add(inputChannel); + requestId[0] = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + try { + progressDialog.dismiss(); + } catch (Exception e) { + FileLog.e(e); + } + boolean notFound = true; + if (response instanceof TLRPC.TL_messages_chats) { + TLRPC.TL_messages_chats res = (TLRPC.TL_messages_chats) response; + if (!res.chats.isEmpty()) { + notFound = false; + MessagesController.getInstance(currentAccount).putChats(res.chats, false); + TLRPC.Chat chat = res.chats.get(0); + if (lastFragment == null || MessagesController.getInstance(intentAccount).checkCanOpenChat(args, lastFragment)) { + actionBarLayout.presentFragment(new ChatActivity(args)); + } + } + } + if (notFound) { + showAlertDialog(AlertsCreator.createSimpleAlert(LaunchActivity.this, LocaleController.getString("LinkNotFound", R.string.LinkNotFound))); + } + })); + } + }); + } } if (requestId[0] != 0) { @@ -2369,8 +2454,8 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (ArticleViewer.hasInstance()) { ArticleViewer.getInstance().destroyArticleViewer(); } - if (StickerPreviewViewer.hasInstance()) { - StickerPreviewViewer.getInstance().destroy(); + if (ContentPreviewViewer.hasInstance()) { + ContentPreviewViewer.getInstance().destroy(); } PipRoundVideoView pipRoundVideoView = PipRoundVideoView.getInstance(); MediaController.getInstance().setBaseActivity(this, false); @@ -2633,6 +2718,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (sideMenu != null) { sideMenu.setBackgroundColor(Theme.getColor(Theme.key_chats_menuBackground)); sideMenu.setGlowColor(Theme.getColor(Theme.key_chats_menuBackground)); + sideMenu.setListSelectorColor(Theme.getColor(Theme.key_listSelector)); sideMenu.getAdapter().notifyDataSetChanged(); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { @@ -2643,6 +2729,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } } } + drawerLayoutContainer.setBehindKeyboardColor(Theme.getColor(Theme.key_windowBackgroundWhite)); } else if (id == NotificationCenter.needSetDayNightTheme) { Theme.ThemeInfo theme = (Theme.ThemeInfo) args[0]; boolean nigthTheme = (Boolean) args[1]; @@ -2964,6 +3051,13 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa actionBarLayout.setTitleOverlayText(title, titleId, action); } + public void hideVisibleActionMode() { + if (visibleActionMode == null) { + return; + } + visibleActionMode.finish(); + } + @Override protected void onSaveInstanceState(Bundle outState) { try { @@ -3054,6 +3148,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa @Override public void onActionModeStarted(ActionMode mode) { super.onActionModeStarted(mode); + visibleActionMode = mode; try { Menu menu = mode.getMenu(); if (menu != null) { @@ -3081,6 +3176,9 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa @Override public void onActionModeFinished(ActionMode mode) { super.onActionModeFinished(mode); + if (visibleActionMode == mode) { + visibleActionMode = null; + } if (Build.VERSION.SDK_INT >= 23 && mode.getType() == ActionMode.TYPE_FLOATING) { return; } @@ -3116,6 +3214,14 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa return true; } } + if (AndroidUtilities.isTablet() && !rightFragmentsStack.isEmpty()) { + fragment = rightFragmentsStack.get(rightFragmentsStack.size() - 1); + if (fragment instanceof ChatActivity) { + if (((ChatActivity) fragment).maybePlayVisibleVideo()) { + return true; + } + } + } } return super.dispatchKeyEvent(event); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java index 5aa1ed0f1..bd33231d5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java @@ -66,8 +66,6 @@ import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.MessageObject; @@ -101,6 +99,9 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class LocationActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { public class LiveLocation { @@ -274,7 +275,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } else { actionBar.setTitle(LocaleController.getString("ChatLocation", R.string.ChatLocation)); } - menu.addItem(share, R.drawable.share); + menu.addItem(share, R.drawable.share).setContentDescription(LocaleController.getString("ShareFile", R.string.ShareFile)); } } else { actionBar.setTitle(LocaleController.getString("ShareLocation", R.string.ShareLocation)); @@ -321,9 +322,10 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } otherItem = menu.addItem(0, R.drawable.ic_ab_other); - otherItem.addSubItem(map_list_menu_map, LocaleController.getString("Map", R.string.Map)); - otherItem.addSubItem(map_list_menu_satellite, LocaleController.getString("Satellite", R.string.Satellite)); - otherItem.addSubItem(map_list_menu_hybrid, LocaleController.getString("Hybrid", R.string.Hybrid)); + otherItem.addSubItem(map_list_menu_map, R.drawable.msg_map, LocaleController.getString("Map", R.string.Map)); + otherItem.addSubItem(map_list_menu_satellite, R.drawable.msg_satellite, LocaleController.getString("Satellite", R.string.Satellite)); + otherItem.addSubItem(map_list_menu_hybrid, R.drawable.msg_hybrid, LocaleController.getString("Hybrid", R.string.Hybrid)); + otherItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); fragmentView = new FrameLayout(context) { private boolean first = true; @@ -353,6 +355,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter locationButton.setImageResource(R.drawable.myloc_on); locationButton.setScaleType(ImageView.ScaleType.CENTER); locationButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_profile_actionIcon), PorterDuff.Mode.MULTIPLY)); + locationButton.setContentDescription(LocaleController.getString("AccDescrMyLocation", R.string.AccDescrMyLocation)); if (Build.VERSION.SDK_INT >= 21) { StateListAnimator animator = new StateListAnimator(); animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(locationButton, "translationZ", AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); @@ -1278,6 +1281,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCHPLACEHOLDER, null, null, null, null, Theme.key_actionBarDefaultSearchPlaceholder), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUBACKGROUND, null, null, null, null, Theme.key_actionBarDefaultSubmenuBackground), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM, null, null, null, null, Theme.key_actionBarDefaultSubmenuItem), + new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubmenuItemIcon), new ThemeDescription(listView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java index e297628bc..3ed9ce6c5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java @@ -32,6 +32,7 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.os.Vibrator; +import android.telephony.PhoneNumberUtils; import android.telephony.SmsManager; import android.telephony.TelephonyManager; import android.text.Editable; @@ -63,6 +64,7 @@ import android.widget.Toast; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; @@ -218,6 +220,7 @@ public class LoginActivity extends BaseFragment { doneProgressView.setScaleY(0.1f); doneProgressView.setVisibility(View.INVISIBLE); doneItem.addView(doneProgressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + doneItem.setContentDescription(LocaleController.getString("Done", R.string.Done)); ScrollView scrollView = new ScrollView(context) { @Override @@ -417,13 +420,13 @@ public class LoginActivity extends BaseFragment { if (Build.VERSION.SDK_INT >= 23) { if (dialog == permissionsDialog && !permissionsItems.isEmpty() && getParentActivity() != null) { try { - getParentActivity().requestPermissions(permissionsItems.toArray(new String[permissionsItems.size()]), 6); + getParentActivity().requestPermissions(permissionsItems.toArray(new String[0]), 6); } catch (Exception ignore) { } } else if (dialog == permissionsShowDialog && !permissionsShowItems.isEmpty() && getParentActivity() != null) { try { - getParentActivity().requestPermissions(permissionsShowItems.toArray(new String[permissionsShowItems.size()]), 7); + getParentActivity().requestPermissions(permissionsShowItems.toArray(new String[0]), 7); } catch (Exception ignore) { } @@ -593,6 +596,7 @@ public class LoginActivity extends BaseFragment { newView.setParams(params, false); actionBar.setTitle(newView.getHeaderName()); + setParentActivityTitle(newView.getHeaderName()); newView.onShow(); newView.setX(back ? -AndroidUtilities.displaySize.x : AndroidUtilities.displaySize.x); newView.setVisibility(View.VISIBLE); @@ -618,6 +622,7 @@ public class LoginActivity extends BaseFragment { views[page].setParams(params, false); views[page].setVisibility(View.VISIBLE); actionBar.setTitle(views[page].getHeaderName()); + setParentActivityTitle(views[page].getHeaderName()); views[page].onShow(); } } @@ -830,13 +835,13 @@ public class LoginActivity extends BaseFragment { country = codesMap.get(sub); if (country != null) { ok = true; - textToSet = text.substring(a, text.length()) + phoneField.getText().toString(); + textToSet = text.substring(a) + phoneField.getText().toString(); codeField.setText(text = sub); break; } } if (!ok) { - textToSet = text.substring(1, text.length()) + phoneField.getText().toString(); + textToSet = text.substring(1) + phoneField.getText().toString(); codeField.setText(text = text.substring(0, 1)); } } @@ -940,7 +945,7 @@ public class LoginActivity extends BaseFragment { String phoneChars = "0123456789"; String str = phoneField.getText().toString(); if (characterAction == 3) { - str = str.substring(0, actionPosition) + str.substring(actionPosition + 1, str.length()); + str = str.substring(0, actionPosition) + str.substring(actionPosition + 1); start--; } StringBuilder builder = new StringBuilder(str.length()); @@ -1157,7 +1162,7 @@ public class LoginActivity extends BaseFragment { if (!permissionsItems.isEmpty()) { SharedPreferences preferences = MessagesController.getGlobalMainSettings(); if (!allowCancelCall && allowCall) { - getParentActivity().requestPermissions(permissionsItems.toArray(new String[permissionsItems.size()]), 6); + getParentActivity().requestPermissions(permissionsItems.toArray(new String[0]), 6); } else if (preferences.getBoolean("firstlogin", true) || getParentActivity().shouldShowRequestPermissionRationale(Manifest.permission.READ_PHONE_STATE)) { preferences.edit().putBoolean("firstlogin", false).commit(); AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); @@ -1167,7 +1172,7 @@ public class LoginActivity extends BaseFragment { permissionsDialog = showDialog(builder.create()); } else { try { - getParentActivity().requestPermissions(permissionsItems.toArray(new String[permissionsItems.size()]), 6); + getParentActivity().requestPermissions(permissionsItems.toArray(new String[0]), 6); } catch (Exception ignore) { ok = false; } @@ -1198,7 +1203,7 @@ public class LoginActivity extends BaseFragment { continue; } String userPhone = userConfig.getCurrentUser().phone; - if (userPhone.contains(phone) || phone.contains(userPhone)) { + if (PhoneNumberUtils.compare(phone, userPhone)) { final int num = a; AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); @@ -1244,7 +1249,7 @@ public class LoginActivity extends BaseFragment { try { String number = tm.getLine1Number(); if (!TextUtils.isEmpty(number)) { - req.settings.current_number = phone.contains(number) || number.contains(phone); + req.settings.current_number = PhoneNumberUtils.compare(phone, number); if (!req.settings.current_number) { req.settings.allow_flashcall = false; } @@ -1322,7 +1327,7 @@ public class LoginActivity extends BaseFragment { builder.setMessage(LocaleController.getString("AllowFillNumber", R.string.AllowFillNumber)); permissionsShowDialog = showDialog(builder.create()); } else { - getParentActivity().requestPermissions(permissionsShowItems.toArray(new String[permissionsShowItems.size()]), 7); + getParentActivity().requestPermissions(permissionsShowItems.toArray(new String[0]), 7); } } return; @@ -1339,13 +1344,13 @@ public class LoginActivity extends BaseFragment { String country = codesMap.get(sub); if (country != null) { ok = true; - textToSet = number.substring(a, number.length()); + textToSet = number.substring(a); codeField.setText(sub); break; } } if (!ok) { - textToSet = number.substring(1, number.length()); + textToSet = number.substring(1); codeField.setText(number.substring(0, 1)); } } @@ -3188,7 +3193,7 @@ public class LoginActivity extends BaseFragment { avatarBig = null; uploadedAvatar = null; showAvatarProgress(false, true); - avatarImage.setImage(avatar, "50_50", avatarDrawable, null); + avatarImage.setImage(null, null, avatarDrawable, null); avatarEditor.setImageResource(R.drawable.actions_setphoto); })); @@ -3309,7 +3314,7 @@ public class LoginActivity extends BaseFragment { AndroidUtilities.runOnUIThread(() -> { avatar = smallSize.location; avatarBig = bigSize.location; - avatarImage.setImage(avatar, "50_50", avatarDrawable, null); + avatarImage.setImage(ImageLocation.getForLocal(avatar), "50_50", avatarDrawable, null); }); } @@ -3528,6 +3533,11 @@ public class LoginActivity extends BaseFragment { @Override public ThemeDescription[] getThemeDescriptions() { + for (int a = 0;a < views.length; a++) { + if (views[a] == null) { + return new ThemeDescription[0]; + } + } PhoneView phoneView = (PhoneView) views[0]; LoginActivitySmsView smsView1 = (LoginActivitySmsView) views[1]; LoginActivitySmsView smsView2 = (LoginActivitySmsView) views[2]; @@ -3655,6 +3665,6 @@ public class LoginActivity extends BaseFragment { arrayList.add(new ThemeDescription(smsView4.blackImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); arrayList.add(new ThemeDescription(smsView4.blueImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chats_actionBackground)); - return arrayList.toArray(new ThemeDescription[arrayList.size()]); + return arrayList.toArray(new ThemeDescription[0]); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LogoutActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LogoutActivity.java index 173727321..6a735f4c1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LogoutActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LogoutActivity.java @@ -23,8 +23,6 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; @@ -39,6 +37,9 @@ import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class LogoutActivity extends BaseFragment { private ListAdapter listAdapter; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java index ea6494d51..b94c1b6f6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java @@ -52,13 +52,10 @@ import org.telegram.messenger.MediaController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.UserObject; import org.telegram.messenger.browser.Browser; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.MessageObject; @@ -69,12 +66,10 @@ 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.AlertDialog; import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; -import org.telegram.ui.Cells.CheckBoxCell; import org.telegram.ui.Cells.GraySectionCell; import org.telegram.ui.Cells.LoadingCell; import org.telegram.ui.Cells.SharedDocumentCell; @@ -82,6 +77,7 @@ import org.telegram.ui.Cells.SharedLinkCell; import org.telegram.ui.Cells.SharedMediaSectionCell; import org.telegram.ui.Cells.SharedPhotoVideoCell; import org.telegram.ui.Cells.SharedAudioCell; +import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AnimationProperties; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.ActionBar.BaseFragment; @@ -96,8 +92,9 @@ import org.telegram.ui.Components.ScrollSlidingTextTabStrip; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.Timer; -import java.util.TimerTask; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; @SuppressWarnings("unchecked") public class MediaActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { @@ -138,6 +135,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No private ArrayList audioCache = new ArrayList<>(10); private FragmentContextView fragmentContextView; private ScrollSlidingTextTabStrip scrollSlidingTextTabStrip; + private View actionModeBackground; private int maximumVelocity; @@ -218,7 +216,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } } if (imageView != null) { - int coords[] = new int[2]; + int[] coords = new int[2]; imageView.getLocationInWindow(coords); PhotoViewer.PlaceProviderObject object = new PhotoViewer.PlaceProviderObject(); object.viewX = coords[0]; @@ -245,8 +243,8 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No private HashMap> sectionArrays = new HashMap<>(); private int totalCount; private boolean loading; - private boolean endReached[] = new boolean[]{false, true}; - private int max_id[] = new int[]{0, 0}; + private boolean[] endReached = new boolean[]{false, true}; + private int[] max_id = new int[]{0, 0}; public void setTotalCount(int count) { totalCount = count; @@ -465,108 +463,24 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No finishFragment(); } } else if (id == delete) { - if (getParentActivity() == null) { - return; - } - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setMessage(LocaleController.formatString("AreYouSureDeleteMessages", R.string.AreYouSureDeleteMessages, LocaleController.formatPluralString("items", selectedFiles[0].size() + selectedFiles[1].size()))); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - - final boolean deleteForAll[] = new boolean[1]; + TLRPC.Chat currentChat = null; + TLRPC.User currentUser = null; + TLRPC.EncryptedChat currentEncryptedChat = null; int lower_id = (int) dialog_id; if (lower_id != 0) { - TLRPC.Chat currentChat; - TLRPC.User currentUser; if (lower_id > 0) { currentUser = MessagesController.getInstance(currentAccount).getUser(lower_id); - currentChat = null; } else { - currentUser = null; currentChat = MessagesController.getInstance(currentAccount).getChat(-lower_id); } - if (currentUser != null || !ChatObject.isChannel(currentChat)) { - int currentDate = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); - if (currentUser != null && currentUser.id != UserConfig.getInstance(currentAccount).getClientUserId() || currentChat != null) { - boolean hasOutgoing = false; - for (int a = 1; a >= 0; a--) { - int channelId = 0; - for (int b = 0; b < selectedFiles[a].size(); b++) { - MessageObject msg = selectedFiles[a].valueAt(b); - if (msg.messageOwner.action != null) { - continue; - } - if (msg.isOut()) { - if ((currentDate - msg.messageOwner.date) <= 2 * 24 * 60 * 60) { - hasOutgoing = true; - } - } else { - hasOutgoing = false; - break; - } - } - if (hasOutgoing) { - break; - } - } - - if (hasOutgoing) { - FrameLayout frameLayout = new FrameLayout(getParentActivity()); - CheckBoxCell cell = new CheckBoxCell(getParentActivity(), 1); - cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); - if (currentChat != null) { - cell.setText(LocaleController.getString("DeleteForAll", R.string.DeleteForAll), "", false, false); - } else { - cell.setText(LocaleController.formatString("DeleteForUser", R.string.DeleteForUser, UserObject.getFirstName(currentUser)), "", false, false); - } - cell.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0, LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0); - frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0)); - cell.setOnClickListener(v -> { - CheckBoxCell cell1 = (CheckBoxCell) v; - deleteForAll[0] = !deleteForAll[0]; - cell1.setChecked(deleteForAll[0], true); - }); - builder.setView(frameLayout); - } - } - } + } else { + currentEncryptedChat = MessagesController.getInstance(currentAccount).getEncryptedChat((int) (dialog_id >> 32)); } - - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> { - for (int a = 1; a >= 0; a--) { - ArrayList ids = new ArrayList<>(); - for (int b = 0; b < selectedFiles[a].size(); b++) { - ids.add(selectedFiles[a].keyAt(b)); - } - ArrayList random_ids = null; - TLRPC.EncryptedChat currentEncryptedChat = null; - int channelId = 0; - if (!ids.isEmpty()) { - MessageObject msg = selectedFiles[a].get(ids.get(0)); - if (channelId == 0 && msg.messageOwner.to_id.channel_id != 0) { - channelId = msg.messageOwner.to_id.channel_id; - } - } - if ((int) dialog_id == 0) { - currentEncryptedChat = MessagesController.getInstance(currentAccount).getEncryptedChat((int) (dialog_id >> 32)); - } - if (currentEncryptedChat != null) { - random_ids = new ArrayList<>(); - for (int b = 0; b < selectedFiles[a].size(); b++) { - MessageObject msg = selectedFiles[a].valueAt(b); - if (msg.messageOwner.random_id != 0 && msg.type != 10) { - random_ids.add(msg.messageOwner.random_id); - } - } - } - MessagesController.getInstance(currentAccount).deleteMessages(ids, random_ids, currentEncryptedChat, channelId, deleteForAll[0]); - selectedFiles[a].clear(); - } + AlertsCreator.createDeleteMessagesAlert(MediaActivity.this, currentUser, currentChat, currentEncryptedChat, null, mergeDialogId, null, selectedFiles, null, 1, () -> { actionBar.hideActionMode(); actionBar.closeSearchField(); cantDeleteMessagesCount = 0; }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showDialog(builder.create()); } else if (id == forward) { Bundle args = new Bundle(); args.putBoolean("onlySelect", true); @@ -668,6 +582,10 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No pinnedHeaderShadowDrawable = context.getResources().getDrawable(R.drawable.photos_header_shadow); pinnedHeaderShadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundGrayShadow), PorterDuff.Mode.MULTIPLY)); + if (scrollSlidingTextTabStrip != null) { + initialTab = scrollSlidingTextTabStrip.getCurrentTabId(); + } + scrollSlidingTextTabStrip = new ScrollSlidingTextTabStrip(context); if (initialTab != -1) { scrollSlidingTextTabStrip.setInitialTabId(initialTab); @@ -752,6 +670,9 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No if (text.length() != 0) { searchWas = true; switchToCurrentSelectedMode(false); + } else { + searchWas = false; + switchToCurrentSelectedMode(false); } if (mediaPages[0].selectedType == 1) { if (documentsSearchAdapter == null) { @@ -772,27 +693,33 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } }); searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); + searchItem.setContentDescription(LocaleController.getString("Search", R.string.Search)); searchItem.setVisibility(View.INVISIBLE); searchItemState = 0; hasOwnBackground = true; final ActionBarMenu actionMode = actionBar.createActionMode(false); - actionMode.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefault)); + actionMode.setBackgroundDrawable(null); actionBar.setItemsColor(Theme.getColor(Theme.key_actionBarDefaultIcon), true); actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSelector), true); + actionModeBackground = new View(context); + actionModeBackground.setBackgroundColor(Theme.getColor(Theme.key_sharedMedia_actionMode)); + actionModeBackground.setAlpha(0.0f); + actionBar.addView(actionModeBackground, actionBar.indexOfChild(actionMode)); + selectedMessagesCountTextView = new NumberTextView(actionMode.getContext()); selectedMessagesCountTextView.setTextSize(18); selectedMessagesCountTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); selectedMessagesCountTextView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultIcon)); selectedMessagesCountTextView.setOnTouchListener((v, event) -> true); - actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 65, 0, 0, 0)); + actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 72, 0, 0, 0)); if ((int) dialog_id != 0) { - actionModeViews.add(gotoItem = actionMode.addItemWithWidth(gotochat, R.drawable.go_to_message, AndroidUtilities.dp(54))); - actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.ic_ab_forward, AndroidUtilities.dp(54))); + actionModeViews.add(gotoItem = actionMode.addItemWithWidth(gotochat, R.drawable.msg_message, AndroidUtilities.dp(54), LocaleController.getString("AccDescrGoToMessage", R.string.AccDescrGoToMessage))); + actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.msg_forward, AndroidUtilities.dp(54), LocaleController.getString("Forward", R.string.Forward))); } - actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.ic_ab_delete, AndroidUtilities.dp(54))); + actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete))); photoVideoAdapter = new SharedPhotoVideoAdapter(context); documentsAdapter = new SharedDocumentsAdapter(context, 1); @@ -995,6 +922,12 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No if (!prepareForMoving(ev, dx < 0)) { maybeStartTracking = true; startedTracking = false; + mediaPages[0].setTranslationX(0); + if (animatingForward) { + mediaPages[1].setTranslationX(mediaPages[0].getMeasuredWidth()); + } else { + mediaPages[1].setTranslationX(-mediaPages[0].getMeasuredWidth()); + } } } if (maybeStartTracking && !startedTracking) { @@ -1003,11 +936,10 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No prepareForMoving(ev, dx < 0); } } else if (startedTracking) { + mediaPages[0].setTranslationX(dx); if (animatingForward) { - mediaPages[0].setTranslationX(dx); mediaPages[1].setTranslationX(mediaPages[0].getMeasuredWidth() + dx); } else { - mediaPages[0].setTranslationX(dx); mediaPages[1].setTranslationX(dx - mediaPages[0].getMeasuredWidth()); } float scrollProgress = Math.abs(dx) / (float) mediaPages[0].getMeasuredWidth(); @@ -1217,12 +1149,24 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } }); mediaPages[a].listView.setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (newState == RecyclerView.SCROLL_STATE_DRAGGING && searching && searchWas) { AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); } scrolling = newState != RecyclerView.SCROLL_STATE_IDLE; + if (newState != RecyclerView.SCROLL_STATE_DRAGGING) { + int scrollY = (int) -actionBar.getTranslationY(); + int actionBarHeight = ActionBar.getCurrentActionBarHeight(); + if (scrollY != 0 && scrollY != actionBarHeight) { + if (scrollY < actionBarHeight / 2) { + mediaPages[0].listView.smoothScrollBy(0, -scrollY); + } else { + mediaPages[0].listView.smoothScrollBy(0, actionBarHeight - scrollY); + } + } + } } @Override @@ -1271,6 +1215,10 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } }); mediaPages[a].listView.setOnItemLongClickListener((view, position) -> { + if (actionBar.isActionModeShowed()) { + mediaPage.listView.getOnItemClickListener().onItemClick(view, position); + return true; + } if (mediaPage.selectedType == 1 && view instanceof SharedDocumentCell) { return MediaActivity.this.onItemLongClick(((SharedDocumentCell) view).getMessage(), view, 0); } else if (mediaPage.selectedType == 3 && view instanceof SharedLinkCell) { @@ -1931,14 +1879,14 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } } else { if (animated) { - if (searchItem.getVisibility() != View.VISIBLE && !actionBar.isSearchFieldVisible()) { + if (searchItem.getVisibility() == View.INVISIBLE && !actionBar.isSearchFieldVisible()) { searchItemState = 1; searchItem.setVisibility(View.VISIBLE); searchItem.setAlpha(0.0f); } else { searchItemState = 0; } - } else { + } else if (searchItem.getVisibility() == View.INVISIBLE) { searchItemState = 0; searchItem.setAlpha(1.0f); searchItem.setVisibility(View.VISIBLE); @@ -2003,7 +1951,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No ((SharedAudioCell) view).setChecked(true, true); } if (!actionBar.isActionModeShowed()) { - actionBar.showActionMode(); + actionBar.showActionMode(null, actionModeBackground, null, null, null, 0); resetScroll(); } return true; @@ -2530,6 +2478,10 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No @Override public boolean didLongClickItem(SharedPhotoVideoCell cell, int index, MessageObject messageObject, int a) { + if (actionBar.isActionModeShowed()) { + didClickItem(cell, index, messageObject, a); + return true; + } return onItemLongClick(messageObject, cell, a); } }); @@ -2606,7 +2558,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No private Context mContext; private ArrayList searchResult = new ArrayList<>(); - private Timer searchTimer; + private Runnable searchRunnable; protected ArrayList globalSearch = new ArrayList<>(); private int reqId = 0; private int lastReqId; @@ -2685,12 +2637,9 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } public void search(final String query) { - try { - if (searchTimer != null) { - searchTimer.cancel(); - } - } catch (Exception e) { - FileLog.e(e); + if (searchRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(searchRunnable); + searchRunnable = null; } if (TextUtils.isEmpty(query)) { if (!searchResult.isEmpty() || !globalSearch.isEmpty() || searchesInProgress != 0) { @@ -2701,8 +2650,8 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No reqId = 0; searchesInProgress--; } - notifyDataSetChanged(); } + notifyDataSetChanged(); } else { for (int a = 0; a < mediaPages.length; a++) { if (mediaPages[a].selectedType == currentType) { @@ -2717,96 +2666,81 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } } - searchTimer = new Timer(); - searchTimer.schedule(new TimerTask() { - @Override - public void run() { - try { - searchTimer.cancel(); - searchTimer = null; - } catch (Exception e) { - FileLog.e(e); - } - processSearch(query); + + AndroidUtilities.runOnUIThread(searchRunnable = () -> { + if (!sharedMediaData[currentType].messages.isEmpty() && (currentType == 1 || currentType == 4)) { + MessageObject messageObject = sharedMediaData[currentType].messages.get(sharedMediaData[currentType].messages.size() - 1); + queryServerSearch(query, messageObject.getId(), messageObject.getDialogId()); + } else if (currentType == 3) { + queryServerSearch(query, 0, dialog_id); } - }, 200, 300); - } - } + if (currentType == 1 || currentType == 4) { + final ArrayList copy = new ArrayList<>(sharedMediaData[currentType].messages); + searchesInProgress++; + Utilities.searchQueue.postRunnable(() -> { + String search1 = query.trim().toLowerCase(); + if (search1.length() == 0) { + updateSearchResults(new ArrayList<>()); + return; + } + String search2 = LocaleController.getInstance().getTranslitString(search1); + if (search1.equals(search2) || search2.length() == 0) { + search2 = null; + } + String[] search = new String[1 + (search2 != null ? 1 : 0)]; + search[0] = search1; + if (search2 != null) { + search[1] = search2; + } - private void processSearch(final String query) { - AndroidUtilities.runOnUIThread(() -> { - if (!sharedMediaData[currentType].messages.isEmpty() && (currentType == 1 || currentType == 4)) { - MessageObject messageObject = sharedMediaData[currentType].messages.get(sharedMediaData[currentType].messages.size() - 1); - queryServerSearch(query, messageObject.getId(), messageObject.getDialogId()); - } else if (currentType == 3) { - queryServerSearch(query, 0, dialog_id); - } - if (currentType == 1 || currentType == 4) { - final ArrayList copy = new ArrayList<>(sharedMediaData[currentType].messages); - searchesInProgress++; - Utilities.searchQueue.postRunnable(() -> { - String search1 = query.trim().toLowerCase(); - if (search1.length() == 0) { - updateSearchResults(new ArrayList<>()); - return; - } - String search2 = LocaleController.getInstance().getTranslitString(search1); - if (search1.equals(search2) || search2.length() == 0) { - search2 = null; - } - String search[] = new String[1 + (search2 != null ? 1 : 0)]; - search[0] = search1; - if (search2 != null) { - search[1] = search2; - } + ArrayList resultArray = new ArrayList<>(); - ArrayList resultArray = new ArrayList<>(); - - for (int a = 0; a < copy.size(); a++) { - MessageObject messageObject = copy.get(a); - for (int b = 0; b < search.length; b++) { - String q = search[b]; - String name = messageObject.getDocumentName(); - if (name == null || name.length() == 0) { - continue; - } - name = name.toLowerCase(); - if (name.contains(q)) { - resultArray.add(messageObject); - break; - } - if (currentType == 4) { - TLRPC.Document document; - if (messageObject.type == 0) { - document = messageObject.messageOwner.media.webpage.document; - } else { - document = messageObject.messageOwner.media.document; + for (int a = 0; a < copy.size(); a++) { + MessageObject messageObject = copy.get(a); + for (int b = 0; b < search.length; b++) { + String q = search[b]; + String name = messageObject.getDocumentName(); + if (name == null || name.length() == 0) { + continue; } - boolean ok = false; - for (int c = 0; c < document.attributes.size(); c++) { - TLRPC.DocumentAttribute attribute = document.attributes.get(c); - if (attribute instanceof TLRPC.TL_documentAttributeAudio) { - if (attribute.performer != null) { - ok = attribute.performer.toLowerCase().contains(q); - } - if (!ok && attribute.title != null) { - ok = attribute.title.toLowerCase().contains(q); - } - break; - } - } - if (ok) { + name = name.toLowerCase(); + if (name.contains(q)) { resultArray.add(messageObject); break; } + if (currentType == 4) { + TLRPC.Document document; + if (messageObject.type == 0) { + document = messageObject.messageOwner.media.webpage.document; + } else { + document = messageObject.messageOwner.media.document; + } + boolean ok = false; + for (int c = 0; c < document.attributes.size(); c++) { + TLRPC.DocumentAttribute attribute = document.attributes.get(c); + if (attribute instanceof TLRPC.TL_documentAttributeAudio) { + if (attribute.performer != null) { + ok = attribute.performer.toLowerCase().contains(q); + } + if (!ok && attribute.title != null) { + ok = attribute.title.toLowerCase().contains(q); + } + break; + } + } + if (ok) { + resultArray.add(messageObject); + break; + } + } } } - } - updateSearchResults(resultArray); - }); - } - }); + updateSearchResults(resultArray); + }); + } + }, 300); + } } private void updateSearchResults(final ArrayList documents) { @@ -2951,9 +2885,10 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector)); arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUBACKGROUND, null, null, null, null, Theme.key_actionBarDefaultSubmenuBackground)); arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM, null, null, null, null, Theme.key_actionBarDefaultSubmenuItem)); + arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubmenuItemIcon)); arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_AM_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon)); - arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_AM_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault)); + arrayList.add(new ThemeDescription(actionModeBackground, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_sharedMedia_actionMode)); arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_AM_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector)); arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCH, null, null, null, null, Theme.key_actionBarDefaultSearch)); arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCHPLACEHOLDER, null, null, null, null, Theme.key_actionBarDefaultSearchPlaceholder)); @@ -2969,7 +2904,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No arrayList.add(new ThemeDescription(scrollSlidingTextTabStrip.getTabsContainer(), ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{TextView.class}, null, null, null, Theme.key_actionBarDefaultTitle)); arrayList.add(new ThemeDescription(scrollSlidingTextTabStrip.getTabsContainer(), ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{TextView.class}, null, null, null, Theme.key_actionBarDefaultSubtitle)); arrayList.add(new ThemeDescription(scrollSlidingTextTabStrip.getTabsContainer(), ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, new Class[]{TextView.class}, null, null, null, Theme.key_actionBarDefaultSelector)); - arrayList.add(new ThemeDescription(null, 0, null, scrollSlidingTextTabStrip.getRectPaint(), null, null, Theme.key_actionBarDefaultTitle)); + arrayList.add(new ThemeDescription(null, 0, null, null, new Drawable[]{scrollSlidingTextTabStrip.getSelectorDrawable()}, null, Theme.key_actionBarDefaultTitle)); for (int a = 0; a < mediaPages.length; a++) { final int num = a; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NewContactActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NewContactActivity.java index e8e6a0c17..1e7e73ffc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NewContactActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NewContactActivity.java @@ -185,6 +185,7 @@ public class NewContactActivity extends BaseFragment implements AdapterView.OnIt ActionBarMenu menu = actionBar.createMenu(); editDoneItem = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)); + editDoneItem.setContentDescription(LocaleController.getString("Done", R.string.Done)); editDoneItemProgress = new ContextProgressView(context, 1); editDoneItem.addView(editDoneItemProgress, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); @@ -323,6 +324,7 @@ public class NewContactActivity extends BaseFragment implements AdapterView.OnIt textView.setText("+"); textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + textView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); linearLayout2.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); codeField = new EditTextBoldCursor(context); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java index b796fb710..b2b69afe4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java @@ -22,21 +22,24 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.Settings; +import android.text.TextUtils; +import android.util.LongSparseArray; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationsController; import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; @@ -59,9 +62,13 @@ import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; +import java.util.Map; import java.util.Timer; import java.util.TimerTask; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class NotificationsCustomSettingsActivity extends BaseFragment { private RecyclerListView listView; @@ -95,9 +102,16 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { private ArrayList exceptions; public NotificationsCustomSettingsActivity(int type, ArrayList notificationExceptions) { + this(type, notificationExceptions, false); + } + + public NotificationsCustomSettingsActivity(int type, ArrayList notificationExceptions, boolean load) { super(); currentType = type; exceptions = notificationExceptions; + if (load) { + loadExceptions(); + } } @Override @@ -257,6 +271,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { profileNotificationsActivity.setDelegate(exception -> { exceptions.add(0, exception); updateRows(); + adapter.notifyDataSetChanged(); }); presentFragment(profileNotificationsActivity, true); }); @@ -327,6 +342,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { Intent tmpIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER); tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION); tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true); + tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true); tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)); Uri currentSound = null; @@ -483,6 +499,156 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { } } + private void loadExceptions() { + MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> { + ArrayList usersResult = new ArrayList<>(); + ArrayList chatsResult = new ArrayList<>(); + ArrayList channelsResult = new ArrayList<>(); + LongSparseArray waitingForLoadExceptions = new LongSparseArray<>(); + + ArrayList usersToLoad = new ArrayList<>(); + ArrayList chatsToLoad = new ArrayList<>(); + ArrayList encryptedChatsToLoad = new ArrayList<>(); + + ArrayList users = new ArrayList<>(); + ArrayList chats = new ArrayList<>(); + ArrayList encryptedChats = new ArrayList<>(); + int selfId = UserConfig.getInstance(currentAccount).clientUserId; + + SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); + Map values = preferences.getAll(); + for (Map.Entry entry : values.entrySet()) { + String key = entry.getKey(); + if (key.startsWith("notify2_")) { + key = key.replace("notify2_", ""); + + long did = Utilities.parseLong(key); + if (did != 0 && did != selfId) { + NotificationsSettingsActivity.NotificationException exception = new NotificationsSettingsActivity.NotificationException(); + exception.did = did; + exception.hasCustom = preferences.getBoolean("custom_" + did, false); + exception.notify = (Integer) entry.getValue(); + if (exception.notify != 0) { + Integer time = (Integer) values.get("notifyuntil_" + key); + if (time != null) { + exception.muteUntil = time; + } + } + + int lower_id = (int) did; + int high_id = (int) (did << 32); + if (lower_id != 0) { + if (lower_id > 0) { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(lower_id); + if (user == null) { + usersToLoad.add(lower_id); + waitingForLoadExceptions.put(did, exception); + } else if (user.deleted) { + continue; + } + usersResult.add(exception); + } else { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_id); + if (chat == null) { + chatsToLoad.add(-lower_id); + waitingForLoadExceptions.put(did, exception); + continue; + } else if (chat.left || chat.kicked || chat.migrated_to != null) { + continue; + } + if (ChatObject.isChannel(chat) && !chat.megagroup) { + channelsResult.add(exception); + } else { + chatsResult.add(exception); + } + } + } else if (high_id != 0) { + TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance(currentAccount).getEncryptedChat(high_id); + if (encryptedChat == null) { + encryptedChatsToLoad.add(high_id); + waitingForLoadExceptions.put(did, exception); + } else { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(encryptedChat.user_id); + if (user == null) { + usersToLoad.add(encryptedChat.user_id); + waitingForLoadExceptions.put(encryptedChat.user_id, exception); + } else if (user.deleted) { + continue; + } + } + usersResult.add(exception); + } + } + } + } + if (waitingForLoadExceptions.size() != 0) { + try { + if (!encryptedChatsToLoad.isEmpty()) { + MessagesStorage.getInstance(currentAccount).getEncryptedChatsInternal(TextUtils.join(",", encryptedChatsToLoad), encryptedChats, usersToLoad); + } + if (!usersToLoad.isEmpty()) { + MessagesStorage.getInstance(currentAccount).getUsersInternal(TextUtils.join(",", usersToLoad), users); + } + if (!chatsToLoad.isEmpty()) { + MessagesStorage.getInstance(currentAccount).getChatsInternal(TextUtils.join(",", chatsToLoad), chats); + } + } catch (Exception e) { + FileLog.e(e); + } + for (int a = 0, size = chats.size(); a < size; a++) { + TLRPC.Chat chat = chats.get(a); + if (chat.left || chat.kicked || chat.migrated_to != null) { + continue; + } + NotificationsSettingsActivity.NotificationException exception = waitingForLoadExceptions.get(-chat.id); + waitingForLoadExceptions.remove(-chat.id); + + if (exception != null) { + if (ChatObject.isChannel(chat) && !chat.megagroup) { + channelsResult.add(exception); + } else { + chatsResult.add(exception); + } + } + } + for (int a = 0, size = users.size(); a < size; a++) { + TLRPC.User user = users.get(a); + if (user.deleted) { + continue; + } + waitingForLoadExceptions.remove(user.id); + } + for (int a = 0, size = encryptedChats.size(); a < size; a++) { + TLRPC.EncryptedChat encryptedChat = encryptedChats.get(a); + waitingForLoadExceptions.remove(((long) encryptedChat.id) << 32); + } + for (int a = 0, size = waitingForLoadExceptions.size(); a < size; a++) { + long did = waitingForLoadExceptions.keyAt(a); + if ((int) did < 0) { + chatsResult.remove(waitingForLoadExceptions.valueAt(a)); + channelsResult.remove(waitingForLoadExceptions.valueAt(a)); + } else { + usersResult.remove(waitingForLoadExceptions.valueAt(a)); + } + } + } + AndroidUtilities.runOnUIThread(() -> { + MessagesController.getInstance(currentAccount).putUsers(users, true); + MessagesController.getInstance(currentAccount).putChats(chats, true); + MessagesController.getInstance(currentAccount).putEncryptedChats(encryptedChats, true); + if (currentType == NotificationsController.TYPE_PRIVATE) { + exceptions = usersResult; + } else if (currentType == NotificationsController.TYPE_GROUP) { + exceptions = chatsResult; + } else { + exceptions = channelsResult; + } + updateRows(); + adapter.notifyDataSetChanged(); + }); + }); + } + private void updateRows() { rowCount = 0; if (currentType != -1) { @@ -648,7 +814,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { if (search1.equals(search2) || search2.length() == 0) { search2 = null; } - String search[] = new String[1 + (search2 != null ? 1 : 0)]; + String[] search = new String[1 + (search2 != null ? 1 : 0)]; search[0] = search1; if (search2 != null) { search[1] = search2; @@ -657,7 +823,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment { ArrayList resultArray = new ArrayList<>(); ArrayList resultArrayNames = new ArrayList<>(); - String names[] = new String[2]; + String[] names = new String[2]; for (int a = 0; a < contactsCopy.size(); a++) { NotificationsSettingsActivity.NotificationException exception = contactsCopy.get(a); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java index 063d0d7c5..fe17a769d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java @@ -31,10 +31,9 @@ import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationsController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.FileLog; @@ -50,6 +49,7 @@ import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextDetailSettingsCell; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.LayoutHelper; @@ -58,6 +58,9 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; import java.util.Map; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class NotificationsSettingsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { public static class NotificationException { @@ -70,10 +73,16 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif private RecyclerListView listView; private boolean reseting = false; private ListAdapter adapter; + @SuppressWarnings("FieldCanBeLocal") + private LinearLayoutManager layoutManager; private ArrayList exceptionUsers = null; private ArrayList exceptionChats = null; private ArrayList exceptionChannels = null; + private int accountsSectionRow; + private int accountsAllRow; + private int accountsInfoRow; + private int notificationsServiceRow; private int notificationsServiceConnectionRow; @@ -116,6 +125,16 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif MessagesController.getInstance(currentAccount).loadSignUpNotificationsSettings(); loadExceptions(); + if (UserConfig.getActivatedAccountsCount() > 1) { + accountsSectionRow = rowCount++; + accountsAllRow = rowCount++; + accountsInfoRow = rowCount++; + } else { + accountsSectionRow = -1; + accountsAllRow = -1; + accountsInfoRow = -1; + } + notificationsSectionRow = rowCount++; privateRow = rowCount++; groupRow = rowCount++; @@ -338,7 +357,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif listView = new RecyclerListView(context); listView.setItemAnimator(null); listView.setLayoutAnimation(null); - listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) { + listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) { @Override public boolean supportsPredictiveItemAnimations() { return false; @@ -382,6 +401,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif Intent tmpIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER); tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE); tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true); + tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true); tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)); Uri currentSound = null; @@ -521,6 +541,24 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif } else { ConnectionsManager.getInstance(currentAccount).setPushConnectionEnabled(false); } + } else if (position == accountsAllRow) { + SharedPreferences preferences = MessagesController.getGlobalNotificationsSettings(); + enabled = preferences.getBoolean("AllAccounts", true); + SharedPreferences.Editor editor = preferences.edit(); + editor.putBoolean("AllAccounts", !enabled); + editor.commit(); + SharedConfig.showNotificationsForAllAccounts = !enabled; + for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { + if (SharedConfig.showNotificationsForAllAccounts) { + NotificationsController.getInstance(a).showNotifications(); + } else { + if (a == currentAccount) { + NotificationsController.getInstance(a).showNotifications(); + } else { + NotificationsController.getInstance(a).hideNotifications(); + } + } + } } else if (position == notificationsServiceRow) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); enabled = preferences.getBoolean("pushService", true); @@ -688,7 +726,8 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif return !(position == notificationsSectionRow || position == notificationsSection2Row || position == inappSectionRow || position == eventsSectionRow || position == otherSectionRow || position == resetSectionRow || position == badgeNumberSection || position == otherSection2Row || position == resetSection2Row || - position == callsSection2Row || position == callsSectionRow || position == badgeNumberSection2Row); + position == callsSection2Row || position == callsSectionRow || position == badgeNumberSection2Row || + position == accountsSectionRow || position == accountsInfoRow); } @Override @@ -720,10 +759,14 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif view = new ShadowSectionCell(mContext); break; case 5: - default: view = new TextSettingsCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; + case 6: + default: + view = new TextInfoPrivacyCell(mContext); + view.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + break; } return new RecyclerListView.Holder(view); } @@ -747,6 +790,8 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif headerCell.setText(LocaleController.getString("VoipNotificationSettings", R.string.VoipNotificationSettings)); } else if (position == badgeNumberSection) { headerCell.setText(LocaleController.getString("BadgeNumber", R.string.BadgeNumber)); + } else if (position == accountsSectionRow) { + headerCell.setText(LocaleController.getString("ShowNotificationsFor", R.string.ShowNotificationsFor)); } break; } @@ -781,6 +826,8 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif checkCell.setTextAndCheck(LocaleController.getString("InChatSound", R.string.InChatSound), preferences.getBoolean("EnableInChatSound", true), true); } else if (position == callsVibrateRow) { checkCell.setTextAndCheck(LocaleController.getString("Vibrate", R.string.Vibrate), preferences.getBoolean("EnableCallVibrate", true), true); + } else if (position == accountsAllRow) { + checkCell.setTextAndCheck(LocaleController.getString("AllAccounts", R.string.AllAccounts), MessagesController.getGlobalNotificationsSettings().getBoolean("AllAccounts", true), false); } break; } @@ -841,7 +888,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif checkCell.setTextAndValueAndCheck(text, builder, enabled, iconType, position != channelsRow); break; } - case 5: + case 5: { TextSettingsCell textCell = (TextSettingsCell) holder.itemView; SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); if (position == callsRingtoneRow) { @@ -879,6 +926,14 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif textCell.setTextAndValue(LocaleController.getString("RepeatNotifications", R.string.RepeatNotifications), value, false); } break; + } + case 6: { + TextInfoPrivacyCell textCell = (TextInfoPrivacyCell) holder.itemView; + if (position == accountsInfoRow) { + textCell.setText(LocaleController.getString("ShowNotificationsForInfo", R.string.ShowNotificationsForInfo)); + } + break; + } } } @@ -886,13 +941,13 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif public int getItemViewType(int position) { if (position == eventsSectionRow || position == otherSectionRow || position == resetSectionRow || position == callsSectionRow || position == badgeNumberSection || position == inappSectionRow || - position == notificationsSectionRow) { + position == notificationsSectionRow || position == accountsSectionRow) { return 0; } else if (position == inappSoundRow || position == inappVibrateRow || position == notificationsServiceConnectionRow || position == inappPreviewRow || position == contactJoinedRow || position == pinnedMessageRow || position == notificationsServiceRow || position == badgeNumberMutedRow || position == badgeNumberMessagesRow || position == badgeNumberShowRow || position == inappPriorityRow || position == inchatSoundRow || - position == androidAutoAlertRow) { + position == androidAutoAlertRow || position == accountsAllRow) { return 1; } else if (position == resetNotificationsRow) { return 2; @@ -901,6 +956,8 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif } else if (position == eventsSection2Row || position == notificationsSection2Row || position == otherSection2Row || position == resetSection2Row || position == callsSection2Row || position == badgeNumberSection2Row) { return 4; + } else if (position == accountsInfoRow) { + return 6; } else { return 5; } @@ -942,6 +999,10 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif new ThemeDescription(listView, 0, new Class[]{TextDetailSettingsCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), new ThemeDescription(listView, 0, new Class[]{TextDetailSettingsCell.class}, new String[]{"valueTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText2), + + 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_windowBackgroundWhiteGrayText4), + new ThemeDescription(listView, ThemeDescription.FLAG_LINKCOLOR, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteLinkText), }; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java index 82fb9f53a..88d4aa17f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java @@ -46,8 +46,6 @@ import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.messenger.support.fingerprint.FingerprintManagerCompat; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; @@ -64,6 +62,9 @@ import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.NumberPicker; import org.telegram.ui.Components.RecyclerListView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class PasscodeActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListAdapter listAdapter; @@ -718,6 +719,7 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUBACKGROUND, null, null, null, null, Theme.key_actionBarDefaultSubmenuBackground), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM, null, null, null, null, Theme.key_actionBarDefaultSubmenuItem), + new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubmenuItemIcon), new ThemeDescription(listView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java index 17b437a5c..0f88c7f21 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java @@ -27,7 +27,9 @@ import android.os.Build; import android.os.Bundle; import android.os.Vibrator; import android.provider.MediaStore; -import android.support.v4.content.FileProvider; +import androidx.core.content.FileProvider; + +import android.telephony.PhoneNumberUtils; import android.telephony.SmsManager; import android.telephony.TelephonyManager; import android.text.Editable; @@ -73,6 +75,7 @@ import org.telegram.messenger.DownloadController; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.MessageObject; @@ -352,7 +355,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter return null; } SecureDocumentCell cell = (SecureDocumentCell) currentPhotoViewerLayout.getChildAt(index); - int coords[] = new int[2]; + int[] coords = new int[2]; cell.imageView.getLocationInWindow(coords); PhotoViewer.PlaceProviderObject object = new PhotoViewer.PlaceProviderObject(); object.viewX = coords[0]; @@ -1522,11 +1525,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter passwordAvatarContainer.addView(avatarImageView, LayoutHelper.createFrame(64, 64, Gravity.CENTER, 0, 8, 0, 0)); AvatarDrawable avatarDrawable = new AvatarDrawable(botUser); - TLRPC.FileLocation photo = null; - if (botUser.photo != null) { - photo = botUser.photo.photo_small; - } - avatarImageView.setImage(photo, "50_50", avatarDrawable, botUser); + avatarImageView.setImage(ImageLocation.getForUser(botUser, false), "50_50", avatarDrawable, botUser); passwordRequestTextView = new TextInfoPrivacyCell(context); passwordRequestTextView.getTextView().setGravity(Gravity.CENTER_HORIZONTAL); @@ -1698,7 +1697,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter Utilities.globalQueue.postRunnable(() -> { TLRPC.TL_account_getPasswordSettings req = new TLRPC.TL_account_getPasswordSettings(); - final byte x_bytes[]; + final byte[] x_bytes; if (saved) { x_bytes = savedPasswordHash; } else if (currentPassword.current_algo instanceof TLRPC.TL_passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow) { @@ -2003,11 +2002,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter avatarContainer.addView(avatarImageView, LayoutHelper.createFrame(64, 64, Gravity.CENTER, 0, 8, 0, 0)); AvatarDrawable avatarDrawable = new AvatarDrawable(botUser); - TLRPC.FileLocation photo = null; - if (botUser.photo != null) { - photo = botUser.photo.photo_small; - } - avatarImageView.setImage(photo, "50_50", avatarDrawable, botUser); + avatarImageView.setImage(ImageLocation.getForUser(botUser, false), "50_50", avatarDrawable, botUser); bottomCell = new TextInfoPrivacyCell(context); bottomCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_top, Theme.key_windowBackgroundGrayShadow)); @@ -2645,7 +2640,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("PassportNoDocumentsAdd", R.string.PassportNoDocumentsAdd)); - builder.setItems(values.toArray(new CharSequence[values.size()]), (dialog, which) -> { + builder.setItems(values.toArray(new CharSequence[0]), (dialog, which) -> { TLRPC.TL_secureRequiredType requiredType = null; TLRPC.TL_secureRequiredType documentRequiredType = null; try { @@ -3530,7 +3525,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter } private void createDocumentDeleteAlert() { - final boolean checks[] = new boolean[]{true}; + final boolean[] checks = new boolean[]{true}; AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialog, which) -> { @@ -4200,7 +4195,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter int selectedDay = -1; int selectedMonth = -1; int selectedYear = -1; - String args[] = field1.getText().toString().split("\\."); + String[] args = field1.getText().toString().split("\\."); if (args.length == 3) { selectedDay = Utilities.parseInt(args[0]); selectedMonth = Utilities.parseInt(args[1]); @@ -4759,7 +4754,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter case "expiry_date": boolean ok = false; if (!TextUtils.isEmpty(value)) { - String args[] = value.split("\\."); + String[] args = value.split("\\."); if (args.length == 3) { currentExpireDate[0] = Utilities.parseInt(args[2]); currentExpireDate[1] = Utilities.parseInt(args[1]); @@ -5066,8 +5061,8 @@ public class PassportActivity extends BaseFragment implements NotificationCenter return; } values.clear(); - String keys[] = null; - String documentKeys[] = null; + String[] keys = null; + String[] documentKeys = null; if (requiredType.type instanceof TLRPC.TL_secureValueTypePersonalDetails) { if (currentActivityType == TYPE_REQUEST && !documentOnly || currentActivityType == TYPE_MANAGE && documentRequiredType == null) { keys = new String[]{ @@ -5104,7 +5099,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter if (keys != null || documentKeys != null) { try { JSONObject jsonObject = null; - String currentKeys[] = null; + String[] currentKeys = null; for (int b = 0; b < 2; b++) { if (b == 0) { if (json != null) { @@ -5955,7 +5950,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter } } - builder.setItems(strings.toArray(new CharSequence[strings.size()]), (dialog, which) -> openTypeActivity(requiredType, documentRequiredTypes.get(which), documentRequiredTypes, documentOnly)); + builder.setItems(strings.toArray(new CharSequence[0]), (dialog, which) -> openTypeActivity(requiredType, documentRequiredTypes.get(which), documentRequiredTypes, documentOnly)); showDialog(builder.create()); return; } @@ -6273,7 +6268,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter builder.setMessage(LocaleController.getString("AllowReadCall", R.string.AllowReadCall)); permissionsDialog = showDialog(builder.create()); } else { - getParentActivity().requestPermissions(permissionsItems.toArray(new String[permissionsItems.size()]), 6); + getParentActivity().requestPermissions(permissionsItems.toArray(new String[0]), 6); } pendingPhone = phone; pendingErrorRunnable = errorRunnable; @@ -6309,7 +6304,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter @SuppressLint("HardwareIds") String number = tm.getLine1Number(); if (!TextUtils.isEmpty(number)) { - req.settings.current_number = phone.contains(number) || number.contains(phone); + req.settings.current_number = PhoneNumberUtils.compare(phone, number); if (!req.settings.current_number) { req.settings.allow_flashcall = false; } @@ -6697,7 +6692,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter protected void onDialogDismiss(Dialog dialog) { if (currentActivityType == TYPE_PHONE) { if (Build.VERSION.SDK_INT >= 23 && dialog == permissionsDialog && !permissionsItems.isEmpty()) { - getParentActivity().requestPermissions(permissionsItems.toArray(new String[permissionsItems.size()]), 6); + getParentActivity().requestPermissions(permissionsItems.toArray(new String[0]), 6); } } } @@ -8074,6 +8069,6 @@ public class PassportActivity extends BaseFragment implements NotificationCenter arrayList.add(new ThemeDescription(emptyTextView2, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteGrayText2)); arrayList.add(new ThemeDescription(emptyTextView3, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlueText4)); - return arrayList.toArray(new ThemeDescription[arrayList.size()]); + return arrayList.toArray(new ThemeDescription[0]); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java index 71ce2e001..70a33d1d5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java @@ -180,15 +180,17 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen private ContextProgressView progressViewButton; private AnimatorSet doneItemAnimation; private WebView webView; + private String webViewUrl; + private boolean shouldNavigateBack; private ScrollView scrollView; private TextView textView; - private HeaderCell headerCell[] = new HeaderCell[3]; + private HeaderCell[] headerCell = new HeaderCell[3]; private ArrayList dividers = new ArrayList<>(); - private ShadowSectionCell sectionCell[] = new ShadowSectionCell[3]; + private ShadowSectionCell[] sectionCell = new ShadowSectionCell[3]; private TextCheckCell checkCell1; - private TextInfoPrivacyCell bottomCell[] = new TextInfoPrivacyCell[3]; - private TextSettingsCell settingsCell[] = new TextSettingsCell[2]; + private TextInfoPrivacyCell[] bottomCell = new TextInfoPrivacyCell[3]; + private TextSettingsCell[] settingsCell = new TextSettingsCell[2]; private FrameLayout androidPayContainer; private LinearLayout linearLayout2; @@ -199,7 +201,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen private TextView payTextView; private FrameLayout bottomLayout; private PaymentInfoCell paymentInfoCell; - private TextDetailSettingsCell detailSettingsCell[] = new TextDetailSettingsCell[7]; + private TextDetailSettingsCell[] detailSettingsCell = new TextDetailSettingsCell[7]; private TLRPC.TL_account_password currentPassword; private boolean waitingForEmail; @@ -726,13 +728,13 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen country = codesMap.get(sub); if (country != null) { ok = true; - textToSet = text.substring(a, text.length()) + inputFields[FIELD_PHONE].getText().toString(); + textToSet = text.substring(a) + inputFields[FIELD_PHONE].getText().toString(); inputFields[FIELD_PHONECODE].setText(text = sub); break; } } if (!ok) { - textToSet = text.substring(1, text.length()) + inputFields[FIELD_PHONE].getText().toString(); + textToSet = text.substring(1) + inputFields[FIELD_PHONE].getText().toString(); inputFields[FIELD_PHONECODE].setText(text = text.substring(0, 1)); } } @@ -804,7 +806,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen String phoneChars = "0123456789"; String str = phoneField.getText().toString(); if (characterAction == 3) { - str = str.substring(0, actionPosition) + str.substring(actionPosition + 1, str.length()); + str = str.substring(0, actionPosition) + str.substring(actionPosition + 1); start--; } StringBuilder builder = new StringBuilder(str.length()); @@ -1022,9 +1024,14 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen webView = new WebView(context) { @Override public boolean onTouchEvent(MotionEvent event) { - getParent().requestDisallowInterceptTouchEvent(true); + ((ViewGroup) fragmentView).requestDisallowInterceptTouchEvent(true); return super.onTouchEvent(event); } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } }; webView.getSettings().setJavaScriptEnabled(true); webView.getSettings().setDomStorageEnabled(true); @@ -1043,6 +1050,12 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen super.onLoadResource(view, url); } + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + shouldNavigateBack = !url.equals(webViewUrl); + return super.shouldOverrideUrlLoading(view, url); + } + @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); @@ -1238,7 +1251,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen String phoneChars = "0123456789"; String str = phoneField.getText().toString(); if (characterAction == 3) { - str = str.substring(0, actionPosition) + str.substring(actionPosition + 1, str.length()); + str = str.substring(0, actionPosition) + str.substring(actionPosition + 1); start--; } StringBuilder builder = new StringBuilder(str.length()); @@ -1254,7 +1267,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen if (builder.length() > 0) { String currentString = builder.toString(); for (int a = 0; a < 3; a++) { - String checkArr[]; + String[] checkArr; String resultHint; int resultMaxLength; switch (a) { @@ -1377,7 +1390,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen String phoneChars = "0123456789"; String str = phoneField.getText().toString(); if (characterAction == 3) { - str = str.substring(0, actionPosition) + str.substring(actionPosition + 1, str.length()); + str = str.substring(0, actionPosition) + str.substring(actionPosition + 1); start--; } StringBuilder builder = new StringBuilder(str.length()); @@ -2242,10 +2255,11 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen try { ViewParent parent = webView.getParent(); if (parent != null) { - ((FrameLayout) parent).removeView(webView); + ((ViewGroup) parent).removeView(webView); } webView.stopLoading(); webView.loadUrl("about:blank"); + webViewUrl = null; webView.destroy(); webView = null; } catch (Exception e) { @@ -2268,7 +2282,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen if (isOpen && !backward) { if (webView != null) { if (currentStep != 4) { - webView.loadUrl(paymentForm.url); + webView.loadUrl(webViewUrl = paymentForm.url); } } else if (currentStep == 2) { inputFields[FIELD_CARD].requestFocus(); @@ -2595,13 +2609,13 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen String country = codesMap.get(sub); if (country != null) { ok = true; - textToSet = number.substring(a, number.length()); + textToSet = number.substring(a); inputFields[FIELD_PHONECODE].setText(sub); break; } } if (!ok) { - textToSet = number.substring(1, number.length()); + textToSet = number.substring(1); inputFields[FIELD_PHONECODE].setText(number.substring(0, 1)); } } @@ -2691,7 +2705,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen } int dot = email.lastIndexOf('.'); int dog = email.lastIndexOf('@'); - if (dot < 0 || dog < 0 || dot < dog) { + if (dog < 0 || dot < dog) { shakeField(FIELD_ENTERPASSWORDEMAIL); return; } @@ -2796,7 +2810,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen Integer month; Integer year; String date = inputFields[FIELD_EXPIRE_DATE].getText().toString(); - String args[] = date.split("/"); + String[] args = date.split("/"); if (args.length == 2) { month = Utilities.parseInt(args[0]); year = Utilities.parseInt(args[1]); @@ -3029,7 +3043,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen progressView.setVisibility(View.VISIBLE); doneItem.setEnabled(false); doneItem.getImageView().setVisibility(View.INVISIBLE); - webView.loadUrl(((TLRPC.TL_payments_paymentVerficationNeeded) response).url); + webView.loadUrl(webViewUrl = ((TLRPC.TL_payments_paymentVerficationNeeded) response).url); }); } } else { @@ -3100,7 +3114,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen byte[] passwordBytes = AndroidUtilities.getStringBytes(password); Utilities.globalQueue.postRunnable(() -> { - final byte x_bytes[]; + final byte[] x_bytes; if (currentPassword.current_algo instanceof TLRPC.TL_passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow) { TLRPC.TL_passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow algo = (TLRPC.TL_passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow) currentPassword.current_algo; x_bytes = SRPHelper.getX(passwordBytes, algo); @@ -3264,6 +3278,11 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen @Override public boolean onBackPressed() { + if (shouldNavigateBack) { + webView.loadUrl(webViewUrl); + shouldNavigateBack = false; + return false; + } return !donePressed; } @@ -3366,6 +3385,6 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen arrayList.add(new ThemeDescription(bottomLayout, ThemeDescription.FLAG_SELECTORWHITE, null, null, null, null, Theme.key_windowBackgroundWhite)); arrayList.add(new ThemeDescription(bottomLayout, ThemeDescription.FLAG_SELECTORWHITE, null, null, null, null, Theme.key_listSelector)); - return arrayList.toArray(new ThemeDescription[arrayList.size()]); + return arrayList.toArray(new ThemeDescription[0]); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhonebookSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhonebookSelectActivity.java index f3a6d8518..41a634eb0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhonebookSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhonebookSelectActivity.java @@ -18,8 +18,6 @@ import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; import org.telegram.messenger.LocaleController; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; @@ -37,6 +35,9 @@ import org.telegram.ui.Components.EmptyTextProgressView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class PhonebookSelectActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private RecyclerListView listView; @@ -58,7 +59,6 @@ public class PhonebookSelectActivity extends BaseFragment implements Notificatio void didSelectContact(TLRPC.User user); } - @SuppressWarnings("unchecked") @Override public boolean onFragmentCreate() { super.onFragmentCreate(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhonebookShareActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhonebookShareActivity.java index eb5488d8a..dfa7a233d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhonebookShareActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhonebookShareActivity.java @@ -25,11 +25,10 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ContactsController; import org.telegram.messenger.FileLog; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; import org.telegram.messenger.browser.Browser; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.AlertDialog; @@ -49,6 +48,9 @@ import java.io.File; import java.util.ArrayList; import java.util.Locale; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class PhonebookShareActivity extends BaseFragment { public class TextCheckBoxCell extends FrameLayout { @@ -609,7 +611,7 @@ public class PhonebookShareActivity extends BaseFragment { } else if (item.type == 2) { ContentValues row = new ContentValues(); row.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE); - String args[] = item.getRawValue(); + String[] args = item.getRawValue(); if (args.length > 0) { row.put(ContactsContract.CommonDataKinds.StructuredPostal.POBOX, args[0]); } @@ -790,11 +792,7 @@ public class PhonebookShareActivity extends BaseFragment { avatarDrawable.setInfo(5, currentUser.first_name, currentUser.last_name, false); avatarDrawable.setColor(Theme.getColor(Theme.key_avatar_backgroundInProfileBlue)); - TLRPC.FileLocation photo = null; - if (currentUser.photo != null) { - photo = currentUser.photo.photo_small; - } - avatarImage.setImage(photo, "50_50", avatarDrawable, currentUser); + avatarImage.setImage(ImageLocation.getForUser(currentUser, false), "50_50", avatarDrawable, currentUser); nameTextView.setText(ContactsController.formatName(currentUser.first_name, currentUser.last_name)); return fragmentView; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java index e96dcad1a..4b9376414 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java @@ -27,8 +27,6 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.BaseFragment; @@ -43,6 +41,9 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; import java.util.HashMap; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class PhotoAlbumPickerActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { public interface PhotoAlbumPickerActivityDelegate { @@ -103,7 +104,6 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati super.onFragmentDestroy(); } - @SuppressWarnings("unchecked") @Override public View createView(Context context) { actionBar.setBackgroundColor(Theme.ACTION_BAR_MEDIA_PICKER_COLOR); @@ -125,7 +125,7 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati }); ActionBarMenu menu = actionBar.createMenu(); - menu.addItem(1, R.drawable.ic_ab_other); + menu.addItem(1, R.drawable.ic_ab_other).setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); fragmentView = new FrameLayout(context); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java index e29cd7e9f..7c2f99438 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java @@ -43,8 +43,6 @@ import org.telegram.messenger.SharedConfig; import org.telegram.messenger.VideoEditedInfo; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.GridLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; @@ -66,6 +64,9 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; import java.util.HashMap; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class PhotoPickerActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { public interface PhotoPickerActivityDelegate { @@ -88,13 +89,10 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen private AnimatorSet hintAnimation; private boolean searching; - private boolean bingSearchEndReached = true; - private boolean giphySearchEndReached = true; + private boolean imageSearchEndReached = true; private String lastSearchString; private String nextImagesSearchOffset; private boolean loadingRecent; - private int nextGiphySearchOffset; - private int giphyReqId; private int imageReqId; private int lastSearchToken; private boolean allowCaption; @@ -132,7 +130,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index, boolean needPreview) { PhotoPickerPhotoCell cell = getCellForIndex(index); if (cell != null) { - int coords[] = new int[2]; + int[] coords = new int[2]; cell.photoImage.getLocationInWindow(coords); PhotoViewer.PlaceProviderObject object = new PhotoViewer.PlaceProviderObject(); object.viewX = coords[0]; @@ -413,10 +411,6 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen public void onFragmentDestroy() { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.closeChats); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.recentImagesDidLoad); - if (giphyReqId != 0) { - ConnectionsManager.getInstance(currentAccount).cancelRequest(giphyReqId, true); - giphyReqId = 0; - } if (imageReqId != 0) { ConnectionsManager.getInstance(currentAccount).cancelRequest(imageReqId, true); imageReqId = 0; @@ -467,17 +461,12 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen searchResult.clear(); searchResultKeys.clear(); lastSearchString = null; - bingSearchEndReached = true; - giphySearchEndReached = true; + imageSearchEndReached = true; searching = false; if (imageReqId != 0) { ConnectionsManager.getInstance(currentAccount).cancelRequest(imageReqId, true); imageReqId = 0; } - if (giphyReqId != 0) { - ConnectionsManager.getInstance(currentAccount).cancelRequest(giphyReqId, true); - giphyReqId = 0; - } emptyView.setText(""); /*if (type == 0) { emptyView.setText(LocaleController.getString("NoRecentPhotos", R.string.NoRecentPhotos)); @@ -623,10 +612,8 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen if (visibleItemCount > 0) { int totalItemCount = layoutManager.getItemCount(); if (visibleItemCount != 0 && firstVisibleItem + visibleItemCount > totalItemCount - 2 && !searching) { - if (type == 0 && !bingSearchEndReached) { - searchImages(lastSearchString, nextImagesSearchOffset, true); - } else if (type == 1 && !giphySearchEndReached) { - searchGiphyImages(searchItem.getSearchField().getText().toString(), nextGiphySearchOffset); + if (!imageSearchEndReached) { + searchImages(type == 1, lastSearchString, nextImagesSearchOffset, true); } } } @@ -649,12 +636,14 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen imageOrderToggleButton = new ImageView(context); imageOrderToggleButton.setScaleType(ImageView.ScaleType.CENTER); imageOrderToggleButton.setImageResource(R.drawable.photos_group); + imageOrderToggleButton.setContentDescription(SharedConfig.groupPhotosEnabled ? LocaleController.getString("GroupPhotosHelp", R.string.GroupPhotosHelp) : LocaleController.getString("SinglePhotosHelp", R.string.SinglePhotosHelp)); pickerBottomLayout.addView(imageOrderToggleButton, LayoutHelper.createFrame(48, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); imageOrderToggleButton.setOnClickListener(v -> { SharedConfig.toggleGroupPhotosEnabled(); imageOrderToggleButton.setColorFilter(SharedConfig.groupPhotosEnabled ? new PorterDuffColorFilter(0xff66bffa, PorterDuff.Mode.MULTIPLY) : null); showHint(false, SharedConfig.groupPhotosEnabled); updateCheckedPhotoIndices(); + imageOrderToggleButton.setContentDescription(SharedConfig.groupPhotosEnabled ? LocaleController.getString("GroupPhotosHelp", R.string.GroupPhotosHelp) : LocaleController.getString("SinglePhotosHelp", R.string.SinglePhotosHelp)); }); imageOrderToggleButton.setColorFilter(SharedConfig.groupPhotosEnabled ? new PorterDuffColorFilter(0xff66bffa, PorterDuff.Mode.MULTIPLY) : null); } @@ -743,14 +732,8 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen } searchResult.clear(); searchResultKeys.clear(); - bingSearchEndReached = true; - giphySearchEndReached = true; - if (type == 0) { - searchImages(editText.getText().toString(), "", true); - } else if (type == 1) { - nextGiphySearchOffset = 0; - searchGiphyImages(editText.getText().toString(), 0); - } + imageSearchEndReached = true; + searchImages(type == 1, editText.getText().toString(), "", true); lastSearchString = editText.getText().toString(); if (lastSearchString.length() == 0) { lastSearchString = null; @@ -945,93 +928,13 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen } } - private void searchGiphyImages(final String query, int offset) { - if (searching) { - searching = false; - if (giphyReqId != 0) { - ConnectionsManager.getInstance(currentAccount).cancelRequest(giphyReqId, true); - giphyReqId = 0; - } - if (imageReqId != 0) { - ConnectionsManager.getInstance(currentAccount).cancelRequest(imageReqId, true); - imageReqId = 0; - } - } - searching = true; - TLRPC.TL_messages_searchGifs req = new TLRPC.TL_messages_searchGifs(); - req.q = query; - req.offset = offset; - final int token = ++lastSearchToken; - giphyReqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - if (token != lastSearchToken) { - return; - } - int addedCount = 0; - int oldCount = searchResult.size(); - if (response != null) { - TLRPC.TL_messages_foundGifs res = (TLRPC.TL_messages_foundGifs) response; - nextGiphySearchOffset = res.next_offset; - for (int a = 0; a < res.results.size(); a++) { - TLRPC.FoundGif gif = res.results.get(a); - if (searchResultKeys.containsKey(gif.url)) { - continue; - } - MediaController.SearchImage bingImage = new MediaController.SearchImage(); - bingImage.id = gif.url; - if (gif.document != null) { - for (int b = 0; b < gif.document.attributes.size(); b++) { - TLRPC.DocumentAttribute attribute = gif.document.attributes.get(b); - if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { - bingImage.width = attribute.w; - bingImage.height = attribute.h; - break; - } - } - } else { - bingImage.width = gif.w; - bingImage.height = gif.h; - } - bingImage.size = 0; - bingImage.imageUrl = gif.content_url; - bingImage.thumbUrl = gif.thumb_url; - bingImage.localUrl = gif.url + "|" + query; - bingImage.document = gif.document; - if (gif.photo != null && gif.document != null) { - TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(gif.photo.sizes, itemWidth, true); - if (size != null) { - gif.document.thumbs.add(size); - gif.document.flags |= 1; - } - } - bingImage.type = 1; - searchResult.add(bingImage); - addedCount++; - searchResultKeys.put(bingImage.id, bingImage); - } - giphySearchEndReached = oldCount == searchResult.size(); - } - searching = false; - if (addedCount != 0) { - listAdapter.notifyItemRangeInserted(oldCount, addedCount); - } else if (giphySearchEndReached) { - listAdapter.notifyItemRemoved(searchResult.size() - 1); - } - if (searching && searchResult.isEmpty() || loadingRecent && lastSearchString == null) { - emptyView.showProgress(); - } else { - emptyView.showTextView(); - } - })); - ConnectionsManager.getInstance(currentAccount).bindRequestToGuid(giphyReqId, classGuid); - } - - private void searchBotUser() { + private void searchBotUser(boolean gif) { if (searchingUser) { return; } searchingUser = true; TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); - req.username = MessagesController.getInstance(currentAccount).imageSearchBot; + req.username = gif ? MessagesController.getInstance(currentAccount).gifSearchBot : MessagesController.getInstance(currentAccount).imageSearchBot; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (response != null) { AndroidUtilities.runOnUIThread(() -> { @@ -1041,19 +944,15 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen MessagesStorage.getInstance(currentAccount).putUsersAndChats(res.users, res.chats, true, true); String str = lastSearchImageString; lastSearchImageString = null; - searchImages(str, "", false); + searchImages(gif, str, "", false); }); } }); } - private void searchImages(final String query, final String offset, boolean searchUser) { + private void searchImages(boolean gif, final String query, final String offset, boolean searchUser) { if (searching) { searching = false; - if (giphyReqId != 0) { - ConnectionsManager.getInstance(currentAccount).cancelRequest(giphyReqId, true); - giphyReqId = 0; - } if (imageReqId != 0) { ConnectionsManager.getInstance(currentAccount).cancelRequest(imageReqId, true); imageReqId = 0; @@ -1063,10 +962,10 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen lastSearchImageString = query; searching = true; - TLObject object = MessagesController.getInstance(currentAccount).getUserOrChat(MessagesController.getInstance(currentAccount).imageSearchBot); + TLObject object = MessagesController.getInstance(currentAccount).getUserOrChat(gif ? MessagesController.getInstance(currentAccount).gifSearchBot : MessagesController.getInstance(currentAccount).imageSearchBot); if (!(object instanceof TLRPC.User)) { if (searchUser) { - searchBotUser(); + searchBotUser(gif); } return; } @@ -1103,26 +1002,45 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen for (int a = 0, count = res.results.size(); a < count; a++) { TLRPC.BotInlineResult result = res.results.get(a); - if (!"photo".equals(result.type)) { + if (!gif && !"photo".equals(result.type) || gif && !"gif".equals(result.type)) { continue; } if (searchResultKeys.containsKey(result.id)) { continue; } - MediaController.SearchImage bingImage = new MediaController.SearchImage(); - if (result.photo != null) { + MediaController.SearchImage image = new MediaController.SearchImage(); + + if (gif && result.document != null) { + for (int b = 0; b < result.document.attributes.size(); b++) { + TLRPC.DocumentAttribute attribute = result.document.attributes.get(b); + if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { + image.width = attribute.w; + image.height = attribute.h; + break; + } + } + image.document = result.document; + image.size = 0; + if (result.photo != null && result.document != null) { + TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(result.photo.sizes, itemWidth, true); + if (size != null) { + result.document.thumbs.add(size); + result.document.flags |= 1; + } + } + } else if (!gif && result.photo != null) { TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(result.photo.sizes, AndroidUtilities.getPhotoSize()); TLRPC.PhotoSize size2 = FileLoader.getClosestPhotoSizeWithSize(result.photo.sizes, 320); if (size == null) { continue; } - bingImage.width = size.w; - bingImage.height = size.h; - bingImage.photoSize = size; - bingImage.photo = result.photo; - bingImage.size = size.size; - bingImage.thumbPhotoSize = size2; + image.width = size.w; + image.height = size.h; + image.photoSize = size; + image.photo = result.photo; + image.size = size.size; + image.thumbPhotoSize = size2; } else { if (result.content == null) { continue; @@ -1130,35 +1048,35 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen for (int b = 0; b < result.content.attributes.size(); b++) { TLRPC.DocumentAttribute attribute = result.content.attributes.get(b); if (attribute instanceof TLRPC.TL_documentAttributeImageSize) { - bingImage.width = attribute.w; - bingImage.height = attribute.h; + image.width = attribute.w; + image.height = attribute.h; break; } } if (result.thumb != null) { - bingImage.thumbUrl = result.thumb.url; + image.thumbUrl = result.thumb.url; } else { - bingImage.thumbUrl = null; + image.thumbUrl = null; } - bingImage.imageUrl = result.content.url; - bingImage.size = result.content.size; + image.imageUrl = result.content.url; + image.size = gif ? 0 : result.content.size; } - bingImage.id = result.id; - bingImage.type = 0; - bingImage.localUrl = ""; + image.id = result.id; + image.type = gif ? 1 : 0; + image.localUrl = ""; - searchResult.add(bingImage); + searchResult.add(image); - searchResultKeys.put(bingImage.id, bingImage); + searchResultKeys.put(image.id, image); addedCount++; } - bingSearchEndReached = oldCount == searchResult.size() || nextImagesSearchOffset == null; + imageSearchEndReached = oldCount == searchResult.size() || nextImagesSearchOffset == null; } searching = false; if (addedCount != 0) { listAdapter.notifyItemRangeInserted(oldCount, addedCount); - } else if (bingSearchEndReached) { + } else if (imageSearchEndReached) { listAdapter.notifyItemRemoved(searchResult.size() - 1); } if (searching && searchResult.isEmpty() || loadingRecent && lastSearchString == null) { @@ -1260,10 +1178,8 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen if (selectedAlbum == null) { if (searchResult.isEmpty() && lastSearchString == null) { return recentImages.size(); - } else if (type == 0) { - return searchResult.size() + (bingSearchEndReached ? 0 : 1); - } else if (type == 1) { - return searchResult.size() + (giphySearchEndReached ? 0 : 1); + } else { + return searchResult.size() + (imageSearchEndReached ? 0 : 1); } } return selectedAlbum.photos.size(); @@ -1348,9 +1264,11 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen int minutes = photoEntry.duration / 60; int seconds = photoEntry.duration - minutes * 60; cell.videoTextView.setText(String.format("%d:%02d", minutes, seconds)); + cell.setContentDescription(LocaleController.getString("AttachVideo", R.string.AttachVideo) + ", " + LocaleController.formatCallDuration(photoEntry.duration)); imageView.setImage("vthumb://" + photoEntry.imageId + ":" + photoEntry.path, null, mContext.getResources().getDrawable(R.drawable.nophotos)); } else { cell.videoInfoContainer.setVisibility(View.INVISIBLE); + cell.setContentDescription(LocaleController.getString("AttachPhoto", R.string.AttachPhoto)); imageView.setImage("thumb://" + photoEntry.imageId + ":" + photoEntry.path, null, mContext.getResources().getDrawable(R.drawable.nophotos)); } } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index a241d02f8..00aa7c391 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -35,15 +35,19 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.media.MediaCodecInfo; -import android.media.MediaPlayer; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.SystemClock; import android.provider.Settings; -import android.support.annotation.Keep; -import android.support.annotation.NonNull; -import android.support.v4.content.FileProvider; +import androidx.annotation.Keep; +import androidx.annotation.NonNull; +import androidx.core.content.FileProvider; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.LinearSmoothScrollerEnd; +import androidx.recyclerview.widget.RecyclerView; + import android.text.Layout; import android.text.Selection; import android.text.Spannable; @@ -70,6 +74,8 @@ import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.WindowInsets; import android.view.WindowManager; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.view.animation.OvershootInterpolator; @@ -84,17 +90,6 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; -import com.coremedia.iso.IsoFile; -import com.coremedia.iso.boxes.Box; -import com.coremedia.iso.boxes.MediaBox; -import com.coremedia.iso.boxes.MediaHeaderBox; -import com.coremedia.iso.boxes.SampleSizeBox; -import com.coremedia.iso.boxes.TimeToSampleBox; -import com.coremedia.iso.boxes.TrackBox; -import com.coremedia.iso.boxes.TrackHeaderBox; -import com.googlecode.mp4parser.util.Matrix; -import com.googlecode.mp4parser.util.Path; - import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.Bitmaps; import org.telegram.messenger.BringAppForegroundService; @@ -104,8 +99,8 @@ import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DataQuery; import org.telegram.messenger.Emoji; -import org.telegram.messenger.EmojiSuggestion; import org.telegram.messenger.ImageLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.SecureDocument; import org.telegram.messenger.SendMessagesHelper; @@ -121,16 +116,13 @@ import org.telegram.messenger.MediaController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.DefaultItemAnimator; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.LinearSmoothScrollerEnd; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.UserConfig; import org.telegram.messenger.MessageObject; import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.SimpleTextView; @@ -174,7 +166,6 @@ import java.net.URLEncoder; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; -import java.util.List; import java.util.Locale; @SuppressWarnings("unchecked") @@ -214,7 +205,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private TextView nameTextView; private TextView dateTextView; private ActionBarMenuItem menuItem; - private TextView allMediaItem; + private ActionBarMenuSubItem allMediaItem; private ActionBarMenuItem sendItem; private ActionBarMenuItem pipItem; private ActionBarMenuItem masksItem; @@ -227,7 +218,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private ImageView pickerViewSendButton; private PickerBottomLayoutViewer editorDoneLayout; private TextView resetButton; - private PhotoProgressView photoProgressViews[] = new PhotoProgressView[3]; + private PhotoProgressView[] photoProgressViews = new PhotoProgressView[3]; private RadialProgressView miniProgressView; private ImageView paintItem; private ImageView cropItem; @@ -259,6 +250,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private boolean needCaptionLayout; private AnimatedFileDrawable currentAnimation; private boolean allowShare; + private boolean openedFullScreenVideo; private boolean pipAvailable; @@ -319,6 +311,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private boolean isStreaming; private boolean firstAnimationDelay; private long lastBufferedPositionCheck; + private View playButtonAccessibilityOverlay; public final static int SELECT_TYPE_AVATAR = 1; public final static int SELECT_TYPE_WALLPAPER = 3; @@ -523,7 +516,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } }; - private float animationValues[][] = new float[2][10]; + private float[][] animationValues = new float[2][10]; private ChatActivity parentChatActivity; private MentionsAdapter mentionsAdapter; @@ -551,9 +544,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private MessageObject currentMessageObject; private Uri currentPlayingVideoFile; private TLRPC.BotInlineResult currentBotInlineResult; - private TLRPC.FileLocation currentFileLocation; + private ImageLocation currentFileLocation; private SecureDocument currentSecureDocument; - private String currentFileNames[] = new String[3]; + private String[] currentFileNames = new String[3]; private PlaceProviderObject currentPlaceObject; private String currentPathObject; private boolean currentVideoFinishedLoading; @@ -571,7 +564,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private boolean isFirstLoading; private boolean needSearchImageInArr; private boolean loadingMoreImages; - private boolean endReached[] = new boolean[] {false, true}; + private boolean[] endReached = new boolean[]{false, true}; private boolean opennedFromMedia; private boolean attachedToWindow; @@ -626,12 +619,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private SparseArray[] imagesByIdsTemp = new SparseArray[] {new SparseArray<>(), new SparseArray<>()}; private ArrayList imagesArr = new ArrayList<>(); private SparseArray[] imagesByIds = new SparseArray[] {new SparseArray<>(), new SparseArray<>()}; - private ArrayList imagesArrLocations = new ArrayList<>(); + private ArrayList imagesArrLocations = new ArrayList<>(); private ArrayList secureDocuments = new ArrayList<>(); private ArrayList avatarsArr = new ArrayList<>(); private ArrayList imagesArrLocationsSizes = new ArrayList<>(); private ArrayList imagesArrLocals = new ArrayList<>(); - private TLRPC.FileLocation currentUserAvatarLocation = null; + private ImageLocation currentUserAvatarLocation = null; private final static int gallery_menu_save = 1; private final static int gallery_menu_showall = 2; @@ -1326,6 +1319,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return localInstance; } + public boolean isOpenedFullScreenVideo() { + return openedFullScreenVideo; + } + public static boolean hasInstance() { return Instance != null; } @@ -1427,15 +1424,22 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (setToImage == -1 && currentFileLocation != null) { for (int b = 0; b < photo.sizes.size(); b++) { TLRPC.PhotoSize size = photo.sizes.get(b); - if (size.location.local_id == currentFileLocation.local_id && size.location.volume_id == currentFileLocation.volume_id) { + if (size.location.local_id == currentFileLocation.location.local_id && size.location.volume_id == currentFileLocation.location.volume_id) { setToImage = imagesArrLocations.size(); break; } } } - imagesArrLocations.add(sizeFull.location); - imagesArrLocationsSizes.add(sizeFull.size); - avatarsArr.add(photo); + if (photo.dc_id != 0) { + sizeFull.location.dc_id = photo.dc_id; + sizeFull.location.file_reference = photo.file_reference; + } + ImageLocation location = ImageLocation.getForPhoto(sizeFull, photo); + if (location != null) { + imagesArrLocations.add(location); + imagesArrLocationsSizes.add(sizeFull.size); + avatarsArr.add(photo); + } } } if (!avatarsArr.isEmpty()) { @@ -1448,10 +1452,27 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (setToImage != -1) { setImageIndex(setToImage, true); } else { - avatarsArr.add(0, new TLRPC.TL_photoEmpty()); - imagesArrLocations.add(0, currentFileLocation); - imagesArrLocationsSizes.add(0, 0); - setImageIndex(0, true); + TLRPC.User user = null; + TLRPC.Chat chat = null; + if (avatarsDialogId > 0) { + user = MessagesController.getInstance(currentAccount).getUser(avatarsDialogId); + } else { + chat = MessagesController.getInstance(currentAccount).getChat(-avatarsDialogId); + } + if (user != null || chat != null) { + ImageLocation location; + if (user != null) { + location = ImageLocation.getForUser(user, true); + } else { + location = ImageLocation.getForChat(chat, true); + } + if (location != null) { + imagesArrLocations.add(0, location); + avatarsArr.add(0, new TLRPC.TL_photoEmpty()); + imagesArrLocationsSizes.add(0, 0); + setImageIndex(0, true); + } + } } if (fromCache) { MessagesController.getInstance(currentAccount).loadDialogPhotos(avatarsDialogId, 80, 0, false, classGuid); @@ -1609,7 +1630,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat progressView.setVisibility(View.INVISIBLE); preparePlayer(currentPlayingVideoFile, false, false); } else if (tryStartRequestPreviewOnFinish) { - releasePlayer(); + releasePlayer(false); tryStartRequestPreviewOnFinish = !MediaController.getInstance().scheduleVideoConvert(videoPreviewMessageObject, true); } else if (messageObject == videoPreviewMessageObject) { requestingPreview = false; @@ -1666,7 +1687,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat f = FileLoader.getPathToMessage(currentMessageObject.messageOwner); } } else if (currentFileLocation != null) { - f = FileLoader.getPathToAttach(currentFileLocation, avatarsDialogId != 0 || isEvent); + f = FileLoader.getPathToAttach(currentFileLocation.location, avatarsDialogId != 0 || isEvent); } if (f.exists()) { @@ -1912,6 +1933,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat windowLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT; windowLayoutParams.gravity = Gravity.TOP | Gravity.LEFT; windowLayoutParams.type = WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; + if (Build.VERSION.SDK_INT >= 28) { + windowLayoutParams.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + } if (Build.VERSION.SDK_INT >= 21) { windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | @@ -1962,7 +1986,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat f = FileLoader.getPathToMessage(currentMessageObject.messageOwner); } } else if (currentFileLocation != null) { - f = FileLoader.getPathToAttach(currentFileLocation, avatarsDialogId != 0 || isEvent); + f = FileLoader.getPathToAttach(currentFileLocation.location, avatarsDialogId != 0 || isEvent); } if (f != null && f.exists()) { @@ -2078,7 +2102,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - final boolean deleteForAll[] = new boolean[1]; + final boolean[] deleteForAll = new boolean[1]; if (currentMessageObject != null) { int lower_id = (int) currentMessageObject.getDialogId(); if (lower_id != 0) { @@ -2094,8 +2118,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (currentUser != null || !ChatObject.isChannel(currentChat)) { boolean hasOutgoing = false; int currentDate = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); + + int revokeTimeLimit; + if (currentUser != null) { + revokeTimeLimit = MessagesController.getInstance(currentAccount).revokeTimePmLimit; + } else { + revokeTimeLimit = MessagesController.getInstance(currentAccount).revokeTimeLimit; + } + if (currentUser != null && currentUser.id != UserConfig.getInstance(currentAccount).getClientUserId() || currentChat != null) { - if ((currentMessageObject.messageOwner.action == null || currentMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) && currentMessageObject.isOut() && (currentDate - currentMessageObject.messageOwner.date) <= 2 * 24 * 60 * 60) { + if ((currentMessageObject.messageOwner.action == null || currentMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) && currentMessageObject.isOut() && (currentDate - currentMessageObject.messageOwner.date) <= revokeTimeLimit) { FrameLayout frameLayout = new FrameLayout(parentActivity); CheckBoxCell cell = new CheckBoxCell(parentActivity, 1); cell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); @@ -2147,7 +2179,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return; } TLRPC.Photo photo = avatarsArr.get(currentIndex); - TLRPC.FileLocation currentLocation = imagesArrLocations.get(currentIndex); + ImageLocation currentLocation = imagesArrLocations.get(currentIndex); if (photo instanceof TLRPC.TL_photoEmpty) { photo = null; } @@ -2155,12 +2187,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (currentUserAvatarLocation != null) { if (photo != null) { for (TLRPC.PhotoSize size : photo.sizes) { - if (size.location.local_id == currentUserAvatarLocation.local_id && size.location.volume_id == currentUserAvatarLocation.volume_id) { + if (size.location.local_id == currentUserAvatarLocation.location.local_id && size.location.volume_id == currentUserAvatarLocation.location.volume_id) { current = true; break; } } - } else if (currentLocation.local_id == currentUserAvatarLocation.local_id && currentLocation.volume_id == currentUserAvatarLocation.volume_id) { + } else if (currentLocation.location.local_id == currentUserAvatarLocation.location.local_id && currentLocation.location.volume_id == currentUserAvatarLocation.location.volume_id) { current = true; } } @@ -2236,7 +2268,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return; } FileLoader.getInstance(currentAccount).cancelLoadFile(currentMessageObject.getDocument()); - releasePlayer(); + releasePlayer(false); bottomLayout.setTag(1); bottomLayout.setVisibility(View.VISIBLE); } @@ -2248,7 +2280,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat File f = FileLoader.getPathToMessage(currentMessageObject.messageOwner); return f.exists(); } else if (currentFileLocation != null) { - File f = FileLoader.getPathToAttach(currentFileLocation, avatarsDialogId != 0 || isEvent); + File f = FileLoader.getPathToAttach(getFileLocation(currentFileLocation), avatarsDialogId != 0 || isEvent); return f.exists(); } return false; @@ -2257,20 +2289,22 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ActionBarMenu menu = actionBar.createMenu(); - masksItem = menu.addItem(gallery_menu_masks, R.drawable.ic_masks_msk1); + masksItem = menu.addItem(gallery_menu_masks, R.drawable.msg_mask); pipItem = menu.addItem(gallery_menu_pip, R.drawable.ic_goinline); - sendItem = menu.addItem(gallery_menu_send, R.drawable.msg_panel_reply); + sendItem = menu.addItem(gallery_menu_send, R.drawable.msg_forward); menuItem = menu.addItem(0, R.drawable.ic_ab_other); - menuItem.addSubItem(gallery_menu_openin, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)).setTextColor(0xfffafafa); - allMediaItem = menuItem.addSubItem(gallery_menu_showall, LocaleController.getString("ShowAllMedia", R.string.ShowAllMedia)); - allMediaItem.setTextColor(0xfffafafa); - menuItem.addSubItem(gallery_menu_showinchat, LocaleController.getString("ShowInChat", R.string.ShowInChat)).setTextColor(0xfffafafa); - menuItem.addSubItem(gallery_menu_share, LocaleController.getString("ShareFile", R.string.ShareFile)).setTextColor(0xfffafafa); - menuItem.addSubItem(gallery_menu_save, LocaleController.getString("SaveToGallery", R.string.SaveToGallery)).setTextColor(0xfffafafa); - menuItem.addSubItem(gallery_menu_delete, LocaleController.getString("Delete", R.string.Delete)).setTextColor(0xfffafafa); - menuItem.addSubItem(gallery_menu_cancel_loading, LocaleController.getString("StopDownload", R.string.StopDownload)).setTextColor(0xfffafafa); + menuItem.addSubItem(gallery_menu_openin, R.drawable.msg_openin, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)).setColors(0xfffafafa, 0xfffafafa); + menuItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); + allMediaItem = menuItem.addSubItem(gallery_menu_showall, R.drawable.msg_media, LocaleController.getString("ShowAllMedia", R.string.ShowAllMedia)); + allMediaItem.setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_showinchat, R.drawable.msg_message, LocaleController.getString("ShowInChat", R.string.ShowInChat)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_share, R.drawable.msg_shareout, LocaleController.getString("ShareFile", R.string.ShareFile)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_save, R.drawable.msg_gallery, LocaleController.getString("SaveToGallery", R.string.SaveToGallery)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_delete, R.drawable.msg_delete, LocaleController.getString("Delete", R.string.Delete)).setColors(0xfffafafa, 0xfffafafa); + menuItem.addSubItem(gallery_menu_cancel_loading, R.drawable.msg_cancel, LocaleController.getString("StopDownload", R.string.StopDownload)).setColors(0xfffafafa, 0xfffafafa); menuItem.redrawPopup(0xf9222222); + sendItem.setContentDescription(LocaleController.getString("Forward", R.string.Forward)); bottomLayout = new FrameLayout(actvityContext); bottomLayout.setBackgroundColor(0x7f000000); @@ -2300,7 +2334,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } @Override - public ArrayList getImagesArrLocations() { + public ArrayList getImagesArrLocations() { return imagesArrLocations; } @@ -2369,6 +2403,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat shareButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); bottomLayout.addView(shareButton, LayoutHelper.createFrame(50, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.RIGHT)); shareButton.setOnClickListener(v -> onSharePressed()); + shareButton.setContentDescription(LocaleController.getString("ShareFile", R.string.ShareFile)); nameTextView = new TextView(containerView.getContext()); nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); @@ -2513,6 +2548,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat pickerViewSendButton.setPadding(AndroidUtilities.dp(4), 0, 0, 0); pickerViewSendButton.setImageResource(R.drawable.ic_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 -> { if (captionEditText.getTag() != null) { return; @@ -2543,6 +2579,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } switchToEditMode(1); }); + cropItem.setContentDescription(LocaleController.getString("CropImage", R.string.CropImage)); rotateItem = new ImageView(parentActivity); rotateItem.setScaleType(ImageView.ScaleType.CENTER); @@ -2555,6 +2592,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } photoCropView.rotate(); }); + rotateItem.setContentDescription(LocaleController.getString("AccDescrRotate", R.string.AccDescrRotate)); paintItem = new ImageView(parentActivity); paintItem.setScaleType(ImageView.ScaleType.CENTER); @@ -2567,6 +2605,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } switchToEditMode(3); }); + paintItem.setContentDescription(LocaleController.getString("AccDescrPhotoEditor", R.string.AccDescrPhotoEditor)); compressItem = new ImageView(parentActivity); compressItem.setTag(1); @@ -2593,6 +2632,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat showQualityView(true); requestVideoPreview(1); }); + String[] compressionStrings = {"240", "360", "480", "720", "1080"}; + compressItem.setContentDescription(LocaleController.getString("AccDescrVideoQuality", R.string.AccDescrVideoQuality) + ", " + compressionStrings[Math.max(0, selectedCompression)]); muteItem = new ImageView(parentActivity); muteItem.setScaleType(ImageView.ScaleType.CENTER); @@ -2603,6 +2644,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return; } muteVideo = !muteVideo; + updateMuteButton(); + updateVideoInfo(); if (muteVideo && !checkImageView.isChecked()) { checkImageView.callOnClick(); } else { @@ -2611,13 +2654,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ((MediaController.PhotoEntry) object).editedInfo = getCurrentVideoEditedInfo(); } } - updateMuteButton(); }); cameraItem = new ImageView(parentActivity); cameraItem.setScaleType(ImageView.ScaleType.CENTER); cameraItem.setImageResource(R.drawable.photo_add); cameraItem.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); + cameraItem.setContentDescription(LocaleController.getString("AccDescrTakeMorePics", R.string.AccDescrTakeMorePics)); containerView.addView(cameraItem, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 16, 0)); cameraItem.setOnClickListener(v -> { if (placeProvider == null || captionEditText.getTag() != null) { @@ -2638,11 +2681,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } switchToEditMode(2); }); + tuneItem.setContentDescription(LocaleController.getString("AccDescrPhotoAdjust", R.string.AccDescrPhotoAdjust)); timeItem = new ImageView(parentActivity); timeItem.setScaleType(ImageView.ScaleType.CENTER); timeItem.setImageResource(R.drawable.photo_timer); timeItem.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); + timeItem.setContentDescription(LocaleController.getString("SetTimer", R.string.SetTimer)); itemsLayout.addView(timeItem, LayoutHelper.createLinear(70, 48)); timeItem.setOnClickListener(v -> { if (parentActivity == null || captionEditText.getTag() != null) { @@ -2747,7 +2792,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat textView.setGravity(Gravity.CENTER); textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); textView.setText(LocaleController.getString("Done", R.string.Done).toUpperCase()); - textView.setBackgroundDrawable(Theme.getRoundRectSelectorDrawable()); + textView.setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(0xff49bcf2)); textView.setPadding(AndroidUtilities.dp(10), 0, AndroidUtilities.dp(10), 0); buttonsLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 36, Gravity.TOP | Gravity.RIGHT)); textView.setOnClickListener(v1 -> { @@ -2783,7 +2828,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat textView.setGravity(Gravity.CENTER); textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); textView.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase()); - textView.setBackgroundDrawable(Theme.getRoundRectSelectorDrawable()); + textView.setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(0xff49bcf2)); textView.setPadding(AndroidUtilities.dp(10), 0, AndroidUtilities.dp(10), 0); buttonsLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 36, Gravity.TOP | Gravity.RIGHT)); textView.setOnClickListener(v14 -> bottomSheet.dismiss()); @@ -2924,6 +2969,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat placeProvider.toggleGroupPhotosEnabled(); ImageView imageView = (ImageView) view; imageView.setColorFilter(!enabled ? new PorterDuffColorFilter(0xff66bffa, PorterDuff.Mode.MULTIPLY) : null); + imageView.setContentDescription(SharedConfig.groupPhotosEnabled ? LocaleController.getString("GroupPhotosHelp", R.string.GroupPhotosHelp) : LocaleController.getString("SinglePhotosHelp", R.string.SinglePhotosHelp)); showHint(false, !enabled); } else { ignoreDidSetImage = true; @@ -2991,6 +3037,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } }); + if (Build.VERSION.SDK_INT >= 19) + captionEditText.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); containerView.addView(captionEditText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT)); mentionListView = new RecyclerListView(actvityContext) { @@ -3123,8 +3171,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } else if (object instanceof String) { captionEditText.replaceWithText(start, len, object + " ", false); - } else if (object instanceof EmojiSuggestion) { - String code = ((EmojiSuggestion) object).emoji; + } else if (object instanceof DataQuery.KeywordResult) { + String code = ((DataQuery.KeywordResult) object).emoji; captionEditText.addEmojiToRecent(code); captionEditText.replaceWithText(start, len, code, true); } @@ -3143,6 +3191,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } return false; }); + + AccessibilityManager am=(AccessibilityManager)actvityContext.getSystemService(Context.ACCESSIBILITY_SERVICE); + if(am.isEnabled()){ + playButtonAccessibilityOverlay=new View(actvityContext); + playButtonAccessibilityOverlay.setContentDescription(LocaleController.getString("AccActionPlay", R.string.AccActionPlay)); + playButtonAccessibilityOverlay.setFocusable(true); + containerView.addView(playButtonAccessibilityOverlay, LayoutHelper.createFrame(64, 64, Gravity.CENTER)); + } } private boolean checkInlinePermissions() { @@ -3225,6 +3281,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (PipInstance != null) { PipInstance.destroyPhotoViewer(); } + openedFullScreenVideo = false; PipInstance = Instance; Instance = null; switchingInlineMode = true; @@ -3440,6 +3497,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat videoPlayButton = new ImageView(containerView.getContext()); videoPlayButton.setScaleType(ImageView.ScaleType.CENTER); videoPlayerControlFrameLayout.addView(videoPlayButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP, 4, 0, 0, 0)); + videoPlayButton.setFocusable(true); + videoPlayButton.setContentDescription(LocaleController.getString("AccActionPlay", R.string.AccActionPlay)); videoPlayButton.setOnClickListener(v -> { if (videoPlayer == null) { return; @@ -3480,6 +3539,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat isPhotosListViewVisible = false; captionEditText.setTag(1); captionEditText.openKeyboard(); + captionEditText.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); lastTitle = actionBar.getTitle(); if (isCurrentVideo) { actionBar.setTitle(muteVideo ? LocaleController.getString("GifCaption", R.string.GifCaption) : LocaleController.getString("VideoCaption", R.string.VideoCaption)); @@ -3561,6 +3621,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat captionEditText.hidePopup(); } captionEditText.closeKeyboard(); + if (Build.VERSION.SDK_INT >= 19) + captionEditText.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); } private void updateVideoPlayerTime() { @@ -3749,7 +3811,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat lastBufferedPositionCheck = 0; firstAnimationDelay = true; inPreview = preview; - releasePlayer(); + releasePlayer(false); if (videoTextureView == null) { aspectRatioFrameLayout = new AspectRatioFrameLayout(parentActivity) { @Override @@ -3946,13 +4008,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat menuItem.showSubItem(gallery_menu_share); } inPreview = preview; + + updateAccessibilityOverlayVisibility(); } - private void releasePlayer() { + private void releasePlayer(boolean onClose) { if (videoPlayer != null) { AndroidUtilities.cancelRunOnUIThread(setLoadingRunnable); videoPlayer.releasePlayer(true); videoPlayer = null; + updateAccessibilityOverlayVisibility(); } toggleMiniProgress(false, false); pipAvailable = false; @@ -3982,10 +4047,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } if (isPlaying) { isPlaying = false; - videoPlayButton.setImageResource(R.drawable.inline_video_play); + if (!onClose) { + videoPlayButton.setImageResource(R.drawable.inline_video_play); + } AndroidUtilities.cancelRunOnUIThread(updateProgressRunnable); } - if (!inPreview && !requestingPreview) { + if (!onClose && !inPreview && !requestingPreview) { videoPlayerControlFrameLayout.setVisibility(View.GONE); dateTextView.setVisibility(View.VISIBLE); nameTextView.setVisibility(View.VISIBLE); @@ -4860,8 +4927,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (index >= imagesArrLocations.size()) { return null; } - TLRPC.FileLocation location = imagesArrLocations.get(index); - return location.volume_id + "_" + location.local_id + ".jpg"; + ImageLocation location = imagesArrLocations.get(index); + if (location == null) { + return null; + } + return location.location.volume_id + "_" + location.location.local_id + ".jpg"; } else if (!imagesArr.isEmpty()) { if (index >= imagesArr.size()) { return null; @@ -4891,7 +4961,84 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return null; } - private TLObject getFileLocation(int index, int size[]) { + private ImageLocation getImageLocation(int index, int[] size) { + if (index < 0) { + return null; + } + if (!secureDocuments.isEmpty()) { + if (index >= secureDocuments.size()) { + return null; + } + if (size != null) { + size[0] = secureDocuments.get(index).secureFile.size; + } + return ImageLocation.getForSecureDocument(secureDocuments.get(index)); + } else if (!imagesArrLocations.isEmpty()) { + if (index >= imagesArrLocations.size()) { + return null; + } + if (size != null) { + size[0] = imagesArrLocationsSizes.get(index); + } + return imagesArrLocations.get(index); + } else if (!imagesArr.isEmpty()) { + if (index >= imagesArr.size()) { + return null; + } + MessageObject message = imagesArr.get(index); + if (message.messageOwner instanceof TLRPC.TL_messageService) { + if (message.messageOwner.action instanceof TLRPC.TL_messageActionUserUpdatedPhoto) { + return null; + } else { + TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(message.photoThumbs, AndroidUtilities.getPhotoSize()); + if (sizeFull != null) { + if (size != null) { + size[0] = sizeFull.size; + if (size[0] == 0) { + size[0] = -1; + } + } + return ImageLocation.getForObject(sizeFull, message.photoThumbsObject); + } else if (size != null) { + size[0] = -1; + } + } + } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && message.messageOwner.media.photo != null || message.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && message.messageOwner.media.webpage != null) { + if (message.isGif()) { + return ImageLocation.getForDocument(message.getDocument()); + } else { + TLRPC.FileLocation location; + TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(message.photoThumbs, AndroidUtilities.getPhotoSize()); + if (sizeFull != null) { + if (size != null) { + size[0] = sizeFull.size; + if (size[0] == 0) { + size[0] = -1; + } + } + return ImageLocation.getForObject(sizeFull, message.photoThumbsObject); + } else if (size != null) { + size[0] = -1; + } + } + } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaInvoice) { + return ImageLocation.getForWebFile(WebFile.createWithWebDocument(((TLRPC.TL_messageMediaInvoice) message.messageOwner.media).photo)); + } else if (message.getDocument() != null && MessageObject.isDocumentHasThumb(message.getDocument())) { + TLRPC.Document document = message.getDocument(); + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); + if (size != null) { + size[0] = thumb.size; + if (size[0] == 0) { + size[0] = -1; + } + } + return ImageLocation.getForDocument(thumb, document); + } + } + return null; + } + + private TLObject getFileLocation(int index, int[] size) { if (index < 0) { return null; } @@ -4910,7 +5057,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (size != null) { size[0] = imagesArrLocationsSizes.get(index); } - return imagesArrLocations.get(index); + return imagesArrLocations.get(index).location; } else if (!imagesArr.isEmpty()) { if (index >= imagesArr.size()) { return null; @@ -5148,7 +5295,20 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat setImageIndex(index, true); } else if (fileLocation != null) { avatarsDialogId = object.dialogId; - imagesArrLocations.add(fileLocation); + ImageLocation imageLocation; + if (avatarsDialogId > 0) { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(avatarsDialogId); + imageLocation = ImageLocation.getForUser(user, true); + } else { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-avatarsDialogId); + imageLocation = ImageLocation.getForChat(chat, true); + } + if (imageLocation == null) { + closePhoto(false, false); + return; + } + imagesArrLocations.add(imageLocation); + currentUserAvatarLocation = imageLocation; imagesArrLocationsSizes.add(object.size); avatarsArr.add(new TLRPC.TL_photoEmpty()); shareButton.setVisibility(videoPlayerControlFrameLayout.getVisibility() != View.VISIBLE ? View.VISIBLE : View.GONE); @@ -5160,7 +5320,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat menuItem.showSubItem(gallery_menu_share); } setImageIndex(0, true); - currentUserAvatarLocation = fileLocation; } else if (messages != null) { opennedFromMedia = true; menuItem.showSubItem(gallery_menu_showinchat); @@ -5515,6 +5674,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat muteItem.setVisibility(View.VISIBLE); compressItem.setVisibility(View.VISIBLE); isCurrentVideo = true; + updateAccessibilityOverlayVisibility(); boolean isMuted = false; if (object instanceof MediaController.PhotoEntry) { MediaController.PhotoEntry photoEntry = ((MediaController.PhotoEntry) object); @@ -5530,6 +5690,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat videoTimelineView.setVisibility(View.GONE); muteItem.setVisibility(View.GONE); isCurrentVideo = false; + updateAccessibilityOverlayVisibility(); compressItem.setVisibility(View.GONE); if (isAnimation) { paintItem.setVisibility(View.GONE); @@ -5604,6 +5765,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat setCurrentCaption(newMessageObject, caption, !init); } + private TLRPC.FileLocation getFileLocation(ImageLocation location) { + if (location == null) { + return null; + } + return location.location; + } + private void setImageIndex(int index, boolean init) { if (currentIndex == index || placeProvider == null) { return; @@ -5617,7 +5785,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat currentFileNames[0] = getFileName(index); currentFileNames[1] = getFileName(index + 1); currentFileNames[2] = getFileName(index - 1); - placeProvider.willSwitchFromPhoto(currentMessageObject, currentFileLocation, currentIndex); + placeProvider.willSwitchFromPhoto(currentMessageObject, getFileLocation(currentFileLocation), currentIndex); int prevIndex = currentIndex; currentIndex = index; @@ -5656,9 +5824,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat closePhoto(false, false); return; } - TLRPC.FileLocation old = currentFileLocation; - TLRPC.FileLocation newLocation = imagesArrLocations.get(index); - if (init && old != null && newLocation != null && old.local_id == newLocation.local_id && old.volume_id == newLocation.volume_id) { + ImageLocation old = currentFileLocation; + ImageLocation newLocation = imagesArrLocations.get(index); + if (init && old != null && newLocation != null && old.location.local_id == newLocation.location.local_id && old.location.volume_id == newLocation.location.volume_id) { sameImage = true; } currentFileLocation = imagesArrLocations.get(index); @@ -5700,7 +5868,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat showAfterAnimation = currentPlaceObject; } } - currentPlaceObject = placeProvider.getPlaceForPhoto(currentMessageObject, currentFileLocation, currentIndex, false); + currentPlaceObject = placeProvider.getPlaceForPhoto(currentMessageObject, getFileLocation(currentFileLocation), currentIndex, false); if (currentPlaceObject != null) { if (animationInProgress == 0) { currentPlaceObject.imageReceiver.setVisible(false, true); @@ -5743,7 +5911,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat canZoom = !imagesArrLocals.isEmpty() || (currentFileNames[0] != null && /*!isVideo && */photoProgressViews[0].backgroundState != 0); } updateMinMax(scale); - releasePlayer(); + releasePlayer(false); } if (isVideo && videoPath != null) { isStreaming = false; @@ -5971,8 +6139,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat photoProgressViews[a].setBackgroundState(-1, animated); return; } - TLRPC.FileLocation location = imagesArrLocations.get(index); - f = FileLoader.getPathToAttach(location, avatarsDialogId != 0 || isEvent); + ImageLocation location = imagesArrLocations.get(index); + f = FileLoader.getPathToAttach(location.location, avatarsDialogId != 0 || isEvent); } else if (currentSecureDocument != null) { if (index < 0 || index >= secureDocuments.size()) { photoProgressViews[a].setBackgroundState(-1, animated); @@ -5986,7 +6154,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat f = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), currentFileNames[a]); } } - boolean exists = f.exists(); + boolean exists = f != null && f.exists(); if (f != null && (exists || canStream)) { if (isVideo) { photoProgressViews[a].setBackgroundState(3, animated); @@ -6059,7 +6227,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } SecureDocument document = secureDocuments.get(index); int imageSize = document.secureFile.size; - imageReceiver.setImage(document, "d", placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, null, null, imageSize, null, null, 0); + imageReceiver.setImage(ImageLocation.getForSecureDocument(document), "d", null, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, imageSize, null, null, 0); } } else if (!imagesArrLocals.isEmpty()) { if (index >= 0 && index < imagesArrLocals.size()) { @@ -6076,6 +6244,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat TLRPC.Document document = null; WebFile webDocument = null; TLRPC.PhotoSize photo = null; + TLObject photoObject = null; int imageSize = 0; String filter = null; boolean isVideo = false; @@ -6104,6 +6273,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (botInlineResult.type.equals("video") || MessageObject.isVideoDocument(botInlineResult.document)) { if (botInlineResult.document != null) { photo = FileLoader.getClosestPhotoSizeWithSize(botInlineResult.document.thumbs, 90); + photoObject = botInlineResult.document; } else if (botInlineResult.thumb instanceof TLRPC.TL_webDocument) { webDocument = WebFile.createWithWebDocument(botInlineResult.thumb); } @@ -6114,6 +6284,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else if (botInlineResult.photo != null) { TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(botInlineResult.photo.sizes, AndroidUtilities.getPhotoSize()); photo = sizeFull; + photoObject = botInlineResult.photo; imageSize = sizeFull.size; filter = String.format(Locale.US, "%d_%d", size, size); } else if (botInlineResult.content instanceof TLRPC.TL_webDocument) { @@ -6129,6 +6300,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat MediaController.SearchImage photoEntry = (MediaController.SearchImage) object; if (photoEntry.photoSize != null) { photo = photoEntry.photoSize; + photoObject = photoEntry.photo; imageSize = photoEntry.photoSize.size; } else if (photoEntry.imagePath != null) { path = photoEntry.imagePath; @@ -6143,11 +6315,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } if (document != null) { TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); - imageReceiver.setImage(document, "d", placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, placeHolder == null ? thumb : null, String.format(Locale.US, "%d_%d", size, size), imageSize, null, object, cacheType); + imageReceiver.setImage(ImageLocation.getForDocument(document), "d", placeHolder == null ? ImageLocation.getForDocument(thumb, document) : null, String.format(Locale.US, "%d_%d", size, size), placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, imageSize, null, object, cacheType); } else if (photo != null) { - imageReceiver.setImage(photo, filter, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, null, String.format(Locale.US, "%d_%d", size, size), imageSize, null, object, cacheType); + imageReceiver.setImage(ImageLocation.getForObject(photo, photoObject), filter, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, imageSize, null, object, cacheType); } else if (webDocument != null) { - imageReceiver.setImage(webDocument, filter, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : (isVideo && parentActivity != null ? parentActivity.getResources().getDrawable(R.drawable.nophotos) : null), null, object, cacheType); + imageReceiver.setImage(ImageLocation.getForWebFile(webDocument), filter, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : (isVideo && parentActivity != null ? parentActivity.getResources().getDrawable(R.drawable.nophotos) : null), null, object, cacheType); } else { imageReceiver.setImage(path, filter, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : (isVideo && parentActivity != null ? parentActivity.getResources().getDrawable(R.drawable.nophotos) : null), null, imageSize); } @@ -6172,7 +6344,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat placeHolder = currentThumb; } TLRPC.PhotoSize thumbLocation = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 100); - imageReceiver.setImage(null, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, placeHolder == null ? thumbLocation : null, "b", 0, null, messageObject, 1); + imageReceiver.setImage(null, null, placeHolder == null ? ImageLocation.getForObject(thumbLocation, messageObject.photoThumbsObject) : null, "b", placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, 0, null, messageObject, 1); } else { imageReceiver.setImageBitmap(parentActivity.getResources().getDrawable(R.drawable.photoview_placeholder)); } @@ -6190,7 +6362,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat placeHolder = currentThumb; } TLRPC.PhotoSize thumbLocation = messageObject != null ? FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 100) : null; - imageReceiver.setImage(document, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, placeHolder == null ? thumbLocation : null, "b", document.size, null, messageObject, 0); + int size = (int) (4096 / AndroidUtilities.density); + imageReceiver.setImage(ImageLocation.getForDocument(document), String.format(Locale.US, "%d_%d", size, size), placeHolder == null ? ImageLocation.getForDocument(thumbLocation, document) : null, "b", placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, document.size, null, messageObject, 0); } else { OtherDocumentPlaceholderDrawable drawable = new OtherDocumentPlaceholderDrawable(parentActivity, containerView, messageObject); imageReceiver.setImageBitmap(drawable); @@ -6198,10 +6371,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return; } } - int size[] = new int[1]; + int[] size = new int[1]; + ImageLocation imageLocation = getImageLocation(index, size); TLObject fileLocation = getFileLocation(index, size); - if (fileLocation != null) { + if (imageLocation != null) { imageReceiver.setNeedsQualityThumb(true); ImageReceiver.BitmapHolder placeHolder = null; if (currentThumb != null && imageReceiver == centerImage) { @@ -6210,12 +6384,32 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (size[0] == 0) { size[0] = -1; } - TLRPC.PhotoSize thumbLocation = messageObject != null ? FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 100) : null; + TLRPC.PhotoSize thumbLocation; + TLObject photoObject; + if (messageObject != null) { + thumbLocation = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 100); + photoObject = messageObject.photoThumbsObject; + } else { + thumbLocation = null; + photoObject = null; + } if (thumbLocation != null && thumbLocation == fileLocation) { thumbLocation = null; } boolean cacheOnly = messageObject != null && messageObject.isWebpage() || avatarsDialogId != 0 || isEvent; - imageReceiver.setImage(fileLocation, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, placeHolder == null ? thumbLocation : null, "b", size[0], null, messageObject, cacheOnly ? 1 : 0); + Object parentObject; + if (messageObject != null) { + parentObject = messageObject; + } else if (avatarsDialogId != 0) { + if (avatarsDialogId > 0) { + parentObject = MessagesController.getInstance(currentAccount).getUser(avatarsDialogId); + } else { + parentObject = MessagesController.getInstance(currentAccount).getChat(-avatarsDialogId); + } + } else { + parentObject = null; + } + imageReceiver.setImage(imageLocation, null, placeHolder == null ? ImageLocation.getForObject(thumbLocation, photoObject) : null, "b", placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, size[0], null, parentObject, cacheOnly ? 1 : 0); } else { imageReceiver.setNeedsQualityThumb(true); if (size[0] == 0) { @@ -6249,7 +6443,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat public static boolean isShowingImage(TLRPC.FileLocation object) { boolean result = false; if (Instance != null) { - result = Instance.isVisible && !Instance.disableShowCheck && object != null && Instance.currentFileLocation != null && object.local_id == Instance.currentFileLocation.local_id && object.volume_id == Instance.currentFileLocation.volume_id && object.dc_id == Instance.currentFileLocation.dc_id; + result = Instance.isVisible && !Instance.disableShowCheck && object != null && Instance.currentFileLocation != null && object.local_id == Instance.currentFileLocation.location.local_id && object.volume_id == Instance.currentFileLocation.location.volume_id && object.dc_id == Instance.currentFileLocation.dc_id; } return result; } @@ -6279,19 +6473,23 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } public boolean openPhoto(final MessageObject messageObject, long dialogId, long mergeDialogId, final PhotoViewerProvider provider) { - return openPhoto(messageObject, null, null, null, null, 0, provider, null, dialogId, mergeDialogId); + return openPhoto(messageObject, null, null, null, null, 0, provider, null, dialogId, mergeDialogId, true); + } + + public boolean openPhoto(final MessageObject messageObject, long dialogId, long mergeDialogId, final PhotoViewerProvider provider, boolean fullScreenVideo) { + return openPhoto(messageObject, null, null, null, null, 0, provider, null, dialogId, mergeDialogId, fullScreenVideo); } public boolean openPhoto(final TLRPC.FileLocation fileLocation, final PhotoViewerProvider provider) { - return openPhoto(null, fileLocation, null, null, null, 0, provider, null, 0, 0); + return openPhoto(null, fileLocation, null, null, null, 0, provider, null, 0, 0, true); } public boolean openPhoto(final ArrayList messages, final int index, long dialogId, long mergeDialogId, final PhotoViewerProvider provider) { - return openPhoto(messages.get(index), null, messages, null, null, index, provider, null, dialogId, mergeDialogId); + return openPhoto(messages.get(index), null, messages, null, null, index, provider, null, dialogId, mergeDialogId, true); } public boolean openPhoto(final ArrayList documents, final int index, final PhotoViewerProvider provider) { - return openPhoto(null, null, null, documents, null, index, provider, null, 0, 0); + return openPhoto(null, null, null, documents, null, index, provider, null, 0, 0, true); } public boolean openPhotoForSelect(final ArrayList photos, final int index, int type, final PhotoViewerProvider provider, ChatActivity chatActivity) { @@ -6313,7 +6511,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } pickerViewSendButton.setLayoutParams(layoutParams2); } - return openPhoto(null, null, null, null, photos, index, provider, chatActivity, 0, 0); + return openPhoto(null, null, null, null, photos, index, provider, chatActivity, 0, 0, true); } private boolean checkAnimation() { @@ -6398,7 +6596,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat padImageForHorizontalInsets = true; } - public boolean openPhoto(final MessageObject messageObject, final TLRPC.FileLocation fileLocation, final ArrayList messages, final ArrayList documents, final ArrayList photos, final int index, final PhotoViewerProvider provider, ChatActivity chatActivity, long dialogId, long mDialogId) { + public boolean openPhoto(final MessageObject messageObject, final TLRPC.FileLocation fileLocation, final ArrayList messages, final ArrayList documents, final ArrayList photos, final int index, final PhotoViewerProvider provider, ChatActivity chatActivity, long dialogId, long mDialogId, boolean fullScreenVideo) { if (parentActivity == null || isVisible || provider == null && checkAnimation() || messageObject == null && fileLocation == null && messages == null && photos == null && documents == null) { return false; } @@ -6462,11 +6660,17 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat isVisible = true; togglePhotosListView(false, false); - if (sendPhotoType == SELECT_TYPE_AVATAR) { - createCropView(); + + openedFullScreenVideo = !fullScreenVideo; + if (openedFullScreenVideo) { toggleActionBar(false, false); } else { - toggleActionBar(true, false); + if (sendPhotoType == SELECT_TYPE_AVATAR) { + createCropView(); + toggleActionBar(false, false); + } else { + toggleActionBar(true, false); + } } seekToProgressPending2 = 0; @@ -6477,14 +6681,18 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat animationInProgress = 1; if (messageObject != null) { currentAnimation = object.imageReceiver.getAnimation(); - if (currentAnimation != null && messageObject.isVideo()) { - object.imageReceiver.setAllowStartAnimation(false); - object.imageReceiver.stopAnimation(); - if (MediaController.getInstance().isPlayingMessage(messageObject)) { - seekToProgressPending2 = messageObject.audioProgress; + if (currentAnimation != null) { + if (messageObject.isVideo()) { + object.imageReceiver.setAllowStartAnimation(false); + object.imageReceiver.stopAnimation(); + if (MediaController.getInstance().isPlayingMessage(messageObject)) { + seekToProgressPending2 = messageObject.audioProgress; + } + skipFirstBufferingProgress = injectingVideoPlayer == null && !FileLoader.getInstance(messageObject.currentAccount).isLoadingVideo(messageObject.getDocument(), true) && (currentAnimation.hasBitmap() || !FileLoader.getInstance(messageObject.currentAccount).isLoadingVideo(messageObject.getDocument(), false)); + currentAnimation = null; + } else if (messageObject.getWebPagePhotos(null, null).size() > 1) { + currentAnimation = null; } - skipFirstBufferingProgress = injectingVideoPlayer == null && !FileLoader.getInstance(messageObject.currentAccount).isLoadingVideo(messageObject.getDocument(), true) && (currentAnimation.hasBitmap() || !FileLoader.getInstance(messageObject.currentAccount).isLoadingVideo(messageObject.getDocument(), false)); - currentAnimation = null; } } @@ -6499,7 +6707,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat public boolean onPreDraw() { windowView.getViewTreeObserver().removeOnPreDrawListener(this); - final Rect drawRegion = object.imageReceiver.getDrawRegion(); + final RectF drawRegion = object.imageReceiver.getDrawRegion(); int orientation = object.imageReceiver.getOrientation(); int animatedOrientation = object.imageReceiver.getAnimatedOrientation(); if (animatedOrientation != 0) { @@ -6525,8 +6733,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat animatingImageView.setTranslationX(object.viewX + drawRegion.left * object.scale); animatingImageView.setTranslationY(object.viewY + drawRegion.top * object.scale); final ViewGroup.LayoutParams layoutParams = animatingImageView.getLayoutParams(); - layoutParams.width = drawRegion.width(); - layoutParams.height = drawRegion.height(); + layoutParams.width = (int) drawRegion.width(); + layoutParams.height = (int) drawRegion.height(); animatingImageView.setLayoutParams(layoutParams); float scaleX; @@ -6558,16 +6766,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat yPos = ((AndroidUtilities.displaySize.y + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0)) - (layoutParams.height * scale)) / 2.0f; xPos = (windowView.getMeasuredWidth() - layoutParams.width * scale) / 2.0f; } - int clipHorizontal = Math.abs(drawRegion.left - object.imageReceiver.getImageX()); - int clipVertical = Math.abs(drawRegion.top - object.imageReceiver.getImageY()); + int clipHorizontal = (int) Math.abs(drawRegion.left - object.imageReceiver.getImageX()); + int clipVertical = (int) Math.abs(drawRegion.top - object.imageReceiver.getImageY()); - int coords2[] = new int[2]; + int[] coords2 = new int[2]; object.parentView.getLocationInWindow(coords2); - int clipTop = coords2[1] - (Build.VERSION.SDK_INT >= 21 ? 0 : AndroidUtilities.statusBarHeight) - (object.viewY + drawRegion.top) + object.clipTopAddition; + int clipTop = (int) (coords2[1] - (Build.VERSION.SDK_INT >= 21 ? 0 : AndroidUtilities.statusBarHeight) - (object.viewY + drawRegion.top) + object.clipTopAddition); if (clipTop < 0) { clipTop = 0; } - int clipBottom = (object.viewY + drawRegion.top + layoutParams.height) - (coords2[1] + object.parentView.getHeight() - (Build.VERSION.SDK_INT >= 21 ? 0 : AndroidUtilities.statusBarHeight)) + object.clipBottomAddition; + int clipBottom = (int) ((object.viewY + drawRegion.top + layoutParams.height) - (coords2[1] + object.parentView.getHeight() - (Build.VERSION.SDK_INT >= 21 ? 0 : AndroidUtilities.statusBarHeight)) + object.clipBottomAddition); if (clipBottom < 0) { clipBottom = 0; } @@ -6600,16 +6808,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat backgroundDrawable.setAlpha(0); containerView.setAlpha(0); - final AnimatorSet animatorSet = new AnimatorSet(); - ArrayList animators = new ArrayList<>(sendPhotoType == SELECT_TYPE_AVATAR ? 4 : 3); - animators.add(ObjectAnimator.ofFloat(animatingImageView, AnimationProperties.CLIPPING_IMAGE_VIEW_PROGRESS, 0.0f, 1.0f)); - animators.add(ObjectAnimator.ofInt(backgroundDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0, 255)); - animators.add(ObjectAnimator.ofFloat(containerView, View.ALPHA, 0.0f, 1.0f)); - if (sendPhotoType == SELECT_TYPE_AVATAR) { - animators.add(ObjectAnimator.ofFloat(photoCropView, View.ALPHA, 0, 1)); - } - animatorSet.playTogether(animators); - animationEndRunnable = () -> { if (containerView == null || windowView == null) { return; @@ -6648,33 +6846,54 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } }; - animatorSet.setDuration(200); - animatorSet.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - AndroidUtilities.runOnUIThread(() -> { - NotificationCenter.getInstance(currentAccount).setAnimationInProgress(false); - if (animationEndRunnable != null) { - animationEndRunnable.run(); - animationEndRunnable = null; - } - }); + if (!openedFullScreenVideo) { + final AnimatorSet animatorSet = new AnimatorSet(); + ArrayList animators = new ArrayList<>(sendPhotoType == SELECT_TYPE_AVATAR ? 4 : 3); + animators.add(ObjectAnimator.ofFloat(animatingImageView, AnimationProperties.CLIPPING_IMAGE_VIEW_PROGRESS, 0.0f, 1.0f)); + animators.add(ObjectAnimator.ofInt(backgroundDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0, 255)); + animators.add(ObjectAnimator.ofFloat(containerView, View.ALPHA, 0.0f, 1.0f)); + if (sendPhotoType == SELECT_TYPE_AVATAR) { + animators.add(ObjectAnimator.ofFloat(photoCropView, View.ALPHA, 0, 1.0f)); + } + animatorSet.playTogether(animators); + animatorSet.setDuration(200); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(currentAccount).setAnimationInProgress(false); + if (animationEndRunnable != null) { + animationEndRunnable.run(); + animationEndRunnable = null; + } + }); + } + }); + if (Build.VERSION.SDK_INT >= 18) { + containerView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + } + transitionAnimationStartTime = System.currentTimeMillis(); + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(currentAccount).setAllowedNotificationsDutingAnimation(new int[]{NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, NotificationCenter.mediaCountDidLoad, NotificationCenter.mediaDidLoad, NotificationCenter.dialogPhotosLoaded}); + NotificationCenter.getInstance(currentAccount).setAnimationInProgress(true); + animatorSet.start(); + }); + } else { + if (animationEndRunnable != null) { + animationEndRunnable.run(); + animationEndRunnable = null; + } + containerView.setAlpha(1.0f); + backgroundDrawable.setAlpha(255); + animatingImageView.setAnimationProgress(1.0f); + if (sendPhotoType == SELECT_TYPE_AVATAR) { + photoCropView.setAlpha(1.0f); } - }); - transitionAnimationStartTime = System.currentTimeMillis(); - AndroidUtilities.runOnUIThread(() -> { - NotificationCenter.getInstance(currentAccount).setAllowedNotificationsDutingAnimation(new int[]{NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats, NotificationCenter.mediaCountDidLoad, NotificationCenter.mediaDidLoad, NotificationCenter.dialogPhotosLoaded}); - NotificationCenter.getInstance(currentAccount).setAnimationInProgress(true); - animatorSet.start(); - }); - if (Build.VERSION.SDK_INT >= 18) { - containerView.setLayerType(View.LAYER_TYPE_HARDWARE, null); } backgroundDrawable.drawRunnable = () -> { disableShowCheck = false; object.imageReceiver.setVisible(false, true); }; - return true; } }); @@ -6699,9 +6918,26 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat initCropView(); setCropBitmap(); } + + AccessibilityManager am = (AccessibilityManager) parentActivity.getSystemService(Context.ACCESSIBILITY_SERVICE); + if (am.isTouchExplorationEnabled()) { + AccessibilityEvent event = AccessibilityEvent.obtain(); + event.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT); + event.getText().add(LocaleController.getString("AccDescrPhotoViewer", R.string.AccDescrPhotoViewer)); + am.sendAccessibilityEvent(event); + } + return true; } + public void injectVideoPlayerToMediaController() { + if (videoPlayer.isPlaying()) { + MediaController.getInstance().injectVideoPlayer(videoPlayer, currentMessageObject); + videoPlayer = null; + updateAccessibilityOverlayVisibility(); + } + } + public void closePhoto(boolean animated, boolean fromEditMode) { if (!fromEditMode && currentEditMode != 0) { if (currentEditMode == 3 && photoPaintView != null) { @@ -6715,6 +6951,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat qualityPicker.cancelButton.callOnClick(); return; } + openedFullScreenVideo = false; try { if (visibleDialog != null) { visibleDialog.dismiss(); @@ -6753,7 +6990,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (captionEditText.hideActionMode() && !fromEditMode) { return; } - final PlaceProviderObject object = placeProvider.getPlaceForPhoto(currentMessageObject, currentFileLocation, currentIndex, true); + final PlaceProviderObject object = placeProvider.getPlaceForPhoto(currentMessageObject, getFileLocation(currentFileLocation), currentIndex, true); if (videoPlayer != null && object != null) { AnimatedFileDrawable animation = object.imageReceiver.getAnimation(); if (animation != null) { @@ -6775,7 +7012,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat object.imageReceiver.startAnimation(); } } - releasePlayer(); + releasePlayer(true); captionEditText.onDestroy(); parentChatActivity = null; removeObservers(); @@ -6802,12 +7039,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat AnimatorSet animatorSet = new AnimatorSet(); final ViewGroup.LayoutParams layoutParams = animatingImageView.getLayoutParams(); - Rect drawRegion = null; + RectF drawRegion = null; if (object != null) { animatingImageView.setNeedRadius(object.radius != 0); drawRegion = object.imageReceiver.getDrawRegion(); - layoutParams.width = drawRegion.right - drawRegion.left; - layoutParams.height = drawRegion.bottom - drawRegion.top; + layoutParams.width = (int) drawRegion.width(); + layoutParams.height = (int) drawRegion.height(); int orientation = object.imageReceiver.getOrientation(); int animatedOrientation = object.imageReceiver.getAnimatedOrientation(); if (animatedOrientation != 0) { @@ -6838,16 +7075,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (object != null) { object.imageReceiver.setVisible(false, true); - int clipHorizontal = Math.abs(drawRegion.left - object.imageReceiver.getImageX()); - int clipVertical = Math.abs(drawRegion.top - object.imageReceiver.getImageY()); + int clipHorizontal = (int) Math.abs(drawRegion.left - object.imageReceiver.getImageX()); + int clipVertical = (int) Math.abs(drawRegion.top - object.imageReceiver.getImageY()); - int coords2[] = new int[2]; + int[] coords2 = new int[2]; object.parentView.getLocationInWindow(coords2); - int clipTop = coords2[1] - (Build.VERSION.SDK_INT >= 21 ? 0 : AndroidUtilities.statusBarHeight) - (object.viewY + drawRegion.top) + object.clipTopAddition; + int clipTop = (int) (coords2[1] - (Build.VERSION.SDK_INT >= 21 ? 0 : AndroidUtilities.statusBarHeight) - (object.viewY + drawRegion.top) + object.clipTopAddition); if (clipTop < 0) { clipTop = 0; } - int clipBottom = (object.viewY + drawRegion.top + (drawRegion.bottom - drawRegion.top)) - (coords2[1] + object.parentView.getHeight() - (Build.VERSION.SDK_INT >= 21 ? 0 : AndroidUtilities.statusBarHeight)) + object.clipBottomAddition; + int clipBottom = (int) ((object.viewY + drawRegion.top + (drawRegion.bottom - drawRegion.top)) - (coords2[1] + object.parentView.getHeight() - (Build.VERSION.SDK_INT >= 21 ? 0 : AndroidUtilities.statusBarHeight)) + object.clipBottomAddition); if (clipBottom < 0) { clipBottom = 0; } @@ -6990,7 +7227,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat pipVideoView = null; } removeObservers(); - releasePlayer(); + releasePlayer(false); try { if (windowView.getParent() != null) { WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); @@ -7023,6 +7260,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat currentFileLocation = null; currentSecureDocument = null; currentPathObject = null; + if (videoPlayerControlFrameLayout != null) { + videoPlayerControlFrameLayout.setVisibility(View.GONE); + dateTextView.setVisibility(View.VISIBLE); + nameTextView.setVisibility(View.VISIBLE); + } sendPhotoType = 0; if (currentThumb != null) { currentThumb.release(); @@ -7601,6 +7843,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } if (switchImageAfterAnimation != 0) { + openedFullScreenVideo = false; if (switchImageAfterAnimation == 1) { AndroidUtilities.runOnUIThread(() -> setImageIndex(currentIndex + 1, false)); } else if (switchImageAfterAnimation == 2) { @@ -7747,6 +7990,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat drawProgress = progressView.getVisibility() != View.VISIBLE && (videoPlayer == null || !videoPlayer.isPlaying()); } else { drawProgress = !drawTextureView && videoPlayerControlFrameLayout.getVisibility() != View.VISIBLE; + if (drawProgress && currentAnimation != null && !currentAnimation.isLoadingStream()) { + drawProgress = false; + } } if (drawProgress) { canvas.save(); @@ -8273,10 +8519,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat compressItem.setEnabled(false); } videoTimelineView.setMaxProgressDiff(30000.0f / videoDuration); + muteItem.setContentDescription(LocaleController.getString("NoSound", R.string.NoSound)); } else { muteItem.setColorFilter(null); actionBar.setSubtitle(currentSubtitle); muteItem.setImageResource(R.drawable.volume_on); + muteItem.setContentDescription(LocaleController.getString("Sound", R.string.Sound)); if (compressItem.getTag() != null) { compressItem.setClickable(true); compressItem.setAlpha(1.0f); @@ -8319,6 +8567,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else if (selectedCompression == 4) { compressItem.setImageResource(R.drawable.video_1080); } + String[] compressionStrings = {"240", "360", "480", "720", "1080"}; + compressItem.setContentDescription(LocaleController.getString("AccDescrVideoQuality", R.string.AccDescrVideoQuality) + ", " + compressionStrings[Math.max(0, selectedCompression)]); estimatedDuration = (long) Math.ceil((videoTimelineView.getRightProgress() - videoTimelineView.getLeftProgress()) * videoDuration); @@ -8375,7 +8625,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } else { requestingPreview = true; - releasePlayer(); + releasePlayer(false); if (videoPreviewMessageObject == null) { TLRPC.TL_message message = new TLRPC.TL_message(); message.id = 0; @@ -8569,131 +8819,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (currentLoadingVideoRunnable != this) { return; } - TrackHeaderBox trackHeaderBox = null; - boolean isAvc = true; - try { - IsoFile isoFile = new IsoFile(videoPath); - List boxes = Path.getPaths(isoFile, "/moov/trak/"); - - Box boxTest = Path.getPath(isoFile, "/moov/trak/mdia/minf/stbl/stsd/mp4a/"); - if (boxTest == null) { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("video hasn't mp4a atom"); - } - } - - boxTest = Path.getPath(isoFile, "/moov/trak/mdia/minf/stbl/stsd/avc1/"); - if (boxTest == null) { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("video hasn't avc1 atom"); - } - - isAvc = false; - } - - audioFramesSize = 0; - videoFramesSize = 0; - videoDuration = 0; - for (int b = 0; b < boxes.size(); b++) { - if (currentLoadingVideoRunnable != this) { - return; - } - Box box = boxes.get(b); - TrackBox trackBox = (TrackBox) box; - long sampleSizes = 0; - long trackBitrate = 0; - MediaBox mediaBox = null; - MediaHeaderBox mediaHeaderBox = null; - try { - mediaBox = trackBox.getMediaBox(); - mediaHeaderBox = mediaBox.getMediaHeaderBox(); - - SampleSizeBox sampleSizeBox = mediaBox.getMediaInformationBox().getSampleTableBox().getSampleSizeBox(); - long[] sizes = sampleSizeBox.getSampleSizes(); - for (int a = 0; a < sizes.length; a++) { - if (currentLoadingVideoRunnable != this) { - return; - } - sampleSizes += sizes[a]; - } - - if (videoDuration == 0) { - videoDuration = (float) mediaHeaderBox.getDuration() / (float) mediaHeaderBox.getTimescale(); - if (videoDuration == 0) { - MediaPlayer player = null; - try { - player = new MediaPlayer(); - player.setDataSource(videoPath); - player.prepare(); - videoDuration = player.getDuration() / 1000.0f; - if (videoDuration < 0) { - videoDuration = 0; - } - } catch (Throwable ignore) { - - } finally { - try { - if (player != null) { - player.release(); - } - } catch (Throwable ignore) { - - } - } - } - } - if (videoDuration != 0) { - trackBitrate = (int) (sampleSizes * 8 / videoDuration); - } else { - trackBitrate = 400000; - } - } catch (Exception e) { - FileLog.e(e); - } - if (currentLoadingVideoRunnable != this) { - return; - } - TrackHeaderBox headerBox = trackBox.getTrackHeaderBox(); - if (headerBox.getWidth() != 0 && headerBox.getHeight() != 0) { - if (trackHeaderBox == null || trackHeaderBox.getWidth() < headerBox.getWidth() || trackHeaderBox.getHeight() < headerBox.getHeight()) { - trackHeaderBox = headerBox; - originalBitrate = bitrate = (int) (trackBitrate / 100000 * 100000); - if (bitrate > 900000) { - bitrate = 900000; - } - videoFramesSize += sampleSizes; - - if (mediaBox != null && mediaHeaderBox != null) { - TimeToSampleBox timeToSampleBox = mediaBox.getMediaInformationBox().getSampleTableBox().getTimeToSampleBox(); - if (timeToSampleBox != null) { - List entries = timeToSampleBox.getEntries(); - long delta = 0; - int size = Math.min(entries.size(), 11); - for (int a = 1; a < size; a++) { - delta += entries.get(a).getDelta(); - } - if (delta != 0) { - videoFramerate = (int) ((double) mediaHeaderBox.getTimescale() / (delta / (size - 1))); - } - } - } - } - } else { - audioFramesSize += sampleSizes; - } - } - } catch (Exception e) { - FileLog.e(e); - isAvc = false; - } - if (trackHeaderBox == null) { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("video hasn't trackHeaderBox atom"); - } - isAvc = false; - } - final boolean isAvcFinal = isAvc; - final TrackHeaderBox trackHeaderBoxFinal = trackHeaderBox; + int[] params = new int[AnimatedFileDrawable.PARAM_NUM_COUNT]; + AnimatedFileDrawable.getVideoInfo(videoPath, params); if (currentLoadingVideoRunnable != this) { return; } @@ -8702,22 +8829,20 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (parentActivity == null) { return; } - videoHasAudio = isAvcFinal; - if (isAvcFinal) { - Matrix matrix = trackHeaderBoxFinal.getMatrix(); - if (matrix.equals(Matrix.ROTATE_90)) { - rotationValue = 90; - } else if (matrix.equals(Matrix.ROTATE_180)) { - rotationValue = 180; - } else if (matrix.equals(Matrix.ROTATE_270)) { - rotationValue = 270; - } else { - rotationValue = 0; - } - resultWidth = originalWidth = (int) trackHeaderBoxFinal.getWidth(); - resultHeight = originalHeight = (int) trackHeaderBoxFinal.getHeight(); + videoHasAudio = params[AnimatedFileDrawable.PARAM_NUM_IS_AVC] != 0; + audioFramesSize = params[AnimatedFileDrawable.PARAM_NUM_AUDIO_FRAME_SIZE]; + videoFramesSize = params[AnimatedFileDrawable.PARAM_NUM_VIDEO_FRAME_SIZE]; + videoDuration = params[AnimatedFileDrawable.PARAM_NUM_DURATION]; + originalBitrate = bitrate = params[AnimatedFileDrawable.PARAM_NUM_BITRATE]; + videoFramerate = params[AnimatedFileDrawable.PARAM_NUM_FRAMERATE]; - videoDuration *= 1000; + if (bitrate > 900000) { + bitrate = 900000; + } + if (videoHasAudio) { + rotationValue = params[AnimatedFileDrawable.PARAM_NUM_ROTATION]; + resultWidth = originalWidth = params[AnimatedFileDrawable.PARAM_NUM_WIDTH]; + resultHeight = originalHeight = params[AnimatedFileDrawable.PARAM_NUM_HEIGHT]; SharedPreferences preferences = MessagesController.getGlobalMainSettings(); selectedCompression = preferences.getInt("compress_video2", 1); @@ -8810,6 +8935,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } + private void updateAccessibilityOverlayVisibility() { + if (playButtonAccessibilityOverlay == null) + return; + if (isCurrentVideo && (videoPlayer == null || !videoPlayer.isPlaying())) { + playButtonAccessibilityOverlay.setVisibility(View.VISIBLE); + } else { + playButtonAccessibilityOverlay.setVisibility(View.INVISIBLE); + } + } + private class ListAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; @@ -8880,6 +9015,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat }; imageView.setScaleType(ImageView.ScaleType.CENTER); imageView.setImageResource(R.drawable.photos_group); + imageView.setFocusable(true); view = imageView; break; } @@ -8935,6 +9071,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat case 1: { ImageView imageView = (ImageView) holder.itemView; imageView.setColorFilter(SharedConfig.groupPhotosEnabled ? new PorterDuffColorFilter(0xff66bffa, PorterDuff.Mode.MULTIPLY) : null); + imageView.setContentDescription(SharedConfig.groupPhotosEnabled ? LocaleController.getString("GroupPhotosHelp", R.string.GroupPhotosHelp) : LocaleController.getString("SinglePhotosHelp", R.string.SinglePhotosHelp)); break; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java index 63cebe576..c3df0cd82 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java @@ -20,10 +20,6 @@ import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.DefaultItemAnimator; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; -import org.telegram.messenger.support.widget.helper.ItemTouchHelper; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; @@ -43,6 +39,11 @@ import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class PollCreateActivity extends BaseFragment { private ActionBarMenuItem doneItem; @@ -171,7 +172,7 @@ public class PollCreateActivity extends BaseFragment { }); ActionBarMenu menu = actionBar.createMenu(); - doneItem = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)); + doneItem = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); progressView = new ContextProgressView(context, 1); progressView.setAlpha(0.0f); progressView.setScaleX(0.1f); @@ -191,6 +192,16 @@ public class PollCreateActivity extends BaseFragment { rectangle.bottom += AndroidUtilities.dp(60); return super.requestChildRectangleOnScreen(child, rectangle, immediate); } + + @Override + protected void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(widthSpec, heightSpec); + } + + @Override + public void requestLayout() { + super.requestLayout(); + } }; listView.setVerticalScrollBarEnabled(false); ((DefaultItemAnimator) listView.getItemAnimator()).setDelayAnimations(false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java index 15659d694..f0087ce14 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java @@ -18,7 +18,6 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Configuration; -import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.PowerManager; @@ -41,6 +40,7 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DownloadController; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.MessagesController; @@ -889,15 +889,13 @@ public class PopupNotificationActivity extends Activity implements NotificationC photoExist = false; } } - if (messageObject.needDrawBluredPreview()) { - imageView.setImage(null, "100_100_b2", thumb, currentPhotoObject.size, messageObject); - } else { + if (!messageObject.needDrawBluredPreview()) { if (photoExist || DownloadController.getInstance(messageObject.currentAccount).canDownloadMedia(messageObject)) { - imageView.setImage(currentPhotoObject, "100_100", thumb, currentPhotoObject.size, messageObject); + imageView.setImage(ImageLocation.getForObject(currentPhotoObject, messageObject.photoThumbsObject), "100_100", ImageLocation.getForObject(thumb, messageObject.photoThumbsObject), "100_100_b", currentPhotoObject.size, messageObject); photoSet = true; } else { if (thumb != null) { - imageView.setImage(thumb, null, (Drawable) null, messageObject); + imageView.setImage(ImageLocation.getForObject(thumb, messageObject.photoThumbsObject), "100_100_b", null, null, messageObject); photoSet = true; } } @@ -921,7 +919,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC double lon = geoPoint._long; if (MessagesController.getInstance(messageObject.currentAccount).mapProvider == 2) { - imageView.setImage(WebFile.createWithGeoPoint(geoPoint, 100, 100, 15, Math.min(2, (int) Math.ceil(AndroidUtilities.density))), null, (Drawable) null, messageObject); + imageView.setImage(ImageLocation.getForWebFile(WebFile.createWithGeoPoint(geoPoint, 100, 100, 15, Math.min(2, (int) Math.ceil(AndroidUtilities.density)))), null, null, null, messageObject); } else { String currentUrl = AndroidUtilities.formapMapUrl(messageObject.currentAccount, lat, lon, 100, 100, true, 15); imageView.setImage(currentUrl, null, null); @@ -1331,32 +1329,26 @@ public class PopupNotificationActivity extends Activity implements NotificationC if (currentMessageObject == null) { return; } - TLRPC.FileLocation newPhoto = null; - AvatarDrawable avatarDrawable = null; - Object parentObject = null; if (currentChat != null) { TLRPC.Chat chat = MessagesController.getInstance(currentMessageObject.currentAccount).getChat(currentChat.id); if (chat == null) { return; } - parentObject = currentChat = chat; - if (currentChat.photo != null) { - newPhoto = currentChat.photo.photo_small; + currentChat = chat; + if (avatarImageView != null) { + AvatarDrawable avatarDrawable = new AvatarDrawable(currentChat); + avatarImageView.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, chat); } - avatarDrawable = new AvatarDrawable(currentChat); } else if (currentUser != null) { TLRPC.User user = MessagesController.getInstance(currentMessageObject.currentAccount).getUser(currentUser.id); if (user == null) { return; } - parentObject = currentUser = user; - if (currentUser.photo != null) { - newPhoto = currentUser.photo.photo_small; + currentUser = user; + if (avatarImageView != null) { + AvatarDrawable avatarDrawable = new AvatarDrawable(currentUser); + avatarImageView.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); } - avatarDrawable = new AvatarDrawable(currentUser); - } - if (avatarImageView != null) { - avatarImageView.setImage(newPhoto, "50_50", avatarDrawable, parentObject); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java index 079c9c60e..45c6a6d60 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java @@ -10,9 +10,15 @@ package org.telegram.ui; import android.content.Context; import android.content.SharedPreferences; +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.os.Bundle; import android.text.Spannable; import android.text.method.LinkMovementMethod; +import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -22,12 +28,12 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; +import org.telegram.messenger.UserConfig; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; @@ -36,20 +42,31 @@ import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; +import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Cells.RadioCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; +import org.telegram.ui.Components.HintView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; +import java.util.Collections; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; public class PrivacyControlActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListAdapter listAdapter; private View doneButton; private RecyclerListView listView; + private MessageCell messageCell; + + private int initialRulesType; + private ArrayList initialPlus = new ArrayList<>(); + private ArrayList initialMinus = new ArrayList<>(); private int rulesType; private ArrayList currentPlus; @@ -60,6 +77,7 @@ public class PrivacyControlActivity extends BaseFragment implements Notification private boolean enableAnimation; + private int messageRow; private int sectionRow; private int everybodyRow; private int myContactsRow; @@ -85,9 +103,141 @@ public class PrivacyControlActivity extends BaseFragment implements Notification } } + private class MessageCell extends FrameLayout { + + private ChatMessageCell cell; + private Drawable backgroundDrawable; + private Drawable shadowDrawable; + private HintView hintView; + private MessageObject messageObject; + + public MessageCell(Context context) { + super(context); + + setWillNotDraw(false); + setClipToPadding(false); + + shadowDrawable = Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow); + setPadding(0, AndroidUtilities.dp(11), 0, AndroidUtilities.dp(11)); + + int date = (int) (System.currentTimeMillis() / 1000) - 60 * 60; + + TLRPC.User currentUser = MessagesController.getInstance(currentAccount).getUser(UserConfig.getInstance(currentAccount).getClientUserId()); + + TLRPC.Message message = new TLRPC.TL_message(); + message.message = LocaleController.getString("PrivacyForwardsMessageLine", R.string.PrivacyForwardsMessageLine); + message.date = date + 60; + message.dialog_id = 1; + message.flags = 257 + TLRPC.MESSAGE_FLAG_FWD; + message.from_id = 0; + message.id = 1; + message.fwd_from = new TLRPC.TL_messageFwdHeader(); + message.fwd_from.from_name = ContactsController.formatName(currentUser.first_name, currentUser.last_name); + 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 = new MessageObject(currentAccount, message, true); + messageObject.eventId = 1; + messageObject.resetLayout(); + + cell = new ChatMessageCell(context); + cell.setDelegate(new ChatMessageCell.ChatMessageCellDelegate() { + + }); + cell.isChat = false; + cell.setFullyDraw(true); + cell.setMessageObject(messageObject, null, false, false); + addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + hintView = new HintView(context, 1, true); + addView(hintView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 19, 0, 19, 0)); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + hintView.showForMessageCell(cell, false); + } + + @Override + protected void onDraw(Canvas canvas) { + Drawable newDrawable = Theme.getCachedWallpaperNonBlocking(); + if (newDrawable != null) { + backgroundDrawable = newDrawable; + } + if (backgroundDrawable instanceof ColorDrawable) { + backgroundDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); + backgroundDrawable.draw(canvas); + } else if (backgroundDrawable instanceof BitmapDrawable) { + BitmapDrawable bitmapDrawable = (BitmapDrawable) backgroundDrawable; + if (bitmapDrawable.getTileModeX() == Shader.TileMode.REPEAT) { + canvas.save(); + float scale = 2.0f / AndroidUtilities.density; + canvas.scale(scale, scale); + backgroundDrawable.setBounds(0, 0, (int) Math.ceil(getMeasuredWidth() / scale), (int) Math.ceil(getMeasuredHeight() / scale)); + backgroundDrawable.draw(canvas); + canvas.restore(); + } else { + int viewHeight = getMeasuredHeight(); + float scaleX = (float) getMeasuredWidth() / (float) backgroundDrawable.getIntrinsicWidth(); + float scaleY = (float) (viewHeight) / (float) backgroundDrawable.getIntrinsicHeight(); + float scale = scaleX < scaleY ? scaleY : scaleX; + int width = (int) Math.ceil(backgroundDrawable.getIntrinsicWidth() * scale); + int height = (int) Math.ceil(backgroundDrawable.getIntrinsicHeight() * scale); + int x = (getMeasuredWidth() - width) / 2; + int y = (viewHeight - height) / 2; + canvas.save(); + canvas.clipRect(0, 0, width, getMeasuredHeight()); + backgroundDrawable.setBounds(x, y, x + width, y + height); + backgroundDrawable.draw(canvas); + canvas.restore(); + } + } else { + super.onDraw(canvas); + } + + 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; + } + + @Override + public void invalidate() { + super.invalidate(); + cell.invalidate(); + } + } + public PrivacyControlActivity(int type) { + this(type, false); + } + + public PrivacyControlActivity(int type, boolean load) { super(); rulesType = type; + if (load) { + ContactsController.getInstance(currentAccount).loadPrivacySettings(); + } } @Override @@ -96,6 +246,7 @@ public class PrivacyControlActivity extends BaseFragment implements Notification checkPrivacy(); updateRows(); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.privacyRulesUpdated); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiDidLoad); return true; } @@ -103,13 +254,22 @@ public class PrivacyControlActivity extends BaseFragment implements Notification public void onFragmentDestroy() { super.onFragmentDestroy(); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.privacyRulesUpdated); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiDidLoad); } @Override public View createView(Context context) { + if (rulesType == 5) { + messageCell = new MessageCell(context); + } + actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); - if (rulesType == 3) { + if (rulesType == 5) { + actionBar.setTitle(LocaleController.getString("PrivacyForwards", R.string.PrivacyForwards)); + } else if (rulesType == 4) { + actionBar.setTitle(LocaleController.getString("PrivacyProfilePhoto", R.string.PrivacyProfilePhoto)); + } else if (rulesType == 3) { actionBar.setTitle(LocaleController.getString("PrivacyP2P", R.string.PrivacyP2P)); } else if (rulesType == 2) { actionBar.setTitle(LocaleController.getString("Calls", R.string.Calls)); @@ -122,33 +282,11 @@ public class PrivacyControlActivity extends BaseFragment implements Notification @Override public void onItemClick(int id) { if (id == -1) { - finishFragment(); + if (checkDiscard()) { + finishFragment(); + } } else if (id == done_button) { - if (getParentActivity() == null) { - return; - } - - if (currentType != 0 && rulesType == 0) { - final SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - boolean showed = preferences.getBoolean("privacyAlertShowed", false); - if (!showed) { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - if (rulesType == 1) { - builder.setMessage(LocaleController.getString("WhoCanAddMeInfo", R.string.WhoCanAddMeInfo)); - } else { - builder.setMessage(LocaleController.getString("CustomHelp", R.string.CustomHelp)); - } - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> { - applyCurrentPrivacySettings(); - preferences.edit().putBoolean("privacyAlertShowed", true).commit(); - }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showDialog(builder.create()); - return; - } - } - applyCurrentPrivacySettings(); + processDone(); } } }); @@ -183,9 +321,9 @@ public class PrivacyControlActivity extends BaseFragment implements Notification return; } enableAnimation = true; - doneButton.setVisibility(View.VISIBLE); lastCheckedType = currentType; currentType = newType; + doneButton.setVisibility(hasChanges() ? View.VISIBLE : View.GONE); updateRows(); } else if (position == neverShareRow || position == alwaysShareRow) { ArrayList createFromArray; @@ -211,8 +349,8 @@ public class PrivacyControlActivity extends BaseFragment implements Notification currentMinus.remove(currentPlus.get(a)); } } - doneButton.setVisibility(View.VISIBLE); lastCheckedType = -1; + doneButton.setVisibility(hasChanges() ? View.VISIBLE : View.GONE); listAdapter.notifyDataSetChanged(); }); presentFragment(fragment); @@ -234,7 +372,7 @@ public class PrivacyControlActivity extends BaseFragment implements Notification } } } - doneButton.setVisibility(View.VISIBLE); + doneButton.setVisibility(hasChanges() ? View.VISIBLE : View.GONE); listAdapter.notifyDataSetChanged(); }); presentFragment(fragment); @@ -242,6 +380,8 @@ public class PrivacyControlActivity extends BaseFragment implements Notification } }); + setMessageText(); + return fragmentView; } @@ -249,12 +389,18 @@ public class PrivacyControlActivity extends BaseFragment implements Notification public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.privacyRulesUpdated) { checkPrivacy(); + } else if (id == NotificationCenter.emojiDidLoad) { + listView.invalidateViews(); } } private void applyCurrentPrivacySettings() { TLRPC.TL_account_setPrivacy req = new TLRPC.TL_account_setPrivacy(); - if (rulesType == 3) { + if (rulesType == 5) { + req.key = new TLRPC.TL_inputPrivacyKeyForwards(); + } else if (rulesType == 4) { + req.key = new TLRPC.TL_inputPrivacyKeyProfilePhoto(); + } else if (rulesType == 3) { req.key = new TLRPC.TL_inputPrivacyKeyPhoneP2P(); } else if (rulesType == 2) { req.key = new TLRPC.TL_inputPrivacyKeyPhoneCall(); @@ -312,10 +458,10 @@ public class PrivacyControlActivity extends BaseFragment implements Notification FileLog.e(e); } if (error == null) { + TLRPC.TL_account_privacyRules privacyRules = (TLRPC.TL_account_privacyRules) response; + MessagesController.getInstance(currentAccount).putUsers(privacyRules.users, false); + ContactsController.getInstance(currentAccount).setPrivacyRules(privacyRules.rules, rulesType); finishFragment(); - TLRPC.TL_account_privacyRules rules = (TLRPC.TL_account_privacyRules) response; - MessagesController.getInstance(currentAccount).putUsers(rules.users, false); - ContactsController.getInstance(currentAccount).setPrivacyRules(rules.rules, rulesType); } else { showErrorAlert(); } @@ -339,42 +485,76 @@ public class PrivacyControlActivity extends BaseFragment implements Notification ArrayList privacyRules = ContactsController.getInstance(currentAccount).getPrivacyRules(rulesType); if (privacyRules == null || privacyRules.size() == 0) { currentType = 1; - return; - } - int type = -1; - for (int a = 0; a < privacyRules.size(); a++) { - TLRPC.PrivacyRule rule = privacyRules.get(a); - if (rule instanceof TLRPC.TL_privacyValueAllowUsers) { - currentPlus.addAll(rule.users); - } else if (rule instanceof TLRPC.TL_privacyValueDisallowUsers) { - currentMinus.addAll(rule.users); - } else if (rule instanceof TLRPC.TL_privacyValueAllowAll) { - type = 0; - } else if (rule instanceof TLRPC.TL_privacyValueDisallowAll) { - type = 1; - } else { - type = 2; + } else { + int type = -1; + for (int a = 0; a < privacyRules.size(); a++) { + TLRPC.PrivacyRule rule = privacyRules.get(a); + if (rule instanceof TLRPC.TL_privacyValueAllowUsers) { + currentPlus.addAll(rule.users); + } else if (rule instanceof TLRPC.TL_privacyValueDisallowUsers) { + currentMinus.addAll(rule.users); + } else if (rule instanceof TLRPC.TL_privacyValueAllowAll) { + type = 0; + } else if (rule instanceof TLRPC.TL_privacyValueDisallowAll) { + type = 1; + } else { + type = 2; + } + } + if (type == 0 || type == -1 && currentMinus.size() > 0) { + currentType = 0; + } else if (type == 2 || type == -1 && currentMinus.size() > 0 && currentPlus.size() > 0) { + currentType = 2; + } else if (type == 1 || type == -1 && currentPlus.size() > 0) { + currentType = 1; + } + if (doneButton != null) { + doneButton.setVisibility(View.GONE); } } - if (type == 0 || type == -1 && currentMinus.size() > 0) { - currentType = 0; - } else if (type == 2 || type == -1 && currentMinus.size() > 0 && currentPlus.size() > 0) { - currentType = 2; - } else if (type == 1 || type == -1 && currentPlus.size() > 0) { - currentType = 1; - } - if (doneButton != null) { - doneButton.setVisibility(View.GONE); - } + initialPlus.clear(); + initialMinus.clear(); + initialRulesType = currentType; + initialPlus.addAll(currentPlus); + initialMinus.addAll(currentMinus); + updateRows(); } + private boolean hasChanges() { + if (initialRulesType != currentType) { + return true; + } + if (initialMinus.size() != currentMinus.size()) { + return true; + } + if (initialPlus.size() != currentPlus.size()) { + return true; + } + Collections.sort(initialPlus); + Collections.sort(currentPlus); + if (!initialPlus.equals(currentPlus)) { + return true; + } + Collections.sort(initialMinus); + Collections.sort(currentMinus); + if (!initialMinus.equals(currentMinus)) { + return true; + } + return false; + } + private void updateRows() { rowCount = 0; + if (rulesType == 5) { + messageRow = rowCount++; + } else { + messageRow = -1; + } sectionRow = rowCount++; everybodyRow = rowCount++; myContactsRow = rowCount++; - if (rulesType != 0 && rulesType != 2 && rulesType != 3) { + if (rulesType != 0 && rulesType != 2 && rulesType != 3 && rulesType != 5) { nobodyRow = -1; } else { nobodyRow = rowCount++; @@ -392,11 +572,30 @@ public class PrivacyControlActivity extends BaseFragment implements Notification neverShareRow = -1; } shareDetailRow = rowCount++; + + setMessageText(); + if (listAdapter != null) { listAdapter.notifyDataSetChanged(); } } + private void setMessageText() { + if (messageCell != null) { + if (currentType == 0) { + messageCell.hintView.setOverrideText(LocaleController.getString("PrivacyForwardsEverybody", R.string.PrivacyForwardsEverybody)); + messageCell.messageObject.messageOwner.fwd_from.from_id = 1; + } else if (currentType == 1) { + messageCell.hintView.setOverrideText(LocaleController.getString("PrivacyForwardsNobody", R.string.PrivacyForwardsNobody)); + messageCell.messageObject.messageOwner.fwd_from.from_id = 0; + } else { + messageCell.hintView.setOverrideText(LocaleController.getString("PrivacyForwardsContacts", R.string.PrivacyForwardsContacts)); + messageCell.messageObject.messageOwner.fwd_from.from_id = 1; + } + messageCell.cell.forceResetMessageObject(); + } + } + @Override public void onResume() { super.onResume(); @@ -404,6 +603,57 @@ public class PrivacyControlActivity extends BaseFragment implements Notification enableAnimation = false; } + @Override + public boolean onBackPressed() { + return checkDiscard(); + } + + private void processDone() { + if (getParentActivity() == null) { + return; + } + + if (currentType != 0 && rulesType == 0) { + final SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + boolean showed = preferences.getBoolean("privacyAlertShowed", false); + if (!showed) { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + if (rulesType == 1) { + builder.setMessage(LocaleController.getString("WhoCanAddMeInfo", R.string.WhoCanAddMeInfo)); + } else { + builder.setMessage(LocaleController.getString("CustomHelp", R.string.CustomHelp)); + } + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> { + applyCurrentPrivacySettings(); + preferences.edit().putBoolean("privacyAlertShowed", true).commit(); + }); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + showDialog(builder.create()); + return; + } + } + applyCurrentPrivacySettings(); + } + + private boolean checkDiscard() { + if (doneButton.getVisibility() == View.VISIBLE) { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString("UserRestrictionsApplyChanges", R.string.UserRestrictionsApplyChanges)); + builder.setMessage(LocaleController.getString("PrivacySettingsChangedAlert", R.string.PrivacySettingsChangedAlert)); + builder.setPositiveButton(LocaleController.getString("ApplyTheme", R.string.ApplyTheme), (dialogInterface, i) -> processDone()); + builder.setNegativeButton(LocaleController.getString("PassportDiscard", R.string.PassportDiscard), (dialog, which) -> finishFragment()); + showDialog(builder.create()); + return false; + } + return true; + } + + @Override + public boolean canBeginSlide() { + return checkDiscard(); + } + private class ListAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; @@ -438,10 +688,13 @@ public class PrivacyControlActivity extends BaseFragment implements Notification view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 3: - default: view = new RadioCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; + case 4: + default: + view = messageCell; + break; } return new RecyclerListView.Holder(view); } @@ -480,7 +733,11 @@ public class PrivacyControlActivity extends BaseFragment implements Notification case 1: TextInfoPrivacyCell privacyCell = (TextInfoPrivacyCell) holder.itemView; if (position == detailRow) { - if (rulesType == 3) { + if (rulesType == 5) { + privacyCell.setText(LocaleController.getString("PrivacyForwardsInfo", R.string.PrivacyForwardsInfo)); + } else if (rulesType == 4) { + privacyCell.setText(LocaleController.getString("PrivacyProfilePhotoInfo", R.string.PrivacyProfilePhotoInfo)); + } else if (rulesType == 3) { privacyCell.setText(LocaleController.getString("PrivacyCallsP2PHelp", R.string.PrivacyCallsP2PHelp)); } else if (rulesType == 2) { privacyCell.setText(LocaleController.getString("WhoCanCallMeInfo", R.string.WhoCanCallMeInfo)); @@ -491,7 +748,11 @@ public class PrivacyControlActivity extends BaseFragment implements Notification } privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); } else if (position == shareDetailRow) { - if (rulesType == 3) { + if (rulesType == 5) { + privacyCell.setText(LocaleController.getString("PrivacyForwardsInfo2", R.string.PrivacyForwardsInfo2)); + } else if (rulesType == 4) { + privacyCell.setText(LocaleController.getString("PrivacyProfilePhotoInfo2", R.string.PrivacyProfilePhotoInfo2)); + } else if (rulesType == 3) { privacyCell.setText(LocaleController.getString("CustomP2PInfo", R.string.CustomP2PInfo)); } else if (rulesType == 2) { privacyCell.setText(LocaleController.getString("CustomCallInfo", R.string.CustomCallInfo)); @@ -506,7 +767,11 @@ public class PrivacyControlActivity extends BaseFragment implements Notification case 2: HeaderCell headerCell = (HeaderCell) holder.itemView; if (position == sectionRow) { - if (rulesType == 3) { + if (rulesType == 5) { + headerCell.setText(LocaleController.getString("PrivacyForwardsTitle", R.string.PrivacyForwardsTitle)); + } else if (rulesType == 4) { + headerCell.setText(LocaleController.getString("PrivacyProfilePhotoTitle", R.string.PrivacyProfilePhotoTitle)); + } else if (rulesType == 3) { headerCell.setText(LocaleController.getString("P2PEnabledWith", R.string.P2PEnabledWith)); } else if (rulesType == 2) { headerCell.setText(LocaleController.getString("WhoCanCallMe", R.string.WhoCanCallMe)); @@ -563,6 +828,8 @@ public class PrivacyControlActivity extends BaseFragment implements Notification return 2; } else if (position == everybodyRow || position == myContactsRow || position == nobodyRow) { return 3; + } else if (position == messageRow) { + return 4; } return 0; } @@ -596,6 +863,30 @@ public class PrivacyControlActivity extends BaseFragment implements Notification new ThemeDescription(listView, 0, new Class[]{RadioCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), new ThemeDescription(listView, ThemeDescription.FLAG_CHECKBOX, new Class[]{RadioCell.class}, new String[]{"radioButton"}, null, null, null, Theme.key_radioBackground), new ThemeDescription(listView, ThemeDescription.FLAG_CHECKBOXCHECK, new Class[]{RadioCell.class}, new String[]{"radioButton"}, null, null, null, Theme.key_radioBackgroundChecked), + + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgInDrawable, Theme.chat_msgInMediaDrawable}, null, Theme.key_chat_inBubble), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgInSelectedDrawable, Theme.chat_msgInMediaSelectedDrawable}, null, Theme.key_chat_inBubbleSelected), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgInShadowDrawable, Theme.chat_msgInMediaShadowDrawable}, null, Theme.key_chat_inBubbleShadow), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutDrawable, Theme.chat_msgOutMediaDrawable}, null, Theme.key_chat_outBubble), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgOutSelectedDrawable, Theme.chat_msgOutMediaSelectedDrawable}, null, Theme.key_chat_outBubbleSelected), + 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_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), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_inReplyNameText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_outReplyNameText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_inReplyMessageText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_outReplyMessageText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_inReplyMediaMessageSelectedText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_outReplyMediaMessageSelectedText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_inTimeText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_outTimeText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_inTimeSelectedText), + new ThemeDescription(listView, 0, null, null, null, null, Theme.key_chat_outTimeSelectedText), }; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java index 407cb45d1..98685d5c5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java @@ -24,8 +24,6 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.UserConfig; @@ -46,15 +44,22 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class PrivacySettingsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListAdapter listAdapter; private RecyclerListView listView; private AlertDialog progressDialog; + @SuppressWarnings("FieldCanBeLocal") + private LinearLayoutManager layoutManager; private int privacySectionRow; private int blockedRow; private int lastSeenRow; + private int profilePhotoRow; + private int forwardsRow; private int callsRow; private int p2pRow; private int groupsRow; @@ -89,7 +94,7 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio private boolean currentSuggest; private boolean newSuggest; - private boolean clear[] = new boolean[2]; + private boolean[] clear = new boolean[2]; @Override public boolean onFragmentCreate() { @@ -156,7 +161,7 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio frameLayout.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); listView = new RecyclerListView(context); - listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) { + listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) { @Override public boolean supportsPredictiveItemAnimations() { return false; @@ -238,6 +243,10 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio presentFragment(new PrivacyControlActivity(2)); } else if (position == p2pRow) { presentFragment(new PrivacyControlActivity(3)); + } else if (position == profilePhotoRow) { + presentFragment(new PrivacyControlActivity(4)); + } else if (position == forwardsRow) { + presentFragment(new PrivacyControlActivity(5)); } else if (position == passwordRow) { presentFragment(new TwoStepVerificationActivity(0)); } else if (position == passcodeRow) { @@ -386,8 +395,10 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio privacySectionRow = rowCount++; blockedRow = rowCount++; lastSeenRow = rowCount++; - callsRow = rowCount++; + profilePhotoRow = rowCount++; + forwardsRow = rowCount++; p2pRow = rowCount++; + callsRow = rowCount++; groupsRow = rowCount++; groupsDetailRow = rowCount++; securitySectionRow = rowCount++; @@ -549,6 +560,8 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio position == lastSeenRow && !ContactsController.getInstance(currentAccount).getLoadingPrivicyInfo(0) || position == callsRow && !ContactsController.getInstance(currentAccount).getLoadingPrivicyInfo(2) || position == p2pRow && !ContactsController.getInstance(currentAccount).getLoadingPrivicyInfo(3) || + position == profilePhotoRow && !ContactsController.getInstance(currentAccount).getLoadingPrivicyInfo(4) || + position == forwardsRow && !ContactsController.getInstance(currentAccount).getLoadingPrivicyInfo(5) || position == deleteAccountRow && !ContactsController.getInstance(currentAccount).getLoadingDeleteInfo() || position == paymentsClearRow || position == secretMapRow || position == contactsSyncRow || position == passportRow || position == contactsDeleteRow || position == contactsSuggestRow; } @@ -629,6 +642,22 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio value = formatRulesString(3); } textCell.setTextAndValue(LocaleController.getString("PrivacyP2P", R.string.PrivacyP2P), value, true); + } else if (position == profilePhotoRow) { + String value; + if (ContactsController.getInstance(currentAccount).getLoadingPrivicyInfo(4)) { + value = LocaleController.getString("Loading", R.string.Loading); + } else { + value = formatRulesString(4); + } + textCell.setTextAndValue(LocaleController.getString("PrivacyProfilePhoto", R.string.PrivacyProfilePhoto), value, true); + } else if (position == forwardsRow) { + String value; + if (ContactsController.getInstance(currentAccount).getLoadingPrivicyInfo(5)) { + value = LocaleController.getString("Loading", R.string.Loading); + } else { + value = formatRulesString(5); + } + textCell.setTextAndValue(LocaleController.getString("PrivacyForwards", R.string.PrivacyForwards), value, true); } else if (position == passportRow) { textCell.setText(LocaleController.getString("TelegramPassport", R.string.TelegramPassport), true); } else if (position == deleteAccountRow) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacyUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacyUsersActivity.java index 604599d4b..3c85fda13 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacyUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacyUsersActivity.java @@ -20,8 +20,6 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; @@ -37,6 +35,9 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class PrivacyUsersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { public interface PrivacyActivityDelegate { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 24235bee9..0365c2453 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -31,7 +31,10 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.support.annotation.Keep; +import androidx.annotation.Keep; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import android.text.TextUtils; import android.util.SparseArray; import android.util.TypedValue; @@ -52,6 +55,8 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.ChatObject; import org.telegram.messenger.DataQuery; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationsController; @@ -59,8 +64,6 @@ import org.telegram.messenger.SecretChatHelper; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.UserObject; import org.telegram.messenger.ApplicationLoader; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.ContactsController; @@ -97,6 +100,7 @@ import org.telegram.ui.Components.IdenticonDrawable; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.ScamDrawable; import org.telegram.ui.Components.voip.VoIPHelper; import java.util.ArrayList; @@ -109,10 +113,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private LinearLayoutManager layoutManager; private ListAdapter listAdapter; private BackupImageView avatarImage; - private SimpleTextView nameTextView[] = new SimpleTextView[2]; - private SimpleTextView onlineTextView[] = new SimpleTextView[2]; + private SimpleTextView[] nameTextView = new SimpleTextView[2]; + private SimpleTextView[] onlineTextView = new SimpleTextView[2]; private ImageView writeButton; private AnimatorSet writeButtonAnimation; + private ScamDrawable scamDrawable; private AvatarDrawable avatarDrawable; private ActionBarMenuItem animatingItem; @@ -149,7 +154,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private boolean isBot; private TLRPC.ChatFull chatInfo; - private TLRPC.TL_userFull userInfo; + private TLRPC.UserFull userInfo; private int selectedUser; private int onlineCount = -1; @@ -236,7 +241,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } if (photoBig != null && photoBig.local_id == fileLocation.local_id && photoBig.volume_id == fileLocation.volume_id && photoBig.dc_id == fileLocation.dc_id) { - int coords[] = new int[2]; + int[] coords = new int[2]; avatarImage.getLocationInWindow(coords); PhotoViewer.PlaceProviderObject object = new PhotoViewer.PlaceProviderObject(); object.viewX = coords[0]; @@ -325,6 +330,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. isBot = true; DataQuery.getInstance(currentAccount).loadBotInfo(user.id, true, classGuid); } + userInfo = MessagesController.getInstance(currentAccount).getUserFull(user_id); MessagesController.getInstance(currentAccount).loadFullUser(MessagesController.getInstance(currentAccount).getUser(user_id), classGuid, true); participantsMap = null; } else if (chat_id != 0) { @@ -594,9 +600,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else { did = -chat_id; } - final AlertDialog progressDialog[] = new AlertDialog[] {new AlertDialog(getParentActivity(), 3)}; + final AlertDialog[] progressDialog = new AlertDialog[]{new AlertDialog(getParentActivity(), 3)}; TLRPC.TL_messages_getStatsURL req = new TLRPC.TL_messages_getStatsURL(); req.peer = MessagesController.getInstance(currentAccount).getInputPeer(did); + req.dark = Theme.getCurrentTheme().isDark(); req.params = ""; int requestId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { try { @@ -759,7 +766,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } MessagesStorage.getInstance(currentAccount).setDialogFlags(did, 0); editor.commit(); - TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(did); + TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(did); if (dialog != null) { dialog.notify_settings = new TLRPC.TL_peerNotifySettings(); } @@ -779,7 +786,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. NotificationsController.getInstance(currentAccount).removeNotificationsForDialog(did); MessagesStorage.getInstance(currentAccount).setDialogFlags(did, flags); editor.commit(); - TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(did); + TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(did); if (dialog != null) { dialog.notify_settings = new TLRPC.TL_peerNotifySettings(); if (defaultEnabled) { @@ -1017,16 +1024,23 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(user_id); if (user.photo != null && user.photo.photo_big != null) { PhotoViewer.getInstance().setParentActivity(getParentActivity()); + if (user.photo.dc_id != 0) { + user.photo.photo_big.dc_id = user.photo.dc_id; + } PhotoViewer.getInstance().openPhoto(user.photo.photo_big, provider); } } else if (chat_id != 0) { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(chat_id); if (chat.photo != null && chat.photo.photo_big != null) { PhotoViewer.getInstance().setParentActivity(getParentActivity()); + if (chat.photo.dc_id != 0) { + chat.photo.photo_big.dc_id = chat.photo.dc_id; + } PhotoViewer.getInstance().openPhoto(chat.photo.photo_big, provider); } } }); + avatarImage.setContentDescription(LocaleController.getString("AccDescrProfilePicture", R.string.AccDescrProfilePicture)); for (int a = 0; a < 2; a++) { if (!playProfileAnimation && a == 0) { @@ -1071,12 +1085,13 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } writeButton.setBackgroundDrawable(drawable); writeButton.setImageResource(R.drawable.profile_newmsg); + writeButton.setContentDescription(LocaleController.getString("AccDescrOpenChat", R.string.AccDescrOpenChat)); writeButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_profile_actionIcon), PorterDuff.Mode.MULTIPLY)); writeButton.setScaleType(ImageView.ScaleType.CENTER); if (Build.VERSION.SDK_INT >= 21) { StateListAnimator animator = new StateListAnimator(); - animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(writeButton, "translationZ", AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); - animator.addState(new int[]{}, ObjectAnimator.ofFloat(writeButton, "translationZ", AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200)); + animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(writeButton, View.TRANSLATION_Z, AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); + animator.addState(new int[]{}, ObjectAnimator.ofFloat(writeButton, View.TRANSLATION_Z, AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200)); writeButton.setStateListAnimator(animator); writeButton.setOutlineProvider(new ViewOutlineProvider() { @SuppressLint("NewApi") @@ -1290,12 +1305,12 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } private void leaveChatPressed() { - AlertsCreator.createClearOrDeleteDialogAlert(ProfileActivity.this, false, currentChat, null, false, () -> { + AlertsCreator.createClearOrDeleteDialogAlert(ProfileActivity.this, false, currentChat, null, false, (param) -> { playProfileAnimation = false; NotificationCenter.getInstance(currentAccount).removeObserver(ProfileActivity.this, NotificationCenter.closeChats); NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.needDeleteDialog, (long) -currentChat.id, null, currentChat); finishFragment(); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.needDeleteDialog, (long) -currentChat.id, null, currentChat, param); }); } @@ -1427,16 +1442,16 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (setVisible) { writeButtonAnimation.setInterpolator(new DecelerateInterpolator()); writeButtonAnimation.playTogether( - ObjectAnimator.ofFloat(writeButton, "scaleX", 1.0f), - ObjectAnimator.ofFloat(writeButton, "scaleY", 1.0f), - ObjectAnimator.ofFloat(writeButton, "alpha", 1.0f) + ObjectAnimator.ofFloat(writeButton, View.SCALE_X, 1.0f), + ObjectAnimator.ofFloat(writeButton, View.SCALE_Y, 1.0f), + ObjectAnimator.ofFloat(writeButton, View.ALPHA, 1.0f) ); } else { writeButtonAnimation.setInterpolator(new AccelerateInterpolator()); writeButtonAnimation.playTogether( - ObjectAnimator.ofFloat(writeButton, "scaleX", 0.2f), - ObjectAnimator.ofFloat(writeButton, "scaleY", 0.2f), - ObjectAnimator.ofFloat(writeButton, "alpha", 0.0f) + ObjectAnimator.ofFloat(writeButton, View.SCALE_X, 0.2f), + ObjectAnimator.ofFloat(writeButton, View.SCALE_Y, 0.2f), + ObjectAnimator.ofFloat(writeButton, View.ALPHA, 0.0f) ); } writeButtonAnimation.setDuration(150); @@ -1750,7 +1765,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else if (id == NotificationCenter.userInfoDidLoad) { int uid = (Integer) args[0]; if (uid == user_id) { - userInfo = (TLRPC.TL_userFull) args[1]; + userInfo = (TLRPC.UserFull) args[1]; if (!openAnimationInProgress && callItem == null) { createActionBarMenu(); } else { @@ -1819,6 +1834,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } updateProfileData(); fixLayout(); + if (nameTextView[1] != null) { + setParentActivityTitle(nameTextView[1].getText()); + } } public void setPlayProfileAnimation(boolean value) { @@ -1858,6 +1876,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (voiceRow != -1) { newRowsCount++; } + if (groupsInCommonRow != -1) { + newRowsCount++; + } listAdapter.notifyItemRangeInserted(sharedHeaderRow, newRowsCount); } else if (sharedHeaderRowPrev != -1 && sharedHeaderRow != -1) { if (photosRowPrev != -1 && photosRow != -1 && prevMediaCount[DataQuery.MEDIA_PHOTOVIDEO] != lastMediaCount[DataQuery.MEDIA_PHOTOVIDEO]) { @@ -1900,6 +1921,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else if (voiceRowPrev != -1 && voiceRow == -1) { listAdapter.notifyItemRemoved(voiceRowPrev); } + if (groupsInCommonRowPrev == -1 && groupsInCommonRow != -1) { + listAdapter.notifyItemInserted(groupsInCommonRow); + } else if (groupsInCommonRowPrev != -1 && groupsInCommonRow == -1) { + listAdapter.notifyItemRemoved(groupsInCommonRowPrev); + } } } @@ -2157,27 +2183,27 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. writeButton.setScaleX(0.2f); writeButton.setScaleY(0.2f); writeButton.setAlpha(0.0f); - animators.add(ObjectAnimator.ofFloat(writeButton, "scaleX", 1.0f)); - animators.add(ObjectAnimator.ofFloat(writeButton, "scaleY", 1.0f)); - animators.add(ObjectAnimator.ofFloat(writeButton, "alpha", 1.0f)); + animators.add(ObjectAnimator.ofFloat(writeButton, View.SCALE_X, 1.0f)); + animators.add(ObjectAnimator.ofFloat(writeButton, View.SCALE_Y, 1.0f)); + animators.add(ObjectAnimator.ofFloat(writeButton, View.ALPHA, 1.0f)); } for (int a = 0; a < 2; a++) { onlineTextView[a].setAlpha(a == 0 ? 1.0f : 0.0f); nameTextView[a].setAlpha(a == 0 ? 1.0f : 0.0f); - animators.add(ObjectAnimator.ofFloat(onlineTextView[a], "alpha", a == 0 ? 0.0f : 1.0f)); - animators.add(ObjectAnimator.ofFloat(nameTextView[a], "alpha", a == 0 ? 0.0f : 1.0f)); + animators.add(ObjectAnimator.ofFloat(onlineTextView[a], View.ALPHA, a == 0 ? 0.0f : 1.0f)); + animators.add(ObjectAnimator.ofFloat(nameTextView[a], View.ALPHA, a == 0 ? 0.0f : 1.0f)); } if (animatingItem != null) { animatingItem.setAlpha(1.0f); - animators.add(ObjectAnimator.ofFloat(animatingItem, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(animatingItem, View.ALPHA, 0.0f)); } if (callItem != null) { callItem.setAlpha(0.0f); - animators.add(ObjectAnimator.ofFloat(callItem, "alpha", 1.0f)); + animators.add(ObjectAnimator.ofFloat(callItem, View.ALPHA, 1.0f)); } if (editItem != null) { editItem.setAlpha(0.0f); - animators.add(ObjectAnimator.ofFloat(editItem, "alpha", 1.0f)); + animators.add(ObjectAnimator.ofFloat(editItem, View.ALPHA, 1.0f)); } animatorSet.playTogether(animators); } else { @@ -2185,25 +2211,25 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. ArrayList animators = new ArrayList<>(); animators.add(ObjectAnimator.ofFloat(this, "animationProgress", 1.0f, 0.0f)); if (writeButton != null) { - animators.add(ObjectAnimator.ofFloat(writeButton, "scaleX", 0.2f)); - animators.add(ObjectAnimator.ofFloat(writeButton, "scaleY", 0.2f)); - animators.add(ObjectAnimator.ofFloat(writeButton, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(writeButton, View.SCALE_X, 0.2f)); + animators.add(ObjectAnimator.ofFloat(writeButton, View.SCALE_Y, 0.2f)); + animators.add(ObjectAnimator.ofFloat(writeButton, View.ALPHA, 0.0f)); } for (int a = 0; a < 2; a++) { - animators.add(ObjectAnimator.ofFloat(onlineTextView[a], "alpha", a == 0 ? 1.0f : 0.0f)); - animators.add(ObjectAnimator.ofFloat(nameTextView[a], "alpha", a == 0 ? 1.0f : 0.0f)); + animators.add(ObjectAnimator.ofFloat(onlineTextView[a], View.ALPHA, a == 0 ? 1.0f : 0.0f)); + animators.add(ObjectAnimator.ofFloat(nameTextView[a], View.ALPHA, a == 0 ? 1.0f : 0.0f)); } if (animatingItem != null) { animatingItem.setAlpha(0.0f); - animators.add(ObjectAnimator.ofFloat(animatingItem, "alpha", 1.0f)); + animators.add(ObjectAnimator.ofFloat(animatingItem, View.ALPHA, 1.0f)); } if (callItem != null) { callItem.setAlpha(1.0f); - animators.add(ObjectAnimator.ofFloat(callItem, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(callItem, View.ALPHA, 0.0f)); } if (editItem != null) { editItem.setAlpha(1.0f); - animators.add(ObjectAnimator.ofFloat(editItem, "alpha", 0.0f)); + animators.add(ObjectAnimator.ofFloat(editItem, View.ALPHA, 0.0f)); } animatorSet.playTogether(animators); } @@ -2307,7 +2333,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. fetchUsersFromChannelInfo(); } - public void setUserInfo(TLRPC.TL_userFull value) { + public void setUserInfo(TLRPC.UserFull value) { userInfo = value; } @@ -2524,7 +2550,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. lastSectionRow = rowCount++; } if (chatInfo != null && currentChat.megagroup && chatInfo.participants != null && !chatInfo.participants.participants.isEmpty()) { - if (currentChat.megagroup && ChatObject.canAddUsers(currentChat) && (chatInfo == null || chatInfo.participants_count < MessagesController.getInstance(currentAccount).maxMegagroupCount)) { + if (!ChatObject.isNotInChat(currentChat) && currentChat.megagroup && ChatObject.canAddUsers(currentChat) && (chatInfo == null || chatInfo.participants_count < MessagesController.getInstance(currentAccount).maxMegagroupCount)) { addMemberRow = rowCount++; } else { membersHeaderRow = rowCount++; @@ -2563,6 +2589,14 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } + private Drawable getScamDrawable() { + if (scamDrawable == null) { + scamDrawable = new ScamDrawable(11); + scamDrawable.setColor(AvatarDrawable.getProfileTextColorForId(user_id != 0 || ChatObject.isChannel(chat_id, currentAccount) && !currentChat.megagroup ? 5 : chat_id)); + } + return scamDrawable; + } + private void updateProfileData() { if (avatarImage == null || nameTextView == null) { return; @@ -2583,14 +2617,13 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (user_id != 0) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(user_id); - TLRPC.FileLocation photo = null; TLRPC.FileLocation photoBig = null; if (user.photo != null) { - photo = user.photo.photo_small; photoBig = user.photo.photo_big; } avatarDrawable.setInfo(user); - avatarImage.setImage(photo, "50_50", avatarDrawable, user); + avatarImage.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); + FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForUser(user, true), user, null, 0, 1); String newString = UserObject.getUserName(user); String newString2; @@ -2631,7 +2664,13 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. Drawable leftIcon = currentEncryptedChat != null ? Theme.chat_lockIconDrawable : null; Drawable rightIcon = null; if (a == 0) { - rightIcon = MessagesController.getInstance(currentAccount).isDialogMuted(dialog_id != 0 ? dialog_id : (long) user_id) ? Theme.chat_muteIconDrawable : null; + if (user.scam) { + rightIcon = getScamDrawable(); + } else { + rightIcon = MessagesController.getInstance(currentAccount).isDialogMuted(dialog_id != 0 ? dialog_id : (long) user_id) ? Theme.chat_muteIconDrawable : null; + } + } else if (user.scam) { + rightIcon = getScamDrawable(); } else if (user.verified) { rightIcon = new CombinedDrawable(Theme.profile_verifiedDrawable, Theme.profile_verifiedCheckDrawable); } @@ -2668,7 +2707,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. newString = LocaleController.formatPluralString("Members", chatInfo.participants_count); } } else { - int result[] = new int[1]; + int[] result = new int[1]; String shortNumber = LocaleController.formatShortNumber(chatInfo.participants_count, result); if (currentChat.megagroup) { newString = LocaleController.formatPluralString("Members", chatInfo.participants_count); @@ -2701,13 +2740,19 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } nameTextView[a].setLeftDrawable(null); if (a != 0) { - if (chat.verified) { + if (chat.scam) { + nameTextView[a].setRightDrawable(getScamDrawable()); + } else if (chat.verified) { nameTextView[a].setRightDrawable(new CombinedDrawable(Theme.profile_verifiedDrawable, Theme.profile_verifiedCheckDrawable)); } else { nameTextView[a].setRightDrawable(null); } } else { - nameTextView[a].setRightDrawable(MessagesController.getInstance(currentAccount).isDialogMuted((long) -chat_id) ? Theme.chat_muteIconDrawable : null); + if (chat.scam) { + nameTextView[a].setRightDrawable(getScamDrawable()); + } else { + nameTextView[a].setRightDrawable(MessagesController.getInstance(currentAccount).isDialogMuted((long) -chat_id) ? Theme.chat_muteIconDrawable : null); + } } if (a == 0 && onlineTextOverride != null) { onlineTextView[a].setText(onlineTextOverride); @@ -2717,7 +2762,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. onlineTextView[a].setText(newString); } } else if (a == 0 && ChatObject.isChannel(currentChat) && chatInfo != null && chatInfo.participants_count != 0 && (currentChat.megagroup || currentChat.broadcast)) { - int result[] = new int[1]; + int[] result = new int[1]; String shortNumber = LocaleController.formatShortNumber(chatInfo.participants_count, result); if (currentChat.megagroup) { onlineTextView[a].setText(LocaleController.formatPluralString("Members", result[0]).replace(String.format("%d", result[0]), shortNumber)); @@ -2735,14 +2780,13 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. needLayout(); } - TLRPC.FileLocation photo = null; TLRPC.FileLocation photoBig = null; if (chat.photo != null) { - photo = chat.photo.photo_small; photoBig = chat.photo.photo_big; } avatarDrawable.setInfo(chat); - avatarImage.setImage(photo, "50_50", avatarDrawable, chat); + avatarImage.setImage(ImageLocation.getForChat(chat, false), "50_50", avatarDrawable, chat); + FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForChat(chat, true), chat, null, 0, 1); avatarImage.getImageReceiver().setVisible(!PhotoViewer.isShowingImage(photoBig), false); } } @@ -2760,64 +2804,64 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return; } if (userInfo != null && userInfo.phone_calls_available) { - callItem = menu.addItem(call_item, R.drawable.ic_call_white_24dp); + callItem = menu.addItem(call_item, R.drawable.ic_call); } if (isBot || ContactsController.getInstance(currentAccount).contactsDict.get(user_id) == null) { item = menu.addItem(10, R.drawable.ic_ab_other); if (MessagesController.isSupportUser(user)) { if (userBlocked) { - item.addSubItem(block_contact, LocaleController.getString("Unblock", R.string.Unblock)); + item.addSubItem(block_contact, R.drawable.msg_block, LocaleController.getString("Unblock", R.string.Unblock)); //TODO icon } } else { if (isBot) { if (!user.bot_nochats) { - item.addSubItem(invite_to_group, LocaleController.getString("BotInvite", R.string.BotInvite)); + item.addSubItem(invite_to_group, R.drawable.msg_addbot, LocaleController.getString("BotInvite", R.string.BotInvite)); } - item.addSubItem(share, LocaleController.getString("BotShare", R.string.BotShare)); + item.addSubItem(share, R.drawable.msg_share, LocaleController.getString("BotShare", R.string.BotShare)); } if (user.phone != null && user.phone.length() != 0) { - item.addSubItem(add_contact, LocaleController.getString("AddContact", R.string.AddContact)); - item.addSubItem(share_contact, LocaleController.getString("ShareContact", R.string.ShareContact)); - item.addSubItem(block_contact, !userBlocked ? LocaleController.getString("BlockContact", R.string.BlockContact) : LocaleController.getString("Unblock", R.string.Unblock)); + item.addSubItem(add_contact, R.drawable.msg_addcontact, LocaleController.getString("AddContact", R.string.AddContact)); + item.addSubItem(share_contact, R.drawable.msg_share, LocaleController.getString("ShareContact", R.string.ShareContact)); + item.addSubItem(block_contact, !userBlocked ? R.drawable.msg_block : R.drawable.msg_block, !userBlocked ? LocaleController.getString("BlockContact", R.string.BlockContact) : LocaleController.getString("Unblock", R.string.Unblock)); //TODO icon } else { if (isBot) { - item.addSubItem(block_contact, !userBlocked ? LocaleController.getString("BotStop", R.string.BotStop) : LocaleController.getString("BotRestart", R.string.BotRestart)); + item.addSubItem(block_contact, !userBlocked ? R.drawable.msg_block : R.drawable.msg_retry, !userBlocked ? LocaleController.getString("BotStop", R.string.BotStop) : LocaleController.getString("BotRestart", R.string.BotRestart)); } else { - item.addSubItem(block_contact, !userBlocked ? LocaleController.getString("BlockContact", R.string.BlockContact) : LocaleController.getString("Unblock", R.string.Unblock)); + item.addSubItem(block_contact, !userBlocked ? R.drawable.msg_block : R.drawable.msg_block, !userBlocked ? LocaleController.getString("BlockContact", R.string.BlockContact) : LocaleController.getString("Unblock", R.string.Unblock)); //TODO icon } } } } else { item = menu.addItem(10, R.drawable.ic_ab_other); - item.addSubItem(share_contact, LocaleController.getString("ShareContact", R.string.ShareContact)); - item.addSubItem(block_contact, !userBlocked ? LocaleController.getString("BlockContact", R.string.BlockContact) : LocaleController.getString("Unblock", R.string.Unblock)); - item.addSubItem(edit_contact, LocaleController.getString("EditContact", R.string.EditContact)); - item.addSubItem(delete_contact, LocaleController.getString("DeleteContact", R.string.DeleteContact)); + item.addSubItem(share_contact, R.drawable.msg_share, LocaleController.getString("ShareContact", R.string.ShareContact)); + item.addSubItem(block_contact, !userBlocked ? R.drawable.msg_block : R.drawable.msg_block, !userBlocked ? LocaleController.getString("BlockContact", R.string.BlockContact) : LocaleController.getString("Unblock", R.string.Unblock)); //TODO icon + item.addSubItem(edit_contact, R.drawable.msg_edit, LocaleController.getString("EditContact", R.string.EditContact)); + item.addSubItem(delete_contact, R.drawable.msg_delete, LocaleController.getString("DeleteContact", R.string.DeleteContact)); } } else { item = menu.addItem(10, R.drawable.ic_ab_other); - item.addSubItem(share_contact, LocaleController.getString("ShareContact", R.string.ShareContact)); + item.addSubItem(share_contact, R.drawable.msg_share, LocaleController.getString("ShareContact", R.string.ShareContact)); } } else if (chat_id != 0) { if (chat_id > 0) { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(chat_id); if (ChatObject.isChannel(chat)) { - if (ChatObject.hasAdminRights(chat) || ChatObject.canChangeChatInfo(chat)) { + if (ChatObject.hasAdminRights(chat) || chat.megagroup && ChatObject.canChangeChatInfo(chat)) { editItem = menu.addItem(edit_channel, R.drawable.group_edit_profile); } if (!chat.megagroup && chatInfo != null && chatInfo.can_view_stats) { if (item == null) { item = menu.addItem(10, R.drawable.ic_ab_other); } - item.addSubItem(statistics, LocaleController.getString("Statistics", R.string.Statistics)); + item.addSubItem(statistics, R.drawable.msg_stats, LocaleController.getString("Statistics", R.string.Statistics)); } if (chat.megagroup) { if (item == null) { item = menu.addItem(10, R.drawable.ic_ab_other); } - item.addSubItem(search_members, LocaleController.getString("SearchMembers", R.string.SearchMembers)); + item.addSubItem(search_members, R.drawable.msg_search, LocaleController.getString("SearchMembers", R.string.SearchMembers)); if (!chat.creator && !chat.left && !chat.kicked) { - item.addSubItem(leave_group, LocaleController.getString("LeaveMegaMenu", R.string.LeaveMegaMenu)); + item.addSubItem(leave_group, R.drawable.msg_leave, LocaleController.getString("LeaveMegaMenu", R.string.LeaveMegaMenu)); } } } else { @@ -2825,15 +2869,22 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. editItem = menu.addItem(edit_channel, R.drawable.group_edit_profile); } item = menu.addItem(10, R.drawable.ic_ab_other); - item.addSubItem(search_members, LocaleController.getString("SearchMembers", R.string.SearchMembers)); - item.addSubItem(leave_group, LocaleController.getString("DeleteAndExit", R.string.DeleteAndExit)); + item.addSubItem(search_members, R.drawable.msg_search, LocaleController.getString("SearchMembers", R.string.SearchMembers)); + item.addSubItem(leave_group, R.drawable.msg_leave, LocaleController.getString("DeleteAndExit", R.string.DeleteAndExit)); } } } if (item == null) { item = menu.addItem(10, R.drawable.ic_ab_other); } - item.addSubItem(add_shortcut, LocaleController.getString("AddShortcut", R.string.AddShortcut)); + item.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut)); + item.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); + if (editItem != null) { + editItem.setContentDescription(LocaleController.getString("Edit", R.string.Edit)); + } + if (callItem != null) { + callItem.setContentDescription(LocaleController.getString("Call", R.string.Call)); + } } @Override @@ -3028,7 +3079,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else if (position == voiceRow) { textCell.setTextAndValueAndIcon(LocaleController.getString("AudioAutodownload", R.string.AudioAutodownload), String.format("%d", lastMediaCount[DataQuery.MEDIA_AUDIO]), R.drawable.profile_voice, position != sharedSectionRow - 1); } else if (position == groupsInCommonRow) { - textCell.setTextAndValueAndIcon(LocaleController.getString("GroupsInCommonTitle", R.string.GroupsInCommonTitle), String.format("%d", userInfo.common_chats_count), R.drawable.profile_groups, position != sharedSectionRow - 1); + textCell.setTextAndValueAndIcon(LocaleController.getString("GroupsInCommonTitle", R.string.GroupsInCommonTitle), String.format("%d", userInfo.common_chats_count), R.drawable.actions_viewmembers, position != sharedSectionRow - 1); } else if (position == settingsTimerRow) { TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance(currentAccount).getEncryptedChat((int) (dialog_id >> 32)); String value; @@ -3195,7 +3246,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. userCell.setIsAdmin(0); } } - userCell.setData(MessagesController.getInstance(currentAccount).getUser(part.user_id), null, null, 0, position != membersEndRow - 1); + userCell.setData(MessagesController.getInstance(currentAccount).getUser(part.user_id), null, null, 0, position != membersEndRow - 1); } break; } @@ -3258,6 +3309,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. new ThemeDescription(listView, 0, null, null, null, null, Theme.key_windowBackgroundGray), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUBACKGROUND, null, null, null, null, Theme.key_actionBarDefaultSubmenuBackground), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM, null, null, null, null, Theme.key_actionBarDefaultSubmenuItem), + new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubmenuItemIcon), new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_avatar_backgroundActionBarBlue), new ThemeDescription(listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_avatar_backgroundActionBarBlue), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java index 2736b08fd..61b63c336 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java @@ -40,8 +40,6 @@ import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.NotificationsController; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.AlertDialog; @@ -64,6 +62,9 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class ProfileNotificationsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private RecyclerListView listView; @@ -152,7 +153,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi int lower_id = (int) dialog_id; if (lower_id < 0) { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_id); - isChannel = chat != null && ChatObject.isChannel(chat) && !chat.megagroup; + isChannel = ChatObject.isChannel(chat) && !chat.megagroup; } else { isChannel = false; } @@ -231,7 +232,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi editor.putBoolean("custom_" + dialog_id, true); - TLRPC.TL_dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(dialog_id); + TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(dialog_id); if (notificationsEnabled) { editor.putInt("notify2_" + dialog_id, 0); MessagesStorage.getInstance(currentAccount).setDialogFlags(dialog_id, 0); @@ -350,6 +351,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi Intent tmpIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER); tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION); tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true); + tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true); tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)); SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); Uri currentSound = null; @@ -379,6 +381,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi Intent tmpIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER); tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE); tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true); + tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true); tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)); SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); Uri currentSound = null; @@ -454,19 +457,18 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view = new TextView(context1) { + TextView textView = new TextView(context1) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(MeasureSpec.makeMeasureSpec(widthMeasureSpec, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY)); } }; - TextView textView = (TextView) view; textView.setGravity(Gravity.CENTER); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); textView.setSingleLine(true); textView.setEllipsize(TextUtils.TruncateAt.END); textView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); - return new RecyclerListView.Holder(view); + return new RecyclerListView.Holder(textView); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProxyListActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProxyListActivity.java index 766ff5fa2..5780650b4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProxyListActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProxyListActivity.java @@ -32,9 +32,6 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; -import org.telegram.messenger.support.widget.DefaultItemAnimator; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.AlertDialog; @@ -49,10 +46,16 @@ import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class ProxyListActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListAdapter listAdapter; private RecyclerListView listView; + @SuppressWarnings("FieldCanBeLocal") + private LinearLayoutManager layoutManager; private int currentConnectionState; @@ -108,6 +111,7 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente checkImageView.setImageResource(R.drawable.profile_info); checkImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText3), PorterDuff.Mode.MULTIPLY)); checkImageView.setScaleType(ImageView.ScaleType.CENTER); + checkImageView.setContentDescription(LocaleController.getString("Edit", R.string.Edit)); addView(checkImageView, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, 8, 8, 8, 0)); checkImageView.setOnClickListener(v -> presentFragment(new ProxySettingsActivity(currentInfo))); @@ -122,7 +126,6 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente public void setProxy(SharedConfig.ProxyInfo proxyInfo) { textView.setText(proxyInfo.address + ":" + proxyInfo.port); currentInfo = proxyInfo; - updateStatus(); } public void updateStatus() { @@ -188,6 +191,12 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente valueTextView.setText(value); } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + updateStatus(); + } + @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); @@ -248,7 +257,7 @@ public class ProxyListActivity extends BaseFragment implements NotificationCente listView = new RecyclerListView(context); ((DefaultItemAnimator) listView.getItemAnimator()).setDelayAnimations(false); listView.setVerticalScrollBarEnabled(false); - listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); + listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); listView.setAdapter(listAdapter); listView.setOnItemClickListener((view, position) -> { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProxySettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProxySettingsActivity.java index d1d36ee34..4028ad3a6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProxySettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProxySettingsActivity.java @@ -210,6 +210,7 @@ public class ProxySettingsActivity extends BaseFragment { }); doneItem = actionBar.createMenu().addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)); + doneItem.setContentDescription(LocaleController.getString("Done", R.string.Done)); fragmentView = new FrameLayout(context); FrameLayout frameLayout = (FrameLayout) fragmentView; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/QuickRepliesSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/QuickRepliesSettingsActivity.java index a71bd05e5..67bb21b82 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/QuickRepliesSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/QuickRepliesSettingsActivity.java @@ -19,8 +19,6 @@ import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; @@ -32,6 +30,9 @@ import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class QuickRepliesSettingsActivity extends BaseFragment { private ListAdapter listAdapter; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java index 0e5822c30..8b7b6f4c8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java @@ -19,7 +19,6 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PixelFormat; -import android.graphics.Rect; import android.graphics.RectF; import android.graphics.SurfaceTexture; import android.graphics.drawable.BitmapDrawable; @@ -27,7 +26,7 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; -import android.support.annotation.Keep; +import androidx.annotation.Keep; import android.util.SparseArray; import android.view.GestureDetector; import android.view.Gravity; @@ -45,6 +44,7 @@ import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; @@ -331,7 +331,7 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD private MessageObject currentMessageObject; private ImageReceiver.BitmapHolder currentThumb; - private int coords[] = new int[2]; + private int[] coords = new int[2]; private boolean isPhotoVisible; @@ -769,10 +769,10 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD disableShowCheck = true; centerImage.setManualAlphaAnimator(false); - final Rect drawRegion = object.imageReceiver.getDrawRegion(); + final RectF drawRegion = object.imageReceiver.getDrawRegion(); - float width = (drawRegion.right - drawRegion.left); - float height = (drawRegion.bottom - drawRegion.top); + float width = drawRegion.width(); + float height = drawRegion.height(); int viewWidth = AndroidUtilities.displaySize.x; int viewHeight = AndroidUtilities.displaySize.y + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0); scale = Math.max(width / viewWidth, height / viewHeight); @@ -780,8 +780,8 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD translationX = object.viewX + drawRegion.left + width / 2 - viewWidth / 2; translationY = object.viewY + drawRegion.top + height / 2 - viewHeight / 2; clipHorizontal = Math.abs(drawRegion.left - object.imageReceiver.getImageX()); - int clipVertical = Math.abs(drawRegion.top - object.imageReceiver.getImageY()); - int coords2[] = new int[2]; + int clipVertical = (int) Math.abs(drawRegion.top - object.imageReceiver.getImageY()); + int[] coords2 = new int[2]; object.parentView.getLocationInWindow(coords2); clipTop = coords2[1] - (Build.VERSION.SDK_INT >= 21 ? 0 : AndroidUtilities.statusBarHeight) - (object.viewY + drawRegion.top) + object.clipTopAddition; if (clipTop < 0) { @@ -820,7 +820,7 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD if (document != null) { if (MessageObject.isGifDocument(document)) { actionBar.setTitle(LocaleController.getString("DisappearingGif", R.string.DisappearingGif)); - centerImage.setImage(document, null, currentThumb != null ? new BitmapDrawable(currentThumb.bitmap) : null, -1, null, messageObject, 1); + centerImage.setImage(ImageLocation.getForDocument(document), null, currentThumb != null ? new BitmapDrawable(currentThumb.bitmap) : null, -1, null, messageObject, 1); secretDeleteTimer.setDestroyTime((long) messageObject.messageOwner.destroyTime * 1000, messageObject.messageOwner.ttl, false); } else { playerRetryPlayCount = 1; @@ -851,7 +851,7 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD } else { actionBar.setTitle(LocaleController.getString("DisappearingPhoto", R.string.DisappearingPhoto)); TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize()); - centerImage.setImage(sizeFull, null, currentThumb != null ? new BitmapDrawable(currentThumb.bitmap) : null, -1, null, messageObject, 2); + centerImage.setImage(ImageLocation.getForObject(sizeFull, messageObject.photoThumbsObject), null, currentThumb != null ? new BitmapDrawable(currentThumb.bitmap) : null, -1, null, messageObject, 2); secretDeleteTimer.setDestroyTime((long) messageObject.messageOwner.destroyTime * 1000, messageObject.messageOwner.ttl, false); } try { @@ -1200,7 +1200,7 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD if (object != null && object.imageReceiver.getThumbBitmap() != null && !byDelete) { object.imageReceiver.setVisible(false, true); - final Rect drawRegion = object.imageReceiver.getDrawRegion(); + final RectF drawRegion = object.imageReceiver.getDrawRegion(); float width = (drawRegion.right - drawRegion.left); float height = (drawRegion.bottom - drawRegion.top); @@ -1210,8 +1210,8 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD animateToX = object.viewX + drawRegion.left + width / 2 - viewWidth / 2; animateToY = object.viewY + drawRegion.top + height / 2 - viewHeight / 2; animateToClipHorizontal = Math.abs(drawRegion.left - object.imageReceiver.getImageX()); - int clipVertical = Math.abs(drawRegion.top - object.imageReceiver.getImageY()); - int coords2[] = new int[2]; + int clipVertical =( int) Math.abs(drawRegion.top - object.imageReceiver.getImageY()); + int[] coords2 = new int[2]; object.parentView.getLocationInWindow(coords2); animateToClipTop = coords2[1] - (Build.VERSION.SDK_INT >= 21 ? 0 : AndroidUtilities.statusBarHeight) - (object.viewY + drawRegion.top) + object.clipTopAddition; if (animateToClipTop < 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java index 935fc1383..71f9c22b0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java @@ -31,8 +31,6 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserObject; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; @@ -53,6 +51,9 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class SessionsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListAdapter listAdapter; @@ -200,11 +201,8 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter if (error == null && response instanceof TLRPC.TL_boolTrue) { Toast toast = Toast.makeText(getParentActivity(), LocaleController.getString("TerminateAllSessions", R.string.TerminateAllSessions), Toast.LENGTH_SHORT); toast.show(); - } else { - Toast toast = Toast.makeText(getParentActivity(), LocaleController.getString("UnknownError", R.string.UnknownError), Toast.LENGTH_SHORT); - toast.show(); + finishFragment(); } - finishFragment(); }); for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { @@ -243,7 +241,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - final boolean param[] = new boolean[1]; + final boolean[] param = new boolean[1]; if (currentType == 0) { builder.setMessage(LocaleController.getString("TerminateSessionQuestion", R.string.TerminateSessionQuestion)); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java index d32d3e70a..8dd22a999 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java @@ -28,9 +28,14 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.v4.content.FileProvider; +import androidx.core.content.FileProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; import android.util.TypedValue; import android.view.Gravity; import android.view.View; @@ -39,6 +44,7 @@ import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; +import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; @@ -51,6 +57,8 @@ import org.telegram.messenger.BuildConfig; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DataQuery; import org.telegram.messenger.ImageLoader; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.NotificationsController; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserObject; import org.telegram.messenger.ApplicationLoader; @@ -59,9 +67,8 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.FileLoader; import org.telegram.messenger.Utilities; import org.telegram.messenger.browser.Browser; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.FileLog; import org.telegram.messenger.MessagesController; @@ -74,7 +81,9 @@ import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.EmptyCell; +import org.telegram.ui.Cells.GraySectionCell; import org.telegram.ui.Cells.HeaderCell; +import org.telegram.ui.Cells.SettingsSearchCell; import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextDetailCell; @@ -84,6 +93,7 @@ import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.EmptyTextProgressView; import org.telegram.ui.Components.ImageUpdater; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.ActionBar.BaseFragment; @@ -99,8 +109,13 @@ import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.Locale; +import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -108,6 +123,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter private RecyclerListView listView; private ListAdapter listAdapter; + private SearchAdapter searchAdapter; private LinearLayoutManager layoutManager; private FrameLayout avatarContainer; private BackupImageView avatarImage; @@ -122,11 +138,13 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter private View extraHeightView; private View shadowView; private AvatarDrawable avatarDrawable; + private ActionBarMenuItem otherItem; + private EmptyTextProgressView emptyView; private TLRPC.FileLocation avatar; private TLRPC.FileLocation avatarBig; - private TLRPC.TL_userFull userInfo; + private TLRPC.UserFull userInfo; private int extraHeight; @@ -148,6 +166,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter private final static int edit_name = 1; private final static int logout = 2; + private final static int search_button = 3; private PhotoViewer.PhotoViewerProvider provider = new PhotoViewer.EmptyPhotoViewerProvider() { @@ -160,7 +179,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter if (user != null && user.photo != null && user.photo.photo_big != null) { TLRPC.FileLocation photoBig = user.photo.photo_big; if (photoBig.local_id == fileLocation.local_id && photoBig.volume_id == fileLocation.volume_id && photoBig.dc_id == fileLocation.dc_id) { - int coords[] = new int[2]; + int[] coords = new int[2]; avatarImage.getLocationInWindow(coords); PhotoViewer.PlaceProviderObject object = new PhotoViewer.PlaceProviderObject(); object.viewX = coords[0]; @@ -254,9 +273,55 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } }); ActionBarMenu menu = actionBar.createMenu(); - ActionBarMenuItem item = menu.addItem(0, R.drawable.ic_ab_other); - item.addSubItem(edit_name, LocaleController.getString("EditName", R.string.EditName)); - item.addSubItem(logout, LocaleController.getString("LogOut", R.string.LogOut)); + ActionBarMenuItem searchItem = menu.addItem(search_button, R.drawable.ic_ab_search).setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { + @Override + public void onSearchExpand() { + if (otherItem != null) { + otherItem.setVisibility(View.GONE); + } + searchAdapter.loadFaqWebPage(); + listView.setAdapter(searchAdapter); + listView.setEmptyView(emptyView); + avatarContainer.setVisibility(View.GONE); + writeButton.setVisibility(View.GONE); + nameTextView.setVisibility(View.GONE); + onlineTextView.setVisibility(View.GONE); + extraHeightView.setVisibility(View.GONE); + fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + fragmentView.setTag(Theme.key_windowBackgroundWhite); + needLayout(); + } + + @Override + public void onSearchCollapse() { + if (otherItem != null) { + otherItem.setVisibility(View.VISIBLE); + } + listView.setAdapter(listAdapter); + listView.setEmptyView(null); + emptyView.setVisibility(View.GONE); + avatarContainer.setVisibility(View.VISIBLE); + writeButton.setVisibility(View.VISIBLE); + nameTextView.setVisibility(View.VISIBLE); + onlineTextView.setVisibility(View.VISIBLE); + extraHeightView.setVisibility(View.VISIBLE); + fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); + fragmentView.setTag(Theme.key_windowBackgroundGray); + needLayout(); + } + + @Override + public void onTextChanged(EditText editText) { + searchAdapter.search(editText.getText().toString().toLowerCase()); + } + }); + searchItem.setContentDescription(LocaleController.getString("SearchInSettings", R.string.SearchInSettings)); + searchItem.setSearchFieldHint(LocaleController.getString("SearchInSettings", R.string.SearchInSettings)); + + otherItem = menu.addItem(0, R.drawable.ic_ab_other); + otherItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); + otherItem.addSubItem(edit_name, R.drawable.msg_edit, LocaleController.getString("EditName", R.string.EditName)); + otherItem.addSubItem(logout, R.drawable.msg_leave, LocaleController.getString("LogOut", R.string.LogOut)); int scrollTo; int scrollToPosition = 0; @@ -275,10 +340,11 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } listAdapter = new ListAdapter(context); + searchAdapter = new SearchAdapter(context); fragmentView = new FrameLayout(context) { @Override - protected boolean drawChild(@NonNull Canvas canvas, @NonNull View child, long drawingTime) { + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { if (child == listView) { boolean result = super.drawChild(canvas, child, drawingTime); if (parentLayout != null) { @@ -305,6 +371,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } }; fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); + fragmentView.setTag(Theme.key_windowBackgroundGray); FrameLayout frameLayout = (FrameLayout) fragmentView; listView = new RecyclerListView(context); @@ -321,114 +388,61 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter listView.setItemAnimator(null); listView.setLayoutAnimation(null); listView.setOnItemClickListener((view, position) -> { - if (position == notificationRow) { - presentFragment(new NotificationsSettingsActivity()); - } else if (position == privacyRow) { - presentFragment(new PrivacySettingsActivity()); - } else if (position == dataRow) { - presentFragment(new DataSettingsActivity()); - } else if (position == chatRow) { - presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC)); - } else if (position == helpRow) { - BottomSheet.Builder builder = new BottomSheet.Builder(context); - builder.setApplyTopPadding(false); - - LinearLayout linearLayout = new LinearLayout(context); - linearLayout.setOrientation(LinearLayout.VERTICAL); - - HeaderCell headerCell = new HeaderCell(context, true, 23, 15, false); - headerCell.setHeight(47); - headerCell.setText(LocaleController.getString("SettingsHelp", R.string.SettingsHelp)); - linearLayout.addView(headerCell); - - LinearLayout linearLayoutInviteContainer = new LinearLayout(context); - linearLayoutInviteContainer.setOrientation(LinearLayout.VERTICAL); - linearLayout.addView(linearLayoutInviteContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - - int count = 6; - for (int a = 0; a < count; a++) { - if (a >= 3 && a <= 4 && !BuildVars.LOGS_ENABLED || a == 5 && !BuildVars.DEBUG_VERSION) { - continue; + if (listView.getAdapter() == listAdapter) { + if (position == notificationRow) { + presentFragment(new NotificationsSettingsActivity()); + } else if (position == privacyRow) { + presentFragment(new PrivacySettingsActivity()); + } else if (position == dataRow) { + presentFragment(new DataSettingsActivity()); + } else if (position == chatRow) { + presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC)); + } else if (position == helpRow) { + showHelpAlert(); + } else if (position == languageRow) { + presentFragment(new LanguageSelectActivity()); + } else if (position == usernameRow) { + presentFragment(new ChangeUsernameActivity()); + } else if (position == bioRow) { + if (userInfo != null) { + presentFragment(new ChangeBioActivity()); } - TextCell textCell = new TextCell(context); - String text; - switch (a) { - case 0: - text = LocaleController.getString("AskAQuestion", R.string.AskAQuestion); - break; - case 1: - text = LocaleController.getString("TelegramFAQ", R.string.TelegramFAQ); - break; - case 2: - text = LocaleController.getString("PrivacyPolicy", R.string.PrivacyPolicy); - break; - case 3: - text = LocaleController.getString("DebugSendLogs", R.string.DebugSendLogs); - break; - case 4: - text = LocaleController.getString("DebugClearLogs", R.string.DebugClearLogs); - break; - case 5: - default: - text = "Switch Backend"; - break; - } - textCell.setText(text, BuildVars.LOGS_ENABLED || BuildVars.DEBUG_VERSION ? a != count - 1 : a != 2); - textCell.setTag(a); - textCell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); - linearLayoutInviteContainer.addView(textCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - textCell.setOnClickListener(v2 -> { - Integer tag = (Integer) v2.getTag(); - switch (tag) { - case 0: { - showDialog(AlertsCreator.createSupportAlert(SettingsActivity.this)); - break; - } - case 1: - Browser.openUrl(getParentActivity(), LocaleController.getString("TelegramFaqUrl", R.string.TelegramFaqUrl)); - break; - case 2: - Browser.openUrl(getParentActivity(), LocaleController.getString("PrivacyPolicyUrl", R.string.PrivacyPolicyUrl)); - break; - case 3: - sendLogs(); - break; - case 4: - FileLog.cleanupLogs(); - break; - case 5: { - if (getParentActivity() == null) { - return; - } - AlertDialog.Builder builder1 = new AlertDialog.Builder(getParentActivity()); - builder1.setMessage(LocaleController.getString("AreYouSure", R.string.AreYouSure)); - builder1.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder1.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> { - SharedConfig.pushAuthKey = null; - SharedConfig.pushAuthKeyId = null; - SharedConfig.saveConfig(); - ConnectionsManager.getInstance(currentAccount).switchBackend(); - }); - builder1.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - showDialog(builder1.create()); - break; - } + } else if (position == numberRow) { + presentFragment(new ChangePhoneHelpActivity()); + } + } else { + if (position < 0) { + return; + } + Object object = numberRow; + if (searchAdapter.searchWas) { + if (position < searchAdapter.searchResults.size()) { + object = searchAdapter.searchResults.get(position); + } else { + position -= searchAdapter.searchResults.size() + 1; + if (position >= 0 && position < searchAdapter.faqSearchResults.size()) { + object = searchAdapter.faqSearchResults.get(position); } - builder.getDismissRunnable().run(); - }); + } + } else { + position--; + if (position < 0) { + return; + } + if (position < searchAdapter.recentSearches.size()) { + object = searchAdapter.recentSearches.get(position); + } } - builder.setCustomView(linearLayout); - showDialog(builder.create()); - } else if (position == languageRow) { - presentFragment(new LanguageSelectActivity()); - } else if (position == usernameRow) { - presentFragment(new ChangeUsernameActivity()); - } else if (position == bioRow) { - if (userInfo != null) { - presentFragment(new ChangeBioActivity()); + if (object instanceof SearchAdapter.SearchResult) { + SearchAdapter.SearchResult result = (SearchAdapter.SearchResult) object; + result.open(); + } else if (object instanceof SearchAdapter.FaqSearchResult) { + SearchAdapter.FaqSearchResult result = (SearchAdapter.FaqSearchResult) object; + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.openArticle, searchAdapter.faqWebPage, result.url); + } + if (object != null) { + searchAdapter.addRecent(object); } - } else if (position == numberRow) { - presentFragment(new ChangePhoneHelpActivity()); } }); @@ -438,6 +452,15 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter @Override public boolean onItemClick(View view, int position) { + if (listView.getAdapter() == searchAdapter) { + 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) -> searchAdapter.clearRecent()); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + showDialog(builder.create()); + return true; + } if (position == versionRow) { pressCount++; if (pressCount >= 2 || BuildVars.DEBUG_PRIVATE_VERSION) { @@ -454,7 +477,8 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter LocaleController.getString("DebugMenuClearMediaCache", R.string.DebugMenuClearMediaCache), LocaleController.getString("DebugMenuCallSettings", R.string.DebugMenuCallSettings), null, - BuildVars.DEBUG_PRIVATE_VERSION ? "Check for app updates" : null + BuildVars.DEBUG_PRIVATE_VERSION ? "Check for app updates" : null, + LocaleController.getString("DebugMenuReadAllDialogs", R.string.DebugMenuReadAllDialogs), }; builder.setItems(items, (dialog, which) -> { if (which == 0) { @@ -475,14 +499,17 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter SharedConfig.toggleInappCamera(); } else if (which == 6) { MessagesStorage.getInstance(currentAccount).clearSentMedia(); - SharedPreferences.Editor editor = MessagesController.getGlobalMainSettings().edit(); SharedConfig.setNoSoundHintShowed(false); + SharedPreferences.Editor editor = MessagesController.getGlobalMainSettings().edit(); + editor.remove("archivehint").remove("archivehint_l").remove("gifhint").remove("soundHint").commit(); } else if (which == 7) { VoIPHelper.showCallDebugSettings(getParentActivity()); } else if (which == 8) { SharedConfig.toggleRoundCamera16to9(); } else if (which == 9) { ((LaunchActivity) getParentActivity()).checkAppUpdate(true); + } else if (which == 10) { + MessagesStorage.getInstance(currentAccount).readAllDialogs(); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); @@ -500,6 +527,13 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } }); + emptyView = new EmptyTextProgressView(context); + emptyView.showTextView(); + emptyView.setTextSize(18); + emptyView.setVisibility(View.GONE); + emptyView.setShowAtCenter(true); + frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + frameLayout.addView(actionBar); extraHeightView = new View(context); @@ -514,7 +548,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter avatarContainer = new FrameLayout(context); avatarContainer.setPivotX(LocaleController.isRTL ? AndroidUtilities.dp(42) : 0); avatarContainer.setPivotY(0); - frameLayout.addView(avatarContainer, LayoutHelper.createFrame(42, 42, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), (LocaleController.isRTL ? 0 : 64), 0, (LocaleController.isRTL ? 64 : 0), 0)); + frameLayout.addView(avatarContainer, LayoutHelper.createFrame(42, 42, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), (LocaleController.isRTL ? 0 : 64), 0, (LocaleController.isRTL ? 112 : 0), 0)); avatarContainer.setOnClickListener(v -> { if (avatar != null) { return; @@ -522,12 +556,16 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(UserConfig.getInstance(currentAccount).getClientUserId()); if (user != null && user.photo != null && user.photo.photo_big != null) { PhotoViewer.getInstance().setParentActivity(getParentActivity()); + if (user.photo.dc_id != 0) { + user.photo.photo_big.dc_id = user.photo.dc_id; + } PhotoViewer.getInstance().openPhoto(user.photo.photo_big, provider); } }); avatarImage = new BackupImageView(context); avatarImage.setRoundRadius(AndroidUtilities.dp(21)); + avatarImage.setContentDescription(LocaleController.getString("AccDescrProfilePicture", R.string.AccDescrProfilePicture)); avatarContainer.addView(avatarImage, LayoutHelper.createFrame(42, 42)); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -565,7 +603,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter nameTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); nameTextView.setPivotY(0); - frameLayout.addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 48 : 118, 0, LocaleController.isRTL ? 118 : 48, 0)); + frameLayout.addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 48 : 118, 0, LocaleController.isRTL ? 166 : 96, 0)); onlineTextView = new TextView(context); onlineTextView.setTextColor(Theme.getColor(Theme.key_avatar_subtitleInProfileBlue)); @@ -575,7 +613,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter onlineTextView.setSingleLine(true); onlineTextView.setEllipsize(TextUtils.TruncateAt.END); onlineTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - frameLayout.addView(onlineTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 48 : 118, 0, LocaleController.isRTL ? 118 : 48, 0)); + frameLayout.addView(onlineTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 48 : 118, 0, LocaleController.isRTL ? 166 : 96, 0)); writeButton = new ImageView(context); Drawable drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), Theme.getColor(Theme.key_profile_actionBackground), Theme.getColor(Theme.key_profile_actionPressedBackground)); @@ -614,6 +652,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } imageUpdater.openMenu(user.photo != null && user.photo.photo_big != null && !(user.photo instanceof TLRPC.TL_userProfilePhotoEmpty), () -> MessagesController.getInstance(currentAccount).deleteUserPhoto(null)); }); + writeButton.setContentDescription(LocaleController.getString("AccDescrChangeProfilePicture", R.string.AccDescrChangeProfilePicture)); if (scrollTo != -1) { layoutManager.scrollToPositionWithOffset(scrollTo, scrollToPosition); @@ -630,6 +669,16 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter needLayout(); listView.setOnScrollListener(new RecyclerView.OnScrollListener() { + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { + if (listView.getAdapter() == searchAdapter) { + AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); + } + } + } + @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (layoutManager.getItemCount() == 0) { @@ -637,7 +686,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } int height = 0; View child = recyclerView.getChildAt(0); - if (child != null) { + if (child != null && avatarContainer.getVisibility() == View.VISIBLE) { if (layoutManager.findFirstVisibleItemPosition() == 0) { height = AndroidUtilities.dp(88) + (child.getTop() < 0 ? child.getTop() : 0); } @@ -692,7 +741,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter src.renameTo(destFile); String oldKey = avatar.volume_id + "_" + avatar.local_id + "@50_50"; String newKey = small.location.volume_id + "_" + small.location.local_id + "@50_50"; - ImageLoader.getInstance().replaceImageInCache(oldKey, newKey, small.location, true); + ImageLoader.getInstance().replaceImageInCache(oldKey, newKey, ImageLocation.getForUser(user, false), true); } if (big != null && avatarBig != null) { File destFile = FileLoader.getPathToAttach(big, true); @@ -719,7 +768,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } else { avatar = smallSize.location; avatarBig = bigSize.location; - avatarImage.setImage(avatar, "50_50", avatarDrawable, null); + avatarImage.setImage(ImageLocation.getForLocal(avatar), "50_50", avatarDrawable, null); showAvatarProgress(true, false); } }); @@ -800,7 +849,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } else if (id == NotificationCenter.userInfoDidLoad) { Integer uid = (Integer) args[0]; if (uid == UserConfig.getInstance(currentAccount).getClientUserId() && listAdapter != null) { - userInfo = (TLRPC.TL_userFull) args[1]; + userInfo = (TLRPC.UserFull) args[1]; listAdapter.notifyItemChanged(bioRow); } } else if (id == NotificationCenter.emojiDidLoad) { @@ -818,6 +867,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } updateUserData(); fixLayout(); + setParentActivityTitle(LocaleController.getString("Settings", R.string.Settings)); } @Override @@ -836,14 +886,26 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter listView.setLayoutParams(layoutParams); extraHeightView.setTranslationY(newTop); } + layoutParams = (FrameLayout.LayoutParams) emptyView.getLayoutParams(); + if (layoutParams.topMargin != newTop) { + layoutParams.topMargin = newTop; + emptyView.setLayoutParams(layoutParams); + } } if (avatarContainer != null) { - float diff = extraHeight / (float) AndroidUtilities.dp(88); - extraHeightView.setScaleY(diff); - shadowView.setTranslationY(newTop + extraHeight); + int currentExtraHeight; + if (avatarContainer.getVisibility() == View.VISIBLE) { + currentExtraHeight = extraHeight; + } else { + currentExtraHeight = 0; + } - writeButton.setTranslationY((actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() + extraHeight - AndroidUtilities.dp(29.5f)); + float diff = currentExtraHeight / (float) AndroidUtilities.dp(88); + extraHeightView.setScaleY(diff); + shadowView.setTranslationY(newTop + currentExtraHeight); + + writeButton.setTranslationY((actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() + currentExtraHeight - AndroidUtilities.dp(29.5f)); final boolean setVisible = diff > 0.2f; boolean currentVisible = writeButton.getTag() == null; @@ -895,14 +957,14 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter float avatarY = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() / 2.0f * (1.0f + diff) - 21 * AndroidUtilities.density + 27 * AndroidUtilities.density * diff; avatarContainer.setTranslationY((float) Math.ceil(avatarY)); nameTextView.setTranslationY((float) Math.floor(avatarY) - (float) Math.ceil(AndroidUtilities.density) + (float) Math.floor(7 * AndroidUtilities.density * diff)); - onlineTextView.setTranslationY((float) Math.floor(avatarY) + AndroidUtilities.dp(22) + (float )Math.floor(11 * AndroidUtilities.density) * diff); + onlineTextView.setTranslationY((float) Math.floor(avatarY) + AndroidUtilities.dp(22) + (float) Math.floor(11 * AndroidUtilities.density) * diff); nameTextView.setScaleX(1.0f + 0.12f * diff); nameTextView.setScaleY(1.0f + 0.12f * diff); if (LocaleController.isRTL) { - avatarContainer.setTranslationX(AndroidUtilities.dp(47) * diff); - nameTextView.setTranslationX(21 * AndroidUtilities.density * diff); - onlineTextView.setTranslationX(21 * AndroidUtilities.density * diff); + avatarContainer.setTranslationX(AndroidUtilities.dp(47 + 48) * diff); + nameTextView.setTranslationX((21 + 48) * AndroidUtilities.density * diff); + onlineTextView.setTranslationX((21 + 48) * AndroidUtilities.density * diff); } else { avatarContainer.setTranslationX(-AndroidUtilities.dp(47) * diff); nameTextView.setTranslationX(-21 * AndroidUtilities.density * diff); @@ -932,17 +994,15 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter if (user == null) { return; } - TLRPC.FileLocation photo = null; TLRPC.FileLocation photoBig = null; if (user.photo != null) { - photo = user.photo.photo_small; photoBig = user.photo.photo_big; } avatarDrawable = new AvatarDrawable(user, true); avatarDrawable.setColor(Theme.getColor(Theme.key_avatar_backgroundInProfileBlue)); if (avatarImage != null) { - avatarImage.setImage(photo, "50_50", avatarDrawable, user); + avatarImage.setImage(ImageLocation.getForUser(user, false), "50_50", avatarDrawable, user); avatarImage.getImageReceiver().setVisible(!PhotoViewer.isShowingImage(photoBig), false); nameTextView.setText(UserObject.getUserName(user)); @@ -952,6 +1012,102 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } } + private void showHelpAlert() { + if (getParentActivity() == null) { + return; + } + Context context = getParentActivity(); + BottomSheet.Builder builder = new BottomSheet.Builder(context); + builder.setApplyTopPadding(false); + + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.VERTICAL); + + HeaderCell headerCell = new HeaderCell(context, true, 23, 15, false); + headerCell.setHeight(47); + headerCell.setText(LocaleController.getString("SettingsHelp", R.string.SettingsHelp)); + linearLayout.addView(headerCell); + + LinearLayout linearLayoutInviteContainer = new LinearLayout(context); + linearLayoutInviteContainer.setOrientation(LinearLayout.VERTICAL); + linearLayout.addView(linearLayoutInviteContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + int count = 6; + for (int a = 0; a < count; a++) { + if (a >= 3 && a <= 4 && !BuildVars.LOGS_ENABLED || a == 5 && !BuildVars.DEBUG_VERSION) { + continue; + } + TextCell textCell = new TextCell(context); + String text; + switch (a) { + case 0: + text = LocaleController.getString("AskAQuestion", R.string.AskAQuestion); + break; + case 1: + text = LocaleController.getString("TelegramFAQ", R.string.TelegramFAQ); + break; + case 2: + text = LocaleController.getString("PrivacyPolicy", R.string.PrivacyPolicy); + break; + case 3: + text = LocaleController.getString("DebugSendLogs", R.string.DebugSendLogs); + break; + case 4: + text = LocaleController.getString("DebugClearLogs", R.string.DebugClearLogs); + break; + case 5: + default: + text = "Switch Backend"; + break; + } + textCell.setText(text, BuildVars.LOGS_ENABLED || BuildVars.DEBUG_VERSION ? a != count - 1 : a != 2); + textCell.setTag(a); + textCell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); + linearLayoutInviteContainer.addView(textCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + textCell.setOnClickListener(v2 -> { + Integer tag = (Integer) v2.getTag(); + switch (tag) { + case 0: { + showDialog(AlertsCreator.createSupportAlert(SettingsActivity.this)); + break; + } + case 1: + Browser.openUrl(getParentActivity(), LocaleController.getString("TelegramFaqUrl", R.string.TelegramFaqUrl)); + break; + case 2: + Browser.openUrl(getParentActivity(), LocaleController.getString("PrivacyPolicyUrl", R.string.PrivacyPolicyUrl)); + break; + case 3: + sendLogs(); + break; + case 4: + FileLog.cleanupLogs(); + break; + case 5: { + if (getParentActivity() == null) { + return; + } + AlertDialog.Builder builder1 = new AlertDialog.Builder(getParentActivity()); + builder1.setMessage(LocaleController.getString("AreYouSure", R.string.AreYouSure)); + builder1.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder1.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> { + SharedConfig.pushAuthKey = null; + SharedConfig.pushAuthKeyId = null; + SharedConfig.saveConfig(); + ConnectionsManager.getInstance(currentAccount).switchBackend(); + }); + builder1.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + showDialog(builder1.create()); + break; + } + } + builder.getDismissRunnable().run(); + }); + } + builder.setCustomView(linearLayout); + showDialog(builder.create()); + } + private void sendLogs() { if (getParentActivity() == null) { return; @@ -978,7 +1134,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter try { FileOutputStream dest = new FileOutputStream(zipFile); out = new ZipOutputStream(new BufferedOutputStream(dest)); - byte data[] = new byte[1024 * 64]; + byte[] data = new byte[1024 * 64]; for (int i = 0; i < files.length; i++) { FileInputStream fi = new FileInputStream(files[i]); @@ -1040,6 +1196,609 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter }); } + private class SearchAdapter extends RecyclerListView.SelectionAdapter { + + private class SearchResult { + + private String searchTitle; + private Runnable openRunnable; + private String rowName; + private String[] path; + private int iconResId; + private int guid; + private int num; + + public SearchResult(int g, String search, int icon, Runnable open) { + this(g, search, null, null, null, icon, open); + } + + public SearchResult(int g, String search, String pathArg1, int icon, Runnable open) { + this(g, search, null, pathArg1, null, icon, open); + } + + public SearchResult(int g, String search, String row, String pathArg1, int icon, Runnable open) { + this(g, search, row, pathArg1, null, icon, open); + } + + public SearchResult(int g, String search, String row, String pathArg1, String pathArg2, int icon, Runnable open) { + guid = g; + searchTitle = search; + rowName = row; + openRunnable = open; + iconResId = icon; + if (pathArg1 != null && pathArg2 != null) { + path = new String[]{pathArg1, pathArg2}; + } else if (pathArg1 != null) { + path = new String[]{pathArg1}; + } + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof SearchResult)) { + return false; + } + SearchResult result = (SearchResult) obj; + return guid == result.guid; + } + + @Override + public String toString() { + SerializedData data = new SerializedData(); + data.writeInt32(num); + data.writeInt32(1); + data.writeInt32(guid); + return Utilities.bytesToHex(data.toByteArray()); + } + + private void open() { + openRunnable.run(); + if (rowName != null) { + + BaseFragment openingFragment = parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 1); + try { + Field listViewField = openingFragment.getClass().getDeclaredField("listView"); + listViewField.setAccessible(true); + RecyclerListView.IntReturnCallback callback = () -> { + int position = -1; + try { + Field rowField = openingFragment.getClass().getDeclaredField(rowName); + Field linearLayoutField = openingFragment.getClass().getDeclaredField("layoutManager"); + rowField.setAccessible(true); + linearLayoutField.setAccessible(true); + LinearLayoutManager layoutManager = (LinearLayoutManager) linearLayoutField.get(openingFragment); + position = rowField.getInt(openingFragment); + layoutManager.scrollToPositionWithOffset(position, 0); + rowField.setAccessible(false); + linearLayoutField.setAccessible(false); + return position; + } catch (Throwable ignore) { + + } + return position; + }; + RecyclerListView listView = (RecyclerListView) listViewField.get(openingFragment); + listView.highlightRow(callback); + listViewField.setAccessible(false); + } catch (Throwable ignore) { + + } + } + } + } + + private class FaqSearchResult { + + private String title; + private String[] path; + private String url; + private int num; + + public FaqSearchResult(String t, String[] p, String u) { + title = t; + path = p; + url = u; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof FaqSearchResult)) { + return false; + } + FaqSearchResult result = (FaqSearchResult) obj; + return title.equals(result.title); + } + + @Override + public String toString() { + SerializedData data = new SerializedData(); + data.writeInt32(num); + data.writeInt32(0); + data.writeString(title); + data.writeInt32(path != null ? path.length : 0); + if (path != null) { + for (int a = 0; a < path.length; a++) { + data.writeString(path[a]); + } + } + data.writeString(url); + return Utilities.bytesToHex(data.toByteArray()); + } + } + + private SearchResult[] searchArray = new SearchResult[]{ + new SearchResult(500, LocaleController.getString("EditName", R.string.EditName), 0, () -> presentFragment(new ChangeNameActivity())), + new SearchResult(501, LocaleController.getString("ChangePhoneNumber", R.string.ChangePhoneNumber), 0, () -> presentFragment(new ChangePhoneHelpActivity())), + new SearchResult(502, LocaleController.getString("AddAnotherAccount", R.string.AddAnotherAccount), 0, () -> { + int freeAccount = -1; + for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { + if (!UserConfig.getInstance(a).isClientActivated()) { + freeAccount = a; + break; + } + } + if (freeAccount >= 0) { + presentFragment(new LoginActivity(freeAccount)); + } + }), + new SearchResult(503, LocaleController.getString("UserBio", R.string.UserBio), 0, () -> { + if (userInfo != null) { + presentFragment(new ChangeBioActivity()); + } + }), + + new SearchResult(1, LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsSettingsActivity())), + new SearchResult(2, LocaleController.getString("NotificationsPrivateChats", R.string.NotificationsPrivateChats), LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsCustomSettingsActivity(NotificationsController.TYPE_PRIVATE, new ArrayList<>(), true))), + new SearchResult(3, LocaleController.getString("NotificationsGroups", R.string.NotificationsGroups), LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsCustomSettingsActivity(NotificationsController.TYPE_GROUP, new ArrayList<>(), true))), + new SearchResult(4, LocaleController.getString("NotificationsChannels", R.string.NotificationsChannels), LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsCustomSettingsActivity(NotificationsController.TYPE_CHANNEL, new ArrayList<>(), true))), + new SearchResult(5, LocaleController.getString("VoipNotificationSettings", R.string.VoipNotificationSettings), "callsSectionRow", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsSettingsActivity())), + new SearchResult(6, LocaleController.getString("BadgeNumber", R.string.BadgeNumber), "badgeNumberSection", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsSettingsActivity())), + new SearchResult(7, LocaleController.getString("InAppNotifications", R.string.InAppNotifications), "inappSectionRow", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsSettingsActivity())), + new SearchResult(8, LocaleController.getString("ContactJoined", R.string.ContactJoined), "contactJoinedRow", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsSettingsActivity())), + new SearchResult(9, LocaleController.getString("PinnedMessages", R.string.PinnedMessages), "pinnedMessageRow", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsSettingsActivity())), + new SearchResult(10, LocaleController.getString("ResetAllNotifications", R.string.ResetAllNotifications), "resetNotificationsRow", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsSettingsActivity())), + + new SearchResult(100, LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), + new SearchResult(101, LocaleController.getString("BlockedUsers", R.string.BlockedUsers), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new BlockedUsersActivity())), + new SearchResult(102, LocaleController.getString("PrivacyLastSeen", R.string.PrivacyLastSeen), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacyControlActivity(0, true))), + new SearchResult(103, LocaleController.getString("PrivacyProfilePhoto", R.string.PrivacyProfilePhoto), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacyControlActivity(4, true))), + new SearchResult(104, LocaleController.getString("PrivacyForwards", R.string.PrivacyForwards), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacyControlActivity(5, true))), + new SearchResult(105, LocaleController.getString("PrivacyP2P", R.string.PrivacyP2P), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacyControlActivity(3, true))), + new SearchResult(106, LocaleController.getString("Calls", R.string.Calls), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacyControlActivity(2, true))), + new SearchResult(107, LocaleController.getString("GroupsAndChannels", R.string.GroupsAndChannels), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacyControlActivity(1, true))), + new SearchResult(108, LocaleController.getString("Passcode", R.string.Passcode), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PasscodeActivity(SharedConfig.passcodeHash.length() > 0 ? 2 : 0))), + new SearchResult(109, LocaleController.getString("TwoStepVerification", R.string.TwoStepVerification), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new TwoStepVerificationActivity(0))), + new SearchResult(110, LocaleController.getString("SessionsTitle", R.string.SessionsTitle), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new SessionsActivity(0))), + new SearchResult(111, LocaleController.getString("PrivacyDeleteCloudDrafts", R.string.PrivacyDeleteCloudDrafts), "clearDraftsRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), + new SearchResult(112, LocaleController.getString("DeleteAccountIfAwayFor2", R.string.DeleteAccountIfAwayFor2), "deleteAccountRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), + new SearchResult(113, LocaleController.getString("PrivacyPaymentsClear", R.string.PrivacyPaymentsClear), "paymentsClearRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), + new SearchResult(114, LocaleController.getString("WebSessionsTitle", R.string.WebSessionsTitle), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new SessionsActivity(1))), + new SearchResult(115, LocaleController.getString("SyncContactsDelete", R.string.SyncContactsDelete), "contactsDeleteRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), + new SearchResult(116, LocaleController.getString("SyncContacts", R.string.SyncContacts), "contactsSyncRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), + new SearchResult(117, LocaleController.getString("SuggestContacts", R.string.SuggestContacts), "contactsSuggestRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), + new SearchResult(118, LocaleController.getString("MapPreviewProvider", R.string.MapPreviewProvider), "secretMapRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), + new SearchResult(119, LocaleController.getString("SecretWebPage", R.string.SecretWebPage), "secretWebpageRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), + + new SearchResult(200, LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(201, LocaleController.getString("DataUsage", R.string.DataUsage), "usageSectionRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(202, LocaleController.getString("StorageUsage", R.string.StorageUsage), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new CacheControlActivity())), + new SearchResult(203, LocaleController.getString("KeepMedia", R.string.KeepMedia), "keepMediaRow", LocaleController.getString("DataSettings", R.string.DataSettings), LocaleController.getString("StorageUsage", R.string.StorageUsage), R.drawable.menu_data, () -> presentFragment(new CacheControlActivity())), + new SearchResult(204, LocaleController.getString("ClearMediaCache", R.string.ClearMediaCache), "cacheRow", LocaleController.getString("DataSettings", R.string.DataSettings), LocaleController.getString("StorageUsage", R.string.StorageUsage), R.drawable.menu_data, () -> presentFragment(new CacheControlActivity())), + new SearchResult(205, LocaleController.getString("LocalDatabase", R.string.LocalDatabase), "databaseRow", LocaleController.getString("DataSettings", R.string.DataSettings), LocaleController.getString("StorageUsage", R.string.StorageUsage), R.drawable.menu_data, () -> presentFragment(new CacheControlActivity())), + new SearchResult(206, LocaleController.getString("NetworkUsage", R.string.NetworkUsage), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataUsageActivity())), + new SearchResult(207, LocaleController.getString("AutomaticMediaDownload", R.string.AutomaticMediaDownload), "mediaDownloadSectionRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(208, LocaleController.getString("WhenUsingMobileData", R.string.WhenUsingMobileData), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataAutoDownloadActivity(0))), + new SearchResult(209, LocaleController.getString("WhenConnectedOnWiFi", R.string.WhenConnectedOnWiFi), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataAutoDownloadActivity(1))), + new SearchResult(210, LocaleController.getString("WhenRoaming", R.string.WhenRoaming), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataAutoDownloadActivity(2))), + new SearchResult(211, LocaleController.getString("ResetAutomaticMediaDownload", R.string.ResetAutomaticMediaDownload), "resetDownloadRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(212, LocaleController.getString("AutoplayMedia", R.string.AutoplayMedia), "autoplayHeaderRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(213, LocaleController.getString("AutoplayGIF", R.string.AutoplayGIF), "autoplayGifsRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(214, LocaleController.getString("AutoplayVideo", R.string.AutoplayVideo), "autoplayVideoRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(215, LocaleController.getString("Streaming", R.string.Streaming), "streamSectionRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(216, LocaleController.getString("EnableStreaming", R.string.EnableStreaming), "enableStreamRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(217, LocaleController.getString("Calls", R.string.Calls), "callsSectionRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(218, LocaleController.getString("VoipUseLessData", R.string.VoipUseLessData), "useLessDataForCallsRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(219, LocaleController.getString("VoipQuickReplies", R.string.VoipQuickReplies), "quickRepliesRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(220, LocaleController.getString("ProxySettings", R.string.ProxySettings), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new ProxyListActivity())), + new SearchResult(221, LocaleController.getString("UseProxyForCalls", R.string.UseProxyForCalls), "callsRow", LocaleController.getString("DataSettings", R.string.DataSettings), LocaleController.getString("ProxySettings", R.string.ProxySettings), R.drawable.menu_data, () -> presentFragment(new ProxyListActivity())), + + new SearchResult(300, LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(301, LocaleController.getString("TextSizeHeader", R.string.TextSizeHeader), "textSizeHeaderRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(302, LocaleController.getString("ChatBackground", R.string.ChatBackground), LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new WallpapersListActivity(WallpapersListActivity.TYPE_ALL))), + new SearchResult(303, LocaleController.getString("SetColor", R.string.SetColor), null, LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("ChatBackground", R.string.ChatBackground), R.drawable.menu_chats, () -> presentFragment(new WallpapersListActivity(WallpapersListActivity.TYPE_COLOR))), + new SearchResult(304, LocaleController.getString("ResetChatBackgrounds", R.string.ResetChatBackgrounds), "resetRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("ChatBackground", R.string.ChatBackground), R.drawable.menu_chats, () -> presentFragment(new WallpapersListActivity(WallpapersListActivity.TYPE_ALL))), + new SearchResult(305, LocaleController.getString("AutoNightTheme", R.string.AutoNightTheme), LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_NIGHT))), + new SearchResult(306, LocaleController.getString("ColorTheme", R.string.ColorTheme), "themeHeaderRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(307, LocaleController.getString("ChromeCustomTabs", R.string.ChromeCustomTabs), "customTabsRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(308, LocaleController.getString("DirectShare", R.string.DirectShare), "directShareRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(309, LocaleController.getString("EnableAnimations", R.string.EnableAnimations), "enableAnimationsRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(310, LocaleController.getString("RaiseToSpeak", R.string.RaiseToSpeak), "raiseToSpeakRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(311, LocaleController.getString("SendByEnter", R.string.SendByEnter), "sendByEnterRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(312, LocaleController.getString("SaveToGallerySettings", R.string.SaveToGallerySettings), "saveToGalleryRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(313, LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new StickersActivity(DataQuery.TYPE_IMAGE))), + new SearchResult(314, LocaleController.getString("SuggestStickers", R.string.SuggestStickers), "suggestRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), R.drawable.menu_chats, () -> presentFragment(new StickersActivity(DataQuery.TYPE_IMAGE))), + new SearchResult(315, LocaleController.getString("FeaturedStickers", R.string.FeaturedStickers), null, LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), R.drawable.menu_chats, () -> presentFragment(new FeaturedStickersActivity())), + new SearchResult(316, LocaleController.getString("Masks", R.string.Masks), null, LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), R.drawable.menu_chats, () -> presentFragment(new StickersActivity(DataQuery.TYPE_MASK))), + new SearchResult(317, LocaleController.getString("ArchivedStickers", R.string.ArchivedStickers), null, LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), R.drawable.menu_chats, () -> presentFragment(new ArchivedStickersActivity(DataQuery.TYPE_IMAGE))), + new SearchResult(317, LocaleController.getString("ArchivedMasks", R.string.ArchivedMasks), null, LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), R.drawable.menu_chats, () -> presentFragment(new ArchivedStickersActivity(DataQuery.TYPE_MASK))), + + new SearchResult(400, LocaleController.getString("Language", R.string.Language), R.drawable.menu_language, () -> presentFragment(new LanguageSelectActivity())), + + new SearchResult(401, LocaleController.getString("SettingsHelp", R.string.SettingsHelp), R.drawable.menu_help, SettingsActivity.this::showHelpAlert), + new SearchResult(402, LocaleController.getString("AskAQuestion", R.string.AskAQuestion), LocaleController.getString("SettingsHelp", R.string.SettingsHelp), R.drawable.menu_help, () -> showDialog(AlertsCreator.createSupportAlert(SettingsActivity.this))), + new SearchResult(403, LocaleController.getString("TelegramFAQ", R.string.TelegramFAQ), LocaleController.getString("SettingsHelp", R.string.SettingsHelp), R.drawable.menu_help, () -> Browser.openUrl(getParentActivity(), LocaleController.getString("TelegramFaqUrl", R.string.TelegramFaqUrl))), + new SearchResult(404, LocaleController.getString("PrivacyPolicy", R.string.PrivacyPolicy), LocaleController.getString("SettingsHelp", R.string.SettingsHelp), R.drawable.menu_help, () -> Browser.openUrl(getParentActivity(), LocaleController.getString("PrivacyPolicyUrl", R.string.PrivacyPolicyUrl))), + }; + private ArrayList faqSearchArray = new ArrayList<>(); + + private Context mContext; + private ArrayList resultNames = new ArrayList<>(); + private ArrayList searchResults = new ArrayList<>(); + private ArrayList faqSearchResults = new ArrayList<>(); + private ArrayList recentSearches = new ArrayList<>(); + private boolean searchWas; + private Runnable searchRunnable; + private String lastSearchString; + private TLRPC.WebPage faqWebPage; + private boolean loadingFaqPage; + + public SearchAdapter(Context context) { + mContext = context; + + HashMap resultHashMap = new HashMap<>(); + for (int a = 0; a < searchArray.length; a++) { + resultHashMap.put(searchArray[a].guid, searchArray[a]); + } + Set set = MessagesController.getGlobalMainSettings().getStringSet("settingsSearchRecent2", null); + if (set != null) { + for (String value : set) { + try { + SerializedData data = new SerializedData(Utilities.hexToBytes(value)); + int num = data.readInt32(false); + int type = data.readInt32(false); + if (type == 0) { + String title = data.readString(false); + int count = data.readInt32(false); + String[] path = null; + if (count > 0) { + path = new String[count]; + for (int a = 0; a < count; a++) { + path[a] = data.readString(false); + } + } + String url = data.readString(false); + FaqSearchResult result = new FaqSearchResult(title, path, url); + result.num = num; + recentSearches.add(result); + } else if (type == 1) { + SearchResult result = resultHashMap.get(data.readInt32(false)); + if (result != null) { + result.num = num; + recentSearches.add(result); + } + } + } catch (Exception ignore) { + + } + } + } + Collections.sort(recentSearches, (o1, o2) -> { + int n1 = getNum(o1); + int n2 = getNum(o2); + if (n1 < n2) { + return -1; + } else if (n1 > n2) { + return 1; + } + return 0; + }); + } + + private void loadFaqWebPage() { + if (faqWebPage != null || loadingFaqPage) { + return; + } + loadingFaqPage = true; + final TLRPC.TL_messages_getWebPage req2 = new TLRPC.TL_messages_getWebPage(); + req2.url = LocaleController.getString("TelegramFaqUrl", R.string.TelegramFaqUrl); + req2.hash = 0; + ConnectionsManager.getInstance(currentAccount).sendRequest(req2, (response2, error2) -> { + if (response2 instanceof TLRPC.WebPage) { + TLRPC.WebPage page = (TLRPC.WebPage) response2; + if (page.cached_page != null) { + for (int a = 0, N = page.cached_page.blocks.size(); a < N; a++) { + TLRPC.PageBlock block = page.cached_page.blocks.get(a); + if (block instanceof TLRPC.TL_pageBlockList) { + String paragraph = null; + if (a != 0) { + TLRPC.PageBlock prevBlock = page.cached_page.blocks.get(a - 1); + if (prevBlock instanceof TLRPC.TL_pageBlockParagraph) { + TLRPC.TL_pageBlockParagraph pageBlockParagraph = (TLRPC.TL_pageBlockParagraph) prevBlock; + paragraph = ArticleViewer.getPlainText(pageBlockParagraph.text).toString(); + } + } + TLRPC.TL_pageBlockList list = (TLRPC.TL_pageBlockList) block; + for (int b = 0, N2 = list.items.size(); b < N2; b++) { + TLRPC.PageListItem item = list.items.get(b); + if (item instanceof TLRPC.TL_pageListItemText) { + TLRPC.TL_pageListItemText itemText = (TLRPC.TL_pageListItemText) item; + String url = ArticleViewer.getUrl(itemText.text); + String text = ArticleViewer.getPlainText(itemText.text).toString(); + if (TextUtils.isEmpty(url) || TextUtils.isEmpty(text)) { + continue; + } + String[] path; + if (paragraph != null) { + path = new String[]{LocaleController.getString("SettingsSearchFaq", R.string.SettingsSearchFaq), paragraph}; + } else { + path = new String[]{LocaleController.getString("SettingsSearchFaq", R.string.SettingsSearchFaq)}; + } + faqSearchArray.add(new FaqSearchResult(text, path, url)); + } + } + } else if (block instanceof TLRPC.TL_pageBlockAnchor) { + break; + } + } + faqWebPage = page; + } + } + loadingFaqPage = false; + }); + } + + @Override + public int getItemCount() { + if (searchWas) { + return searchResults.size() + (faqSearchResults.isEmpty() ? 0 : 1 + faqSearchResults.size()); + } + return (recentSearches.isEmpty() ? 0 : recentSearches.size() + 1); + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return holder.getItemViewType() == 0; + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + switch (holder.getItemViewType()) { + case 0: { + SettingsSearchCell searchCell = (SettingsSearchCell) holder.itemView; + if (searchWas) { + if (position < searchResults.size()) { + SearchResult result = searchResults.get(position); + SearchResult prevResult = position > 0 ? searchResults.get(position - 1) : null; + int icon; + if (prevResult != null && prevResult.iconResId == result.iconResId) { + icon = 0; + } else { + icon = result.iconResId; + } + searchCell.setTextAndValueAndIcon(resultNames.get(position), result.path, icon, position < searchResults.size() - 1); + } else { + position -= searchResults.size() + 1; + FaqSearchResult result = faqSearchResults.get(position); + searchCell.setTextAndValue(resultNames.get(position + searchResults.size()), result.path, true, position < searchResults.size() - 1); + } + } else { + position--; + Object object = recentSearches.get(position); + if (object instanceof SearchResult) { + SearchResult result = (SearchResult) object; + searchCell.setTextAndValue(result.searchTitle, result.path, false, position < recentSearches.size() - 1); + } else if (object instanceof FaqSearchResult) { + FaqSearchResult result = (FaqSearchResult) object; + searchCell.setTextAndValue(result.title, result.path, true, position < recentSearches.size() - 1); + } + } + break; + } + case 1: { + GraySectionCell sectionCell = (GraySectionCell) holder.itemView; + sectionCell.setText(LocaleController.getString("SettingsFaqSearchTitle", R.string.SettingsFaqSearchTitle)); + break; + } + case 2: { + HeaderCell headerCell = (HeaderCell) holder.itemView; + headerCell.setText(LocaleController.getString("SettingsRecent", R.string.SettingsRecent)); + break; + } + } + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view; + switch (viewType) { + case 0: + view = new SettingsSearchCell(mContext); + break; + case 1: + view = new GraySectionCell(mContext); + break; + case 2: + default: + view = new HeaderCell(mContext, 16); + break; + } + view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)); + return new RecyclerListView.Holder(view); + } + + @Override + public int getItemViewType(int position) { + if (searchWas) { + if (position < searchResults.size()) { + return 0; + } else if (position == searchResults.size()) { + return 1; + } + return 0; + } else { + if (position == 0) { + return 2; + } + return 0; + } + } + + public void addRecent(Object object) { + int index = recentSearches.indexOf(object); + if (index >= 0) { + recentSearches.remove(index); + } + recentSearches.add(0, object); + if (!searchWas) { + notifyDataSetChanged(); + } + if (recentSearches.size() > 20) { + recentSearches.remove(recentSearches.size() - 1); + } + LinkedHashSet toSave = new LinkedHashSet<>(); + for (int a = 0, N = recentSearches.size(); a < N; a++) { + Object o = recentSearches.get(a); + if (o instanceof SearchResult) { + ((SearchResult) o).num = a; + } else if (o instanceof FaqSearchResult) { + ((FaqSearchResult) o).num = a; + } + toSave.add(o.toString()); + } + MessagesController.getGlobalMainSettings().edit().putStringSet("settingsSearchRecent2", toSave).commit(); + } + + public void clearRecent() { + recentSearches.clear(); + MessagesController.getGlobalMainSettings().edit().remove("settingsSearchRecent2").commit(); + notifyDataSetChanged(); + } + + private int getNum(Object o) { + if (o instanceof SearchResult) { + return ((SearchResult) o).num; + } else if (o instanceof FaqSearchResult) { + return ((FaqSearchResult) o).num; + } + return 0; + } + + public void search(String text) { + lastSearchString = text; + if (searchRunnable != null) { + Utilities.searchQueue.cancelRunnable(searchRunnable); + searchRunnable = null; + } + if (TextUtils.isEmpty(text)) { + searchWas = false; + searchResults.clear(); + faqSearchResults.clear(); + resultNames.clear(); + emptyView.setTopImage(0); + emptyView.setText(LocaleController.getString("SettingsNoRecent", R.string.SettingsNoRecent)); + notifyDataSetChanged(); + return; + } + Utilities.searchQueue.postRunnable(searchRunnable = () -> { + ArrayList results = new ArrayList<>(); + ArrayList faqResults = new ArrayList<>(); + ArrayList names = new ArrayList<>(); + String[] searchArgs = text.split(" "); + String[] translitArgs = new String[searchArgs.length]; + for (int a = 0; a < searchArgs.length; a++) { + translitArgs[a] = LocaleController.getInstance().getTranslitString(searchArgs[a]); + if (translitArgs[a].equals(searchArgs[a])) { + translitArgs[a] = null; + } + } + + for (int a = 0; a < searchArray.length; a++) { + SearchResult result = searchArray[a]; + String title = " " + result.searchTitle.toLowerCase(); + SpannableStringBuilder stringBuilder = null; + for (int i = 0; i < searchArgs.length; i++) { + if (searchArgs[i].length() != 0) { + String searchString = searchArgs[i]; + int index = title.indexOf(" " + searchString); + if (index < 0 && translitArgs[i] != null) { + searchString = translitArgs[i]; + index = title.indexOf(" " + searchString); + } + if (index >= 0) { + if (stringBuilder == null) { + stringBuilder = new SpannableStringBuilder(result.searchTitle); + } + stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)), index, index + searchString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else { + break; + } + } + if (stringBuilder != null && i == searchArgs.length - 1) { + if (result.guid == 502) { + int freeAccount = -1; + for (int b = 0; b < UserConfig.MAX_ACCOUNT_COUNT; b++) { + if (!UserConfig.getInstance(a).isClientActivated()) { + freeAccount = b; + break; + } + } + if (freeAccount < 0) { + continue; + } + } + results.add(result); + names.add(stringBuilder); + } + } + } + if (faqWebPage != null) { + for (int a = 0, N = faqSearchArray.size(); a < N; a++) { + FaqSearchResult result = faqSearchArray.get(a); + String title = " " + result.title.toLowerCase(); + SpannableStringBuilder stringBuilder = null; + for (int i = 0; i < searchArgs.length; i++) { + if (searchArgs[i].length() != 0) { + String searchString = searchArgs[i]; + int index = title.indexOf(" " + searchString); + if (index < 0 && translitArgs[i] != null) { + searchString = translitArgs[i]; + index = title.indexOf(" " + searchString); + } + if (index >= 0) { + if (stringBuilder == null) { + stringBuilder = new SpannableStringBuilder(result.title); + } + stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)), index, index + searchString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else { + break; + } + } + if (stringBuilder != null && i == searchArgs.length - 1) { + faqResults.add(result); + names.add(stringBuilder); + } + } + } + } + + AndroidUtilities.runOnUIThread(() -> { + if (!text.equals(lastSearchString)) { + return; + } + if (!searchWas) { + emptyView.setTopImage(R.drawable.settings_noresults); + emptyView.setText(LocaleController.getString("SettingsNoResults", R.string.SettingsNoResults)); + } + searchWas = true; + searchResults = results; + faqSearchResults = faqResults; + resultNames = names; + notifyDataSetChanged(); + }); + }, 300); + } + } + private class ListAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; @@ -1223,7 +1982,8 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter public ThemeDescription[] getThemeDescriptions() { return new ThemeDescription[]{ new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{EmptyCell.class, HeaderCell.class, TextDetailCell.class, TextCell.class}, null, null, null, Theme.key_windowBackgroundWhite), - new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray), + new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, null, null, null, null, Theme.key_windowBackgroundGray), + new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, null, null, null, null, Theme.key_windowBackgroundWhite), new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_avatar_backgroundActionBarBlue), new ThemeDescription(listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_avatar_backgroundActionBarBlue), @@ -1235,6 +1995,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter new ThemeDescription(onlineTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_avatar_subtitleInProfileBlue), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUBACKGROUND, null, null, null, null, Theme.key_actionBarDefaultSubmenuBackground), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM, null, null, null, null, Theme.key_actionBarDefaultSubmenuItem), + new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubmenuItemIcon), new ThemeDescription(listView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector), @@ -1260,6 +2021,13 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter new ThemeDescription(writeButton, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_profile_actionIcon), new ThemeDescription(writeButton, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_profile_actionBackground), new ThemeDescription(writeButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_profile_actionPressedBackground), + + 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(listView, 0, new Class[]{SettingsSearchCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText), + new ThemeDescription(listView, 0, new Class[]{SettingsSearchCell.class}, new String[]{"valueTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText2), + new ThemeDescription(listView, 0, new Class[]{SettingsSearchCell.class}, new String[]{"imageView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayIcon), }; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StickerPreviewViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/StickerPreviewViewer.java deleted file mode 100644 index b0bf2b7ab..000000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/StickerPreviewViewer.java +++ /dev/null @@ -1,608 +0,0 @@ -/* - * 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.annotation.SuppressLint; -import android.app.Activity; -import android.app.Dialog; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.PixelFormat; -import android.graphics.drawable.ColorDrawable; -import android.os.Build; -import android.text.Layout; -import android.text.StaticLayout; -import android.text.TextPaint; -import android.text.TextUtils; -import android.view.Gravity; -import android.view.HapticFeedbackConstants; -import android.view.MotionEvent; -import android.view.View; -import android.view.WindowManager; -import android.widget.AbsListView; -import android.widget.AdapterView; -import android.widget.FrameLayout; - -import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.DataQuery; -import org.telegram.messenger.Emoji; -import org.telegram.messenger.FileLoader; -import org.telegram.messenger.ImageReceiver; -import org.telegram.messenger.FileLog; -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.BottomSheet; -import org.telegram.ui.Cells.ContextLinkCell; -import org.telegram.ui.Cells.StickerCell; -import org.telegram.ui.Cells.StickerEmojiCell; -import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.RecyclerListView; - -import java.util.ArrayList; - -public class StickerPreviewViewer { - - private class FrameLayoutDrawer extends FrameLayout { - public FrameLayoutDrawer(Context context) { - super(context); - setWillNotDraw(false); - } - - @Override - protected void onDraw(Canvas canvas) { - StickerPreviewViewer.this.onDraw(canvas); - } - } - - public interface StickerPreviewViewerDelegate { - void sendSticker(TLRPC.Document sticker, Object parent); - void openSet(TLRPC.InputStickerSet set); - boolean needSend(); - default boolean needOpen() { - return true; - } - } - - private static TextPaint textPaint; - - private int startX; - private int startY; - private View currentStickerPreviewCell; - private Runnable openStickerPreviewRunnable; - private Dialog visibleDialog; - private StickerPreviewViewerDelegate delegate; - - private int currentAccount; - - private ColorDrawable backgroundDrawable = new ColorDrawable(0x71000000); - private Activity parentActivity; - private WindowManager.LayoutParams windowLayoutParams; - private FrameLayout windowView; - private FrameLayoutDrawer containerView; - private ImageReceiver centerImage = new ImageReceiver(); - private boolean isVisible = false; - private float showProgress; - private StaticLayout stickerEmojiLayout; - private long lastUpdateTime; - private int keyboardHeight = AndroidUtilities.dp(200); - private Runnable showSheetRunnable = new Runnable() { - @Override - public void run() { - if (parentActivity == null || currentSet == null) { - return; - } - final boolean inFavs = DataQuery.getInstance(currentAccount).isStickerInFavorites(currentSticker); - BottomSheet.Builder builder = new BottomSheet.Builder(parentActivity); - ArrayList items = new ArrayList<>(); - final ArrayList actions = new ArrayList<>(); - ArrayList icons = new ArrayList<>(); - if (delegate != null) { - if (delegate.needSend()) { - items.add(LocaleController.getString("SendStickerPreview", R.string.SendStickerPreview)); - icons.add(R.drawable.stickers_send); - actions.add(0); - } - if (delegate.needOpen()) { - items.add(LocaleController.formatString("ViewPackPreview", R.string.ViewPackPreview)); - icons.add(R.drawable.stickers_pack); - actions.add(1); - } - } - if (!MessageObject.isMaskDocument(currentSticker) && (inFavs || DataQuery.getInstance(currentAccount).canAddStickerToFavorites())) { - items.add(inFavs ? LocaleController.getString("DeleteFromFavorites", R.string.DeleteFromFavorites) : LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); - icons.add(inFavs ? R.drawable.stickers_unfavorite : R.drawable.stickers_favorite); - actions.add(2); - } - if (items.isEmpty()) { - return; - } - int[] ic = new int[icons.size()]; - for (int a = 0; a < icons.size(); a++) { - ic[a] = icons.get(a); - } - builder.setItems(items.toArray(new CharSequence[items.size()]), ic, (dialog, which) -> { - if (parentActivity == null) { - return; - } - if (actions.get(which) == 0) { - if (delegate != null) { - delegate.sendSticker(currentSticker, currentSet); - } - } else if (actions.get(which) == 1) { - if (delegate != null) { - delegate.openSet(currentSet); - } - } else if (actions.get(which) == 2) { - DataQuery.getInstance(currentAccount).addRecentSticker(DataQuery.TYPE_FAVE, currentSet, currentSticker, (int) (System.currentTimeMillis() / 1000), inFavs); - } - }); - visibleDialog = builder.create(); - visibleDialog.setOnDismissListener(dialog -> { - visibleDialog = null; - close(); - }); - visibleDialog.show(); - containerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - } - }; - - private TLRPC.Document currentSticker; - private TLRPC.InputStickerSet currentSet; - - @SuppressLint("StaticFieldLeak") - private static volatile StickerPreviewViewer Instance = null; - public static StickerPreviewViewer getInstance() { - StickerPreviewViewer localInstance = Instance; - if (localInstance == null) { - synchronized (PhotoViewer.class) { - localInstance = Instance; - if (localInstance == null) { - Instance = localInstance = new StickerPreviewViewer(); - } - } - } - return localInstance; - } - - public static boolean hasInstance() { - return Instance != null; - } - - public void reset() { - if (openStickerPreviewRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(openStickerPreviewRunnable); - openStickerPreviewRunnable = null; - } - if (currentStickerPreviewCell != null) { - if (currentStickerPreviewCell instanceof StickerEmojiCell) { - ((StickerEmojiCell) currentStickerPreviewCell).setScaled(false); - } else if (currentStickerPreviewCell instanceof StickerCell) { - ((StickerCell) currentStickerPreviewCell).setScaled(false); - } else if (currentStickerPreviewCell instanceof ContextLinkCell) { - ((ContextLinkCell) currentStickerPreviewCell).setScaled(false); - } - currentStickerPreviewCell = null; - } - } - - public boolean onTouch(MotionEvent event, final View listView, final int height, final Object listener, StickerPreviewViewerDelegate stickerPreviewViewerDelegate) { - delegate = stickerPreviewViewerDelegate; - if (openStickerPreviewRunnable != null || isVisible()) { - if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_POINTER_UP) { - AndroidUtilities.runOnUIThread(() -> { - if (listView instanceof AbsListView) { - ((AbsListView) listView).setOnItemClickListener((AdapterView.OnItemClickListener) listener); - } else if (listView instanceof RecyclerListView) { - ((RecyclerListView) listView).setOnItemClickListener((RecyclerListView.OnItemClickListener) listener); - } - }, 150); - if (openStickerPreviewRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(openStickerPreviewRunnable); - openStickerPreviewRunnable = null; - } else if (isVisible()) { - close(); - if (currentStickerPreviewCell != null) { - if (currentStickerPreviewCell instanceof StickerEmojiCell) { - ((StickerEmojiCell) currentStickerPreviewCell).setScaled(false); - } else if (currentStickerPreviewCell instanceof StickerCell) { - ((StickerCell) currentStickerPreviewCell).setScaled(false); - } else if (currentStickerPreviewCell instanceof ContextLinkCell) { - ((ContextLinkCell) currentStickerPreviewCell).setScaled(false); - } - currentStickerPreviewCell = null; - } - } - } else if (event.getAction() != MotionEvent.ACTION_DOWN) { - if (isVisible()) { - if (event.getAction() == MotionEvent.ACTION_MOVE) { - int x = (int) event.getX(); - int y = (int) event.getY(); - int count = 0; - if (listView instanceof AbsListView) { - count = ((AbsListView) listView).getChildCount(); - } else if (listView instanceof RecyclerListView) { - count = ((RecyclerListView) listView).getChildCount(); - } - for (int a = 0; a < count; a++) { - View view = null; - if (listView instanceof AbsListView) { - view = ((AbsListView) listView).getChildAt(a); - } else if (listView instanceof RecyclerListView) { - view = ((RecyclerListView) listView).getChildAt(a); - } - if (view == null) { - return false; - } - int top = view.getTop(); - int bottom = view.getBottom(); - int left = view.getLeft(); - int right = view.getRight(); - if (top > y || bottom < y || left > x || right < x) { - continue; - } - boolean ok = false; - if (view instanceof StickerEmojiCell) { - ok = true; - } else if (view instanceof StickerCell) { - ok = true; - } else if (view instanceof ContextLinkCell) { - ok = ((ContextLinkCell) view).isSticker(); - } - if (!ok || view == currentStickerPreviewCell) { - break; - } - if (currentStickerPreviewCell instanceof StickerEmojiCell) { - ((StickerEmojiCell) currentStickerPreviewCell).setScaled(false); - } else if (currentStickerPreviewCell instanceof StickerCell) { - ((StickerCell) currentStickerPreviewCell).setScaled(false); - } else if (currentStickerPreviewCell instanceof ContextLinkCell) { - ((ContextLinkCell) currentStickerPreviewCell).setScaled(false); - } - currentStickerPreviewCell = view; - setKeyboardHeight(height); - if (currentStickerPreviewCell instanceof StickerEmojiCell) { - open(((StickerEmojiCell) currentStickerPreviewCell).getSticker(), ((StickerEmojiCell) currentStickerPreviewCell).isRecent()); - ((StickerEmojiCell) currentStickerPreviewCell).setScaled(true); - } else if (currentStickerPreviewCell instanceof StickerCell) { - open(((StickerCell) currentStickerPreviewCell).getSticker(), false); - ((StickerCell) currentStickerPreviewCell).setScaled(true); - } else if (currentStickerPreviewCell instanceof ContextLinkCell) { - open(((ContextLinkCell) currentStickerPreviewCell).getDocument(), false); - ((ContextLinkCell) currentStickerPreviewCell).setScaled(true); - } - return true; - } - } - return true; - } else if (openStickerPreviewRunnable != null) { - if (event.getAction() == MotionEvent.ACTION_MOVE) { - if (Math.hypot(startX - event.getX(), startY - event.getY()) > AndroidUtilities.dp(10)) { - AndroidUtilities.cancelRunOnUIThread(openStickerPreviewRunnable); - openStickerPreviewRunnable = null; - } - } else { - AndroidUtilities.cancelRunOnUIThread(openStickerPreviewRunnable); - openStickerPreviewRunnable = null; - } - } - } - } - return false; - } - - public boolean onInterceptTouchEvent(MotionEvent event, final View listView, final int height, StickerPreviewViewerDelegate stickerPreviewViewerDelegate) { - delegate = stickerPreviewViewerDelegate; - if (event.getAction() == MotionEvent.ACTION_DOWN) { - int x = (int) event.getX(); - int y = (int) event.getY(); - int count = 0; - if (listView instanceof AbsListView) { - count = ((AbsListView) listView).getChildCount(); - } else if (listView instanceof RecyclerListView) { - count = ((RecyclerListView) listView).getChildCount(); - } - for (int a = 0; a < count; a++) { - View view = null; - if (listView instanceof AbsListView) { - view = ((AbsListView) listView).getChildAt(a); - } else if (listView instanceof RecyclerListView) { - view = ((RecyclerListView) listView).getChildAt(a); - } - if (view == null) { - return false; - } - int top = view.getTop(); - int bottom = view.getBottom(); - int left = view.getLeft(); - int right = view.getRight(); - if (top > y || bottom < y || left > x || right < x) { - continue; - } - boolean ok = false; - if (view instanceof StickerEmojiCell) { - ok = ((StickerEmojiCell) view).showingBitmap(); - } else if (view instanceof StickerCell) { - ok = ((StickerCell) view).showingBitmap(); - } else if (view instanceof ContextLinkCell) { - ContextLinkCell cell = (ContextLinkCell) view; - ok = cell.isSticker() && cell.showingBitmap(); - } - if (!ok) { - return false; - } - startX = x; - startY = y; - currentStickerPreviewCell = view; - openStickerPreviewRunnable = () -> { - if (openStickerPreviewRunnable == null) { - return; - } - if (listView instanceof AbsListView) { - ((AbsListView) listView).setOnItemClickListener(null); - ((AbsListView) listView).requestDisallowInterceptTouchEvent(true); - } else if (listView instanceof RecyclerListView) { - ((RecyclerListView) listView).setOnItemClickListener((RecyclerListView.OnItemClickListener) null); - ((RecyclerListView) listView).requestDisallowInterceptTouchEvent(true); - } - openStickerPreviewRunnable = null; - setParentActivity((Activity) listView.getContext()); - setKeyboardHeight(height); - if (currentStickerPreviewCell instanceof StickerEmojiCell) { - open(((StickerEmojiCell) currentStickerPreviewCell).getSticker(), ((StickerEmojiCell) currentStickerPreviewCell).isRecent()); - ((StickerEmojiCell) currentStickerPreviewCell).setScaled(true); - } else if (currentStickerPreviewCell instanceof StickerCell) { - open(((StickerCell) currentStickerPreviewCell).getSticker(), false); - ((StickerCell) currentStickerPreviewCell).setScaled(true); - } else if (currentStickerPreviewCell instanceof ContextLinkCell) { - open(((ContextLinkCell) currentStickerPreviewCell).getDocument(), false); - ((ContextLinkCell) currentStickerPreviewCell).setScaled(true); - } - }; - AndroidUtilities.runOnUIThread(openStickerPreviewRunnable, 200); - return true; - } - } - return false; - } - - public void setDelegate(StickerPreviewViewerDelegate stickerPreviewViewerDelegate) { - delegate = stickerPreviewViewerDelegate; - } - - public void setParentActivity(Activity activity) { - currentAccount = UserConfig.selectedAccount; - centerImage.setCurrentAccount(currentAccount); - if (parentActivity == activity) { - return; - } - parentActivity = activity; - - windowView = new FrameLayout(activity); - windowView.setFocusable(true); - windowView.setFocusableInTouchMode(true); - if (Build.VERSION.SDK_INT >= 23) { - windowView.setFitsSystemWindows(true); - } - - containerView = new FrameLayoutDrawer(activity); - containerView.setFocusable(false); - windowView.addView(containerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); - containerView.setOnTouchListener((v, event) -> { - if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_POINTER_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { - close(); - } - return true; - }); - - windowLayoutParams = new WindowManager.LayoutParams(); - windowLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT; - windowLayoutParams.format = PixelFormat.TRANSLUCENT; - windowLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT; - windowLayoutParams.gravity = Gravity.TOP; - windowLayoutParams.type = WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; - if (Build.VERSION.SDK_INT >= 21) { - windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; - } else { - windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; - } - centerImage.setAspectFit(true); - centerImage.setInvalidateAll(true); - centerImage.setParentView(containerView); - } - - public void setKeyboardHeight(int height) { - keyboardHeight = height; - } - - public void open(TLRPC.Document sticker, boolean isRecent) { - if (parentActivity == null || sticker == null) { - return; - } - if (textPaint == null) { - textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); - textPaint.setTextSize(AndroidUtilities.dp(24)); - } - - TLRPC.InputStickerSet newSet = null; - for (int a = 0; a < sticker.attributes.size(); a++) { - TLRPC.DocumentAttribute attribute = sticker.attributes.get(a); - if (attribute instanceof TLRPC.TL_documentAttributeSticker && attribute.stickerset != null) { - newSet = attribute.stickerset; - break; - } - } - //&& (currentSet == null || currentSet.id != newSet.id) - if (newSet != null) { - try { - if (visibleDialog != null) { - visibleDialog.setOnDismissListener(null); - visibleDialog.dismiss(); - visibleDialog = null; - } - } catch (Exception e) { - FileLog.e(e); - } - AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); - AndroidUtilities.runOnUIThread(showSheetRunnable, 1300); - } - currentSet = newSet; - TLRPC.PhotoSize thumb = sticker != null ? FileLoader.getClosestPhotoSizeWithSize(sticker.thumbs, 90) : null; - centerImage.setImage(sticker, null, thumb, null, "webp", currentSet, 1); - stickerEmojiLayout = null; - for (int a = 0; a < sticker.attributes.size(); a++) { - TLRPC.DocumentAttribute attribute = sticker.attributes.get(a); - if (attribute instanceof TLRPC.TL_documentAttributeSticker) { - if (!TextUtils.isEmpty(attribute.alt)) { - CharSequence emoji = Emoji.replaceEmoji(attribute.alt, textPaint.getFontMetricsInt(), AndroidUtilities.dp(24), false); - stickerEmojiLayout = new StaticLayout(emoji, textPaint, AndroidUtilities.dp(100), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); - break; - } - } - } - - currentSticker = sticker; - containerView.invalidate(); - - if (!isVisible) { - AndroidUtilities.lockOrientation(parentActivity); - try { - if (windowView.getParent() != null) { - WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); - wm.removeView(windowView); - } - } catch (Exception e) { - FileLog.e(e); - } - WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); - wm.addView(windowView, windowLayoutParams); - isVisible = true; - showProgress = 0.0f; - lastUpdateTime = System.currentTimeMillis(); - } - } - - public boolean isVisible() { - return isVisible; - } - - public void close() { - if (parentActivity == null || visibleDialog != null) { - return; - } - AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); - showProgress = 1.0f; - lastUpdateTime = System.currentTimeMillis(); - containerView.invalidate(); - try { - if (visibleDialog != null) { - visibleDialog.dismiss(); - visibleDialog = null; - } - } catch (Exception e) { - FileLog.e(e); - } - currentSticker = null; - currentSet = null; - delegate = null; - isVisible = false; - } - - public void destroy() { - isVisible = false; - delegate = null; - currentSticker = null; - currentSet = null; - try { - if (visibleDialog != null) { - visibleDialog.dismiss(); - visibleDialog = null; - } - } catch (Exception e) { - FileLog.e(e); - } - if (parentActivity == null || windowView == null) { - return; - } - try { - if (windowView.getParent() != null) { - WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); - wm.removeViewImmediate(windowView); - } - windowView = null; - } catch (Exception e) { - FileLog.e(e); - } - Instance = null; - } - - @SuppressLint("DrawAllocation") - private void onDraw(Canvas canvas) { - if (containerView == null || backgroundDrawable == null) { - return; - } - backgroundDrawable.setAlpha((int) (180 * showProgress)); - backgroundDrawable.setBounds(0, 0, containerView.getWidth(), containerView.getHeight()); - backgroundDrawable.draw(canvas); - - canvas.save(); - int size = (int) (Math.min(containerView.getWidth(), containerView.getHeight()) / 1.8f); - canvas.translate(containerView.getWidth() / 2, Math.max(size / 2 + AndroidUtilities.statusBarHeight + (stickerEmojiLayout!=null ? AndroidUtilities.dp(40) : 0), (containerView.getHeight() - keyboardHeight) / 2)); - Bitmap bitmap = centerImage.getBitmap(); - if (bitmap != null) { - float scale = 0.8f * showProgress / 0.8f; - size = (int) (size * scale); - centerImage.setAlpha(showProgress); - centerImage.setImageCoords(-size / 2, -size / 2, size, size); - centerImage.draw(canvas); - } - if (stickerEmojiLayout != null) { - canvas.translate(-AndroidUtilities.dp(50), -centerImage.getImageHeight() / 2 - AndroidUtilities.dp(30)); - stickerEmojiLayout.draw(canvas); - } - canvas.restore(); - if (isVisible) { - if (showProgress != 1) { - long newTime = System.currentTimeMillis(); - long dt = newTime - lastUpdateTime; - lastUpdateTime = newTime; - showProgress += dt / 120.0f; - containerView.invalidate(); - if (showProgress > 1.0f) { - showProgress = 1.0f; - } - } - } else if (showProgress != 0) { - long newTime = System.currentTimeMillis(); - long dt = newTime - lastUpdateTime; - lastUpdateTime = newTime; - showProgress -= dt / 120.0f; - containerView.invalidate(); - if (showProgress < 0.0f) { - showProgress = 0.0f; - } - if (showProgress == 0) { - AndroidUtilities.unlockOrientation(parentActivity); - AndroidUtilities.runOnUIThread(() -> centerImage.setImageBitmap((Bitmap) null)); - try { - if (windowView.getParent() != null) { - WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); - wm.removeView(windowView); - } - } catch (Exception e) { - FileLog.e(e); - } - } - } - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java index 40ef6c4e9..3777d46df 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java @@ -26,9 +26,6 @@ import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; -import org.telegram.messenger.support.widget.helper.ItemTouchHelper; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; @@ -48,10 +45,16 @@ import org.telegram.ui.Components.URLSpanNoUnderline; import java.util.ArrayList; import java.util.Locale; +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class StickersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private RecyclerListView listView; private ListAdapter listAdapter; + @SuppressWarnings("FieldCanBeLocal") + private LinearLayoutManager layoutManager; private boolean needReorder; private int currentType; @@ -174,7 +177,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter listView = new RecyclerListView(context); listView.setFocusable(true); listView.setTag(7); - LinearLayoutManager layoutManager = new LinearLayoutManager(context); + layoutManager = new LinearLayoutManager(context); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); listView.setLayoutManager(layoutManager); ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new TouchHelperCallback()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java index d53b16c23..83c40dccb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java @@ -30,7 +30,11 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Vibrator; -import android.support.v4.content.FileProvider; +import androidx.core.content.FileProvider; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import android.text.InputType; import android.text.TextPaint; import android.util.TypedValue; @@ -58,9 +62,6 @@ 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.widget.DefaultItemAnimator; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.messenger.time.SunDate; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; @@ -72,6 +73,7 @@ import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.BrightnessControlCell; +import org.telegram.ui.Cells.ChatListCell; import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.Cells.CheckBoxCell; import org.telegram.ui.Cells.HeaderCell; @@ -101,6 +103,8 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No private ListAdapter listAdapter; private RecyclerListView listView; + @SuppressWarnings("FieldCanBeLocal") + private LinearLayoutManager layoutManager; private int backgroundRow; private int textSizeHeaderRow; @@ -138,6 +142,9 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No private int preferedHeaderRow; private int newThemeInfoRow; private int themeHeaderRow; + private int chatListHeaderRow; + private int chatListRow; + private int chatListInfoRow; private int themeStartRow; private int themeEndRow; private int themeInfoRow; @@ -418,6 +425,9 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No automaticBrightnessInfoRow = -1; textSizeHeaderRow = -1; themeHeaderRow = -1; + chatListHeaderRow = -1; + chatListRow = -1; + chatListInfoRow = -1; textSizeRow = -1; backgroundRow = -1; @@ -444,6 +454,10 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No themeEndRow = rowCount; themeInfoRow = rowCount++; + chatListHeaderRow = rowCount++; + chatListRow = rowCount++; + chatListInfoRow = rowCount++; + settingsRow = rowCount++; customTabsRow = rowCount++; directShareRow = rowCount++; @@ -567,7 +581,8 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No actionBar.setTitle(LocaleController.getString("ChatSettings", R.string.ChatSettings)); ActionBarMenu menu = actionBar.createMenu(); ActionBarMenuItem item = menu.addItem(0, R.drawable.ic_ab_other); - item.addSubItem(create_theme, LocaleController.getString("CreateNewThemeMenu", R.string.CreateNewThemeMenu)); + item.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); + item.addSubItem(create_theme, R.drawable.menu_palette, LocaleController.getString("CreateNewThemeMenu", R.string.CreateNewThemeMenu)); } else { actionBar.setTitle(LocaleController.getString("AutoNightTheme", R.string.AutoNightTheme)); } @@ -598,7 +613,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No fragmentView = frameLayout; listView = new RecyclerListView(context); - listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); + listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); listView.setVerticalScrollBarEnabled(false); listView.setAdapter(listAdapter); ((DefaultItemAnimator) listView.getItemAnimator()).setDelayAnimations(false); @@ -673,7 +688,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No if (getParentActivity() == null) { return; } - final boolean maskValues[] = new boolean[2]; + final boolean[] maskValues = new boolean[2]; BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity()); builder.setApplyTopPadding(false); @@ -929,7 +944,8 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); if (lastKnownLocation == null) { lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); - } else if (lastKnownLocation == null) { + } + if (lastKnownLocation == null) { lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER); } } catch (Exception e) { @@ -943,7 +959,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No } Theme.autoNightLocationLatitude = lastKnownLocation.getLatitude(); Theme.autoNightLocationLongitude = lastKnownLocation.getLongitude(); - int time[] = SunDate.calculateSunriseSunset(Theme.autoNightLocationLatitude, Theme.autoNightLocationLongitude); + int[] time = SunDate.calculateSunriseSunset(Theme.autoNightLocationLatitude, Theme.autoNightLocationLongitude); Theme.autoNightSunriseTime = time[0]; Theme.autoNightSunsetTime = time[1]; Theme.autoNightCityName = null; @@ -1215,10 +1231,19 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 8: - default: view = new TextSizeCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; + case 9: + default: + view = new ChatListCell(mContext) { + @Override + protected void didSelectChatType(boolean threeLines) { + SharedConfig.setUseThreeLinesLayout(threeLines); + } + }; + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + break; } return new RecyclerListView.Holder(view); @@ -1308,6 +1333,8 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No 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)); } break; } @@ -1362,12 +1389,14 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No } else if (position == automaticBrightnessInfoRow || position == scheduleLocationInfoRow) { return 2; } else if (position == themeInfoRow || position == nightTypeInfoRow || position == scheduleFromToInfoRow || - position == stickersSection2Row || position == settings2Row || position == newThemeInfoRow) { + position == stickersSection2Row || position == settings2Row || position == newThemeInfoRow || + 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 == settingsRow || position == themeHeaderRow || position == textSizeHeaderRow || + position == chatListHeaderRow) { return 5; } else if (position == automaticBrightnessRow) { return 6; @@ -1377,6 +1406,8 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No return 7; } else if (position == textSizeRow) { return 8; + } else if (position == chatListRow) { + return 9; } return 0; } @@ -1385,7 +1416,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No @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}, null, null, null, Theme.key_windowBackgroundWhite), + new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{TextSettingsCell.class, TextCheckCell.class, HeaderCell.class, BrightnessControlCell.class, ThemeTypeCell.class, ThemeCell.class, TextSizeCell.class, ChatListCell.class}, null, null, null, Theme.key_windowBackgroundWhite), new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray), new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault), @@ -1393,6 +1424,9 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No 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(actionBar, ThemeDescription.FLAG_AB_SUBMENUBACKGROUND, null, null, null, null, Theme.key_actionBarDefaultSubmenuBackground), + new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM, null, null, null, null, Theme.key_actionBarDefaultSubmenuItem), + new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubmenuItemIcon), new ThemeDescription(listView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector), @@ -1427,6 +1461,9 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No new ThemeDescription(listView, ThemeDescription.FLAG_PROGRESSBAR, new Class[]{TextSizeCell.class}, new String[]{"sizeBar"}, null, null, null, Theme.key_player_progress), new ThemeDescription(listView, 0, new Class[]{TextSizeCell.class}, new String[]{"sizeBar"}, null, null, null, Theme.key_player_progressBackground), + new ThemeDescription(listView, 0, new Class[]{ChatListCell.class}, null, null, null, Theme.key_radioBackground), + new ThemeDescription(listView, 0, new Class[]{ChatListCell.class}, null, null, null, Theme.key_radioBackgroundChecked), + new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgInDrawable, Theme.chat_msgInMediaDrawable}, null, Theme.key_chat_inBubble), new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgInSelectedDrawable, Theme.chat_msgInMediaSelectedDrawable}, null, Theme.key_chat_inBubbleSelected), new ThemeDescription(listView, 0, null, null, new Drawable[]{Theme.chat_msgInShadowDrawable, Theme.chat_msgInMediaShadowDrawable}, null, Theme.key_chat_inBubbleShadow), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java index 7bc1817e2..307606030 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java @@ -20,9 +20,11 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; import android.os.Build; -import android.support.v4.view.PagerAdapter; -import android.support.v4.view.ViewPager; -import android.text.style.CharacterStyle; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; import android.util.TypedValue; import android.view.Gravity; import android.view.View; @@ -34,13 +36,15 @@ import android.widget.ImageView; 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; +import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; +import org.telegram.messenger.Utilities; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; @@ -216,13 +220,97 @@ public class ThemePreviewActivity extends BaseFragment implements NotificationCe }; page2.setBackgroundImage(Theme.getCachedWallpaper(), Theme.isWallpaperMotion()); + messagesAdapter = new MessagesAdapter(context); + actionBar2 = createActionBar(context); actionBar2.setBackButtonDrawable(new BackDrawable(false)); - actionBar2.setTitle("Reinhardt"); - actionBar2.setSubtitle(LocaleController.formatDateOnline(System.currentTimeMillis() / 1000 - 60 * 60)); + 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)); + } page2.addView(actionBar2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - listView2 = new RecyclerListView(context); + listView2 = new RecyclerListView(context) { + @Override + public boolean drawChild(Canvas canvas, View child, long drawingTime) { + boolean result = super.drawChild(canvas, child, drawingTime); + if (child instanceof ChatMessageCell) { + ChatMessageCell chatMessageCell = (ChatMessageCell) child; + MessageObject message = chatMessageCell.getMessageObject(); + ImageReceiver imageReceiver = chatMessageCell.getAvatarImage(); + if (imageReceiver != null) { + int top = child.getTop(); + if (chatMessageCell.isPinnedBottom()) { + ViewHolder holder = listView2.getChildViewHolder(child); + if (holder != null) { + int p = holder.getAdapterPosition(); + int nextPosition; + nextPosition = p - 1; + holder = listView2.findViewHolderForAdapterPosition(nextPosition); + if (holder != null) { + imageReceiver.setImageY(-AndroidUtilities.dp(1000)); + imageReceiver.draw(canvas); + return result; + } + } + } + float tx = chatMessageCell.getTranslationX(); + int y = child.getTop() + chatMessageCell.getLayoutHeight(); + int maxY = listView2.getMeasuredHeight() - listView2.getPaddingBottom(); + if (y > maxY) { + y = maxY; + } + if (chatMessageCell.isPinnedTop()) { + ViewHolder holder = listView2.getChildViewHolder(child); + if (holder != null) { + int tries = 0; + while (true) { + if (tries >= 20) { + break; + } + tries++; + int p = holder.getAdapterPosition(); + int prevPosition = p + 1; + holder = listView2.findViewHolderForAdapterPosition(prevPosition); + if (holder != null) { + top = holder.itemView.getTop(); + if (y - AndroidUtilities.dp(48) < holder.itemView.getBottom()) { + tx = Math.min(holder.itemView.getTranslationX(), tx); + } + if (holder.itemView instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) holder.itemView; + if (!cell.isPinnedTop()) { + break; + } + } else { + break; + } + } else { + break; + } + } + } + } + if (y - AndroidUtilities.dp(48) < top) { + y = top + AndroidUtilities.dp(48); + } + if (tx != 0) { + canvas.save(); + canvas.translate(tx, 0); + } + imageReceiver.setImageY(y - AndroidUtilities.dp(44)); + imageReceiver.draw(canvas); + if (tx != 0) { + canvas.restore(); + } + } + } + return result; + } + }; listView2.setVerticalScrollBarEnabled(true); listView2.setItemAnimator(null); listView2.setLayoutAnimation(null); @@ -232,7 +320,6 @@ public class ThemePreviewActivity extends BaseFragment implements NotificationCe listView2.setVerticalScrollbarPosition(LocaleController.isRTL ? RecyclerListView.SCROLLBAR_POSITION_LEFT : RecyclerListView.SCROLLBAR_POSITION_RIGHT); page2.addView(listView2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP)); - messagesAdapter = new MessagesAdapter(context); listView2.setAdapter(messagesAdapter); fragmentView = new FrameLayout(context); @@ -393,7 +480,6 @@ public class ThemePreviewActivity extends BaseFragment implements NotificationCe } @Override - @SuppressWarnings("unchecked") public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.emojiDidLoad) { if (listView == null) { @@ -536,7 +622,7 @@ public class ThemePreviewActivity extends BaseFragment implements NotificationCe @Override public int getItemCount() { - return dialogs.size() + 1; + return dialogs.size(); } @Override @@ -579,6 +665,7 @@ public class ThemePreviewActivity extends BaseFragment implements NotificationCe private Context mContext; private ArrayList messages; + private boolean showSecretMessages = Utilities.random.nextInt(100) <= (BuildVars.DEBUG_VERSION ? 5 : 1); public MessagesAdapter(Context context) { mContext = context; @@ -587,130 +674,185 @@ public class ThemePreviewActivity extends BaseFragment implements NotificationCe int date = (int) (System.currentTimeMillis() / 1000) - 60 * 60; TLRPC.Message message; - - message = new TLRPC.TL_message(); - message.message = "Reinhardt, we need to find you some new tunes \uD83C\uDFB6."; - 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 = "I can't even take you seriously right now."; - 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 messageObject; - messages.add(new MessageObject(currentAccount, message, true)); + if (showSecretMessages) { + TLRPC.TL_user user1 = new TLRPC.TL_user(); + user1.id = Integer.MAX_VALUE; + user1.first_name = "Me"; - message = new TLRPC.TL_message(); - message.date = date + 130; - message.dialog_id = 1; - message.flags = 259; - message.from_id = 0; - message.id = 5; - message.media = new TLRPC.TL_messageMediaDocument(); - message.media.flags |= 3; - message.media.document = new TLRPC.TL_document(); - message.media.document.mime_type = "audio/mp4"; - 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"; - message.media.document.attributes.add(audio); - message.out = false; - message.to_id = new TLRPC.TL_peerUser(); - message.to_id.user_id = UserConfig.getInstance(currentAccount).getClientUserId(); - messages.add(new MessageObject(currentAccount, message, true)); + TLRPC.TL_user user2 = new TLRPC.TL_user(); + user2.id = Integer.MAX_VALUE - 1; + user2.first_name = "Serj"; - message = new TLRPC.TL_message(); - message.message = "Ah, you kids today with techno music! You should enjoy the classics, like Hasselhoff!"; - 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 = new MessageObject(currentAccount, message, true); - messageObject.customReplyName = "Lucio"; - messageObject.replyMessageObject = replyMessageObject; - messages.add(messageObject); + ArrayList users = new ArrayList<>(); + users.add(user1); + users.add(user2); + MessagesController.getInstance(currentAccount).putUsers(users, true); - message = new TLRPC.TL_message(); - message.date = date + 120; - message.dialog_id = 1; - message.flags = 259; - message.from_id = UserConfig.getInstance(currentAccount).getClientUserId(); - message.id = 1; - message.media = new TLRPC.TL_messageMediaDocument(); - message.media.flags |= 3; - message.media.document = new TLRPC.TL_document(); - message.media.document.mime_type = "audio/ogg"; - message.media.document.file_reference = new byte[0]; - audio = new TLRPC.TL_documentAttributeAudio(); - audio.flags = 1028; - audio.duration = 3; - audio.voice = true; - audio.waveform = new byte[]{0, 4, 17, -50, -93, 86, -103, -45, -12, -26, 63, -25, -3, 109, -114, -54, -4, -1, + message = new TLRPC.TL_message(); + message.message = "Guess why Half-Life 3 was never released."; + message.date = date + 960; + message.dialog_id = -1; + message.flags = 259; + message.id = Integer.MAX_VALUE - 1; + message.media = new TLRPC.TL_messageMediaEmpty(); + message.out = false; + message.to_id = new TLRPC.TL_peerChat(); + message.to_id.chat_id = 1; + message.from_id = user2.id; + messages.add(new MessageObject(currentAccount, message, true)); + + message = new TLRPC.TL_message(); + message.message = "No.\n" + + "And every unnecessary ping of the dev delays the release for 10 days.\n" + + "Every request for ETA delays the release for 2 weeks."; + message.date = date + 960; + message.dialog_id = -1; + message.flags = 259; + message.id = 1; + message.media = new TLRPC.TL_messageMediaEmpty(); + message.out = false; + message.to_id = new TLRPC.TL_peerChat(); + message.to_id.chat_id = 1; + message.from_id = user2.id; + messages.add(new MessageObject(currentAccount, message, true)); + + message = new TLRPC.TL_message(); + message.message = "Is source code for Android coming anytime soon?"; + message.date = date + 600; + message.dialog_id = -1; + message.flags = 259; + message.id = 1; + message.media = new TLRPC.TL_messageMediaEmpty(); + message.out = false; + message.to_id = new TLRPC.TL_peerChat(); + message.to_id.chat_id = 1; + message.from_id = user1.id; + 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.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 = "I can't even take you seriously right now."; + 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; + messages.add(new MessageObject(currentAccount, message, true)); + + message = new TLRPC.TL_message(); + message.date = date + 130; + message.dialog_id = 1; + message.flags = 259; + message.from_id = 0; + message.id = 5; + message.media = new TLRPC.TL_messageMediaDocument(); + message.media.flags |= 3; + message.media.document = new TLRPC.TL_document(); + message.media.document.mime_type = "audio/mp4"; + 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"; + message.media.document.attributes.add(audio); + message.out = false; + message.to_id = new TLRPC.TL_peerUser(); + message.to_id.user_id = UserConfig.getInstance(currentAccount).getClientUserId(); + 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.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 = new MessageObject(currentAccount, message, true); + messageObject.customReplyName = "Lucio"; + messageObject.replyMessageObject = replyMessageObject; + messages.add(messageObject); + + message = new TLRPC.TL_message(); + message.date = date + 120; + message.dialog_id = 1; + message.flags = 259; + message.from_id = UserConfig.getInstance(currentAccount).getClientUserId(); + message.id = 1; + message.media = new TLRPC.TL_messageMediaDocument(); + message.media.flags |= 3; + message.media.document = new TLRPC.TL_document(); + message.media.document.mime_type = "audio/ogg"; + message.media.document.file_reference = new byte[0]; + audio = new TLRPC.TL_documentAttributeAudio(); + audio.flags = 1028; + audio.duration = 3; + audio.voice = true; + audio.waveform = new byte[]{0, 4, 17, -50, -93, 86, -103, -45, -12, -26, 63, -25, -3, 109, -114, -54, -4, -1, -1, -1, -1, -29, -1, -1, -25, -1, -1, -97, -43, 57, -57, -108, 1, -91, -4, -47, 21, 99, 10, 97, 43, 45, 115, -112, -77, 51, -63, 66, 40, 34, -122, -116, 48, -124, 16, 66, -120, 16, 68, 16, 33, 4, 1}; - message.media.document.attributes.add(audio); - message.out = true; - message.to_id = new TLRPC.TL_peerUser(); - message.to_id.user_id = 0; - messageObject = new MessageObject(currentAccount, message, true); - messageObject.audioProgressSec = 1; - messageObject.audioProgress = 0.3f; - messageObject.useCustomPhoto = true; - messages.add(messageObject); + message.media.document.attributes.add(audio); + message.out = true; + message.to_id = new TLRPC.TL_peerUser(); + message.to_id.user_id = 0; + messageObject = new MessageObject(currentAccount, message, true); + messageObject.audioProgressSec = 1; + messageObject.audioProgress = 0.3f; + messageObject.useCustomPhoto = true; + messages.add(messageObject); - messages.add(replyMessageObject); + messages.add(replyMessageObject); - message = new TLRPC.TL_message(); - message.date = date + 10; - message.dialog_id = 1; - message.flags = 257; - message.from_id = 0; - message.id = 1; - message.media = new TLRPC.TL_messageMediaPhoto(); - message.media.flags |= 3; - message.media.photo = new TLRPC.TL_photo(); - message.media.photo.file_reference = new byte[0]; - message.media.photo.has_stickers = false; - message.media.photo.id = 1; - message.media.photo.access_hash = 0; - message.media.photo.date = date; - TLRPC.TL_photoSize photoSize = new TLRPC.TL_photoSize(); - photoSize.size = 0; - photoSize.w = 500; - photoSize.h = 302; - 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.out = false; - message.to_id = new TLRPC.TL_peerUser(); - message.to_id.user_id = UserConfig.getInstance(currentAccount).getClientUserId(); - messageObject = new MessageObject(currentAccount, message, true); - messageObject.useCustomPhoto = true; - messages.add(messageObject); + message = new TLRPC.TL_message(); + message.date = date + 10; + message.dialog_id = 1; + message.flags = 257; + message.from_id = 0; + message.id = 1; + message.media = new TLRPC.TL_messageMediaPhoto(); + message.media.flags |= 3; + message.media.photo = new TLRPC.TL_photo(); + message.media.photo.file_reference = new byte[0]; + message.media.photo.has_stickers = false; + message.media.photo.id = 1; + message.media.photo.access_hash = 0; + message.media.photo.date = date; + TLRPC.TL_photoSize photoSize = new TLRPC.TL_photoSize(); + photoSize.size = 0; + photoSize.w = 500; + photoSize.h = 302; + 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.out = false; + message.to_id = new TLRPC.TL_peerUser(); + message.to_id.user_id = UserConfig.getInstance(currentAccount).getClientUserId(); + messageObject = new MessageObject(currentAccount, message, true); + messageObject.useCustomPhoto = true; + messages.add(messageObject); + } message = new TLRPC.TL_message(); message.message = LocaleController.formatDateChat(date); @@ -740,118 +882,12 @@ public class ThemePreviewActivity extends BaseFragment implements NotificationCe view = new ChatMessageCell(mContext); ChatMessageCell chatMessageCell = (ChatMessageCell) view; chatMessageCell.setDelegate(new ChatMessageCell.ChatMessageCellDelegate() { - @Override - public void didPressShare(ChatMessageCell cell) { - } - - @Override - public boolean needPlayMessage(MessageObject messageObject) { - return false; - } - - @Override - public void didPressChannelAvatar(ChatMessageCell cell, TLRPC.Chat chat, int postId) { - - } - - @Override - public void didPressOther(ChatMessageCell cell) { - - } - - @Override - public void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user) { - - } - - @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) { - - } - - @Override - public void didLongPress(ChatMessageCell cell) { - - } - - @Override - public boolean canPerformActions() { - return false; - } - - @Override - public void didPressUrl(MessageObject messageObject, final CharacterStyle url, boolean longPress) { - - } - - @Override - public void needOpenWebView(String url, String title, String description, String originalUrl, int w, int h) { - - } - - @Override - public void didPressReplyMessage(ChatMessageCell cell, int id) { - - } - - @Override - public void didPressViaBot(ChatMessageCell cell, String username) { - - } - - @Override - public void didPressImage(ChatMessageCell cell) { - - } - - @Override - public void didPressInstantButton(ChatMessageCell cell, int type) { - - } - - @Override - public boolean isChatAdminCell(int uid) { - return false; - } }); } else if (viewType == 1) { view = new ChatActionCell(mContext); ((ChatActionCell) view).setDelegate(new ChatActionCell.ChatActionCellDelegate() { - @Override - public void didClickedImage(ChatActionCell cell) { - } - - @Override - public void didLongPressed(ChatActionCell cell) { - - } - - @Override - public void needOpenUserProfile(int uid) { - - } - - @Override - public void didPressedReplyMessage(ChatActionCell cell, int id) { - - } - - @Override - public void didPressedBotButton(MessageObject messageObject, TLRPC.KeyboardButton button) { - - } }); } view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)); @@ -882,6 +918,7 @@ public class ThemePreviewActivity extends BaseFragment implements NotificationCe } else { pinnedTop = false; } + messageCell.isChat = showSecretMessages; messageCell.setFullyDraw(true); messageCell.setMessageObject(message, null, pinnedBotton, pinnedTop); } else if (view instanceof ChatActionCell) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java index ccda78fb7..e4d3eee56 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java @@ -43,8 +43,6 @@ import org.telegram.messenger.R; import org.telegram.messenger.SRPHelper; import org.telegram.messenger.UserConfig; import org.telegram.messenger.browser.Browser; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.TLRPC; @@ -68,6 +66,9 @@ import org.telegram.ui.Components.RecyclerListView; import java.math.BigInteger; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class TwoStepVerificationActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListAdapter listAdapter; @@ -859,7 +860,7 @@ public class TwoStepVerificationActivity extends BaseFragment implements Notific } int dot = text.lastIndexOf('.'); int dog = text.lastIndexOf('@'); - return !(dot < 0 || dog < 0 || dot < dog); + return !(dog < 0 || dot < dog); } private void showAlertWithText(String title, String text) { @@ -1139,7 +1140,7 @@ public class TwoStepVerificationActivity extends BaseFragment implements Notific needShowProgress(); Utilities.globalQueue.postRunnable(() -> { final TLRPC.TL_account_getPasswordSettings req = new TLRPC.TL_account_getPasswordSettings(); - final byte x_bytes[]; + final byte[] x_bytes; if (currentPassword.current_algo instanceof TLRPC.TL_passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow) { TLRPC.TL_passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow algo = (TLRPC.TL_passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow) currentPassword.current_algo; x_bytes = SRPHelper.getX(oldPasswordBytes, algo); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/VoIPActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/VoIPActivity.java index 5d12b8440..7884035a1 100755 --- a/TMessagesProj/src/main/java/org/telegram/ui/VoIPActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/VoIPActivity.java @@ -38,10 +38,10 @@ import android.graphics.drawable.GradientDrawable; import android.media.AudioManager; import android.os.Build; import android.os.Bundle; -import android.support.annotation.IntRange; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.graphics.Palette; +import androidx.annotation.IntRange; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.palette.graphics.Palette; import android.text.Editable; import android.text.SpannableString; import android.text.SpannableStringBuilder; @@ -56,6 +56,8 @@ import android.view.KeyEvent; import android.view.View; import android.view.Window; import android.view.WindowManager; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; import android.view.animation.DecelerateInterpolator; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; @@ -72,6 +74,7 @@ import org.telegram.messenger.BuildVars; import org.telegram.messenger.ContactsController; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLog; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; @@ -190,7 +193,7 @@ public class VoIPActivity extends Activity implements VoIPService.StateListener, } } }); - photoView.setImage(user.photo.photo_big, null, new ColorDrawable(0xFF000000), user); + photoView.setImage(ImageLocation.getForUser(user, true), null, new ColorDrawable(0xFF000000), user); photoView.setLayerType(View.LAYER_TYPE_HARDWARE, null); } else { photoView.setVisibility(View.GONE); @@ -440,6 +443,16 @@ public class VoIPActivity extends Activity implements VoIPService.StateListener, NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.closeInCallActivity); 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(){ + @Override + public void run(){ + nameText.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); + } + }, 500); + } } private View createContentView(){ @@ -564,6 +577,7 @@ public class VoIPActivity extends Activity implements VoIPService.StateListener, 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)); buttons.addView(wrap, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, 1f)); @@ -573,6 +587,7 @@ public class VoIPActivity extends Activity implements VoIPService.StateListener, 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)); buttons.addView(wrap, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, 1f)); @@ -595,6 +610,7 @@ public class VoIPActivity extends Activity implements VoIPService.StateListener, 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)); buttons.addView(wrap, LayoutHelper.createLinear(0, LayoutHelper.WRAP_CONTENT, 1f)); @@ -605,10 +621,12 @@ public class VoIPActivity extends Activity implements VoIPService.StateListener, 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)); 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)); content.addView(swipeViewsWrap=swipesWrap, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM, 20, 0, 20, 68)); @@ -645,6 +663,7 @@ public class VoIPActivity extends Activity implements VoIPService.StateListener, endInner.setScaleType(ImageView.ScaleType.CENTER); 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)); ImageView cancelBtn=new ImageView(this); @@ -655,6 +674,7 @@ public class VoIPActivity extends Activity implements VoIPService.StateListener, cancelBtn.setColorFilter(0x89000000); 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)); @@ -845,6 +865,7 @@ public class VoIPActivity extends Activity implements VoIPService.StateListener, byte[] sha256 = Utilities.computeSHA256(encryptedChat.auth_key, 0, encryptedChat.auth_key.length); 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++) { Drawable drawable = Emoji.getEmojiDrawable(emoji[i]); if (drawable != null) { @@ -1170,6 +1191,10 @@ public class VoIPActivity extends Activity implements VoIPService.StateListener, 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)); } else { swipeViewsWrap.setVisibility(View.GONE); acceptBtn.setVisibility(View.GONE); @@ -1228,6 +1253,7 @@ public class VoIPActivity extends Activity implements VoIPService.StateListener, 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){ @@ -1548,7 +1574,7 @@ public class VoIPActivity extends Activity implements VoIPService.StateListener, prefs.getString("quick_reply_msg4", LocaleController.getString("QuickReplyDefault4", R.string.QuickReplyDefault4))}; LinearLayout sheetView=new LinearLayout(this); sheetView.setOrientation(LinearLayout.VERTICAL); - final BottomSheet sheet=new BottomSheet(this, true); + 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(){ diff --git a/TMessagesProj/src/main/java/org/telegram/ui/WallpaperActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/WallpaperActivity.java index 6e498ce42..cdb9c25e9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/WallpaperActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/WallpaperActivity.java @@ -52,6 +52,7 @@ import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.DownloadController; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; +import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; @@ -60,8 +61,6 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.FileLoader; import org.telegram.messenger.R; @@ -90,6 +89,9 @@ import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class WallpaperActivity extends BaseFragment implements DownloadController.FileDownloadProgressListener, NotificationCenter.NotificationCenterDelegate { private RecyclerListView listView; @@ -182,7 +184,7 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle private Bitmap colorWheelBitmap; - private EditTextBoldCursor colorEditText[] = new EditTextBoldCursor[2]; + private EditTextBoldCursor[] colorEditText = new EditTextBoldCursor[2]; private int colorWheelRadius; @@ -375,8 +377,8 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle int colorCount = 12; int colorAngleStep = 360 / 12; - int colors[] = new int[colorCount + 1]; - float hsv[] = new float[] { 0.0f, 1.0f, 1.0f }; + 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); @@ -507,7 +509,7 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle currentPattern = wallPaper; if (wallPaper != null) { TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(wallPaper.document.thumbs, 100); - setImage(thumb, "100_100", null, null, "jpg", 0, 1, wallPaper); + setImage(ImageLocation.getForDocument(thumb, wallPaper.document), "100_100", null, null, "jpg", 0, 1, wallPaper); } else { setImageDrawable(null); } @@ -1257,7 +1259,7 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle if (selectedPattern == null) { backgroundImage.setImageDrawable(null); } else { - backgroundImage.setImage(selectedPattern.document, imageFilter, null, null, "jpg", selectedPattern.document.size, 1, selectedPattern); + backgroundImage.setImage(ImageLocation.getForDocument(selectedPattern.document), imageFilter, null, null, "jpg", selectedPattern.document.size, 1, selectedPattern); } checkBoxView[1].setChecked(selectedPattern != null, false); @@ -1314,7 +1316,7 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle updateButtonState(radialProgress, null, WallpaperActivity.this, false, true); } else { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) patterns.get(position - 1); - backgroundImage.setImage(wallPaper.document, imageFilter, null, null, "jpg", wallPaper.document.size, 1, wallPaper); + backgroundImage.setImage(ImageLocation.getForDocument(wallPaper.document), imageFilter, null, null, "jpg", wallPaper.document.size, 1, wallPaper); selectedPattern = wallPaper; isMotion = checkBoxView[2].isChecked(); updateButtonState(radialProgress, null, WallpaperActivity.this, false, true); @@ -1702,12 +1704,12 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle if (currentWallpaper instanceof TLRPC.TL_wallPaper) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) currentWallpaper; TLRPC.PhotoSize thumb = setThumb ? FileLoader.getClosestPhotoSizeWithSize(wallPaper.document.thumbs, 100) : null; - backgroundImage.setImage(wallPaper.document, imageFilter, thumb, "100_100_b", "jpg", wallPaper.document.size, 1, wallPaper); + backgroundImage.setImage(ImageLocation.getForDocument(wallPaper.document), imageFilter, ImageLocation.getForDocument(thumb, wallPaper.document), "100_100_b", "jpg", wallPaper.document.size, 1, wallPaper); } else if (currentWallpaper instanceof WallpapersListActivity.ColorWallpaper) { WallpapersListActivity.ColorWallpaper wallPaper = (WallpapersListActivity.ColorWallpaper) currentWallpaper; setBackgroundColor(wallPaper.color); if (selectedPattern != null) { - backgroundImage.setImage(selectedPattern.document, imageFilter, null, null, "jpg", selectedPattern.document.size, 1, selectedPattern); + backgroundImage.setImage(ImageLocation.getForDocument(selectedPattern.document), imageFilter, null, null, "jpg", selectedPattern.document.size, 1, selectedPattern); } } else if (currentWallpaper instanceof WallpapersListActivity.FileWallpaper) { if (currentWallpaperBitmap != null) { @@ -1733,7 +1735,7 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle image = null; } int size = image != null ? image.size : 0; - backgroundImage.setImage(image, imageFilter, thumb, "100_100_b", "jpg", size, 1, wallPaper); + backgroundImage.setImage(ImageLocation.getForPhoto(image, wallPaper.photo), imageFilter, ImageLocation.getForPhoto(thumb, wallPaper.photo), "100_100_b", "jpg", size, 1, wallPaper); } else { backgroundImage.setImage(wallPaper.imageUrl, imageFilter, wallPaper.thumbUrl, "100_100_b"); } @@ -1997,6 +1999,6 @@ public class WallpaperActivity extends BaseFragment implements DownloadControlle arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inTimeSelectedText)); arrayList.add(new ThemeDescription(listView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outTimeSelectedText)); - return arrayList.toArray(new ThemeDescription[arrayList.size()]); + return arrayList.toArray(new ThemeDescription[0]); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersListActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersListActivity.java index 7d1672c23..d8d48c0f4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersListActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersListActivity.java @@ -48,8 +48,6 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.support.widget.LinearLayoutManager; -import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; @@ -77,6 +75,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + public class WallpapersListActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private int rowCount; @@ -283,6 +284,10 @@ public class WallpapersListActivity extends BaseFragment implements Notification for (int a = 0; a < defaultColors.length; a++) { wallPapers.add(new ColorWallpaper(-(a + 3), defaultColors[a])); } + if (currentType == TYPE_COLOR && patterns.isEmpty()) { + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.wallpapersDidLoad); + MessagesStorage.getInstance(currentAccount).getWallpapers(); + } } return super.onFragmentCreate(); } @@ -294,12 +299,13 @@ public class WallpapersListActivity extends BaseFragment implements Notification NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.wallpapersDidLoad); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didSetNewWallpapper); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.wallpapersNeedReload); + } else if (currentType == TYPE_COLOR) { + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.wallpapersDidLoad); } updater.cleanup(); super.onFragmentDestroy(); } - @SuppressWarnings("unchecked") @Override public View createView(Context context) { colorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -352,7 +358,7 @@ public class WallpapersListActivity extends BaseFragment implements Notification progressDialog.show(); ArrayList ids = new ArrayList<>(); - int deleteCount[] = new int[]{selectedWallPapers.size()}; + int[] deleteCount = new int[]{selectedWallPapers.size()}; for (int b = 0; b < selectedWallPapers.size(); b++) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) selectedWallPapers.valueAt(b); @@ -500,8 +506,8 @@ public class WallpapersListActivity extends BaseFragment implements Notification selectedMessagesCountTextView.setOnTouchListener((v, event) -> true); actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 65, 0, 0, 0)); - actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.ic_ab_forward, AndroidUtilities.dp(54))); - actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.ic_ab_delete, AndroidUtilities.dp(54))); + actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.msg_forward, AndroidUtilities.dp(54))); + actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54))); selectedWallPapers.clear(); } @@ -759,18 +765,20 @@ public class WallpapersListActivity extends BaseFragment implements Notification public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.wallpapersDidLoad) { ArrayList arrayList = (ArrayList) args[0]; - wallPapers.clear(); patterns.clear(); - allWallPapers.clear(); - allWallPapersDict.clear(); - allWallPapers.addAll(arrayList); + if (currentType != TYPE_COLOR) { + wallPapers.clear(); + allWallPapers.clear(); + allWallPapersDict.clear(); + allWallPapers.addAll(arrayList); + } for (int a = 0, N = arrayList.size(); a < N; a++) { TLRPC.TL_wallPaper wallPaper = arrayList.get(a); - allWallPapersDict.put(wallPaper.id, wallPaper); if (wallPaper.pattern) { patterns.add(wallPaper); } - if (!wallPaper.pattern || wallPaper.settings != null) { + if (currentType != TYPE_COLOR && (!wallPaper.pattern || wallPaper.settings != null)) { + allWallPapersDict.put(wallPaper.id, wallPaper); wallPapers.add(wallPaper); } } @@ -807,18 +815,20 @@ public class WallpapersListActivity extends BaseFragment implements Notification int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (response instanceof TLRPC.TL_account_wallPapers) { TLRPC.TL_account_wallPapers res = (TLRPC.TL_account_wallPapers) response; - wallPapers.clear(); patterns.clear(); - allWallPapersDict.clear(); - allWallPapers.clear(); - allWallPapers.addAll(res.wallpapers); + if (currentType != TYPE_COLOR) { + wallPapers.clear(); + allWallPapersDict.clear(); + allWallPapers.clear(); + allWallPapers.addAll(res.wallpapers); + } for (int a = 0, N = res.wallpapers.size(); a < N; a++) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) res.wallpapers.get(a); allWallPapersDict.put(wallPaper.id, wallPaper); if (wallPaper.pattern) { patterns.add(wallPaper); } - if (!wallPaper.pattern || wallPaper.settings != null) { + if (currentType != TYPE_COLOR && (!wallPaper.pattern || wallPaper.settings != null)) { wallPapers.add(wallPaper); } } @@ -869,7 +879,7 @@ public class WallpapersListActivity extends BaseFragment implements Notification if (wallPaper1.dark && wallPaper2.dark || !wallPaper1.dark && !wallPaper2.dark) { if (index1 > index2) { return 1; - } else if (index2 < index1) { + } else if (index1 < index2) { return -1; } else { return 0; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/WebviewActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/WebviewActivity.java index ed96ab12b..3e58a9aa4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/WebviewActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/WebviewActivity.java @@ -171,8 +171,10 @@ public class WebviewActivity extends BaseFragment { if (id == -1) { finishFragment(); } else if (id == share) { - currentMessageObject.messageOwner.with_my_score = false; - showDialog(ShareAlert.createShareAlert(getParentActivity(), currentMessageObject, null, false, linkToCopy, false)); + if (currentMessageObject != null) { + currentMessageObject.messageOwner.with_my_score = false; + showDialog(ShareAlert.createShareAlert(getParentActivity(), currentMessageObject, null, false, linkToCopy, false)); + } } else if (id == open_in) { openGameInBrowser(currentUrl, currentMessageObject, getParentActivity(), short_param, currentBot); } @@ -182,7 +184,7 @@ public class WebviewActivity extends BaseFragment { progressItem = menu.addItemWithWidth(share, R.drawable.share, AndroidUtilities.dp(54)); if (type == TYPE_GAME) { ActionBarMenuItem menuItem = menu.addItem(0, R.drawable.ic_ab_other); - menuItem.addSubItem(open_in, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)); + menuItem.addSubItem(open_in, R.drawable.msg_openin, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)); actionBar.setTitle(currentGame); actionBar.setSubtitle("@" + currentBot); @@ -208,6 +210,7 @@ public class WebviewActivity extends BaseFragment { progressView.setScaleY(1.0f); progressView.setVisibility(View.VISIBLE); progressItem.getImageView().setVisibility(View.GONE); + progressItem.setEnabled(false); } webView = new WebView(context); @@ -349,6 +352,7 @@ public class WebviewActivity extends BaseFragment { TLRPC.TL_messages_getStatsURL req = new TLRPC.TL_messages_getStatsURL(); req.peer = MessagesController.getInstance(currentAccount).getInputPeer((int) currentDialogId); req.params = params != null ? params : ""; + req.dark = Theme.getCurrentTheme().isDark(); ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { loadStats = false; if (response != null) { @@ -413,6 +417,7 @@ public class WebviewActivity extends BaseFragment { new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUBACKGROUND, null, null, null, null, Theme.key_actionBarDefaultSubmenuBackground), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM, null, null, null, null, Theme.key_actionBarDefaultSubmenuItem), + new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubmenuItemIcon), new ThemeDescription(progressView, 0, null, null, null, null, Theme.key_contextProgressInner2), new ThemeDescription(progressView, 0, null, null, null, null, Theme.key_contextProgressOuter2), @@ -428,6 +433,7 @@ public class WebviewActivity extends BaseFragment { new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_player_actionBarSelector), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUBACKGROUND, null, null, null, null, Theme.key_actionBarDefaultSubmenuBackground), new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM, null, null, null, null, Theme.key_actionBarDefaultSubmenuItem), + new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubmenuItemIcon), new ThemeDescription(progressView, 0, null, null, null, null, Theme.key_contextProgressInner4), new ThemeDescription(progressView, 0, null, null, null, null, Theme.key_contextProgressOuter4), diff --git a/TMessagesProj/src/main/res/anim/popup_context_in.xml b/TMessagesProj/src/main/res/anim/popup_context_in.xml new file mode 100644 index 000000000..05a8f814f --- /dev/null +++ b/TMessagesProj/src/main/res/anim/popup_context_in.xml @@ -0,0 +1,18 @@ + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ab_progress.png b/TMessagesProj/src/main/res/drawable-hdpi/ab_progress.png index 5792d48b2..f134949d8 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ab_progress.png and b/TMessagesProj/src/main/res/drawable-hdpi/ab_progress.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/account_add.png b/TMessagesProj/src/main/res/drawable-hdpi/account_add.png index 401342dfa..28e2a184a 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/account_add.png and b/TMessagesProj/src/main/res/drawable-hdpi/account_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/account_check.png b/TMessagesProj/src/main/res/drawable-hdpi/account_check.png index a6386072b..12fd63f71 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/account_check.png and b/TMessagesProj/src/main/res/drawable-hdpi/account_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/actions_addadmin.png b/TMessagesProj/src/main/res/drawable-hdpi/actions_addadmin.png index 8c8970772..26bd0f347 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/actions_addadmin.png and b/TMessagesProj/src/main/res/drawable-hdpi/actions_addadmin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/actions_addmember2.png b/TMessagesProj/src/main/res/drawable-hdpi/actions_addmember2.png index 19dc80574..6f1040055 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/actions_addmember2.png and b/TMessagesProj/src/main/res/drawable-hdpi/actions_addmember2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/actions_permissions.png b/TMessagesProj/src/main/res/drawable-hdpi/actions_permissions.png index e77d80ca1..43b384aca 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/actions_permissions.png and b/TMessagesProj/src/main/res/drawable-hdpi/actions_permissions.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/actions_remove_user.png b/TMessagesProj/src/main/res/drawable-hdpi/actions_remove_user.png index 41dc96387..4cc187a0a 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/actions_remove_user.png and b/TMessagesProj/src/main/res/drawable-hdpi/actions_remove_user.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/actions_removed.png b/TMessagesProj/src/main/res/drawable-hdpi/actions_removed.png index 1779a64bb..0459d48ba 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/actions_removed.png and b/TMessagesProj/src/main/res/drawable-hdpi/actions_removed.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/actions_setphoto.png b/TMessagesProj/src/main/res/drawable-hdpi/actions_setphoto.png index 2e279f06c..8940ea89e 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/actions_setphoto.png and b/TMessagesProj/src/main/res/drawable-hdpi/actions_setphoto.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/actions_viewmembers.png b/TMessagesProj/src/main/res/drawable-hdpi/actions_viewmembers.png index 621fa27c5..6cb63ee7d 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/actions_viewmembers.png and b/TMessagesProj/src/main/res/drawable-hdpi/actions_viewmembers.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/add.png b/TMessagesProj/src/main/res/drawable-hdpi/add.png index 1bd29eafd..4bf59bd53 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/add.png and b/TMessagesProj/src/main/res/drawable-hdpi/add.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/add_admin.png b/TMessagesProj/src/main/res/drawable-hdpi/add_admin.png index 2a4d183c4..b96daee10 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/add_admin.png and b/TMessagesProj/src/main/res/drawable-hdpi/add_admin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/add_contact_new.png b/TMessagesProj/src/main/res/drawable-hdpi/add_contact_new.png index 2a94e8893..861fad8a8 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/add_contact_new.png and b/TMessagesProj/src/main/res/drawable-hdpi/add_contact_new.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/animationpin.png b/TMessagesProj/src/main/res/drawable-hdpi/animationpin.png index 9ceaf6d52..65ae75844 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/animationpin.png and b/TMessagesProj/src/main/res/drawable-hdpi/animationpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/animationpinleft.png b/TMessagesProj/src/main/res/drawable-hdpi/animationpinleft.png index d6706666b..e3e90be68 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/animationpinleft.png and b/TMessagesProj/src/main/res/drawable-hdpi/animationpinleft.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/animationpinright.png b/TMessagesProj/src/main/res/drawable-hdpi/animationpinright.png index 597d4ab36..db90bf759 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/animationpinright.png and b/TMessagesProj/src/main/res/drawable-hdpi/animationpinright.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_audio.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_audio.png index 883013c26..66bfa5580 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/attach_audio.png and b/TMessagesProj/src/main/res/drawable-hdpi/attach_audio.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_close.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_close.png index ae1792926..7e2514144 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/attach_close.png and b/TMessagesProj/src/main/res/drawable-hdpi/attach_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_contact.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_contact.png index 8e76a17fd..5b8ff8501 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/attach_contact.png and b/TMessagesProj/src/main/res/drawable-hdpi/attach_contact.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_file.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_file.png index 8acffd9f2..6e11322a6 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/attach_file.png and b/TMessagesProj/src/main/res/drawable-hdpi/attach_file.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_gallery.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_gallery.png index d1eb0fb05..dd874454b 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/attach_gallery.png and b/TMessagesProj/src/main/res/drawable-hdpi/attach_gallery.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_location.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_location.png index 117fd214a..ab730e3cf 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/attach_location.png and b/TMessagesProj/src/main/res/drawable-hdpi/attach_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_polls.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_polls.png index 460f39763..2f7db0923 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/attach_polls.png and b/TMessagesProj/src/main/res/drawable-hdpi/attach_polls.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_send.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_send.png old mode 100755 new mode 100644 index 37d8fa26f..fa8b68e08 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/attach_send.png and b/TMessagesProj/src/main/res/drawable-hdpi/attach_send.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_video.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_video.png index 7fa7e978a..aa7184939 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/attach_video.png and b/TMessagesProj/src/main/res/drawable-hdpi/attach_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/audio_mini_arrow.png b/TMessagesProj/src/main/res/drawable-hdpi/audio_mini_arrow.png index dd89050e4..8e72bc9a2 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/audio_mini_arrow.png and b/TMessagesProj/src/main/res/drawable-hdpi/audio_mini_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/audio_mini_cancel.png b/TMessagesProj/src/main/res/drawable-hdpi/audio_mini_cancel.png index 43080c762..f0cb6fedc 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/audio_mini_cancel.png and b/TMessagesProj/src/main/res/drawable-hdpi/audio_mini_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/audiosend_pause.png b/TMessagesProj/src/main/res/drawable-hdpi/audiosend_pause.png index 4a8c89084..0d68a49d3 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/audiosend_pause.png and b/TMessagesProj/src/main/res/drawable-hdpi/audiosend_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/audiosend_play.png b/TMessagesProj/src/main/res/drawable-hdpi/audiosend_play.png index f032aeb38..c83726b7a 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/audiosend_play.png and b/TMessagesProj/src/main/res/drawable-hdpi/audiosend_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/authorize.png b/TMessagesProj/src/main/res/drawable-hdpi/authorize.png index 12df61a34..36b18aef9 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/authorize.png and b/TMessagesProj/src/main/res/drawable-hdpi/authorize.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/background_hd.jpg b/TMessagesProj/src/main/res/drawable-hdpi/background_hd.jpg old mode 100755 new mode 100644 index 1baf9f865..b21f280ba Binary files a/TMessagesProj/src/main/res/drawable-hdpi/background_hd.jpg and b/TMessagesProj/src/main/res/drawable-hdpi/background_hd.jpg differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/background_selected.png b/TMessagesProj/src/main/res/drawable-hdpi/background_selected.png index efaf6964e..4a6ac82a2 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/background_selected.png and b/TMessagesProj/src/main/res/drawable-hdpi/background_selected.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/bigcheck.png b/TMessagesProj/src/main/res/drawable-hdpi/bigcheck.png index e7c336bdc..35d9ae2b2 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/bigcheck.png and b/TMessagesProj/src/main/res/drawable-hdpi/bigcheck.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/blockpanel.png b/TMessagesProj/src/main/res/drawable-hdpi/blockpanel.png index b9f658a3a..006ce5cb9 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/blockpanel.png and b/TMessagesProj/src/main/res/drawable-hdpi/blockpanel.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/bluecounter.9.png b/TMessagesProj/src/main/res/drawable-hdpi/bluecounter.9.png index afafbee3b..61465c81f 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/bluecounter.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/bluecounter.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/blur_linear.png b/TMessagesProj/src/main/res/drawable-hdpi/blur_linear.png index 4067689eb..5dac89eb8 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/blur_linear.png and b/TMessagesProj/src/main/res/drawable-hdpi/blur_linear.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/blur_off.png b/TMessagesProj/src/main/res/drawable-hdpi/blur_off.png index 70dba57ce..04b207a65 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/blur_off.png and b/TMessagesProj/src/main/res/drawable-hdpi/blur_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/blur_radial.png b/TMessagesProj/src/main/res/drawable-hdpi/blur_radial.png index 205ea4aa1..1bbd25efc 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/blur_radial.png and b/TMessagesProj/src/main/res/drawable-hdpi/blur_radial.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/book_bot.png b/TMessagesProj/src/main/res/drawable-hdpi/book_bot.png index a46f3ff10..f38c1a2ee 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/book_bot.png and b/TMessagesProj/src/main/res/drawable-hdpi/book_bot.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/book_channel.png b/TMessagesProj/src/main/res/drawable-hdpi/book_channel.png index b4589d99c..d969b5f79 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/book_channel.png and b/TMessagesProj/src/main/res/drawable-hdpi/book_channel.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/book_group.png b/TMessagesProj/src/main/res/drawable-hdpi/book_group.png index e72578d6e..c1b6a3d42 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/book_group.png and b/TMessagesProj/src/main/res/drawable-hdpi/book_group.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/book_logo.png b/TMessagesProj/src/main/res/drawable-hdpi/book_logo.png index 634d8a342..1554a1416 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/book_logo.png and b/TMessagesProj/src/main/res/drawable-hdpi/book_logo.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/book_user.png b/TMessagesProj/src/main/res/drawable-hdpi/book_user.png index c39c07123..0a4565e38 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/book_user.png and b/TMessagesProj/src/main/res/drawable-hdpi/book_user.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/bookmark_large.png b/TMessagesProj/src/main/res/drawable-hdpi/bookmark_large.png deleted file mode 100755 index e59b4a9b8..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/bookmark_large.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/bot_file.png b/TMessagesProj/src/main/res/drawable-hdpi/bot_file.png index ce32afeee..9bc629bb9 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/bot_file.png and b/TMessagesProj/src/main/res/drawable-hdpi/bot_file.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/bot_keyboard.png b/TMessagesProj/src/main/res/drawable-hdpi/bot_keyboard.png deleted file mode 100755 index 68ba9865a..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/bot_keyboard.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/bot_keyboard2.png b/TMessagesProj/src/main/res/drawable-hdpi/bot_keyboard2.png deleted file mode 100755 index 5783d098e..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/bot_keyboard2.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/bot_lines.png b/TMessagesProj/src/main/res/drawable-hdpi/bot_lines.png index 3d80a3e40..634fde933 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/bot_lines.png and b/TMessagesProj/src/main/res/drawable-hdpi/bot_lines.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/bot_link.png b/TMessagesProj/src/main/res/drawable-hdpi/bot_link.png index 9fbea8cf5..61bf43aa0 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/bot_link.png and b/TMessagesProj/src/main/res/drawable-hdpi/bot_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/bot_location.png b/TMessagesProj/src/main/res/drawable-hdpi/bot_location.png index 8dffe4504..305781d5c 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/bot_location.png and b/TMessagesProj/src/main/res/drawable-hdpi/bot_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/bot_music.png b/TMessagesProj/src/main/res/drawable-hdpi/bot_music.png index 4cccd6ed2..22fcb2727 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/bot_music.png and b/TMessagesProj/src/main/res/drawable-hdpi/bot_music.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/bottom_shadow.png b/TMessagesProj/src/main/res/drawable-hdpi/bottom_shadow.png index c2d6c3756..918305f8a 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/bottom_shadow.png and b/TMessagesProj/src/main/res/drawable-hdpi/bottom_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/boxshadow.9.png b/TMessagesProj/src/main/res/drawable-hdpi/boxshadow.9.png index 9c4c66110..77b6f85cf 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/boxshadow.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/boxshadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/brightness_high.png b/TMessagesProj/src/main/res/drawable-hdpi/brightness_high.png index a1c0036b8..3a66805bf 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/brightness_high.png and b/TMessagesProj/src/main/res/drawable-hdpi/brightness_high.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/brightness_low.png b/TMessagesProj/src/main/res/drawable-hdpi/brightness_low.png index eaa64ecb7..2b0bd75d2 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/brightness_low.png and b/TMessagesProj/src/main/res/drawable-hdpi/brightness_low.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/broadcast3.png b/TMessagesProj/src/main/res/drawable-hdpi/broadcast3.png index 4c8a3328d..8cbb34bd5 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/broadcast3.png and b/TMessagesProj/src/main/res/drawable-hdpi/broadcast3.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/broadcast_w.png b/TMessagesProj/src/main/res/drawable-hdpi/broadcast_w.png index 007323ebc..9bf4aeee9 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/broadcast_w.png and b/TMessagesProj/src/main/res/drawable-hdpi/broadcast_w.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/btnshadow.9.png b/TMessagesProj/src/main/res/drawable-hdpi/btnshadow.9.png index a75bd31af..9befa1507 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/btnshadow.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/btnshadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/burn.png b/TMessagesProj/src/main/res/drawable-hdpi/burn.png index 219acbb48..0e2d40342 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/burn.png and b/TMessagesProj/src/main/res/drawable-hdpi/burn.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/camera_btn.png b/TMessagesProj/src/main/res/drawable-hdpi/camera_btn.png index 587e65d6f..bb17f21cb 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/camera_btn.png and b/TMessagesProj/src/main/res/drawable-hdpi/camera_btn.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/camera_revert1.png b/TMessagesProj/src/main/res/drawable-hdpi/camera_revert1.png index dfcb6c43d..7cf7678de 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/camera_revert1.png and b/TMessagesProj/src/main/res/drawable-hdpi/camera_revert1.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/camera_revert2.png b/TMessagesProj/src/main/res/drawable-hdpi/camera_revert2.png index fab3c886c..787886219 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/camera_revert2.png and b/TMessagesProj/src/main/res/drawable-hdpi/camera_revert2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/cancel_big.png b/TMessagesProj/src/main/res/drawable-hdpi/cancel_big.png index 2dadadc3f..96035d5cc 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/cancel_big.png and b/TMessagesProj/src/main/res/drawable-hdpi/cancel_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/channelintro.png b/TMessagesProj/src/main/res/drawable-hdpi/channelintro.png index 7a9b8b497..c46fcb3c6 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/channelintro.png and b/TMessagesProj/src/main/res/drawable-hdpi/channelintro.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/chats_archive.png b/TMessagesProj/src/main/res/drawable-hdpi/chats_archive.png new file mode 100644 index 000000000..2dc731bc5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/chats_archive.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_arrow.png b/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_arrow.png new file mode 100644 index 000000000..64ff332ef Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_box.png b/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_box.png new file mode 100644 index 000000000..a3485aa9f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_box.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_hide.png b/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_hide.png new file mode 100644 index 000000000..170d26991 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_hide.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_muted.png b/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_muted.png new file mode 100644 index 000000000..c27940ae2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_muted.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_pin.png b/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_pin.png new file mode 100644 index 000000000..f20c8c706 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_show.png b/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_show.png new file mode 100644 index 000000000..df2dde739 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/chats_archive_show.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/chats_clear.png b/TMessagesProj/src/main/res/drawable-hdpi/chats_clear.png deleted file mode 100644 index 0ae1bc5d2..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/chats_clear.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/chats_delete.png b/TMessagesProj/src/main/res/drawable-hdpi/chats_delete.png index 500405a42..9ed4a30de 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/chats_delete.png and b/TMessagesProj/src/main/res/drawable-hdpi/chats_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/chats_leave.png b/TMessagesProj/src/main/res/drawable-hdpi/chats_leave.png index 8fa0a7a1c..b5d8aa31c 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/chats_leave.png and b/TMessagesProj/src/main/res/drawable-hdpi/chats_leave.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/chats_pin.png b/TMessagesProj/src/main/res/drawable-hdpi/chats_pin.png index 12e9562a8..751476b12 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/chats_pin.png and b/TMessagesProj/src/main/res/drawable-hdpi/chats_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/chats_saved.png b/TMessagesProj/src/main/res/drawable-hdpi/chats_saved.png new file mode 100644 index 000000000..a4a4830c2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/chats_saved.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/chats_unarchive.png b/TMessagesProj/src/main/res/drawable-hdpi/chats_unarchive.png new file mode 100644 index 000000000..bc03eb21f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/chats_unarchive.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/chats_undo.png b/TMessagesProj/src/main/res/drawable-hdpi/chats_undo.png index bfb23e3c8..bc86be1a0 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/chats_undo.png and b/TMessagesProj/src/main/res/drawable-hdpi/chats_undo.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/chats_unpin.png b/TMessagesProj/src/main/res/drawable-hdpi/chats_unpin.png index 4659ddb08..c11e9e1e2 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/chats_unpin.png and b/TMessagesProj/src/main/res/drawable-hdpi/chats_unpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/checkbig.png b/TMessagesProj/src/main/res/drawable-hdpi/checkbig.png index 6eea2cf85..cfc73dd08 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/checkbig.png and b/TMessagesProj/src/main/res/drawable-hdpi/checkbig.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/circle.png b/TMessagesProj/src/main/res/drawable-hdpi/circle.png index fb0b2f899..ce1018b1f 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/circle.png and b/TMessagesProj/src/main/res/drawable-hdpi/circle.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/circle_big.png b/TMessagesProj/src/main/res/drawable-hdpi/circle_big.png index 4a0f8dd5f..f65999d44 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/circle_big.png and b/TMessagesProj/src/main/res/drawable-hdpi/circle_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/cloud_big.png b/TMessagesProj/src/main/res/drawable-hdpi/cloud_big.png index dfd33d5bb..1416de322 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/cloud_big.png and b/TMessagesProj/src/main/res/drawable-hdpi/cloud_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/collapse_down.png b/TMessagesProj/src/main/res/drawable-hdpi/collapse_down.png index 4037d4f58..923e09750 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/collapse_down.png and b/TMessagesProj/src/main/res/drawable-hdpi/collapse_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/collapse_up.png b/TMessagesProj/src/main/res/drawable-hdpi/collapse_up.png index 651b2dd50..071e5894e 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/collapse_up.png and b/TMessagesProj/src/main/res/drawable-hdpi/collapse_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/compose_panel_shadow.png b/TMessagesProj/src/main/res/drawable-hdpi/compose_panel_shadow.png index afde14d30..262020886 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/compose_panel_shadow.png and b/TMessagesProj/src/main/res/drawable-hdpi/compose_panel_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/contacts_sort_name.png b/TMessagesProj/src/main/res/drawable-hdpi/contacts_sort_name.png index 756d2676f..5a9e50ed5 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/contacts_sort_name.png and b/TMessagesProj/src/main/res/drawable-hdpi/contacts_sort_name.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/contacts_sort_time.png b/TMessagesProj/src/main/res/drawable-hdpi/contacts_sort_time.png index 7e087a698..a534cecd9 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/contacts_sort_time.png and b/TMessagesProj/src/main/res/drawable-hdpi/contacts_sort_time.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/corner_in_bl.png b/TMessagesProj/src/main/res/drawable-hdpi/corner_in_bl.png index 76fac7c47..3216380b1 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/corner_in_bl.png and b/TMessagesProj/src/main/res/drawable-hdpi/corner_in_bl.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/corner_in_br.png b/TMessagesProj/src/main/res/drawable-hdpi/corner_in_br.png index 336ffd5de..c45255775 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/corner_in_br.png and b/TMessagesProj/src/main/res/drawable-hdpi/corner_in_br.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/corner_in_tl.png b/TMessagesProj/src/main/res/drawable-hdpi/corner_in_tl.png index 50d82e546..d51b8bd28 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/corner_in_tl.png and b/TMessagesProj/src/main/res/drawable-hdpi/corner_in_tl.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/corner_in_tr.png b/TMessagesProj/src/main/res/drawable-hdpi/corner_in_tr.png index c8f77c77c..ea708a3ea 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/corner_in_tr.png and b/TMessagesProj/src/main/res/drawable-hdpi/corner_in_tr.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/corner_out_bl.png b/TMessagesProj/src/main/res/drawable-hdpi/corner_out_bl.png index 919027012..d3c36763f 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/corner_out_bl.png and b/TMessagesProj/src/main/res/drawable-hdpi/corner_out_bl.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/corner_out_br.png b/TMessagesProj/src/main/res/drawable-hdpi/corner_out_br.png index d3774e9eb..a314e7886 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/corner_out_br.png and b/TMessagesProj/src/main/res/drawable-hdpi/corner_out_br.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/corner_out_tl.png b/TMessagesProj/src/main/res/drawable-hdpi/corner_out_tl.png index 69b666400..0803c64a8 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/corner_out_tl.png and b/TMessagesProj/src/main/res/drawable-hdpi/corner_out_tl.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/corner_out_tr.png b/TMessagesProj/src/main/res/drawable-hdpi/corner_out_tr.png index 223a637da..5c21ae517 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/corner_out_tr.png and b/TMessagesProj/src/main/res/drawable-hdpi/corner_out_tr.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/delete.png b/TMessagesProj/src/main/res/drawable-hdpi/delete.png index 79c04e5f2..fccd26a4a 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/delete.png and b/TMessagesProj/src/main/res/drawable-hdpi/delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/devices.png b/TMessagesProj/src/main/res/drawable-hdpi/devices.png index 71ffe85e0..d72e42b81 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/devices.png and b/TMessagesProj/src/main/res/drawable-hdpi/devices.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/doc_big.png b/TMessagesProj/src/main/res/drawable-hdpi/doc_big.png index 5368ac95f..3973173e7 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/doc_big.png and b/TMessagesProj/src/main/res/drawable-hdpi/doc_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/edit_cancel.png b/TMessagesProj/src/main/res/drawable-hdpi/edit_cancel.png index 8fb629d04..81dd1ae61 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/edit_cancel.png and b/TMessagesProj/src/main/res/drawable-hdpi/edit_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/edit_done.png b/TMessagesProj/src/main/res/drawable-hdpi/edit_done.png deleted file mode 100755 index 9dd3864b4..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/edit_done.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/fast_reply.png b/TMessagesProj/src/main/res/drawable-hdpi/fast_reply.png index a784350ba..052386e79 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/fast_reply.png and b/TMessagesProj/src/main/res/drawable-hdpi/fast_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/flame_small.png b/TMessagesProj/src/main/res/drawable-hdpi/flame_small.png index 40773a63c..5d8ff850b 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/flame_small.png and b/TMessagesProj/src/main/res/drawable-hdpi/flame_small.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/flash_auto.png b/TMessagesProj/src/main/res/drawable-hdpi/flash_auto.png index 8535c5365..bd7b1629b 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/flash_auto.png and b/TMessagesProj/src/main/res/drawable-hdpi/flash_auto.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/flash_off.png b/TMessagesProj/src/main/res/drawable-hdpi/flash_off.png index 926589853..ce1ea3d82 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/flash_off.png and b/TMessagesProj/src/main/res/drawable-hdpi/flash_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/flash_on.png b/TMessagesProj/src/main/res/drawable-hdpi/flash_on.png index 91d79499c..d59f1d90f 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/flash_on.png and b/TMessagesProj/src/main/res/drawable-hdpi/flash_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/floating_camera.png b/TMessagesProj/src/main/res/drawable-hdpi/floating_camera.png index 7d1701ef8..d03697daf 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/floating_camera.png and b/TMessagesProj/src/main/res/drawable-hdpi/floating_camera.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/floating_message.png b/TMessagesProj/src/main/res/drawable-hdpi/floating_message.png index 7fb41f8bc..149d47ab6 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/floating_message.png and b/TMessagesProj/src/main/res/drawable-hdpi/floating_message.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/floating_pencil.png b/TMessagesProj/src/main/res/drawable-hdpi/floating_pencil.png index 69c48cd41..8889aa003 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/floating_pencil.png and b/TMessagesProj/src/main/res/drawable-hdpi/floating_pencil.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/floating_shadow.png b/TMessagesProj/src/main/res/drawable-hdpi/floating_shadow.png index 25e06ca7c..3a5fcd7cf 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/floating_shadow.png and b/TMessagesProj/src/main/res/drawable-hdpi/floating_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/floating_shadow_profile.png b/TMessagesProj/src/main/res/drawable-hdpi/floating_shadow_profile.png index 5cece6401..8f7c2ca41 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/floating_shadow_profile.png and b/TMessagesProj/src/main/res/drawable-hdpi/floating_shadow_profile.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/forwardvideo.png b/TMessagesProj/src/main/res/drawable-hdpi/forwardvideo.png index 44a3434d3..28ba9f86a 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/forwardvideo.png and b/TMessagesProj/src/main/res/drawable-hdpi/forwardvideo.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/foursquare.png b/TMessagesProj/src/main/res/drawable-hdpi/foursquare.png index ca3a16b3a..4650d7f77 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/foursquare.png and b/TMessagesProj/src/main/res/drawable-hdpi/foursquare.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/gif_empty.png b/TMessagesProj/src/main/res/drawable-hdpi/gif_empty.png new file mode 100644 index 000000000..75b69f509 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/gif_empty.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/go_to_message.png b/TMessagesProj/src/main/res/drawable-hdpi/go_to_message.png deleted file mode 100644 index b71236e8c..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/go_to_message.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/greydivider.9.png b/TMessagesProj/src/main/res/drawable-hdpi/greydivider.9.png index 1cfd119be..b7a999c44 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/greydivider.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/greydivider.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/greydivider_bottom.9.png b/TMessagesProj/src/main/res/drawable-hdpi/greydivider_bottom.9.png index e9b7c009b..55d4fe8ac 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/greydivider_bottom.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/greydivider_bottom.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/greydivider_top.9.png b/TMessagesProj/src/main/res/drawable-hdpi/greydivider_top.9.png index 32a461249..0caebabec 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/greydivider_top.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/greydivider_top.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/group_addmember.png b/TMessagesProj/src/main/res/drawable-hdpi/group_addmember.png index a633067a0..3e8a48077 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/group_addmember.png and b/TMessagesProj/src/main/res/drawable-hdpi/group_addmember.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/group_admin.png b/TMessagesProj/src/main/res/drawable-hdpi/group_admin.png index a9e269ef4..f759c04ea 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/group_admin.png and b/TMessagesProj/src/main/res/drawable-hdpi/group_admin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/group_admin_new.png b/TMessagesProj/src/main/res/drawable-hdpi/group_admin_new.png index de4076527..dbd6b12a7 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/group_admin_new.png and b/TMessagesProj/src/main/res/drawable-hdpi/group_admin_new.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/group_ban_empty.png b/TMessagesProj/src/main/res/drawable-hdpi/group_ban_empty.png index 9e2c5a1a9..acb87d598 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/group_ban_empty.png and b/TMessagesProj/src/main/res/drawable-hdpi/group_ban_empty.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/group_ban_new.png b/TMessagesProj/src/main/res/drawable-hdpi/group_ban_new.png index 713ac7d51..9d7731485 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/group_ban_new.png and b/TMessagesProj/src/main/res/drawable-hdpi/group_ban_new.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/group_banned.png b/TMessagesProj/src/main/res/drawable-hdpi/group_banned.png index ca5298aed..fdbbed10a 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/group_banned.png and b/TMessagesProj/src/main/res/drawable-hdpi/group_banned.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/group_edit.png b/TMessagesProj/src/main/res/drawable-hdpi/group_edit.png index d7d36c0ef..f2157994c 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/group_edit.png and b/TMessagesProj/src/main/res/drawable-hdpi/group_edit.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/group_edit_profile.png b/TMessagesProj/src/main/res/drawable-hdpi/group_edit_profile.png index 661e77566..b5126b168 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/group_edit_profile.png and b/TMessagesProj/src/main/res/drawable-hdpi/group_edit_profile.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/group_log.png b/TMessagesProj/src/main/res/drawable-hdpi/group_log.png index b6b90c6f1..32eae119b 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/group_log.png and b/TMessagesProj/src/main/res/drawable-hdpi/group_log.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/groups_overview_check.png b/TMessagesProj/src/main/res/drawable-hdpi/groups_overview_check.png index 635aa9fb5..875403a39 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/groups_overview_check.png and b/TMessagesProj/src/main/res/drawable-hdpi/groups_overview_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/header_shadow.png b/TMessagesProj/src/main/res/drawable-hdpi/header_shadow.png index 9adb8afca..8a92c34ac 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/header_shadow.png and b/TMessagesProj/src/main/res/drawable-hdpi/header_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/header_shadow_reverse.png b/TMessagesProj/src/main/res/drawable-hdpi/header_shadow_reverse.png index 57ccb3eb2..4f74e66b6 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/header_shadow_reverse.png and b/TMessagesProj/src/main/res/drawable-hdpi/header_shadow_reverse.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_attach.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_attach.png deleted file mode 100755 index 4a2855b21..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_attach.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_back.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_back.png index 5fa494878..fe424468e 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_back.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_back.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_copy.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_copy.png index 761096b47..d04909b69 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_copy.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_copy.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_delete.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_delete.png index 257f5d4e9..986e7b899 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_delete.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_done.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_done.png index 7152d5739..8c81c1525 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_done.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_done.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_fave.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_fave.png index ef4fe8256..310d45a5a 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_fave.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_fave.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_forward.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_forward.png index 474b0fd33..6af59fc31 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_forward.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_new.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_new.png index 890c3367c..8db1903b8 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_new.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_new.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_other.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_other.png index fdc4a5ad2..95c025f09 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_other.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_other.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_reply.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_reply.png index 0b4e6a813..b02393e92 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_reply.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_reply2.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_reply2.png index 3df84d52a..6775d9b9c 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_reply2.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_reply2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_search.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_search.png index a2fc5b2e7..452a8970d 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_search.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_unfave.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_unfave.png index bbc49e436..953419212 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_unfave.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_unfave.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_again.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_again.png index e8116a335..51381a981 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_again.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_again.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_againinline.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_againinline.png index 391b7b5f1..b943d84f8 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_againinline.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_againinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_arrow_drop_down.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_arrow_drop_down.png index c9dab492a..622e66ffe 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_arrow_drop_down.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_arrow_drop_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_bluetooth_white_24dp.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_bluetooth_white_24dp.png index fce188400..d42c2bb14 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_bluetooth_white_24dp.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_bluetooth_white_24dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_call.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_call.png new file mode 100644 index 000000000..9c0766652 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/ic_call.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_call_made_green_18dp.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_call_made_green_18dp.png index 0c96e2e94..50b2464b9 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_call_made_green_18dp.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_call_made_green_18dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_call_received_green_18dp.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_call_received_green_18dp.png index 49daf602a..4455c0458 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_call_received_green_18dp.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_call_received_green_18dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_call_white_24dp.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_call_white_24dp.png deleted file mode 100755 index 4dc506515..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_call_white_24dp.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_close_white.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_close_white.png index 0fd15563a..a32831e3c 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_close_white.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_close_white.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_directory.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_directory.png index a13bd1569..36b1e7089 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_directory.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_directory.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_done.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_done.png index f42a0e2d2..8c81c1525 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_done.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_done.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_external_storage.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_external_storage.png index b9b8af36a..825a029d8 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_external_storage.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_external_storage.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_fp_40px.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_fp_40px.png index 48ebd8ad7..3d6eef451 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_fp_40px.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_fp_40px.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_gallery_background.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_gallery_background.png index 4d3fb8407..9c1b36856 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_gallery_background.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_gallery_background.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_gofullscreen.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_gofullscreen.png index a77ad403a..6e9f9652c 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_gofullscreen.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_gofullscreen.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_goinline.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_goinline.png index e7ddb90a6..8f7849e3b 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_goinline.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_goinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_keyboard_w.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_keyboard_w.png deleted file mode 100755 index f0b6a5da5..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_keyboard_w.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_launcher.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_launcher.png deleted file mode 100755 index 625167422..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_launcher.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_launcher_dr.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_launcher_dr.png new file mode 100644 index 000000000..6e16733c9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/ic_launcher_dr.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_lock_header.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_lock_header.png index 07be8fc72..5d480448e 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_lock_header.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_lock_header.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_lock_white.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_lock_white.png index f1d8caecd..34afbbbc5 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_lock_white.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_lock_white.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_masks_msk1.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_masks_msk1.png index b4354ed7e..7ec6e37be 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_masks_msk1.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_masks_msk1.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_masks_recent1.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_masks_recent1.png index fd4c9f076..8bb65fe3c 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_masks_recent1.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_masks_recent1.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_masks_sticker1.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_masks_sticker1.png index aed1f2c92..839e06603 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_masks_sticker1.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_masks_sticker1.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_msg_panel_gif.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_msg_panel_gif.png deleted file mode 100755 index b7b3569ce..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_msg_panel_gif.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_msg_panel_kb.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_msg_panel_kb.png deleted file mode 100755 index f5dd8c7d7..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_msg_panel_kb.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_msg_panel_smiles.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_msg_panel_smiles.png deleted file mode 100755 index 94ef04311..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_msg_panel_smiles.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_msg_panel_stickers.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_msg_panel_stickers.png deleted file mode 100755 index c481140e2..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_msg_panel_stickers.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_msg_panel_video.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_msg_panel_video.png deleted file mode 100755 index 692955933..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_msg_panel_video.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_outfullscreen.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_outfullscreen.png index d27b1101d..d48664a76 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_outfullscreen.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_outfullscreen.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_outinline.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_outinline.png index 43d650434..868469b22 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_outinline.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_outinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_pause.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_pause.png index 630f0e5df..5882c75fe 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_pause.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_pauseinline.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_pauseinline.png index 6efd86472..389c4101b 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_pauseinline.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_pauseinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_play.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_play.png index e04ea8a3a..86709a9af 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_play.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_playinline.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_playinline.png index a2d21e6b3..d2562fcf2 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_playinline.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_playinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_rating_star.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_rating_star.png index dc6a99f91..557538de2 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_rating_star.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_rating_star.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_rating_star_filled.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_rating_star_filled.png index b4a6325d1..38c6014f3 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_rating_star_filled.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_rating_star_filled.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_reply_icon.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_reply_icon.png index f483f3427..ebe314ac6 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_reply_icon.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_reply_icon.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_send.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_send.png index ffa715e32..1be7ad942 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_send.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_send.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_share_article.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_share_article.png index e23af5fcb..50949ba34 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_share_article.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_share_article.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_share_video.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_share_video.png index 9a90837c2..e428faa28 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_share_video.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_share_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_smile_small.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_smile_small.png deleted file mode 100644 index 82d646751..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_smile_small.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_smile_w.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_smile_w.png deleted file mode 100755 index 2f8711cd9..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_smile_w.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_car.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_car.png deleted file mode 100755 index 8648c6e84..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_car.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_food.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_food.png deleted file mode 100755 index b0e92a314..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_food.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_nature.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_nature.png deleted file mode 100755 index 3fd0a3ef0..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_nature.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_objects.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_objects.png deleted file mode 100755 index f834a4242..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_objects.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_recent.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_recent.png deleted file mode 100755 index 63d98b603..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_recent.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_sad.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_sad.png index 804475310..2c8cc7f3a 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_sad.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_sad.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_smile.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_smile.png deleted file mode 100755 index 3411fd33c..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_smile.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_stickers.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_stickers.png deleted file mode 100755 index 7f0ac891f..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles2_stickers.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles_backspace.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles_backspace.png deleted file mode 100755 index 19eb21d5e..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles_backspace.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles_gif.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles_gif.png deleted file mode 100755 index 016963ba6..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles_gif.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles_settings.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles_settings.png deleted file mode 100755 index 0c1b57df3..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles_settings.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles_trend.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles_trend.png deleted file mode 100755 index 30c53cfaa..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_smiles_trend.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_storage.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_storage.png index 014219a19..194b7d8ef 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_storage.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_storage.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_storage_gallery.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_storage_gallery.png index 01e504f42..fec1938d3 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_storage_gallery.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_storage_gallery.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_storage_music.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_storage_music.png index e7ddbf2f9..b7da88c0f 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_storage_music.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_storage_music.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_video.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_video.png index c2c017260..8160264c3 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_video.png and b/TMessagesProj/src/main/res/drawable-hdpi/ic_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/inline_video_pause.png b/TMessagesProj/src/main/res/drawable-hdpi/inline_video_pause.png index 4832b585c..6dd5b7951 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/inline_video_pause.png and b/TMessagesProj/src/main/res/drawable-hdpi/inline_video_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/inline_video_play.png b/TMessagesProj/src/main/res/drawable-hdpi/inline_video_play.png index 981f5fb21..3c7bc10a7 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/inline_video_play.png and b/TMessagesProj/src/main/res/drawable-hdpi/inline_video_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_attach.png b/TMessagesProj/src/main/res/drawable-hdpi/input_attach.png new file mode 100644 index 000000000..57a5a5185 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_attach.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_bot1.png b/TMessagesProj/src/main/res/drawable-hdpi/input_bot1.png new file mode 100644 index 000000000..f5fddbe29 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_bot1.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_bot2.png b/TMessagesProj/src/main/res/drawable-hdpi/input_bot2.png new file mode 100644 index 000000000..eaecf8c1f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_bot2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_clear.png b/TMessagesProj/src/main/res/drawable-hdpi/input_clear.png new file mode 100644 index 000000000..2bfaebd8b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_done.png b/TMessagesProj/src/main/res/drawable-hdpi/input_done.png new file mode 100644 index 000000000..e35e3ddd2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_done.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_forward.png b/TMessagesProj/src/main/res/drawable-hdpi/input_forward.png new file mode 100644 index 000000000..75e547093 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_gif.png b/TMessagesProj/src/main/res/drawable-hdpi/input_gif.png new file mode 100644 index 000000000..eb517c42f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_keyboard.png b/TMessagesProj/src/main/res/drawable-hdpi/input_keyboard.png new file mode 100644 index 000000000..e8f7779d9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_keyboard.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_mic.png b/TMessagesProj/src/main/res/drawable-hdpi/input_mic.png new file mode 100644 index 000000000..e34ad493f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_mic.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_notify_off.png b/TMessagesProj/src/main/res/drawable-hdpi/input_notify_off.png new file mode 100644 index 000000000..283703fdc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_notify_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_notify_on.png b/TMessagesProj/src/main/res/drawable-hdpi/input_notify_on.png new file mode 100644 index 000000000..8b2ddbc98 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_notify_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_reply.png b/TMessagesProj/src/main/res/drawable-hdpi/input_reply.png new file mode 100644 index 000000000..5e1868710 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_smile.png b/TMessagesProj/src/main/res/drawable-hdpi/input_smile.png new file mode 100644 index 000000000..c3acc1a2b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_smile.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_sticker.png b/TMessagesProj/src/main/res/drawable-hdpi/input_sticker.png new file mode 100644 index 000000000..952ee4337 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_sticker.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/input_video.png b/TMessagesProj/src/main/res/drawable-hdpi/input_video.png new file mode 100644 index 000000000..bd1d5fe93 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/input_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/instant_camera.png b/TMessagesProj/src/main/res/drawable-hdpi/instant_camera.png index 44f8c061f..de6404d5f 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/instant_camera.png and b/TMessagesProj/src/main/res/drawable-hdpi/instant_camera.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/instant_link.png b/TMessagesProj/src/main/res/drawable-hdpi/instant_link.png index c7ff7786e..af41b2025 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/instant_link.png and b/TMessagesProj/src/main/res/drawable-hdpi/instant_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_fast_arrow.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_fast_arrow.png index 7a835e5cc..46850d299 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_fast_arrow.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_fast_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_fast_arrow_shadow.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_fast_arrow_shadow.png index 71d8731a0..854523a2c 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_fast_arrow_shadow.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_fast_arrow_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_fast_body.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_fast_body.png index 8960f4cce..bbb12b166 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_fast_body.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_fast_body.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_fast_spiral.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_fast_spiral.png index 4e328347c..8ee8ca78c 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_fast_spiral.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_fast_spiral.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_bubble.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_bubble.png index a22b99fcf..e11f1bd96 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_bubble.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_bubble.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_bubble_dot.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_bubble_dot.png index 4fb0563c3..0411d28ab 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_bubble_dot.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_bubble_dot.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_cam.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_cam.png index 3e9ac9c4c..f43036cb8 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_cam.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_cam.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_cam_lens.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_cam_lens.png index a2b598b86..abee554ed 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_cam_lens.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_cam_lens.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_pencil.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_pencil.png index 3ea76136b..f8774abbe 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_pencil.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_pencil.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_pin.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_pin.png index 5ee93c8fe..6815b778b 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_pin.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_smile.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_smile.png index b2a06031b..922be73e6 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_smile.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_smile.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_smile_eye.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_smile_eye.png index c38bb6b3c..39106f184 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_smile_eye.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_smile_eye.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_videocam.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_videocam.png index f7787655b..1840b1b59 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_videocam.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_ic_videocam.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_knot_down.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_knot_down.png index 5eeab7bc9..61c6cc828 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_knot_down.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_knot_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_knot_up.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_knot_up.png index d2c38e6de..1cc83d782 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_knot_up.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_knot_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_powerful_infinity.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_powerful_infinity.png index cfc1182b5..28b1082c5 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_powerful_infinity.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_powerful_infinity.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_powerful_infinity_white.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_powerful_infinity_white.png index 85a9f6d0b..ef3b2bdca 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_powerful_infinity_white.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_powerful_infinity_white.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_powerful_mask.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_powerful_mask.png index 1706123bf..5112ff6de 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_powerful_mask.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_powerful_mask.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_powerful_star.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_powerful_star.png index 32b1352a2..a7b23643a 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_powerful_star.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_powerful_star.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_private_door.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_private_door.png index 58c3bcbf2..88fd08074 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_private_door.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_private_door.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_private_screw.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_private_screw.png index fa2dd4f9c..09703406d 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_private_screw.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_private_screw.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_tg_plane.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_tg_plane.png index 57c6124f0..7a822ed9a 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_tg_plane.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_tg_plane.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/intro_tg_sphere.png b/TMessagesProj/src/main/res/drawable-hdpi/intro_tg_sphere.png index 3a0a11455..7f6e497af 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/intro_tg_sphere.png and b/TMessagesProj/src/main/res/drawable-hdpi/intro_tg_sphere.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/knob_shadow.png b/TMessagesProj/src/main/res/drawable-hdpi/knob_shadow.png index 746b0adcf..ef2c82c24 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/knob_shadow.png and b/TMessagesProj/src/main/res/drawable-hdpi/knob_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/layer_shadow.png b/TMessagesProj/src/main/res/drawable-hdpi/layer_shadow.png index 9bb9bf101..d72891973 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/layer_shadow.png and b/TMessagesProj/src/main/res/drawable-hdpi/layer_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/list_bot.png b/TMessagesProj/src/main/res/drawable-hdpi/list_bot.png index 4e1616512..4d41b59b9 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/list_bot.png and b/TMessagesProj/src/main/res/drawable-hdpi/list_bot.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/list_broadcast.png b/TMessagesProj/src/main/res/drawable-hdpi/list_broadcast.png index 46876a5e1..d89282468 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/list_broadcast.png and b/TMessagesProj/src/main/res/drawable-hdpi/list_broadcast.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/list_check.png b/TMessagesProj/src/main/res/drawable-hdpi/list_check.png old mode 100755 new mode 100644 index 3b578669b..8f21f0f8c Binary files a/TMessagesProj/src/main/res/drawable-hdpi/list_check.png and b/TMessagesProj/src/main/res/drawable-hdpi/list_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/list_circle.png b/TMessagesProj/src/main/res/drawable-hdpi/list_circle.png index e6c27d1d8..9236ee815 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/list_circle.png and b/TMessagesProj/src/main/res/drawable-hdpi/list_circle.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/list_group.png b/TMessagesProj/src/main/res/drawable-hdpi/list_group.png index 4b2e05477..c59dd7a27 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/list_group.png and b/TMessagesProj/src/main/res/drawable-hdpi/list_group.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/list_halfcheck.png b/TMessagesProj/src/main/res/drawable-hdpi/list_halfcheck.png old mode 100755 new mode 100644 index dc9b8f279..5cc9a09ec Binary files a/TMessagesProj/src/main/res/drawable-hdpi/list_halfcheck.png and b/TMessagesProj/src/main/res/drawable-hdpi/list_halfcheck.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/list_mute.png b/TMessagesProj/src/main/res/drawable-hdpi/list_mute.png old mode 100755 new mode 100644 index 4835db6f5..6886760b0 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/list_mute.png and b/TMessagesProj/src/main/res/drawable-hdpi/list_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/list_pin.png b/TMessagesProj/src/main/res/drawable-hdpi/list_pin.png old mode 100755 new mode 100644 index 9a1030ff6..eabebd24e Binary files a/TMessagesProj/src/main/res/drawable-hdpi/list_pin.png and b/TMessagesProj/src/main/res/drawable-hdpi/list_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/list_reorder.png b/TMessagesProj/src/main/res/drawable-hdpi/list_reorder.png new file mode 100644 index 000000000..4928a9d54 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/list_reorder.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/list_secret.png b/TMessagesProj/src/main/res/drawable-hdpi/list_secret.png index 80d702f86..6a7f312c5 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/list_secret.png and b/TMessagesProj/src/main/res/drawable-hdpi/list_secret.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/list_warning_sign.png b/TMessagesProj/src/main/res/drawable-hdpi/list_warning_sign.png index 0a0ac17b6..379f633b4 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/list_warning_sign.png and b/TMessagesProj/src/main/res/drawable-hdpi/list_warning_sign.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/live_loc.png b/TMessagesProj/src/main/res/drawable-hdpi/live_loc.png index e43eb0949..b319350e1 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/live_loc.png and b/TMessagesProj/src/main/res/drawable-hdpi/live_loc.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/livelocationpin.png b/TMessagesProj/src/main/res/drawable-hdpi/livelocationpin.png index 0becef33d..ab15ff8e0 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/livelocationpin.png and b/TMessagesProj/src/main/res/drawable-hdpi/livelocationpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/livepin.png b/TMessagesProj/src/main/res/drawable-hdpi/livepin.png index 6f2692940..ac6680e83 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/livepin.png and b/TMessagesProj/src/main/res/drawable-hdpi/livepin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/load_big.png b/TMessagesProj/src/main/res/drawable-hdpi/load_big.png index 6a082f283..be3229365 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/load_big.png and b/TMessagesProj/src/main/res/drawable-hdpi/load_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/location_panel.9.png b/TMessagesProj/src/main/res/drawable-hdpi/location_panel.9.png index 309286005..e882e614a 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/location_panel.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/location_panel.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/lock_arrow.png b/TMessagesProj/src/main/res/drawable-hdpi/lock_arrow.png index b3895dd1c..da9a2e694 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/lock_arrow.png and b/TMessagesProj/src/main/res/drawable-hdpi/lock_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/lock_close.png b/TMessagesProj/src/main/res/drawable-hdpi/lock_close.png index f9b9072cd..aae1bbb62 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/lock_close.png and b/TMessagesProj/src/main/res/drawable-hdpi/lock_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/lock_middle.png b/TMessagesProj/src/main/res/drawable-hdpi/lock_middle.png index 62d360e56..781f8691f 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/lock_middle.png and b/TMessagesProj/src/main/res/drawable-hdpi/lock_middle.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/lock_open.png b/TMessagesProj/src/main/res/drawable-hdpi/lock_open.png index b7cc48642..6dcfc864b 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/lock_open.png and b/TMessagesProj/src/main/res/drawable-hdpi/lock_open.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/lock_round.9.png b/TMessagesProj/src/main/res/drawable-hdpi/lock_round.9.png index 61bc758ee..ca07c2ce6 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/lock_round.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/lock_round.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/lock_round_shadow.9.png b/TMessagesProj/src/main/res/drawable-hdpi/lock_round_shadow.9.png index 56d0563c9..34a0eecf3 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/lock_round_shadow.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/lock_round_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/lock_top.png b/TMessagesProj/src/main/res/drawable-hdpi/lock_top.png index 38aacd992..56ed2f8b3 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/lock_top.png and b/TMessagesProj/src/main/res/drawable-hdpi/lock_top.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/log_info.png b/TMessagesProj/src/main/res/drawable-hdpi/log_info.png index 09c27549e..1d067afb4 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/log_info.png and b/TMessagesProj/src/main/res/drawable-hdpi/log_info.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/logo_middle.png b/TMessagesProj/src/main/res/drawable-hdpi/logo_middle.png index bf7d44fb3..2d209f206 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/logo_middle.png and b/TMessagesProj/src/main/res/drawable-hdpi/logo_middle.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/map_pin.png b/TMessagesProj/src/main/res/drawable-hdpi/map_pin.png index d3b369f31..667b8b3a1 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/map_pin.png and b/TMessagesProj/src/main/res/drawable-hdpi/map_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_blue.png b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_blue.png index 14048fbe0..0ec63cbe5 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_blue.png and b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_blue.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_blue_b.png b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_blue_b.png index c07bd2b11..79b073597 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_blue_b.png and b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_blue_b.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_green.png b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_green.png index ba0e8d3a0..50a1a6d73 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_green.png and b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_green.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_green_b.png b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_green_b.png index d4fda7a0f..5d6a02c71 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_green_b.png and b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_green_b.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_load.png b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_load.png index 0b47292ab..260daaaa9 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_load.png and b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_load.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_pause.png b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_pause.png index 29e74bfee..5b856eaf9 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_pause.png and b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_red.png b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_red.png index 766760f2c..fc3cf22d8 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_red.png and b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_red.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_red_b.png b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_red_b.png index 8c5567fc8..6af22de93 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_red_b.png and b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_red_b.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_yellow.png b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_yellow.png index f225a61b6..74bc973a7 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_yellow.png and b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_yellow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_yellow_b.png b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_yellow_b.png index 2ab4fac69..bd8b328b0 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/media_doc_yellow_b.png and b/TMessagesProj/src/main/res/drawable-hdpi/media_doc_yellow_b.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/mentionbutton.png b/TMessagesProj/src/main/res/drawable-hdpi/mentionbutton.png index 4c05daa16..9dddb3fbc 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/mentionbutton.png and b/TMessagesProj/src/main/res/drawable-hdpi/mentionbutton.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/mentionchatslist.png b/TMessagesProj/src/main/res/drawable-hdpi/mentionchatslist.png index c89f968f5..d1bf44853 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/mentionchatslist.png and b/TMessagesProj/src/main/res/drawable-hdpi/mentionchatslist.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_add.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_add.png index fef73f527..98f3f8d77 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_add.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_bookmarks_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_bookmarks_ny.png index adc42b74d..d8c73f31f 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_bookmarks_ny.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_bookmarks_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_broadcast.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_broadcast.png index f00132b6f..375ae3210 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_broadcast.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_broadcast.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_calls.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_calls.png index b5c2d7648..d057db85d 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_calls.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_calls.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_calls_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_calls_ny.png index 4f29615f7..44a7bb27a 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_calls_ny.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_calls_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_camera.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_camera.png index 77ec8d52d..04f4335b1 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_camera.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_camera.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_camera_av.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_camera_av.png index 80972e403..be8ec0c65 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_camera_av.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_camera_av.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_channel_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_channel_ny.png index 7c6136dce..ff5579fb1 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_channel_ny.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_channel_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_chats.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_chats.png index 37b78882d..740eef6c2 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_chats.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_chats.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_clearcache.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_clearcache.png index 1035425cf..2b6602488 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_clearcache.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_clearcache.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_contacts.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_contacts.png index b476ba777..9701640c9 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_contacts.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_contacts.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_contacts_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_contacts_ny.png index 3ed98b773..e158a2f39 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_contacts_ny.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_contacts_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_copy.9.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_copy.9.png index f981e1b7d..2e36d039c 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_copy.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_copy.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_data.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_data.png index 35ff53276..e0a122680 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_data.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_data.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_groups.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_groups.png new file mode 100644 index 000000000..43624ca94 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_groups.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_groups_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_groups_ny.png index 953c14e27..1d8ab4e69 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_groups_ny.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_groups_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_help.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_help.png index a19f3cba2..8d819687f 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_help.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_help.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_help_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_help_ny.png index 75897c304..3f324f668 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_help_ny.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_help_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_invite.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_invite.png index 6e40be937..26a83bd83 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_invite.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_invite.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_invite_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_invite_ny.png index 584e8ee09..b3544b98e 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_invite_ny.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_invite_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_language.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_language.png index e516000c0..d0dccf2a6 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_language.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_language.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_newgroup.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_newgroup.png deleted file mode 100644 index b0cccd5bf..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_newgroup.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_newphone.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_newphone.png index 2e8b1c890..b5cbf0141 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_newphone.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_newphone.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_notifications.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_notifications.png index e2062be2f..65bd7c475 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_notifications.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_notifications.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_palette.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_palette.png index 35daf6bdf..deaa1b183 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_palette.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_palette.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_passcode.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_passcode.png index d10eb14b2..4bbc5d399 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_passcode.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_passcode.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_read.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_read.png index 65205d339..c38b696b1 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_read.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_read.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_saved.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_saved.png index 7ca0a3ef2..054870098 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_saved.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_saved.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_search.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_search.png index 50e4d550f..82b7d20f7 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_search.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_secret.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_secret.png index ee2f8a5c7..29b923f1f 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_secret.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_secret.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_secret_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_secret_ny.png index 04c72d602..25751551f 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_secret_ny.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_secret_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_settings.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_settings.png index 7415d55aa..30ae6042d 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_settings.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_settings_filled.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_settings_filled.png index 520c2c465..fe19d1372 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_settings_filled.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_settings_filled.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_settings_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_settings_ny.png index 536b10448..78ad397d8 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_settings_ny.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_settings_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_shadow.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_shadow.png index e60f9bf98..419835a85 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_shadow.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_support.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_support.png index f645eaffa..5c3666d77 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_support.png and b/TMessagesProj/src/main/res/drawable-hdpi/menu_support.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_unread.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_unread.png deleted file mode 100644 index f43e30d9e..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_unread.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/message_arrow.png b/TMessagesProj/src/main/res/drawable-hdpi/message_arrow.png index c27c172d0..6d2d50001 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/message_arrow.png and b/TMessagesProj/src/main/res/drawable-hdpi/message_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/mic.png b/TMessagesProj/src/main/res/drawable-hdpi/mic.png deleted file mode 100644 index 68738425b..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/mic.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_close.png b/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_close.png index 95ef2b917..5b43d2c93 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_close.png and b/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_pause.png b/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_pause.png index 612b8704d..a9ed779b6 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_pause.png and b/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_play.png b/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_play.png index 9e90258b7..47f0822f9 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_play.png and b/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/moon.png b/TMessagesProj/src/main/res/drawable-hdpi/moon.png index ec5925666..40b5acb17 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/moon.png and b/TMessagesProj/src/main/res/drawable-hdpi/moon.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_actions.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_actions.png index 11878ff28..95c025f09 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_actions.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_actions.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_addbot.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_addbot.png new file mode 100644 index 000000000..44bb78f6a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_addbot.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_addcontact.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_addcontact.png new file mode 100644 index 000000000..b52f8de45 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_addcontact.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_archive.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_archive.png new file mode 100644 index 000000000..8a166b183 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_archive.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_block.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_block.png new file mode 100644 index 000000000..07a7a945f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_block.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_calendar.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_calendar.png new file mode 100644 index 000000000..2d9cf49b7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_calendar.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_callback.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_callback.png new file mode 100644 index 000000000..cabffcae9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_callback.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_cancel.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_cancel.png new file mode 100644 index 000000000..6e3da3a1a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_check.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_check.png index 9d1983663..6c1ccbbd7 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_check.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_clear.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_clear.png new file mode 100644 index 000000000..1c43863ea Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_clock.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_clock.png index 1587746c4..cea2ae43a 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_clock.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_clock.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_contact.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_contact.png index b49b48171..b545d95e6 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_contact.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_contact.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_copy.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_copy.png new file mode 100644 index 000000000..3adb5299c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_copy.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_delete.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_delete.png new file mode 100644 index 000000000..04653df98 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_download.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_download.png new file mode 100644 index 000000000..e3f956203 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_download.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_edit.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_edit.png new file mode 100644 index 000000000..4fdf49bd8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_edit.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_fave.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_fave.png new file mode 100644 index 000000000..b99933fce Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_fave.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_forward.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_forward.png new file mode 100644 index 000000000..5ace7ef56 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_gallery.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_gallery.png new file mode 100644 index 000000000..b5800378c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_gallery.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_gif.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_gif.png new file mode 100644 index 000000000..51d3731eb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_go_down.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_go_down.png new file mode 100644 index 000000000..ab0fc3303 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_go_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_go_up.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_go_up.png new file mode 100644 index 000000000..447c642ec Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_go_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_halfcheck.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_halfcheck.png index e3b19944e..e08540bd9 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_halfcheck.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_halfcheck.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_home.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_home.png new file mode 100644 index 000000000..35cb62fa4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_home.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_hybrid.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_hybrid.png new file mode 100644 index 000000000..446507162 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_hybrid.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_in.9.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_in.9.png index 50df48361..fe490b94b 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_in.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_in.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_in_shadow.9.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_in_shadow.9.png index c97fb2a18..bd348f440 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_in_shadow.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_in_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_instant.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_instant.png index 0d44d5ac6..3669d8c54 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_instant.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_instant.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_language.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_language.png new file mode 100644 index 000000000..d1fdb97b1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_language.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_leave.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_leave.png new file mode 100644 index 000000000..9bcbe7316 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_leave.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_link.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_link.png new file mode 100644 index 000000000..3edfc3275 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_location.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_location.png index 81fe1629a..33aae1f7a 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_location.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_map.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_map.png new file mode 100644 index 000000000..bb7d09e3a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_map.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_markread.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_markread.png new file mode 100644 index 000000000..459c025cf Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_markread.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_markunread.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_markunread.png new file mode 100644 index 000000000..3ebac7613 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_markunread.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_mask.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_mask.png new file mode 100644 index 000000000..dc55a00b9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_mask.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_media.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_media.png new file mode 100644 index 000000000..52842da3f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_media.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_message.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_message.png new file mode 100644 index 000000000..86b4adb4f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_message.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_mute.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_mute.png new file mode 100644 index 000000000..9a6e3b2b3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_openin.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_openin.png new file mode 100644 index 000000000..ed67c9eeb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_openin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_out.9.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_out.9.png index 9087ef0c2..28ce75200 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_out.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_out.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_out_shadow.9.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_out_shadow.9.png index 9899e38da..170b3ee49 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_out_shadow.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_out_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_panel_clear.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_panel_clear.png index d576ba038..cb02bfd4f 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_panel_clear.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_panel_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_panel_forward.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_panel_forward.png index 426bb5588..6af59fc31 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_panel_forward.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_panel_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_panel_link.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_panel_link.png deleted file mode 100755 index b7220e36a..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_panel_link.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_panel_reply.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_panel_reply.png index a23cabdb4..7f01b9abd 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_panel_reply.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_panel_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo.9.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo.9.png index dfa168743..49349da0c 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_shadow.9.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_shadow.9.png index 4c080fa11..004193402 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_shadow.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_pin.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_pin.png new file mode 100644 index 000000000..2b781babe Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_pollstop.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_pollstop.png new file mode 100644 index 000000000..e175ecf89 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_pollstop.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_reply.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_reply.png new file mode 100644 index 000000000..62253a583 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_report.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_report.png new file mode 100644 index 000000000..f9982fd48 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_report.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_retry.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_retry.png new file mode 100644 index 000000000..14cd387b7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_retry.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_round_cancel_m.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_round_cancel_m.png index 0ddb34811..54b0d11b4 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_round_cancel_m.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_round_cancel_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_round_file_s.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_round_file_s.png index d9a07fbe9..55384a43b 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_round_file_s.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_round_file_s.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_round_gif_m.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_round_gif_m.png index c2fc9129e..9155508fb 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_round_gif_m.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_round_gif_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_round_load_m.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_round_load_m.png index 3eca41413..f9aebaaa8 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_round_load_m.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_round_load_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_round_pause_m.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_round_pause_m.png index e136413f6..5e5f6e8dc 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_round_pause_m.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_round_pause_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_round_play_m.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_round_play_m.png index 56e77657d..f760d19dc 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_round_play_m.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_round_play_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_satellite.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_satellite.png new file mode 100644 index 000000000..68a8de49f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_satellite.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_search.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_search.png new file mode 100644 index 000000000..e76432671 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_share.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_share.png new file mode 100644 index 000000000..4ccfa6439 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_share.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_shareout.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_shareout.png new file mode 100644 index 000000000..40d480a52 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_shareout.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_stats.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_stats.png new file mode 100644 index 000000000..ae3f60f92 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_stats.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_sticker.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_sticker.png new file mode 100644 index 000000000..aaa7dff43 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_sticker.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_theme.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_theme.png new file mode 100644 index 000000000..87b6e9bf1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_theme.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_timer.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_timer.png new file mode 100644 index 000000000..7ccd1fc8b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_timer.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_unarchive.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_unarchive.png new file mode 100644 index 000000000..52b3e5a33 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_unarchive.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_unfave.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_unfave.png new file mode 100644 index 000000000..83bf9b1cc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_unfave.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_unmute.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_unmute.png new file mode 100644 index 000000000..56a75943f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_unmute.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_unpin.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_unpin.png new file mode 100644 index 000000000..cb984904a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_unpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_unvote.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_unvote.png new file mode 100644 index 000000000..b2741e589 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_unvote.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_usersearch.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_usersearch.png new file mode 100644 index 000000000..9a5aeaeef Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_usersearch.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_views.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_views.png index 69fe2c37a..b20d01a62 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_views.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_views.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_warning.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_warning.png index c52eebd93..05b84d851 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_warning.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_warning.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/music_reverse.png b/TMessagesProj/src/main/res/drawable-hdpi/music_reverse.png index b805bdc94..0fb601c00 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/music_reverse.png and b/TMessagesProj/src/main/res/drawable-hdpi/music_reverse.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/myloc_on.png b/TMessagesProj/src/main/res/drawable-hdpi/myloc_on.png index ad517c3a7..224fc5748 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/myloc_on.png and b/TMessagesProj/src/main/res/drawable-hdpi/myloc_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/navigate.png b/TMessagesProj/src/main/res/drawable-hdpi/navigate.png index 5bf5640aa..9af674cbd 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/navigate.png and b/TMessagesProj/src/main/res/drawable-hdpi/navigate.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/newmsg_divider.png b/TMessagesProj/src/main/res/drawable-hdpi/newmsg_divider.png index 58321338a..7de83c593 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/newmsg_divider.png and b/TMessagesProj/src/main/res/drawable-hdpi/newmsg_divider.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/newyear.png b/TMessagesProj/src/main/res/drawable-hdpi/newyear.png index f517b056b..f4db07f3e 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/newyear.png and b/TMessagesProj/src/main/res/drawable-hdpi/newyear.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/no_apps.png b/TMessagesProj/src/main/res/drawable-hdpi/no_apps.png index 2ee7b8bfd..0d59d549e 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/no_apps.png and b/TMessagesProj/src/main/res/drawable-hdpi/no_apps.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/no_passport.png b/TMessagesProj/src/main/res/drawable-hdpi/no_passport.png index 1a11de8a1..febd0e49a 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/no_passport.png and b/TMessagesProj/src/main/res/drawable-hdpi/no_passport.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/no_password.png b/TMessagesProj/src/main/res/drawable-hdpi/no_password.png index 1e9da4303..12941ed78 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/no_password.png and b/TMessagesProj/src/main/res/drawable-hdpi/no_password.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/nocover.png b/TMessagesProj/src/main/res/drawable-hdpi/nocover.png index 27d173943..3193227da 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/nocover.png and b/TMessagesProj/src/main/res/drawable-hdpi/nocover.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/nocover_big.9.png b/TMessagesProj/src/main/res/drawable-hdpi/nocover_big.9.png index 7b02d9e1c..49c9b4163 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/nocover_big.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/nocover_big.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/nocover_small.9.png b/TMessagesProj/src/main/res/drawable-hdpi/nocover_small.9.png index 8e5d60b8a..0ea8deed9 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/nocover_small.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/nocover_small.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/nophotos.9.png b/TMessagesProj/src/main/res/drawable-hdpi/nophotos.9.png index 27c40f747..21bb02555 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/nophotos.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/nophotos.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/notification.png b/TMessagesProj/src/main/res/drawable-hdpi/notification.png old mode 100755 new mode 100644 index e9ba19015..f3e0235e1 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/notification.png and b/TMessagesProj/src/main/res/drawable-hdpi/notification.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/notifications_mute1h.png b/TMessagesProj/src/main/res/drawable-hdpi/notifications_mute1h.png index b7f538594..1d11c0d18 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/notifications_mute1h.png and b/TMessagesProj/src/main/res/drawable-hdpi/notifications_mute1h.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/notifications_mute2d.png b/TMessagesProj/src/main/res/drawable-hdpi/notifications_mute2d.png index fb7da6993..9410ddf27 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/notifications_mute2d.png and b/TMessagesProj/src/main/res/drawable-hdpi/notifications_mute2d.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/notifications_off.png b/TMessagesProj/src/main/res/drawable-hdpi/notifications_off.png index ee8dee2e5..eae18160b 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/notifications_off.png and b/TMessagesProj/src/main/res/drawable-hdpi/notifications_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/notifications_on.png b/TMessagesProj/src/main/res/drawable-hdpi/notifications_on.png index 4cbeb2d99..e20c79ae4 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/notifications_on.png and b/TMessagesProj/src/main/res/drawable-hdpi/notifications_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/notifications_settings.png b/TMessagesProj/src/main/res/drawable-hdpi/notifications_settings.png index 8f2fdbccd..3ecfbe527 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/notifications_settings.png and b/TMessagesProj/src/main/res/drawable-hdpi/notifications_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/notify_members_off.png b/TMessagesProj/src/main/res/drawable-hdpi/notify_members_off.png deleted file mode 100644 index 69af0ff9b..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/notify_members_off.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/notify_members_on.png b/TMessagesProj/src/main/res/drawable-hdpi/notify_members_on.png deleted file mode 100644 index fe97c7a9c..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/notify_members_on.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/outline_add_gif.png b/TMessagesProj/src/main/res/drawable-hdpi/outline_add_gif.png new file mode 100644 index 000000000..1e24f9d93 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/outline_add_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/outline_fave.png b/TMessagesProj/src/main/res/drawable-hdpi/outline_fave.png new file mode 100644 index 000000000..9513482e4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/outline_fave.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/outline_pack.png b/TMessagesProj/src/main/res/drawable-hdpi/outline_pack.png new file mode 100644 index 000000000..66e123409 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/outline_pack.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/outline_send.png b/TMessagesProj/src/main/res/drawable-hdpi/outline_send.png new file mode 100644 index 000000000..a2a5bca4b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/outline_send.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/outline_unfave.png b/TMessagesProj/src/main/res/drawable-hdpi/outline_unfave.png new file mode 100644 index 000000000..243760aed Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/outline_unfave.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pagedown.png b/TMessagesProj/src/main/res/drawable-hdpi/pagedown.png index 909ab4815..d79d99295 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/pagedown.png and b/TMessagesProj/src/main/res/drawable-hdpi/pagedown.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pagedown_shadow.png b/TMessagesProj/src/main/res/drawable-hdpi/pagedown_shadow.png index e823700cc..6f23d83d1 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/pagedown_shadow.png and b/TMessagesProj/src/main/res/drawable-hdpi/pagedown_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/passcode_check.png b/TMessagesProj/src/main/res/drawable-hdpi/passcode_check.png index d9b4dc28d..b01e6151b 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/passcode_check.png and b/TMessagesProj/src/main/res/drawable-hdpi/passcode_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/passcode_delete.png b/TMessagesProj/src/main/res/drawable-hdpi/passcode_delete.png index 317c52c5c..b8f57271d 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/passcode_delete.png and b/TMessagesProj/src/main/res/drawable-hdpi/passcode_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/passcode_logo.png b/TMessagesProj/src/main/res/drawable-hdpi/passcode_logo.png index a004ca95c..6d0869781 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/passcode_logo.png and b/TMessagesProj/src/main/res/drawable-hdpi/passcode_logo.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/permission_locked.png b/TMessagesProj/src/main/res/drawable-hdpi/permission_locked.png index e6ea87beb..b085f8887 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/permission_locked.png and b/TMessagesProj/src/main/res/drawable-hdpi/permission_locked.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/permissions_contacts.png b/TMessagesProj/src/main/res/drawable-hdpi/permissions_contacts.png index 1001c8c6d..fb05e3678 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/permissions_contacts.png and b/TMessagesProj/src/main/res/drawable-hdpi/permissions_contacts.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/phone_activate.png b/TMessagesProj/src/main/res/drawable-hdpi/phone_activate.png index 52b4de8d6..32cecba1d 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/phone_activate.png and b/TMessagesProj/src/main/res/drawable-hdpi/phone_activate.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/phone_change.png b/TMessagesProj/src/main/res/drawable-hdpi/phone_change.png index 592645f6c..2faa712ad 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/phone_change.png and b/TMessagesProj/src/main/res/drawable-hdpi/phone_change.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photo_add.png b/TMessagesProj/src/main/res/drawable-hdpi/photo_add.png index 8cd53837f..afd010edb 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photo_add.png and b/TMessagesProj/src/main/res/drawable-hdpi/photo_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photo_crop.png b/TMessagesProj/src/main/res/drawable-hdpi/photo_crop.png index f32bdf9cb..3a9933867 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photo_crop.png and b/TMessagesProj/src/main/res/drawable-hdpi/photo_crop.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photo_outline.png b/TMessagesProj/src/main/res/drawable-hdpi/photo_outline.png index f9dcc42e6..8706710a3 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photo_outline.png and b/TMessagesProj/src/main/res/drawable-hdpi/photo_outline.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photo_paint.png b/TMessagesProj/src/main/res/drawable-hdpi/photo_paint.png index 9fb4c684e..8ad3793a9 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photo_paint.png and b/TMessagesProj/src/main/res/drawable-hdpi/photo_paint.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photo_paint_brush.png b/TMessagesProj/src/main/res/drawable-hdpi/photo_paint_brush.png index 7636ed84a..98cb527ff 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photo_paint_brush.png and b/TMessagesProj/src/main/res/drawable-hdpi/photo_paint_brush.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photo_paint_text.png b/TMessagesProj/src/main/res/drawable-hdpi/photo_paint_text.png index 118367b02..4d9f798e3 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photo_paint_text.png and b/TMessagesProj/src/main/res/drawable-hdpi/photo_paint_text.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photo_sticker.png b/TMessagesProj/src/main/res/drawable-hdpi/photo_sticker.png index 692b2004e..4c24f7fb5 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photo_sticker.png and b/TMessagesProj/src/main/res/drawable-hdpi/photo_sticker.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photo_timer.png b/TMessagesProj/src/main/res/drawable-hdpi/photo_timer.png index 554fee811..66020cbe7 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photo_timer.png and b/TMessagesProj/src/main/res/drawable-hdpi/photo_timer.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photo_tools.png b/TMessagesProj/src/main/res/drawable-hdpi/photo_tools.png index c8f09f606..69fcd32ff 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photo_tools.png and b/TMessagesProj/src/main/res/drawable-hdpi/photo_tools.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photo_undo.png b/TMessagesProj/src/main/res/drawable-hdpi/photo_undo.png index 3d36fa079..eb172fb1b 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photo_undo.png and b/TMessagesProj/src/main/res/drawable-hdpi/photo_undo.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photo_w.png b/TMessagesProj/src/main/res/drawable-hdpi/photo_w.png index 2aae32939..20b4f5423 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photo_w.png and b/TMessagesProj/src/main/res/drawable-hdpi/photo_w.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photobadge.9.png b/TMessagesProj/src/main/res/drawable-hdpi/photobadge.9.png index 003ad33c0..a64511ec7 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photobadge.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/photobadge.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photocheck.png b/TMessagesProj/src/main/res/drawable-hdpi/photocheck.png index a2aa287f5..91d5cc24a 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photocheck.png and b/TMessagesProj/src/main/res/drawable-hdpi/photocheck.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photos_arrow.png b/TMessagesProj/src/main/res/drawable-hdpi/photos_arrow.png index 0b17d9a2f..6dc3cba31 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photos_arrow.png and b/TMessagesProj/src/main/res/drawable-hdpi/photos_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photos_group.png b/TMessagesProj/src/main/res/drawable-hdpi/photos_group.png index d6a33fe20..14071820b 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photos_group.png and b/TMessagesProj/src/main/res/drawable-hdpi/photos_group.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photos_header_shadow.png b/TMessagesProj/src/main/res/drawable-hdpi/photos_header_shadow.png index b142c59f3..4c2c51caf 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photos_header_shadow.png and b/TMessagesProj/src/main/res/drawable-hdpi/photos_header_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/photos_rounded.9.png b/TMessagesProj/src/main/res/drawable-hdpi/photos_rounded.9.png index a56c3758f..8a7c610b5 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/photos_rounded.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/photos_rounded.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/phototime.9.png b/TMessagesProj/src/main/res/drawable-hdpi/phototime.9.png index 8c0fad9bd..7cb710823 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/phototime.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/phototime.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pin.png b/TMessagesProj/src/main/res/drawable-hdpi/pin.png index 5eaceb350..9bdb62bb8 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/pin.png and b/TMessagesProj/src/main/res/drawable-hdpi/pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_next.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_next.png index e66cb1e9a..3ac679fa1 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/pl_next.png and b/TMessagesProj/src/main/res/drawable-hdpi/pl_next.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_pause.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_pause.png index 1c3af4310..7755a20ae 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/pl_pause.png and b/TMessagesProj/src/main/res/drawable-hdpi/pl_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_play.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_play.png index c6b899407..1d6542850 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/pl_play.png and b/TMessagesProj/src/main/res/drawable-hdpi/pl_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_previous.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_previous.png index 6936afb03..5a625ea52 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/pl_previous.png and b/TMessagesProj/src/main/res/drawable-hdpi/pl_previous.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat.png index c2c227c32..ca6f90d33 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat.png and b/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat1.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat1.png index b5dc34773..3874f9eeb 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat1.png and b/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat1.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_shuffle.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_shuffle.png index 534637cf5..ffc262e2a 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/pl_shuffle.png and b/TMessagesProj/src/main/res/drawable-hdpi/pl_shuffle.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/place_x.png b/TMessagesProj/src/main/res/drawable-hdpi/place_x.png index 734a1466a..3e04a0574 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/place_x.png and b/TMessagesProj/src/main/res/drawable-hdpi/place_x.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/play_big.png b/TMessagesProj/src/main/res/drawable-hdpi/play_big.png index ede6189a8..bfd5ff765 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/play_big.png and b/TMessagesProj/src/main/res/drawable-hdpi/play_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/play_mini_video.png b/TMessagesProj/src/main/res/drawable-hdpi/play_mini_video.png index f2a414df8..fa4bf4428 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/play_mini_video.png and b/TMessagesProj/src/main/res/drawable-hdpi/play_mini_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/player.png b/TMessagesProj/src/main/res/drawable-hdpi/player.png index a62ef59b8..a15c9a662 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/player.png and b/TMessagesProj/src/main/res/drawable-hdpi/player.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/plus.png b/TMessagesProj/src/main/res/drawable-hdpi/plus.png index 1bc967dfe..b2be938be 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/plus.png and b/TMessagesProj/src/main/res/drawable-hdpi/plus.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/popup_fixed.9.png b/TMessagesProj/src/main/res/drawable-hdpi/popup_fixed.9.png index 07c30b766..80449d60e 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/popup_fixed.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/popup_fixed.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/popup_fixed_alert.9.png b/TMessagesProj/src/main/res/drawable-hdpi/popup_fixed_alert.9.png index c19436fc7..a0c10b4ce 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/popup_fixed_alert.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/popup_fixed_alert.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/popup_fixed_alert2.9.png b/TMessagesProj/src/main/res/drawable-hdpi/popup_fixed_alert2.9.png new file mode 100644 index 000000000..9e406b910 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/popup_fixed_alert2.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/popup_fixed_top.9.png b/TMessagesProj/src/main/res/drawable-hdpi/popup_fixed_top.9.png index b202d3c67..0c95c1744 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/popup_fixed_top.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/popup_fixed_top.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/preview_arrow.png b/TMessagesProj/src/main/res/drawable-hdpi/preview_arrow.png new file mode 100644 index 000000000..2d252be15 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/preview_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/preview_open.png b/TMessagesProj/src/main/res/drawable-hdpi/preview_open.png index b5bb7ce9e..e81c339fb 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/preview_open.png and b/TMessagesProj/src/main/res/drawable-hdpi/preview_open.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/profile_admin.png b/TMessagesProj/src/main/res/drawable-hdpi/profile_admin.png index 007fe1765..6d26265f2 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/profile_admin.png and b/TMessagesProj/src/main/res/drawable-hdpi/profile_admin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/profile_audio.png b/TMessagesProj/src/main/res/drawable-hdpi/profile_audio.png index e2e87bd7c..1723ebf7c 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/profile_audio.png and b/TMessagesProj/src/main/res/drawable-hdpi/profile_audio.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/profile_ban.png b/TMessagesProj/src/main/res/drawable-hdpi/profile_ban.png index f11262ee8..62bd0cc72 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/profile_ban.png and b/TMessagesProj/src/main/res/drawable-hdpi/profile_ban.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/profile_file.png b/TMessagesProj/src/main/res/drawable-hdpi/profile_file.png index b1602ccb2..040f7f321 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/profile_file.png and b/TMessagesProj/src/main/res/drawable-hdpi/profile_file.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/profile_groups.png b/TMessagesProj/src/main/res/drawable-hdpi/profile_groups.png deleted file mode 100644 index 9e50d2f50..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/profile_groups.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/profile_info.png b/TMessagesProj/src/main/res/drawable-hdpi/profile_info.png index 7d731cdfb..1a4624a25 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/profile_info.png and b/TMessagesProj/src/main/res/drawable-hdpi/profile_info.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/profile_link.png b/TMessagesProj/src/main/res/drawable-hdpi/profile_link.png index f0981aabc..3f2dcc447 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/profile_link.png and b/TMessagesProj/src/main/res/drawable-hdpi/profile_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/profile_list.png b/TMessagesProj/src/main/res/drawable-hdpi/profile_list.png index 56a4d8933..516575424 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/profile_list.png and b/TMessagesProj/src/main/res/drawable-hdpi/profile_list.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/profile_message.png b/TMessagesProj/src/main/res/drawable-hdpi/profile_message.png index a3dfef123..bb05e0136 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/profile_message.png and b/TMessagesProj/src/main/res/drawable-hdpi/profile_message.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/profile_newmsg.png b/TMessagesProj/src/main/res/drawable-hdpi/profile_newmsg.png index e811fd437..f6d10d113 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/profile_newmsg.png and b/TMessagesProj/src/main/res/drawable-hdpi/profile_newmsg.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/profile_phone.png b/TMessagesProj/src/main/res/drawable-hdpi/profile_phone.png index 02a43d7fa..7b7e68a66 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/profile_phone.png and b/TMessagesProj/src/main/res/drawable-hdpi/profile_phone.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/profile_photos.png b/TMessagesProj/src/main/res/drawable-hdpi/profile_photos.png index 5cfc35a05..d1b032986 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/profile_photos.png and b/TMessagesProj/src/main/res/drawable-hdpi/profile_photos.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/profile_voice.png b/TMessagesProj/src/main/res/drawable-hdpi/profile_voice.png index de795a198..960e10155 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/profile_voice.png and b/TMessagesProj/src/main/res/drawable-hdpi/profile_voice.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/proxy_check.png b/TMessagesProj/src/main/res/drawable-hdpi/proxy_check.png index ec1456bd8..f3789ed59 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/proxy_check.png and b/TMessagesProj/src/main/res/drawable-hdpi/proxy_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/proxy_off.png b/TMessagesProj/src/main/res/drawable-hdpi/proxy_off.png index fb5b37f52..1e6bb23eb 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/proxy_off.png and b/TMessagesProj/src/main/res/drawable-hdpi/proxy_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/proxy_on.png b/TMessagesProj/src/main/res/drawable-hdpi/proxy_on.png index 84021b337..00fb01273 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/proxy_on.png and b/TMessagesProj/src/main/res/drawable-hdpi/proxy_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/redcircle.png b/TMessagesProj/src/main/res/drawable-hdpi/redcircle.png index 8b93a6c8c..c3fff7753 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/redcircle.png and b/TMessagesProj/src/main/res/drawable-hdpi/redcircle.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/regbtn2.9.png b/TMessagesProj/src/main/res/drawable-hdpi/regbtn2.9.png index 3723ab563..ba7852435 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/regbtn2.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/regbtn2.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/regbtn2_pressed.9.png b/TMessagesProj/src/main/res/drawable-hdpi/regbtn2_pressed.9.png index c1ba0e187..775048da1 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/regbtn2_pressed.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/regbtn2_pressed.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/replyvideo.png b/TMessagesProj/src/main/res/drawable-hdpi/replyvideo.png index cc0702c64..b4176fbd3 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/replyvideo.png and b/TMessagesProj/src/main/res/drawable-hdpi/replyvideo.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/round_check2.png b/TMessagesProj/src/main/res/drawable-hdpi/round_check2.png index f00b4ffd2..9b7716996 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/round_check2.png and b/TMessagesProj/src/main/res/drawable-hdpi/round_check2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/round_grey.png b/TMessagesProj/src/main/res/drawable-hdpi/round_grey.png index 6f9f3f215..689fef471 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/round_grey.png and b/TMessagesProj/src/main/res/drawable-hdpi/round_grey.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/s_pause.png b/TMessagesProj/src/main/res/drawable-hdpi/s_pause.png index 9fac4ed33..13d782710 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/s_pause.png and b/TMessagesProj/src/main/res/drawable-hdpi/s_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/s_play.png b/TMessagesProj/src/main/res/drawable-hdpi/s_play.png index 678a351a4..2e4107093 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/s_play.png and b/TMessagesProj/src/main/res/drawable-hdpi/s_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/scroll_tip.png b/TMessagesProj/src/main/res/drawable-hdpi/scroll_tip.png index c3a1bb273..5f75ceed3 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/scroll_tip.png and b/TMessagesProj/src/main/res/drawable-hdpi/scroll_tip.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/search_calendar.png b/TMessagesProj/src/main/res/drawable-hdpi/search_calendar.png deleted file mode 100755 index 81d8fdf6d..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/search_calendar.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/search_dark.9.png b/TMessagesProj/src/main/res/drawable-hdpi/search_dark.9.png index cbe5823ba..339eb2772 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/search_dark.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/search_dark.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/search_dark_activated.9.png b/TMessagesProj/src/main/res/drawable-hdpi/search_dark_activated.9.png index 5fb492d87..cb175380b 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/search_dark_activated.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/search_dark_activated.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/search_down.png b/TMessagesProj/src/main/res/drawable-hdpi/search_down.png deleted file mode 100755 index 59b3e1960..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/search_down.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/search_gif.png b/TMessagesProj/src/main/res/drawable-hdpi/search_gif.png index 3be94584a..a92d3af2f 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/search_gif.png and b/TMessagesProj/src/main/res/drawable-hdpi/search_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/search_up.png b/TMessagesProj/src/main/res/drawable-hdpi/search_up.png deleted file mode 100755 index cfb07e55d..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/search_up.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/search_web.png b/TMessagesProj/src/main/res/drawable-hdpi/search_web.png index 900a5303b..494089cb7 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/search_web.png and b/TMessagesProj/src/main/res/drawable-hdpi/search_web.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/selectphoto_large.png b/TMessagesProj/src/main/res/drawable-hdpi/selectphoto_large.png index 18273a21c..f522c5730 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/selectphoto_large.png and b/TMessagesProj/src/main/res/drawable-hdpi/selectphoto_large.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/settings_arrow.png b/TMessagesProj/src/main/res/drawable-hdpi/settings_arrow.png new file mode 100644 index 000000000..a9c1f0401 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/settings_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/settings_noresults.png b/TMessagesProj/src/main/res/drawable-hdpi/settings_noresults.png new file mode 100644 index 000000000..7055fed6a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/settings_noresults.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/shadowdown.png b/TMessagesProj/src/main/res/drawable-hdpi/shadowdown.png index 1b591ce3b..880d19f55 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/shadowdown.png and b/TMessagesProj/src/main/res/drawable-hdpi/shadowdown.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/share.png b/TMessagesProj/src/main/res/drawable-hdpi/share.png index 8b853cf2d..a1b3b2a01 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/share.png and b/TMessagesProj/src/main/res/drawable-hdpi/share.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/share_arrow.png b/TMessagesProj/src/main/res/drawable-hdpi/share_arrow.png index 26219ff73..caa4f98a2 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/share_arrow.png and b/TMessagesProj/src/main/res/drawable-hdpi/share_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/share_round.png b/TMessagesProj/src/main/res/drawable-hdpi/share_round.png index d21a328b5..30a3dfd8d 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/share_round.png and b/TMessagesProj/src/main/res/drawable-hdpi/share_round.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/sheet_shadow.9.png b/TMessagesProj/src/main/res/drawable-hdpi/sheet_shadow.9.png index dccf34feb..2c5c84495 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/sheet_shadow.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/sheet_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/sheet_shadow_round.9.png b/TMessagesProj/src/main/res/drawable-hdpi/sheet_shadow_round.9.png new file mode 100644 index 000000000..607208e16 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/sheet_shadow_round.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/shortcut_compose.png b/TMessagesProj/src/main/res/drawable-hdpi/shortcut_compose.png index a6e9202eb..7927b553f 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/shortcut_compose.png and b/TMessagesProj/src/main/res/drawable-hdpi/shortcut_compose.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/shortcut_user.png b/TMessagesProj/src/main/res/drawable-hdpi/shortcut_user.png index c898b5cb0..c9fadd813 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/shortcut_user.png and b/TMessagesProj/src/main/res/drawable-hdpi/shortcut_user.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/slide_dot_big.png b/TMessagesProj/src/main/res/drawable-hdpi/slide_dot_big.png index 5802f30d6..8016e5f97 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/slide_dot_big.png and b/TMessagesProj/src/main/res/drawable-hdpi/slide_dot_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/slide_dot_small.png b/TMessagesProj/src/main/res/drawable-hdpi/slide_dot_small.png index 0ddb0e59f..b1faf7223 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/slide_dot_small.png and b/TMessagesProj/src/main/res/drawable-hdpi/slide_dot_small.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/slidearrow.png b/TMessagesProj/src/main/res/drawable-hdpi/slidearrow.png index f7c95e8e3..1085485ee 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/slidearrow.png and b/TMessagesProj/src/main/res/drawable-hdpi/slidearrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smallanimationpin.png b/TMessagesProj/src/main/res/drawable-hdpi/smallanimationpin.png index fa0e0d346..6a759ea8c 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/smallanimationpin.png and b/TMessagesProj/src/main/res/drawable-hdpi/smallanimationpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smallanimationpinleft.png b/TMessagesProj/src/main/res/drawable-hdpi/smallanimationpinleft.png index 53e37c78c..f95dc4d00 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/smallanimationpinleft.png and b/TMessagesProj/src/main/res/drawable-hdpi/smallanimationpinleft.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smallanimationpinright.png b/TMessagesProj/src/main/res/drawable-hdpi/smallanimationpinright.png index 23825e3c5..9f819dcab 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/smallanimationpinright.png and b/TMessagesProj/src/main/res/drawable-hdpi/smallanimationpinright.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_info.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_info.png new file mode 100644 index 000000000..965573ae5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_info.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_inputsearch.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_inputsearch.png new file mode 100644 index 000000000..a79f1c51c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_inputsearch.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_activities.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_activities.png new file mode 100644 index 000000000..885660932 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_activities.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_cat.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_cat.png new file mode 100644 index 000000000..dc05943c4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_cat.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_faves.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_faves.png new file mode 100644 index 000000000..41fa65bbb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_faves.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_flags.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_flags.png new file mode 100644 index 000000000..16d178321 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_flags.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_food.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_food.png new file mode 100644 index 000000000..cb4c47994 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_food.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_objects.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_objects.png new file mode 100644 index 000000000..d15d1437c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_objects.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_other.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_other.png new file mode 100644 index 000000000..6eda49c44 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_other.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_question.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_question.png new file mode 100644 index 000000000..943f84254 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_question.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_recent.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_recent.png new file mode 100644 index 000000000..cc89310cb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_recent.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_smiles.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_smiles.png new file mode 100644 index 000000000..c4a6d7180 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_smiles.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_travel.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_travel.png new file mode 100644 index 000000000..f12cf285e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_travel.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_trending.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_trending.png new file mode 100644 index 000000000..059fe9f6f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_panel_trending.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_popup.9.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_popup.9.png index ce757c867..d2bf4df45 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/smiles_popup.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_popup.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_clear.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_clear.png new file mode 100644 index 000000000..eb083ecf8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_gif.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_gif.png new file mode 100644 index 000000000..f307aad08 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_search.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_search.png new file mode 100644 index 000000000..ca881e9fb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_settings.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_settings.png new file mode 100644 index 000000000..e304a275c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_smiles.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_smiles.png new file mode 100644 index 000000000..46ef42f7c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_smiles.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_stickers.png b/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_stickers.png new file mode 100644 index 000000000..ac28df722 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/smiles_tab_stickers.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/sms_bubble.png b/TMessagesProj/src/main/res/drawable-hdpi/sms_bubble.png index 4945d4ec2..9806626a5 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/sms_bubble.png and b/TMessagesProj/src/main/res/drawable-hdpi/sms_bubble.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/sms_code.png b/TMessagesProj/src/main/res/drawable-hdpi/sms_code.png index 843e01a58..25c19147e 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/sms_code.png and b/TMessagesProj/src/main/res/drawable-hdpi/sms_code.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/sms_devices.png b/TMessagesProj/src/main/res/drawable-hdpi/sms_devices.png index eb8ba1f45..b95c4734e 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/sms_devices.png and b/TMessagesProj/src/main/res/drawable-hdpi/sms_devices.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/staredstickerstab.png b/TMessagesProj/src/main/res/drawable-hdpi/staredstickerstab.png deleted file mode 100644 index 0254c7118..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/staredstickerstab.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/sticker_added.png b/TMessagesProj/src/main/res/drawable-hdpi/sticker_added.png index 8ee9dabed..e8aad9208 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/sticker_added.png and b/TMessagesProj/src/main/res/drawable-hdpi/sticker_added.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/sticker_search.png b/TMessagesProj/src/main/res/drawable-hdpi/sticker_search.png deleted file mode 100644 index 3533306ef..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/sticker_search.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_all.9.png b/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_all.9.png index 8025f3e1a..3844f9a84 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_all.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_all.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_arrow.png b/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_arrow.png index 93a2d75b4..411b6432c 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_arrow.png and b/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_center.9.png b/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_center.9.png index a8c0ac384..e850c5b57 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_center.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_center.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_left.9.png b/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_left.9.png index 6afd3266a..7b8db301b 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_left.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_left.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_right.9.png b/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_right.9.png index c87f02450..198468cff 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_right.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/stickers_back_right.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/stickers_empty.png b/TMessagesProj/src/main/res/drawable-hdpi/stickers_empty.png new file mode 100644 index 000000000..475b1bc92 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/stickers_empty.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/stickers_favorite.png b/TMessagesProj/src/main/res/drawable-hdpi/stickers_favorite.png deleted file mode 100644 index 286f0da9c..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/stickers_favorite.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/stickers_none.png b/TMessagesProj/src/main/res/drawable-hdpi/stickers_none.png deleted file mode 100644 index 63800eb2e..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/stickers_none.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/stickers_pack.png b/TMessagesProj/src/main/res/drawable-hdpi/stickers_pack.png deleted file mode 100644 index e7bb3e42d..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/stickers_pack.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/stickers_send.png b/TMessagesProj/src/main/res/drawable-hdpi/stickers_send.png deleted file mode 100644 index 4e9cae63f..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/stickers_send.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/stickers_unfavorite.png b/TMessagesProj/src/main/res/drawable-hdpi/stickers_unfavorite.png deleted file mode 100644 index f6216a101..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/stickers_unfavorite.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/stickersclose.png b/TMessagesProj/src/main/res/drawable-hdpi/stickersclose.png index 0e6c2ddab..6f7f347e3 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/stickersclose.png and b/TMessagesProj/src/main/res/drawable-hdpi/stickersclose.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/stickerset_close.png b/TMessagesProj/src/main/res/drawable-hdpi/stickerset_close.png index 1dea2df7d..d7c78d1fc 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/stickerset_close.png and b/TMessagesProj/src/main/res/drawable-hdpi/stickerset_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/switch_to_on1.9.png b/TMessagesProj/src/main/res/drawable-hdpi/switch_to_on1.9.png index c8ca13e9e..6dcfd7331 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/switch_to_on1.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/switch_to_on1.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/switch_to_on2.9.png b/TMessagesProj/src/main/res/drawable-hdpi/switch_to_on2.9.png index c8ca13e9e..6dcfd7331 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/switch_to_on2.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/switch_to_on2.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/switch_track.9.png b/TMessagesProj/src/main/res/drawable-hdpi/switch_track.9.png index 0ebe65e79..977f3f25a 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/switch_track.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/switch_track.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/system.9.png b/TMessagesProj/src/main/res/drawable-hdpi/system.9.png index de5d484a1..7377d0e67 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/system.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/system.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/system_loader.png b/TMessagesProj/src/main/res/drawable-hdpi/system_loader.png index f6a19f070..e22e72c70 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/system_loader.png and b/TMessagesProj/src/main/res/drawable-hdpi/system_loader.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/theme_picker.png b/TMessagesProj/src/main/res/drawable-hdpi/theme_picker.png index 289abe83a..5bd1f182a 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/theme_picker.png and b/TMessagesProj/src/main/res/drawable-hdpi/theme_picker.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/tip1.png b/TMessagesProj/src/main/res/drawable-hdpi/tip1.png index 16abb9b9f..c42d531e9 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/tip1.png and b/TMessagesProj/src/main/res/drawable-hdpi/tip1.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/tip2.png b/TMessagesProj/src/main/res/drawable-hdpi/tip2.png index e68701602..2a1b44506 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/tip2.png and b/TMessagesProj/src/main/res/drawable-hdpi/tip2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/tip3.png b/TMessagesProj/src/main/res/drawable-hdpi/tip3.png index 241f3c1ec..bea69f501 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/tip3.png and b/TMessagesProj/src/main/res/drawable-hdpi/tip3.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/tip4.png b/TMessagesProj/src/main/res/drawable-hdpi/tip4.png index cdc21ca78..ef6bcd87a 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/tip4.png and b/TMessagesProj/src/main/res/drawable-hdpi/tip4.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/tool_blur.png b/TMessagesProj/src/main/res/drawable-hdpi/tool_blur.png index b5d4a6419..9e1349591 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/tool_blur.png and b/TMessagesProj/src/main/res/drawable-hdpi/tool_blur.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/tool_cropfix.png b/TMessagesProj/src/main/res/drawable-hdpi/tool_cropfix.png index 78d0fa455..a23720e0d 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/tool_cropfix.png and b/TMessagesProj/src/main/res/drawable-hdpi/tool_cropfix.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/tool_curve.png b/TMessagesProj/src/main/res/drawable-hdpi/tool_curve.png index 3e0922c49..fe3bf8cb2 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/tool_curve.png and b/TMessagesProj/src/main/res/drawable-hdpi/tool_curve.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/tool_rotate.png b/TMessagesProj/src/main/res/drawable-hdpi/tool_rotate.png index 06816100e..5fa5d7231 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/tool_rotate.png and b/TMessagesProj/src/main/res/drawable-hdpi/tool_rotate.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/tooltip_arrow.png b/TMessagesProj/src/main/res/drawable-hdpi/tooltip_arrow.png index 588efcfd5..5a6d561e8 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/tooltip_arrow.png and b/TMessagesProj/src/main/res/drawable-hdpi/tooltip_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/tooltip_arrow_up.png b/TMessagesProj/src/main/res/drawable-hdpi/tooltip_arrow_up.png new file mode 100644 index 000000000..4caa5b517 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/tooltip_arrow_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/tooltip_sound.png b/TMessagesProj/src/main/res/drawable-hdpi/tooltip_sound.png index 639b9eab6..e54076a3a 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/tooltip_sound.png and b/TMessagesProj/src/main/res/drawable-hdpi/tooltip_sound.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/update.png b/TMessagesProj/src/main/res/drawable-hdpi/update.png index 2cd3f066b..64797c897 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/update.png and b/TMessagesProj/src/main/res/drawable-hdpi/update.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/usersearch.png b/TMessagesProj/src/main/res/drawable-hdpi/usersearch.png deleted file mode 100644 index 540c9687c..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/usersearch.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/verified_area.png b/TMessagesProj/src/main/res/drawable-hdpi/verified_area.png old mode 100755 new mode 100644 index ad8dc9f06..194e6a901 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/verified_area.png and b/TMessagesProj/src/main/res/drawable-hdpi/verified_area.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/verified_check.png b/TMessagesProj/src/main/res/drawable-hdpi/verified_check.png old mode 100755 new mode 100644 index 105abc93d..8b5cdc2d7 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/verified_check.png and b/TMessagesProj/src/main/res/drawable-hdpi/verified_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/video_1080.png b/TMessagesProj/src/main/res/drawable-hdpi/video_1080.png index 09074b170..26e729b21 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/video_1080.png and b/TMessagesProj/src/main/res/drawable-hdpi/video_1080.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/video_240.png b/TMessagesProj/src/main/res/drawable-hdpi/video_240.png index 07bf28438..ad2995892 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/video_240.png and b/TMessagesProj/src/main/res/drawable-hdpi/video_240.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/video_360.png b/TMessagesProj/src/main/res/drawable-hdpi/video_360.png index a512bd5ca..000a2aec9 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/video_360.png and b/TMessagesProj/src/main/res/drawable-hdpi/video_360.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/video_480.png b/TMessagesProj/src/main/res/drawable-hdpi/video_480.png index 44119ad85..7bbb3c49f 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/video_480.png and b/TMessagesProj/src/main/res/drawable-hdpi/video_480.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/video_720.png b/TMessagesProj/src/main/res/drawable-hdpi/video_720.png index a838191a6..fbedd1244 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/video_720.png and b/TMessagesProj/src/main/res/drawable-hdpi/video_720.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/video_actions.png b/TMessagesProj/src/main/res/drawable-hdpi/video_actions.png index 1a80a8cd4..2e33904eb 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/video_actions.png and b/TMessagesProj/src/main/res/drawable-hdpi/video_actions.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/video_copy.png b/TMessagesProj/src/main/res/drawable-hdpi/video_copy.png index 3ea2b169a..5ac936545 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/video_copy.png and b/TMessagesProj/src/main/res/drawable-hdpi/video_copy.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/video_cropleft.png b/TMessagesProj/src/main/res/drawable-hdpi/video_cropleft.png index dd39ff800..12520b124 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/video_cropleft.png and b/TMessagesProj/src/main/res/drawable-hdpi/video_cropleft.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/video_cropright.png b/TMessagesProj/src/main/res/drawable-hdpi/video_cropright.png index d52101460..eaa4a10fe 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/video_cropright.png and b/TMessagesProj/src/main/res/drawable-hdpi/video_cropright.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/video_mini_arrow.png b/TMessagesProj/src/main/res/drawable-hdpi/video_mini_arrow.png index ad5da1883..0d858475b 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/video_mini_arrow.png and b/TMessagesProj/src/main/res/drawable-hdpi/video_mini_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/video_mini_cancel.png b/TMessagesProj/src/main/res/drawable-hdpi/video_mini_cancel.png index ca68d6e1b..88b9e8e87 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/video_mini_cancel.png and b/TMessagesProj/src/main/res/drawable-hdpi/video_mini_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/video_mute.png b/TMessagesProj/src/main/res/drawable-hdpi/video_mute.png index 7cb6d4b6d..edb0f82bd 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/video_mute.png and b/TMessagesProj/src/main/res/drawable-hdpi/video_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/video_muted.png b/TMessagesProj/src/main/res/drawable-hdpi/video_muted.png index 121038220..2057e3c11 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/video_muted.png and b/TMessagesProj/src/main/res/drawable-hdpi/video_muted.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/video_pip.png b/TMessagesProj/src/main/res/drawable-hdpi/video_pip.png index 2b2c17734..84461e792 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/video_pip.png and b/TMessagesProj/src/main/res/drawable-hdpi/video_pip.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/voice2x.png b/TMessagesProj/src/main/res/drawable-hdpi/voice2x.png index f6904fdd6..42f2cd9fd 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/voice2x.png and b/TMessagesProj/src/main/res/drawable-hdpi/voice2x.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/volume_off.png b/TMessagesProj/src/main/res/drawable-hdpi/volume_off.png index bb22a2e83..7c1cf4b0b 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/volume_off.png and b/TMessagesProj/src/main/res/drawable-hdpi/volume_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/volume_on.png b/TMessagesProj/src/main/res/drawable-hdpi/volume_on.png index 01ef347eb..0cdc9c5e1 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/volume_on.png and b/TMessagesProj/src/main/res/drawable-hdpi/volume_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/wall_selection.9.png b/TMessagesProj/src/main/res/drawable-hdpi/wall_selection.9.png index 69d7007fe..e6fb5125b 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/wall_selection.9.png and b/TMessagesProj/src/main/res/drawable-hdpi/wall_selection.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ab_progress.png b/TMessagesProj/src/main/res/drawable-mdpi/ab_progress.png index 6ae282746..e9b0c3460 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ab_progress.png and b/TMessagesProj/src/main/res/drawable-mdpi/ab_progress.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/account_add.png b/TMessagesProj/src/main/res/drawable-mdpi/account_add.png index 943249b06..56a1e10d5 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/account_add.png and b/TMessagesProj/src/main/res/drawable-mdpi/account_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/account_check.png b/TMessagesProj/src/main/res/drawable-mdpi/account_check.png index 138199360..6be339e80 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/account_check.png and b/TMessagesProj/src/main/res/drawable-mdpi/account_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/actions_addadmin.png b/TMessagesProj/src/main/res/drawable-mdpi/actions_addadmin.png index aa00f690f..2101155e2 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/actions_addadmin.png and b/TMessagesProj/src/main/res/drawable-mdpi/actions_addadmin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/actions_addmember2.png b/TMessagesProj/src/main/res/drawable-mdpi/actions_addmember2.png index 41103b112..067df7932 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/actions_addmember2.png and b/TMessagesProj/src/main/res/drawable-mdpi/actions_addmember2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/actions_permissions.png b/TMessagesProj/src/main/res/drawable-mdpi/actions_permissions.png index 47a5f847c..a2c992746 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/actions_permissions.png and b/TMessagesProj/src/main/res/drawable-mdpi/actions_permissions.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/actions_remove_user.png b/TMessagesProj/src/main/res/drawable-mdpi/actions_remove_user.png index ce8c667ab..d9d941e4c 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/actions_remove_user.png and b/TMessagesProj/src/main/res/drawable-mdpi/actions_remove_user.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/actions_removed.png b/TMessagesProj/src/main/res/drawable-mdpi/actions_removed.png index a565529f5..dc4551969 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/actions_removed.png and b/TMessagesProj/src/main/res/drawable-mdpi/actions_removed.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/actions_setphoto.png b/TMessagesProj/src/main/res/drawable-mdpi/actions_setphoto.png index 0d41b551a..c4c21e2fd 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/actions_setphoto.png and b/TMessagesProj/src/main/res/drawable-mdpi/actions_setphoto.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/actions_viewmembers.png b/TMessagesProj/src/main/res/drawable-mdpi/actions_viewmembers.png index 7cd5bde5c..340f5debb 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/actions_viewmembers.png and b/TMessagesProj/src/main/res/drawable-mdpi/actions_viewmembers.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/add.png b/TMessagesProj/src/main/res/drawable-mdpi/add.png index 953d3c612..9b48783a3 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/add.png and b/TMessagesProj/src/main/res/drawable-mdpi/add.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/add_admin.png b/TMessagesProj/src/main/res/drawable-mdpi/add_admin.png index 1cdb3b46a..baf9cfe92 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/add_admin.png and b/TMessagesProj/src/main/res/drawable-mdpi/add_admin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/add_contact_new.png b/TMessagesProj/src/main/res/drawable-mdpi/add_contact_new.png index de7dabdde..cbcd39de3 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/add_contact_new.png and b/TMessagesProj/src/main/res/drawable-mdpi/add_contact_new.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/animationpin.png b/TMessagesProj/src/main/res/drawable-mdpi/animationpin.png index 27a37e758..a431792fb 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/animationpin.png and b/TMessagesProj/src/main/res/drawable-mdpi/animationpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/animationpinleft.png b/TMessagesProj/src/main/res/drawable-mdpi/animationpinleft.png index 42247be21..00e89ab30 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/animationpinleft.png and b/TMessagesProj/src/main/res/drawable-mdpi/animationpinleft.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/animationpinright.png b/TMessagesProj/src/main/res/drawable-mdpi/animationpinright.png index 4c09455f7..56fff04f9 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/animationpinright.png and b/TMessagesProj/src/main/res/drawable-mdpi/animationpinright.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_audio.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_audio.png index bbde6dcd9..937cd187c 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/attach_audio.png and b/TMessagesProj/src/main/res/drawable-mdpi/attach_audio.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_close.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_close.png index ab0f4244d..36742f870 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/attach_close.png and b/TMessagesProj/src/main/res/drawable-mdpi/attach_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_contact.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_contact.png index 9dbeca665..b9407f555 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/attach_contact.png and b/TMessagesProj/src/main/res/drawable-mdpi/attach_contact.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_file.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_file.png index d1c1b6761..44e110e63 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/attach_file.png and b/TMessagesProj/src/main/res/drawable-mdpi/attach_file.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_gallery.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_gallery.png index fedebe10a..32ca414a0 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/attach_gallery.png and b/TMessagesProj/src/main/res/drawable-mdpi/attach_gallery.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_location.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_location.png index 725c06e72..7385cdcc7 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/attach_location.png and b/TMessagesProj/src/main/res/drawable-mdpi/attach_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_polls.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_polls.png index 2c22f76f6..4d33eccc8 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/attach_polls.png and b/TMessagesProj/src/main/res/drawable-mdpi/attach_polls.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_send.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_send.png old mode 100755 new mode 100644 index 5351f0369..3d426209e Binary files a/TMessagesProj/src/main/res/drawable-mdpi/attach_send.png and b/TMessagesProj/src/main/res/drawable-mdpi/attach_send.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_video.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_video.png index 1bf497191..d544b61d8 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/attach_video.png and b/TMessagesProj/src/main/res/drawable-mdpi/attach_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/audio_mini_arrow.png b/TMessagesProj/src/main/res/drawable-mdpi/audio_mini_arrow.png index 5198fbfbf..0ae22f459 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/audio_mini_arrow.png and b/TMessagesProj/src/main/res/drawable-mdpi/audio_mini_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/audio_mini_cancel.png b/TMessagesProj/src/main/res/drawable-mdpi/audio_mini_cancel.png index 4aa258afb..10d892313 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/audio_mini_cancel.png and b/TMessagesProj/src/main/res/drawable-mdpi/audio_mini_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/audiosend_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/audiosend_pause.png index cc46f5653..fde71deeb 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/audiosend_pause.png and b/TMessagesProj/src/main/res/drawable-mdpi/audiosend_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/audiosend_play.png b/TMessagesProj/src/main/res/drawable-mdpi/audiosend_play.png index ec37d365f..fa1fcda28 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/audiosend_play.png and b/TMessagesProj/src/main/res/drawable-mdpi/audiosend_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/authorize.png b/TMessagesProj/src/main/res/drawable-mdpi/authorize.png index 493eff323..a6f875150 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/authorize.png and b/TMessagesProj/src/main/res/drawable-mdpi/authorize.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/background_hd.jpg b/TMessagesProj/src/main/res/drawable-mdpi/background_hd.jpg old mode 100755 new mode 100644 index 9087f3e2a..dd7ca0176 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/background_hd.jpg and b/TMessagesProj/src/main/res/drawable-mdpi/background_hd.jpg differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/background_selected.png b/TMessagesProj/src/main/res/drawable-mdpi/background_selected.png index 1ee659b6e..e9ed77824 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/background_selected.png and b/TMessagesProj/src/main/res/drawable-mdpi/background_selected.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/bigcheck.png b/TMessagesProj/src/main/res/drawable-mdpi/bigcheck.png index 07c70e2b8..25f6661ad 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/bigcheck.png and b/TMessagesProj/src/main/res/drawable-mdpi/bigcheck.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/blockpanel.png b/TMessagesProj/src/main/res/drawable-mdpi/blockpanel.png index fd46ec9b3..3ca6bd983 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/blockpanel.png and b/TMessagesProj/src/main/res/drawable-mdpi/blockpanel.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/bluecounter.9.png b/TMessagesProj/src/main/res/drawable-mdpi/bluecounter.9.png index b683c0cea..ee3a92c79 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/bluecounter.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/bluecounter.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/blur_linear.png b/TMessagesProj/src/main/res/drawable-mdpi/blur_linear.png index 51ac41fad..ca451ffef 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/blur_linear.png and b/TMessagesProj/src/main/res/drawable-mdpi/blur_linear.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/blur_off.png b/TMessagesProj/src/main/res/drawable-mdpi/blur_off.png index 13b951054..2b30b4d3b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/blur_off.png and b/TMessagesProj/src/main/res/drawable-mdpi/blur_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/blur_radial.png b/TMessagesProj/src/main/res/drawable-mdpi/blur_radial.png index 817a51000..af45ee3fd 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/blur_radial.png and b/TMessagesProj/src/main/res/drawable-mdpi/blur_radial.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/book_bot.png b/TMessagesProj/src/main/res/drawable-mdpi/book_bot.png index 5ab629420..f8b0be758 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/book_bot.png and b/TMessagesProj/src/main/res/drawable-mdpi/book_bot.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/book_channel.png b/TMessagesProj/src/main/res/drawable-mdpi/book_channel.png index cb937f63e..504d1e296 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/book_channel.png and b/TMessagesProj/src/main/res/drawable-mdpi/book_channel.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/book_group.png b/TMessagesProj/src/main/res/drawable-mdpi/book_group.png index e09831fa0..6f96f55dc 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/book_group.png and b/TMessagesProj/src/main/res/drawable-mdpi/book_group.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/book_logo.png b/TMessagesProj/src/main/res/drawable-mdpi/book_logo.png index f452a54eb..0935e5a45 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/book_logo.png and b/TMessagesProj/src/main/res/drawable-mdpi/book_logo.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/book_user.png b/TMessagesProj/src/main/res/drawable-mdpi/book_user.png index 66bf3b1d5..8886e58e2 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/book_user.png and b/TMessagesProj/src/main/res/drawable-mdpi/book_user.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/bookmark_large.png b/TMessagesProj/src/main/res/drawable-mdpi/bookmark_large.png deleted file mode 100755 index 3391286e8..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/bookmark_large.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/bot_file.png b/TMessagesProj/src/main/res/drawable-mdpi/bot_file.png index 38f4b9d00..d55ddc39a 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/bot_file.png and b/TMessagesProj/src/main/res/drawable-mdpi/bot_file.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/bot_keyboard.png b/TMessagesProj/src/main/res/drawable-mdpi/bot_keyboard.png deleted file mode 100755 index cf775a2d8..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/bot_keyboard.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/bot_keyboard2.png b/TMessagesProj/src/main/res/drawable-mdpi/bot_keyboard2.png deleted file mode 100755 index 4631330cb..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/bot_keyboard2.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/bot_lines.png b/TMessagesProj/src/main/res/drawable-mdpi/bot_lines.png index 8f7e13f52..ea85c9a81 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/bot_lines.png and b/TMessagesProj/src/main/res/drawable-mdpi/bot_lines.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/bot_link.png b/TMessagesProj/src/main/res/drawable-mdpi/bot_link.png index 76d34b503..c6891320e 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/bot_link.png and b/TMessagesProj/src/main/res/drawable-mdpi/bot_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/bot_location.png b/TMessagesProj/src/main/res/drawable-mdpi/bot_location.png index f2b4113de..010aa170d 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/bot_location.png and b/TMessagesProj/src/main/res/drawable-mdpi/bot_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/bot_music.png b/TMessagesProj/src/main/res/drawable-mdpi/bot_music.png index 36c1bb4ad..00cc78cf5 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/bot_music.png and b/TMessagesProj/src/main/res/drawable-mdpi/bot_music.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/bottom_shadow.png b/TMessagesProj/src/main/res/drawable-mdpi/bottom_shadow.png index 08ede3f29..4a16cd395 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/bottom_shadow.png and b/TMessagesProj/src/main/res/drawable-mdpi/bottom_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/boxshadow.9.png b/TMessagesProj/src/main/res/drawable-mdpi/boxshadow.9.png index c63d9ff95..9fbd7222a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/boxshadow.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/boxshadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/broadcast3.png b/TMessagesProj/src/main/res/drawable-mdpi/broadcast3.png index 4024613db..9523170d4 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/broadcast3.png and b/TMessagesProj/src/main/res/drawable-mdpi/broadcast3.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/broadcast_w.png b/TMessagesProj/src/main/res/drawable-mdpi/broadcast_w.png index 53ba97a4a..55b9d6e95 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/broadcast_w.png and b/TMessagesProj/src/main/res/drawable-mdpi/broadcast_w.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/btnshadow.9.png b/TMessagesProj/src/main/res/drawable-mdpi/btnshadow.9.png index 9bda10680..761af80c3 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/btnshadow.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/btnshadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/burn.png b/TMessagesProj/src/main/res/drawable-mdpi/burn.png index e00361849..a385b7c83 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/burn.png and b/TMessagesProj/src/main/res/drawable-mdpi/burn.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/camera_btn.png b/TMessagesProj/src/main/res/drawable-mdpi/camera_btn.png index 74d1c1c29..4acbc3467 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/camera_btn.png and b/TMessagesProj/src/main/res/drawable-mdpi/camera_btn.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/camera_revert1.png b/TMessagesProj/src/main/res/drawable-mdpi/camera_revert1.png index 502187fe2..4475f01bd 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/camera_revert1.png and b/TMessagesProj/src/main/res/drawable-mdpi/camera_revert1.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/camera_revert2.png b/TMessagesProj/src/main/res/drawable-mdpi/camera_revert2.png index f8df66d01..75b6aa33c 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/camera_revert2.png and b/TMessagesProj/src/main/res/drawable-mdpi/camera_revert2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/cancel_big.png b/TMessagesProj/src/main/res/drawable-mdpi/cancel_big.png index 105022781..dce25d97b 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/cancel_big.png and b/TMessagesProj/src/main/res/drawable-mdpi/cancel_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/channelintro.png b/TMessagesProj/src/main/res/drawable-mdpi/channelintro.png index e4a828907..78a1964b2 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/channelintro.png and b/TMessagesProj/src/main/res/drawable-mdpi/channelintro.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/chats_archive.png b/TMessagesProj/src/main/res/drawable-mdpi/chats_archive.png new file mode 100644 index 000000000..c4538882e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/chats_archive.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_arrow.png b/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_arrow.png new file mode 100644 index 000000000..3e07345ab Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_box.png b/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_box.png new file mode 100644 index 000000000..529072322 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_box.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_hide.png b/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_hide.png new file mode 100644 index 000000000..10e67900e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_hide.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_muted.png b/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_muted.png new file mode 100644 index 000000000..1c1cc8f06 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_muted.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 new file mode 100644 index 000000000..508056633 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_show.png b/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_show.png new file mode 100644 index 000000000..1f4b56f33 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/chats_archive_show.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/chats_clear.png b/TMessagesProj/src/main/res/drawable-mdpi/chats_clear.png deleted file mode 100644 index dabe785ec..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/chats_clear.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/chats_delete.png b/TMessagesProj/src/main/res/drawable-mdpi/chats_delete.png index f7b13c614..b5742fbef 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/chats_delete.png and b/TMessagesProj/src/main/res/drawable-mdpi/chats_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/chats_leave.png b/TMessagesProj/src/main/res/drawable-mdpi/chats_leave.png index 3d7028540..42c3c4a12 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/chats_leave.png and b/TMessagesProj/src/main/res/drawable-mdpi/chats_leave.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/chats_pin.png b/TMessagesProj/src/main/res/drawable-mdpi/chats_pin.png index 25485e26c..1463ef646 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/chats_pin.png and b/TMessagesProj/src/main/res/drawable-mdpi/chats_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/chats_saved.png b/TMessagesProj/src/main/res/drawable-mdpi/chats_saved.png new file mode 100644 index 000000000..e80b5c6a7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/chats_saved.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/chats_unarchive.png b/TMessagesProj/src/main/res/drawable-mdpi/chats_unarchive.png new file mode 100644 index 000000000..3b834d9ec Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/chats_unarchive.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/chats_undo.png b/TMessagesProj/src/main/res/drawable-mdpi/chats_undo.png index db98b292f..13532af65 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/chats_undo.png and b/TMessagesProj/src/main/res/drawable-mdpi/chats_undo.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/chats_unpin.png b/TMessagesProj/src/main/res/drawable-mdpi/chats_unpin.png index 98c52061c..4bfc74b9a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/chats_unpin.png and b/TMessagesProj/src/main/res/drawable-mdpi/chats_unpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/checkbig.png b/TMessagesProj/src/main/res/drawable-mdpi/checkbig.png index 4e48a884c..9621fa349 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/checkbig.png and b/TMessagesProj/src/main/res/drawable-mdpi/checkbig.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/circle.png b/TMessagesProj/src/main/res/drawable-mdpi/circle.png index c3fb788c7..c1ae2bc58 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/circle.png and b/TMessagesProj/src/main/res/drawable-mdpi/circle.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/circle_big.png b/TMessagesProj/src/main/res/drawable-mdpi/circle_big.png index a42899d88..3b335c57e 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/circle_big.png and b/TMessagesProj/src/main/res/drawable-mdpi/circle_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/cloud_big.png b/TMessagesProj/src/main/res/drawable-mdpi/cloud_big.png index f23298c9c..b07072298 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/cloud_big.png and b/TMessagesProj/src/main/res/drawable-mdpi/cloud_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/collapse_down.png b/TMessagesProj/src/main/res/drawable-mdpi/collapse_down.png index 4402ea292..1d9b140a7 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/collapse_down.png and b/TMessagesProj/src/main/res/drawable-mdpi/collapse_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/collapse_up.png b/TMessagesProj/src/main/res/drawable-mdpi/collapse_up.png index 1e26447b2..54989ad3b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/collapse_up.png and b/TMessagesProj/src/main/res/drawable-mdpi/collapse_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/compose_panel_shadow.png b/TMessagesProj/src/main/res/drawable-mdpi/compose_panel_shadow.png index 5a5b8e5e7..5010c4712 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/compose_panel_shadow.png and b/TMessagesProj/src/main/res/drawable-mdpi/compose_panel_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/contacts_sort_name.png b/TMessagesProj/src/main/res/drawable-mdpi/contacts_sort_name.png index 5d6369d76..035ac06da 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/contacts_sort_name.png and b/TMessagesProj/src/main/res/drawable-mdpi/contacts_sort_name.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/contacts_sort_time.png b/TMessagesProj/src/main/res/drawable-mdpi/contacts_sort_time.png index bdfa2bef1..72d9481d6 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/contacts_sort_time.png and b/TMessagesProj/src/main/res/drawable-mdpi/contacts_sort_time.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/corner_in_bl.png b/TMessagesProj/src/main/res/drawable-mdpi/corner_in_bl.png index 6c9767042..6dd5135e4 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/corner_in_bl.png and b/TMessagesProj/src/main/res/drawable-mdpi/corner_in_bl.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/corner_in_br.png b/TMessagesProj/src/main/res/drawable-mdpi/corner_in_br.png index a74c63b80..46f6c1f7d 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/corner_in_br.png and b/TMessagesProj/src/main/res/drawable-mdpi/corner_in_br.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/corner_in_tl.png b/TMessagesProj/src/main/res/drawable-mdpi/corner_in_tl.png index 71de37a0d..2de60d50f 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/corner_in_tl.png and b/TMessagesProj/src/main/res/drawable-mdpi/corner_in_tl.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/corner_in_tr.png b/TMessagesProj/src/main/res/drawable-mdpi/corner_in_tr.png index 3dd1a4c4f..6976e6c42 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/corner_in_tr.png and b/TMessagesProj/src/main/res/drawable-mdpi/corner_in_tr.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/corner_out_bl.png b/TMessagesProj/src/main/res/drawable-mdpi/corner_out_bl.png index 05cf134d6..66ee2a578 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/corner_out_bl.png and b/TMessagesProj/src/main/res/drawable-mdpi/corner_out_bl.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/corner_out_br.png b/TMessagesProj/src/main/res/drawable-mdpi/corner_out_br.png index 7e4abd9c7..081baba38 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/corner_out_br.png and b/TMessagesProj/src/main/res/drawable-mdpi/corner_out_br.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/corner_out_tl.png b/TMessagesProj/src/main/res/drawable-mdpi/corner_out_tl.png index 026b68398..a55c0f20f 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/corner_out_tl.png and b/TMessagesProj/src/main/res/drawable-mdpi/corner_out_tl.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/corner_out_tr.png b/TMessagesProj/src/main/res/drawable-mdpi/corner_out_tr.png index 68bc95bd1..8720eeb3b 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/corner_out_tr.png and b/TMessagesProj/src/main/res/drawable-mdpi/corner_out_tr.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/delete.png b/TMessagesProj/src/main/res/drawable-mdpi/delete.png index 08aacdbaa..cc787b632 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/delete.png and b/TMessagesProj/src/main/res/drawable-mdpi/delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/devices.png b/TMessagesProj/src/main/res/drawable-mdpi/devices.png index 9422ede4b..30a92d92e 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/devices.png and b/TMessagesProj/src/main/res/drawable-mdpi/devices.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/doc_big.png b/TMessagesProj/src/main/res/drawable-mdpi/doc_big.png index 71c5a4756..d89bd7057 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/doc_big.png and b/TMessagesProj/src/main/res/drawable-mdpi/doc_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/edit_cancel.png b/TMessagesProj/src/main/res/drawable-mdpi/edit_cancel.png index 5dd045bca..e9c7dc694 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/edit_cancel.png and b/TMessagesProj/src/main/res/drawable-mdpi/edit_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/edit_done.png b/TMessagesProj/src/main/res/drawable-mdpi/edit_done.png deleted file mode 100755 index d1de075db..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/edit_done.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/fast_reply.png b/TMessagesProj/src/main/res/drawable-mdpi/fast_reply.png index 4cf2b6bdb..66d622c7a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/fast_reply.png and b/TMessagesProj/src/main/res/drawable-mdpi/fast_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/flame_small.png b/TMessagesProj/src/main/res/drawable-mdpi/flame_small.png index 1fc51cc65..b5439228c 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/flame_small.png and b/TMessagesProj/src/main/res/drawable-mdpi/flame_small.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/flash_auto.png b/TMessagesProj/src/main/res/drawable-mdpi/flash_auto.png index a10415524..738526d4a 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/flash_auto.png and b/TMessagesProj/src/main/res/drawable-mdpi/flash_auto.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/flash_off.png b/TMessagesProj/src/main/res/drawable-mdpi/flash_off.png index 74b80cda4..8134a1466 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/flash_off.png and b/TMessagesProj/src/main/res/drawable-mdpi/flash_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/flash_on.png b/TMessagesProj/src/main/res/drawable-mdpi/flash_on.png index eea0466fe..150356a38 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/flash_on.png and b/TMessagesProj/src/main/res/drawable-mdpi/flash_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/floating_camera.png b/TMessagesProj/src/main/res/drawable-mdpi/floating_camera.png index 0f3911b17..cf0507290 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/floating_camera.png and b/TMessagesProj/src/main/res/drawable-mdpi/floating_camera.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/floating_message.png b/TMessagesProj/src/main/res/drawable-mdpi/floating_message.png index f84107450..e9805fddc 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/floating_message.png and b/TMessagesProj/src/main/res/drawable-mdpi/floating_message.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/floating_pencil.png b/TMessagesProj/src/main/res/drawable-mdpi/floating_pencil.png index f4cd02644..5af5a8326 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/floating_pencil.png and b/TMessagesProj/src/main/res/drawable-mdpi/floating_pencil.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/floating_shadow.png b/TMessagesProj/src/main/res/drawable-mdpi/floating_shadow.png index 719152f85..1e758db84 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/floating_shadow.png and b/TMessagesProj/src/main/res/drawable-mdpi/floating_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/floating_shadow_profile.png b/TMessagesProj/src/main/res/drawable-mdpi/floating_shadow_profile.png index d30c7a0eb..91ddeede8 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/floating_shadow_profile.png and b/TMessagesProj/src/main/res/drawable-mdpi/floating_shadow_profile.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/forwardvideo.png b/TMessagesProj/src/main/res/drawable-mdpi/forwardvideo.png index 66e904420..6c463b685 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/forwardvideo.png and b/TMessagesProj/src/main/res/drawable-mdpi/forwardvideo.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/foursquare.png b/TMessagesProj/src/main/res/drawable-mdpi/foursquare.png index 845b3c9ad..94c15cffc 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/foursquare.png and b/TMessagesProj/src/main/res/drawable-mdpi/foursquare.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/gif_empty.png b/TMessagesProj/src/main/res/drawable-mdpi/gif_empty.png new file mode 100644 index 000000000..ff9dec2f4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/gif_empty.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/go_to_message.png b/TMessagesProj/src/main/res/drawable-mdpi/go_to_message.png deleted file mode 100644 index 44fb7471c..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/go_to_message.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/greydivider.9.png b/TMessagesProj/src/main/res/drawable-mdpi/greydivider.9.png index f37c794c8..191621af9 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/greydivider.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/greydivider.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/greydivider_bottom.9.png b/TMessagesProj/src/main/res/drawable-mdpi/greydivider_bottom.9.png index 87c76fba2..d865ccc0b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/greydivider_bottom.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/greydivider_bottom.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/greydivider_top.9.png b/TMessagesProj/src/main/res/drawable-mdpi/greydivider_top.9.png index 997f15345..b82954480 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/greydivider_top.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/greydivider_top.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/group_addmember.png b/TMessagesProj/src/main/res/drawable-mdpi/group_addmember.png index 03ac5771c..bc64f189b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/group_addmember.png and b/TMessagesProj/src/main/res/drawable-mdpi/group_addmember.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/group_admin.png b/TMessagesProj/src/main/res/drawable-mdpi/group_admin.png index 81cfdf57a..51ebf4974 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/group_admin.png and b/TMessagesProj/src/main/res/drawable-mdpi/group_admin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/group_admin_new.png b/TMessagesProj/src/main/res/drawable-mdpi/group_admin_new.png index 9562a204c..0da33e3d2 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/group_admin_new.png and b/TMessagesProj/src/main/res/drawable-mdpi/group_admin_new.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/group_ban_empty.png b/TMessagesProj/src/main/res/drawable-mdpi/group_ban_empty.png index 8c14a2834..643f901cb 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/group_ban_empty.png and b/TMessagesProj/src/main/res/drawable-mdpi/group_ban_empty.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/group_ban_new.png b/TMessagesProj/src/main/res/drawable-mdpi/group_ban_new.png index 856368d57..fa618b890 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/group_ban_new.png and b/TMessagesProj/src/main/res/drawable-mdpi/group_ban_new.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/group_banned.png b/TMessagesProj/src/main/res/drawable-mdpi/group_banned.png index 66584bf30..bbdcb1486 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/group_banned.png and b/TMessagesProj/src/main/res/drawable-mdpi/group_banned.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/group_edit.png b/TMessagesProj/src/main/res/drawable-mdpi/group_edit.png index 080faa1a9..62794d828 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/group_edit.png and b/TMessagesProj/src/main/res/drawable-mdpi/group_edit.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/group_edit_profile.png b/TMessagesProj/src/main/res/drawable-mdpi/group_edit_profile.png index f30f75109..6ec2cd52c 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/group_edit_profile.png and b/TMessagesProj/src/main/res/drawable-mdpi/group_edit_profile.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/group_log.png b/TMessagesProj/src/main/res/drawable-mdpi/group_log.png index e59cd9854..00bed3a79 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/group_log.png and b/TMessagesProj/src/main/res/drawable-mdpi/group_log.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/groups_overview_check.png b/TMessagesProj/src/main/res/drawable-mdpi/groups_overview_check.png index ba76becda..abd020502 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/groups_overview_check.png and b/TMessagesProj/src/main/res/drawable-mdpi/groups_overview_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/header_shadow.png b/TMessagesProj/src/main/res/drawable-mdpi/header_shadow.png index 3f23c3eb5..fc6a8053c 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/header_shadow.png and b/TMessagesProj/src/main/res/drawable-mdpi/header_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/header_shadow_reverse.png b/TMessagesProj/src/main/res/drawable-mdpi/header_shadow_reverse.png index cab866e17..ec685369b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/header_shadow_reverse.png and b/TMessagesProj/src/main/res/drawable-mdpi/header_shadow_reverse.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_attach.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_attach.png deleted file mode 100755 index 5d25c50ba..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_attach.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_back.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_back.png index 9e662f6d4..09040008e 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_back.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_back.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_copy.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_copy.png index 661cd9a17..8c159de83 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_copy.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_copy.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_delete.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_delete.png index 9d8104c01..64a417823 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_delete.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_done.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_done.png index 428dc8454..a48c82663 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_done.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_done.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_fave.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_fave.png index 883e9aa73..fc2b814ff 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_fave.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_fave.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_forward.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_forward.png index 6d24be15d..01dfdfb4d 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_forward.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_new.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_new.png index a877390bd..1d8078137 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_new.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_new.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_other.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_other.png index 1d8ad18a0..3d19133f7 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_other.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_other.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_reply.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_reply.png index 5e66fa969..a2e13a1b9 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_reply.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_reply2.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_reply2.png index 48c90010d..30d186ce1 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_reply2.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_reply2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_search.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_search.png index dff1e3a8a..2090d8fa8 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_search.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_unfave.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_unfave.png index a38f06a62..62714010e 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_unfave.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_unfave.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_again.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_again.png index cb77bb1f6..87ad2fbe9 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_again.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_again.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_againinline.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_againinline.png index 0d1d8e73d..b554d2d34 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_againinline.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_againinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_arrow_drop_down.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_arrow_drop_down.png index dc801dc1a..120e8bc2f 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_arrow_drop_down.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_arrow_drop_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_call.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_call.png new file mode 100644 index 000000000..a84b9acdc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/ic_call.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_call_made_green_18dp.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_call_made_green_18dp.png index 68dd5ef7a..7d2ccaa22 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_call_made_green_18dp.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_call_made_green_18dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_call_received_green_18dp.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_call_received_green_18dp.png index dbd3e2069..e42fce636 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_call_received_green_18dp.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_call_received_green_18dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_call_white_24dp.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_call_white_24dp.png deleted file mode 100755 index 77f9de5e3..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_call_white_24dp.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_close_white.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_close_white.png index e80681aeb..f60c6a09d 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_close_white.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_close_white.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_directory.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_directory.png index 4d64f01e0..f61d4d076 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_directory.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_directory.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_done.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_done.png index e91f9048b..a48c82663 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_done.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_done.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_external_storage.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_external_storage.png index 903927e72..81b69f236 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_external_storage.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_external_storage.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_fp_40px.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_fp_40px.png index 122f44257..ed8012f08 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_fp_40px.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_fp_40px.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_gallery_background.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_gallery_background.png index 7205e0826..311345641 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_gallery_background.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_gallery_background.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_gofullscreen.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_gofullscreen.png index 678d86c06..5d9930c00 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_gofullscreen.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_gofullscreen.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_goinline.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_goinline.png index ab8b13d87..aa02907be 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_goinline.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_goinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_keyboard_w.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_keyboard_w.png deleted file mode 100755 index 1f4614aab..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_keyboard_w.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_launcher.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_launcher.png deleted file mode 100755 index b74069ad0..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_launcher.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_launcher_dr.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_launcher_dr.png new file mode 100644 index 000000000..ef397fd79 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/ic_launcher_dr.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_lock_header.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_lock_header.png index a414a87ae..2ff251dea 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_lock_header.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_lock_header.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_lock_white.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_lock_white.png index 15894766f..e0c6b583a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_lock_white.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_lock_white.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_masks_msk1.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_masks_msk1.png index 72eb40059..88761765e 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_masks_msk1.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_masks_msk1.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_masks_recent1.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_masks_recent1.png index c3f39d111..56379a965 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_masks_recent1.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_masks_recent1.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_masks_sticker1.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_masks_sticker1.png index f4c491e1f..5fcf7d9b6 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_masks_sticker1.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_masks_sticker1.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_msg_panel_gif.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_msg_panel_gif.png deleted file mode 100755 index b994a09e9..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_msg_panel_gif.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_msg_panel_kb.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_msg_panel_kb.png deleted file mode 100755 index 50d1439d6..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_msg_panel_kb.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_msg_panel_smiles.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_msg_panel_smiles.png deleted file mode 100755 index c53353143..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_msg_panel_smiles.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_msg_panel_stickers.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_msg_panel_stickers.png deleted file mode 100755 index 9ec2f8599..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_msg_panel_stickers.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_msg_panel_video.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_msg_panel_video.png deleted file mode 100755 index dfa24c677..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_msg_panel_video.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_outfullscreen.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_outfullscreen.png index 9ac836715..d267c6942 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_outfullscreen.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_outfullscreen.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_outinline.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_outinline.png index 59ffad30c..565ac1555 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_outinline.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_outinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_pause.png index a96530f53..c6dc73c93 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_pause.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_pauseinline.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_pauseinline.png index e37cba7a8..1818039e5 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_pauseinline.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_pauseinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_play.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_play.png index 458981e73..f18fdea5f 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_play.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_playinline.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_playinline.png index 9e903a4b4..94722cea5 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_playinline.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_playinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_rating_star.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_rating_star.png index c80fa717d..97371d5a1 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_rating_star.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_rating_star.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_rating_star_filled.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_rating_star_filled.png index b509c0ba4..a8edeacf1 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_rating_star_filled.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_rating_star_filled.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_reply_icon.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_reply_icon.png index 513865901..a8a07a94c 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_reply_icon.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_reply_icon.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_send.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_send.png index 982a7e522..7c439115f 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_send.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_send.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_share_article.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_share_article.png index 046f3461c..5809251b1 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_share_article.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_share_article.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_share_video.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_share_video.png index ed27722cf..1ed63ca85 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_share_video.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_share_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_smile_small.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_smile_small.png deleted file mode 100644 index 827de6255..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_smile_small.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_smile_w.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_smile_w.png deleted file mode 100755 index a110abc10..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_smile_w.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_car.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_car.png deleted file mode 100755 index 1750f01c5..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_car.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_food.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_food.png deleted file mode 100755 index a11434a35..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_food.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_nature.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_nature.png deleted file mode 100755 index 1e7bbf406..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_nature.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_objects.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_objects.png deleted file mode 100755 index a31f51e10..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_objects.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_recent.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_recent.png deleted file mode 100755 index 492879ca2..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_recent.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_sad.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_sad.png index 242bd564d..84fe08b52 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_sad.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_sad.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_smile.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_smile.png deleted file mode 100755 index ef295e9e6..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_smile.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_stickers.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_stickers.png deleted file mode 100755 index 7796db2f3..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles2_stickers.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles_backspace.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles_backspace.png deleted file mode 100755 index 3ca28d429..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles_backspace.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles_gif.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles_gif.png deleted file mode 100755 index 2e5e499d1..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles_gif.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles_settings.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles_settings.png deleted file mode 100755 index b5057c249..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles_settings.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles_trend.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles_trend.png deleted file mode 100755 index 1b7361856..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_smiles_trend.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_storage.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_storage.png index 6b7f42149..e6dfc3d2f 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_storage.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_storage.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_storage_gallery.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_storage_gallery.png index 69faf7c21..c4e31cb85 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_storage_gallery.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_storage_gallery.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_storage_music.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_storage_music.png index 77f4ebe95..3fbfe86ee 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_storage_music.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_storage_music.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_video.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_video.png index b83d000ae..1d840f406 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_video.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_volume_up_white_24dp.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_volume_up_white_24dp.png index 7cfd4c7b8..c727f1129 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_volume_up_white_24dp.png and b/TMessagesProj/src/main/res/drawable-mdpi/ic_volume_up_white_24dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/inline_video_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/inline_video_pause.png index 27d8ea66e..f748ba8f9 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/inline_video_pause.png and b/TMessagesProj/src/main/res/drawable-mdpi/inline_video_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/inline_video_play.png b/TMessagesProj/src/main/res/drawable-mdpi/inline_video_play.png index e3b8d462a..220f98e41 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/inline_video_play.png and b/TMessagesProj/src/main/res/drawable-mdpi/inline_video_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_attach.png b/TMessagesProj/src/main/res/drawable-mdpi/input_attach.png new file mode 100644 index 000000000..ae24662ad Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_attach.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_bot1.png b/TMessagesProj/src/main/res/drawable-mdpi/input_bot1.png new file mode 100644 index 000000000..fea8796c1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_bot1.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_bot2.png b/TMessagesProj/src/main/res/drawable-mdpi/input_bot2.png new file mode 100644 index 000000000..682e2a35d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_bot2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_clear.png b/TMessagesProj/src/main/res/drawable-mdpi/input_clear.png new file mode 100644 index 000000000..54521055f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_done.png b/TMessagesProj/src/main/res/drawable-mdpi/input_done.png new file mode 100644 index 000000000..685914f92 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_done.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_forward.png b/TMessagesProj/src/main/res/drawable-mdpi/input_forward.png new file mode 100644 index 000000000..e5b7c44eb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_gif.png b/TMessagesProj/src/main/res/drawable-mdpi/input_gif.png new file mode 100644 index 000000000..0b267fafe Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_keyboard.png b/TMessagesProj/src/main/res/drawable-mdpi/input_keyboard.png new file mode 100644 index 000000000..1e23b7225 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_keyboard.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_mic.png b/TMessagesProj/src/main/res/drawable-mdpi/input_mic.png new file mode 100644 index 000000000..bf85b1e75 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_mic.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_notify_off.png b/TMessagesProj/src/main/res/drawable-mdpi/input_notify_off.png new file mode 100644 index 000000000..591c1bffd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_notify_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_notify_on.png b/TMessagesProj/src/main/res/drawable-mdpi/input_notify_on.png new file mode 100644 index 000000000..5afbfcc41 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_notify_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_reply.png b/TMessagesProj/src/main/res/drawable-mdpi/input_reply.png new file mode 100644 index 000000000..8a3bb8754 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_smile.png b/TMessagesProj/src/main/res/drawable-mdpi/input_smile.png new file mode 100644 index 000000000..82ab6cdb1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_smile.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_sticker.png b/TMessagesProj/src/main/res/drawable-mdpi/input_sticker.png new file mode 100644 index 000000000..56bf9edc7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_sticker.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/input_video.png b/TMessagesProj/src/main/res/drawable-mdpi/input_video.png new file mode 100644 index 000000000..15a54b9e9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/input_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/instant_camera.png b/TMessagesProj/src/main/res/drawable-mdpi/instant_camera.png index 3dc347e88..a130cc730 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/instant_camera.png and b/TMessagesProj/src/main/res/drawable-mdpi/instant_camera.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/instant_link.png b/TMessagesProj/src/main/res/drawable-mdpi/instant_link.png index 040ce08f6..3c6fe4de9 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/instant_link.png and b/TMessagesProj/src/main/res/drawable-mdpi/instant_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_fast_arrow.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_fast_arrow.png index 1712dcb05..8bb275018 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_fast_arrow.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_fast_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_fast_arrow_shadow.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_fast_arrow_shadow.png index be5e6940b..6a1548c3f 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_fast_arrow_shadow.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_fast_arrow_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_fast_body.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_fast_body.png index a0ae7455c..fe23c9574 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_fast_body.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_fast_body.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_fast_spiral.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_fast_spiral.png index 5ec4b2e4a..c7a82bf1b 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_fast_spiral.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_fast_spiral.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_bubble.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_bubble.png index 041c59faf..b8a8e0500 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_bubble.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_bubble.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_bubble_dot.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_bubble_dot.png index b23265aa7..05777def3 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_bubble_dot.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_bubble_dot.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_cam.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_cam.png index 71b03c12f..f4da301f1 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_cam.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_cam.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_cam_lens.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_cam_lens.png index 7bd1f3203..4e954ccfa 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_cam_lens.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_cam_lens.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_pencil.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_pencil.png index 0e53de3ff..a57d6143d 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_pencil.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_pencil.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_pin.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_pin.png index 8fd091b63..092ec5c9f 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_pin.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_smile.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_smile.png index b7055d81e..1105bbae5 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_smile.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_smile.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_smile_eye.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_smile_eye.png index 72f350010..4065fd8ce 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_smile_eye.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_smile_eye.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_videocam.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_videocam.png index d3c3a5a25..71ea9528f 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_videocam.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_ic_videocam.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_knot_down.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_knot_down.png index c4c50ee6f..510701f60 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_knot_down.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_knot_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_knot_up.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_knot_up.png index c853bd18c..2062893c3 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_knot_up.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_knot_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_powerful_infinity.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_powerful_infinity.png index 6b0c87622..6952c47d9 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_powerful_infinity.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_powerful_infinity.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_powerful_infinity_white.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_powerful_infinity_white.png index dd6ee3861..81f598346 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_powerful_infinity_white.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_powerful_infinity_white.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_powerful_mask.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_powerful_mask.png index 4efc053a1..e627a51b2 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_powerful_mask.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_powerful_mask.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_powerful_star.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_powerful_star.png index d0fefec08..e5b9aac38 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_powerful_star.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_powerful_star.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_private_door.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_private_door.png index 869068856..52a7fd4b4 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_private_door.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_private_door.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_private_screw.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_private_screw.png index 77100ed23..75993711a 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_private_screw.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_private_screw.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_tg_plane.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_tg_plane.png index 51e6ef344..c7c65f292 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_tg_plane.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_tg_plane.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/intro_tg_sphere.png b/TMessagesProj/src/main/res/drawable-mdpi/intro_tg_sphere.png index 73cfd009f..0b08835ac 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/intro_tg_sphere.png and b/TMessagesProj/src/main/res/drawable-mdpi/intro_tg_sphere.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/knob_shadow.png b/TMessagesProj/src/main/res/drawable-mdpi/knob_shadow.png index 7cf10ee65..465978b9d 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/knob_shadow.png and b/TMessagesProj/src/main/res/drawable-mdpi/knob_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/layer_shadow.png b/TMessagesProj/src/main/res/drawable-mdpi/layer_shadow.png index aeefef42d..be5e51fe9 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/layer_shadow.png and b/TMessagesProj/src/main/res/drawable-mdpi/layer_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/list_bot.png b/TMessagesProj/src/main/res/drawable-mdpi/list_bot.png index a56320080..91b3cf511 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/list_bot.png and b/TMessagesProj/src/main/res/drawable-mdpi/list_bot.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/list_broadcast.png b/TMessagesProj/src/main/res/drawable-mdpi/list_broadcast.png index 72e0fa3e8..d7038f89c 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/list_broadcast.png and b/TMessagesProj/src/main/res/drawable-mdpi/list_broadcast.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/list_check.png b/TMessagesProj/src/main/res/drawable-mdpi/list_check.png old mode 100755 new mode 100644 index da4b4c832..420011712 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/list_check.png and b/TMessagesProj/src/main/res/drawable-mdpi/list_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/list_circle.png b/TMessagesProj/src/main/res/drawable-mdpi/list_circle.png index b35bee65f..ef7069e55 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/list_circle.png and b/TMessagesProj/src/main/res/drawable-mdpi/list_circle.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/list_group.png b/TMessagesProj/src/main/res/drawable-mdpi/list_group.png index 896d41b56..c0620b5e2 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/list_group.png and b/TMessagesProj/src/main/res/drawable-mdpi/list_group.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/list_halfcheck.png b/TMessagesProj/src/main/res/drawable-mdpi/list_halfcheck.png old mode 100755 new mode 100644 index 6fde716cb..5854a4a9d Binary files a/TMessagesProj/src/main/res/drawable-mdpi/list_halfcheck.png and b/TMessagesProj/src/main/res/drawable-mdpi/list_halfcheck.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/list_mute.png b/TMessagesProj/src/main/res/drawable-mdpi/list_mute.png old mode 100755 new mode 100644 index 756851163..8ccb01c1b Binary files a/TMessagesProj/src/main/res/drawable-mdpi/list_mute.png and b/TMessagesProj/src/main/res/drawable-mdpi/list_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/list_pin.png b/TMessagesProj/src/main/res/drawable-mdpi/list_pin.png old mode 100755 new mode 100644 index 1d0b16806..26075d5fa Binary files a/TMessagesProj/src/main/res/drawable-mdpi/list_pin.png and b/TMessagesProj/src/main/res/drawable-mdpi/list_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/list_reorder.png b/TMessagesProj/src/main/res/drawable-mdpi/list_reorder.png new file mode 100644 index 000000000..64bb73c2b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/list_reorder.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/list_secret.png b/TMessagesProj/src/main/res/drawable-mdpi/list_secret.png index 123d3a8d6..ff046cf73 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/list_secret.png and b/TMessagesProj/src/main/res/drawable-mdpi/list_secret.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/list_warning_sign.png b/TMessagesProj/src/main/res/drawable-mdpi/list_warning_sign.png index 6b2b30e57..4c0839b9a 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/list_warning_sign.png and b/TMessagesProj/src/main/res/drawable-mdpi/list_warning_sign.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/live_loc.png b/TMessagesProj/src/main/res/drawable-mdpi/live_loc.png index d3596179e..ae07b67a4 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/live_loc.png and b/TMessagesProj/src/main/res/drawable-mdpi/live_loc.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/livelocationpin.png b/TMessagesProj/src/main/res/drawable-mdpi/livelocationpin.png index 8d1e07860..ae979952e 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/livelocationpin.png and b/TMessagesProj/src/main/res/drawable-mdpi/livelocationpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/livepin.png b/TMessagesProj/src/main/res/drawable-mdpi/livepin.png index 50e3a2d3c..ace90aabb 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/livepin.png and b/TMessagesProj/src/main/res/drawable-mdpi/livepin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/load_big.png b/TMessagesProj/src/main/res/drawable-mdpi/load_big.png index 6cc2fabe4..10b4922ae 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/load_big.png and b/TMessagesProj/src/main/res/drawable-mdpi/load_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/location_panel.9.png b/TMessagesProj/src/main/res/drawable-mdpi/location_panel.9.png index 2fa579c0f..a3dedd7be 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/location_panel.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/location_panel.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/lock_arrow.png b/TMessagesProj/src/main/res/drawable-mdpi/lock_arrow.png index 4c37b9e05..a137f9402 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/lock_arrow.png and b/TMessagesProj/src/main/res/drawable-mdpi/lock_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/lock_close.png b/TMessagesProj/src/main/res/drawable-mdpi/lock_close.png index 47b4dd80a..77e14ceee 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/lock_close.png and b/TMessagesProj/src/main/res/drawable-mdpi/lock_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/lock_middle.png b/TMessagesProj/src/main/res/drawable-mdpi/lock_middle.png index 1e93060c2..59b37792f 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/lock_middle.png and b/TMessagesProj/src/main/res/drawable-mdpi/lock_middle.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/lock_open.png b/TMessagesProj/src/main/res/drawable-mdpi/lock_open.png index 689f1901e..cdb7696bb 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/lock_open.png and b/TMessagesProj/src/main/res/drawable-mdpi/lock_open.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/lock_round.9.png b/TMessagesProj/src/main/res/drawable-mdpi/lock_round.9.png index a8bc4f2df..68840612c 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/lock_round.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/lock_round.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/lock_round_shadow.9.png b/TMessagesProj/src/main/res/drawable-mdpi/lock_round_shadow.9.png index f6d88b6bd..52c566378 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/lock_round_shadow.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/lock_round_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/lock_top.png b/TMessagesProj/src/main/res/drawable-mdpi/lock_top.png index 23feb7b6f..27df9d125 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/lock_top.png and b/TMessagesProj/src/main/res/drawable-mdpi/lock_top.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/log_info.png b/TMessagesProj/src/main/res/drawable-mdpi/log_info.png index c256730ad..a223da1ff 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/log_info.png and b/TMessagesProj/src/main/res/drawable-mdpi/log_info.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/logo_avatar.png b/TMessagesProj/src/main/res/drawable-mdpi/logo_avatar.png index c2de7747c..c777a68dd 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/logo_avatar.png and b/TMessagesProj/src/main/res/drawable-mdpi/logo_avatar.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/logo_middle.png b/TMessagesProj/src/main/res/drawable-mdpi/logo_middle.png index f80d91042..fb126a838 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/logo_middle.png and b/TMessagesProj/src/main/res/drawable-mdpi/logo_middle.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/map_pin.png b/TMessagesProj/src/main/res/drawable-mdpi/map_pin.png index 6b685404b..67f418ee4 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/map_pin.png and b/TMessagesProj/src/main/res/drawable-mdpi/map_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_blue.png b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_blue.png index f62600314..11c167e90 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_blue.png and b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_blue.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_blue_b.png b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_blue_b.png index 660b44b99..2672b05cb 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_blue_b.png and b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_blue_b.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_green.png b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_green.png index 1d3f72ae3..ffbd82bea 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_green.png and b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_green.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_green_b.png b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_green_b.png index af67361e4..b9b0686d5 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_green_b.png and b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_green_b.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_load.png b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_load.png index bbf0446ec..2a73bb61c 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_load.png and b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_load.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_pause.png index 647de1b72..9b11ea066 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_pause.png and b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_red.png b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_red.png index 9c3803eb4..8697b8301 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_red.png and b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_red.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_red_b.png b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_red_b.png index b9711f6ff..069d42fc1 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_red_b.png and b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_red_b.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_yellow.png b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_yellow.png index 137f5e5a7..de7c2a101 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_yellow.png and b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_yellow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_yellow_b.png b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_yellow_b.png index 44174e20d..2f910224d 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/media_doc_yellow_b.png and b/TMessagesProj/src/main/res/drawable-mdpi/media_doc_yellow_b.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/mentionbutton.png b/TMessagesProj/src/main/res/drawable-mdpi/mentionbutton.png index bce0ae229..0d6554425 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/mentionbutton.png and b/TMessagesProj/src/main/res/drawable-mdpi/mentionbutton.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/mentionchatslist.png b/TMessagesProj/src/main/res/drawable-mdpi/mentionchatslist.png index dcc4d3e7e..97a62ca51 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/mentionchatslist.png and b/TMessagesProj/src/main/res/drawable-mdpi/mentionchatslist.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_add.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_add.png index 035ea63f5..e9a2d34f6 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_add.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_bookmarks_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_bookmarks_ny.png index 64cbb3e60..56e621030 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_bookmarks_ny.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_bookmarks_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_broadcast.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_broadcast.png index f7a74d485..2d6f0f7a8 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_broadcast.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_broadcast.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_calls.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_calls.png index 836675e7d..99b5a7426 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_calls.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_calls.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_calls_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_calls_ny.png index 93eda4b78..7ab3191bb 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_calls_ny.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_calls_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_camera.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_camera.png index 9d94e5ca9..48a900c66 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_camera.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_camera.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_camera_av.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_camera_av.png index 609904bf0..35770572c 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_camera_av.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_camera_av.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_channel_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_channel_ny.png index ae55b89a4..57eadd807 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_channel_ny.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_channel_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_chats.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_chats.png index 90d4b98e1..fae19199a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_chats.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_chats.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_clearcache.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_clearcache.png index db2e4a600..6934a31f7 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_clearcache.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_clearcache.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_contacts.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_contacts.png index db3dd45a5..1eedff198 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_contacts.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_contacts.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_contacts_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_contacts_ny.png index b330ca538..87fba8987 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_contacts_ny.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_contacts_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_copy.9.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_copy.9.png index 1c8dfc502..85d5cb7dc 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_copy.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_copy.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_data.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_data.png index 3fdc948a1..d86878635 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_data.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_data.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_groups.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_groups.png new file mode 100644 index 000000000..09beec6d0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_groups.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_groups_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_groups_ny.png index c56b66135..1b59c0af6 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_groups_ny.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_groups_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_help.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_help.png index 889ead161..e3e1644d1 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_help.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_help.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_help_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_help_ny.png index 22a644d6c..6b99b0fa2 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_help_ny.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_help_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_invite.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_invite.png index fc9920138..21233cc78 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_invite.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_invite.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_invite_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_invite_ny.png index 8ed7d2500..7e93eba0f 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_invite_ny.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_invite_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_language.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_language.png index 8a1502ff2..ac3fdf49a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_language.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_language.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_newgroup.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_newgroup.png deleted file mode 100644 index 83534ce4a..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_newgroup.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_newphone.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_newphone.png index fedd598d0..f1cb5012d 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_newphone.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_newphone.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_notifications.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_notifications.png index d2a48fe5a..e706df859 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_notifications.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_notifications.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_palette.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_palette.png index ad0670f3f..a0e85cf73 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_palette.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_palette.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_passcode.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_passcode.png index 179c5ff1b..c84ab7f49 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_passcode.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_passcode.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_read.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_read.png index fc6943817..6d9aa981b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_read.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_read.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_saved.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_saved.png index 441d8b1e2..86d92e59a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_saved.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_saved.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_search.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_search.png index a18b8fcfe..df9921dbb 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_search.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_secret.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_secret.png index bbb7a928e..05f1c2940 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_secret.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_secret.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_secret_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_secret_ny.png index 357595a43..237f65315 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_secret_ny.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_secret_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_settings.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_settings.png index 4b4d28ad6..3f26f268e 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_settings.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_settings_filled.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_settings_filled.png index 8a9422d3f..ca3afb885 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_settings_filled.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_settings_filled.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_settings_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_settings_ny.png index 92fe97683..913db500c 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_settings_ny.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_settings_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_shadow.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_shadow.png index 1ffe94269..f22b515da 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_shadow.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_support.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_support.png index 4c08b8f86..2b5613373 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_support.png and b/TMessagesProj/src/main/res/drawable-mdpi/menu_support.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_unread.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_unread.png deleted file mode 100644 index 65f4072a9..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_unread.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/message_arrow.png b/TMessagesProj/src/main/res/drawable-mdpi/message_arrow.png index 8d6a060d4..19264a870 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/message_arrow.png and b/TMessagesProj/src/main/res/drawable-mdpi/message_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/mic.png b/TMessagesProj/src/main/res/drawable-mdpi/mic.png deleted file mode 100644 index 400f59f6f..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/mic.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_close.png b/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_close.png index 7f74b0156..37099718b 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_close.png and b/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_pause.png index 0f608a014..c02b9ec14 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_pause.png and b/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_play.png b/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_play.png index 28116e88c..6a1d1c4bd 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_play.png and b/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/moon.png b/TMessagesProj/src/main/res/drawable-mdpi/moon.png index ebc53da3e..345430d72 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/moon.png and b/TMessagesProj/src/main/res/drawable-mdpi/moon.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_actions.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_actions.png index b683c96de..96cab86ae 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_actions.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_actions.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_addbot.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_addbot.png new file mode 100644 index 000000000..e95c3b4c0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_addbot.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_addcontact.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_addcontact.png new file mode 100644 index 000000000..5c1cdbead Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_addcontact.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_archive.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_archive.png new file mode 100644 index 000000000..0f0243bc9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_archive.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_block.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_block.png new file mode 100644 index 000000000..8dde94d52 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_block.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_calendar.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_calendar.png new file mode 100644 index 000000000..220627a80 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_calendar.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_callback.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_callback.png new file mode 100644 index 000000000..e786dfa03 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_callback.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_cancel.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_cancel.png new file mode 100644 index 000000000..cbb33253d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_check.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_check.png index f56fd66a3..a86450d0d 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_check.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_clear.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_clear.png new file mode 100644 index 000000000..bf7a84683 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_clock.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_clock.png index 2182fb4e1..1248954b3 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_clock.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_clock.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_contact.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_contact.png index 90d9388e1..534467d93 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_contact.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_contact.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_copy.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_copy.png new file mode 100644 index 000000000..608f009e2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_copy.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_delete.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_delete.png new file mode 100644 index 000000000..0a846fb25 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_download.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_download.png new file mode 100644 index 000000000..dbaa9e9ad Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_download.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_edit.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_edit.png new file mode 100644 index 000000000..486dbd350 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_edit.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_fave.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_fave.png new file mode 100644 index 000000000..d4c6d083a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_fave.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_forward.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_forward.png new file mode 100644 index 000000000..b89bc4983 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_gallery.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_gallery.png new file mode 100644 index 000000000..36c7c50e4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_gallery.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_gif.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_gif.png new file mode 100644 index 000000000..c988f096b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_go_down.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_go_down.png new file mode 100644 index 000000000..f84a64969 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_go_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_go_up.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_go_up.png new file mode 100644 index 000000000..7b91fae01 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_go_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_halfcheck.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_halfcheck.png index 23ed5e7ce..cf3867cde 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_halfcheck.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_halfcheck.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_home.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_home.png new file mode 100644 index 000000000..425389511 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_home.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_hybrid.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_hybrid.png new file mode 100644 index 000000000..af3989c15 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_hybrid.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_in.9.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_in.9.png index 1b993976d..1e7afefc2 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_in.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_in.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_in_shadow.9.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_in_shadow.9.png index 6a780bdbc..7773d861b 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_in_shadow.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_in_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_instant.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_instant.png index 1cacca81c..c5d1a41a9 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_instant.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_instant.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_language.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_language.png new file mode 100644 index 000000000..ef26204bb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_language.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_leave.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_leave.png new file mode 100644 index 000000000..77c1cb482 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_leave.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_link.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_link.png new file mode 100644 index 000000000..3e3ba72ec Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_location.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_location.png index 176d9a099..f60c06310 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_location.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_map.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_map.png new file mode 100644 index 000000000..fb9494b3d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_map.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_markread.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_markread.png new file mode 100644 index 000000000..8fc3aeba3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_markread.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_markunread.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_markunread.png new file mode 100644 index 000000000..ff705bb09 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_markunread.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_mask.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_mask.png new file mode 100644 index 000000000..4684b3b1d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_mask.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_media.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_media.png new file mode 100644 index 000000000..c6a7a4c0d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_media.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_message.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_message.png new file mode 100644 index 000000000..aac6b3edf Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_message.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_mute.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_mute.png new file mode 100644 index 000000000..4dc2917ba Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_openin.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_openin.png new file mode 100644 index 000000000..470a21b43 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_openin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_out.9.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_out.9.png index 869bf1479..cbaf0649f 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_out.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_out.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_out_shadow.9.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_out_shadow.9.png index 047d9dd7b..3ba555d0c 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_out_shadow.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_out_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_panel_clear.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_panel_clear.png index 20f4fc40e..a7f343f93 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_panel_clear.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_panel_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_panel_forward.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_panel_forward.png index ec6848192..01dfdfb4d 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_panel_forward.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_panel_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_panel_link.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_panel_link.png deleted file mode 100755 index be6d04d9e..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_panel_link.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_panel_reply.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_panel_reply.png index 4cd49dd5f..1fdd6af8c 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_panel_reply.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_panel_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo.9.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo.9.png index d8c59ffe4..cdcc5a472 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_shadow.9.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_shadow.9.png index 50d35cdf9..48643c643 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_shadow.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_pin.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_pin.png new file mode 100644 index 000000000..7d7b9b312 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_pollstop.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_pollstop.png new file mode 100644 index 000000000..569e6927c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_pollstop.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_reply.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_reply.png new file mode 100644 index 000000000..e0d2252e7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_report.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_report.png new file mode 100644 index 000000000..07d2713e4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_report.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_retry.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_retry.png new file mode 100644 index 000000000..84632d17d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_retry.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_round_cancel_m.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_round_cancel_m.png index 668dc2cc6..88d1316dd 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_round_cancel_m.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_round_cancel_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_round_file_s.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_round_file_s.png index 2666ccc28..68f20b277 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_round_file_s.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_round_file_s.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_round_gif_m.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_round_gif_m.png index a82b2fdd9..ebc432037 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_round_gif_m.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_round_gif_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_round_load_m.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_round_load_m.png index 2e8cb31ba..a1103cabb 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_round_load_m.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_round_load_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_round_pause_m.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_round_pause_m.png index b8361c70a..38d7a4696 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_round_pause_m.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_round_pause_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_round_play_m.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_round_play_m.png index 922864b52..9488d86ac 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_round_play_m.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_round_play_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_satellite.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_satellite.png new file mode 100644 index 000000000..6c3da8198 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_satellite.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_search.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_search.png new file mode 100644 index 000000000..b5fa27021 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_share.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_share.png new file mode 100644 index 000000000..818a0edb7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_share.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_shareout.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_shareout.png new file mode 100644 index 000000000..0a19abd51 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_shareout.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_stats.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_stats.png new file mode 100644 index 000000000..68cc22fba Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_stats.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_sticker.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_sticker.png new file mode 100644 index 000000000..7bf88c334 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_sticker.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_theme.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_theme.png new file mode 100644 index 000000000..900656117 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_theme.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_timer.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_timer.png new file mode 100644 index 000000000..912381dc3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_timer.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_unarchive.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_unarchive.png new file mode 100644 index 000000000..49618d07d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_unarchive.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_unfave.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_unfave.png new file mode 100644 index 000000000..83e95a8f8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_unfave.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_unmute.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_unmute.png new file mode 100644 index 000000000..2e201bbd9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_unmute.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_unpin.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_unpin.png new file mode 100644 index 000000000..b0fd8507d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_unpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_unvote.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_unvote.png new file mode 100644 index 000000000..0c108cbcb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_unvote.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_usersearch.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_usersearch.png new file mode 100644 index 000000000..d0b290916 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_usersearch.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_views.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_views.png index 894d8cbb6..258e9bd02 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_views.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_views.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_warning.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_warning.png index 0c868b862..448063ede 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_warning.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_warning.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/music_reverse.png b/TMessagesProj/src/main/res/drawable-mdpi/music_reverse.png index 248826ba9..03b7ddcf1 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/music_reverse.png and b/TMessagesProj/src/main/res/drawable-mdpi/music_reverse.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/myloc_on.png b/TMessagesProj/src/main/res/drawable-mdpi/myloc_on.png index 5484c902d..2eff321b1 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/myloc_on.png and b/TMessagesProj/src/main/res/drawable-mdpi/myloc_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/navigate.png b/TMessagesProj/src/main/res/drawable-mdpi/navigate.png index 872d18fa7..3aa139836 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/navigate.png and b/TMessagesProj/src/main/res/drawable-mdpi/navigate.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/newmsg_divider.png b/TMessagesProj/src/main/res/drawable-mdpi/newmsg_divider.png index 61510e887..3f7dbcd12 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/newmsg_divider.png and b/TMessagesProj/src/main/res/drawable-mdpi/newmsg_divider.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/newyear.png b/TMessagesProj/src/main/res/drawable-mdpi/newyear.png index 5d21eacf8..957881bd9 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/newyear.png and b/TMessagesProj/src/main/res/drawable-mdpi/newyear.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/no_apps.png b/TMessagesProj/src/main/res/drawable-mdpi/no_apps.png index 33e8b358f..0ad4947f4 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/no_apps.png and b/TMessagesProj/src/main/res/drawable-mdpi/no_apps.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/no_passport.png b/TMessagesProj/src/main/res/drawable-mdpi/no_passport.png index 50429d6b0..a52fd01ef 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/no_passport.png and b/TMessagesProj/src/main/res/drawable-mdpi/no_passport.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/no_password.png b/TMessagesProj/src/main/res/drawable-mdpi/no_password.png index f7722265d..7350f803b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/no_password.png and b/TMessagesProj/src/main/res/drawable-mdpi/no_password.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/nocover.png b/TMessagesProj/src/main/res/drawable-mdpi/nocover.png index 30db7ed46..be516152e 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/nocover.png and b/TMessagesProj/src/main/res/drawable-mdpi/nocover.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/nocover_big.9.png b/TMessagesProj/src/main/res/drawable-mdpi/nocover_big.9.png index 017c16f16..1641d37ee 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/nocover_big.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/nocover_big.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/nocover_small.9.png b/TMessagesProj/src/main/res/drawable-mdpi/nocover_small.9.png index 6c5b5e65f..a92c729a9 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/nocover_small.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/nocover_small.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/nophotos.9.png b/TMessagesProj/src/main/res/drawable-mdpi/nophotos.9.png index 30f05e378..e4222e50d 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/nophotos.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/nophotos.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/notification.png b/TMessagesProj/src/main/res/drawable-mdpi/notification.png old mode 100755 new mode 100644 index 675c75020..68680918f Binary files a/TMessagesProj/src/main/res/drawable-mdpi/notification.png and b/TMessagesProj/src/main/res/drawable-mdpi/notification.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/notifications_mute1h.png b/TMessagesProj/src/main/res/drawable-mdpi/notifications_mute1h.png index 81229a3fa..ed980c76c 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/notifications_mute1h.png and b/TMessagesProj/src/main/res/drawable-mdpi/notifications_mute1h.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/notifications_mute2d.png b/TMessagesProj/src/main/res/drawable-mdpi/notifications_mute2d.png index b03287a16..7675c726d 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/notifications_mute2d.png and b/TMessagesProj/src/main/res/drawable-mdpi/notifications_mute2d.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/notifications_off.png b/TMessagesProj/src/main/res/drawable-mdpi/notifications_off.png index 74adb3023..0f92fdae5 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/notifications_off.png and b/TMessagesProj/src/main/res/drawable-mdpi/notifications_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/notifications_on.png b/TMessagesProj/src/main/res/drawable-mdpi/notifications_on.png index 54f1360d5..43ef6ec41 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/notifications_on.png and b/TMessagesProj/src/main/res/drawable-mdpi/notifications_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/notifications_settings.png b/TMessagesProj/src/main/res/drawable-mdpi/notifications_settings.png index b141069de..bf910a41d 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/notifications_settings.png and b/TMessagesProj/src/main/res/drawable-mdpi/notifications_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/notify_members_off.png b/TMessagesProj/src/main/res/drawable-mdpi/notify_members_off.png deleted file mode 100644 index 298196404..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/notify_members_off.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/notify_members_on.png b/TMessagesProj/src/main/res/drawable-mdpi/notify_members_on.png deleted file mode 100644 index 75fe60c38..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/notify_members_on.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/outline_add_gif.png b/TMessagesProj/src/main/res/drawable-mdpi/outline_add_gif.png new file mode 100644 index 000000000..79aa29baa Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/outline_add_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/outline_fave.png b/TMessagesProj/src/main/res/drawable-mdpi/outline_fave.png new file mode 100644 index 000000000..313fff27c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/outline_fave.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/outline_pack.png b/TMessagesProj/src/main/res/drawable-mdpi/outline_pack.png new file mode 100644 index 000000000..28c7f4bd0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/outline_pack.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/outline_send.png b/TMessagesProj/src/main/res/drawable-mdpi/outline_send.png new file mode 100644 index 000000000..f02c80c52 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/outline_send.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/outline_unfave.png b/TMessagesProj/src/main/res/drawable-mdpi/outline_unfave.png new file mode 100644 index 000000000..e7a93e130 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/outline_unfave.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pagedown.png b/TMessagesProj/src/main/res/drawable-mdpi/pagedown.png index 2438a0486..c21b132d6 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/pagedown.png and b/TMessagesProj/src/main/res/drawable-mdpi/pagedown.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pagedown_shadow.png b/TMessagesProj/src/main/res/drawable-mdpi/pagedown_shadow.png index 7d9d6470a..5af9bfebc 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/pagedown_shadow.png and b/TMessagesProj/src/main/res/drawable-mdpi/pagedown_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/passcode_check.png b/TMessagesProj/src/main/res/drawable-mdpi/passcode_check.png index 1a39754e0..cc8ce7ee1 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/passcode_check.png and b/TMessagesProj/src/main/res/drawable-mdpi/passcode_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/passcode_delete.png b/TMessagesProj/src/main/res/drawable-mdpi/passcode_delete.png index c1ccb443b..0c87b8d88 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/passcode_delete.png and b/TMessagesProj/src/main/res/drawable-mdpi/passcode_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/passcode_logo.png b/TMessagesProj/src/main/res/drawable-mdpi/passcode_logo.png index 865cb4c97..2b831955c 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/passcode_logo.png and b/TMessagesProj/src/main/res/drawable-mdpi/passcode_logo.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/permission_locked.png b/TMessagesProj/src/main/res/drawable-mdpi/permission_locked.png index f44822b27..307d8d182 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/permission_locked.png and b/TMessagesProj/src/main/res/drawable-mdpi/permission_locked.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/permissions_contacts.png b/TMessagesProj/src/main/res/drawable-mdpi/permissions_contacts.png index e9041c5a9..6b935d05f 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/permissions_contacts.png and b/TMessagesProj/src/main/res/drawable-mdpi/permissions_contacts.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/phone_activate.png b/TMessagesProj/src/main/res/drawable-mdpi/phone_activate.png index 62dcc7aee..58f95cdce 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/phone_activate.png and b/TMessagesProj/src/main/res/drawable-mdpi/phone_activate.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/phone_change.png b/TMessagesProj/src/main/res/drawable-mdpi/phone_change.png index 20ba8c38a..bb58221c8 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/phone_change.png and b/TMessagesProj/src/main/res/drawable-mdpi/phone_change.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photo_add.png b/TMessagesProj/src/main/res/drawable-mdpi/photo_add.png index eca6c77a2..b5189257b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photo_add.png and b/TMessagesProj/src/main/res/drawable-mdpi/photo_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photo_crop.png b/TMessagesProj/src/main/res/drawable-mdpi/photo_crop.png index 0e0cfd83e..c3642da00 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photo_crop.png and b/TMessagesProj/src/main/res/drawable-mdpi/photo_crop.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photo_outline.png b/TMessagesProj/src/main/res/drawable-mdpi/photo_outline.png index e172b0cb9..ed44c2392 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photo_outline.png and b/TMessagesProj/src/main/res/drawable-mdpi/photo_outline.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photo_paint.png b/TMessagesProj/src/main/res/drawable-mdpi/photo_paint.png index 1acfcc770..348ba9407 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photo_paint.png and b/TMessagesProj/src/main/res/drawable-mdpi/photo_paint.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photo_paint_brush.png b/TMessagesProj/src/main/res/drawable-mdpi/photo_paint_brush.png index 0120118fa..c2c3848db 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photo_paint_brush.png and b/TMessagesProj/src/main/res/drawable-mdpi/photo_paint_brush.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photo_paint_text.png b/TMessagesProj/src/main/res/drawable-mdpi/photo_paint_text.png index 64812fa09..a17dc5f6c 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photo_paint_text.png and b/TMessagesProj/src/main/res/drawable-mdpi/photo_paint_text.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photo_sticker.png b/TMessagesProj/src/main/res/drawable-mdpi/photo_sticker.png index 8e942e352..3b0522508 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photo_sticker.png and b/TMessagesProj/src/main/res/drawable-mdpi/photo_sticker.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photo_timer.png b/TMessagesProj/src/main/res/drawable-mdpi/photo_timer.png index 60d24143c..c37347e51 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photo_timer.png and b/TMessagesProj/src/main/res/drawable-mdpi/photo_timer.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photo_tools.png b/TMessagesProj/src/main/res/drawable-mdpi/photo_tools.png index 8832fb1dc..172789190 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photo_tools.png and b/TMessagesProj/src/main/res/drawable-mdpi/photo_tools.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photo_undo.png b/TMessagesProj/src/main/res/drawable-mdpi/photo_undo.png index d1c42c2bc..958fd9744 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photo_undo.png and b/TMessagesProj/src/main/res/drawable-mdpi/photo_undo.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photo_w.png b/TMessagesProj/src/main/res/drawable-mdpi/photo_w.png index 0f44275cd..d569e0d2d 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photo_w.png and b/TMessagesProj/src/main/res/drawable-mdpi/photo_w.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photobadge.9.png b/TMessagesProj/src/main/res/drawable-mdpi/photobadge.9.png index 259973e94..4df4e6f3b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photobadge.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/photobadge.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photocheck.png b/TMessagesProj/src/main/res/drawable-mdpi/photocheck.png index f21bacafa..b8253563e 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photocheck.png and b/TMessagesProj/src/main/res/drawable-mdpi/photocheck.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photos_arrow.png b/TMessagesProj/src/main/res/drawable-mdpi/photos_arrow.png index 31fd75a95..1b229476a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photos_arrow.png and b/TMessagesProj/src/main/res/drawable-mdpi/photos_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photos_group.png b/TMessagesProj/src/main/res/drawable-mdpi/photos_group.png index 32fad9748..9ca1783a3 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photos_group.png and b/TMessagesProj/src/main/res/drawable-mdpi/photos_group.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photos_header_shadow.png b/TMessagesProj/src/main/res/drawable-mdpi/photos_header_shadow.png index 5d297f8c6..9a78ae562 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photos_header_shadow.png and b/TMessagesProj/src/main/res/drawable-mdpi/photos_header_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/photos_rounded.9.png b/TMessagesProj/src/main/res/drawable-mdpi/photos_rounded.9.png index 9cdb4b296..3b0ff3b4f 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/photos_rounded.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/photos_rounded.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/phototime.9.png b/TMessagesProj/src/main/res/drawable-mdpi/phototime.9.png index 54a97cc78..0fc8eb83c 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/phototime.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/phototime.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pin.png b/TMessagesProj/src/main/res/drawable-mdpi/pin.png index 4ef2499c7..568155321 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/pin.png and b/TMessagesProj/src/main/res/drawable-mdpi/pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_next.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_next.png index 361102ebe..a14e23fdb 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/pl_next.png and b/TMessagesProj/src/main/res/drawable-mdpi/pl_next.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_pause.png index 977e79f88..e88b9aa7f 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/pl_pause.png and b/TMessagesProj/src/main/res/drawable-mdpi/pl_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_play.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_play.png index 7ade0e77c..8724b960e 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/pl_play.png and b/TMessagesProj/src/main/res/drawable-mdpi/pl_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_previous.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_previous.png index 2f48d1930..56dcd2555 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/pl_previous.png and b/TMessagesProj/src/main/res/drawable-mdpi/pl_previous.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat.png index d76515010..49d8251ea 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat.png and b/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat1.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat1.png index f53107316..105508574 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat1.png and b/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat1.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_shuffle.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_shuffle.png index acad2cf25..5b79693e9 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/pl_shuffle.png and b/TMessagesProj/src/main/res/drawable-mdpi/pl_shuffle.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/place_x.png b/TMessagesProj/src/main/res/drawable-mdpi/place_x.png index bf940d8cf..3ef4234c4 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/place_x.png and b/TMessagesProj/src/main/res/drawable-mdpi/place_x.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/play_big.png b/TMessagesProj/src/main/res/drawable-mdpi/play_big.png index 341bcac7f..f6b016301 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/play_big.png and b/TMessagesProj/src/main/res/drawable-mdpi/play_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/play_mini_video.png b/TMessagesProj/src/main/res/drawable-mdpi/play_mini_video.png index d5a6e8cfd..86dad3633 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/play_mini_video.png and b/TMessagesProj/src/main/res/drawable-mdpi/play_mini_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/player.png b/TMessagesProj/src/main/res/drawable-mdpi/player.png index 1a26651ce..dad8cd1d8 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/player.png and b/TMessagesProj/src/main/res/drawable-mdpi/player.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/plus.png b/TMessagesProj/src/main/res/drawable-mdpi/plus.png index 1a1d05e2a..f46832026 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/plus.png and b/TMessagesProj/src/main/res/drawable-mdpi/plus.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/popup_fixed.9.png b/TMessagesProj/src/main/res/drawable-mdpi/popup_fixed.9.png index 8b72316de..8220925b7 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/popup_fixed.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/popup_fixed.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/popup_fixed_alert.9.png b/TMessagesProj/src/main/res/drawable-mdpi/popup_fixed_alert.9.png index 58570d83e..08c408676 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/popup_fixed_alert.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/popup_fixed_alert.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/popup_fixed_alert2.9.png b/TMessagesProj/src/main/res/drawable-mdpi/popup_fixed_alert2.9.png new file mode 100644 index 000000000..811259dec Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/popup_fixed_alert2.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/popup_fixed_top.9.png b/TMessagesProj/src/main/res/drawable-mdpi/popup_fixed_top.9.png index 9083dbb5c..29cda0bd5 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/popup_fixed_top.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/popup_fixed_top.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/preview_arrow.png b/TMessagesProj/src/main/res/drawable-mdpi/preview_arrow.png new file mode 100644 index 000000000..fcf1989f8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/preview_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/preview_open.png b/TMessagesProj/src/main/res/drawable-mdpi/preview_open.png index 76b9b905b..c1e7f89b0 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/preview_open.png and b/TMessagesProj/src/main/res/drawable-mdpi/preview_open.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/profile_admin.png b/TMessagesProj/src/main/res/drawable-mdpi/profile_admin.png index ee9b77879..db681a4a1 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/profile_admin.png and b/TMessagesProj/src/main/res/drawable-mdpi/profile_admin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/profile_audio.png b/TMessagesProj/src/main/res/drawable-mdpi/profile_audio.png index 50fee19fb..6df6f65f5 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/profile_audio.png and b/TMessagesProj/src/main/res/drawable-mdpi/profile_audio.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/profile_ban.png b/TMessagesProj/src/main/res/drawable-mdpi/profile_ban.png index 211a50d97..b65d3c2bb 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/profile_ban.png and b/TMessagesProj/src/main/res/drawable-mdpi/profile_ban.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/profile_file.png b/TMessagesProj/src/main/res/drawable-mdpi/profile_file.png index 96a29a46f..8acf69881 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/profile_file.png and b/TMessagesProj/src/main/res/drawable-mdpi/profile_file.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/profile_groups.png b/TMessagesProj/src/main/res/drawable-mdpi/profile_groups.png deleted file mode 100644 index 33a3133fc..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/profile_groups.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/profile_info.png b/TMessagesProj/src/main/res/drawable-mdpi/profile_info.png index 999d4a785..0f4c0edfa 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/profile_info.png and b/TMessagesProj/src/main/res/drawable-mdpi/profile_info.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/profile_link.png b/TMessagesProj/src/main/res/drawable-mdpi/profile_link.png index e9d434242..49b86e402 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/profile_link.png and b/TMessagesProj/src/main/res/drawable-mdpi/profile_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/profile_list.png b/TMessagesProj/src/main/res/drawable-mdpi/profile_list.png index 0d808d0ea..a7647e5ea 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/profile_list.png and b/TMessagesProj/src/main/res/drawable-mdpi/profile_list.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/profile_message.png b/TMessagesProj/src/main/res/drawable-mdpi/profile_message.png index 836dd713c..c5bcddc32 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/profile_message.png and b/TMessagesProj/src/main/res/drawable-mdpi/profile_message.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/profile_newmsg.png b/TMessagesProj/src/main/res/drawable-mdpi/profile_newmsg.png index 4b3d75194..56ed64cf0 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/profile_newmsg.png and b/TMessagesProj/src/main/res/drawable-mdpi/profile_newmsg.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/profile_phone.png b/TMessagesProj/src/main/res/drawable-mdpi/profile_phone.png index 031f1823e..199982649 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/profile_phone.png and b/TMessagesProj/src/main/res/drawable-mdpi/profile_phone.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/profile_photos.png b/TMessagesProj/src/main/res/drawable-mdpi/profile_photos.png index 50deb93ac..6662b6867 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/profile_photos.png and b/TMessagesProj/src/main/res/drawable-mdpi/profile_photos.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/profile_voice.png b/TMessagesProj/src/main/res/drawable-mdpi/profile_voice.png index a6b223d2b..66f26b245 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/profile_voice.png and b/TMessagesProj/src/main/res/drawable-mdpi/profile_voice.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/proxy_check.png b/TMessagesProj/src/main/res/drawable-mdpi/proxy_check.png index 3ea33c621..13820112b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/proxy_check.png and b/TMessagesProj/src/main/res/drawable-mdpi/proxy_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/proxy_off.png b/TMessagesProj/src/main/res/drawable-mdpi/proxy_off.png index a7dc6c4d5..02ef8797a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/proxy_off.png and b/TMessagesProj/src/main/res/drawable-mdpi/proxy_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/proxy_on.png b/TMessagesProj/src/main/res/drawable-mdpi/proxy_on.png index cdc9fb901..2baf57564 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/proxy_on.png and b/TMessagesProj/src/main/res/drawable-mdpi/proxy_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/redcircle.png b/TMessagesProj/src/main/res/drawable-mdpi/redcircle.png index da49308fe..267fe7e4d 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/redcircle.png and b/TMessagesProj/src/main/res/drawable-mdpi/redcircle.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/regbtn2.9.png b/TMessagesProj/src/main/res/drawable-mdpi/regbtn2.9.png index 05534776b..0b4a6a51d 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/regbtn2.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/regbtn2.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/regbtn2_pressed.9.png b/TMessagesProj/src/main/res/drawable-mdpi/regbtn2_pressed.9.png index 3063f75d6..708ff2493 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/regbtn2_pressed.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/regbtn2_pressed.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/replyvideo.png b/TMessagesProj/src/main/res/drawable-mdpi/replyvideo.png index 4ac161def..fc2431522 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/replyvideo.png and b/TMessagesProj/src/main/res/drawable-mdpi/replyvideo.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/round_check2.png b/TMessagesProj/src/main/res/drawable-mdpi/round_check2.png index 6ff1a82af..d83f0fa3f 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/round_check2.png and b/TMessagesProj/src/main/res/drawable-mdpi/round_check2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/round_grey.png b/TMessagesProj/src/main/res/drawable-mdpi/round_grey.png index 7753080de..9f14e698a 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/round_grey.png and b/TMessagesProj/src/main/res/drawable-mdpi/round_grey.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/s_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/s_pause.png index 6411c8019..38583ccfc 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/s_pause.png and b/TMessagesProj/src/main/res/drawable-mdpi/s_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/s_play.png b/TMessagesProj/src/main/res/drawable-mdpi/s_play.png index 3602a9596..1ca38d58f 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/s_play.png and b/TMessagesProj/src/main/res/drawable-mdpi/s_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/scroll_tip.png b/TMessagesProj/src/main/res/drawable-mdpi/scroll_tip.png index 7023f7017..466eef136 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/scroll_tip.png and b/TMessagesProj/src/main/res/drawable-mdpi/scroll_tip.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/search_calendar.png b/TMessagesProj/src/main/res/drawable-mdpi/search_calendar.png deleted file mode 100755 index a6f7bb712..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/search_calendar.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/search_dark.9.png b/TMessagesProj/src/main/res/drawable-mdpi/search_dark.9.png index 19ca07db0..451ca7cd7 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/search_dark.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/search_dark.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/search_dark_activated.9.png b/TMessagesProj/src/main/res/drawable-mdpi/search_dark_activated.9.png index 3617983da..451ca7cd7 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/search_dark_activated.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/search_dark_activated.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/search_down.png b/TMessagesProj/src/main/res/drawable-mdpi/search_down.png deleted file mode 100755 index 7cabdcc9f..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/search_down.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/search_gif.png b/TMessagesProj/src/main/res/drawable-mdpi/search_gif.png index 5e8873fa7..818bd4090 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/search_gif.png and b/TMessagesProj/src/main/res/drawable-mdpi/search_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/search_up.png b/TMessagesProj/src/main/res/drawable-mdpi/search_up.png deleted file mode 100755 index 50353171f..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/search_up.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/search_web.png b/TMessagesProj/src/main/res/drawable-mdpi/search_web.png index bab8acf03..90466e70e 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/search_web.png and b/TMessagesProj/src/main/res/drawable-mdpi/search_web.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/selectphoto_large.png b/TMessagesProj/src/main/res/drawable-mdpi/selectphoto_large.png index 3e5eaf579..55c509b7f 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/selectphoto_large.png and b/TMessagesProj/src/main/res/drawable-mdpi/selectphoto_large.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/settings_arrow.png b/TMessagesProj/src/main/res/drawable-mdpi/settings_arrow.png new file mode 100644 index 000000000..8895766c2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/settings_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/settings_noresults.png b/TMessagesProj/src/main/res/drawable-mdpi/settings_noresults.png new file mode 100644 index 000000000..89fb45890 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/settings_noresults.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/shadowdown.png b/TMessagesProj/src/main/res/drawable-mdpi/shadowdown.png index f2be9d95b..442455b65 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/shadowdown.png and b/TMessagesProj/src/main/res/drawable-mdpi/shadowdown.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/share.png b/TMessagesProj/src/main/res/drawable-mdpi/share.png index 48a9439cb..849a026e0 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/share.png and b/TMessagesProj/src/main/res/drawable-mdpi/share.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/share_arrow.png b/TMessagesProj/src/main/res/drawable-mdpi/share_arrow.png index c49fb5699..19a23fb72 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/share_arrow.png and b/TMessagesProj/src/main/res/drawable-mdpi/share_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/share_round.png b/TMessagesProj/src/main/res/drawable-mdpi/share_round.png index abdb1a8b2..75b24ae74 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/share_round.png and b/TMessagesProj/src/main/res/drawable-mdpi/share_round.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/sheet_shadow.9.png b/TMessagesProj/src/main/res/drawable-mdpi/sheet_shadow.9.png index 58be559f8..e9dc2a77f 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/sheet_shadow.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/sheet_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/sheet_shadow_round.9.png b/TMessagesProj/src/main/res/drawable-mdpi/sheet_shadow_round.9.png new file mode 100644 index 000000000..fb54b66c6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/sheet_shadow_round.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/shortcut_compose.png b/TMessagesProj/src/main/res/drawable-mdpi/shortcut_compose.png index b9c413abe..f8d86fc0b 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/shortcut_compose.png and b/TMessagesProj/src/main/res/drawable-mdpi/shortcut_compose.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/shortcut_user.png b/TMessagesProj/src/main/res/drawable-mdpi/shortcut_user.png index b3c1325ff..59aa1c45b 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/shortcut_user.png and b/TMessagesProj/src/main/res/drawable-mdpi/shortcut_user.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/slide_dot_big.png b/TMessagesProj/src/main/res/drawable-mdpi/slide_dot_big.png index c9d55e980..e3a1041bf 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/slide_dot_big.png and b/TMessagesProj/src/main/res/drawable-mdpi/slide_dot_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/slide_dot_small.png b/TMessagesProj/src/main/res/drawable-mdpi/slide_dot_small.png index 975b49d87..862f0817a 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/slide_dot_small.png and b/TMessagesProj/src/main/res/drawable-mdpi/slide_dot_small.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/slidearrow.png b/TMessagesProj/src/main/res/drawable-mdpi/slidearrow.png index c796dddc4..56f626fa5 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/slidearrow.png and b/TMessagesProj/src/main/res/drawable-mdpi/slidearrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smallanimationpin.png b/TMessagesProj/src/main/res/drawable-mdpi/smallanimationpin.png index 129d223c7..7ad7ffc82 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/smallanimationpin.png and b/TMessagesProj/src/main/res/drawable-mdpi/smallanimationpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smallanimationpinleft.png b/TMessagesProj/src/main/res/drawable-mdpi/smallanimationpinleft.png index 2cf1904cb..51384d162 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/smallanimationpinleft.png and b/TMessagesProj/src/main/res/drawable-mdpi/smallanimationpinleft.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smallanimationpinright.png b/TMessagesProj/src/main/res/drawable-mdpi/smallanimationpinright.png index baf812b84..362ff18f3 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/smallanimationpinright.png and b/TMessagesProj/src/main/res/drawable-mdpi/smallanimationpinright.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_info.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_info.png new file mode 100644 index 000000000..e25475c3a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_info.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_inputsearch.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_inputsearch.png new file mode 100644 index 000000000..ca5e707b7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_inputsearch.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_activities.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_activities.png new file mode 100644 index 000000000..7172d8562 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_activities.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_cat.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_cat.png new file mode 100644 index 000000000..f762c168a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_cat.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_faves.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_faves.png new file mode 100644 index 000000000..fdd3ba797 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_faves.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_flags.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_flags.png new file mode 100644 index 000000000..688fdaea8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_flags.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_food.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_food.png new file mode 100644 index 000000000..86a8b10a5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_food.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_objects.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_objects.png new file mode 100644 index 000000000..c95949584 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_objects.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_other.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_other.png new file mode 100644 index 000000000..e8dd1e699 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_other.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_question.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_question.png new file mode 100644 index 000000000..863f04711 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_question.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_recent.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_recent.png new file mode 100644 index 000000000..5f7bd69b2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_recent.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_smiles.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_smiles.png new file mode 100644 index 000000000..395e33202 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_smiles.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_travel.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_travel.png new file mode 100644 index 000000000..115eab222 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_travel.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_trending.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_trending.png new file mode 100644 index 000000000..5aef34403 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_panel_trending.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_popup.9.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_popup.9.png index c3b212f57..60a7561f2 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/smiles_popup.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_popup.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_clear.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_clear.png new file mode 100644 index 000000000..d4368b294 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_gif.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_gif.png new file mode 100644 index 000000000..7da3698c9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_search.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_search.png new file mode 100644 index 000000000..5430eedc0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_settings.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_settings.png new file mode 100644 index 000000000..5e7278e84 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_smiles.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_smiles.png new file mode 100644 index 000000000..2101c5317 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_smiles.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_stickers.png b/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_stickers.png new file mode 100644 index 000000000..c16662c7d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/smiles_tab_stickers.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/sms_bubble.png b/TMessagesProj/src/main/res/drawable-mdpi/sms_bubble.png index cca1f3444..f49579e27 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/sms_bubble.png and b/TMessagesProj/src/main/res/drawable-mdpi/sms_bubble.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/sms_code.png b/TMessagesProj/src/main/res/drawable-mdpi/sms_code.png index 033ed3b42..ee166e80b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/sms_code.png and b/TMessagesProj/src/main/res/drawable-mdpi/sms_code.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/sms_devices.png b/TMessagesProj/src/main/res/drawable-mdpi/sms_devices.png index 4b1c6bd60..e67800bc6 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/sms_devices.png and b/TMessagesProj/src/main/res/drawable-mdpi/sms_devices.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/staredstickerstab.png b/TMessagesProj/src/main/res/drawable-mdpi/staredstickerstab.png deleted file mode 100644 index 1f7ea4c0a..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/staredstickerstab.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/sticker_added.png b/TMessagesProj/src/main/res/drawable-mdpi/sticker_added.png index 15d5a445f..90ba9bd6e 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/sticker_added.png and b/TMessagesProj/src/main/res/drawable-mdpi/sticker_added.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/sticker_search.png b/TMessagesProj/src/main/res/drawable-mdpi/sticker_search.png deleted file mode 100644 index 435121cb3..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/sticker_search.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_all.9.png b/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_all.9.png index b53869dc0..cd673e1c4 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_all.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_all.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_arrow.png b/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_arrow.png index 48e9e8122..b4a42446e 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_arrow.png and b/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_center.9.png b/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_center.9.png index a61ac56b2..4da94518c 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_center.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_center.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_left.9.png b/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_left.9.png index f92beb7b1..3977a29ff 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_left.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_left.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_right.9.png b/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_right.9.png index c16892ae9..c6e82de35 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_right.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/stickers_back_right.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/stickers_empty.png b/TMessagesProj/src/main/res/drawable-mdpi/stickers_empty.png new file mode 100644 index 000000000..514d1edd5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/stickers_empty.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/stickers_favorite.png b/TMessagesProj/src/main/res/drawable-mdpi/stickers_favorite.png deleted file mode 100644 index d34c70896..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/stickers_favorite.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/stickers_none.png b/TMessagesProj/src/main/res/drawable-mdpi/stickers_none.png deleted file mode 100644 index 12ac725d5..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/stickers_none.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/stickers_pack.png b/TMessagesProj/src/main/res/drawable-mdpi/stickers_pack.png deleted file mode 100644 index f1111970e..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/stickers_pack.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/stickers_send.png b/TMessagesProj/src/main/res/drawable-mdpi/stickers_send.png deleted file mode 100644 index 9aaa32cd2..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/stickers_send.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/stickers_unfavorite.png b/TMessagesProj/src/main/res/drawable-mdpi/stickers_unfavorite.png deleted file mode 100644 index d099b43c7..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/stickers_unfavorite.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/stickersclose.png b/TMessagesProj/src/main/res/drawable-mdpi/stickersclose.png index d231bbb94..c6ea80306 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/stickersclose.png and b/TMessagesProj/src/main/res/drawable-mdpi/stickersclose.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/stickerset_close.png b/TMessagesProj/src/main/res/drawable-mdpi/stickerset_close.png index 9b6095fa0..6bf238da0 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/stickerset_close.png and b/TMessagesProj/src/main/res/drawable-mdpi/stickerset_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/switch_to_on1.9.png b/TMessagesProj/src/main/res/drawable-mdpi/switch_to_on1.9.png index 9e8d3f45d..6cff6912f 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/switch_to_on1.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/switch_to_on1.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/switch_to_on2.9.png b/TMessagesProj/src/main/res/drawable-mdpi/switch_to_on2.9.png index 9e8d3f45d..6cff6912f 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/switch_to_on2.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/switch_to_on2.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/switch_track.9.png b/TMessagesProj/src/main/res/drawable-mdpi/switch_track.9.png index f8677ab8f..4d0cf5cae 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/switch_track.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/switch_track.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/system.9.png b/TMessagesProj/src/main/res/drawable-mdpi/system.9.png index 5ffd21af6..28c6ee54b 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/system.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/system.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/system_loader.png b/TMessagesProj/src/main/res/drawable-mdpi/system_loader.png index 79c6aab98..c02f0fcc0 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/system_loader.png and b/TMessagesProj/src/main/res/drawable-mdpi/system_loader.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/theme_picker.png b/TMessagesProj/src/main/res/drawable-mdpi/theme_picker.png index e7573e4a7..e7d7f35a0 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/theme_picker.png and b/TMessagesProj/src/main/res/drawable-mdpi/theme_picker.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/tip1.png b/TMessagesProj/src/main/res/drawable-mdpi/tip1.png index af62d2e32..0157499f7 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/tip1.png and b/TMessagesProj/src/main/res/drawable-mdpi/tip1.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/tip2.png b/TMessagesProj/src/main/res/drawable-mdpi/tip2.png index 09ccb58bd..7a3744169 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/tip2.png and b/TMessagesProj/src/main/res/drawable-mdpi/tip2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/tip3.png b/TMessagesProj/src/main/res/drawable-mdpi/tip3.png index db501192a..c72356f8e 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/tip3.png and b/TMessagesProj/src/main/res/drawable-mdpi/tip3.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/tip4.png b/TMessagesProj/src/main/res/drawable-mdpi/tip4.png index a73985ca7..7326ad3f6 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/tip4.png and b/TMessagesProj/src/main/res/drawable-mdpi/tip4.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/tool_blur.png b/TMessagesProj/src/main/res/drawable-mdpi/tool_blur.png index 7b488f92f..1d46aed8a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/tool_blur.png and b/TMessagesProj/src/main/res/drawable-mdpi/tool_blur.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/tool_cropfix.png b/TMessagesProj/src/main/res/drawable-mdpi/tool_cropfix.png index defd1458d..5753b63d2 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/tool_cropfix.png and b/TMessagesProj/src/main/res/drawable-mdpi/tool_cropfix.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/tool_curve.png b/TMessagesProj/src/main/res/drawable-mdpi/tool_curve.png index 833c4b666..da5358614 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/tool_curve.png and b/TMessagesProj/src/main/res/drawable-mdpi/tool_curve.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/tool_rotate.png b/TMessagesProj/src/main/res/drawable-mdpi/tool_rotate.png index cef52efb8..56e6202e3 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/tool_rotate.png and b/TMessagesProj/src/main/res/drawable-mdpi/tool_rotate.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/tooltip_arrow.png b/TMessagesProj/src/main/res/drawable-mdpi/tooltip_arrow.png index 9fe5b5b5c..8d38aac77 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/tooltip_arrow.png and b/TMessagesProj/src/main/res/drawable-mdpi/tooltip_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/tooltip_arrow_up.png b/TMessagesProj/src/main/res/drawable-mdpi/tooltip_arrow_up.png new file mode 100644 index 000000000..3cce31153 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/tooltip_arrow_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/tooltip_sound.png b/TMessagesProj/src/main/res/drawable-mdpi/tooltip_sound.png index fedce0179..2dda48f92 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/tooltip_sound.png and b/TMessagesProj/src/main/res/drawable-mdpi/tooltip_sound.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/update.png b/TMessagesProj/src/main/res/drawable-mdpi/update.png index 3d093331c..ba021292b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/update.png and b/TMessagesProj/src/main/res/drawable-mdpi/update.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/usersearch.png b/TMessagesProj/src/main/res/drawable-mdpi/usersearch.png deleted file mode 100644 index 67cd30bd6..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/usersearch.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/verified_area.png b/TMessagesProj/src/main/res/drawable-mdpi/verified_area.png old mode 100755 new mode 100644 index e6e1c192f..7d2fec045 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/verified_area.png and b/TMessagesProj/src/main/res/drawable-mdpi/verified_area.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/verified_check.png b/TMessagesProj/src/main/res/drawable-mdpi/verified_check.png old mode 100755 new mode 100644 index 5339caa1b..4cdbb8c08 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/verified_check.png and b/TMessagesProj/src/main/res/drawable-mdpi/verified_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/video_1080.png b/TMessagesProj/src/main/res/drawable-mdpi/video_1080.png index d82cbfecb..895d00af2 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/video_1080.png and b/TMessagesProj/src/main/res/drawable-mdpi/video_1080.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/video_240.png b/TMessagesProj/src/main/res/drawable-mdpi/video_240.png index 8c144c0e3..e86ede044 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/video_240.png and b/TMessagesProj/src/main/res/drawable-mdpi/video_240.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/video_360.png b/TMessagesProj/src/main/res/drawable-mdpi/video_360.png index 8bae8b4cc..d016666c7 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/video_360.png and b/TMessagesProj/src/main/res/drawable-mdpi/video_360.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/video_480.png b/TMessagesProj/src/main/res/drawable-mdpi/video_480.png index 8dd87fbda..b81914705 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/video_480.png and b/TMessagesProj/src/main/res/drawable-mdpi/video_480.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/video_720.png b/TMessagesProj/src/main/res/drawable-mdpi/video_720.png index 1204f56c0..3fba2f8b3 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/video_720.png and b/TMessagesProj/src/main/res/drawable-mdpi/video_720.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/video_actions.png b/TMessagesProj/src/main/res/drawable-mdpi/video_actions.png index 84aee2f58..8dc45437b 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/video_actions.png and b/TMessagesProj/src/main/res/drawable-mdpi/video_actions.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/video_copy.png b/TMessagesProj/src/main/res/drawable-mdpi/video_copy.png index de6bb176b..030f87842 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/video_copy.png and b/TMessagesProj/src/main/res/drawable-mdpi/video_copy.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/video_cropleft.png b/TMessagesProj/src/main/res/drawable-mdpi/video_cropleft.png index 998abb9f2..4e39dc488 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/video_cropleft.png and b/TMessagesProj/src/main/res/drawable-mdpi/video_cropleft.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/video_cropright.png b/TMessagesProj/src/main/res/drawable-mdpi/video_cropright.png index 6fe7617ac..7d5ae66cf 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/video_cropright.png and b/TMessagesProj/src/main/res/drawable-mdpi/video_cropright.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/video_mini_arrow.png b/TMessagesProj/src/main/res/drawable-mdpi/video_mini_arrow.png index 7a21ce97e..b4e6a592a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/video_mini_arrow.png and b/TMessagesProj/src/main/res/drawable-mdpi/video_mini_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/video_mini_cancel.png b/TMessagesProj/src/main/res/drawable-mdpi/video_mini_cancel.png index 9a533b6b8..cc10f2992 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/video_mini_cancel.png and b/TMessagesProj/src/main/res/drawable-mdpi/video_mini_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/video_mute.png b/TMessagesProj/src/main/res/drawable-mdpi/video_mute.png index 8c98ae8ac..11752aa5e 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/video_mute.png and b/TMessagesProj/src/main/res/drawable-mdpi/video_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/video_muted.png b/TMessagesProj/src/main/res/drawable-mdpi/video_muted.png index 6db8f9a12..f22d3fea1 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/video_muted.png and b/TMessagesProj/src/main/res/drawable-mdpi/video_muted.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/video_pip.png b/TMessagesProj/src/main/res/drawable-mdpi/video_pip.png index 83fc887a8..b42bf414b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/video_pip.png and b/TMessagesProj/src/main/res/drawable-mdpi/video_pip.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/voice2x.png b/TMessagesProj/src/main/res/drawable-mdpi/voice2x.png index 69b5e49bc..c29b22b49 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/voice2x.png and b/TMessagesProj/src/main/res/drawable-mdpi/voice2x.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/volume_off.png b/TMessagesProj/src/main/res/drawable-mdpi/volume_off.png index f37883f34..877111cdc 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/volume_off.png and b/TMessagesProj/src/main/res/drawable-mdpi/volume_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/volume_on.png b/TMessagesProj/src/main/res/drawable-mdpi/volume_on.png index 0fa849130..341622b1a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/volume_on.png and b/TMessagesProj/src/main/res/drawable-mdpi/volume_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/wall_selection.9.png b/TMessagesProj/src/main/res/drawable-mdpi/wall_selection.9.png index eee84d772..f296d0e9f 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/wall_selection.9.png and b/TMessagesProj/src/main/res/drawable-mdpi/wall_selection.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ab_progress.png b/TMessagesProj/src/main/res/drawable-xhdpi/ab_progress.png index 452f2a852..914eb9484 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ab_progress.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ab_progress.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/abc_ic_menu_share_mtrl_alpha.png b/TMessagesProj/src/main/res/drawable-xhdpi/abc_ic_menu_share_mtrl_alpha.png index b57ee1935..5ffe8a6b8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/abc_ic_menu_share_mtrl_alpha.png and b/TMessagesProj/src/main/res/drawable-xhdpi/abc_ic_menu_share_mtrl_alpha.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/account_add.png b/TMessagesProj/src/main/res/drawable-xhdpi/account_add.png index 6be1f9cb0..3fb36136d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/account_add.png and b/TMessagesProj/src/main/res/drawable-xhdpi/account_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/account_check.png b/TMessagesProj/src/main/res/drawable-xhdpi/account_check.png index 639ba24b3..4d07169d7 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/account_check.png and b/TMessagesProj/src/main/res/drawable-xhdpi/account_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/actions_addadmin.png b/TMessagesProj/src/main/res/drawable-xhdpi/actions_addadmin.png index 32f8f59f1..5ae3cbd63 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/actions_addadmin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/actions_addadmin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/actions_addmember2.png b/TMessagesProj/src/main/res/drawable-xhdpi/actions_addmember2.png index 11ea222f0..26007f9e7 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/actions_addmember2.png and b/TMessagesProj/src/main/res/drawable-xhdpi/actions_addmember2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/actions_permissions.png b/TMessagesProj/src/main/res/drawable-xhdpi/actions_permissions.png index bd325aab1..e7be31f77 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/actions_permissions.png and b/TMessagesProj/src/main/res/drawable-xhdpi/actions_permissions.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/actions_remove_user.png b/TMessagesProj/src/main/res/drawable-xhdpi/actions_remove_user.png index c209e2b1a..6b7757907 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/actions_remove_user.png and b/TMessagesProj/src/main/res/drawable-xhdpi/actions_remove_user.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/actions_removed.png b/TMessagesProj/src/main/res/drawable-xhdpi/actions_removed.png index 78cb09b64..f2c2b5cb6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/actions_removed.png and b/TMessagesProj/src/main/res/drawable-xhdpi/actions_removed.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/actions_setphoto.png b/TMessagesProj/src/main/res/drawable-xhdpi/actions_setphoto.png index 3e6d286bf..9afae6c43 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/actions_setphoto.png and b/TMessagesProj/src/main/res/drawable-xhdpi/actions_setphoto.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/actions_viewmembers.png b/TMessagesProj/src/main/res/drawable-xhdpi/actions_viewmembers.png index 894f53512..ee380e8cc 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/actions_viewmembers.png and b/TMessagesProj/src/main/res/drawable-xhdpi/actions_viewmembers.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/add.png b/TMessagesProj/src/main/res/drawable-xhdpi/add.png index cbfdc7eb3..587864209 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/add.png and b/TMessagesProj/src/main/res/drawable-xhdpi/add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/add_admin.png b/TMessagesProj/src/main/res/drawable-xhdpi/add_admin.png index 9516668a4..f6b09bcec 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/add_admin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/add_admin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/add_contact_new.png b/TMessagesProj/src/main/res/drawable-xhdpi/add_contact_new.png index 762b9dc52..1a4b3894e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/add_contact_new.png and b/TMessagesProj/src/main/res/drawable-xhdpi/add_contact_new.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/animationpin.png b/TMessagesProj/src/main/res/drawable-xhdpi/animationpin.png index d14749d00..ebcc0e6fa 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/animationpin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/animationpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/animationpinleft.png b/TMessagesProj/src/main/res/drawable-xhdpi/animationpinleft.png index 9d13a3aea..3b5a48156 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/animationpinleft.png and b/TMessagesProj/src/main/res/drawable-xhdpi/animationpinleft.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/animationpinright.png b/TMessagesProj/src/main/res/drawable-xhdpi/animationpinright.png index babf08563..f1596dc2e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/animationpinright.png and b/TMessagesProj/src/main/res/drawable-xhdpi/animationpinright.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_audio.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_audio.png index f44cead34..d35451fc0 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/attach_audio.png and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_audio.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_close.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_close.png index 7ad4e9135..345cbcda2 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/attach_close.png and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_contact.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_contact.png index 507063d51..9461209f2 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/attach_contact.png and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_contact.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_file.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_file.png index 19490d9f5..beb8720c6 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/attach_file.png and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_file.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_gallery.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_gallery.png index 5eeae8954..d6a726246 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/attach_gallery.png and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_gallery.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_location.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_location.png index eb7b4b791..6736d0457 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/attach_location.png and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_polls.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_polls.png index c5b24ff9c..fb4c09ddd 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/attach_polls.png and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_polls.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_send.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_send.png old mode 100755 new mode 100644 index a4b04655b..73dc86a84 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/attach_send.png and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_send.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_video.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_video.png index 49a50e2d7..7054ded2b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/attach_video.png and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/audio_mini_arrow.png b/TMessagesProj/src/main/res/drawable-xhdpi/audio_mini_arrow.png index 3dff851e1..ee20b011b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/audio_mini_arrow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/audio_mini_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/audio_mini_cancel.png b/TMessagesProj/src/main/res/drawable-xhdpi/audio_mini_cancel.png index 2803b1089..aa2098cf7 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/audio_mini_cancel.png and b/TMessagesProj/src/main/res/drawable-xhdpi/audio_mini_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/audiosend_pause.png b/TMessagesProj/src/main/res/drawable-xhdpi/audiosend_pause.png index db13c0430..9eba3045b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/audiosend_pause.png and b/TMessagesProj/src/main/res/drawable-xhdpi/audiosend_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/audiosend_play.png b/TMessagesProj/src/main/res/drawable-xhdpi/audiosend_play.png index b4764fc7f..af77c3203 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/audiosend_play.png and b/TMessagesProj/src/main/res/drawable-xhdpi/audiosend_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/authorize.png b/TMessagesProj/src/main/res/drawable-xhdpi/authorize.png index 8ff8278e9..6a115e867 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/authorize.png and b/TMessagesProj/src/main/res/drawable-xhdpi/authorize.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/background_hd.jpg b/TMessagesProj/src/main/res/drawable-xhdpi/background_hd.jpg old mode 100755 new mode 100644 index a6e95cd79..66c14324f Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/background_hd.jpg and b/TMessagesProj/src/main/res/drawable-xhdpi/background_hd.jpg differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/background_selected.png b/TMessagesProj/src/main/res/drawable-xhdpi/background_selected.png index b8aa315c9..b99b50758 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/background_selected.png and b/TMessagesProj/src/main/res/drawable-xhdpi/background_selected.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/bigcheck.png b/TMessagesProj/src/main/res/drawable-xhdpi/bigcheck.png index b400932e4..e1bbb705e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/bigcheck.png and b/TMessagesProj/src/main/res/drawable-xhdpi/bigcheck.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/blockpanel.png b/TMessagesProj/src/main/res/drawable-xhdpi/blockpanel.png index 0e3bb913d..1df8b1eae 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/blockpanel.png and b/TMessagesProj/src/main/res/drawable-xhdpi/blockpanel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/bluecounter.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/bluecounter.9.png index 2087fd181..99452b42e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/bluecounter.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/bluecounter.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/blur_linear.png b/TMessagesProj/src/main/res/drawable-xhdpi/blur_linear.png index 3794193ee..1be0ee505 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/blur_linear.png and b/TMessagesProj/src/main/res/drawable-xhdpi/blur_linear.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/blur_off.png b/TMessagesProj/src/main/res/drawable-xhdpi/blur_off.png index 0b4205973..3ba854671 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/blur_off.png and b/TMessagesProj/src/main/res/drawable-xhdpi/blur_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/blur_radial.png b/TMessagesProj/src/main/res/drawable-xhdpi/blur_radial.png index 907d8a6fa..748dc4535 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/blur_radial.png and b/TMessagesProj/src/main/res/drawable-xhdpi/blur_radial.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/book_bot.png b/TMessagesProj/src/main/res/drawable-xhdpi/book_bot.png index 7a71567fb..a204f7be4 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/book_bot.png and b/TMessagesProj/src/main/res/drawable-xhdpi/book_bot.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/book_channel.png b/TMessagesProj/src/main/res/drawable-xhdpi/book_channel.png index 73f7e8910..23564ce99 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/book_channel.png and b/TMessagesProj/src/main/res/drawable-xhdpi/book_channel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/book_group.png b/TMessagesProj/src/main/res/drawable-xhdpi/book_group.png index 99ca2dc8e..563c68877 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/book_group.png and b/TMessagesProj/src/main/res/drawable-xhdpi/book_group.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/book_logo.png b/TMessagesProj/src/main/res/drawable-xhdpi/book_logo.png index 3524d3067..36357a9dd 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/book_logo.png and b/TMessagesProj/src/main/res/drawable-xhdpi/book_logo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/book_user.png b/TMessagesProj/src/main/res/drawable-xhdpi/book_user.png index 64df4bf31..22975744d 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/book_user.png and b/TMessagesProj/src/main/res/drawable-xhdpi/book_user.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/bookmark_large.png b/TMessagesProj/src/main/res/drawable-xhdpi/bookmark_large.png deleted file mode 100755 index bd5af322f..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/bookmark_large.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/bot_file.png b/TMessagesProj/src/main/res/drawable-xhdpi/bot_file.png index 35879ffb7..9bc629bb9 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/bot_file.png and b/TMessagesProj/src/main/res/drawable-xhdpi/bot_file.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/bot_keyboard.png b/TMessagesProj/src/main/res/drawable-xhdpi/bot_keyboard.png deleted file mode 100755 index 5a46d4ce8..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/bot_keyboard.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/bot_keyboard2.png b/TMessagesProj/src/main/res/drawable-xhdpi/bot_keyboard2.png deleted file mode 100755 index 850395293..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/bot_keyboard2.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/bot_lines.png b/TMessagesProj/src/main/res/drawable-xhdpi/bot_lines.png index 11980a894..d3f815f39 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/bot_lines.png and b/TMessagesProj/src/main/res/drawable-xhdpi/bot_lines.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/bot_link.png b/TMessagesProj/src/main/res/drawable-xhdpi/bot_link.png index 024405b37..d2661da8f 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/bot_link.png and b/TMessagesProj/src/main/res/drawable-xhdpi/bot_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/bot_location.png b/TMessagesProj/src/main/res/drawable-xhdpi/bot_location.png index 984b1c749..a24ff3c68 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/bot_location.png and b/TMessagesProj/src/main/res/drawable-xhdpi/bot_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/bot_music.png b/TMessagesProj/src/main/res/drawable-xhdpi/bot_music.png index 262bb1975..7d855d279 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/bot_music.png and b/TMessagesProj/src/main/res/drawable-xhdpi/bot_music.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/bottom_shadow.png b/TMessagesProj/src/main/res/drawable-xhdpi/bottom_shadow.png index 9e1a2a274..3c93e9e88 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/bottom_shadow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/bottom_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/boxshadow.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/boxshadow.9.png index 6d5cbad08..9b2d1b956 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/boxshadow.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/boxshadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/broadcast3.png b/TMessagesProj/src/main/res/drawable-xhdpi/broadcast3.png index ddfd4b155..fcd80bf2f 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/broadcast3.png and b/TMessagesProj/src/main/res/drawable-xhdpi/broadcast3.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/broadcast_w.png b/TMessagesProj/src/main/res/drawable-xhdpi/broadcast_w.png index ea1da2f3e..6ed162199 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/broadcast_w.png and b/TMessagesProj/src/main/res/drawable-xhdpi/broadcast_w.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/btnshadow.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/btnshadow.9.png index e3d0d98f3..c222571f7 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/btnshadow.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/btnshadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/burn.png b/TMessagesProj/src/main/res/drawable-xhdpi/burn.png index 30629464b..f69a5d838 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/burn.png and b/TMessagesProj/src/main/res/drawable-xhdpi/burn.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/camera_btn.png b/TMessagesProj/src/main/res/drawable-xhdpi/camera_btn.png index cbe2ba251..fc890d443 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/camera_btn.png and b/TMessagesProj/src/main/res/drawable-xhdpi/camera_btn.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/camera_revert1.png b/TMessagesProj/src/main/res/drawable-xhdpi/camera_revert1.png index 905875b62..2036b95cb 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/camera_revert1.png and b/TMessagesProj/src/main/res/drawable-xhdpi/camera_revert1.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/camera_revert2.png b/TMessagesProj/src/main/res/drawable-xhdpi/camera_revert2.png index 0a9ffb8fd..19a55bb56 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/camera_revert2.png and b/TMessagesProj/src/main/res/drawable-xhdpi/camera_revert2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/cancel_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/cancel_big.png index 843ef5eb6..24e094773 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/cancel_big.png and b/TMessagesProj/src/main/res/drawable-xhdpi/cancel_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/channelintro.png b/TMessagesProj/src/main/res/drawable-xhdpi/channelintro.png index 0d6febb75..fb7b8df77 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/channelintro.png and b/TMessagesProj/src/main/res/drawable-xhdpi/channelintro.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive.png b/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive.png new file mode 100644 index 000000000..347f18ffc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_arrow.png b/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_arrow.png new file mode 100644 index 000000000..34b11daa7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_box.png b/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_box.png new file mode 100644 index 000000000..e224b4f08 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_box.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_hide.png b/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_hide.png new file mode 100644 index 000000000..4dc5179b0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_hide.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_muted.png b/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_muted.png new file mode 100644 index 000000000..272d3f296 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_muted.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 new file mode 100644 index 000000000..e564fc17d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_show.png b/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_show.png new file mode 100644 index 000000000..3bd0b727f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/chats_archive_show.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/chats_clear.png b/TMessagesProj/src/main/res/drawable-xhdpi/chats_clear.png deleted file mode 100644 index cae17f93e..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/chats_clear.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/chats_delete.png b/TMessagesProj/src/main/res/drawable-xhdpi/chats_delete.png index 7bd7c781f..d3d79e43e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/chats_delete.png and b/TMessagesProj/src/main/res/drawable-xhdpi/chats_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/chats_leave.png b/TMessagesProj/src/main/res/drawable-xhdpi/chats_leave.png index bb17834ac..aabe75e5f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/chats_leave.png and b/TMessagesProj/src/main/res/drawable-xhdpi/chats_leave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/chats_pin.png b/TMessagesProj/src/main/res/drawable-xhdpi/chats_pin.png index 1db793d0f..442cd410c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/chats_pin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/chats_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/chats_saved.png b/TMessagesProj/src/main/res/drawable-xhdpi/chats_saved.png new file mode 100644 index 000000000..4e40842b8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/chats_saved.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/chats_unarchive.png b/TMessagesProj/src/main/res/drawable-xhdpi/chats_unarchive.png new file mode 100644 index 000000000..971694cc9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/chats_unarchive.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/chats_undo.png b/TMessagesProj/src/main/res/drawable-xhdpi/chats_undo.png index 5a0d53b79..9971b4e19 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/chats_undo.png and b/TMessagesProj/src/main/res/drawable-xhdpi/chats_undo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/chats_unpin.png b/TMessagesProj/src/main/res/drawable-xhdpi/chats_unpin.png index f355f94aa..cec51347e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/chats_unpin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/chats_unpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/checkbig.png b/TMessagesProj/src/main/res/drawable-xhdpi/checkbig.png index 959e46a2a..e989b4499 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/checkbig.png and b/TMessagesProj/src/main/res/drawable-xhdpi/checkbig.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/circle.png b/TMessagesProj/src/main/res/drawable-xhdpi/circle.png index 6d582799c..efac085f9 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/circle.png and b/TMessagesProj/src/main/res/drawable-xhdpi/circle.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/circle_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/circle_big.png index a661d8bae..fe63e6ef4 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/circle_big.png and b/TMessagesProj/src/main/res/drawable-xhdpi/circle_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/cloud_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/cloud_big.png index d998d1f7e..62210373e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/cloud_big.png and b/TMessagesProj/src/main/res/drawable-xhdpi/cloud_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/collapse_down.png b/TMessagesProj/src/main/res/drawable-xhdpi/collapse_down.png index b74722e61..b85b76adb 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/collapse_down.png and b/TMessagesProj/src/main/res/drawable-xhdpi/collapse_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/collapse_up.png b/TMessagesProj/src/main/res/drawable-xhdpi/collapse_up.png index 551f31be3..a36e16f2d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/collapse_up.png and b/TMessagesProj/src/main/res/drawable-xhdpi/collapse_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/compose_panel_shadow.png b/TMessagesProj/src/main/res/drawable-xhdpi/compose_panel_shadow.png index ea53d2d4d..a4133d2b7 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/compose_panel_shadow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/compose_panel_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/contacts_sort_name.png b/TMessagesProj/src/main/res/drawable-xhdpi/contacts_sort_name.png index b8eabca32..11250e2a4 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/contacts_sort_name.png and b/TMessagesProj/src/main/res/drawable-xhdpi/contacts_sort_name.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/contacts_sort_time.png b/TMessagesProj/src/main/res/drawable-xhdpi/contacts_sort_time.png index 54a158219..eeefca9f4 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/contacts_sort_time.png and b/TMessagesProj/src/main/res/drawable-xhdpi/contacts_sort_time.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/corner_in_bl.png b/TMessagesProj/src/main/res/drawable-xhdpi/corner_in_bl.png index 1bc2555ce..d43d37e08 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/corner_in_bl.png and b/TMessagesProj/src/main/res/drawable-xhdpi/corner_in_bl.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/corner_in_br.png b/TMessagesProj/src/main/res/drawable-xhdpi/corner_in_br.png index 7947baf0d..1820d84b4 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/corner_in_br.png and b/TMessagesProj/src/main/res/drawable-xhdpi/corner_in_br.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/corner_in_tl.png b/TMessagesProj/src/main/res/drawable-xhdpi/corner_in_tl.png index d3af56ed6..f5434afe5 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/corner_in_tl.png and b/TMessagesProj/src/main/res/drawable-xhdpi/corner_in_tl.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/corner_in_tr.png b/TMessagesProj/src/main/res/drawable-xhdpi/corner_in_tr.png index 8c7ab4dbb..dfd156b2a 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/corner_in_tr.png and b/TMessagesProj/src/main/res/drawable-xhdpi/corner_in_tr.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/corner_out_bl.png b/TMessagesProj/src/main/res/drawable-xhdpi/corner_out_bl.png index 3edd6cd92..d839cf8c8 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/corner_out_bl.png and b/TMessagesProj/src/main/res/drawable-xhdpi/corner_out_bl.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/corner_out_br.png b/TMessagesProj/src/main/res/drawable-xhdpi/corner_out_br.png index 6b94a5bcc..ccc4b29db 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/corner_out_br.png and b/TMessagesProj/src/main/res/drawable-xhdpi/corner_out_br.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/corner_out_tl.png b/TMessagesProj/src/main/res/drawable-xhdpi/corner_out_tl.png index bb9521b66..46e5690c0 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/corner_out_tl.png and b/TMessagesProj/src/main/res/drawable-xhdpi/corner_out_tl.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/corner_out_tr.png b/TMessagesProj/src/main/res/drawable-xhdpi/corner_out_tr.png index 02daa0290..1eb986546 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/corner_out_tr.png and b/TMessagesProj/src/main/res/drawable-xhdpi/corner_out_tr.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/delete.png b/TMessagesProj/src/main/res/drawable-xhdpi/delete.png index ff7e84c40..03bc6ca1b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/delete.png and b/TMessagesProj/src/main/res/drawable-xhdpi/delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/devices.png b/TMessagesProj/src/main/res/drawable-xhdpi/devices.png index c2a90afc6..033d60650 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/devices.png and b/TMessagesProj/src/main/res/drawable-xhdpi/devices.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/doc_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/doc_big.png index c25d6a02b..623467ff0 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/doc_big.png and b/TMessagesProj/src/main/res/drawable-xhdpi/doc_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/edit_cancel.png b/TMessagesProj/src/main/res/drawable-xhdpi/edit_cancel.png index bfea63bc6..8388a7109 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/edit_cancel.png and b/TMessagesProj/src/main/res/drawable-xhdpi/edit_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/edit_done.png b/TMessagesProj/src/main/res/drawable-xhdpi/edit_done.png deleted file mode 100755 index 0041ebb99..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/edit_done.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/fast_reply.png b/TMessagesProj/src/main/res/drawable-xhdpi/fast_reply.png index fc69e7c29..6ef121881 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/fast_reply.png and b/TMessagesProj/src/main/res/drawable-xhdpi/fast_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/flame_small.png b/TMessagesProj/src/main/res/drawable-xhdpi/flame_small.png index 12f787053..a22b89684 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/flame_small.png and b/TMessagesProj/src/main/res/drawable-xhdpi/flame_small.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/flash_auto.png b/TMessagesProj/src/main/res/drawable-xhdpi/flash_auto.png index 37dbc2168..3095c2a91 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/flash_auto.png and b/TMessagesProj/src/main/res/drawable-xhdpi/flash_auto.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/flash_off.png b/TMessagesProj/src/main/res/drawable-xhdpi/flash_off.png index 749cb5d2a..250a2631e 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/flash_off.png and b/TMessagesProj/src/main/res/drawable-xhdpi/flash_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/flash_on.png b/TMessagesProj/src/main/res/drawable-xhdpi/flash_on.png index 454e404ca..93129c8f1 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/flash_on.png and b/TMessagesProj/src/main/res/drawable-xhdpi/flash_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/floating_camera.png b/TMessagesProj/src/main/res/drawable-xhdpi/floating_camera.png index 253e7503d..0e9039dc0 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/floating_camera.png and b/TMessagesProj/src/main/res/drawable-xhdpi/floating_camera.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/floating_message.png b/TMessagesProj/src/main/res/drawable-xhdpi/floating_message.png index 4aefc95d7..b6b6cb5e6 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/floating_message.png and b/TMessagesProj/src/main/res/drawable-xhdpi/floating_message.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/floating_pencil.png b/TMessagesProj/src/main/res/drawable-xhdpi/floating_pencil.png index adf178ac1..91a9e8347 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/floating_pencil.png and b/TMessagesProj/src/main/res/drawable-xhdpi/floating_pencil.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/floating_shadow.png b/TMessagesProj/src/main/res/drawable-xhdpi/floating_shadow.png index 5f9ceafc9..02befbe68 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/floating_shadow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/floating_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/floating_shadow_profile.png b/TMessagesProj/src/main/res/drawable-xhdpi/floating_shadow_profile.png index f5d5c8994..a60788ce9 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/floating_shadow_profile.png and b/TMessagesProj/src/main/res/drawable-xhdpi/floating_shadow_profile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/forwardvideo.png b/TMessagesProj/src/main/res/drawable-xhdpi/forwardvideo.png index 3067e3a7f..a0a6f3bc8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/forwardvideo.png and b/TMessagesProj/src/main/res/drawable-xhdpi/forwardvideo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/foursquare.png b/TMessagesProj/src/main/res/drawable-xhdpi/foursquare.png index a59c7757e..d8c5479a9 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/foursquare.png and b/TMessagesProj/src/main/res/drawable-xhdpi/foursquare.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/gif_empty.png b/TMessagesProj/src/main/res/drawable-xhdpi/gif_empty.png new file mode 100644 index 000000000..00dcda935 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/gif_empty.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/go_to_message.png b/TMessagesProj/src/main/res/drawable-xhdpi/go_to_message.png deleted file mode 100644 index 372e1918d..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/go_to_message.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/greydivider.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/greydivider.9.png index e438cbaf5..45b903661 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/greydivider.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/greydivider.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/greydivider_bottom.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/greydivider_bottom.9.png index bc6032165..7595686b6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/greydivider_bottom.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/greydivider_bottom.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/greydivider_top.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/greydivider_top.9.png index e31198a3b..7eef1cbc8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/greydivider_top.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/greydivider_top.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/group_addmember.png b/TMessagesProj/src/main/res/drawable-xhdpi/group_addmember.png index 52c1a32d4..eb7641847 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/group_addmember.png and b/TMessagesProj/src/main/res/drawable-xhdpi/group_addmember.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/group_admin.png b/TMessagesProj/src/main/res/drawable-xhdpi/group_admin.png index dd80eac2c..1b25c821b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/group_admin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/group_admin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/group_admin_new.png b/TMessagesProj/src/main/res/drawable-xhdpi/group_admin_new.png index cf95adcf4..2c5bdb292 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/group_admin_new.png and b/TMessagesProj/src/main/res/drawable-xhdpi/group_admin_new.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/group_ban_empty.png b/TMessagesProj/src/main/res/drawable-xhdpi/group_ban_empty.png index 8fb16b308..5a57da26b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/group_ban_empty.png and b/TMessagesProj/src/main/res/drawable-xhdpi/group_ban_empty.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/group_ban_new.png b/TMessagesProj/src/main/res/drawable-xhdpi/group_ban_new.png index 00fc6ec4a..e1d028897 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/group_ban_new.png and b/TMessagesProj/src/main/res/drawable-xhdpi/group_ban_new.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/group_banned.png b/TMessagesProj/src/main/res/drawable-xhdpi/group_banned.png index ff4ea8d5e..86b902e11 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/group_banned.png and b/TMessagesProj/src/main/res/drawable-xhdpi/group_banned.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/group_edit.png b/TMessagesProj/src/main/res/drawable-xhdpi/group_edit.png index dde469b24..876a61cd4 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/group_edit.png and b/TMessagesProj/src/main/res/drawable-xhdpi/group_edit.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/group_edit_profile.png b/TMessagesProj/src/main/res/drawable-xhdpi/group_edit_profile.png index 80828cf33..de12f915e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/group_edit_profile.png and b/TMessagesProj/src/main/res/drawable-xhdpi/group_edit_profile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/group_log.png b/TMessagesProj/src/main/res/drawable-xhdpi/group_log.png index 8ad3c0d17..fe748d1f5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/group_log.png and b/TMessagesProj/src/main/res/drawable-xhdpi/group_log.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/groups_overview_check.png b/TMessagesProj/src/main/res/drawable-xhdpi/groups_overview_check.png index c2969b218..3cae657f6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/groups_overview_check.png and b/TMessagesProj/src/main/res/drawable-xhdpi/groups_overview_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/header_shadow.png b/TMessagesProj/src/main/res/drawable-xhdpi/header_shadow.png index 5492342b5..e5a529969 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/header_shadow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/header_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/header_shadow_reverse.png b/TMessagesProj/src/main/res/drawable-xhdpi/header_shadow_reverse.png index b8ab34806..847c63757 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/header_shadow_reverse.png and b/TMessagesProj/src/main/res/drawable-xhdpi/header_shadow_reverse.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_attach.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_attach.png deleted file mode 100755 index ed39a9bab..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_attach.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_back.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_back.png index addbfc886..c8d4f06c4 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_back.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_back.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_copy.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_copy.png index 5bb7599e5..ae31674c6 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_copy.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_copy.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_delete.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_delete.png index 4696f9644..b3aa07e66 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_delete.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_done.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_done.png index d949f3a4b..ae90ffdad 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_done.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_done.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_fave.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_fave.png index 2ee3d2d06..a43385ee7 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_fave.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_fave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_forward.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_forward.png index d9e605ab5..cd1af759a 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_forward.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_new.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_new.png index efb7d8949..e905189fc 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_new.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_new.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_other.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_other.png index 1b04eda04..6baec5634 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_other.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_other.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_reply.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_reply.png index 258cd5a28..45427e193 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_reply.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_reply2.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_reply2.png index 2bfa2a5d2..92cd0c782 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_reply2.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_reply2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_search.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_search.png index 043759acd..776e2b928 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_search.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_unfave.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_unfave.png index 73da70d23..f3649d4e6 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_unfave.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_unfave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_again.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_again.png index 1c6918377..1ff614ccb 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_again.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_again.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_againinline.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_againinline.png index cda2c5e4b..8660cc2bf 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_againinline.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_againinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_arrow_drop_down.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_arrow_drop_down.png index 0dcf82c93..be37cf66f 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_arrow_drop_down.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_arrow_drop_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_call.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_call.png new file mode 100644 index 000000000..8e54cb03e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_call.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_made_green_18dp.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_made_green_18dp.png index 403be7917..503b68701 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_made_green_18dp.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_made_green_18dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_received_green_18dp.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_received_green_18dp.png index 3f54e5051..fa6cedb08 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_received_green_18dp.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_received_green_18dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_white_24dp.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_white_24dp.png deleted file mode 100755 index ef45e933a..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_call_white_24dp.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_close_white.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_close_white.png index 76e07f097..ae5541db1 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_close_white.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_close_white.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_directory.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_directory.png index dcbfcc9d9..036d061b1 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_directory.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_directory.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_done.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_done.png index e5024472a..ae90ffdad 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_done.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_done.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_external_storage.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_external_storage.png index 511cbbc74..9c03531ee 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_external_storage.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_external_storage.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_fp_40px.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_fp_40px.png index e1c9590bb..d8318633d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_fp_40px.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_fp_40px.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_gallery_background.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_gallery_background.png index 4e3820ff3..2dfd59ffc 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_gallery_background.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_gallery_background.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_gofullscreen.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_gofullscreen.png index 8ccff7d13..6c3333f63 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_gofullscreen.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_gofullscreen.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_goinline.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_goinline.png index f4204b8e5..f90723808 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_goinline.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_goinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_keyboard_w.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_keyboard_w.png deleted file mode 100755 index 4866b74e4..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_keyboard_w.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_launcher.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_launcher.png deleted file mode 100755 index b03cd17af..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_launcher.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_launcher_dr.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_launcher_dr.png new file mode 100644 index 000000000..92ef5db54 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_launcher_dr.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_lock_header.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_lock_header.png index 33d6d9b7f..25f996dec 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_lock_header.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_lock_header.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_lock_white.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_lock_white.png index fa9e9e3d2..36e58e99c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_lock_white.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_lock_white.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_masks_msk1.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_masks_msk1.png index 7e8e93e8b..729839e57 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_masks_msk1.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_masks_msk1.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_masks_recent1.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_masks_recent1.png index 186726458..ebc5ed2f5 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_masks_recent1.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_masks_recent1.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_masks_sticker1.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_masks_sticker1.png index b5285491a..45b9510d1 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_masks_sticker1.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_masks_sticker1.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_msg_panel_gif.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_msg_panel_gif.png deleted file mode 100755 index c391538fe..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_msg_panel_gif.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_msg_panel_kb.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_msg_panel_kb.png deleted file mode 100755 index 81ad38432..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_msg_panel_kb.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_msg_panel_smiles.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_msg_panel_smiles.png deleted file mode 100755 index e16659743..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_msg_panel_smiles.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_msg_panel_stickers.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_msg_panel_stickers.png deleted file mode 100755 index 4eb1ab1d1..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_msg_panel_stickers.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_msg_panel_video.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_msg_panel_video.png deleted file mode 100755 index a6cb272c8..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_msg_panel_video.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_outfullscreen.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_outfullscreen.png index af5e2e275..f7f7d0b1b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_outfullscreen.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_outfullscreen.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_outinline.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_outinline.png index 3ca7fca47..d4f55a273 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_outinline.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_outinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_pause.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_pause.png index 7e1600c15..3d6a9c5ee 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_pause.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_pauseinline.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_pauseinline.png index bf835605b..f49aed757 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_pauseinline.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_pauseinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_play.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_play.png index 248c87e5b..df1953f26 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_play.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_playinline.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_playinline.png index f653a3305..cd449d9c6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_playinline.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_playinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_rating_star.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_rating_star.png index 6bacf5763..5277bc682 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_rating_star.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_rating_star.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_rating_star_filled.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_rating_star_filled.png index e447c80cf..65ed8c2d0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_rating_star_filled.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_rating_star_filled.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_reply_icon.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_reply_icon.png index 9caeae67c..2d90808b5 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_reply_icon.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_reply_icon.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_send.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_send.png index 79e85a8eb..517f4d7bf 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_send.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_send.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_share_article.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_share_article.png index 5c6cf3c37..726c9c7b9 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_share_article.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_share_article.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_share_video.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_share_video.png index a62366c5c..c31183e3d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_share_video.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_share_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smile_small.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_smile_small.png deleted file mode 100644 index 534f594b2..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smile_small.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smile_w.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_smile_w.png deleted file mode 100755 index f03eb4053..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smile_w.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_car.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_car.png deleted file mode 100755 index 8feaca01a..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_car.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_food.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_food.png deleted file mode 100755 index b78e5f1bd..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_food.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_nature.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_nature.png deleted file mode 100755 index f64082875..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_nature.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_objects.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_objects.png deleted file mode 100755 index 52e307f0b..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_objects.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_recent.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_recent.png deleted file mode 100755 index f4691b546..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_recent.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_sad.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_sad.png index 0fee4d667..e7edf3879 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_sad.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_sad.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_smile.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_smile.png deleted file mode 100755 index 12d99d091..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_smile.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_stickers.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_stickers.png deleted file mode 100755 index f72c63ed6..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles2_stickers.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles_backspace.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles_backspace.png deleted file mode 100755 index 536579024..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles_backspace.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles_gif.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles_gif.png deleted file mode 100755 index 1de26dbda..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles_gif.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles_settings.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles_settings.png deleted file mode 100755 index 27ee73f22..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles_settings.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles_trend.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles_trend.png deleted file mode 100755 index 6c9b25625..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_smiles_trend.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_storage.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_storage.png index e7913dd2f..66cf8c917 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_storage.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_storage.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_storage_gallery.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_storage_gallery.png index aa2a87ddc..998bbf392 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_storage_gallery.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_storage_gallery.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_storage_music.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_storage_music.png index 4f8df9d52..b3f95362b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_storage_music.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_storage_music.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_video.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_video.png index 4e02e64ab..a7beabab4 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_video.png and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/inline_video_pause.png b/TMessagesProj/src/main/res/drawable-xhdpi/inline_video_pause.png index 5ac38bd6f..f7641c139 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/inline_video_pause.png and b/TMessagesProj/src/main/res/drawable-xhdpi/inline_video_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/inline_video_play.png b/TMessagesProj/src/main/res/drawable-xhdpi/inline_video_play.png index 99e0e6fb8..71340a39f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/inline_video_play.png and b/TMessagesProj/src/main/res/drawable-xhdpi/inline_video_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_attach.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_attach.png new file mode 100644 index 000000000..a1f5c24c7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_attach.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_bot1.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_bot1.png new file mode 100644 index 000000000..5a20aa207 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_bot1.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_bot2.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_bot2.png new file mode 100644 index 000000000..8e3a84838 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_bot2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_clear.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_clear.png new file mode 100644 index 000000000..b427bfccc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_done.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_done.png new file mode 100644 index 000000000..14ce71c9b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_done.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_forward.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_forward.png new file mode 100644 index 000000000..7c5cfc610 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_gif.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_gif.png new file mode 100644 index 000000000..34a012370 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_keyboard.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_keyboard.png new file mode 100644 index 000000000..38ca12f9e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_keyboard.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_mic.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_mic.png new file mode 100644 index 000000000..1addb71df Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_mic.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_notify_off.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_notify_off.png new file mode 100644 index 000000000..c4f5191e4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_notify_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_notify_on.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_notify_on.png new file mode 100644 index 000000000..b926fa34b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_notify_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_reply.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_reply.png new file mode 100644 index 000000000..fb37e0c9e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_smile.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_smile.png new file mode 100644 index 000000000..edb1c3a12 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_smile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_sticker.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_sticker.png new file mode 100644 index 000000000..f343ddd04 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_sticker.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/input_video.png b/TMessagesProj/src/main/res/drawable-xhdpi/input_video.png new file mode 100644 index 000000000..62ce504b1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/input_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/instant_camera.png b/TMessagesProj/src/main/res/drawable-xhdpi/instant_camera.png index 767694370..f3d6e2d8c 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/instant_camera.png and b/TMessagesProj/src/main/res/drawable-xhdpi/instant_camera.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/instant_link.png b/TMessagesProj/src/main/res/drawable-xhdpi/instant_link.png index 4e52937d7..ce36ab3d0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/instant_link.png and b/TMessagesProj/src/main/res/drawable-xhdpi/instant_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_fast_arrow.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_fast_arrow.png index e9592206b..39a689017 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_fast_arrow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_fast_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_fast_arrow_shadow.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_fast_arrow_shadow.png index 5d904ab79..dafc5e7d6 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_fast_arrow_shadow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_fast_arrow_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_fast_body.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_fast_body.png index 6c1bda76f..f915d1182 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_fast_body.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_fast_body.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_fast_spiral.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_fast_spiral.png index 7d035b8a2..2bdc3e92b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_fast_spiral.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_fast_spiral.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_bubble.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_bubble.png index e2c8ae334..0426bf44b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_bubble.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_bubble.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_bubble_dot.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_bubble_dot.png index 3db545fc6..1a810f741 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_bubble_dot.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_bubble_dot.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_cam.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_cam.png index 4be47e374..59b1eb50c 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_cam.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_cam.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_cam_lens.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_cam_lens.png index 521526252..491be5e1b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_cam_lens.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_cam_lens.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_pencil.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_pencil.png index 51a7b7320..070a65780 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_pencil.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_pencil.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_pin.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_pin.png index 93f2aa5be..b8cb6ae5d 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_pin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_smile.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_smile.png index 7f81d87de..5c5bbf22a 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_smile.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_smile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_smile_eye.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_smile_eye.png index 2f2956cce..61541a38a 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_smile_eye.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_smile_eye.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_videocam.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_videocam.png index 43ce262c1..38f74ed11 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_videocam.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_ic_videocam.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_knot_down.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_knot_down.png index 99da27876..9c27b1143 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_knot_down.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_knot_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_knot_up.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_knot_up.png index 33f67d5a8..2356b2895 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_knot_up.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_knot_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_powerful_infinity.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_powerful_infinity.png index 8274c8f25..4a0b010ea 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_powerful_infinity.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_powerful_infinity.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_powerful_infinity_white.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_powerful_infinity_white.png index dca6ff670..6fbe740f3 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_powerful_infinity_white.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_powerful_infinity_white.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_powerful_mask.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_powerful_mask.png index e7c5d561a..698d221ee 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_powerful_mask.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_powerful_mask.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_powerful_star.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_powerful_star.png index 3be017732..2fc0573e0 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_powerful_star.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_powerful_star.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_private_door.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_private_door.png index 4197879ee..a349fa890 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_private_door.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_private_door.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_private_screw.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_private_screw.png index 59ce382f7..499e27820 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_private_screw.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_private_screw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_tg_plane.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_tg_plane.png index f56072cb1..228222daa 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_tg_plane.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_tg_plane.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/intro_tg_sphere.png b/TMessagesProj/src/main/res/drawable-xhdpi/intro_tg_sphere.png index c5a4816ad..0555c03dc 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/intro_tg_sphere.png and b/TMessagesProj/src/main/res/drawable-xhdpi/intro_tg_sphere.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/knob_shadow.png b/TMessagesProj/src/main/res/drawable-xhdpi/knob_shadow.png index 6616f3143..326d84718 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/knob_shadow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/knob_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/layer_shadow.png b/TMessagesProj/src/main/res/drawable-xhdpi/layer_shadow.png index 8724204dd..e400c0f49 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/layer_shadow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/layer_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/list_bot.png b/TMessagesProj/src/main/res/drawable-xhdpi/list_bot.png index 2b7763e08..a893bdd56 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/list_bot.png and b/TMessagesProj/src/main/res/drawable-xhdpi/list_bot.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/list_broadcast.png b/TMessagesProj/src/main/res/drawable-xhdpi/list_broadcast.png index 9c9220c31..e5b378835 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/list_broadcast.png and b/TMessagesProj/src/main/res/drawable-xhdpi/list_broadcast.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/list_check.png b/TMessagesProj/src/main/res/drawable-xhdpi/list_check.png old mode 100755 new mode 100644 index b861ff734..bdc715d8c Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/list_check.png and b/TMessagesProj/src/main/res/drawable-xhdpi/list_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/list_circle.png b/TMessagesProj/src/main/res/drawable-xhdpi/list_circle.png index 73433f905..6b5b03d68 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/list_circle.png and b/TMessagesProj/src/main/res/drawable-xhdpi/list_circle.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/list_group.png b/TMessagesProj/src/main/res/drawable-xhdpi/list_group.png index 185c653ea..490f1e783 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/list_group.png and b/TMessagesProj/src/main/res/drawable-xhdpi/list_group.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/list_halfcheck.png b/TMessagesProj/src/main/res/drawable-xhdpi/list_halfcheck.png old mode 100755 new mode 100644 index c61e9df11..6a0f88009 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/list_halfcheck.png and b/TMessagesProj/src/main/res/drawable-xhdpi/list_halfcheck.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/list_mute.png b/TMessagesProj/src/main/res/drawable-xhdpi/list_mute.png old mode 100755 new mode 100644 index fe772f354..8394b2a3b Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/list_mute.png and b/TMessagesProj/src/main/res/drawable-xhdpi/list_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/list_pin.png b/TMessagesProj/src/main/res/drawable-xhdpi/list_pin.png old mode 100755 new mode 100644 index 60dfe7cd4..0502fa00d Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/list_pin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/list_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/list_reorder.png b/TMessagesProj/src/main/res/drawable-xhdpi/list_reorder.png new file mode 100644 index 000000000..b1ed0a1d0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/list_reorder.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/list_secret.png b/TMessagesProj/src/main/res/drawable-xhdpi/list_secret.png index 03d8c9d53..18b59d99f 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/list_secret.png and b/TMessagesProj/src/main/res/drawable-xhdpi/list_secret.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/list_warning_sign.png b/TMessagesProj/src/main/res/drawable-xhdpi/list_warning_sign.png index c5d384b1d..b0b0d969c 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/list_warning_sign.png and b/TMessagesProj/src/main/res/drawable-xhdpi/list_warning_sign.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/live_loc.png b/TMessagesProj/src/main/res/drawable-xhdpi/live_loc.png index bc29eb803..32028e854 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/live_loc.png and b/TMessagesProj/src/main/res/drawable-xhdpi/live_loc.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/livelocationpin.png b/TMessagesProj/src/main/res/drawable-xhdpi/livelocationpin.png index d2263b4b7..3a74a1463 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/livelocationpin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/livelocationpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/livepin.png b/TMessagesProj/src/main/res/drawable-xhdpi/livepin.png index eb714bf8c..9eb89fc39 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/livepin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/livepin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/load_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/load_big.png index 747d9aff9..e8f2a1030 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/load_big.png and b/TMessagesProj/src/main/res/drawable-xhdpi/load_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/location_panel.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/location_panel.9.png index 8d2d3ab13..8bc85c248 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/location_panel.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/location_panel.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/lock_arrow.png b/TMessagesProj/src/main/res/drawable-xhdpi/lock_arrow.png index 79087de8a..202571faf 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/lock_arrow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/lock_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/lock_close.png b/TMessagesProj/src/main/res/drawable-xhdpi/lock_close.png index 9ea564016..003223a16 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/lock_close.png and b/TMessagesProj/src/main/res/drawable-xhdpi/lock_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/lock_middle.png b/TMessagesProj/src/main/res/drawable-xhdpi/lock_middle.png index 28f67d6ac..ee69f8b92 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/lock_middle.png and b/TMessagesProj/src/main/res/drawable-xhdpi/lock_middle.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/lock_open.png b/TMessagesProj/src/main/res/drawable-xhdpi/lock_open.png index c85e140b1..abc4447c8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/lock_open.png and b/TMessagesProj/src/main/res/drawable-xhdpi/lock_open.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/lock_round.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/lock_round.9.png index 9667fdee2..06f2e1573 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/lock_round.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/lock_round.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/lock_round_shadow.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/lock_round_shadow.9.png index 6c9c03af6..3d81dfe79 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/lock_round_shadow.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/lock_round_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/lock_top.png b/TMessagesProj/src/main/res/drawable-xhdpi/lock_top.png index 7b0423f60..f51d128c7 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/lock_top.png and b/TMessagesProj/src/main/res/drawable-xhdpi/lock_top.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/log_info.png b/TMessagesProj/src/main/res/drawable-xhdpi/log_info.png index 3c75bfc87..9811db4de 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/log_info.png and b/TMessagesProj/src/main/res/drawable-xhdpi/log_info.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/logo_middle.png b/TMessagesProj/src/main/res/drawable-xhdpi/logo_middle.png index 65e145fe2..1a5cda5a8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/logo_middle.png and b/TMessagesProj/src/main/res/drawable-xhdpi/logo_middle.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/map_pin.png b/TMessagesProj/src/main/res/drawable-xhdpi/map_pin.png index b72b803f0..982737190 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/map_pin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/map_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_blue.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_blue.png index 89fea9c3a..828d62d45 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_blue.png and b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_blue.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_blue_b.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_blue_b.png index 7fe9f949c..7125c99b8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_blue_b.png and b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_blue_b.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_green.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_green.png index ad29010fd..464314361 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_green.png and b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_green.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_green_b.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_green_b.png index 6064fad1f..32970944f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_green_b.png and b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_green_b.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_load.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_load.png index bb80f73aa..affb6ec78 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_load.png and b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_load.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_pause.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_pause.png index 9bf50dc22..9b0067c7c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_pause.png and b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_red.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_red.png index 141acd312..31270a869 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_red.png and b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_red.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_red_b.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_red_b.png index a3896c88f..03a810e7f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_red_b.png and b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_red_b.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_yellow.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_yellow.png index 697672aa5..c0ab83751 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_yellow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_yellow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_yellow_b.png b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_yellow_b.png index d29562ff1..8551c6a61 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_yellow_b.png and b/TMessagesProj/src/main/res/drawable-xhdpi/media_doc_yellow_b.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/mentionbutton.png b/TMessagesProj/src/main/res/drawable-xhdpi/mentionbutton.png index 827d9b839..790344acd 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/mentionbutton.png and b/TMessagesProj/src/main/res/drawable-xhdpi/mentionbutton.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/mentionchatslist.png b/TMessagesProj/src/main/res/drawable-xhdpi/mentionchatslist.png index b30732e45..e8f0383f3 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/mentionchatslist.png and b/TMessagesProj/src/main/res/drawable-xhdpi/mentionchatslist.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_add.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_add.png index 6bbd65933..f83f3b5d6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_add.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_bookmarks_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_bookmarks_ny.png index be83de585..3706ad265 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_bookmarks_ny.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_bookmarks_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_broadcast.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_broadcast.png index d10d08994..4e9007501 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_broadcast.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_broadcast.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_calls.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_calls.png index e46f86327..b57563eec 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_calls.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_calls.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_calls_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_calls_ny.png index 7c15e6e6d..3042a4bf8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_calls_ny.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_calls_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_camera.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_camera.png index 1ac9d2a40..0ba269d28 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_camera.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_camera.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_camera_av.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_camera_av.png index 93513bf20..22b884847 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_camera_av.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_camera_av.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_channel_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_channel_ny.png index 3ae33349b..da284bee9 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_channel_ny.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_channel_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_chats.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_chats.png index 1168ec9a6..ef417c749 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_chats.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_chats.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_clearcache.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_clearcache.png index 8047f6565..eaea1c8c4 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_clearcache.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_clearcache.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_contacts.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_contacts.png index 588668fe4..cf1ebbbce 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_contacts.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_contacts.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_contacts_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_contacts_ny.png index dd6f7451c..d4c9d3ccb 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_contacts_ny.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_contacts_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_copy.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_copy.9.png index 79bad8012..52e4be997 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_copy.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_copy.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_data.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_data.png index a5a16e2d9..b97b25f71 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_data.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_data.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_groups.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_groups.png new file mode 100644 index 000000000..026eeacee Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_groups.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_groups_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_groups_ny.png index 2f6a2630f..707de81f2 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_groups_ny.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_groups_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_help.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_help.png index 4b9f1ad3f..8ebf31be2 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_help.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_help.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_help_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_help_ny.png index 2ebaded1f..b9a0c0b85 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_help_ny.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_help_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_invite.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_invite.png index 83ac1e771..e726579ba 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_invite.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_invite.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_invite_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_invite_ny.png index 8c4c4c6f4..73a23f1ad 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_invite_ny.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_invite_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_language.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_language.png index c50d1dfa5..4aae16c53 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_language.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_language.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_newgroup.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_newgroup.png deleted file mode 100644 index e9496312c..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_newgroup.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_newphone.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_newphone.png index c1bfe53ac..a74f6ffa5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_newphone.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_newphone.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_notifications.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_notifications.png index b23157ce3..e02d27c93 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_notifications.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_notifications.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_palette.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_palette.png index 859598dfa..5e2e79a36 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_palette.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_palette.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_passcode.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_passcode.png index 016267096..1926ce328 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_passcode.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_passcode.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_read.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_read.png index 631bc2684..8c41578af 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_read.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_read.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_saved.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_saved.png index 8a41f4069..47081e92a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_saved.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_saved.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_search.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_search.png index 72da9d93a..881192501 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_search.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_secret.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_secret.png index d2e01af32..63639b49e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_secret.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_secret.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_secret_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_secret_ny.png index 4e9c3171f..59ee33b02 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_secret_ny.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_secret_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_settings.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_settings.png index 16176b426..9a455f08d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_settings.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_settings_filled.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_settings_filled.png index d631f43e2..7ec1b5bb0 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_settings_filled.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_settings_filled.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_settings_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_settings_ny.png index 1982d48db..072bea13a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_settings_ny.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_settings_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_shadow.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_shadow.png index 8d539199a..50dac59a0 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_shadow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_support.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_support.png index bc8e90fc6..bcacdff28 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_support.png and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_support.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_unread.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_unread.png deleted file mode 100644 index 9580a9d06..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_unread.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/message_arrow.png b/TMessagesProj/src/main/res/drawable-xhdpi/message_arrow.png index ae2ec11d0..a74690ef3 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/message_arrow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/message_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/mic.png b/TMessagesProj/src/main/res/drawable-xhdpi/mic.png deleted file mode 100644 index 07595c77d..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/mic.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_close.png b/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_close.png index 37f544ec0..48d684a30 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_close.png and b/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_pause.png b/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_pause.png index 4b1840d21..983abace1 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_pause.png and b/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_play.png b/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_play.png index 3967d3725..a2f113c69 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_play.png and b/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/moon.png b/TMessagesProj/src/main/res/drawable-xhdpi/moon.png index 4ff8798b1..01daf9239 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/moon.png and b/TMessagesProj/src/main/res/drawable-xhdpi/moon.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_actions.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_actions.png index 58ccde2d6..6baec5634 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_actions.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_actions.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_addbot.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addbot.png new file mode 100644 index 000000000..5f9afb426 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addbot.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_addcontact.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addcontact.png new file mode 100644 index 000000000..10fb39f15 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addcontact.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_archive.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_archive.png new file mode 100644 index 000000000..96e0a5a7d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_archive.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_block.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_block.png new file mode 100644 index 000000000..dfd3d7d9f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_block.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_calendar.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calendar.png new file mode 100644 index 000000000..1ba18b011 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calendar.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_callback.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_callback.png new file mode 100644 index 000000000..22e43320d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_callback.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_cancel.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_cancel.png new file mode 100644 index 000000000..eec3c61f9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_check.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_check.png index e869b16ba..69087d164 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_check.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_clear.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_clear.png new file mode 100644 index 000000000..794464c60 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_clock.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_clock.png index e38d7f9fd..4168e3b71 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_clock.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_clock.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_contact.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_contact.png index 7d622cbbc..c2d5029f9 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_contact.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_contact.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_copy.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_copy.png new file mode 100644 index 000000000..3e8019fea Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_copy.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_delete.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_delete.png new file mode 100644 index 000000000..93ac3b001 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_download.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_download.png new file mode 100644 index 000000000..01be76015 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_download.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_edit.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_edit.png new file mode 100644 index 000000000..e8499fd46 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_edit.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_fave.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_fave.png new file mode 100644 index 000000000..5d667c129 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_fave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_forward.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_forward.png new file mode 100644 index 000000000..d8bb1c54b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_gallery.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_gallery.png new file mode 100644 index 000000000..b392961ec Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_gallery.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_gif.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_gif.png new file mode 100644 index 000000000..c9720b8f9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_go_down.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_go_down.png new file mode 100644 index 000000000..34888b613 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_go_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_go_up.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_go_up.png new file mode 100644 index 000000000..3b7f39bea Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_go_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_halfcheck.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_halfcheck.png index f357df4f6..f09d26e8d 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_halfcheck.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_halfcheck.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_home.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_home.png new file mode 100644 index 000000000..42be54108 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_home.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_hybrid.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_hybrid.png new file mode 100644 index 000000000..40c43c601 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_hybrid.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_in.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_in.9.png index 63fee107e..3137034e8 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_in.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_in.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_in_shadow.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_in_shadow.9.png index e7286533d..a4c2f64cf 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_in_shadow.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_in_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_instant.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_instant.png index f03df3f07..0571be59d 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_instant.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_instant.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_language.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_language.png new file mode 100644 index 000000000..99eaab7a5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_language.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_leave.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_leave.png new file mode 100644 index 000000000..65af266cb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_leave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_link.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_link.png new file mode 100644 index 000000000..4c3724711 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_location.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_location.png index a23c6f9b2..3ccd38e27 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_location.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_map.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_map.png new file mode 100644 index 000000000..64f3b7bc4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_map.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_markread.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_markread.png new file mode 100644 index 000000000..fb76ba61a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_markread.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_markunread.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_markunread.png new file mode 100644 index 000000000..7669c6e9d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_markunread.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_mask.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mask.png new file mode 100644 index 000000000..51b53f4f1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mask.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_media.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_media.png new file mode 100644 index 000000000..b512e340c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_media.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_message.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_message.png new file mode 100644 index 000000000..b97215aea Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_message.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_mute.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mute.png new file mode 100644 index 000000000..7fb830bc7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_openin.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_openin.png new file mode 100644 index 000000000..5513e8be3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_openin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_out.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_out.9.png index 34de041e9..c868195d3 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_out.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_out.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_out_shadow.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_out_shadow.9.png index dc71a23f9..32082931d 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_out_shadow.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_out_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_panel_clear.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_panel_clear.png index d6e1f4725..926030510 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_panel_clear.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_panel_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_panel_forward.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_panel_forward.png index beb9a83dd..cdfacb8e7 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_panel_forward.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_panel_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_panel_link.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_panel_link.png deleted file mode 100755 index 4cd2021e5..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_panel_link.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_panel_reply.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_panel_reply.png index 33c847c2b..077cbf068 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_panel_reply.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_panel_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo.9.png index fc7d66402..d0bc898d2 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_shadow.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_shadow.9.png index b8a548157..70b49261e 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_shadow.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_pin.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_pin.png new file mode 100644 index 000000000..a7cc6fd52 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_pollstop.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_pollstop.png new file mode 100644 index 000000000..76a62c35b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_pollstop.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_reply.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_reply.png new file mode 100644 index 000000000..9f41c7b87 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_report.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_report.png new file mode 100644 index 000000000..418f0bf23 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_report.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_retry.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_retry.png new file mode 100644 index 000000000..796fd61a2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_retry.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_cancel_m.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_cancel_m.png index 3dca5e127..8c8d868f0 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_cancel_m.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_cancel_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_file_s.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_file_s.png index a96ebcf20..029a961f0 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_file_s.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_file_s.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_gif_m.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_gif_m.png index fe04dc322..aa862bc4a 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_gif_m.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_gif_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_load_m.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_load_m.png index 926e76fdb..73d863c81 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_load_m.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_load_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_pause_m.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_pause_m.png index 575c0ef58..5e63548fd 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_pause_m.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_pause_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_play_m.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_play_m.png index 2c237ddce..579898b36 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_play_m.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_round_play_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_satellite.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_satellite.png new file mode 100644 index 000000000..bcc7340a6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_satellite.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_search.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_search.png new file mode 100644 index 000000000..2bf287b43 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_share.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_share.png new file mode 100644 index 000000000..a475b29d4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_share.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_shareout.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_shareout.png new file mode 100644 index 000000000..70a2a7b59 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_shareout.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_stats.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_stats.png new file mode 100644 index 000000000..13cec400c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_stats.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_sticker.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_sticker.png new file mode 100644 index 000000000..d585ed923 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_sticker.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_theme.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_theme.png new file mode 100644 index 000000000..7942e4dc5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_theme.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_timer.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_timer.png new file mode 100644 index 000000000..455e059be Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_timer.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_unarchive.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unarchive.png new file mode 100644 index 000000000..b0fa8bc88 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unarchive.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_unfave.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unfave.png new file mode 100644 index 000000000..b36f8b4eb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unfave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_unmute.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unmute.png new file mode 100644 index 000000000..037d3bf97 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unmute.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_unpin.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unpin.png new file mode 100644 index 000000000..35cc9ff9c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_unvote.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unvote.png new file mode 100644 index 000000000..1526eb4e6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unvote.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_usersearch.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_usersearch.png new file mode 100644 index 000000000..6c78313b5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_usersearch.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_views.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_views.png index f6eb7815d..179c3122e 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_views.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_views.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_warning.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_warning.png index e0d2c5999..4270937e9 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_warning.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_warning.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/music_reverse.png b/TMessagesProj/src/main/res/drawable-xhdpi/music_reverse.png index 970652465..798f76da0 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/music_reverse.png and b/TMessagesProj/src/main/res/drawable-xhdpi/music_reverse.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/myloc_on.png b/TMessagesProj/src/main/res/drawable-xhdpi/myloc_on.png index 0ebd34173..fa8029d01 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/myloc_on.png and b/TMessagesProj/src/main/res/drawable-xhdpi/myloc_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/navigate.png b/TMessagesProj/src/main/res/drawable-xhdpi/navigate.png index 6c7b7e134..167559164 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/navigate.png and b/TMessagesProj/src/main/res/drawable-xhdpi/navigate.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/newmsg_divider.png b/TMessagesProj/src/main/res/drawable-xhdpi/newmsg_divider.png index 935c3fb0f..1b8edb36c 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/newmsg_divider.png and b/TMessagesProj/src/main/res/drawable-xhdpi/newmsg_divider.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/newyear.png b/TMessagesProj/src/main/res/drawable-xhdpi/newyear.png index 5d626d502..a69ac9e1b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/newyear.png and b/TMessagesProj/src/main/res/drawable-xhdpi/newyear.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/no_apps.png b/TMessagesProj/src/main/res/drawable-xhdpi/no_apps.png index 0a0aee1ec..1db9de5dd 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/no_apps.png and b/TMessagesProj/src/main/res/drawable-xhdpi/no_apps.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/no_passport.png b/TMessagesProj/src/main/res/drawable-xhdpi/no_passport.png index c5cc6cffb..22084565c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/no_passport.png and b/TMessagesProj/src/main/res/drawable-xhdpi/no_passport.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/no_password.png b/TMessagesProj/src/main/res/drawable-xhdpi/no_password.png index 66ee9e7a1..1e6a6ff63 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/no_password.png and b/TMessagesProj/src/main/res/drawable-xhdpi/no_password.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/nocover.png b/TMessagesProj/src/main/res/drawable-xhdpi/nocover.png index 6d655f833..89545ec67 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/nocover.png and b/TMessagesProj/src/main/res/drawable-xhdpi/nocover.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/nocover_big.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/nocover_big.9.png index 7026a671f..e68ec4656 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/nocover_big.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/nocover_big.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/nocover_small.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/nocover_small.9.png index 5e135bde6..bfed60afe 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/nocover_small.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/nocover_small.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/nophotos.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/nophotos.9.png index 3d70646b3..2642e2d81 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/nophotos.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/nophotos.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/notification.png b/TMessagesProj/src/main/res/drawable-xhdpi/notification.png old mode 100755 new mode 100644 index fb9787589..13b8fb830 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/notification.png and b/TMessagesProj/src/main/res/drawable-xhdpi/notification.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/notifications_mute1h.png b/TMessagesProj/src/main/res/drawable-xhdpi/notifications_mute1h.png index ceef5d559..d6889edfd 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/notifications_mute1h.png and b/TMessagesProj/src/main/res/drawable-xhdpi/notifications_mute1h.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/notifications_mute2d.png b/TMessagesProj/src/main/res/drawable-xhdpi/notifications_mute2d.png index 91afbdcfb..547a5a3b3 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/notifications_mute2d.png and b/TMessagesProj/src/main/res/drawable-xhdpi/notifications_mute2d.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/notifications_off.png b/TMessagesProj/src/main/res/drawable-xhdpi/notifications_off.png index df6588840..3cc138ba5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/notifications_off.png and b/TMessagesProj/src/main/res/drawable-xhdpi/notifications_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/notifications_on.png b/TMessagesProj/src/main/res/drawable-xhdpi/notifications_on.png index 74d6c18ec..98fe11da9 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/notifications_on.png and b/TMessagesProj/src/main/res/drawable-xhdpi/notifications_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/notifications_settings.png b/TMessagesProj/src/main/res/drawable-xhdpi/notifications_settings.png index 7bf29a8ea..68153c2fb 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/notifications_settings.png and b/TMessagesProj/src/main/res/drawable-xhdpi/notifications_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/notify_members_off.png b/TMessagesProj/src/main/res/drawable-xhdpi/notify_members_off.png deleted file mode 100644 index 3c7af833c..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/notify_members_off.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/notify_members_on.png b/TMessagesProj/src/main/res/drawable-xhdpi/notify_members_on.png deleted file mode 100644 index 55a9c9d1a..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/notify_members_on.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/outline_add_gif.png b/TMessagesProj/src/main/res/drawable-xhdpi/outline_add_gif.png new file mode 100644 index 000000000..51378fa75 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/outline_add_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/outline_fave.png b/TMessagesProj/src/main/res/drawable-xhdpi/outline_fave.png new file mode 100644 index 000000000..c620884cc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/outline_fave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/outline_pack.png b/TMessagesProj/src/main/res/drawable-xhdpi/outline_pack.png new file mode 100644 index 000000000..7a456334f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/outline_pack.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/outline_send.png b/TMessagesProj/src/main/res/drawable-xhdpi/outline_send.png new file mode 100644 index 000000000..ea718179f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/outline_send.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/outline_unfave.png b/TMessagesProj/src/main/res/drawable-xhdpi/outline_unfave.png new file mode 100644 index 000000000..489cdafbf Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/outline_unfave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pagedown.png b/TMessagesProj/src/main/res/drawable-xhdpi/pagedown.png index 94be23952..362519888 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/pagedown.png and b/TMessagesProj/src/main/res/drawable-xhdpi/pagedown.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pagedown_shadow.png b/TMessagesProj/src/main/res/drawable-xhdpi/pagedown_shadow.png index 89486c7fb..a7d064945 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/pagedown_shadow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/pagedown_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/passcode_check.png b/TMessagesProj/src/main/res/drawable-xhdpi/passcode_check.png index f407719d7..578c49231 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/passcode_check.png and b/TMessagesProj/src/main/res/drawable-xhdpi/passcode_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/passcode_delete.png b/TMessagesProj/src/main/res/drawable-xhdpi/passcode_delete.png index 57af5956d..021fd2a6d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/passcode_delete.png and b/TMessagesProj/src/main/res/drawable-xhdpi/passcode_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/passcode_logo.png b/TMessagesProj/src/main/res/drawable-xhdpi/passcode_logo.png index 92c5f2d5b..1b697ed8e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/passcode_logo.png and b/TMessagesProj/src/main/res/drawable-xhdpi/passcode_logo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/permission_locked.png b/TMessagesProj/src/main/res/drawable-xhdpi/permission_locked.png index e8f454e82..7476aa295 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/permission_locked.png and b/TMessagesProj/src/main/res/drawable-xhdpi/permission_locked.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/permissions_contacts.png b/TMessagesProj/src/main/res/drawable-xhdpi/permissions_contacts.png index ad5375d93..1422a9ce9 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/permissions_contacts.png and b/TMessagesProj/src/main/res/drawable-xhdpi/permissions_contacts.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/phone_activate.png b/TMessagesProj/src/main/res/drawable-xhdpi/phone_activate.png index f97ecc3bf..c52774e02 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/phone_activate.png and b/TMessagesProj/src/main/res/drawable-xhdpi/phone_activate.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/phone_change.png b/TMessagesProj/src/main/res/drawable-xhdpi/phone_change.png index 4b39140b9..9fe6bd8df 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/phone_change.png and b/TMessagesProj/src/main/res/drawable-xhdpi/phone_change.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photo_add.png b/TMessagesProj/src/main/res/drawable-xhdpi/photo_add.png index fde0b1ec4..0db62e656 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photo_add.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photo_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photo_crop.png b/TMessagesProj/src/main/res/drawable-xhdpi/photo_crop.png index aa3c9f1b9..7d9f22dcb 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photo_crop.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photo_crop.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photo_outline.png b/TMessagesProj/src/main/res/drawable-xhdpi/photo_outline.png index b2cc45dbb..19be0c455 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photo_outline.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photo_outline.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photo_paint.png b/TMessagesProj/src/main/res/drawable-xhdpi/photo_paint.png index a0b50a307..3bcdef7b8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photo_paint.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photo_paint.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photo_paint_brush.png b/TMessagesProj/src/main/res/drawable-xhdpi/photo_paint_brush.png index 7abb99831..6ccc13170 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photo_paint_brush.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photo_paint_brush.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photo_paint_text.png b/TMessagesProj/src/main/res/drawable-xhdpi/photo_paint_text.png index ef97e015c..ab9b8b9e1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photo_paint_text.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photo_paint_text.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photo_sticker.png b/TMessagesProj/src/main/res/drawable-xhdpi/photo_sticker.png index 9da291fa3..e9a82d8b0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photo_sticker.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photo_sticker.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photo_timer.png b/TMessagesProj/src/main/res/drawable-xhdpi/photo_timer.png index 3a0b07e4d..e4baa0c85 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photo_timer.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photo_timer.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photo_tools.png b/TMessagesProj/src/main/res/drawable-xhdpi/photo_tools.png index 2a8a2b0c3..650d627fc 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photo_tools.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photo_tools.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photo_undo.png b/TMessagesProj/src/main/res/drawable-xhdpi/photo_undo.png index 5a77382e1..25a590759 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photo_undo.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photo_undo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photo_w.png b/TMessagesProj/src/main/res/drawable-xhdpi/photo_w.png index 99dadead6..32d604464 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photo_w.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photo_w.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photobadge.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/photobadge.9.png index 19e093fc7..3617f2b32 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photobadge.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photobadge.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photocheck.png b/TMessagesProj/src/main/res/drawable-xhdpi/photocheck.png index 476dc2a27..d90554529 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photocheck.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photocheck.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photos_arrow.png b/TMessagesProj/src/main/res/drawable-xhdpi/photos_arrow.png index c5d974a89..b31f6b595 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photos_arrow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photos_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photos_group.png b/TMessagesProj/src/main/res/drawable-xhdpi/photos_group.png index 1cb0b933c..751d5958c 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photos_group.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photos_group.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photos_header_shadow.png b/TMessagesProj/src/main/res/drawable-xhdpi/photos_header_shadow.png index 28487fec1..b31428e31 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photos_header_shadow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photos_header_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/photos_rounded.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/photos_rounded.9.png index 6a03ff4a4..1bf8599c7 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/photos_rounded.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/photos_rounded.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/phototime.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/phototime.9.png index e1d7fa493..8b50616c3 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/phototime.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/phototime.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pin.png b/TMessagesProj/src/main/res/drawable-xhdpi/pin.png index 314f0b24a..3ee841ea4 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/pin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_next.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_next.png index 7fcb3e6ec..36ce2ec33 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/pl_next.png and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_next.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_pause.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_pause.png index 06a465338..eafdf7752 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/pl_pause.png and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_play.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_play.png index 916d3d136..f92f797ed 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/pl_play.png and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_previous.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_previous.png index b592bfc4d..f65c9d920 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/pl_previous.png and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_previous.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat.png index ef720019c..d999afa0e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat.png and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat1.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat1.png index 7f31bac08..e6f8132df 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat1.png and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat1.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_shuffle.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_shuffle.png index 55eb5dca1..81a4e5bf4 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/pl_shuffle.png and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_shuffle.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/place_x.png b/TMessagesProj/src/main/res/drawable-xhdpi/place_x.png index be7548eb3..4f0f7b325 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/place_x.png and b/TMessagesProj/src/main/res/drawable-xhdpi/place_x.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/play_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/play_big.png index 37409d865..5b4181363 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/play_big.png and b/TMessagesProj/src/main/res/drawable-xhdpi/play_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/play_mini_video.png b/TMessagesProj/src/main/res/drawable-xhdpi/play_mini_video.png index 970e57517..41d86adaf 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/play_mini_video.png and b/TMessagesProj/src/main/res/drawable-xhdpi/play_mini_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/player.png b/TMessagesProj/src/main/res/drawable-xhdpi/player.png index c236f57a6..11d7042b0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/player.png and b/TMessagesProj/src/main/res/drawable-xhdpi/player.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/plus.png b/TMessagesProj/src/main/res/drawable-xhdpi/plus.png index 0451c72bf..dff43dd68 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/plus.png and b/TMessagesProj/src/main/res/drawable-xhdpi/plus.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/popup_fixed.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/popup_fixed.9.png index c94b50ef8..9b851d817 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/popup_fixed.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/popup_fixed.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/popup_fixed_alert.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/popup_fixed_alert.9.png index 150e5e6e1..d6bb84498 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/popup_fixed_alert.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/popup_fixed_alert.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/popup_fixed_alert2.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/popup_fixed_alert2.9.png new file mode 100644 index 000000000..bbfa7c82c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/popup_fixed_alert2.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/popup_fixed_top.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/popup_fixed_top.9.png index c08c8860a..f7ce561ac 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/popup_fixed_top.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/popup_fixed_top.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/preview_arrow.png b/TMessagesProj/src/main/res/drawable-xhdpi/preview_arrow.png new file mode 100644 index 000000000..ad6d059cc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/preview_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/preview_open.png b/TMessagesProj/src/main/res/drawable-xhdpi/preview_open.png index bd80018da..6cf8402d4 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/preview_open.png and b/TMessagesProj/src/main/res/drawable-xhdpi/preview_open.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/profile_admin.png b/TMessagesProj/src/main/res/drawable-xhdpi/profile_admin.png index 5b7e1bf14..e093072db 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/profile_admin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/profile_admin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/profile_audio.png b/TMessagesProj/src/main/res/drawable-xhdpi/profile_audio.png index df97532f4..b7cddb8c0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/profile_audio.png and b/TMessagesProj/src/main/res/drawable-xhdpi/profile_audio.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/profile_ban.png b/TMessagesProj/src/main/res/drawable-xhdpi/profile_ban.png index a9afd1539..a107f1af3 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/profile_ban.png and b/TMessagesProj/src/main/res/drawable-xhdpi/profile_ban.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/profile_file.png b/TMessagesProj/src/main/res/drawable-xhdpi/profile_file.png index cb3b3c3e5..0d96c25a3 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/profile_file.png and b/TMessagesProj/src/main/res/drawable-xhdpi/profile_file.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/profile_groups.png b/TMessagesProj/src/main/res/drawable-xhdpi/profile_groups.png deleted file mode 100644 index 92b6f5924..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/profile_groups.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/profile_info.png b/TMessagesProj/src/main/res/drawable-xhdpi/profile_info.png index 26cd7be65..3e63cdbd4 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/profile_info.png and b/TMessagesProj/src/main/res/drawable-xhdpi/profile_info.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/profile_link.png b/TMessagesProj/src/main/res/drawable-xhdpi/profile_link.png index c6a4a3e45..f018a50d4 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/profile_link.png and b/TMessagesProj/src/main/res/drawable-xhdpi/profile_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/profile_list.png b/TMessagesProj/src/main/res/drawable-xhdpi/profile_list.png index ad39ad088..757f58782 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/profile_list.png and b/TMessagesProj/src/main/res/drawable-xhdpi/profile_list.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/profile_message.png b/TMessagesProj/src/main/res/drawable-xhdpi/profile_message.png index 5742b95c0..9cb3c31d6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/profile_message.png and b/TMessagesProj/src/main/res/drawable-xhdpi/profile_message.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/profile_newmsg.png b/TMessagesProj/src/main/res/drawable-xhdpi/profile_newmsg.png index 35ea26d75..53978ffb5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/profile_newmsg.png and b/TMessagesProj/src/main/res/drawable-xhdpi/profile_newmsg.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/profile_phone.png b/TMessagesProj/src/main/res/drawable-xhdpi/profile_phone.png index b8c3072f8..b30f8d525 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/profile_phone.png and b/TMessagesProj/src/main/res/drawable-xhdpi/profile_phone.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/profile_photos.png b/TMessagesProj/src/main/res/drawable-xhdpi/profile_photos.png index 3ff00f2c0..fc25217c8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/profile_photos.png and b/TMessagesProj/src/main/res/drawable-xhdpi/profile_photos.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/profile_voice.png b/TMessagesProj/src/main/res/drawable-xhdpi/profile_voice.png index 86af3a1a5..d333e8ff5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/profile_voice.png and b/TMessagesProj/src/main/res/drawable-xhdpi/profile_voice.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/proxy_check.png b/TMessagesProj/src/main/res/drawable-xhdpi/proxy_check.png index e6e48e66c..19c99de79 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/proxy_check.png and b/TMessagesProj/src/main/res/drawable-xhdpi/proxy_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/proxy_off.png b/TMessagesProj/src/main/res/drawable-xhdpi/proxy_off.png index 6fca2795f..2b9910bb2 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/proxy_off.png and b/TMessagesProj/src/main/res/drawable-xhdpi/proxy_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/proxy_on.png b/TMessagesProj/src/main/res/drawable-xhdpi/proxy_on.png index 9bdbe4fa2..0c331af7c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/proxy_on.png and b/TMessagesProj/src/main/res/drawable-xhdpi/proxy_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/redcircle.png b/TMessagesProj/src/main/res/drawable-xhdpi/redcircle.png index 0b9723679..85ae7cfd9 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/redcircle.png and b/TMessagesProj/src/main/res/drawable-xhdpi/redcircle.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/regbtn2.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/regbtn2.9.png index c7c9e54aa..8aea6835f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/regbtn2.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/regbtn2.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/regbtn2_pressed.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/regbtn2_pressed.9.png index 294660c23..9751557f9 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/regbtn2_pressed.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/regbtn2_pressed.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/replyvideo.png b/TMessagesProj/src/main/res/drawable-xhdpi/replyvideo.png index 76efd5b1b..6f040ec24 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/replyvideo.png and b/TMessagesProj/src/main/res/drawable-xhdpi/replyvideo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/round_check2.png b/TMessagesProj/src/main/res/drawable-xhdpi/round_check2.png index 0ccccb73c..087c3653f 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/round_check2.png and b/TMessagesProj/src/main/res/drawable-xhdpi/round_check2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/round_grey.png b/TMessagesProj/src/main/res/drawable-xhdpi/round_grey.png index de6e1f5cc..534653621 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/round_grey.png and b/TMessagesProj/src/main/res/drawable-xhdpi/round_grey.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/s_pause.png b/TMessagesProj/src/main/res/drawable-xhdpi/s_pause.png index 980cb0d4b..3a8a94699 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/s_pause.png and b/TMessagesProj/src/main/res/drawable-xhdpi/s_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/s_play.png b/TMessagesProj/src/main/res/drawable-xhdpi/s_play.png index 2d98d4cc3..3a29fd9dd 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/s_play.png and b/TMessagesProj/src/main/res/drawable-xhdpi/s_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/scroll_tip.png b/TMessagesProj/src/main/res/drawable-xhdpi/scroll_tip.png index 9d088d80e..03c7a1196 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/scroll_tip.png and b/TMessagesProj/src/main/res/drawable-xhdpi/scroll_tip.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/search_calendar.png b/TMessagesProj/src/main/res/drawable-xhdpi/search_calendar.png deleted file mode 100755 index 8c7d29406..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/search_calendar.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/search_dark.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/search_dark.9.png index cc5dfb27d..b58d81e84 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/search_dark.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/search_dark.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/search_dark_activated.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/search_dark_activated.9.png index 71aa58d74..527ec4c10 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/search_dark_activated.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/search_dark_activated.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/search_down.png b/TMessagesProj/src/main/res/drawable-xhdpi/search_down.png deleted file mode 100755 index 5b07c1dff..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/search_down.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/search_gif.png b/TMessagesProj/src/main/res/drawable-xhdpi/search_gif.png index 5cd150ba3..b283c123c 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/search_gif.png and b/TMessagesProj/src/main/res/drawable-xhdpi/search_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/search_up.png b/TMessagesProj/src/main/res/drawable-xhdpi/search_up.png deleted file mode 100755 index 8ff662fdf..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/search_up.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/search_web.png b/TMessagesProj/src/main/res/drawable-xhdpi/search_web.png index 44532e089..ba00b81c6 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/search_web.png and b/TMessagesProj/src/main/res/drawable-xhdpi/search_web.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/selectphoto_large.png b/TMessagesProj/src/main/res/drawable-xhdpi/selectphoto_large.png index b6b46e247..8d833d0c8 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/selectphoto_large.png and b/TMessagesProj/src/main/res/drawable-xhdpi/selectphoto_large.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/settings_arrow.png b/TMessagesProj/src/main/res/drawable-xhdpi/settings_arrow.png new file mode 100644 index 000000000..1e31fabf6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/settings_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/settings_noresults.png b/TMessagesProj/src/main/res/drawable-xhdpi/settings_noresults.png new file mode 100644 index 000000000..d4d174b0e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/settings_noresults.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/shadowdown.png b/TMessagesProj/src/main/res/drawable-xhdpi/shadowdown.png index 0e78f86e6..d4e0b2110 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/shadowdown.png and b/TMessagesProj/src/main/res/drawable-xhdpi/shadowdown.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/share.png b/TMessagesProj/src/main/res/drawable-xhdpi/share.png index d554570d9..f1fd91198 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/share.png and b/TMessagesProj/src/main/res/drawable-xhdpi/share.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/share_arrow.png b/TMessagesProj/src/main/res/drawable-xhdpi/share_arrow.png index 8fdb77f90..9d99475c5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/share_arrow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/share_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/share_round.png b/TMessagesProj/src/main/res/drawable-xhdpi/share_round.png index 78cf5a523..15dfc70fd 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/share_round.png and b/TMessagesProj/src/main/res/drawable-xhdpi/share_round.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/sheet_shadow.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/sheet_shadow.9.png index 171a4d54e..88effafa6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/sheet_shadow.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/sheet_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/sheet_shadow_round.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/sheet_shadow_round.9.png new file mode 100644 index 000000000..10ad2eb90 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/sheet_shadow_round.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/shortcut_compose.png b/TMessagesProj/src/main/res/drawable-xhdpi/shortcut_compose.png index 3cc65ac94..f8ea596a4 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/shortcut_compose.png and b/TMessagesProj/src/main/res/drawable-xhdpi/shortcut_compose.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/shortcut_user.png b/TMessagesProj/src/main/res/drawable-xhdpi/shortcut_user.png index 1261b387a..c5d07b2fc 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/shortcut_user.png and b/TMessagesProj/src/main/res/drawable-xhdpi/shortcut_user.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/slide_dot_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/slide_dot_big.png index e73a8fc44..6722e128b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/slide_dot_big.png and b/TMessagesProj/src/main/res/drawable-xhdpi/slide_dot_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/slide_dot_small.png b/TMessagesProj/src/main/res/drawable-xhdpi/slide_dot_small.png index 0ee66007c..0e055d07e 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/slide_dot_small.png and b/TMessagesProj/src/main/res/drawable-xhdpi/slide_dot_small.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/slidearrow.png b/TMessagesProj/src/main/res/drawable-xhdpi/slidearrow.png index aea2017d6..0ac9da10a 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/slidearrow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/slidearrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smallanimationpin.png b/TMessagesProj/src/main/res/drawable-xhdpi/smallanimationpin.png index bfff907ec..f59f20fe2 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/smallanimationpin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/smallanimationpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smallanimationpinleft.png b/TMessagesProj/src/main/res/drawable-xhdpi/smallanimationpinleft.png index 942a637e0..84b09f43b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/smallanimationpinleft.png and b/TMessagesProj/src/main/res/drawable-xhdpi/smallanimationpinleft.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smallanimationpinright.png b/TMessagesProj/src/main/res/drawable-xhdpi/smallanimationpinright.png index 152dcd904..3cb7f387d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/smallanimationpinright.png and b/TMessagesProj/src/main/res/drawable-xhdpi/smallanimationpinright.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_info.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_info.png new file mode 100644 index 000000000..0122cde8d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_info.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_inputsearch.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_inputsearch.png new file mode 100644 index 000000000..4542002de Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_inputsearch.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_activities.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_activities.png new file mode 100644 index 000000000..ebde0fc1f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_activities.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_cat.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_cat.png new file mode 100644 index 000000000..d6f058c27 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_cat.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_faves.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_faves.png new file mode 100644 index 000000000..7d3018593 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_faves.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_flags.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_flags.png new file mode 100644 index 000000000..cd5275a38 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_flags.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_food.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_food.png new file mode 100644 index 000000000..ab3802e3b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_food.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_objects.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_objects.png new file mode 100644 index 000000000..9432129ac Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_objects.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_other.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_other.png new file mode 100644 index 000000000..591e9f77f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_other.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_question.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_question.png new file mode 100644 index 000000000..befe68b70 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_question.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_recent.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_recent.png new file mode 100644 index 000000000..16948d3a9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_recent.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_smiles.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_smiles.png new file mode 100644 index 000000000..598d23514 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_smiles.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_travel.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_travel.png new file mode 100644 index 000000000..f0fb87289 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_travel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_trending.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_trending.png new file mode 100644 index 000000000..2219e1152 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_panel_trending.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_popup.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_popup.9.png index 29d4408eb..16fcf7375 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_popup.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_popup.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_clear.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_clear.png new file mode 100644 index 000000000..2ce9720fc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_gif.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_gif.png new file mode 100644 index 000000000..50f26249f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_search.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_search.png new file mode 100644 index 000000000..00c85ae61 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_settings.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_settings.png new file mode 100644 index 000000000..9d1e7f7ac Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_smiles.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_smiles.png new file mode 100644 index 000000000..2f3860a2a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_smiles.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_stickers.png b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_stickers.png new file mode 100644 index 000000000..7b1ca5c0d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/smiles_tab_stickers.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/sms_bubble.png b/TMessagesProj/src/main/res/drawable-xhdpi/sms_bubble.png index f8cb3c792..7caa30f08 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/sms_bubble.png and b/TMessagesProj/src/main/res/drawable-xhdpi/sms_bubble.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/sms_code.png b/TMessagesProj/src/main/res/drawable-xhdpi/sms_code.png index 5ab546c94..bd05dfd4b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/sms_code.png and b/TMessagesProj/src/main/res/drawable-xhdpi/sms_code.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/sms_devices.png b/TMessagesProj/src/main/res/drawable-xhdpi/sms_devices.png index f6d6f72aa..32988b506 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/sms_devices.png and b/TMessagesProj/src/main/res/drawable-xhdpi/sms_devices.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/staredstickerstab.png b/TMessagesProj/src/main/res/drawable-xhdpi/staredstickerstab.png deleted file mode 100644 index 87a733dfd..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/staredstickerstab.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/sticker_added.png b/TMessagesProj/src/main/res/drawable-xhdpi/sticker_added.png index 1a7b78370..31b788272 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/sticker_added.png and b/TMessagesProj/src/main/res/drawable-xhdpi/sticker_added.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/sticker_search.png b/TMessagesProj/src/main/res/drawable-xhdpi/sticker_search.png deleted file mode 100644 index 9708d0811..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/sticker_search.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_all.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_all.9.png index 6a05a79f5..15445807d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_all.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_all.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_arrow.png b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_arrow.png index 4579d546a..c04972bf0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_arrow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_center.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_center.9.png index a88308f6c..8eb589f0a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_center.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_center.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_left.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_left.9.png index 4f73f707d..cd0589ea5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_left.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_left.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_right.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_right.9.png index 5d29b580b..ffeea3fce 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_right.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_back_right.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_empty.png b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_empty.png new file mode 100644 index 000000000..deb4544e0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_empty.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_favorite.png b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_favorite.png deleted file mode 100644 index aaae6b242..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_favorite.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_none.png b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_none.png deleted file mode 100644 index 09de1a0e0..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_none.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_pack.png b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_pack.png deleted file mode 100644 index 6827906fc..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_pack.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_send.png b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_send.png deleted file mode 100644 index 610c10da2..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_send.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_unfavorite.png b/TMessagesProj/src/main/res/drawable-xhdpi/stickers_unfavorite.png deleted file mode 100644 index 86963b6a4..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/stickers_unfavorite.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/stickersclose.png b/TMessagesProj/src/main/res/drawable-xhdpi/stickersclose.png index ad4fa51aa..9bcc6b78f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/stickersclose.png and b/TMessagesProj/src/main/res/drawable-xhdpi/stickersclose.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/stickerset_close.png b/TMessagesProj/src/main/res/drawable-xhdpi/stickerset_close.png index 59e2b6898..8948363fa 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/stickerset_close.png and b/TMessagesProj/src/main/res/drawable-xhdpi/stickerset_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/switch_to_on1.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/switch_to_on1.9.png index 5146dde2b..f55292d7b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/switch_to_on1.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/switch_to_on1.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/switch_to_on2.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/switch_to_on2.9.png index 5146dde2b..f55292d7b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/switch_to_on2.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/switch_to_on2.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/switch_track.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/switch_track.9.png index fd47f15e4..2431e83db 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/switch_track.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/switch_track.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/system.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/system.9.png index 2d50ef794..16e955bb6 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/system.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/system.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/system_loader.png b/TMessagesProj/src/main/res/drawable-xhdpi/system_loader.png index fe0a9e49d..71485eb94 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/system_loader.png and b/TMessagesProj/src/main/res/drawable-xhdpi/system_loader.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/theme_picker.png b/TMessagesProj/src/main/res/drawable-xhdpi/theme_picker.png index d1c3618e7..8691a848c 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/theme_picker.png and b/TMessagesProj/src/main/res/drawable-xhdpi/theme_picker.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/tip1.png b/TMessagesProj/src/main/res/drawable-xhdpi/tip1.png index 98934f271..3a34cf1f7 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/tip1.png and b/TMessagesProj/src/main/res/drawable-xhdpi/tip1.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/tip2.png b/TMessagesProj/src/main/res/drawable-xhdpi/tip2.png index 8fb813f92..ab20a4a95 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/tip2.png and b/TMessagesProj/src/main/res/drawable-xhdpi/tip2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/tip3.png b/TMessagesProj/src/main/res/drawable-xhdpi/tip3.png index 4f128e892..eda99d1d1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/tip3.png and b/TMessagesProj/src/main/res/drawable-xhdpi/tip3.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/tip4.png b/TMessagesProj/src/main/res/drawable-xhdpi/tip4.png index e27f791d8..d056ef847 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/tip4.png and b/TMessagesProj/src/main/res/drawable-xhdpi/tip4.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/tool_blur.png b/TMessagesProj/src/main/res/drawable-xhdpi/tool_blur.png index 35aa4a801..b4b1325d2 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/tool_blur.png and b/TMessagesProj/src/main/res/drawable-xhdpi/tool_blur.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/tool_cropfix.png b/TMessagesProj/src/main/res/drawable-xhdpi/tool_cropfix.png index 5b3c7682c..6924f2191 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/tool_cropfix.png and b/TMessagesProj/src/main/res/drawable-xhdpi/tool_cropfix.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/tool_curve.png b/TMessagesProj/src/main/res/drawable-xhdpi/tool_curve.png index afd39fc85..7e5570a17 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/tool_curve.png and b/TMessagesProj/src/main/res/drawable-xhdpi/tool_curve.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/tool_rotate.png b/TMessagesProj/src/main/res/drawable-xhdpi/tool_rotate.png index 9eaec36d0..dfd271d37 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/tool_rotate.png and b/TMessagesProj/src/main/res/drawable-xhdpi/tool_rotate.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/tooltip_arrow.png b/TMessagesProj/src/main/res/drawable-xhdpi/tooltip_arrow.png index c6fc8bacd..47589b4cc 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/tooltip_arrow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/tooltip_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/tooltip_arrow_up.png b/TMessagesProj/src/main/res/drawable-xhdpi/tooltip_arrow_up.png new file mode 100644 index 000000000..7ebf25f78 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/tooltip_arrow_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/tooltip_sound.png b/TMessagesProj/src/main/res/drawable-xhdpi/tooltip_sound.png index a120bba45..635185cf4 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/tooltip_sound.png and b/TMessagesProj/src/main/res/drawable-xhdpi/tooltip_sound.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/update.png b/TMessagesProj/src/main/res/drawable-xhdpi/update.png index 069c31dfe..40d983c01 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/update.png and b/TMessagesProj/src/main/res/drawable-xhdpi/update.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/usersearch.png b/TMessagesProj/src/main/res/drawable-xhdpi/usersearch.png deleted file mode 100644 index 4553ae5c9..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/usersearch.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/verified_area.png b/TMessagesProj/src/main/res/drawable-xhdpi/verified_area.png old mode 100755 new mode 100644 index 11c954ab8..6d66492dd Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/verified_area.png and b/TMessagesProj/src/main/res/drawable-xhdpi/verified_area.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/verified_check.png b/TMessagesProj/src/main/res/drawable-xhdpi/verified_check.png old mode 100755 new mode 100644 index aa22dc8ce..bd3a93182 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/verified_check.png and b/TMessagesProj/src/main/res/drawable-xhdpi/verified_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/video_1080.png b/TMessagesProj/src/main/res/drawable-xhdpi/video_1080.png index 210f681f8..424d9c3dc 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/video_1080.png and b/TMessagesProj/src/main/res/drawable-xhdpi/video_1080.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/video_240.png b/TMessagesProj/src/main/res/drawable-xhdpi/video_240.png index 5cc634a7a..279ba5ac3 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/video_240.png and b/TMessagesProj/src/main/res/drawable-xhdpi/video_240.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/video_360.png b/TMessagesProj/src/main/res/drawable-xhdpi/video_360.png index 359b00d2e..f299d3d52 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/video_360.png and b/TMessagesProj/src/main/res/drawable-xhdpi/video_360.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/video_480.png b/TMessagesProj/src/main/res/drawable-xhdpi/video_480.png index 7c226d6af..dd565104c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/video_480.png and b/TMessagesProj/src/main/res/drawable-xhdpi/video_480.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/video_720.png b/TMessagesProj/src/main/res/drawable-xhdpi/video_720.png index 1231ca0e6..326653342 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/video_720.png and b/TMessagesProj/src/main/res/drawable-xhdpi/video_720.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/video_actions.png b/TMessagesProj/src/main/res/drawable-xhdpi/video_actions.png index f692c3008..4477e83ce 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/video_actions.png and b/TMessagesProj/src/main/res/drawable-xhdpi/video_actions.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/video_cropleft.png b/TMessagesProj/src/main/res/drawable-xhdpi/video_cropleft.png index 7a6ccf247..e219cc02f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/video_cropleft.png and b/TMessagesProj/src/main/res/drawable-xhdpi/video_cropleft.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/video_cropright.png b/TMessagesProj/src/main/res/drawable-xhdpi/video_cropright.png index 4b314d88c..755dbbf4e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/video_cropright.png and b/TMessagesProj/src/main/res/drawable-xhdpi/video_cropright.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/video_mini_arrow.png b/TMessagesProj/src/main/res/drawable-xhdpi/video_mini_arrow.png index bc4fec176..786559698 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/video_mini_arrow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/video_mini_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/video_mini_cancel.png b/TMessagesProj/src/main/res/drawable-xhdpi/video_mini_cancel.png index 1fec833f9..9f9e3c55a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/video_mini_cancel.png and b/TMessagesProj/src/main/res/drawable-xhdpi/video_mini_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/video_mute.png b/TMessagesProj/src/main/res/drawable-xhdpi/video_mute.png index dc8d33ce8..a2730cb87 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/video_mute.png and b/TMessagesProj/src/main/res/drawable-xhdpi/video_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/video_muted.png b/TMessagesProj/src/main/res/drawable-xhdpi/video_muted.png index 5fcc6b0ed..0a0c7173e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/video_muted.png and b/TMessagesProj/src/main/res/drawable-xhdpi/video_muted.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/video_pip.png b/TMessagesProj/src/main/res/drawable-xhdpi/video_pip.png index 1000802e2..ff36b5594 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/video_pip.png and b/TMessagesProj/src/main/res/drawable-xhdpi/video_pip.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/video_png.png b/TMessagesProj/src/main/res/drawable-xhdpi/video_png.png index 9a623817e..0aaff8b51 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/video_png.png and b/TMessagesProj/src/main/res/drawable-xhdpi/video_png.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/voice2x.png b/TMessagesProj/src/main/res/drawable-xhdpi/voice2x.png index 6fc20bf54..7fecad22b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/voice2x.png and b/TMessagesProj/src/main/res/drawable-xhdpi/voice2x.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/volume_off.png b/TMessagesProj/src/main/res/drawable-xhdpi/volume_off.png index 3282f8318..f26649271 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/volume_off.png and b/TMessagesProj/src/main/res/drawable-xhdpi/volume_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/volume_on.png b/TMessagesProj/src/main/res/drawable-xhdpi/volume_on.png index 8bd76be8a..06f7a4a2d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/volume_on.png and b/TMessagesProj/src/main/res/drawable-xhdpi/volume_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/wall_selection.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/wall_selection.9.png index 8b4e52cd7..e83fd2dea 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/wall_selection.9.png and b/TMessagesProj/src/main/res/drawable-xhdpi/wall_selection.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ab_progress.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ab_progress.png index 12c682cff..7e5f8b3f3 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ab_progress.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ab_progress.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/account_add.png b/TMessagesProj/src/main/res/drawable-xxhdpi/account_add.png index 08c1dcb90..0cb639a26 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/account_add.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/account_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/account_check.png b/TMessagesProj/src/main/res/drawable-xxhdpi/account_check.png index e1d4d19d1..5d57b4e13 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/account_check.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/account_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/actions_addadmin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/actions_addadmin.png index 95bbcf9b3..84875dc93 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/actions_addadmin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/actions_addadmin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/actions_addmember2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/actions_addmember2.png index 6dc569cb9..678aad3e2 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/actions_addmember2.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/actions_addmember2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/actions_permissions.png b/TMessagesProj/src/main/res/drawable-xxhdpi/actions_permissions.png index 3b8f6f1cf..7e4df186a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/actions_permissions.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/actions_permissions.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/actions_remove_user.png b/TMessagesProj/src/main/res/drawable-xxhdpi/actions_remove_user.png index e3273d4ea..b20972567 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/actions_remove_user.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/actions_remove_user.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/actions_removed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/actions_removed.png index afcf22fb6..c5a5b1929 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/actions_removed.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/actions_removed.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/actions_setphoto.png b/TMessagesProj/src/main/res/drawable-xxhdpi/actions_setphoto.png index ddfd79d4d..4317f120b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/actions_setphoto.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/actions_setphoto.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/actions_viewmembers.png b/TMessagesProj/src/main/res/drawable-xxhdpi/actions_viewmembers.png index 75bc934db..0b8136cca 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/actions_viewmembers.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/actions_viewmembers.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/add.png b/TMessagesProj/src/main/res/drawable-xxhdpi/add.png index 341c741be..e46e85e74 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/add.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/add_admin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/add_admin.png index 718a0d35b..9f293e5c0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/add_admin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/add_admin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/add_contact_new.png b/TMessagesProj/src/main/res/drawable-xxhdpi/add_contact_new.png index 5439b7546..9788a4af0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/add_contact_new.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/add_contact_new.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/animationpin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/animationpin.png index 297b098a0..0bb3df962 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/animationpin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/animationpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/animationpinleft.png b/TMessagesProj/src/main/res/drawable-xxhdpi/animationpinleft.png index ee4a43340..9d6b300ab 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/animationpinleft.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/animationpinleft.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/animationpinright.png b/TMessagesProj/src/main/res/drawable-xxhdpi/animationpinright.png index 5294ef3be..166b7ae9d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/animationpinright.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/animationpinright.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_audio.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_audio.png index 6a0013432..d58489eb3 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_audio.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_audio.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_close.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_close.png index 5cc06b85b..15c79490d 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_close.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_contact.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_contact.png index 5a9bd0134..84a1836b6 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_contact.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_contact.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_file.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_file.png index b090113d7..03d328637 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_file.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_file.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_gallery.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_gallery.png index d875e6391..4c095bf1c 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_gallery.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_gallery.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_location.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_location.png index b86544387..12e9999a3 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_location.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_polls.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_polls.png index cf0a476a8..ae401f903 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_polls.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_polls.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_send.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_send.png old mode 100755 new mode 100644 index 421503df6..b18849f06 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_send.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_send.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_video.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_video.png index b602df77e..8a702e311 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_video.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/audio_mini_arrow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/audio_mini_arrow.png index 836023f42..2a9d3bb9a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/audio_mini_arrow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/audio_mini_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/audio_mini_cancel.png b/TMessagesProj/src/main/res/drawable-xxhdpi/audio_mini_cancel.png index dc5325015..f4a65655e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/audio_mini_cancel.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/audio_mini_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_pause.png b/TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_pause.png index a7beb78c0..14b792e66 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_pause.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_play.png b/TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_play.png index b4362fa07..5432a7d05 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_play.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/authorize.png b/TMessagesProj/src/main/res/drawable-xxhdpi/authorize.png index 8db89ae8d..a772af792 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/authorize.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/authorize.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/background_hd.jpg b/TMessagesProj/src/main/res/drawable-xxhdpi/background_hd.jpg old mode 100755 new mode 100644 index 46351c313..022fb0010 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/background_hd.jpg and b/TMessagesProj/src/main/res/drawable-xxhdpi/background_hd.jpg differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/background_selected.png b/TMessagesProj/src/main/res/drawable-xxhdpi/background_selected.png index 7d0f2b22c..18ba8befc 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/background_selected.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/background_selected.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/bigcheck.png b/TMessagesProj/src/main/res/drawable-xxhdpi/bigcheck.png index 0189c773d..9037d1292 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/bigcheck.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/bigcheck.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/blockpanel.png b/TMessagesProj/src/main/res/drawable-xxhdpi/blockpanel.png index cad6be169..6969029bc 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/blockpanel.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/blockpanel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/bluecounter.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/bluecounter.9.png index 113537b7f..4894fb1ce 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/bluecounter.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/bluecounter.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/blur_linear.png b/TMessagesProj/src/main/res/drawable-xxhdpi/blur_linear.png index 2536335bd..036b5b48d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/blur_linear.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/blur_linear.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/blur_off.png b/TMessagesProj/src/main/res/drawable-xxhdpi/blur_off.png index 6f467b2c9..859c72e62 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/blur_off.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/blur_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/blur_radial.png b/TMessagesProj/src/main/res/drawable-xxhdpi/blur_radial.png index 6a025fd43..96cfe3cae 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/blur_radial.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/blur_radial.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/book_bot.png b/TMessagesProj/src/main/res/drawable-xxhdpi/book_bot.png index eb3cec411..d79a6e2c0 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/book_bot.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/book_bot.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/book_channel.png b/TMessagesProj/src/main/res/drawable-xxhdpi/book_channel.png index dd04a6844..e41b73e4f 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/book_channel.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/book_channel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/book_group.png b/TMessagesProj/src/main/res/drawable-xxhdpi/book_group.png index cc64fc758..a8740e7f9 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/book_group.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/book_group.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/book_logo.png b/TMessagesProj/src/main/res/drawable-xxhdpi/book_logo.png index ebe816fdf..71d8bbd1b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/book_logo.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/book_logo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/book_user.png b/TMessagesProj/src/main/res/drawable-xxhdpi/book_user.png index 2f54d6b5e..2a7f32edb 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/book_user.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/book_user.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/bookmark_large.png b/TMessagesProj/src/main/res/drawable-xxhdpi/bookmark_large.png deleted file mode 100755 index 3717f7a4e..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/bookmark_large.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/bot_file.png b/TMessagesProj/src/main/res/drawable-xxhdpi/bot_file.png index 9cd059b8c..e0c8100fb 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/bot_file.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/bot_file.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/bot_keyboard.png b/TMessagesProj/src/main/res/drawable-xxhdpi/bot_keyboard.png deleted file mode 100755 index f57e1bc6e..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/bot_keyboard.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/bot_keyboard2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/bot_keyboard2.png deleted file mode 100755 index 7991e46a6..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/bot_keyboard2.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/bot_lines.png b/TMessagesProj/src/main/res/drawable-xxhdpi/bot_lines.png index e5d26151c..d86bb4d58 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/bot_lines.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/bot_lines.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/bot_link.png b/TMessagesProj/src/main/res/drawable-xxhdpi/bot_link.png index 411dc89d8..5567f21fc 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/bot_link.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/bot_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/bot_location.png b/TMessagesProj/src/main/res/drawable-xxhdpi/bot_location.png index 21652a6bd..4caf33ffb 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/bot_location.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/bot_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/bot_music.png b/TMessagesProj/src/main/res/drawable-xxhdpi/bot_music.png index ce6c20adc..55b83ab32 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/bot_music.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/bot_music.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/bottom_shadow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/bottom_shadow.png index 36ba70346..88f60b6b4 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/bottom_shadow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/bottom_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/boxshadow.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/boxshadow.9.png index 8226d849e..dffa79d93 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/boxshadow.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/boxshadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/brightness_low.png b/TMessagesProj/src/main/res/drawable-xxhdpi/brightness_low.png index ca4c80fb8..6c3399960 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/brightness_low.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/brightness_low.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/broadcast3.png b/TMessagesProj/src/main/res/drawable-xxhdpi/broadcast3.png index a4fca0864..1e8186eae 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/broadcast3.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/broadcast3.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/broadcast_w.png b/TMessagesProj/src/main/res/drawable-xxhdpi/broadcast_w.png index c60de471f..7fbd57692 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/broadcast_w.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/broadcast_w.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/btnshadow.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/btnshadow.9.png index f74d3632c..5ea8dd6c8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/btnshadow.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/btnshadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/burn.png b/TMessagesProj/src/main/res/drawable-xxhdpi/burn.png index 6a83e3584..68a0c8448 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/burn.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/burn.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/camera_btn.png b/TMessagesProj/src/main/res/drawable-xxhdpi/camera_btn.png index f3f7fb5f3..6feb1980f 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/camera_btn.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/camera_btn.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/camera_revert1.png b/TMessagesProj/src/main/res/drawable-xxhdpi/camera_revert1.png index dcb2eadb2..15bf82a88 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/camera_revert1.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/camera_revert1.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/camera_revert2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/camera_revert2.png index ecc98126d..c2de28787 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/camera_revert2.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/camera_revert2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/cancel_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/cancel_big.png index 96a6c3d71..1a70ac3a5 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/cancel_big.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/cancel_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/channelintro.png b/TMessagesProj/src/main/res/drawable-xxhdpi/channelintro.png index 22d7c01c3..d2497f091 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/channelintro.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/channelintro.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive.png b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive.png new file mode 100644 index 000000000..db61101fb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_arrow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_arrow.png new file mode 100644 index 000000000..eb10ec4c1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_box.png b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_box.png new file mode 100644 index 000000000..c69bd87d7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_box.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_hide.png b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_hide.png new file mode 100644 index 000000000..54b725074 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_hide.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_muted.png b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_muted.png new file mode 100644 index 000000000..ca2eb6842 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_muted.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 new file mode 100644 index 000000000..0c1fe3fab Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_show.png b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_show.png new file mode 100644 index 000000000..772967cda Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_archive_show.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_clear.png b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_clear.png deleted file mode 100644 index 1758a6dfd..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_clear.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_delete.png b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_delete.png index b2d058141..c2b5ff666 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_delete.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_leave.png b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_leave.png index c08aa1647..f8e1fd83c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_leave.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_leave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_pin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_pin.png index 24da0fd96..809da046f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_pin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_saved.png b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_saved.png new file mode 100644 index 000000000..3c63044e7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_saved.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_unarchive.png b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_unarchive.png new file mode 100644 index 000000000..f1533b3c4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_unarchive.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_undo.png b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_undo.png index e0dd767a5..7a6c33b2c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_undo.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_undo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_unpin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_unpin.png index 9aeeae167..5f9fa7f8c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/chats_unpin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/chats_unpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/checkbig.png b/TMessagesProj/src/main/res/drawable-xxhdpi/checkbig.png index ad8ff9d03..bd2a9c9d6 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/checkbig.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/checkbig.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/circle.png b/TMessagesProj/src/main/res/drawable-xxhdpi/circle.png index 931ced169..36f9bc014 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/circle.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/circle.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/circle_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/circle_big.png index 8b0cd9fd1..1758453d9 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/circle_big.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/circle_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/cloud_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/cloud_big.png index deceb2a07..c53446bc0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/cloud_big.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/cloud_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/collapse_down.png b/TMessagesProj/src/main/res/drawable-xxhdpi/collapse_down.png index 03cab3f07..aeb4b3c7f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/collapse_down.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/collapse_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/collapse_up.png b/TMessagesProj/src/main/res/drawable-xxhdpi/collapse_up.png index 479d2adb0..11a8202c8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/collapse_up.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/collapse_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/compose_panel_shadow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/compose_panel_shadow.png index a84e83515..b68077ec1 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/compose_panel_shadow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/compose_panel_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/contacts_sort_name.png b/TMessagesProj/src/main/res/drawable-xxhdpi/contacts_sort_name.png index 9996f996f..4e4d64ce6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/contacts_sort_name.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/contacts_sort_name.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/contacts_sort_time.png b/TMessagesProj/src/main/res/drawable-xxhdpi/contacts_sort_time.png index 1586f79cf..63663ca99 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/contacts_sort_time.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/contacts_sort_time.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/corner_in_bl.png b/TMessagesProj/src/main/res/drawable-xxhdpi/corner_in_bl.png index 4d8ff724e..ff9cce560 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/corner_in_bl.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/corner_in_bl.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/corner_in_br.png b/TMessagesProj/src/main/res/drawable-xxhdpi/corner_in_br.png index b7e7f208c..0ea1e3263 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/corner_in_br.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/corner_in_br.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/corner_in_tl.png b/TMessagesProj/src/main/res/drawable-xxhdpi/corner_in_tl.png index cec5eed9a..5aabc50f5 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/corner_in_tl.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/corner_in_tl.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/corner_in_tr.png b/TMessagesProj/src/main/res/drawable-xxhdpi/corner_in_tr.png index 20fd7f930..87bbb3b08 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/corner_in_tr.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/corner_in_tr.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/corner_out_bl.png b/TMessagesProj/src/main/res/drawable-xxhdpi/corner_out_bl.png index 80cbf39fb..7e9f321e8 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/corner_out_bl.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/corner_out_bl.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/corner_out_br.png b/TMessagesProj/src/main/res/drawable-xxhdpi/corner_out_br.png index 4bdd87d12..3706b2b6d 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/corner_out_br.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/corner_out_br.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/corner_out_tl.png b/TMessagesProj/src/main/res/drawable-xxhdpi/corner_out_tl.png index 848917112..f8044c90b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/corner_out_tl.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/corner_out_tl.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/corner_out_tr.png b/TMessagesProj/src/main/res/drawable-xxhdpi/corner_out_tr.png index 4d631fa89..76a6a50e1 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/corner_out_tr.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/corner_out_tr.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/delete.png b/TMessagesProj/src/main/res/drawable-xxhdpi/delete.png index 6c87bf139..c0fe41e84 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/delete.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/devices.png b/TMessagesProj/src/main/res/drawable-xxhdpi/devices.png index e767cc0f2..cdb923ead 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/devices.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/devices.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/doc_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/doc_big.png index 4fe1a5013..c3bf5624b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/doc_big.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/doc_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/edit_cancel.png b/TMessagesProj/src/main/res/drawable-xxhdpi/edit_cancel.png index d050523b7..582ab81b3 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/edit_cancel.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/edit_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/edit_done.png b/TMessagesProj/src/main/res/drawable-xxhdpi/edit_done.png deleted file mode 100755 index a1efc36a6..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/edit_done.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/fast_reply.png b/TMessagesProj/src/main/res/drawable-xxhdpi/fast_reply.png index b507aa45e..e3153a20f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/fast_reply.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/fast_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/flame_small.png b/TMessagesProj/src/main/res/drawable-xxhdpi/flame_small.png index 7d0263826..f7a2fd0d3 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/flame_small.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/flame_small.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/flash_auto.png b/TMessagesProj/src/main/res/drawable-xxhdpi/flash_auto.png index ca058eb80..6d2fcf4d6 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/flash_auto.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/flash_auto.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/flash_off.png b/TMessagesProj/src/main/res/drawable-xxhdpi/flash_off.png index e6658228b..20b766592 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/flash_off.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/flash_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/flash_on.png b/TMessagesProj/src/main/res/drawable-xxhdpi/flash_on.png index f6801e2f0..2ad4fab6a 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/flash_on.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/flash_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/floating_camera.png b/TMessagesProj/src/main/res/drawable-xxhdpi/floating_camera.png index fbb08d565..15527a17a 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/floating_camera.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/floating_camera.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/floating_message.png b/TMessagesProj/src/main/res/drawable-xxhdpi/floating_message.png index 0bb02efaa..823de6d2c 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/floating_message.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/floating_message.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/floating_pencil.png b/TMessagesProj/src/main/res/drawable-xxhdpi/floating_pencil.png index a93db5735..9f4ff2913 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/floating_pencil.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/floating_pencil.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/floating_shadow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/floating_shadow.png index e69ef7e24..00aa8f0fe 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/floating_shadow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/floating_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/floating_shadow_profile.png b/TMessagesProj/src/main/res/drawable-xxhdpi/floating_shadow_profile.png index 9f1ffc94b..97bfe0792 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/floating_shadow_profile.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/floating_shadow_profile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/forwardvideo.png b/TMessagesProj/src/main/res/drawable-xxhdpi/forwardvideo.png index 217fa9d9b..497475c2f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/forwardvideo.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/forwardvideo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/foursquare.png b/TMessagesProj/src/main/res/drawable-xxhdpi/foursquare.png index baeaca21e..dd3ba4a4b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/foursquare.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/foursquare.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/gif_empty.png b/TMessagesProj/src/main/res/drawable-xxhdpi/gif_empty.png new file mode 100644 index 000000000..6c564b159 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/gif_empty.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/go_to_message.png b/TMessagesProj/src/main/res/drawable-xxhdpi/go_to_message.png deleted file mode 100644 index 7e5c5443a..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/go_to_message.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/greydivider.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/greydivider.9.png index 9187b2f82..79ab4239d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/greydivider.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/greydivider.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/greydivider_bottom.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/greydivider_bottom.9.png index 16340de4c..81d91e468 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/greydivider_bottom.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/greydivider_bottom.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/greydivider_top.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/greydivider_top.9.png index 411d33d96..fb2a7c198 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/greydivider_top.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/greydivider_top.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/group_addmember.png b/TMessagesProj/src/main/res/drawable-xxhdpi/group_addmember.png index aa0a34feb..26af28913 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/group_addmember.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/group_addmember.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/group_admin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/group_admin.png index 1632432e2..7600b6a8d 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/group_admin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/group_admin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/group_admin_new.png b/TMessagesProj/src/main/res/drawable-xxhdpi/group_admin_new.png index afb3f6489..995a899ea 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/group_admin_new.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/group_admin_new.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/group_ban_empty.png b/TMessagesProj/src/main/res/drawable-xxhdpi/group_ban_empty.png index 68bb80d70..243c0c1c7 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/group_ban_empty.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/group_ban_empty.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/group_ban_new.png b/TMessagesProj/src/main/res/drawable-xxhdpi/group_ban_new.png index 4a999047d..c0341a918 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/group_ban_new.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/group_ban_new.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/group_banned.png b/TMessagesProj/src/main/res/drawable-xxhdpi/group_banned.png index 808379e96..850d04a60 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/group_banned.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/group_banned.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/group_edit.png b/TMessagesProj/src/main/res/drawable-xxhdpi/group_edit.png index da1949f1d..6227d159f 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/group_edit.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/group_edit.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/group_edit_profile.png b/TMessagesProj/src/main/res/drawable-xxhdpi/group_edit_profile.png index 279ab9b0a..d93916f7d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/group_edit_profile.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/group_edit_profile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/group_log.png b/TMessagesProj/src/main/res/drawable-xxhdpi/group_log.png index 1a81cb7f7..bc0f3e332 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/group_log.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/group_log.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/groups_overview_check.png b/TMessagesProj/src/main/res/drawable-xxhdpi/groups_overview_check.png index 50ff1e5a7..f18a14736 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/groups_overview_check.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/groups_overview_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/header_shadow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/header_shadow.png index 382af9c50..3d050fb4c 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/header_shadow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/header_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/header_shadow_reverse.png b/TMessagesProj/src/main/res/drawable-xxhdpi/header_shadow_reverse.png index 3d39b80a1..7bec68540 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/header_shadow_reverse.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/header_shadow_reverse.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_attach.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_attach.png deleted file mode 100755 index 22fca80de..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_attach.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_back.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_back.png index 4057cc545..298a4e7d0 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_back.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_back.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_copy.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_copy.png index a9129dd51..ce0fea9d7 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_copy.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_copy.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_delete.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_delete.png index b51e9267d..a592de0b4 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_delete.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_done.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_done.png index 25c54ef75..a9bf7033d 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_done.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_done.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_fave.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_fave.png index 092c4bc5e..98d15d2cc 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_fave.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_fave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_forward.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_forward.png index 22b3daf30..70ae5956e 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_forward.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_new.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_new.png index 0c668fdc8..8c46f766f 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_new.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_new.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_other.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_other.png index 2955c02ec..b50b233b2 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_other.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_other.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_reply.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_reply.png index 2e74dd013..91e09cf20 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_reply.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_reply2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_reply2.png index dab2c5376..9fc10fd79 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_reply2.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_reply2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_search.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_search.png index 0bbeab150..cf64be0fe 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_search.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_unfave.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_unfave.png index ee5eacbd7..809f50ae4 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_unfave.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_unfave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_again.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_again.png index 8164863e5..90b1605ae 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_again.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_again.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_againinline.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_againinline.png index 781e2e871..23adf4741 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_againinline.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_againinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_arrow_drop_down.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_arrow_drop_down.png index 8127958a1..3a3d9ddff 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_arrow_drop_down.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_arrow_drop_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_bluetooth_white_24dp.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_bluetooth_white_24dp.png index 860c75864..caf98cce3 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_bluetooth_white_24dp.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_bluetooth_white_24dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call.png new file mode 100644 index 000000000..0423cbb9e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_made_green_18dp.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_made_green_18dp.png index 14b481cf6..5267f2c8b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_made_green_18dp.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_made_green_18dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_received_green_18dp.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_received_green_18dp.png index a290ac319..853e81400 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_received_green_18dp.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_received_green_18dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_white_24dp.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_white_24dp.png deleted file mode 100755 index d9d2b8770..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_call_white_24dp.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_close_white.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_close_white.png index 0eb9d8b08..e970d1507 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_close_white.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_close_white.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_directory.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_directory.png index 2254d8106..59d424bd7 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_directory.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_directory.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_done.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_done.png index f801e7ab3..a9bf7033d 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_done.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_done.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_external_storage.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_external_storage.png index dc7764cb9..84423a873 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_external_storage.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_external_storage.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_fp_40px.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_fp_40px.png index f7e87240e..1f183bd32 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_fp_40px.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_fp_40px.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_gallery_background.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_gallery_background.png index dd3e553b0..7621b782f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_gallery_background.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_gallery_background.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_gofullscreen.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_gofullscreen.png index 4a501c587..9bd2d91bd 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_gofullscreen.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_gofullscreen.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_goinline.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_goinline.png index c8e966132..b6f983a04 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_goinline.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_goinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_keyboard_w.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_keyboard_w.png deleted file mode 100755 index f6bb99dc9..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_keyboard_w.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_launcher.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_launcher.png deleted file mode 100755 index 0fff9d390..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_launcher_dr.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_launcher_dr.png new file mode 100644 index 000000000..f84bd8f92 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_launcher_dr.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_lock_header.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_lock_header.png index 6e5af9ac7..3473bfbe3 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_lock_header.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_lock_header.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_lock_white.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_lock_white.png index 6767c995d..2b7039be8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_lock_white.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_lock_white.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_masks_msk1.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_masks_msk1.png index ddc0e1d29..e0e13cc20 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_masks_msk1.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_masks_msk1.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_masks_recent1.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_masks_recent1.png index 2c073103b..5b163f771 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_masks_recent1.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_masks_recent1.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_msg_panel_gif.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_msg_panel_gif.png deleted file mode 100755 index e09e84617..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_msg_panel_gif.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_msg_panel_kb.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_msg_panel_kb.png deleted file mode 100755 index e82bd3c21..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_msg_panel_kb.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_msg_panel_smiles.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_msg_panel_smiles.png deleted file mode 100755 index be0f86f02..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_msg_panel_smiles.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_msg_panel_stickers.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_msg_panel_stickers.png deleted file mode 100755 index f3a80f975..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_msg_panel_stickers.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_msg_panel_video.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_msg_panel_video.png deleted file mode 100755 index d8a957dc0..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_msg_panel_video.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_outfullscreen.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_outfullscreen.png index 28e150e19..09f640ac1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_outfullscreen.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_outfullscreen.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_outinline.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_outinline.png index de3c11021..0d2467dd2 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_outinline.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_outinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_pause.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_pause.png index 8167aee49..0ea19f552 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_pause.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_pauseinline.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_pauseinline.png index bb6504d7c..7192ad487 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_pauseinline.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_pauseinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_phone_in_talk_white_24dp.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_phone_in_talk_white_24dp.png index 9c002da0a..0fc1df1a7 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_phone_in_talk_white_24dp.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_phone_in_talk_white_24dp.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_play.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_play.png index ce34b24d8..d65cd2762 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_play.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_playinline.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_playinline.png index 5b0ed00f5..9ee7c9759 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_playinline.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_playinline.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_rating_star.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_rating_star.png index f70a7a949..806044e30 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_rating_star.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_rating_star.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_rating_star_filled.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_rating_star_filled.png index af437f9d0..2fa1e84b5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_rating_star_filled.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_rating_star_filled.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_send.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_send.png index 69c6f9978..a7bbf2c17 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_send.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_send.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_share_article.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_share_article.png index 1cbbb2615..d381401a1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_share_article.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_share_article.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_share_video.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_share_video.png index 6494c1755..b5a4d49a4 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_share_video.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_share_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smile_small.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smile_small.png deleted file mode 100644 index f9a5e3224..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smile_small.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smile_w.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smile_w.png deleted file mode 100755 index fd3453ebd..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smile_w.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_car.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_car.png deleted file mode 100755 index 3cbef4aa0..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_car.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_food.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_food.png deleted file mode 100755 index d0cbece34..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_food.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_nature.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_nature.png deleted file mode 100755 index 77f383561..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_nature.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_objects.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_objects.png deleted file mode 100755 index 34591ad86..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_objects.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_recent.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_recent.png deleted file mode 100755 index 2f83e451e..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_recent.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_sad.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_sad.png index 1a8217383..3ba6732a3 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_sad.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_sad.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_smile.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_smile.png deleted file mode 100755 index d1539aa1a..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_smile.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_stickers.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_stickers.png deleted file mode 100755 index 25a14e390..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles2_stickers.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles_backspace.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles_backspace.png deleted file mode 100755 index 15486e100..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles_backspace.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles_gif.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles_gif.png deleted file mode 100755 index 35d512420..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles_gif.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles_settings.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles_settings.png deleted file mode 100755 index 23e77a55f..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles_settings.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles_trend.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles_trend.png deleted file mode 100755 index dcf17cc42..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_smiles_trend.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_storage.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_storage.png index 7759760e6..d14a6e254 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_storage.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_storage.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_storage_gallery.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_storage_gallery.png index bdb863009..cc931d96b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_storage_gallery.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_storage_gallery.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_storage_music.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_storage_music.png index c00b06e04..3f3054726 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_storage_music.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_storage_music.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_video.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_video.png index 274af5e69..ed7aad862 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_video.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/inline_video_pause.png b/TMessagesProj/src/main/res/drawable-xxhdpi/inline_video_pause.png index 5016a920f..001ec7b25 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/inline_video_pause.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/inline_video_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/inline_video_play.png b/TMessagesProj/src/main/res/drawable-xxhdpi/inline_video_play.png index ef8b9cf6b..23c912620 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/inline_video_play.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/inline_video_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_attach.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_attach.png new file mode 100644 index 000000000..b942f3257 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_attach.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_bot1.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_bot1.png new file mode 100644 index 000000000..5c16f4055 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_bot1.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_bot2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_bot2.png new file mode 100644 index 000000000..c7dba6826 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_bot2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_clear.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_clear.png new file mode 100644 index 000000000..1ac7f70ce Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_done.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_done.png new file mode 100644 index 000000000..c0521ccf8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_done.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_forward.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_forward.png new file mode 100644 index 000000000..34f1658e1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_gif.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_gif.png new file mode 100644 index 000000000..94b26be2f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_keyboard.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_keyboard.png new file mode 100644 index 000000000..80b60a6cc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_keyboard.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_mic.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_mic.png new file mode 100644 index 000000000..f33e58f03 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_mic.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_notify_off.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_notify_off.png new file mode 100644 index 000000000..5382a1ea3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_notify_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_notify_on.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_notify_on.png new file mode 100644 index 000000000..7805424d4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_notify_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_reply.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_reply.png new file mode 100644 index 000000000..55142191e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_smile.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_smile.png new file mode 100644 index 000000000..230f180fd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_smile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_sticker.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_sticker.png new file mode 100644 index 000000000..ff305fcb3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_sticker.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/input_video.png b/TMessagesProj/src/main/res/drawable-xxhdpi/input_video.png new file mode 100644 index 000000000..d561fdca6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/input_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/instant_camera.png b/TMessagesProj/src/main/res/drawable-xxhdpi/instant_camera.png index 46d242be5..001b74c5a 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/instant_camera.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/instant_camera.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/instant_link.png b/TMessagesProj/src/main/res/drawable-xxhdpi/instant_link.png index ccef12f34..08a6b4515 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/instant_link.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/instant_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_fast_arrow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_fast_arrow.png index 75958e57b..49868c5b3 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_fast_arrow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_fast_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_fast_arrow_shadow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_fast_arrow_shadow.png index 1e800196f..dbd117d3f 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_fast_arrow_shadow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_fast_arrow_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_fast_body.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_fast_body.png index f73062d0e..b1088dedb 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_fast_body.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_fast_body.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_fast_spiral.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_fast_spiral.png index 47f84d686..d77b05dbd 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_fast_spiral.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_fast_spiral.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_bubble.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_bubble.png index 1703e622e..fd9491359 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_bubble.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_bubble.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_bubble_dot.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_bubble_dot.png index cd316642a..098adb917 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_bubble_dot.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_bubble_dot.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_cam.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_cam.png index 1cdd5de4f..1824a7473 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_cam.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_cam.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_cam_lens.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_cam_lens.png index 21255f1b1..17b6e3516 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_cam_lens.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_cam_lens.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_pencil.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_pencil.png index b85402d0b..543bd98d4 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_pencil.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_pencil.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_pin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_pin.png index 6548b487b..6127dfcb1 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_pin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_smile.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_smile.png index d51bcfb87..9c4133cba 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_smile.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_smile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_smile_eye.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_smile_eye.png index 0703cb21d..c47f3d536 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_smile_eye.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_smile_eye.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_videocam.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_videocam.png index 15e97ed6e..a2ab4ddb4 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_videocam.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_ic_videocam.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_knot_down.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_knot_down.png index 4caa342fa..f54d09a41 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_knot_down.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_knot_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_knot_up.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_knot_up.png index 7559ee614..2af230db6 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_knot_up.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_knot_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_powerful_infinity.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_powerful_infinity.png index 8dca0dec1..d9a6ae60b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_powerful_infinity.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_powerful_infinity.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_powerful_infinity_white.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_powerful_infinity_white.png index a32c1f298..f74e18a37 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_powerful_infinity_white.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_powerful_infinity_white.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_powerful_mask.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_powerful_mask.png index d7d885b82..1a97baf85 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_powerful_mask.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_powerful_mask.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_powerful_star.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_powerful_star.png index fa901bcf1..d8b1f2aea 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_powerful_star.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_powerful_star.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_private_door.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_private_door.png index a091403d4..1d8ecedce 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_private_door.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_private_door.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_private_screw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_private_screw.png index cc3a0fb4c..849973520 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_private_screw.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_private_screw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_tg_plane.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_tg_plane.png index a6af63624..6b6460673 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_tg_plane.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_tg_plane.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_tg_sphere.png b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_tg_sphere.png index adec08025..82d564939 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/intro_tg_sphere.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/intro_tg_sphere.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/knob_shadow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/knob_shadow.png index a9bd8af3c..43d6ebfbb 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/knob_shadow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/knob_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/layer_shadow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/layer_shadow.png index 637e319f0..7e62bc1cb 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/layer_shadow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/layer_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/list_bot.png b/TMessagesProj/src/main/res/drawable-xxhdpi/list_bot.png index 0596f8f12..a7b60a6c9 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/list_bot.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/list_bot.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/list_broadcast.png b/TMessagesProj/src/main/res/drawable-xxhdpi/list_broadcast.png index adf93a846..0560f772e 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/list_broadcast.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/list_broadcast.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/list_check.png b/TMessagesProj/src/main/res/drawable-xxhdpi/list_check.png old mode 100755 new mode 100644 index 30f01c6d9..71710420d Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/list_check.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/list_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/list_circle.png b/TMessagesProj/src/main/res/drawable-xxhdpi/list_circle.png index 5a16cbaff..5bd239d89 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/list_circle.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/list_circle.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/list_group.png b/TMessagesProj/src/main/res/drawable-xxhdpi/list_group.png index 14c071e67..9dc754d07 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/list_group.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/list_group.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/list_halfcheck.png b/TMessagesProj/src/main/res/drawable-xxhdpi/list_halfcheck.png old mode 100755 new mode 100644 index 2c8e85fe0..6170ee2be Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/list_halfcheck.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/list_halfcheck.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/list_mute.png b/TMessagesProj/src/main/res/drawable-xxhdpi/list_mute.png old mode 100755 new mode 100644 index a0e5efc6f..86c79499f Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/list_mute.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/list_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/list_pin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/list_pin.png old mode 100755 new mode 100644 index b72568bbf..8102c40d3 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/list_pin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/list_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/list_reorder.png b/TMessagesProj/src/main/res/drawable-xxhdpi/list_reorder.png new file mode 100644 index 000000000..9b7b9a143 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/list_reorder.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/list_secret.png b/TMessagesProj/src/main/res/drawable-xxhdpi/list_secret.png index 35a15b3bf..5d6efa0e7 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/list_secret.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/list_secret.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/list_warning_sign.png b/TMessagesProj/src/main/res/drawable-xxhdpi/list_warning_sign.png index c0f5b2dd1..5360daea0 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/list_warning_sign.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/list_warning_sign.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/live_loc.png b/TMessagesProj/src/main/res/drawable-xxhdpi/live_loc.png index 016be0d5c..b45caa762 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/live_loc.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/live_loc.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/livelocationpin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/livelocationpin.png index acf3ee183..d799a8361 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/livelocationpin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/livelocationpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/livepin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/livepin.png index dc6d6806a..f527589a2 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/livepin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/livepin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/load_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/load_big.png index cbf60bc07..eb90aa331 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/load_big.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/load_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/location_panel.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/location_panel.9.png index 85a6d26e5..f9bb86ef5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/location_panel.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/location_panel.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/lock_arrow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/lock_arrow.png index 71c66fdc2..62790d963 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/lock_arrow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/lock_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/lock_close.png b/TMessagesProj/src/main/res/drawable-xxhdpi/lock_close.png index 716b83b66..624ed57c5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/lock_close.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/lock_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/lock_middle.png b/TMessagesProj/src/main/res/drawable-xxhdpi/lock_middle.png index fb6112276..b1ed38b5f 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/lock_middle.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/lock_middle.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/lock_open.png b/TMessagesProj/src/main/res/drawable-xxhdpi/lock_open.png index 3cb15715f..43c2bef23 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/lock_open.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/lock_open.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/lock_round.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/lock_round.9.png index 82a3d5e68..82b9f0d01 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/lock_round.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/lock_round.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/lock_round_shadow.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/lock_round_shadow.9.png index c1940ae77..3ea678966 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/lock_round_shadow.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/lock_round_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/lock_top.png b/TMessagesProj/src/main/res/drawable-xxhdpi/lock_top.png index 743dea6ba..d24a6583a 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/lock_top.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/lock_top.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/log_info.png b/TMessagesProj/src/main/res/drawable-xxhdpi/log_info.png index 132330fad..625fffd16 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/log_info.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/log_info.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/logo_middle.png b/TMessagesProj/src/main/res/drawable-xxhdpi/logo_middle.png index e9b840ee2..53ede642e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/logo_middle.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/logo_middle.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/map_pin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/map_pin.png index 7592078d7..fcddc71a0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/map_pin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/map_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_blue.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_blue.png index 6400fd7c4..791f41f40 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_blue.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_blue.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_blue_b.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_blue_b.png index 956876d5b..552eb7414 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_blue_b.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_blue_b.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_green.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_green.png index 81e6726fe..c08a178e9 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_green.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_green.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_green_b.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_green_b.png index 2fa5d5a37..46aade7b2 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_green_b.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_green_b.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_load.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_load.png index 0ba267f43..0c42484de 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_load.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_load.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_pause.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_pause.png index b944ac209..ddc4376b6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_pause.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_red.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_red.png index 3b793afa5..bc1b6b03f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_red.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_red.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_red_b.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_red_b.png index 70211a3a2..3230b599e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_red_b.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_red_b.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_yellow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_yellow.png index 8bb147362..dae7e6a83 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_yellow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_yellow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_yellow_b.png b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_yellow_b.png index a3f1603e5..b1a149b4b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_yellow_b.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/media_doc_yellow_b.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/mentionbutton.png b/TMessagesProj/src/main/res/drawable-xxhdpi/mentionbutton.png index c5f0a4710..8fe89a76c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/mentionbutton.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/mentionbutton.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/mentionchatslist.png b/TMessagesProj/src/main/res/drawable-xxhdpi/mentionchatslist.png index 50cee8a1d..89c16cd7d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/mentionchatslist.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/mentionchatslist.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_add.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_add.png index 1b58e9cdc..bb6a169a7 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_add.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_bookmarks_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_bookmarks_ny.png index 19ee0c783..b09ead591 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_bookmarks_ny.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_bookmarks_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_broadcast.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_broadcast.png index 7a5660584..49fcd685b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_broadcast.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_broadcast.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_calls.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_calls.png index a61133600..93efc86b3 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_calls.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_calls.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_calls_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_calls_ny.png index 55baa943d..a87e5943f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_calls_ny.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_calls_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_camera.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_camera.png index 36aa6580e..9eb4c795d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_camera.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_camera.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_camera_av.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_camera_av.png index 050515b6e..a30314f55 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_camera_av.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_camera_av.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_channel_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_channel_ny.png index 74518b930..f4a58a49b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_channel_ny.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_channel_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_chats.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_chats.png index 4f6abcfe4..3103b83b5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_chats.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_chats.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_clearcache.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_clearcache.png index 077284a15..e203d8154 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_clearcache.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_clearcache.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_contacts.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_contacts.png index 42c8a4d4c..5bfd81406 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_contacts.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_contacts.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_contacts_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_contacts_ny.png index b49b9da8b..8723eabb0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_contacts_ny.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_contacts_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_copy.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_copy.9.png index 7269d0e09..297241f26 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_copy.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_copy.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_data.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_data.png index b053ee577..eed3d235a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_data.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_data.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_groups.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_groups.png new file mode 100644 index 000000000..ee1bb1f4d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_groups.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_groups_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_groups_ny.png index bb5ebc5fe..d258f21a2 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_groups_ny.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_groups_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_help.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_help.png index dbb12fc65..2aae6f808 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_help.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_help.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_help_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_help_ny.png index 66f638eb8..f2206bc22 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_help_ny.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_help_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_invite.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_invite.png index da9f2ed98..9387e0683 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_invite.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_invite.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_invite_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_invite_ny.png index def47b204..152df5280 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_invite_ny.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_invite_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_language.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_language.png index f9d6de11d..3705c9b8a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_language.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_language.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_newgroup.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_newgroup.png deleted file mode 100644 index 7b1429baa..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_newgroup.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_newphone.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_newphone.png index 0a79e34d6..068c823c7 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_newphone.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_newphone.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_notifications.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_notifications.png index 3eaf69da6..0d373750b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_notifications.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_notifications.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_palette.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_palette.png index d3e3db333..a797213d7 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_palette.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_palette.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_passcode.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_passcode.png index 3c9a00d71..5eacc52c7 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_passcode.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_passcode.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_read.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_read.png index 6b740c9c0..5974ea810 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_read.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_read.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_saved.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_saved.png index 983043b4e..768812717 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_saved.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_saved.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_search.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_search.png index 2614632b6..70c970359 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_search.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_secret.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_secret.png index 61283237d..ddc3405ba 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_secret.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_secret.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_secret_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_secret_ny.png index 480acd829..8edf03256 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_secret_ny.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_secret_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_settings.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_settings.png index 530fa3849..c90fad6ad 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_settings.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_settings_filled.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_settings_filled.png index 5c9c7388f..81aff0510 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_settings_filled.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_settings_filled.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_settings_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_settings_ny.png index 72f2b97e4..dca31bac8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_settings_ny.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_settings_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_shadow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_shadow.png index bc4fc1ea9..64def28b7 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_shadow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_support.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_support.png index 273c37d65..a7be48fad 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_support.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_support.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_unread.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_unread.png deleted file mode 100644 index 0995c9a99..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_unread.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/message_arrow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/message_arrow.png index 298efdd58..878bca3ca 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/message_arrow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/message_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/mic.png b/TMessagesProj/src/main/res/drawable-xxhdpi/mic.png deleted file mode 100644 index b1a9cba26..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/mic.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_close.png b/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_close.png index 650dc6fc4..20aa1fdde 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_close.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_pause.png b/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_pause.png index df49d651a..056585093 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_pause.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_play.png b/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_play.png index 0926c4326..6d1b751df 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_play.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/moon.png b/TMessagesProj/src/main/res/drawable-xxhdpi/moon.png index 1a2d70090..df700ce92 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/moon.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/moon.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_actions.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_actions.png index 2c70066ca..b50b233b2 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_actions.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_actions.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addbot.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addbot.png new file mode 100644 index 000000000..6d62bf618 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addbot.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addcontact.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addcontact.png new file mode 100644 index 000000000..1c6bc2e4f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addcontact.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_archive.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_archive.png new file mode 100644 index 000000000..f81ca5f62 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_archive.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_block.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_block.png new file mode 100644 index 000000000..5223dd43f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_block.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calendar.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calendar.png new file mode 100644 index 000000000..005d52e22 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calendar.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_callback.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_callback.png new file mode 100644 index 000000000..39585cc8b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_callback.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_cancel.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_cancel.png new file mode 100644 index 000000000..316f40e02 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_check.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_check.png index 7c78b851e..1f5db8bca 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_check.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clear.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clear.png new file mode 100644 index 000000000..ea78fb3f8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clock.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clock.png index c7b96ea3a..5d11071da 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clock.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clock.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contact.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contact.png index 738a3816e..ccbd2c20f 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contact.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contact.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_copy.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_copy.png new file mode 100644 index 000000000..87ed4473f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_copy.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_delete.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_delete.png new file mode 100644 index 000000000..800cd12af Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_download.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_download.png new file mode 100644 index 000000000..9a7fd7739 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_download.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_edit.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_edit.png new file mode 100644 index 000000000..23c63c725 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_edit.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_fave.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_fave.png new file mode 100644 index 000000000..d30ab499c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_fave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_forward.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_forward.png new file mode 100644 index 000000000..fe592c16d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gallery.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gallery.png new file mode 100644 index 000000000..a21ffce4f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gallery.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gif.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gif.png new file mode 100644 index 000000000..49d7d77e9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_go_down.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_go_down.png new file mode 100644 index 000000000..208648826 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_go_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_go_up.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_go_up.png new file mode 100644 index 000000000..4ea67a15f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_go_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_halfcheck.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_halfcheck.png index 9e52c5bf7..085b4df93 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_halfcheck.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_halfcheck.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_home.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_home.png new file mode 100644 index 000000000..507440762 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_home.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_hybrid.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_hybrid.png new file mode 100644 index 000000000..308a343ac Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_hybrid.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_in.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_in.9.png index 9288fdb23..2049a8446 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_in.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_in.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_in_shadow.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_in_shadow.9.png index 00ccf246c..075f3b5a2 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_in_shadow.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_in_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_instant.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_instant.png index 59968c26c..97e268ded 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_instant.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_instant.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_language.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_language.png new file mode 100644 index 000000000..34dabdabc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_language.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_leave.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_leave.png new file mode 100644 index 000000000..4767b2b81 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_leave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_link.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_link.png new file mode 100644 index 000000000..48298e408 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location.png index fc080b46d..611c78c4c 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_map.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_map.png new file mode 100644 index 000000000..82b2f7f58 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_map.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_markread.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_markread.png new file mode 100644 index 000000000..719fc2f16 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_markread.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_markunread.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_markunread.png new file mode 100644 index 000000000..43f206d65 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_markunread.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mask.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mask.png new file mode 100644 index 000000000..bc0645af6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mask.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_media.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_media.png new file mode 100644 index 000000000..4f331f9fd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_media.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_message.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_message.png new file mode 100644 index 000000000..a13e9514f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_message.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mute.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mute.png new file mode 100644 index 000000000..e089f9ab4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_openin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_openin.png new file mode 100644 index 000000000..904ef8078 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_openin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_out.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_out.9.png index f2115074c..2303548c2 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_out.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_out.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_out_shadow.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_out_shadow.9.png index fc5612f08..14bfdad84 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_out_shadow.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_out_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_panel_clear.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_panel_clear.png index a495f8369..feea2c97f 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_panel_clear.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_panel_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_panel_forward.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_panel_forward.png index 0a06cb529..70ae5956e 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_panel_forward.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_panel_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_panel_link.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_panel_link.png deleted file mode 100755 index b9f19cc0f..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_panel_link.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_panel_reply.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_panel_reply.png index 0979942a4..a36b29779 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_panel_reply.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_panel_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo.9.png index 001cea3de..5485eb061 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_shadow.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_shadow.9.png index e03c0c113..1d68db4d8 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_shadow.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pin.png new file mode 100644 index 000000000..855d195fa Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pollstop.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pollstop.png new file mode 100644 index 000000000..524c3d5b6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pollstop.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reply.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reply.png new file mode 100644 index 000000000..e7dea2c06 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_report.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_report.png new file mode 100644 index 000000000..4b10420f0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_report.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_retry.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_retry.png new file mode 100644 index 000000000..f0a3f9299 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_retry.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_cancel_m.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_cancel_m.png index 7ffc2d6b0..5d04544f6 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_cancel_m.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_cancel_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_file_s.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_file_s.png index 68d16e112..735add6f5 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_file_s.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_file_s.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_gif_m.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_gif_m.png index 9d517d4f9..bcd9f270c 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_gif_m.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_gif_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_load_m.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_load_m.png index f32acf3f4..ea74b1265 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_load_m.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_load_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_pause_m.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_pause_m.png index 738f5b648..e596b2fc5 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_pause_m.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_pause_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_play_m.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_play_m.png index 449657696..5bb378e77 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_play_m.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_round_play_m.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_satellite.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_satellite.png new file mode 100644 index 000000000..978f49233 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_satellite.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_search.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_search.png new file mode 100644 index 000000000..6e74cbee4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_share.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_share.png new file mode 100644 index 000000000..5b54ca176 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_share.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_shareout.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_shareout.png new file mode 100644 index 000000000..55664d519 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_shareout.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_stats.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_stats.png new file mode 100644 index 000000000..4e0581776 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_stats.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_sticker.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_sticker.png new file mode 100644 index 000000000..e8f12dfd5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_sticker.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_theme.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_theme.png new file mode 100644 index 000000000..e2ba113b3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_theme.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_timer.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_timer.png new file mode 100644 index 000000000..36fb2fdf9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_timer.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unarchive.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unarchive.png new file mode 100644 index 000000000..1538baa05 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unarchive.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unfave.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unfave.png new file mode 100644 index 000000000..9f9d24443 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unfave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unmute.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unmute.png new file mode 100644 index 000000000..4c7f5c7b8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unmute.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unpin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unpin.png new file mode 100644 index 000000000..0933b4a05 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unvote.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unvote.png new file mode 100644 index 000000000..9128a67c9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unvote.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_usersearch.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_usersearch.png new file mode 100644 index 000000000..cc89fff0e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_usersearch.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_views.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_views.png index fb6825ae9..44a97820a 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_views.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_views.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_warning.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_warning.png index 8a7d22f35..d07ea709c 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_warning.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_warning.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/music_reverse.png b/TMessagesProj/src/main/res/drawable-xxhdpi/music_reverse.png index 80c1d8dfa..2efb70c99 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/music_reverse.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/music_reverse.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/myloc_on.png b/TMessagesProj/src/main/res/drawable-xxhdpi/myloc_on.png index 92fbeda71..63f319fc7 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/myloc_on.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/myloc_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/navigate.png b/TMessagesProj/src/main/res/drawable-xxhdpi/navigate.png index ffe55f7fe..1eb892a87 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/navigate.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/navigate.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/newmsg_divider.png b/TMessagesProj/src/main/res/drawable-xxhdpi/newmsg_divider.png index e9c1a24b7..07d969e86 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/newmsg_divider.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/newmsg_divider.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/newyear.png b/TMessagesProj/src/main/res/drawable-xxhdpi/newyear.png index d5f3e1bc1..e220a02f6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/newyear.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/newyear.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/no_apps.png b/TMessagesProj/src/main/res/drawable-xxhdpi/no_apps.png index f7d2c53be..f760eaa84 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/no_apps.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/no_apps.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/no_passport.png b/TMessagesProj/src/main/res/drawable-xxhdpi/no_passport.png index 9b3176852..077b22108 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/no_passport.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/no_passport.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/no_password.png b/TMessagesProj/src/main/res/drawable-xxhdpi/no_password.png index 6f2955edd..47f555b36 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/no_password.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/no_password.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/nocover.png b/TMessagesProj/src/main/res/drawable-xxhdpi/nocover.png index ae86c205b..37b656c51 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/nocover.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/nocover.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/nocover_big.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/nocover_big.9.png index eacbc19f7..601beffc0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/nocover_big.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/nocover_big.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/nocover_small.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/nocover_small.9.png index 012386f97..2b37b1054 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/nocover_small.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/nocover_small.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/nophotos.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/nophotos.9.png index 123b71b56..e95022278 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/nophotos.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/nophotos.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/notification.png b/TMessagesProj/src/main/res/drawable-xxhdpi/notification.png old mode 100755 new mode 100644 index 6ed95b8fd..a8d2beef9 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/notification.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/notification.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_mute1h.png b/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_mute1h.png index ed002bc92..c5892e14a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_mute1h.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_mute1h.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_mute2d.png b/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_mute2d.png index 7abca37cf..d3edb46fb 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_mute2d.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_mute2d.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_off.png b/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_off.png index e625f654e..fb102e71b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_off.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_on.png b/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_on.png index 9800a9fdd..6437b9c33 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_on.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_settings.png b/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_settings.png index 8154454cf..9a4a1f301 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_settings.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/notifications_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/notify_members_off.png b/TMessagesProj/src/main/res/drawable-xxhdpi/notify_members_off.png deleted file mode 100644 index 6d0eea38a..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/notify_members_off.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/notify_members_on.png b/TMessagesProj/src/main/res/drawable-xxhdpi/notify_members_on.png deleted file mode 100644 index 26ea2694b..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/notify_members_on.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/outline_add_gif.png b/TMessagesProj/src/main/res/drawable-xxhdpi/outline_add_gif.png new file mode 100644 index 000000000..d63045ff1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/outline_add_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/outline_fave.png b/TMessagesProj/src/main/res/drawable-xxhdpi/outline_fave.png new file mode 100644 index 000000000..3bab4460b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/outline_fave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/outline_pack.png b/TMessagesProj/src/main/res/drawable-xxhdpi/outline_pack.png new file mode 100644 index 000000000..576d80899 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/outline_pack.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/outline_send.png b/TMessagesProj/src/main/res/drawable-xxhdpi/outline_send.png new file mode 100644 index 000000000..ed3e8803b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/outline_send.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/outline_unfave.png b/TMessagesProj/src/main/res/drawable-xxhdpi/outline_unfave.png new file mode 100644 index 000000000..cbf5a1dab Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/outline_unfave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pagedown.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pagedown.png index 2ba302806..48ebbf2bb 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/pagedown.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/pagedown.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pagedown_shadow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pagedown_shadow.png index 98603e32c..268a0bcf8 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/pagedown_shadow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/pagedown_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/passcode_check.png b/TMessagesProj/src/main/res/drawable-xxhdpi/passcode_check.png index a831f4bb1..bbe1d993a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/passcode_check.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/passcode_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/passcode_delete.png b/TMessagesProj/src/main/res/drawable-xxhdpi/passcode_delete.png index cdd6dce68..a771e227e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/passcode_delete.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/passcode_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/passcode_logo.png b/TMessagesProj/src/main/res/drawable-xxhdpi/passcode_logo.png index af2428a20..5086ff849 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/passcode_logo.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/passcode_logo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/permission_locked.png b/TMessagesProj/src/main/res/drawable-xxhdpi/permission_locked.png index a06a09dbf..8337c551c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/permission_locked.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/permission_locked.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/permissions_contacts.png b/TMessagesProj/src/main/res/drawable-xxhdpi/permissions_contacts.png index ba36b93ad..8202daa09 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/permissions_contacts.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/permissions_contacts.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/phone_activate.png b/TMessagesProj/src/main/res/drawable-xxhdpi/phone_activate.png index d422603db..8f99f1c50 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/phone_activate.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/phone_activate.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/phone_change.png b/TMessagesProj/src/main/res/drawable-xxhdpi/phone_change.png index 2133e1604..0867a90e6 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/phone_change.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/phone_change.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_add.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_add.png index 3b361e900..3df075a33 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_add.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_crop.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_crop.png index 4e5183fa5..e79ceb2c1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_crop.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_crop.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_outline.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_outline.png index 348741607..e3f0313e0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_outline.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_outline.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_paint.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_paint.png index 5758aa96f..f564393ad 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_paint.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_paint.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_paint_brush.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_paint_brush.png index 8927dea1c..5458b15af 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_paint_brush.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_paint_brush.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_paint_text.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_paint_text.png index 6a8aa7598..97a545904 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_paint_text.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_paint_text.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_sticker.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_sticker.png index 21c7098da..1f3b1e3a6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_sticker.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_sticker.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_timer.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_timer.png index 7c781ac2f..c09b537b7 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_timer.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_timer.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_tools.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_tools.png index 896447358..47270996c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_tools.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_tools.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_undo.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_undo.png index af1165606..2ccf7258f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_undo.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_undo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_w.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_w.png index 75073d1c6..636984607 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photo_w.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photo_w.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photobadge.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photobadge.9.png index 72fdedbdb..c03f6867c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photobadge.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photobadge.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photocheck.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photocheck.png index fa83dc2bd..9aba64fe0 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photocheck.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photocheck.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photos_arrow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photos_arrow.png index 0b6ef1a7a..e93b28ae4 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photos_arrow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photos_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photos_group.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photos_group.png index 09c8f467b..c671d9921 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photos_group.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photos_group.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photos_header_shadow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photos_header_shadow.png index 1d4097947..2b1af53b9 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photos_header_shadow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photos_header_shadow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/photos_rounded.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/photos_rounded.9.png index e7ff4d1b3..740d1512c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/photos_rounded.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/photos_rounded.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/phototime.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/phototime.9.png index 650ecf617..e493f511e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/phototime.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/phototime.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pin.png index 6663b7158..471be7074 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/pin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_next.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_next.png index 37928e0b4..6cb192023 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_next.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_next.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_pause.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_pause.png index 917bba404..730b4a5ab 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_pause.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_play.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_play.png index c3f04d39d..6bf75867f 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_play.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_previous.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_previous.png index 2b0733816..941caed24 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_previous.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_previous.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat.png index a2c09eaab..c98c818c8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat1.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat1.png index 957cda76d..dee13fcc3 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat1.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat1.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_shuffle.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_shuffle.png index 181ffc2c3..85fdec828 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_shuffle.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_shuffle.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/place_x.png b/TMessagesProj/src/main/res/drawable-xxhdpi/place_x.png index f0d94e6df..17d4bbd82 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/place_x.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/place_x.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/play_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/play_big.png index b04acefb6..e4d1f1c88 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/play_big.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/play_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/play_mini_video.png b/TMessagesProj/src/main/res/drawable-xxhdpi/play_mini_video.png index 4e89c928c..c7b55a7ac 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/play_mini_video.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/play_mini_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/player.png b/TMessagesProj/src/main/res/drawable-xxhdpi/player.png index 21217b2c1..d28a42469 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/player.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/player.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/plus.png b/TMessagesProj/src/main/res/drawable-xxhdpi/plus.png index 10b5f8f17..c033b7a60 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/plus.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/plus.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/popup_fixed.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/popup_fixed.9.png index 050190c71..64a91e650 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/popup_fixed.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/popup_fixed.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/popup_fixed_alert.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/popup_fixed_alert.9.png index 87fcf07ce..6b2ec2287 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/popup_fixed_alert.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/popup_fixed_alert.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/popup_fixed_alert2.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/popup_fixed_alert2.9.png new file mode 100644 index 000000000..97913d52b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/popup_fixed_alert2.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/popup_fixed_top.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/popup_fixed_top.9.png index 99bf6326c..eb71ef90d 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/popup_fixed_top.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/popup_fixed_top.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/preview_arrow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/preview_arrow.png new file mode 100644 index 000000000..95193eeef Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/preview_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/preview_open.png b/TMessagesProj/src/main/res/drawable-xxhdpi/preview_open.png index 3649fe83c..77cd8a536 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/preview_open.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/preview_open.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_admin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_admin.png index 9a5cd643b..73be1d178 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_admin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_admin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_audio.png b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_audio.png index 3a9db5ec3..78a8917cf 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_audio.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_audio.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_ban.png b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_ban.png index 35e30b908..856d08deb 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_ban.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_ban.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_file.png b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_file.png index 142d78c98..c1a58fa95 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_file.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_file.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_groups.png b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_groups.png deleted file mode 100644 index 7ec50eb24..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_groups.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_info.png b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_info.png index c3b7e5567..718dad5b9 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_info.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_info.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_link.png b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_link.png index e0ce90f24..10e20531f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_link.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_list.png b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_list.png index 7d87c6373..00e588076 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_list.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_list.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_message.png b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_message.png index e84145b9e..a9b89e6f6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_message.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_message.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_newmsg.png b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_newmsg.png index ab848f945..0070bab1f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_newmsg.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_newmsg.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_phone.png b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_phone.png index 64472781f..47104ca83 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_phone.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_phone.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_photos.png b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_photos.png index 120f28790..49e64e725 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_photos.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_photos.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_voice.png b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_voice.png index a89b3540e..20a76cd02 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/profile_voice.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/profile_voice.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/proxy_check.png b/TMessagesProj/src/main/res/drawable-xxhdpi/proxy_check.png index e7201747c..860284be1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/proxy_check.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/proxy_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/proxy_off.png b/TMessagesProj/src/main/res/drawable-xxhdpi/proxy_off.png index 179a2667a..cb8c19440 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/proxy_off.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/proxy_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/proxy_on.png b/TMessagesProj/src/main/res/drawable-xxhdpi/proxy_on.png index b67d112a4..88b1297d2 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/proxy_on.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/proxy_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/redcircle.png b/TMessagesProj/src/main/res/drawable-xxhdpi/redcircle.png index 927e62b39..32118e910 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/redcircle.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/redcircle.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/regbtn2.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/regbtn2.9.png index 2d0e03434..b8c21d82a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/regbtn2.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/regbtn2.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/regbtn2_pressed.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/regbtn2_pressed.9.png index 6504cbf7f..4ee56e461 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/regbtn2_pressed.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/regbtn2_pressed.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/replyvideo.png b/TMessagesProj/src/main/res/drawable-xxhdpi/replyvideo.png index 07ce21467..a1374752a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/replyvideo.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/replyvideo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/round_check2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/round_check2.png index 88c5e2143..e741574c4 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/round_check2.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/round_check2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/round_grey.png b/TMessagesProj/src/main/res/drawable-xxhdpi/round_grey.png index 7b037c623..2a9ea8934 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/round_grey.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/round_grey.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/s_pause.png b/TMessagesProj/src/main/res/drawable-xxhdpi/s_pause.png index 48279a1c2..9bada4c98 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/s_pause.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/s_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/s_play.png b/TMessagesProj/src/main/res/drawable-xxhdpi/s_play.png index ec1dd1751..6025199bf 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/s_play.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/s_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/scroll_tip.png b/TMessagesProj/src/main/res/drawable-xxhdpi/scroll_tip.png index e736cedf8..354efbee9 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/scroll_tip.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/scroll_tip.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/search_calendar.png b/TMessagesProj/src/main/res/drawable-xxhdpi/search_calendar.png deleted file mode 100755 index 23485e842..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/search_calendar.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/search_dark.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/search_dark.9.png index df1a121bc..6ea1665f0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/search_dark.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/search_dark.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/search_dark_activated.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/search_dark_activated.9.png index bebe13be5..4412c1288 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/search_dark_activated.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/search_dark_activated.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/search_down.png b/TMessagesProj/src/main/res/drawable-xxhdpi/search_down.png deleted file mode 100755 index 71c3667e7..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/search_down.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/search_gif.png b/TMessagesProj/src/main/res/drawable-xxhdpi/search_gif.png index d9e7195be..581a6ebf2 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/search_gif.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/search_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/search_up.png b/TMessagesProj/src/main/res/drawable-xxhdpi/search_up.png deleted file mode 100755 index ec9efb265..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/search_up.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/search_web.png b/TMessagesProj/src/main/res/drawable-xxhdpi/search_web.png index 193208c52..655764478 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/search_web.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/search_web.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/selectphoto_large.png b/TMessagesProj/src/main/res/drawable-xxhdpi/selectphoto_large.png index 0c8ff5a49..a90480717 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/selectphoto_large.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/selectphoto_large.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/settings_arrow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/settings_arrow.png new file mode 100644 index 000000000..23ef6cdf1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/settings_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/settings_noresults.png b/TMessagesProj/src/main/res/drawable-xxhdpi/settings_noresults.png new file mode 100644 index 000000000..d7a43651a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/settings_noresults.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/shadowdown.png b/TMessagesProj/src/main/res/drawable-xxhdpi/shadowdown.png index b9527e164..93dd64e05 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/shadowdown.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/shadowdown.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/share.png b/TMessagesProj/src/main/res/drawable-xxhdpi/share.png index b72403da1..ac2f19d33 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/share.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/share.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/share_arrow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/share_arrow.png index e26a7d040..3c4ff666e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/share_arrow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/share_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/share_round.png b/TMessagesProj/src/main/res/drawable-xxhdpi/share_round.png index 64fe260ba..5e62c4a30 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/share_round.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/share_round.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/sheet_shadow.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/sheet_shadow.9.png index 1e8e69099..ef680ecb6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/sheet_shadow.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/sheet_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/sheet_shadow_round.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/sheet_shadow_round.9.png new file mode 100644 index 000000000..685aeb4f5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/sheet_shadow_round.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/shortcut_compose.png b/TMessagesProj/src/main/res/drawable-xxhdpi/shortcut_compose.png index caebb609e..d057d949d 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/shortcut_compose.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/shortcut_compose.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/shortcut_user.png b/TMessagesProj/src/main/res/drawable-xxhdpi/shortcut_user.png index 21cd37252..8543de711 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/shortcut_user.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/shortcut_user.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/slide_dot_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/slide_dot_big.png index edc3b7ad9..d5ec8763b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/slide_dot_big.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/slide_dot_big.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/slide_dot_small.png b/TMessagesProj/src/main/res/drawable-xxhdpi/slide_dot_small.png index 5be0e81f9..5a5301888 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/slide_dot_small.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/slide_dot_small.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/slidearrow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/slidearrow.png index 6fb78051e..51969e550 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/slidearrow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/slidearrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smallanimationpin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smallanimationpin.png index b95b84822..a9a62189e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/smallanimationpin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/smallanimationpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smallanimationpinleft.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smallanimationpinleft.png index f9fba58c2..bcfe4aed5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/smallanimationpinleft.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/smallanimationpinleft.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smallanimationpinright.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smallanimationpinright.png index fa74c81db..f5622c3be 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/smallanimationpinright.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/smallanimationpinright.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_info.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_info.png new file mode 100644 index 000000000..6faf29610 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_info.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_inputsearch.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_inputsearch.png new file mode 100644 index 000000000..d2fdb23d5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_inputsearch.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_activities.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_activities.png new file mode 100644 index 000000000..f89c086fa Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_activities.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_cat.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_cat.png new file mode 100644 index 000000000..58f1412c5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_cat.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_faves.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_faves.png new file mode 100644 index 000000000..6683627db Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_faves.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_flags.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_flags.png new file mode 100644 index 000000000..4035cc52c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_flags.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_food.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_food.png new file mode 100644 index 000000000..2d744df2a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_food.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_objects.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_objects.png new file mode 100644 index 000000000..9f209058f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_objects.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_other.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_other.png new file mode 100644 index 000000000..7072bb077 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_other.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_question.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_question.png new file mode 100644 index 000000000..c158b021c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_question.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_recent.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_recent.png new file mode 100644 index 000000000..37807a409 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_recent.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_smiles.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_smiles.png new file mode 100644 index 000000000..3f791d161 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_smiles.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_travel.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_travel.png new file mode 100644 index 000000000..d7240d4b9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_travel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_trending.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_trending.png new file mode 100644 index 000000000..f30e5fa5e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_panel_trending.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_popup.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_popup.9.png index 585a098c7..878d09d4e 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_popup.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_popup.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_clear.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_clear.png new file mode 100644 index 000000000..9e9dfa4d7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_gif.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_gif.png new file mode 100644 index 000000000..9b123100e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_search.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_search.png new file mode 100644 index 000000000..49335ddb9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_settings.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_settings.png new file mode 100644 index 000000000..c0e223a48 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_smiles.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_smiles.png new file mode 100644 index 000000000..de9fa3a85 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_smiles.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_stickers.png b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_stickers.png new file mode 100644 index 000000000..2688cf86f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/smiles_tab_stickers.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/sms_bubble.png b/TMessagesProj/src/main/res/drawable-xxhdpi/sms_bubble.png index f1fc95eb4..a5d8c1f5c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/sms_bubble.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/sms_bubble.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/sms_code.png b/TMessagesProj/src/main/res/drawable-xxhdpi/sms_code.png index 2279f464b..5e223e35c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/sms_code.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/sms_code.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/sms_devices.png b/TMessagesProj/src/main/res/drawable-xxhdpi/sms_devices.png index 4c7c703ba..c85514cf9 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/sms_devices.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/sms_devices.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/staredstickerstab.png b/TMessagesProj/src/main/res/drawable-xxhdpi/staredstickerstab.png deleted file mode 100644 index cd3e33c62..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/staredstickerstab.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/sticker_added.png b/TMessagesProj/src/main/res/drawable-xxhdpi/sticker_added.png index 1e9ad6878..f31f2f828 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/sticker_added.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/sticker_added.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/sticker_search.png b/TMessagesProj/src/main/res/drawable-xxhdpi/sticker_search.png deleted file mode 100644 index c6abcc54f..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/sticker_search.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_all.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_all.9.png index 7b0ed60d1..bacbab355 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_all.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_all.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_arrow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_arrow.png index 43d89e76e..6b16f2b7e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_arrow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_center.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_center.9.png index 973fdb0f4..a61b2f0dc 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_center.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_center.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_left.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_left.9.png index faca48ac0..2ec23eb3b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_left.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_left.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_right.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_right.9.png index f946b9fd5..c722c0112 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_right.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_back_right.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_empty.png b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_empty.png new file mode 100644 index 000000000..85d8fc988 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_empty.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_favorite.png b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_favorite.png deleted file mode 100644 index 1db011aa3..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_favorite.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_none.png b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_none.png deleted file mode 100644 index 2bfa370e7..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_none.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_pack.png b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_pack.png deleted file mode 100644 index f68d40e9b..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_pack.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_send.png b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_send.png deleted file mode 100644 index 3ed7351e7..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_send.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_unfavorite.png b/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_unfavorite.png deleted file mode 100644 index 1d82d680e..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/stickers_unfavorite.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/stickersclose.png b/TMessagesProj/src/main/res/drawable-xxhdpi/stickersclose.png index 7017b9c50..a20d58143 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/stickersclose.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/stickersclose.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/stickerset_close.png b/TMessagesProj/src/main/res/drawable-xxhdpi/stickerset_close.png index 4dc9de7e4..fcb21b7d4 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/stickerset_close.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/stickerset_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/switch_to_on1.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/switch_to_on1.9.png index 12a95f517..da2e30b18 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/switch_to_on1.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/switch_to_on1.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/switch_to_on2.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/switch_to_on2.9.png index 12a95f517..da2e30b18 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/switch_to_on2.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/switch_to_on2.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/switch_track.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/switch_track.9.png index 3e3174d08..e76f3c822 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/switch_track.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/switch_track.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/system.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/system.9.png index f4b4f35ec..0cdb7b8a4 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/system.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/system.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/system_loader.png b/TMessagesProj/src/main/res/drawable-xxhdpi/system_loader.png index d2c6ec3a3..fa7341741 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/system_loader.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/system_loader.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/theme_picker.png b/TMessagesProj/src/main/res/drawable-xxhdpi/theme_picker.png index c742274b7..346de93dc 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/theme_picker.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/theme_picker.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/tip1.png b/TMessagesProj/src/main/res/drawable-xxhdpi/tip1.png index f126139a5..c93ef12b9 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/tip1.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/tip1.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/tip2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/tip2.png index bc35c8e0c..55ebd8b63 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/tip2.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/tip2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/tip3.png b/TMessagesProj/src/main/res/drawable-xxhdpi/tip3.png index 3fe466657..56b86dc6e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/tip3.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/tip3.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/tip4.png b/TMessagesProj/src/main/res/drawable-xxhdpi/tip4.png index 01a06346b..e973d9ae0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/tip4.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/tip4.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/tip5.png b/TMessagesProj/src/main/res/drawable-xxhdpi/tip5.png index e041bd0e2..6d641ffc4 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/tip5.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/tip5.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/tool_blur.png b/TMessagesProj/src/main/res/drawable-xxhdpi/tool_blur.png index cd7469701..a97da43c9 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/tool_blur.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/tool_blur.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/tool_cropfix.png b/TMessagesProj/src/main/res/drawable-xxhdpi/tool_cropfix.png index da85e5414..c8453fe37 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/tool_cropfix.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/tool_cropfix.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/tool_curve.png b/TMessagesProj/src/main/res/drawable-xxhdpi/tool_curve.png index 84fe36543..ec8724080 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/tool_curve.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/tool_curve.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/tool_rotate.png b/TMessagesProj/src/main/res/drawable-xxhdpi/tool_rotate.png index 0d5767689..071296b30 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/tool_rotate.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/tool_rotate.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/tooltip_arrow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/tooltip_arrow.png index 0adbe4b60..1fdff8874 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/tooltip_arrow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/tooltip_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/tooltip_arrow_up.png b/TMessagesProj/src/main/res/drawable-xxhdpi/tooltip_arrow_up.png new file mode 100644 index 000000000..238741331 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/tooltip_arrow_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/tooltip_sound.png b/TMessagesProj/src/main/res/drawable-xxhdpi/tooltip_sound.png index 624f09326..da9299f42 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/tooltip_sound.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/tooltip_sound.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/update.png b/TMessagesProj/src/main/res/drawable-xxhdpi/update.png index e10ba6354..ada5aed4c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/update.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/update.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/usersearch.png b/TMessagesProj/src/main/res/drawable-xxhdpi/usersearch.png deleted file mode 100644 index 209f4e0a4..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/usersearch.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/verified_area.png b/TMessagesProj/src/main/res/drawable-xxhdpi/verified_area.png old mode 100755 new mode 100644 index 356bf24ac..2c10f4fe6 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/verified_area.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/verified_area.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/verified_check.png b/TMessagesProj/src/main/res/drawable-xxhdpi/verified_check.png old mode 100755 new mode 100644 index 7e37cd3cb..93d1eae49 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/verified_check.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/verified_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/video_1080.png b/TMessagesProj/src/main/res/drawable-xxhdpi/video_1080.png index 1c7c5d84c..e4082c24f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/video_1080.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/video_1080.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/video_240.png b/TMessagesProj/src/main/res/drawable-xxhdpi/video_240.png index 0c8acfc0b..fff133fca 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/video_240.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/video_240.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/video_360.png b/TMessagesProj/src/main/res/drawable-xxhdpi/video_360.png index 4855eb8a9..03693d262 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/video_360.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/video_360.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/video_480.png b/TMessagesProj/src/main/res/drawable-xxhdpi/video_480.png index a1d765ca0..89c8d8454 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/video_480.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/video_480.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/video_720.png b/TMessagesProj/src/main/res/drawable-xxhdpi/video_720.png index f2d2822dd..3951a42bc 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/video_720.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/video_720.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/video_actions.png b/TMessagesProj/src/main/res/drawable-xxhdpi/video_actions.png index bfc2dbadd..d966e827b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/video_actions.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/video_actions.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/video_copy.png b/TMessagesProj/src/main/res/drawable-xxhdpi/video_copy.png index c4b6d1a18..ff79a8e2d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/video_copy.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/video_copy.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/video_cropleft.png b/TMessagesProj/src/main/res/drawable-xxhdpi/video_cropleft.png index 94f79a8a9..6fc50b0f5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/video_cropleft.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/video_cropleft.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/video_cropright.png b/TMessagesProj/src/main/res/drawable-xxhdpi/video_cropright.png index 3742bd6d7..49f02ea85 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/video_cropright.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/video_cropright.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/video_mini_arrow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/video_mini_arrow.png index ada661033..28b4d5886 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/video_mini_arrow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/video_mini_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/video_mini_cancel.png b/TMessagesProj/src/main/res/drawable-xxhdpi/video_mini_cancel.png index 4fbfde2d8..e814c1e2e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/video_mini_cancel.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/video_mini_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/video_mute.png b/TMessagesProj/src/main/res/drawable-xxhdpi/video_mute.png index aae2bc97f..8e1e1464b 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/video_mute.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/video_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/video_muted.png b/TMessagesProj/src/main/res/drawable-xxhdpi/video_muted.png index ca726a405..6f741f925 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/video_muted.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/video_muted.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/video_pip.png b/TMessagesProj/src/main/res/drawable-xxhdpi/video_pip.png index 3e63ee780..0e3951864 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/video_pip.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/video_pip.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/voice2x.png b/TMessagesProj/src/main/res/drawable-xxhdpi/voice2x.png index 5149b1bce..8462ef026 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/voice2x.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/voice2x.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/volume_off.png b/TMessagesProj/src/main/res/drawable-xxhdpi/volume_off.png index f49733d49..234d9f342 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/volume_off.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/volume_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/volume_on.png b/TMessagesProj/src/main/res/drawable-xxhdpi/volume_on.png index e3ee4703e..5fd3ce8d2 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/volume_on.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/volume_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/wall_selection.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/wall_selection.9.png index d3764c9a6..475ee47fc 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/wall_selection.9.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/wall_selection.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxxhdpi/book_logo.png b/TMessagesProj/src/main/res/drawable-xxxhdpi/book_logo.png index 1dce719a5..1b1ddb108 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxxhdpi/book_logo.png and b/TMessagesProj/src/main/res/drawable-xxxhdpi/book_logo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxxhdpi/ic_launcher.png b/TMessagesProj/src/main/res/drawable-xxxhdpi/ic_launcher.png deleted file mode 100755 index e659827f8..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxxhdpi/ic_launcher_dr.png b/TMessagesProj/src/main/res/drawable-xxxhdpi/ic_launcher_dr.png new file mode 100644 index 000000000..881369185 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxxhdpi/ic_launcher_dr.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxxhdpi/sheet_shadow.9.png b/TMessagesProj/src/main/res/drawable-xxxhdpi/sheet_shadow.9.png index d15a95606..66300db84 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxxhdpi/sheet_shadow.9.png and b/TMessagesProj/src/main/res/drawable-xxxhdpi/sheet_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable/catstile.jpg b/TMessagesProj/src/main/res/drawable/catstile.jpg index daf57b123..c42d45d3e 100644 Binary files a/TMessagesProj/src/main/res/drawable/catstile.jpg and b/TMessagesProj/src/main/res/drawable/catstile.jpg differ diff --git a/TMessagesProj/src/main/res/drawable/ic_call_notification_answer.xml b/TMessagesProj/src/main/res/drawable/ic_call_notification_answer.xml index fd23c95eb..f52c56c73 100644 --- a/TMessagesProj/src/main/res/drawable/ic_call_notification_answer.xml +++ b/TMessagesProj/src/main/res/drawable/ic_call_notification_answer.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/scrollbar_vertical_thumb.xml b/TMessagesProj/src/main/res/drawable/scrollbar_vertical_thumb.xml new file mode 100644 index 000000000..31c2b8c34 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/scrollbar_vertical_thumb.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/scrollbar_vertical_thumb_inset.xml b/TMessagesProj/src/main/res/drawable/scrollbar_vertical_thumb_inset.xml new file mode 100644 index 000000000..92ea9a984 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/scrollbar_vertical_thumb_inset.xml @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 000000000..19c7d4c77 --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 000000000..da6d7a8de --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/ic_launcher.png b/TMessagesProj/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..6e16733c9 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/ic_launcher_round.png b/TMessagesProj/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 000000000..6e16733c9 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_background.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_background.png new file mode 100644 index 000000000..9ed2c32b6 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_background.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_background_round.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_background_round.png new file mode 100644 index 000000000..356e98457 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_background_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_foreground.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_foreground.png new file mode 100644 index 000000000..04d68f67c Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_foreground_round.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_foreground_round.png new file mode 100644 index 000000000..0902d4184 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/ic_launcher.png b/TMessagesProj/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..ef397fd79 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/ic_launcher_round.png b/TMessagesProj/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 000000000..ef397fd79 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_background.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_background.png new file mode 100644 index 000000000..af59d9ab1 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_background.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_background_round.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_background_round.png new file mode 100644 index 000000000..481c8035a Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_background_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_foreground.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_foreground.png new file mode 100644 index 000000000..d15e45acf Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_foreground_round.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_foreground_round.png new file mode 100644 index 000000000..e82b7d0f7 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/ic_launcher.png b/TMessagesProj/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..92ef5db54 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 000000000..92ef5db54 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_background.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_background.png new file mode 100644 index 000000000..9c23c07c5 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_background.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_background_round.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_background_round.png new file mode 100644 index 000000000..8f440b41f Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_background_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_foreground.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_foreground.png new file mode 100644 index 000000000..44a050d0c Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_foreground_round.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_foreground_round.png new file mode 100644 index 000000000..0e35d7802 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/ic_launcher.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..f84bd8f92 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..f84bd8f92 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_background.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_background.png new file mode 100644 index 000000000..6fe595e31 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_background.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_background_round.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_background_round.png new file mode 100644 index 000000000..6c83d032c Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_background_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_foreground.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_foreground.png new file mode 100644 index 000000000..df3c8aa44 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_foreground_round.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_foreground_round.png new file mode 100644 index 000000000..eb7062e47 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..881369185 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..881369185 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_background.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_background.png new file mode 100644 index 000000000..16b2fee7b Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_background.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_background_round.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_background_round.png new file mode 100644 index 000000000..e1755fc07 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_background_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_foreground.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_foreground.png new file mode 100644 index 000000000..f07164647 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_foreground_round.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_foreground_round.png new file mode 100644 index 000000000..a2c257e27 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/raw/chats_archive.json b/TMessagesProj/src/main/res/raw/chats_archive.json new file mode 100755 index 000000000..75964e575 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/chats_archive.json @@ -0,0 +1 @@ +{"v":"5.5.1","fr":60,"ip":0,"op":50,"w":36,"h":36,"nm":"icArchive","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Box2","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,-57,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.56,0.56],[0,0],[-0.79,0],[0,0],[-0.56,-0.56],[0,0],[0,-0.79],[0,0]],"o":[[0,0],[0,-0.79],[0,0],[0.56,-0.56],[0,0],[0.79,0],[0,0],[0.56,0.56],[0,0],[0,0]],"v":[[-10,3],[-10,2.24],[-9.12,0.12],[-6.88,-2.12],[-4.76,-3],[4.76,-3],[6.88,-2.12],[9.12,0.12],[10,2.24],[10,3]],"c":false},"ix":2},"nm":"Contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Box2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Arrow","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.502,"y":0},"t":0,"s":[18,5.396,0],"to":[0,2.417,0],"ti":[0,-2.417,0]},{"t":20,"s":[18,19.896,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[16.667,16.667,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.927,"y":0},"t":0,"s":[{"i":[[0,0],[-0.27,0],[0,0],[0,-0.28],[0,0],[0,0],[-0.09,-0.1],[0.19,-0.19],[0,0],[0.19,0.19],[0,0],[0,0.13],[-0.28,0],[0,0]],"o":[[0,-0.28],[0,0],[0.28,0],[0,0],[0,0],[0.13,0],[0.19,0.19],[0,0],[-0.2,0.19],[0,0],[-0.1,-0.09],[0,-0.28],[0,0],[0,0]],"v":[[-2.003,-11.313],[-1.503,-11.813],[1.497,-11.813],[1.997,-11.313],[1.997,-1.896],[4.797,-1.896],[5.147,-1.746],[5.147,-1.046],[0.357,3.754],[-0.353,3.754],[-5.143,-1.046],[-5.293,-1.396],[-4.793,-1.896],[-2.003,-1.896]],"c":true}]},{"t":25,"s":[{"i":[[0,0],[-0.27,0],[0,0],[0,-0.28],[0,0],[0,0],[-0.09,-0.1],[0.19,-0.19],[0,0],[0.19,0.19],[0,0],[0,0.13],[-0.28,0],[0,0]],"o":[[0,-0.28],[0,0],[0.28,0],[0,0],[0,0],[0.13,0],[0.19,0.19],[0,0],[-0.2,0.19],[0,0],[-0.1,-0.09],[0,-0.28],[0,0],[0,0]],"v":[[-2.003,-3.396],[-1.503,-3.896],[1.497,-3.896],[1.997,-3.396],[1.997,-1.896],[4.797,-1.896],[5.147,-1.746],[5.147,-1.046],[0.357,3.754],[-0.353,3.754],[-5.143,-1.046],[-5.293,-1.396],[-4.793,-1.896],[-2.003,-1.896]],"c":true}]}],"ix":2},"nm":"Contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33,"s":[0.40000000596,0.662745118141,0.878431379795,1]},{"t":34,"s":[0.68235296011,0.701960802078,0.72549021244,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Arrow","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Box1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,19.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.203,0.203,0.667],"y":[1,1,1]},"o":{"x":[0.17,0.17,0.333],"y":[0,0,0]},"t":-2,"s":[11.667,11.667,100]},{"t":25,"s":[16.667,16.667,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.1,0],[0,0],[0,-1.1],[0,0],[1.1,0],[0,0],[0,1.1],[0,0]],"o":[[0,0],[1.1,0],[0,0],[0,1.1],[0,0],[-1.1,0],[0,0],[0,-1.1]],"v":[[-8,-8.5],[8,-8.5],[10,-6.5],[10,6.5],[8,8.5],[-8,8.5],[-10,6.5],[-10,-6.5]],"c":true},"ix":2},"nm":"Contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Box1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/chats_archiveavatar.json b/TMessagesProj/src/main/res/raw/chats_archiveavatar.json new file mode 100755 index 000000000..e38fd53a7 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/chats_archiveavatar.json @@ -0,0 +1 @@ +{"v":"5.5.1","fr":60,"ip":0,"op":50,"w":36,"h":36,"nm":"icArchiveAvatar","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Box2","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,-57,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.56,0.56],[0,0],[-0.79,0],[0,0],[-0.56,-0.56],[0,0],[0,-0.79],[0,0]],"o":[[0,0],[0,-0.79],[0,0],[0.56,-0.56],[0,0],[0.79,0],[0,0],[0.56,0.56],[0,0],[0,0]],"v":[[-10,3],[-10,2.24],[-9.12,0.12],[-6.88,-2.12],[-4.76,-3],[4.76,-3],[6.88,-2.12],[9.12,0.12],[10,2.24],[10,3]],"c":false},"ix":2},"nm":"Contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Box2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Arrow1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.001,"y":1},"o":{"x":0.505,"y":0},"t":0,"s":[18,19.896,0],"to":[0,2.25,0],"ti":[0,-2.25,0]},{"t":20,"s":[18,33.396,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[16.667,16.667,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-0.27,0],[0,0],[0,-0.28],[0,0],[0,0],[-0.09,-0.1],[0.19,-0.19],[0,0],[0.19,0.19],[0,0],[0,0.13],[-0.28,0],[0,0]],"o":[[0,-0.28],[0,0],[0.28,0],[0,0],[0,0],[0.13,0],[0.19,0.19],[0,0],[-0.2,0.19],[0,0],[-0.1,-0.09],[0,-0.28],[0,0],[0,0]],"v":[[-2.003,-3.396],[-1.503,-3.896],[1.497,-3.896],[1.997,-3.396],[1.997,-1.896],[4.797,-1.896],[5.147,-1.746],[5.147,-1.046],[0.357,3.754],[-0.353,3.754],[-5.143,-1.046],[-5.293,-1.396],[-4.793,-1.896],[-2.003,-1.896]],"c":true},"ix":2},"nm":"Contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.776470588235,0.788235294118,0.8,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Arrow1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Arrow2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.502,"y":0},"t":0,"s":[18,5.396,0],"to":[0,2.417,0],"ti":[0,-2.417,0]},{"t":20,"s":[18,19.896,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[16.667,16.667,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.927,"y":0},"t":0,"s":[{"i":[[0,0],[-0.27,0],[0,0],[0,-0.28],[0,0],[0,0],[-0.09,-0.1],[0.19,-0.19],[0,0],[0.19,0.19],[0,0],[0,0.13],[-0.28,0],[0,0]],"o":[[0,-0.28],[0,0],[0.28,0],[0,0],[0,0],[0.13,0],[0.19,0.19],[0,0],[-0.2,0.19],[0,0],[-0.1,-0.09],[0,-0.28],[0,0],[0,0]],"v":[[-2.003,-11.313],[-1.503,-11.813],[1.497,-11.813],[1.997,-11.313],[1.997,-1.896],[4.797,-1.896],[5.147,-1.746],[5.147,-1.046],[0.357,3.754],[-0.353,3.754],[-5.143,-1.046],[-5.293,-1.396],[-4.793,-1.896],[-2.003,-1.896]],"c":true}]},{"t":25,"s":[{"i":[[0,0],[-0.27,0],[0,0],[0,-0.28],[0,0],[0,0],[-0.09,-0.1],[0.19,-0.19],[0,0],[0.19,0.19],[0,0],[0,0.13],[-0.28,0],[0,0]],"o":[[0,-0.28],[0,0],[0.28,0],[0,0],[0,0],[0.13,0],[0.19,0.19],[0,0],[-0.2,0.19],[0,0],[-0.1,-0.09],[0,-0.28],[0,0],[0,0]],"v":[[-2.003,-3.396],[-1.503,-3.896],[1.497,-3.896],[1.997,-3.396],[1.997,-1.896],[4.797,-1.896],[5.147,-1.746],[5.147,-1.046],[0.357,3.754],[-0.353,3.754],[-5.143,-1.046],[-5.293,-1.396],[-4.793,-1.896],[-2.003,-1.896]],"c":true}]}],"ix":2},"nm":"Contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.776470588235,0.788235294118,0.8,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Stroke","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Arrow2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Box1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,19.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[16.667,16.667,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.1,0],[0,0],[0,-1.1],[0,0],[1.1,0],[0,0],[0,1.1],[0,0]],"o":[[0,0],[1.1,0],[0,0],[0,1.1],[0,0],[-1.1,0],[0,0],[0,-1.1]],"v":[[-8,-8.5],[8,-8.5],[10,-6.5],[10,6.5],[8,8.5],[-8,8.5],[-10,6.5],[-10,-6.5]],"c":true},"ix":2},"nm":"Contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Box1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/chats_archived.json b/TMessagesProj/src/main/res/raw/chats_archived.json new file mode 100644 index 000000000..4f39bfc99 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/chats_archived.json @@ -0,0 +1 @@ +{"v":"5.5.1","fr":60,"ip":0,"op":45,"w":36,"h":36,"nm":"icArchived","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"info1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,19.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[16.667,16.667,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-5,0.5],[-2,3.5],[5,-3.5]],"c":false},"ix":2},"nm":"contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"info1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.816],"y":[0]},"t":5,"s":[0]},{"t":20,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"trim","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":45,"st":-5,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Oval","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,17.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[16.667,16.667,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.75,0.75],[0,0],[-1.06,0],[0,0],[-0.75,-0.75],[0,0],[0,-1.06],[0,0],[1.66,0],[0,0],[0,1.66],[0,0]],"o":[[0,0],[0,-1.06],[0,0],[0.75,-0.75],[0,0],[1.06,0],[0,0],[0.75,0.75],[0,0],[0,1.66],[0,0],[-1.66,0],[0,0],[0,0]],"v":[[-11,-4.5],[-11,-5.26],[-9.83,-8.09],[-7.59,-10.33],[-4.76,-11.5],[4.76,-11.5],[7.59,-10.33],[9.83,-8.09],[11,-5.26],[11,8.5],[8,11.5],[-8,11.5],[-11,8.5],[-11,-4.5]],"c":true},"ix":2},"nm":"contour1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0.53,0],[0,0],[0.38,-0.38],[0,0],[0,0]],"o":[[0,0],[-0.38,-0.38],[0,0],[-0.53,0],[0,0],[0,0],[0,0]],"v":[[7.584,-7.5],[6.174,-8.91],[4.754,-9.5],[-4.756,-9.5],[-6.176,-8.91],[-7.586,-7.5],[7.584,-7.5]],"c":true},"ix":2},"nm":"contour2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Oval","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":45,"st":-5,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/chats_hide.json b/TMessagesProj/src/main/res/raw/chats_hide.json new file mode 100755 index 000000000..4660b0865 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/chats_hide.json @@ -0,0 +1 @@ +{"v":"5.5.1","fr":60,"ip":0,"op":50,"w":36,"h":36,"nm":"icHide","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Mask","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,17,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[16.667,16.667,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.28,0],[0,0],[0,0.28],[0,0],[0,0],[0,0],[0.28,0],[0,0],[0,-0.28],[0,0]],"o":[[0,0],[0,0.28],[0,0],[0.28,0],[0,0],[0,0],[0,0],[0,-0.28],[0,0],[-0.28,0],[0,0],[0,0]],"v":[[-7,-3.5],[-2,-3.5],[-1.5,-3],[1.5,-3],[2,-3.5],[7,-3.5],[7,3.5],[2,3.5],[1.5,3],[-1.5,3],[-2,3.5],[-7,3.5]],"c":true},"ix":2},"nm":"Contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.847000002861,0.847000002861,0.847000002861,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Mask","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Arrow","tt":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,17.606,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[16.667,-16.667,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.494,"y":0},"t":0,"s":[{"i":[[0,0],[-0.27,0],[0,0],[0,-0.28],[0,0],[0,0],[-0.09,-0.1],[0.19,-0.19],[0,0],[0.19,0.19],[0,0],[0,0.13],[-0.28,0],[0,0]],"o":[[0,-0.28],[0,0],[0.28,0],[0,0],[0,0],[0.13,0],[0.19,0.19],[0,0],[-0.2,0.19],[0,0],[-0.1,-0.09],[0,-0.28],[0,0],[0,0]],"v":[[-2.003,-10.896],[-1.503,-11.396],[1.497,-11.396],[1.997,-10.896],[1.997,-9.813],[4.797,-9.813],[5.147,-9.663],[5.147,-8.963],[0.357,-4.163],[-0.353,-4.163],[-5.143,-8.963],[-5.293,-9.313],[-4.793,-9.813],[-2.003,-9.813]],"c":true}]},{"t":20,"s":[{"i":[[0,0],[-0.27,0],[0,0],[0,-0.28],[0,0],[0,0],[-0.09,-0.1],[0.19,-0.19],[0,0],[0.19,0.19],[0,0],[0,0.13],[-0.28,0],[0,0]],"o":[[0,-0.28],[0,0],[0.28,0],[0,0],[0,0],[0.13,0],[0.19,0.19],[0,0],[-0.2,0.19],[0,0],[-0.1,-0.09],[0,-0.28],[0,0],[0,0]],"v":[[-2.003,-10.896],[-1.503,-11.396],[1.497,-11.396],[1.997,-10.896],[1.997,5.604],[4.797,5.604],[5.147,5.754],[5.147,6.454],[0.357,11.254],[-0.353,11.254],[-5.143,6.454],[-5.293,6.104],[-4.793,5.604],[-2.003,5.604]],"c":true}]}],"ix":2},"nm":"Сontour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Arrow","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Line","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,17,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.203,0.203,0.667],"y":[1,1,1]},"o":{"x":[0.17,0.17,0.333],"y":[0,0,0]},"t":0,"s":[11.667,11.667,100]},{"t":27,"s":[16.667,16.667,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-10,0],[10,0]],"c":false},"ix":2},"nm":"Contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Line","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/chats_infotip.json b/TMessagesProj/src/main/res/raw/chats_infotip.json new file mode 100644 index 000000000..bb65af0d5 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/chats_infotip.json @@ -0,0 +1 @@ +{"v":"5.5.1","fr":60,"ip":0,"op":45,"w":36,"h":36,"nm":"Lamp 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"luc12","parent":15,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":20,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-43.5,75.344,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.5,0],[-2.5,0]],"c":false},"ix":2},"nm":"contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":-60,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"luc12","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[40]},{"t":20,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.697],"y":[0.848]},"o":{"x":[0.527],"y":[0.407]},"t":2,"s":[40]},{"t":5,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":45,"st":-15,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"luc11","parent":15,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":20,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[43.5,75.344,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.5,0],[-2.5,0]],"c":false},"ix":2},"nm":"contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":60,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"luc11","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.697],"y":[0.848]},"o":{"x":[0.526],"y":[0.407]},"t":2,"s":[60]},{"t":5,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":2,"s":[60]},{"i":{"x":[0.201],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[60]},{"t":20,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":45,"st":-15,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"luc10","parent":15,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":20,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,87,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.5,0],[-2.5,0]],"c":false},"ix":2},"nm":"contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":90,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"luc10","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.697],"y":[0.848]},"o":{"x":[0.526],"y":[0.407]},"t":2,"s":[60]},{"t":5,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":2,"s":[60]},{"i":{"x":[0.201],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[60]},{"t":20,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":45,"st":-15,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"luc9","parent":15,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":20,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75.344,43.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.5,0],[-2.5,0]],"c":false},"ix":2},"nm":"contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":30,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"luc9","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.697],"y":[0.848]},"o":{"x":[0.526],"y":[0.407]},"t":2,"s":[60]},{"t":5,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":2,"s":[60]},{"i":{"x":[0.201],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[60]},{"t":20,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":45,"st":-15,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"luc8","parent":15,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":20,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[87,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.5,0],[-2.5,0]],"c":false},"ix":2},"nm":"contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"luc8","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.697],"y":[0.848]},"o":{"x":[0.526],"y":[0.407]},"t":2,"s":[60]},{"t":5,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":2,"s":[60]},{"i":{"x":[0.201],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[60]},{"t":20,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":45,"st":-15,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"luc7","parent":15,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":20,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[75.344,-43.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.5,0],[-2.5,0]],"c":false},"ix":2},"nm":"contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":-30,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"luc7","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.697],"y":[0.848]},"o":{"x":[0.526],"y":[0.407]},"t":2,"s":[60]},{"t":5,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":2,"s":[60]},{"i":{"x":[0.201],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[60]},{"t":20,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":45,"st":-15,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"luc6","parent":15,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":20,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[43.5,-75.344,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.5,0],[-2.5,0]],"c":false},"ix":2},"nm":"contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":-60,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"luc6","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.697],"y":[0.848]},"o":{"x":[0.526],"y":[0.407]},"t":2,"s":[60]},{"t":5,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":2,"s":[60]},{"i":{"x":[0.201],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[60]},{"t":20,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":45,"st":-15,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"luc5","parent":15,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":20,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,-87,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.5,0],[-2.5,0]],"c":false},"ix":2},"nm":"contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":90,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"luc5","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[40]},{"t":20,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.697],"y":[0.848]},"o":{"x":[0.527],"y":[0.407]},"t":2,"s":[40]},{"t":5,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":45,"st":-15,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"luc4","parent":15,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":20,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-43.5,-75.344,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.5,0],[-2.5,0]],"c":false},"ix":2},"nm":"contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":60,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"luc4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[40]},{"t":20,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.697],"y":[0.848]},"o":{"x":[0.527],"y":[0.407]},"t":2,"s":[40]},{"t":5,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":45,"st":-15,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"luc3","parent":15,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":20,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-75.344,-43.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.5,0],[-2.5,0]],"c":false},"ix":2},"nm":"contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":30,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"luc3","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[40]},{"t":20,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.697],"y":[0.848]},"o":{"x":[0.527],"y":[0.407]},"t":2,"s":[40]},{"t":5,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":45,"st":-15,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"luc2","parent":15,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":20,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-87,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.5,0],[-2.5,0]],"c":false},"ix":2},"nm":"contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"luc2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[40]},{"t":20,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.697],"y":[0.848]},"o":{"x":[0.527],"y":[0.407]},"t":2,"s":[40]},{"t":5,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":45,"st":-15,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"luc1","parent":15,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":20,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-75.344,43.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.5,0],[-2.5,0]],"c":false},"ix":2},"nm":"contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":-30,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"luc1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[40]},{"t":20,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.697],"y":[0.848]},"o":{"x":[0.527],"y":[0.407]},"t":2,"s":[40]},{"t":5,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":45,"st":-15,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"info1","parent":15,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,14,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,3],[0,-3]],"c":false},"ix":2},"nm":"contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.223529411765,0.262745098039,0.309803921569,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"info1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.799],"y":[0]},"t":5,"s":[0]},{"t":15,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"trim","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":45,"st":-15,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"info2","parent":15,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":15,"s":[0,-4,0],"to":[0,-2,0],"ti":[0,4.999,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":23,"s":[0,-39,0],"to":[0,-5.001,0],"ti":[0,2,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":31,"s":[0,-24,0],"to":[0,-4,0],"ti":[0,0,0]},{"t":39,"s":[0,-28,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":15,"s":[67,67,100]},{"t":25,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.83,0],[0,0.83],[0.83,0],[0,-0.83]],"o":[[0.83,0],[0,-0.83],[-0.83,0],[0,0.83]],"v":[[0,1.5],[1.5,0],[0,-1.5],[-1.5,0]],"c":true},"ix":2},"nm":"contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.223529411765,0.262745098039,0.309803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"info2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":15,"op":45,"st":-15,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"Oval","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,18,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.203,0.203,0.667],"y":[1,1,1]},"o":{"x":[0.17,0.17,0.333],"y":[0,0,0]},"t":2,"s":[11.667,11.667,100]},{"t":27,"s":[16.667,16.667,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[24,24],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"contour","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Oval","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":45,"st":-15,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/chats_swipearchive.json b/TMessagesProj/src/main/res/raw/chats_swipearchive.json new file mode 100644 index 000000000..298f3b065 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/chats_swipearchive.json @@ -0,0 +1 @@ +{"v":"5.5.1","fr":60,"ip":0,"op":120,"w":36,"h":48,"nm":"icswipe 4","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"luc4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[18]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":75,"s":[18]},{"t":90,"s":[18]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[37.333]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":75,"s":[22.375]},{"t":90,"s":[23.5]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":60,"s":[5.333,5.333,100]},{"t":75,"s":[16.667,16.667,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,1.66],[0,0],[-0.75,0.75],[0,0],[-1.06,0],[0,0],[-0.75,-0.75],[0,0],[0,-1.06],[0,0],[1.66,0],[0,0]],"o":[[0,0],[0,-1.06],[0,0],[0.75,-0.75],[0,0],[1.06,0],[0,0],[0.75,0.75],[0,0],[0,1.66],[0,0],[-1.66,0]],"v":[[-11,8.5],[-11,-5.26],[-9.83,-8.09],[-7.59,-10.33],[-4.76,-11.5],[4.76,-11.5],[7.59,-10.33],[9.83,-8.09],[11,-5.26],[11,8.5],[8,11.5],[-8,11.5]],"c":true},"ix":2},"nm":"contour1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0.53,0],[0,0],[0.38,-0.38],[0,0]],"o":[[0,0],[-0.38,-0.38],[0,0],[-0.53,0],[0,0],[0,0]],"v":[[7.584,-7.5],[6.174,-8.91],[4.754,-9.5],[-4.756,-9.5],[-6.176,-8.91],[-7.586,-7.5]],"c":true},"ix":2},"nm":"contour2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,-0.28],[0,0],[0,0],[0,-0.28],[-0.1,-0.09],[0,0],[-0.2,0.19],[0,0],[0.19,0.19],[0.13,0],[0,0],[0,0],[0.28,0],[0,0]],"o":[[0,0],[0,0],[-0.28,0],[0,0.13],[0,0],[0.19,0.19],[0,0],[0.19,-0.19],[-0.09,-0.1],[0,0],[0,0],[0,-0.28],[0,0],[-0.27,0]],"v":[[-2.003,-1],[-2.003,0.5],[-4.793,0.5],[-5.293,1],[-5.143,1.35],[-0.353,6.15],[0.357,6.15],[5.147,1.35],[5.147,0.65],[4.797,0.5],[1.997,0.5],[1.997,-1],[1.497,-1.5],[-1.503,-1.5]],"c":true},"ix":2},"nm":"contour3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"unite","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"luc4","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":60,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"luc3","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[0]},{"t":30,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.331,"y":1},"o":{"x":0.333,"y":0},"t":30,"s":[18,17.333,0],"to":[0,3.333,0],"ti":[0,-3.333,0]},{"t":60,"s":[18,37.333,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[12.5,12.5,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":30,"s":[16.667,16.667,100]},{"t":60,"s":[8.333,8.333,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[16,16],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"contour","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"luc3","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"luc2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[20]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[20]},{"t":35,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,17.333,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.398,0.398,0.593],"y":[1,1,-22.251]},"o":{"x":[0.202,0.202,0.175],"y":[0.15,0.15,10.582]},"t":0,"s":[0,0,100]},{"t":20,"s":[30,30,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[16,16],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"contour","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"luc2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"luc1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.297],"y":[0]},"t":30,"s":[20]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":48,"s":[20]},{"t":60,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,27.333,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[16.667,16.667,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.336,"y":1},"o":{"x":0.333,"y":0},"t":30,"s":[{"i":[[0,-4.418],[0,0],[4.418,0],[0,4.418],[0,0],[-4.418,0]],"o":[[0,0],[0,4.418],[-4.418,0],[0,0],[0,-4.418],[4.418,0]],"v":[[8,-10],[8,-10],[0,-2],[-8,-10],[-8,-10],[0,-18]],"c":true}]},{"t":60,"s":[{"i":[[0,-4.418],[0,0],[4.418,0],[0,4.418],[0,0],[-4.418,0]],"o":[[0,0],[0,4.418],[-4.418,0],[0,0],[0,-4.418],[4.418,0]],"v":[[8,-6.667],[8,10],[0,18],[-8,10],[-8,-6.667],[0,-14.667]],"c":true}]}],"ix":2},"nm":"contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"luc1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":120,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/chats_unarchive.json b/TMessagesProj/src/main/res/raw/chats_unarchive.json new file mode 100755 index 000000000..c49e36d93 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/chats_unarchive.json @@ -0,0 +1 @@ +{"v":"5.5.1","fr":60,"ip":0,"op":50,"w":36,"h":36,"nm":"icUnArchive","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Mask","parent":6,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.48,"y":0},"t":0,"s":[0,0,0],"to":[0,5,0],"ti":[0,-5,0]},{"t":25,"s":[0,30,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.48,"y":0},"t":0,"s":[{"i":[[-1.1,0],[0,0],[0,-1.1],[0,0],[1.1,0],[0,0],[0,1.1],[0,0]],"o":[[0,0],[1.1,0],[0,0],[0,1.1],[0,0],[-1.1,0],[0,0],[0,-1.1]],"v":[[-8,-9.438],[8,-9.438],[10,-7.438],[10,7.469],[8,9.469],[-8,9.469],[-10,7.469],[-10,-7.438]],"c":true}]},{"t":25,"s":[{"i":[[-1.1,0],[0,0],[0,-1.1],[0,0],[1.1,0],[0,0],[0,1.1],[0,0]],"o":[[0,0],[1.1,0],[0,0],[0,1.1],[0,0],[-1.1,0],[0,0],[0,-1.1]],"v":[[-8,-4.438],[8,-4.438],[10,-2.438],[10,2.5],[8,4.5],[-8,4.5],[-10,2.5],[-10,-2.438]],"c":true}]}],"ix":2},"nm":"Contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Mask","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Arrow2","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.483,"y":0},"t":0,"s":[18,19.23,0],"to":[0,-1.722,0],"ti":[0,1.722,0]},{"t":25,"s":[18,8.896,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[16.667,-16.667,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-0.27,0],[0,0],[0,-0.28],[0,0],[0,0],[-0.09,-0.1],[0.19,-0.19],[0,0],[0.19,0.19],[0,0],[0,0.13],[-0.28,0],[0,0]],"o":[[0,-0.28],[0,0],[0.28,0],[0,0],[0,0],[0.13,0],[0.19,0.19],[0,0],[-0.2,0.19],[0,0],[-0.1,-0.09],[0,-0.28],[0,0],[0,0]],"v":[[-2.003,-3.396],[-1.503,-3.896],[1.497,-3.896],[1.997,-3.396],[1.997,-1.896],[4.797,-1.896],[5.147,-1.746],[5.147,-1.046],[0.357,3.754],[-0.353,3.754],[-5.143,-1.046],[-5.293,-1.396],[-4.793,-1.896],[-2.003,-1.896]],"c":true},"ix":2},"nm":"Contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.682352941176,0.701960784314,0.725490196078,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Arrow2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Box2","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.48,"y":0},"t":0,"s":[0,-57,0],"to":[0,10,0],"ti":[0,-10,0]},{"t":25,"s":[0,3,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.56,0.56],[0,0],[-0.79,0],[0,0],[-0.56,-0.56],[0,0],[0,-0.79],[0,0]],"o":[[0,0],[0,-0.79],[0,0],[0.56,-0.56],[0,0],[0.79,0],[0,0],[0.56,0.56],[0,0],[0,0]],"v":[[-10,3],[-10,2.24],[-9.12,0.12],[-6.88,-2.12],[-4.76,-3],[4.76,-3],[6.88,-2.12],[9.12,0.12],[10,2.24],[10,3]],"c":false},"ix":2},"nm":"Contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Box2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Box1","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.48,"y":0},"t":0,"s":[0,0,0],"to":[0,5,0],"ti":[0,-5,0]},{"t":25,"s":[0,30,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.48,"y":0},"t":0,"s":[{"i":[[-1.1,0],[0,0],[0,-1.1],[0,0],[1.1,0],[0,0],[0,1.1],[0,0]],"o":[[0,0],[1.1,0],[0,0],[0,1.1],[0,0],[-1.1,0],[0,0],[0,-1.1]],"v":[[-8,-8.5],[8,-8.5],[10,-6.5],[10,6.5],[8,8.5],[-8,8.5],[-10,6.5],[-10,-6.5]],"c":true}]},{"t":25,"s":[{"i":[[-1.1,0],[0,0],[0,-1.1],[0,0],[1.1,0],[0,0],[0,1.1],[0,0]],"o":[[0,0],[1.1,0],[0,0],[0,1.1],[0,0],[-1.1,0],[0,0],[0,-1.1]],"v":[[-8,-3.5],[8,-3.5],[10,-1.5],[10,1.5],[8,3.5],[-8,3.5],[-10,1.5],[-10,-1.5]],"c":true}]}],"ix":2},"nm":"Contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Box1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Arrow1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.483,"y":0},"t":0,"s":[18,19.23,0],"to":[0,-1.722,0],"ti":[0,1.722,0]},{"t":25,"s":[18,8.896,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[16.667,-16.667,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-0.27,0],[0,0],[0,-0.28],[0,0],[0,0],[-0.09,-0.1],[0.19,-0.19],[0,0],[0.19,0.19],[0,0],[0,0.13],[-0.28,0],[0,0]],"o":[[0,-0.28],[0,0],[0.28,0],[0,0],[0,0],[0.13,0],[0.19,0.19],[0,0],[-0.2,0.19],[0,0],[-0.1,-0.09],[0,-0.28],[0,0],[0,0]],"v":[[-2.003,-3.396],[-1.503,-3.896],[1.497,-3.896],[1.997,-3.396],[1.997,-1.896],[4.797,-1.896],[5.147,-1.746],[5.147,-1.046],[0.357,3.754],[-0.353,3.754],[-5.143,-1.046],[-5.293,-1.396],[-4.793,-1.896],[-2.003,-1.896]],"c":true},"ix":2},"nm":"Contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Arrow1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0},{"ddd":0,"ind":6,"ty":3,"nm":"Box1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,19.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.203,0.203,0.667],"y":[1,1,1]},"o":{"x":[0.17,0.17,0.333],"y":[0,0,0]},"t":-2,"s":[13.333,13.333,100]},{"t":25,"s":[16.667,16.667,100]}],"ix":6}},"ao":0,"ip":0,"op":50,"st":-10,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/chats_unhide.json b/TMessagesProj/src/main/res/raw/chats_unhide.json new file mode 100755 index 000000000..369520228 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/chats_unhide.json @@ -0,0 +1 @@ +{"v":"5.5.1","fr":60,"ip":0,"op":50,"w":36,"h":36,"nm":"icUnHide","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Mask","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,17,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[16.667,-16.667,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.28,0],[0,0],[0,0.28],[0,0],[0,0],[0,0],[0.28,0],[0,0],[0,-0.28],[0,0]],"o":[[0,0],[0,0.28],[0,0],[0.28,0],[0,0],[0,0],[0,0],[0,-0.28],[0,0],[-0.28,0],[0,0],[0,0]],"v":[[-7,-3.5],[-2,-3.5],[-1.5,-3],[1.5,-3],[2,-3.5],[7,-3.5],[7,3.5],[2,3.5],[1.5,3],[-1.5,3],[-2,3.5],[-7,3.5]],"c":true},"ix":2},"nm":"Contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.847000002861,0.847000002861,0.847000002861,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Mask","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Arrow","tt":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,17.606,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[16.667,16.667,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.494,"y":0},"t":0,"s":[{"i":[[0,0],[-0.27,0],[0,0],[0,-0.28],[0,0],[0,0],[-0.09,-0.1],[0.19,-0.19],[0,0],[0.19,0.19],[0,0],[0,0.13],[-0.28,0],[0,0]],"o":[[0,-0.28],[0,0],[0.28,0],[0,0],[0,0],[0.13,0],[0.19,0.19],[0,0],[-0.2,0.19],[0,0],[-0.1,-0.09],[0,-0.28],[0,0],[0,0]],"v":[[-2.003,-10.896],[-1.503,-11.396],[1.497,-11.396],[1.997,-10.896],[1.997,-9.813],[4.797,-9.813],[5.147,-9.663],[5.147,-8.963],[0.357,-4.163],[-0.353,-4.163],[-5.143,-8.963],[-5.293,-9.313],[-4.793,-9.813],[-2.003,-9.813]],"c":true}]},{"t":20,"s":[{"i":[[0,0],[-0.27,0],[0,0],[0,-0.28],[0,0],[0,0],[-0.09,-0.1],[0.19,-0.19],[0,0],[0.19,0.19],[0,0],[0,0.13],[-0.28,0],[0,0]],"o":[[0,-0.28],[0,0],[0.28,0],[0,0],[0,0],[0.13,0],[0.19,0.19],[0,0],[-0.2,0.19],[0,0],[-0.1,-0.09],[0,-0.28],[0,0],[0,0]],"v":[[-2.003,-10.896],[-1.503,-11.396],[1.497,-11.396],[1.997,-10.896],[1.997,5.604],[4.797,5.604],[5.147,5.754],[5.147,6.454],[0.357,11.254],[-0.353,11.254],[-5.143,6.454],[-5.293,6.104],[-4.793,5.604],[-2.003,5.604]],"c":true}]}],"ix":2},"nm":"Сontour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Arrow","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Line","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18,17,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.203,0.203,0.667],"y":[1,1,1]},"o":{"x":[0.17,0.17,0.333],"y":[0,0,0]},"t":0,"s":[11.667,11.667,100]},{"t":27,"s":[16.667,16.667,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-10,0],[10,0]],"c":false},"ix":2},"nm":"Contour","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Line","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":50,"st":-10,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-ar/strings.xml b/TMessagesProj/src/main/res/values-ar/strings.xml index 90653ebf8..456eae269 100644 --- a/TMessagesProj/src/main/res/values-ar/strings.xml +++ b/TMessagesProj/src/main/res/values-ar/strings.xml @@ -15,7 +15,7 @@ تم تسجيل الدخول إلى هذا الحساب من هذا التطبيق. تبديل مزامنة جهات الاتصال - سيؤدي هذا إلى حذف جهات اتصالك من خوادم تيليجرام، إذا كان خيار «مزامنة جهات الاتصال» مفعلا فستتم إعادة مزامنتها تلقائيًا. + سيؤدي هذا إلى حذف جهات اتصالك من خوادم تيليجرام، إذا كان خيار «مزامنة جهات الاتصال» مفعَّلا فستتم إعادة مزامنتها تلقائيًا. ستتم إضافة جهات اتصال هذا الجهاز إلى هذا الحساب. لن يتم إضافة جهات اتصال هذا الجهاز إلى هذا الحساب. ستتم إضافة جهات اتصال جهازك هذا إلى حسابك. @@ -38,7 +38,7 @@ لم يصلك الرمز؟ إرسال الرمز برسالة SMS قصيرة إلغاء إعادة تعيين الحساب - شخص ما لديه صلاحية الوصول لرقمك **%1$s** طلب حذف حسابك وتعطيل التحقق بخطوتين من حسابك.\n\nإن لم يكن أنت، فقم رجاء بإدخال الرمز الذي أرسلناه للتوِّ برسالة SMS قصيرة. + شخص ما لديه صلاحية الوصول لرقمك **%1$s** طلب حذف حسابك وتعطيل التحقق بخطوتين من حسابك.\n\nإذا لم تكن أنت من قام بذلك فقم رجاء بإدخال الرمز الذي أرسلناه للتوِّ برسالة SMS قصيرة. إعادة تعيين الحساب نظرًا لأن الحساب **%1$s** نشطٌ ومحميٌ بكلمة مرور؛ سنقوم بحذفه خلال أسبوع لدواعٍ أمنية.\n\nيمْكنك إلغاء هذه العملية في أي وقت. ستتمكن من إعادة تعيين حسابك خلال: @@ -49,7 +49,7 @@ رمز الدخول هو **%1$s**. قم بإدخاله في تطبيق تيليجرام الذي تحاول تسجيل الدخول منه.\n\nلا تعطِ هذا الرمز لأي شخص كان. اسمك - يرجى إدخال اسمك الكامل ورفع صورتك الشخصية. + يرجى إدخال اسمك الكامل واختيار صورة لملفك الشخصي. الاسم الأول (مطلوب) اسم العائلة (اختياري) إلغاء التسجيل @@ -86,8 +86,8 @@ مراجعة العملية هل ترغب حقًا في تحويل %1$s إلى البوت %2$s مقابل %3$s؟ الإجمالي - الفاتورة - الفاتورة التجريبية + فاتورة + فاتورة تجريبية ادفع %1$s وسيلة الدفع موفِّر عملية الدفع @@ -144,12 +144,26 @@ لقد انضممت للمحادثة السرية مسح محتوى المحادثة تم مسح المحتوى. + كتم + إلغاء الكتم تم حذف المحادثة. تم حذف المجموعة. تم حذف القناة. + تم تثبيت الأرشيف. + اسحب الأرشيف لليسار لإخفاءه. + تم إخفاء الأرشيف. + اسحب للأسفل لرؤية الأرشيف. + تمت أرشفة المحادثة. + تمت أرشفة المحادثات. + اسحب الأرشيف لليسار لإخفاءه. تراجع حذف من الذاكرة المؤقتة حذف وخروج + إخفاء + تثبيت + أرشفة + إلغاء الأرشفة + المحادثات المؤرشفة حذف المحادثة حساب محذوف اختر محادثة @@ -176,6 +190,7 @@ %1$s بواسطة %2$s اكتب رأيك حول هذا الإستعراض إرسال الملصق + إرسال الصورة المتحركة عرض الحزمة تثبيت في الأعلى المعذرة، لا يمكنك تثبيت أكثر من %1$s محادثات بالأعلى. @@ -190,6 +205,12 @@ ليس الآن الاستمرار جهات اتصالك في تيليجرام + هذا هو أرشيفك + سيتم إلغاء أرشفة المحادثات غير المكتومة عند وصول رسائل جديدة إليها. + المحادثات المكتومة + ستبقى المحادثات المكتومة داخل الأرشيف عند وصول رسائل جديدة إليها. + تثبيت المحادثات + يمكنك تثبيت عدد غير محدود من المحادثات المؤرشفة في الأعلى. ترقية إلى مشرف تعديل صلاحيات المشرف @@ -231,20 +252,20 @@ قناة جديدة اسم القناة إضافة جهات اتصالك لقناتك - يمكن للناس مشاركة هذا الرابط مع بعضهم، كما يمكنهم إيجاد قناتك عبر البحث في تيليجرام. - يمكن للناس مشاركة هذا الرابط مع بعضهم، كما يمكنهم إيجاد مجموعتك عبر البحث في تيليجرام. + إذا قمت بتعيين رابط عام دائم للقناة فسيتمكن الآخرون من العثور عليها والانضمامِ إليها عبره.\n\nيمكنك استخدام الأحرف الإنجليزية والشَّرطاتِ السفلية.\n\nالحد الأدنى هو خمسُ خانات. + إذا قمت بتعيين رابط عام دائم للمجموعة فسيتمكن الآخرون من العثور عليها والانضمامِ إليها عبره.\n\nيمكنك استخدام الأحرف الإنجليزية والشَّرطاتِ السفلية.\n\nالحد الأدنى هو خمسُ خانات. الرابط يمكن للناس الانضمام لقناتك عبر هذا الرابط، بإمكانك استبداله في أي وقت. - يمكن للناس الانضمام لمجموعتك عبر هذا الرابط، بإمكانك استبداله في أي وقت. + يمكن للناس الانضمام لمجموعتك عبر هذا الرابط، يمكنك استبداله في أي وقت. الوصف (اختياري) الوصف يمكنك إضافة وصف اختياري لقناتك. - لقد قمت بتغيير بعض الإعدادات في هذه المجموعة. تطبيق التغييرات؟ - لقد قمت بتغيير بعض الإعدادات في هذه القناة. تطبيق التغييرات؟ + لقد قمت بتغيير بعض الإعدادات في هذه المجموعة؛ تطبيق التغييرات؟ + لقد قمت بتغيير بعض الإعدادات في هذه القناة؛ تطبيق التغييرات؟ قناة عامة مجموعة عامة يمكن العثور على القنوات العامة عبر البحث ويمكن لأي شخص الانضمام لها. - يمكن العثور على المجموعات العامة من خلال البحث، سجل المحادثة متاح للجميع، ويمكن لأي شخص الانضمام إليها. + يمكن العثور على المجموعات العامة عبر البحث، سيكون محتوى المجموعة متاحًا للجميع، ويمكن لأي شخص الانضمام إليها. قناة خاصة مجموعة خاصة يمكن الانضمام للقنوات الخاصة عن طريق رابط الدعوة فقط. @@ -281,6 +302,11 @@ إضافة استثناء بحث في الاستثناءات مستخدمون تمت إزالتهم + Contacts in this channel + Contacts in this group + Bots + Other members + Other subscribers المستخدمون المقيدون المشرفون حذف القناة @@ -330,18 +356,19 @@ نشرت %1$s رسالة نشرت %1$s صورة نشرت %1$s مقطعًا مرئيًا - نشرت %1$s جهة اتصال - نشرت %1$s استفتاءًا + %1$s posted a contact %2$s + %1$s posted a poll %2$s نشرت %1$s موقعًا نشرت %1$s موقعًا حيًا نشرت %1$s ملفًا نشرت %1$s صورةً متحركة نشرت %1$s %2$s + %1$s posted an album نشرت %1$s رسالةً صوتية نشرت %1$s رسالةً مرئية نشرت %1$s ملفًا صوتيًا نشرت %1$s ملصقًا - نشرت %1$s ملصق %2$s + نشرت %1$s ملصقًا %2$s من يمْكنه إضافة أعضاء؟ جميع الأعضاء المشرفون فقط @@ -366,7 +393,7 @@ تمت ترقيته من قبل %1$s لا يمكنك تعديل صلاحيات هذا المشرف. لا يمكنك تعديل هذه الصلاحية. - هذه الصلاحية ليست متوفرة في المجموعات العامة. + هذه الصلاحية ليست متاحةً في المجموعات العامة. تمت إزالته من قبل %1$s صلاحيات المستخدم تم تعطيل هذا الخيار لجميع الأعضاء في صلاحيات المجموعة. @@ -380,20 +407,20 @@ تغيير معلومات المحادثة تثبيت الرسائل إضافة مستخدمين - لا يمكنه قراءة الرسائل + لا يمكنه القراءة لا يمكنه إرسال الرسائل - بلا وسائط - بلا استفتاءات - بلا ملصقات وصور متحركة - لا يمكنه تضمين روابط - لا يمكنه تغيير معلومات المجموعة - بلا تثبيت + لا وسائط + لا استفتاءات + لا ملصقات وصور متحركة + لا روابط مضمَّنة + لا يمكنه تغيير المعلومات + لا تثبيت رسائل لا يمكنه إضافة مستخدمين المدة للأبد حظر وإزالة من المجموعة تطبيق التغييرات؟ - لقد قمت بتغيير حقوق هذا المستخدم في **%1$s**. تطبيق التغييرات؟ + لقد قمت بتغيير صلاحيات هذا المستخدم في **%1$s**؛ تطبيق التغييرات؟ إدارة المجموعة إدارة القناة إدارة المجموعة @@ -422,9 +449,9 @@ اختيار من المعرض البحث في الويب الإحصائيات - يمكن إضافة البوتات فقط كمشرفين. - المعذرة، يمكن إضافة البوتات إلى القنوات فقط كمشرفين. - جعله مشرفًا + يمكن إضافة البوتات كمشرفين فقط. + المعذرة، يمكن إضافة البوتات إلى القنوات كمشرفين فقط. + تعيينُه كمشرف سيتم إزالة %1$s من المشرفين إذا قمت بتقييده. استفتاء جديد @@ -434,11 +461,11 @@ خيارات الاستفتاء إضافة خيار آخر... يمكنك إضافة %1$s. - لقد قمت بإضافة الحد الأقصى من الخيارات. + لقد قمت بإضافة العدد الأقصى من الخيارات. استفتاء سري إيقاف الاستفتاء إيقاف الاستفتاء؟ - إذا قمت بإيقاف الاستفتاء الآن، لن يتمكن أي أحد من التصويت عليه. لا يمكنك التراجع عن هذا القرار. + إذا قمت بإيقاف الاستفتاء الآنَ فلن يتمكن أي أحد من التصويت عليه، لا يمكنك التراجع عن هذا القرار. تجاهل الاستفتاء؟ هل ترغب حقًا في تجاهل هذا الاستفتاء؟ سحب الصوت @@ -451,7 +478,7 @@ %1$d صوتًا %1$d صوت %1$d خيار إضافي - خيارٌ واحد إضافي + خيارٍ واحد إضافي خيارين إضافيين %1$d خيارات إضافية %1$d خيارًا إضافيًا @@ -495,8 +522,8 @@ حذف un1 هذه الرسالة: un1 غير حزمة ملصقات المجموعة \nun1 أزال حزمة ملصقات المجموعة - un1 غير رابط المجموعة: - un1 غير رابط القناة: + غيّرَ un1 رابط المجموعة: + غيّرَ un1 رابط القناة: un1 أزال رابط المجموعة un1 أزال رابط القناة الرابط السابق @@ -509,8 +536,8 @@ un1 عطّل دعوات المجموعة فعّل un1 التواقيع عطّل un1 التواقيع - غيّر صلاحيات %1$s\n\nالمدة: %2$s - غيّر الصلاحيات الافتراضية + غيَّر صلاحيات %1$s\n\nالمدة: %2$s + غيَّر الصلاحيات الافتراضية إرسال الملصقات والصور المتحركة إرسال الوسائط تغيير المعلومات @@ -520,7 +547,7 @@ إرسال الرسائل تضمين روابط قراءة الرسائل - غير صلاحيات %1$s + غيّرَ صلاحيات %1$s تغيير معلومات القناة تغيير معلومات المجموعة نشر الرسائل @@ -560,7 +587,7 @@ خطأ في الوصول لا يمكن أن يتجاوز حجم الملف %1$s الذاكرة غير موجودة - نقل USB مفعل + نقل USB مفعَّل الذاكرة الداخلية الذاكرة الخارجية جذر النظام @@ -571,7 +598,7 @@ ملصقات المجموعة اختر من ملصقاتك - يمكنك اختيار حزمة لتكون متوفرة لكل أعضاء هذه المجموعة أثناء المراسلة فيها. + يمكنك اختيار حزمة لتَكون متاحةً لكل أعضاء هذه المجموعة أثناء المراسلة فيها. اختيار حزمة ملصقات رابط الحزمة يمكنك إنشاء حزم الملصقات الخاصة بك عن طريق البوت stickers@. @@ -631,8 +658,8 @@ تمنع تحويل الرسائل منها تمت إزالتك من هذه المجموعة لقد قمت بمغادرة المجموعة - حذف هذه المجموعة - حذف هذه الدردشة + حذف هذه المحادثة + حذف هذه المحادثة اسحب للإلغاء حفظ في الجهاز حفظ في الصور المتحركة @@ -653,7 +680,7 @@ إرسال كملفات هل ترغب في فتح الرابط %1$s؟ إلغاء الإرسال - هل ترغب في السماح لـ %1$s بإرسال اسمك ورقم هويتك على تيليجرام (ليس رقم هاتفك) إلى الصفحات التي تفتحها من خلال هذا البوت؟ + هل ترغب في السماح لـ %1$s بإرسال اسمك وهويتك على تيليجرام للصفحات التي تفتحها عبر هذا البوت؟\n\nهويتك ليست رقمَ هاتفك. تبليغ عن إزعاج تبليغ عن إزعاج ومغادرة إضافة جهة اتصال @@ -679,6 +706,14 @@ إبلاغ عن إزعاج حذف جميع مشاركات %1$s مسح الرموز التعبيرية الأخيرة؟ + الابتسامات والناس + حيوانات وطبيعة + أطعمة وأشربة + أنشطة + التنقل والأماكن + أدوات + رموز + أعلام تبليغ تم إرسال البلاغ إزعاج @@ -703,11 +738,11 @@ قم بتحويل الرسائل إلى هنا لحفظها. أنت قمت بإنشاء **مجموعة**. - يمكن للمجموعات: - إحتواء حتى 200,000 عضو - إمتلاك سجل محادثة موحّد - إمتلاك روابط t.me عامة - إمتلاك مشرفين بصلاحيات مختلفة + يمكن للمجموعات أن: + تضمَّ حتى 200,000 عضو + تمتلكَ سجل محادثة موحدًا + تمتلكَ روابط مثل T.me/Group + يديرَها مشرفون بصلاحيات مختلفة قم بتحويل الرسائل إلى هنا لحفظها أرسل الوسائط والملفات لحفظها افتح هذه المحادثة عبر أي جهاز من أجهزتك @@ -727,19 +762,23 @@ مشرفو هذه المجموعة قيدوك من إرسال الوسائط إليها حتى %1$s مشرفو هذه المجموعة قيدوك من من إرسال محتوى استعلامي إليها حتى %1$s مشرفو هذه المجموعة قيدوك من إرسال الملصقات إليها حتى %1$s + قام مشرفو هذه المجموعة بتقييدك من إرسال الصور المتحركة إليها حتى %1$s مشرفو هذه المجموعة قيدوك من الكتابة فيها حتى %1$s قام مشرفو هذه المجموعة بتقييدك من إرسال الوسائط إليها. مشرفو هذه المجموعة قيدوك من إرسال محتوى استعلامي إليها قام مشرفو هذه المجموعة بتقييدك من إرسال الملصقات. + قام مشرفو هذه المجموعة بتقييدك من إرسال الصور المتحركة إليها. قام مشرفو هذه المجموعة بتقييدك من الكتابة هنا. - ليس من المسموح إرسال الوسائط إلى هذه المجموعة. - ليس من المسموح إرسال أي محتوى استعلامي إلى هذه المجموعة. - ليس من المسموح إرسال الملصقات إلى هذه المجموعة. - ليس من المسموح إرسال الرسائل إلى هذه المجموعة. + لا يُسمحُ بإرسال الوسائط في هذه المجموعة. + لا يُسمحُ بإرسال محتوى استعلامي في هذه المجموعة. + لا يُسمحُ بإرسال الملصقات في هذه المجموعة. + لا يُسمحُ بإرسال الصور المتحركة في هذه المجموعة. + لا يُسمحُ بكتابة الرسائل في هذه المجموعة. مشرف "تثبيت ملفات APK محظور لهذا التطبيق، يمكنك السماح بهذا من إعدادات النظام. " الرسائل غير المقروءة بحث عن حزم الملصقات + بحث الرموز التعبيرية الرابط مزود معاينة الخرائط اختيار مزود معاينة الخرائط @@ -748,6 +787,7 @@ ياندكس بلا معاينات تثبيت خرائط جوجل؟ + احتيالي عيّن %1$s عداد التدمير الذاتي ليصبح %2$s قمت بتعيين عداد التدمير الذاتي ليصبح %1$s @@ -756,6 +796,7 @@ لديك رسالة جديدة %1$s: %2$s أرسل لك %1$s %2$s + %1$s sent you an album حوَّل %1$s %2$s إليك أرسل لك %1$s رسالةً أرسل لك %1$s صورةً @@ -763,11 +804,12 @@ أرسل لك %1$s فاتورة %2$s أرسل لك %1$s صورةً ذاتية التدمير أرسل لك %1$s مقطعًا مرئيًا ذاتي التدمير - %1$s شارك جهة اتصال معك - أرسل لك %1$s استفتاءًا + %1$s shared a contact %2$s with you + أرسل لك %1$s الاستفتاء %2$s أرسل لك %1$s موقعًا أرسل لك %1$s موقعًا حيًا %1$s دعاك للعب %2$s + أحرز %1$s %3$s في لعبة %2$s " أرسل لك %1$s ملفًا" أرسل لك %1$s صورةً متحركة أرسل لك %1$s رسالةً صوتية @@ -776,64 +818,68 @@ أرسل لك %1$s ملصقًا أرسل لك %1$s ملصق %2$s %1$s @ %2$s: %3$s - أرسل %1$s رسالة للمجموعة %2$s + أرسل %1$s رسالةً لمجموعة %2$s أرسل %1$s صورة لمجموعة %2$s أرسل %1$s مقطعًا مرئيًا لمجموعة %2$s - أرسل %1$s استفتاءًا إلى مجموعة %2$s - %1$s شارك جهة اتصال مع المجموعة %2$s - %1$s أرسل موقعًا حيًا للمجموعة %2$s + أرسل %1$s الاستفتاء %3$s في مجموعة %2$s + شارك %1$s جهة اتصال %3$s مع مجموعة %2$s + أرسل %1$s موقعًا حيًا لمجموعة %2$s شارك %1$s موقعه الحي مع مجموعة %2$s - %1$s دعا المجموعة %2$s للعب %3$s + دعا %1$s مجموعة %2$s للعب %3$s + %1$s scored %4$s in game %3$s in the group %2$s أرسل %1$s ملفًا لمجموعة %2$s - أرسل %1$s صورةً متحركةً لمجموعة %2$s - %1$s أرسل فاتورة إلى المجموعة %2$s لقاء %3$s + أرسل %1$s صورةً متحركة لمجموعة %2$s + أرسل %1$s فاتورةً لمجموعة %2$s لقاء %3$s أرسل %1$s رسالةً صوتيةً لمجموعة %2$s أرسل %1$s رسالةً مرئيةً لمجموعة %2$s أرسل %1$s ملفًا صوتيًا لمجموعة %2$s أرسل %1$s ملصقًا لمجموعة %2$s أرسل %1$s ملصق %3$s لمجموعة %2$s - %1$s أضافك إلى المجموعة %2$s + أضافك %1$s لمجموعة %2$s %1$s انضم للمجموعة %2$s - غيّر %1$s صورة المجموعة %2$s + غيّرَ %1$s صورة مجموعة %2$s %1$s أضاف %3$s للمجموعة %2$s - %1$s عاد إلى المجموعة %2$s - %1$s انضم للمجموعة %2$s + عاد %1$s لمجموعة %2$s + انضم %1$s لمجموعة %2$s %1$s أزال %3$s من المجموعة %2$s - %1$s أزالك من المجموعة %2$s - %1$s غادر المجموعة %2$s + أزالك %1$s من مجموعة %2$s + غادر %1$s مجموعة %2$s انضم %1$s لتيليجرام! - %1$s، \nلقد تم تسجيل الدخول لحسابك هذا من جهاز جديد في: %2$s\n\nالجهاز: %3$s\nالموقع: %4$s\n\nإن لم تكن أنت من قام بتسجيل الدخول فيمكنك الذهاب للإعدادات - الخصوصية والأمان - الجلسات النشطة - ومن ثم إنهاء الجلسات المريبة.\n\nإذا كنت تعتقد أن شخصًا ما قام بتسجيل الدخول دون إذنك فيمكنك تفعيل التحقق بخطوتين من خلال قسم الخصوصية واﻷمان في الإعدادات.\n\nشكرًا، \nفريق تيليجرام - %1$s حدث صورته الشخصية + %1$s؛\nلقد تم تسجيل الدخول لحسابك هذا من جهاز جديد في: %2$s\n\nالجهاز: %3$s\nالموقع: %4$s\n\nإذا لم تكن أنت من قام بتسجيل الدخول فيمكنك الذهاب للإعدادات - الخصوصية والأمان - الجلسات النشطة - ومن ثَم إنهاء الجلسات المريبة.\n\nإذا كنت تعتقد أن شخصًا ما قام بتسجيل الدخول دون إذنك فيمكنك تفعيل التحقق بخطوتين عبر قسم الخصوصية واﻷمان في الإعدادات.\n\nشكرًا..\nفريق تيليجرام + حدّثَ %1$s صورته الشخصية %1$s انضم للمجموعة %2$s عبر رابط دعوة - %1$s أرسل %3$s إلى المجموعة %2$s - %1$s أعاد تحويل %3$s إلى المجموعة %2$s + أرسل %1$s %3$s لمجموعة %2$s + %1$s sent an album to the group %2$s + أعاد %1$s تحويل %3$s لمجموعة %2$s رد الرد على %1$s الرد على %1$s تم تقييد البيانات الخلفية %1$s %2$s - ثبت %1$s «%2$s» في المجموعة %3$s - %1$s ثبت رسالة في المجموعة %2$s - ثبت %1$s استفتاءًا في مجموعة %2$s - %1$s ثبت صورة في المجموعة %2$s - %1$s ثبت لعبة في المجموعة %2$s - ثبت %1$s مقطعًا مرئيًا في المجموعة %2$s - ثبت %1$s ملفًا في المجموعة %2$s - ثبت %1$s ملصقًا في مجموعة %2$s - ثبت %1$s ملصق %3$s في مجموعة %2$s - ثبت %1$s رسالةً صوتيةً في مجموعة %2$s - ثبت %1$s رسالةً مرئيةً في مجموعة %2$s - %1$s ثبت جهة اتصال في المجموعة %2$s - %1$s ثبت خريطة في المجموعة %2$s - ثبت %1$s موقعًا حيًا في مجموعة %2$s - %1$s ثبت صورة متحركة في المجموعة %2$s - ثبت %1$s ملفًا صوتيًا في مجموعة %2$s - ثبت %1$s فاتورةً في مجموعة %2$s + ثبّتَ %1$s «%2$s» في مجموعة %3$s + ثبّتَ %1$s رسالةً في مجموعة %2$s + ثبّتَ %1$s الاستفتاء %3$s في مجموعة %2$s + ثبّتَ %1$s صورةً في مجموعة %2$s + ثبّتَ %1$s لعبةً في مجموعة %2$s + %1$s pinned a game score in the group %2$s + ثبّتَ %1$s مقطعًا مرئيًا في مجموعة %2$s + ثبّتَ %1$s ملفًا في مجموعة %2$s + ثبّتَ %1$s ملصقًا في مجموعة %2$s + ثبّتَ %1$s ملصق %3$s في مجموعة %2$s + ثبّتَ %1$s رسالةً صوتيةً في مجموعة %2$s + ثبّتَ %1$s رسالةً مرئيةً في مجموعة %2$s + ثبّتَ %1$s جهة اتصال %3$s في مجموعة %2$s + ثبّتَ %1$s خريطةً في مجموعة %2$s + ثبّتَ %1$s موقعًا حيًا في مجموعة %2$s + ثبّتَ %1$s صورةً متحركة في مجموعة %2$s + ثبّتَ %1$s ملفًا صوتيًا في مجموعة %2$s + ثبّتَ %1$s فاتورةً في مجموعة %2$s ثبت %1$s «%2$s» ثبت %1$s رسالة - ثبت %1$s استفتاءًا + %1$s pinned a poll %2$s %1$s ثبت صورة %1$s ثبت لعبة + %1$s pinned a game score ثبت %1$s مقطعًا مرئيًا ثبت %1$s ملفًا %1$s ثبت فاتورة @@ -841,7 +887,7 @@ ثبت %1$s ملصق %2$s ثبت %1$s رسالةً صوتية ثبت %1$s رسالةً مرئية - %1$s ثبت جهة اتصال + %1$s pinned a contact %2$s ثبت %1$s خريطة ثبت %1$s موقعًا حيًا ثبت %1$s صورةً متحركة @@ -886,12 +932,14 @@ المعذرة، هذه المجموعة ممتلئة. المعذرة، هذه المحادثة غير موجودة. تم نسخ الرابط للحافظة + Link copied to clipboard.\nThis link will only work for members of this chat. + للأسف لا يمكنك الوصول إلى هذه الرسالة؛ أنت لست عضوًا في المحادثة التي تم نشرها فيها. تم نسخ رقم الهاتف للحافظة تم نسخ البريد للحافظة استخدام رابط للدعوة إلى المجموعة رابط الدعوة هل ترغب حقًا في استبدال الرابط؟ إن قمت بذلك لن يتمكن أحد من الانضمام عبره. - رابط الدعوة السابق لم يعد مفعلًا، تم إنشاء رابط جديد بدلًا منه. + رابط الدعوة السابق لم يعد مفعَّلا، تم إنشاء رابط جديد بدلًا منه. استبدال استبدال الرابط هل ترغب حقًا في تعطيل الرابط **%1$s**؟\n\nستصبح المجموعة «**%2$s**» خاصة. @@ -908,6 +956,7 @@ تعيين المشرفين حظر من المجموعة مغادرة المجموعة وحذفها + حذف ومغادرة المجموعة الإشعارات تغيير صلاحيات العضو إزالة من المجموعة @@ -916,8 +965,8 @@ تحويل إلى مجموعة خارقة تحذير تحذير: هذا القرار لا يمكن التراجع عنه، لن تتمكن من إعادة المجموعة الخارقة إلى مجموع عادية مرة أخرى. - **تم بلوغ الحد الأقصى لعدد الأعضاء**\n\nلتخطي هذا الحد والحصول على خصائص جديدة، يمكنك الترقية لمجموعة خارقة:\n\n• يمكن أن تحتوي المجموعات الخارقة على %1$s عضو\n• يمكن للأعضاء الجدد مشاهدة محتوى المحادثة كاملًا\n• تختفي الرسائل المحذوفة من أجهزة جميع الأعضاء\n• يمكن للمشرفين إضافة وصفًا للمجموعة\n• يمكن لمالك المجموعة إنشاء رابط عام لها - ** في المجموعات الخارقة:**\n\n• يمكن للأعضاء الجدد مشاهدة محتوى المحادثة كاملًا\n• تختفي الرسائل المحذوفة من أجهزة جميع الأعضاء\n• يمكن للمشرفين إضافة وصفًا للمجموعة\n• يمكن لمالك المجموعة إنشاء رابط عام لها + **تم بلوغ الحد الأقصى لعدد الأعضاء**\n\nلتخطي هذا الحد والحصول على خصائص جديدة، يمكنك الترقية لمجموعة خارقة:\n\n• يمكن أن تحتوي المجموعات الخارقة على %1$s عضو\n• يمكن للأعضاء الجدد مشاهدة محتوى المحادثة كاملًا\n• تختفي الرسائل المحذوفة من أجهزة جميع الأعضاء\n• يمكن للمشرفين إضافة وصفٍ للمجموعة\n• يمكن لمالك المجموعة إنشاء رابط عام لها + ** في المجموعات الخارقة:**\n\n• يمكن للأعضاء الجدد مشاهدة محتوى المحادثة كاملًا\n• تختفي الرسائل المحذوفة من أجهزة جميع الأعضاء\n• يمكن للمشرفين إضافة وصفٍ للمجموعة\n• يمكن لمالك المجموعة إنشاء رابط عام لها **ملحوظة:** لا يمكنك التراجع عن هذا القرار. مشاركة @@ -979,6 +1028,8 @@ الملصقات والأقنعة إضافة الملصقات + ADD %1$s + REMOVE %1$s إضافة أقنعة إضافة إلى الملصقات إضافة للمفضلة @@ -1000,7 +1051,12 @@ إزالة لا يوجد ملصقات بعد لم يتم العثور على ملصقات + لم يتم العثور على صور متحركة + لم يتم العثور على رموز لا توجد أقنعة بعد + اقتراحات الرموز التعبيرية + يسمح لك **تيليجرام** بالعثور على الرموز التعبيرية عبر آلاف الكلمات، لكن من المؤكد أنه لايزال هناك نقصٌ ما، في حال كنت ترغب في اقتراح كلمة مفتاحية جديدة لرمز تعبيري ما، يمكنك مساعدتنا عبر زيارة: + https://translations.telegram.org/%1$s/emoji الأقنعة يمكنك إضافة أقنعة للصور التي ترسلها، لعمل ذلك قم بفتح محرر الصور قبل إرسال الصورة. الملصقات الشائعة @@ -1008,7 +1064,7 @@ جميع الحزم حزمي إيقاف - هذه الملصقات شائعة حاليًا على تيليجرام. يمكنك إضافة ملصقات مخصصة من خلال البوت @stickers. + هذه الملصقات شائعة حاليًا على تيليجرام، يمكنك إضافة ملصقات مخصصة عبر البوت @stickers. الملصقات المؤرشفة الأقنعة المؤرشفة ما من ملصقات مؤرشفة @@ -1023,8 +1079,8 @@ النمط الوضع الليلي الآلي - معطّل - معطّل + معطَّل + معطَّل مجدول تلقائي الجدولة @@ -1046,6 +1102,9 @@ حفظ النمط نمط جديد لون النمط + عرض قائمة المحادثات + خطين اثنين + ثلاثة خطوط إنشاء نمط تطبيق معاينة النمط @@ -1101,11 +1160,11 @@ عام مكتومة مُلغى كتمها - تشغيل - إيقاف - معطّلة حتى %1$s - الافتراضي (مفعل) - الافتراضي (معطّل) + مفعَّلة + معطَّلة + معطَّلة حتى %1$s + الافتراضي (مفعَّلة) + الافتراضي (معطَّلة) تشغيل إيقاف المستخدمون المحظورون @@ -1115,10 +1174,10 @@ الدعم فقط في وضع الصامت تأثير ضبابي - تأثير حركي + تأثير حرَكي خلفية المحادثة إعادة تعيين الخلفيات - لإزالة جميع الخلفيات المرفوعة وإستعادة الخلفيات الإفتراضية لجميع الأنماط. + لإزالة جميع الخلفيات المرفوعة واستعادةِ الخلفيات الافتراضية لكل الأنماط. هل ترغب حقًا في إعادة تعيين كافة خلفيات المحادثة؟ هل ترغب حقًا في حذف الخلفيات المحددة؟ معاينة الخلفية @@ -1130,7 +1189,7 @@ أحمد، هل أحضرت كافة الأشياء المطلوبة... بلى، أنا جاهز للانطلاق في أي وقت! هل سنخبرهم بقدومنا أم نجعلها مفاجأة؟ سنخبرهم بالطبع! هل تتذكر كيف انتهت آخر مفاجأة؟ - اضغط على \'تعيين\' لتطبيق الخلفية. + اضغط على «تعيين» لتطبيق الخلفية. طلعت يا محلا نورها يا شمس الشموسة تعيين كخلفية بحث بواسطة اللون @@ -1171,7 +1230,7 @@ البيانات غير كافية لغات غير رسمية تعذر العثور على هذه اللغة. - أنت تستخدم حزمة اللغة (**%1$s**) بالفعل. يمكنك تغيير لغتك في أي وقت من خلال الإعدادات. + أنت تستخدم حزمة اللغة (**%1$s**) بالفعل، يمكنك تغيير لغتك في أي وقت عبر الإعدادات. للأسف، لا تحتوي حزمة اللغة المخصصةُ هذه (**%1$s **) على بيانات لتيليجرام للأندرويد. نرجو الأخذ بالعلم أن الدعم الفني في تيليجرام يقوم به مجموعة من المتطوعين. نحاول الرد سريعًا قدر الإمكان، لكن ذلك قد يستغرق بعض الوقت.\n\nيرجى الإطلاع على الأسئلة الشائعة عن تيليجرام]]> فهي تحوي إجابات لمعظم الأسئلة وحلولًا للعديد من المشاكل.]]> اسأل متطوعًا @@ -1182,7 +1241,7 @@ https://telegram.org/faq/ar سياسة الخصوصية شروط الخدمة - من خلال تسجيلك،\nأنت توافق على *شروط الخدمة*. + عبر تسجيلك\nأنت توافق على *شروط الخدمة*. https://telegram.org/faq/ar#a10 حذف التعريب؟ ملف التعريب غير صحيح @@ -1201,18 +1260,18 @@ في حال إغلاق الشاشة فقط أظهرها دائمًا شارةُ عدّاد الرسائل - مفعلة + مفعَّلة تضمين المحادثات المكتومة عَدُّ الرسائل غير المقروءة قصير طويل تنزيل الوسائط تلقائيًا تنزيل الوسائط تلقائيًا - مفعّل في جميع المحادثات + مفعَّل في جميع المحادثات حتى %1$s في جميع المحادثات - معطّل + معطَّل حتى %1$s في %2$s - مفعّل في %1$s + مفعَّل في %1$s جهات الاتصال القنوات منخفض @@ -1224,18 +1283,21 @@ الصور المقاطع المرئية الملفات + Photos + Videos + Files تنزيل الملفات والمقاطع الصوتية تلقائيًا تنزيل الصور تلقائيًا تنزيل المقاطع المرئية والصور المتحركة تلقائيًا الحجم الأقصى للمقطع المرئي الحجم الأقصى للملف تجهيز المقطع التالي - Start downloading the next track while you are listening to an audio file. + البدءُ بتحميل المقطع التالي أثناء استماعك لمقطعٍ صوتي. تجهيز المرئيات الكبيرة تحميل الثواني الأولى (1-2 م.ب) من المقاطع المرئية الأكبر من %1$s لمشاهدتها فورَ الضغط عليها. - قم بتفعيل هذا الخيار إذا كنت تريد أن تتحمل الوسائط تلقائيًا على البيانات الخلوية. - قم بتفعيل هذا الخيار إذا كنت تريد أن تتحمل الوسائط تلقائيًا عند التجوال. - Turn this ON if you want media to be automatically downloaded on Wi-Fi. + قم بالتفعيل إذا كنت ترغب في تحميل الوسائط تلقائيًا عبر البيانات الخلوية. + قم بالتفعيل إذا كنت ترغب في تحميل الوسائط تلقائيًا عند التجوال. + قم بالتفعيل إذا كنت ترغب في تحميل الوسائط تلقائيًا عبر شبكات الـ Wi-Fi. على البيانات الخلوية عند التجوال على الـ Wi-Fi @@ -1250,7 +1312,8 @@ عند التجوال الصور المتحركة المقاطع المرئية - Press the volume buttons to turn sound on. + اضغط على أزرار الصوت لتشغيله. + تم إخفاء الحساب من قِبل المستخدم. تشغيل الوسائط تلقائيًا الرفع للتحدث حفظ في المعرض @@ -1274,8 +1337,8 @@ الرقم %1$s مرتبط بالفعل بحساب آخَر على تيليجرام. يرجى حذف ذلك الحساب قبل محاولة تغيير رقمك. غير ذلك تعطيل - مفعلة - معطّلة + مفعَّلة + معطَّلة تعطيل إيقاف أصوات داخل المحادثات @@ -1334,10 +1397,10 @@ بروكسي MTProto لم يتم إعداد البروكسي الذي تستخدمه بشكل صحيح وسيتم تعطيله. يرجى العثور على واحد آخر. راعي البروكسي - يقوم البروكسي الخاص بك بعرض هذه القناة. لإزالتها من قائمة دردشاتك، قم بتعطيل البروكسي من إعدادات تيليجرام. + يقوم البروكسي الخاص بك بعرض هذه القناة. لإزالتها من قائمة محادثاتك، قم بتعطيل البروكسي من إعدادات تيليجرام. إعدادات بروكسي SOCKS5 إعدادات بروكسي MTProto. - قد يعرض هذا البروكسي قناة إعلانية في قائمة الدردشات الخاصة بك.\nلن يكشف هذا عن أي من بيانات تيليجرام الخاصة بك. + قد يعرض هذا البروكسي قناة إعلانية في قائمة محادثاتك.\nلن يكشف هذا عن أي من بيانات تيليجرام الخاصة بك. استخدام البروكسي للمكالمات قد تقلل خوادم البروكسي من جودة مكالماتك. تفعيل @@ -1358,6 +1421,9 @@ المظهر الملصقات والأقنعة اختيار لون مخصص للتطبيق + إظهار الإشعارات من + جميع الحسابات + قم بتعطيل هذا الخيار لاستلام الإشعارات فقط من حسابك النشط. إشعارات المحادثات المحادثات الخاصة المجموعات @@ -1371,17 +1437,23 @@ انقر للتغيير خيارات بديلة إضافة حساب آخر - "إضافة حسابات تيليجرام أخرى والتبديل بينها بسهولة. " - تعيين رمز قفل - "قفل التطبيق برمز لمنع الآخرين من فتحه. " + إضافة حساباتك الأخرى على تيليجرام والتبديل بينها بسهولة. + تعيين رمز مرور + تأمين التطبيق برمز مرور لحمايته من المتطفلين. مسح الذاكرة المؤقتة "تفريغ بعض المساحة من جهازك؛ ستبقى وسائطك في السحابة. " تغيير رقم الهاتف - "نقل حسابك ومحادثاتك مع وسائطها لرقمٍ آخر. " + نقلُ حسابك مع ما يحويه من محادثات ووسائطَ لرقمٍ آخر. التواصل مع الدعم - أخبرنا عن أي مشاكل تواجهك لأن تسجيل الخروج غالبًا لا ينفع. + أخبرنا عن أي مشاكلَ تواجهك؛ تسجيل الخروج ليس حلا ناجحا في العادة. تسجيل الخروج - لا تنسَ أن تسجيل الخروج سيحذف كل محادثاتك السرية. + تسجيل الخروج سيلغي كل المحادثات السرية. + بحث الإعدادات والأسئلة الشائعة + عمليات البحث الأخيرة + الأسئلة الشائعة + لم يتم العثور على نتائج + ما من عمليات بحث تمت مؤخرًا + الأسئلة الشائعة قاعدة البيانات على الجهاز هل ترغب في مسح الرسائل النصية من الذاكرة المؤقتة؟ @@ -1407,7 +1479,7 @@ المعلومات المطلوبة المعلومات المضافة ماهو جواز تيليجرام؟ - مع جواز تيليجرام يمْكنك التسجيل في المواقع والخدمات التي تتطلب توثيق الهوية الشخصية بسهولة.\n\nمعلوماتك، بياناتك الشخصية ووثائقك محمية ومشفرة من البداية للنهاية. لا أحد بما فيهم تيليجرام ذاتُه يمكنه الوصول إليها دون إذنك. \n\nلمزيد من التفاصيل يمكنك زيارة *الأسئلة الشائعة*. + مع جواز تيليجرام يمْكنك التسجيل في المواقع والخدمات التي تتطلب توثيق الهوية الشخصية بسهولة.\n\nمعلوماتك، بياناتك الشخصية ووثائقك محمية ومشفرة من البداية للنهاية، لا أحد بما فيهم تيليجرام ذاتُه يمكنه الوصول إليها دون إذنك. \n\nلمزيد من التفاصيل يمكنك زيارة *الأسئلة الشائعة*. https://telegram.org/faq/ar#i7 "يرجى إنشاء كلمة مرور لحماية بياناتك الشخصية باستخدام التشفير من البداية للنهاية.\n\nستُطلب كلمة المرور هذه في كل مرة تقوم فيها بتسجيل الدخول لجهازٍ جديد. " إنشاء كلمة مرور @@ -1616,7 +1688,7 @@ رمز القفل تغيير رمز القفل - عندما تقوم بتعيين رمز قفل إضافي ستظهر أيقونة قفل أعلى صفحةِ المحادثات. اضغط عليها لإقفال تيليجرام أو فتْحِه.\n\nملحوظة: إذا نسيت رمز القفل فستحتاج لحذف التطبيق وإعادة تنزيله، ستفقد كافة محادثاتك السرية. + عندما تقوم بتعيين رمز قفل إضافي، ستظهر أيقونة قفل أعلى صفحة المحادثات، اضغط عليها لإقفال تيليجرام أو فتحِه.\n\nملحوظة: إذا نسيت رمز القفل ستحتاج لحذف التطبيق وإعادةِ تثبيته، ستَفقد كافة محادثاتك السرية. رقم كلمة مرور قم بإدخال رمز قفلك الحالي @@ -1628,13 +1700,13 @@ القفل التلقائي طلب رمز القفل إن غِبتُ لفترةٍ ما. خلال %1$s - معطّل + معطَّل فتح القفل عبر البصمة قم بتأكيد البصمة للاستمرار مستشعر اللمس لم يتم التعرف على البصمة. حاول مرة أخرى. عرض المحتوى عند التبديل بين التطبيقات - إن تم التعطيل، لن تتمكن من تصوير الشاشة داخل التطبيق، لكن سيتم إخفاء محتوى المحادثات في شاشة تعدد المهام. + إذا تم التعطيل فلن تتمكن من تصوير الشاشة داخل التطبيق، لكن سيتم إخفاء محتوى المحادثات في شاشة تعدد المهام. سيؤدي هذا لإخفاء محتوى محادثاتك من شاشة تعدد المهام، لكن بالمقابل لن تتمكن من أخذ لقطات الشاشة في تيليجرام.\n\nقد تحتاج لإعادة تشغيل التطبيق ليتم تفعيل هذا الخيار. محاولات عديدة.\nأعد المحاولة خلال %1$s. @@ -1701,7 +1773,7 @@ تقوم بمشاركة موقعك الحي مع %1$s اختر المدة التي سيتمكن خلالها %1$s من مشاهدة موقعك الفعلي. اختر المدة التي سيتمكن خلالها أعضاء هذه المحادثة من مشاهدة موقعك الحي. - يبدو أن تحديد المواقع معطّل لديك، يرجى تفعيله لاستخدام ميزات تيليجرام التي تحتاجه. + يبدو أن تحديد المواقع معطَّل لديك، يرجى تفعيله لاستخدام ميزات تيليجرام التي تحتاجه. عرض كافة الوسائط عرض جميع الملفات @@ -1856,6 +1928,18 @@ الخصوصية والأمان الخصوصية آخر ظهور + الصورة الشخصية + من يمْكنه رؤية صورتي الشخصية؟ + بإمكانك تخصيص من يمْكنه رؤية صورتك الشخصية بدقة انتقائية. + ستتجاوز هذه الإعدادات القيم في الأعلى. + الرسائل المحوَّلة + رابط إلى حسابك + السماح بالرابط حسب الإعدادات أدناه + بدون رابط إلى حسابك + من يضيف رابطًا إلى حسابي عند تحويل رسائلي؟ + لن تملك الرسائل التي تقوم بتحويلها بنفسك إلى محادثاتٍ أخرى رابطًا إلى حسابك. + ستتجاوز هذه الإعدادات القيم في الأعلى. + نعم، جاهز للإنطلاق في أي وقت! هل سنخبرهم بقدومنا أم نجعلها مفاجأة؟ النِّدُّ للنِّدِّ في المكالمات البوتات والمواقع مسح معلومات الدفع والشحن @@ -1888,6 +1972,7 @@ من يمْكنه رؤية آخر ظهور لك؟ إضافة استثناءات هام: لن تتمكن من رؤية آخر ظهور للأشخاص الذين اخترت ألا يروا آخر ظهور لك.\nسيتم بدلًا من ذلك عرض آخر ظهور تقريبي (شُوهدَ مؤخرًا، خلال أسبوع، خلال شهر). + لقد قمت بتغيير بعض إعدادات الخصوصية؛ تطبيق التغييرات؟ المشاركة دائمًا مع عدم المشاركة مع ستتجاوز هذه الإعدادات القيم في الأعلى. @@ -1976,8 +2061,8 @@ un1 غادر المجموعة un1 أضاف un2 أزال un1 صورة المجموعة - غيّر un1 صورة المجموعة - غيّر un1 اسم المجموعة ليصبح un2 + غيّرَ un1 صورة المجموعة + غيّرَ un1 اسم المجموعة ليصبح un2 انشأ un1 المجموعة لقد أزلت un2 أنت غادرت المجموعة @@ -2056,10 +2141,17 @@ هل ترغب في مشاركة اللعبة مع %1$s؟ إرسال جهة الاتصال إلى %1$s؟ هل ترغب حقًا في تسجيل الخروج؟\n\nتذكَّر أنه يمكنك استخدام تيليجرام على جميع أجهزتك في ذات الوقت بسهولة تامة.\n\nولا تنسَ أن تسجيل الخروج سيحذف كل محادثاتك السرية. + حذف %1$s + Clear %1$s + Empty cache for %1$s + هل ترغب حقًا في حذف المحادثات المحددة؟ + هل ترغب حقًا في مسح محتوى المحادثات المحددة؟ + حذف جميع الرسائل والوسائط المخزنة مؤقتًا من المحادثات المحددة؟ هل ترغب حقًا في حذف هذه المجموعة والخروج منها؟ - هل ترغب حقًا في حذف ومغادرة المجموعة **%1$s**؟ + هل ترغب حقًا في حذف ومغادرة مجموعة **%1$s**؟ هل ترغب حقًا في حذف هذه المحادثة؟ هل ترغب حقًا في حذف المحادثة مع **%1$s**؟ + هل ترغب حقًا في حذف **الرسائل المحفوظة**؟ هل ترغب حقًا في حذف المحادثة السرية مع **%1$s**؟ هل ترغب حقًا في حذف المحادثة **%1$s**؟ هل ترغب حقًا في حذف جميع المسودات السحابية؟ @@ -2082,9 +2174,21 @@ هل ترغب حقًا في مسح محتوى المحادثة السرية مع **%1$s**؟ هل ترغب حقًا في مسح محتوى محادثة **%1$s**؟ هل ترغب حقًا في مسح محتوى المحادثة؟ + هل ترغب حقًا في مسح محتوى **الرسائل المحفوظة**؟ حذف كافة المحادثات والوسائط المتعلقة بهذه القناة من الذاكرة المؤقتة؟ حذف جميع الرسائل والوسائط المخزنة مؤقتًا من هذه المجموعة؟ - هل ترغب حقًا في حذف %1$s؟ + حذف %1$s + حذف الرسالة + You can also delete the %1$s from the inboxes of other group members by checking \"Delete for all members\". + You can also delete the %1$s you sent from the inboxes of other group members by checking \"Unsend my messages\". + You can also delete the %1$s you sent from **%2$s**\'s inbox by checking \"Unsend my messages\". + هل ترغب حقًا في حذف هذه الرسالة؟ + هل ترغب حقًا في حذف هذه الرسائل؟ + هل ترغب حقًا في حذف هذه الرسالة من عند الكل؟ + هل ترغب حقًا في حذف هذه الرسائل من عند الكل؟ + التراجع عن إرسال رسائلي + حذف من عند %1$s أيضًا + مسح المحتوى من عند %1$s أيضًا إرسال الرسائل إلى %1$s؟ هل ترغب في مشاركة اللعبة مع %1$s؟ إرسال جهة الاتصال إلى %1$s؟ @@ -2095,8 +2199,8 @@ المعذرة، لا يمكنك تعديل هذه الرسالة. فضلًا قم بالسماح لتيليجرام بتلقي رسائل SMS القصيرة ليتمكن من تفعيل حسابك تلقائيًا. فصلًا قم بالسماح لتيليجرام باستقبال اتصالات ليتمكن من إدخال الرمز لك تلقائيًا. - فضلًا قم بالسماح لتيليجرام بتلقي المكالمات ليتمكن من التحقق من رقم هاتفك تلقائيًا. - فضلًا قم بالسماح لتيليجرام بتلقي المكالمات ليتمكن من التحقق من رقم هاتفك تلقائيًا. + رجاءً قم بالسماح لتيليجرام بتلقي المكالمات للتمكن من تفعيل رقم هاتفك تلقائيًا. + رجاءً قم بالسماح لتيليجرام بتلقي المكالمات للتمكن من تفعيل رقم هاتفك تلقائيًا. المعذرة، لا يمكنك القيام بذلك. المعذرة، لا يمكنك إضافة هذا المستخدم أو البوت للمجموعات بسبب أنك قمت بحظره. فضلًا قم بإزالة الحظر للاستمرار. انضمام للمجموعة @@ -2106,9 +2210,9 @@ المعذرة، مشرفو هذه المجموعة قيدوك من إرسال الملصقات. المعذرة، قام مشرفو هذه المجموعة بتقييدك من إرسال الوسائط. المعذرة، قام مشرفو هذه المجموعة بتقييدك من إرسال الاستفتاءات. - المعذرة، ليس من المسموح إرسال الملصقات إلى هذه المجموعة. - المعذرة، ليس من المسموح إرسال الوسائط إلى هذه المجموعة. - المعذرة، ليس من المسموح إرسال الاستفتاءات إلى هذه المجموعة. + المعذرة، لا يُسمحُ بإرسال الملصقات في هذه المجموعة. + المعذرة، لا يُسمحُ بإرسال الوسائط في هذه المجموعة. + المعذرة، لا يُسمحُ بإرسال الاستفتاءات في هذه المجموعة. نحن متأسفون للغاية، ولكن هذا يعني أنه لا يمكنك الاشتراك بتيليجرام.\n\nعلى عكس الآخرين، نحن لا نستخدم بياناتك لاستهدافك بالإعلانات أو لأغراض تجارية أخرى. لا يخزن تيليجرام سوى المعلومات التي يحتاجها ليعمل كخدمة سحابية غنية بالميزات. يمكنك ضبط كيفية استخدامنا لبياناتك (مثل إعدادات حذف الجهات المزامَنة) في إعدادات الخصوصية والأمان.\n\nلكن إن كنت غير موافق على احتياجات تيليجرام المتواضعة بشكل عام، فلن يكون من الممكن لنا تقديم هذه الخدمة. التحقق من العمر سياسة الخصوصية وشروط الخدمة @@ -2196,7 +2300,7 @@ هل ترغب حقًا في حذف هذه المكالمة من سجل المكالمات؟ مكالمة تيليجرام سماعة الأذن - مكبر صوت + مكبر الصوت بلوتوث الرجوع للمكالمة المعذرة، **%1$s** لا يستقبل مكالمات. @@ -2217,13 +2321,13 @@ السماح برسائل مخصصة مكالمة تيليجرام مع %s لا يمكن إجراء مكالمة تيليجرام حاليًا. - سمعتُ صوتي + سمعتُ صدى صوتي سمعت ضوضاء في الخلفية - كان صوت الشخص الآخر يختفي + كان صوت الطرف الآخر يتقطع لم يكن الكلام واضحًا لم أتمكن من سماع الطرف الآخر لم يسمعني الطرف الآخر - انتهت المكالمة فجأة + انقطع الاتصال فجأة لا يوجد مستقبلون مستقبل واحد @@ -2255,6 +2359,24 @@ %1$d محادثات %1$d محادثة %1$d محادثة + %1$d chats + %1$d chat + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d محادثة + محادثة واحدة + المحادثتين + %1$d محادثات + %1$d محادثة + %1$d محادثة + %1$d محادثة + محادثة واحدة + محادثتان + %1$d محادثات + %1$d محادثة + %1$d محادثة محادثة واحدة محادثتين @@ -2381,6 +2503,12 @@ %1$d ملصقات %1$d ملصقًا %1$d ملصق + %1$d masks + %1$d mask + %1$d masks + %1$d masks + %1$d masks + %1$d masks لا يوجد مشتركين مشترك واحد مشتركان @@ -2395,7 +2523,7 @@ %1$d استثناء %1$d مستخدم تمت إزالته مستخدمٌ واحد تمت إزالته - مستخدمين إثنين تمت إزالتهم + مستخدمان اثنان تمت إزالتهما %1$d مستخدمين تمت إزالتهم %1$d مستخدمًا تمت إزالتهم %1$d مستخدم تمت إزالته @@ -2448,6 +2576,12 @@ %1$d صور %1$d صورة %1$d صورة + %1$d photos + %1$d photo + %1$d photos + %1$d photos + %1$d photos + %1$d photos %1$d ملف ملف واحد ملفان اثنان @@ -2526,6 +2660,88 @@ و%1$d آخرون و%1$d آخرون و%1$d آخرون + + مجموعة + قناة + محادثة سرية + تم الإرسال %s + تم التسليم %s + العودة للخلف + فتح قائمة التنقل + %2$s من قِبل %1$s + مزيد من الخيارات + تشغيل + إيقاف مؤقت + تنزيل + إيقاف التنزيل + فتح الملف + خيارات الرسالة + الدخول إلى وضع التحديد + الرموز التعبيرية، الملصقات والصور المتحركة + إرفاق وسائط + إرسال بشكلٍ صامت + إرسال الإشعارات + أوامر البوت + لوحة مفاتيح البوت + إظهار لوحة المفاتيح + تسجيل رسالة صوتية + تسجيل رسالة مرئية + فتح المحادثة + الصورة الشخصية + تغيير الصورة الشخصية + تغيير الترتيب + إظهار الحسابات + إخفاء الحسابات + الذهاب إلى الرسالة + إلغاء الرد + إلغاء التحويل + إلغاء التعديل + رد على + تحويل من + يتم التعديل + قفل التطبيق + فتح قفل التطبيق + رجوع + السابق + التكرار، إيقاف + التكرار، قائمة التشغيل + التكرار، هذا المقطع + إغلاق مشغل الصوتيات + سرعة مضاعفة + إيقاف مشاركة الموقع الحي + الكاميرا الفورية + لقط صورة + تبديل الكاميرا + الكشاف، إيقاف + الكشاف، تلقائي + الكشاف، تشغيل + حزمة ملصقات + صور متحركة + الملصقات + تكبير اللوحة + تصغير اللوحة + خيارات المستخدم + تدوير + محرر الصور + تعديلات + عارض الصور + الذهاب للأسفل + الذهاب إلى الإشارة التالية + كتم الميكروفون + العنوان + الرأسية + موقعي + دقة المقطع المرئي + الأبعاد + أخذ صورة أخرى + Seen + غير مقروءة + Not played + نتيجة البحث التالية + نتيجة البحث السابقة + Filter by user + التقاط صورة + تسجيل مقطع مرئي MMM dd yyyy, h:mm a MMM dd yyyy, HH:mm diff --git a/TMessagesProj/src/main/res/values-de/strings.xml b/TMessagesProj/src/main/res/values-de/strings.xml index 2e23384b1..f38de9049 100644 --- a/TMessagesProj/src/main/res/values-de/strings.xml +++ b/TMessagesProj/src/main/res/values-de/strings.xml @@ -144,12 +144,26 @@ Du bist dem geheimen Chat beigetreten. Verlauf leeren Verlauf geleert. + Stumm + Stumm aus Chat gelöscht. Gruppe gelöscht. Kanal gelöscht. + Archiv angeheftet. + Archiv nach links wischen,\num es zu verstecken. + Archiv versteckt. + Nach unten wischen,\num Archiv anzuzeigen. + Chat archiviert. + Chats archiviert + Archiv nach links wischen,\num es zu verstecken. RÜCKGÄNGIG Cache leeren Löschen und verlassen + Verstecken + Anheften + Archivieren + Einblenden + Archivierte Chats Chat löschen Gelöschtes Konto Chat auswählen @@ -168,7 +182,7 @@ HASHTAGS Letzte Leute - Lösche %1$s aus Vorschlägen? + %1$s aus Vorschlägen entfernen? Linkvorschau Entwurf Verlauf wurde gelöscht @@ -176,6 +190,7 @@ %1$s von %2$s Rückmeldung zu dieser Vorschau hinterlassen Sticker senden + GIF senden Paket anzeigen Oben anheften Mehr als %1$s kann man leider nicht oben anheften. @@ -190,6 +205,12 @@ JETZT NICHT WEITER Deine Kontakte bei Telegram + Das ist dein Archiv + Chats mit aktivierten Benachrichtigungen landen wieder in der Chatliste, wenn neue Benachrichtigungen eintreffen. + Chats ohne Benachrichtigungen + Stummgeschaltete Chats bleiben im Archiv,\nwenn neue Nachrichten eintreffen. + Angeheftete Chats + Unbegrenzt viele archivierte Chats\nkannst du oben anheften. Zum Admin machen Adminrechte bearbeiten @@ -281,6 +302,11 @@ Ausnahme hinzufügen Ausnahmen durchsuchen Entfernte Nutzer + Kontakte in diesem Kanal + Kontakte in dieser Gruppe + Bots + Weitere Mitglieder + Weitere Abonnenten Eingeschränke Nutzer Administratoren Kanal löschen @@ -330,13 +356,14 @@ %1$s hat eine Nachricht gesendet %1$s hat ein Bild gesendet %1$s hat ein Video gesendet - %1$s hat einen Kontakt gesendet - %1$s hat eine Umfrage gesendet + %1$s hat einen Kontakt gesendet %2$s + %1$s hat eine Umfrage gesendet %2$s %1$s hat einen Standort gesendet %1$@ hat einen Live-Standort geteilt %1$s hat eine Datei gesendet %1$s hat ein GIF gesendet %1$s hat %2$s gesendet + %1$s hat ein Album gesendet %1$s hat eine Sprachnachricht gesendet %1$s hat eine Videonachricht gesendet %1$s hat eine Audiodatei gesendet @@ -580,7 +607,7 @@ unsichtbar Support - tippt… + tippt... tippt... tippen… %1$s tippt... @@ -679,6 +706,14 @@ Spam melden Lösche alles von %1$s Zuletzt benutzte Emoji leeren? + Smileys und Leute + Tiere und Natur + Essen und Trinken + Aktivität + Reisen und Orte + Objekte + Symbole + Flaggen Melden Meldung gesendet Spam @@ -727,19 +762,23 @@ Die Admins dieser Gruppe haben dir die Berechtigung entzogen, Medien bis %1$s zu senden Die Admins dieser Gruppe haben dir die Berechtigung entzogen, Sticker bis %1$s zu senden Die Admins dieser Gruppe haben dir die Berechtigung entzogen, Sticker bis %1$s zu senden + Die Admins dieser Gruppe haben dir die Berechtigung entzogen, GIFs bis %1$s zu senden Die Admins dieser Gruppe haben dir die Berechtigung entzogen, Nachrichten bis %1$s zu senden Die Admins dieser Gruppe haben dir die Berechtigung entzogen, Medien zu senden. Die Admins dieser Gruppe haben dir die Berechtigung entzogen, Inline-Bot Inhalte zu senden Die Admins dieser Gruppe haben dir die Berechtigung entzogen, Sticker zu senden. + Die Admins dieser Gruppe haben dir die Berechtigung entzogen, GIFs zu senden. Die Admins dieser Gruppe haben dir die Berechtigung entzogen, Nachrichten zu senden. Versand von Medien ist hier nicht erlaubt. Inline-Bots sind in dieser Gruppe nicht erlaubt. Sticker sind in dieser Gruppe nicht erlaubt. + GIFs sind in dieser Gruppe nicht erlaubt. Schreiben ist in dieser Gruppe nicht erlaubt. Admin APK Installation ist in dieser App eingeschränkt. Du kannst es in den System-Einstellungen aktivieren. Ungelesene Nachrichten Sticker suchen + Emoji suchen URL Kartenvorschau Anbieter der Kartenvorschau @@ -748,6 +787,7 @@ Yandex Keine Vorschau Google Maps installieren? + BETRUG %1$s hat den Selbstzerstörungs-Timer auf %2$s gesetzt Du hast den Selbstzerstörungs-Timer auf %1$s gesetzt @@ -756,6 +796,7 @@ Du hast eine neue Nachricht %1$s: %2$s %1$s hat dir %2$s gesendet + %1$s hat dir ein Album gesendet %1$s hat dir %2$s weitergeleitet %1$s hat dir eine Nachricht gesendet %1$s hat dir ein Bild gesendet @@ -763,11 +804,12 @@ %1$s hat dir eine Rechnung für %2$s gesendet %1$s hat dir ein selbstzerstörendes Bild gesendet %1$s hat dir ein selbstzerstörendes Video gesendet - %1$s hat dir einen Kontakt gesendet - %1$s hat dir eine Umfrage gesendet + %1$s hat einen Kontakt %2$s mit dir geteilt + %1$s hat dir eine Umfrage gesendet %2$s %1$s hat dir einen Standort gesendet %1$s hat dir einen Live-Standort gesendet %1$s hat dich eingeladen, %2$s zu spielen + %1$s hat %3$s Punke im Spiel %2$s erzielt %1$s hat dir eine Datei gesendet %1$s hat dir ein GIF gesendet %1$s hat dir eine Sprachnachricht gesendet @@ -779,11 +821,12 @@ %1$s hat eine Nachricht an die Gruppe %2$s gesendet %1$s hat ein Bild an die Gruppe %2$s gesendet %1$s hat ein Video an die Gruppe %2$s gesendet - %1$s hat eine Umfrage an die Gruppe %2$s gesendet - %1$s hat einen Kontakt an die Gruppe %2$s gesendet + %1$s hat eine Umfrage %3$s an die Gruppe %2$s gesendet + %1$s hat einen Kontakt %3$s in der Gruppe %2$s geteilt %1$s hat einen Standort an die Gruppe %2$s gesendet %1$s hat Live-Standort mit der Gruppe %2$s geteilt %1$s hat die Gruppe %2$s eingeladen, %3$s zu spielen. + %1$s hat %4$s Punkte im Spiel %3$s in der Gruppe %2$s erzielt %1$s hat eine Datei an die Gruppe %2$s gesendet %1$s hat ein GIF an die Gruppe %2$s gesendet %1$s hat eine Rechnung der Gruppe %2$s für %3$s gesendet @@ -806,6 +849,7 @@ %1$s hat das Profilbild geändert %1$s ist per Einladungslink der Gruppe %2$s beigetreten %1$s hat %3$s an die Gruppe %2$s gesendet + %1$s hat ein Album an die Gruppe %2$s gesendet %1$s hat %3$s an die Gruppe %2$s weitergeleitet Antworten %1$s antworten @@ -814,16 +858,17 @@ %1$s %2$s %1$s hat \"%2$s\" in der Gruppe %3$s angeheftet %1$s hat eine Nachricht in der der Gruppe %2$s angeheftet - %1$s hat eine Umfrage in der Gruppe %2$s angeheftet + %1$s hat eine Umfrage %3$s in der Gruppe %2$s angeheftet %1$s hat ein Bild in der Gruppe %2$s angeheftet %1$s hat ein Spiel in der Gruppe %2$s angeheftet + %1$s hat ein Spielergebnis in der Gruppe %2$s angeheftet %1$s hat ein Video in der Gruppe %2$s angeheftet %1$s hat eine Datei in der Gruppe %2$s angeheftet %1$s hat einen Sticker in der Gruppe %2$s angeheftet %1$s hat einen %3$s Sticker in der Gruppe %2$s angeheftet %1$s hat eine Sprachnachricht in der Gruppe %2$s angeheftet %1$s hat eine Videonachricht in der Gruppe %2$s angeheftet - %1$s hat einen Kontakt in der Gruppe %2$s angeheftet + %1$s hat einen Kontakt %3$s in der Gruppe %2$s angeheftet %1$s hat einen Standort in der Gruppe %2$s angeheftet %1$s hat einen Live-Standort in der Gruppe %2$s angeheftet %1$s hat ein GIF in der Gruppe %2$s angeheftet @@ -831,9 +876,10 @@ %1$s hat eine Rechnung in der Gruppe %2$s angeheftet %1$s hat \"%2$s\" angeheftet %1$s hat eine Nachricht angeheftet - %1$s hat eine Umfrage angeheftet + %1$s hat eine Umfrage %2$s angeheftet %1$s hat ein Bild angeheftet %1$s hat ein Spiel angeheftet + %1$s hat ein Spielergebnis angeheftet %1$s hat ein Video angeheftet %1$s hat eine Datei angeheftet %1$s hat eine Rechnung angeheftet @@ -841,7 +887,7 @@ %1$s hat einen %2$s Sticker angeheftet %1$s hat eine Sprachnachricht angeheftet %1$s hat eine Videonachricht angeheftet - %1$s hat einen Kontakt angeheftet + %1$s hat einen Kontakt %2$s angeheftet %1$s hat einen Standort angeheftet %1$s hat einen Live-Standort angeheftet %1$s hat ein GIF angeheftet @@ -886,6 +932,8 @@ Leider ist diese Gruppe schon voll. Leider gibt es diesen Chat nicht. Link in die Zwischenablage kopiert + Link in Zwischenablage kopiert.\nDer Link funktioniert nur für Mitglieder dieses Chats. + Leider kannst du auf diese Nachricht nicht zugreifen. Du bist kein Mitglied des Chats, in dem sie veröffentlicht wurde. Telefon in die Zwischenablage kopiert E-Mail in die Zwischenablage kopiert Per Link zur Gruppe einladen @@ -908,6 +956,7 @@ Administratoren NUTZER EINSCHRÄNKEN Löschen und Gruppe verlassen + Löschen und Gruppe verlassen Mitteilungen Berechtigungen ändern Aus der Gruppe entfernen @@ -979,6 +1028,8 @@ Sticker Sticker hinzufügen + %1$s HINZUFÜGEN + %1$s ENTFERNEN Masken hinzufügen Sticker hinzufügen Zu Favoriten hinzufügen @@ -1000,7 +1051,12 @@ Entfernen Noch keine Sticker Keine Sticker gefunden + Kein GIF gefunden + Kein Emoji gefunden Noch keine Masken + Emoji-Vorschläge + "**Telegram** ermöglicht dir die Suche nach tausenden Emoji anhand von Wörtern. Hier und da fehlen jedoch einige. Wenn du Emoji-Ersetzungen vorschlagen möchtest, besuche bitte diese Seite: " + https://translations.telegram.org/%1$s/emoji Masken Masken lassen sich Bildern hinzufügen. Öffne dazu vor dem Versand einfach den Editor. Angesagte Sticker @@ -1046,6 +1102,9 @@ THEMA SPEICHERN Neues Farbthema Farbthema + Ansicht der Chatliste + Zwei Zeilen + Drei Zeilen THEMA ERSTELLEN ANWENDEN Vorschau @@ -1224,6 +1283,9 @@ Bilder Videos Dateien + Bilder + Videos + Dateien Auto-Download (Dateien und Musik) Auto-Download (Bilder) Auto-Download (Videos und GIFs) @@ -1250,7 +1312,8 @@ Bei Roaming GIFs Videos - Press the volume buttons to turn sound on. + Lautstärketasten drücken,\num Ton einzuschalten. + Das Konto wurde vom Nutzer ausgeblendet Automatische Medienwiedergabe Zum Sprechen ans Ohr In der Galerie speichern @@ -1292,7 +1355,7 @@ Anzahl Benachrichtigungen %1$s innerhalb %2$s Linkvorschau - Die Linkvorschau wird auf den Telegram-Servern generiert. Wir speichern keine Daten über die von dir gesendeten Links. + Die Linkvorschau wird auf den Servern von Telegram generiert. Wir speichern keine Daten über die von dir gesendeten Links. Geheime Chats In-App Browser Externe Links innerhalb der App öffnen @@ -1358,6 +1421,9 @@ Darstellung Sticker und Masken Wähle eigene Farbthemen + Zeige Benachrichtigungen von + Allen Konten + Ausschalten, wenn du nur vom aktiven Konto Benachrichtigungen empfangen möchtest. Benachrichtigungen für Chats Private Chats Gruppen @@ -1382,6 +1448,12 @@ Melde uns jederzeit Probleme. Die Abmeldung löst sie normalerweise nicht. Abmelden Wichtig: Die Abmeldung in der App beendet alle deine Geheimen Chats. + Einstellungen durchsuchen + Letzte Suche + Häufig gestellte Fragen + Leider nichts gefunden + Du hast bisher\nnoch nichts gesucht + FAQ Lokale Datenbank Textnachrichten-Cache leeren? @@ -1856,6 +1928,18 @@ Privatsphäre und Sicherheit Privatsphäre Zuletzt gesehen + Profilbild + Wer darf mein Profilbild sehen? + Hier kannst du per Feineinstellung bestimmen, wer dein Profilbild sehen darf. + Das überschreibt die Einstellungen oben. + Weiterleitungen + Verknüpfung mit deinem Konto + Verknüpfung, laut Einstellungen unten + Keine Verknüpfung mit deinem Konto + Wer darf beim Weiterleiten meiner Nachrichten eine Verknüpfung zu meinem Konto hinzufügen? + Leitet man deine Nachrichten an andere Chats weiter, werden sie nicht mit deinem Konto verknüpft. + Das überschreibt die Einstellungen oben. + Reinhardt, wir brauchen neue Musik für dich 🎶. Peer-to-Peer bei Anrufen Bots und Webseiten Zahlungsinfo entfernen @@ -1888,6 +1972,7 @@ Wer darf deinen Online-Status sehen? Ausnahmen hinzufügen Wichtig: Du kannst den \"zuletzt gesehen\" Status nur von Personen sehen, mit denen du auch deinen teilst. Ansonsten wird die ungefähre Zeit angezeigt (kürzlich, innerhalb einer Woche, innerhalb eines Monats). + Du hast einige Änderungen im Bereich Privatsphäre durchgeführt. Möchtest du die Änderungen anwenden? Immer teilen mit Niemals teilen mit Hier kannst du Kontakte hinzufügen, für die eine Ausnahme gemacht werden soll. @@ -2056,10 +2141,17 @@ Spiel mit %1$s teilen? Kontakt senden an %1$s? Wirklich abmelden?\n\nDu kannst Telegram von all deinen Geräten gleichzeitig nutzen.\n\nWichtig: Abmelden löscht deine Geheimen Chats. + %1$s löschen + %1$s leeren + Cache für %1$s leeren + Wirklich die ausgewählten Chats löschen? + Wirklich den Chatverlauf der ausgewählten Chats leeren? + Gesamten Text- und Medien-Cache für ausgewählte Chats löschen? Gruppe löschen und verlassen? Wirklich Gruppe **%1$s** verlassen und löschen? Möchtest du wirklich diesen Chat löschen? Wirklich den Chat mit **%1$s** löschen? + Wirklich den Chat **Gespeichertes** löschen? Wirklich den Geheimen Chat mit **%1$s** löschen? Wirklich den Chat **%1$s** löschen? Wirklich all deine Cloud-Entwürfe löschen? @@ -2080,11 +2172,23 @@ "Möchtest du wirklich den Verifikationsvorgang stoppen? " Wirklich deinen Verlauf mit **%1$s** leeren? Wirklich den geheimen Verlauf bei dir und **%1$s** leeren? - Wirklich den Verlauf mit **%1$s** leeren? + Wirklich den Verlauf in **%1$s** leeren? Möchtest du wirklich den Verlauf löschen? - Cache des Kanals wirklich löschen? + Wirklich den Chat **Gespeichertes** leeren? + Cache (Texte und Medien) des Kanals wirklich löschen? Cache der Gruppe wirklich löschen? - Sicher, dass du %1$s löschen willst? + %1$s löschen + Nachricht löschen + Du kannst auch %1$s in den Chats der anderen Gruppenmitglieder löschen, wenn du \"Bei allen Mitgliedern löschen\" aktivierst. + Aktivierst du \"Widerrufe meine Nachrichten\", kannst du auch %1$s in den Chats der anderen Mitglieder der Gruppe löschen. + Du kannst auch %1$s bei **%2$s** im Chat löschen, wenn du \"Widerrufe meine Nachrichten\" aktivierst. + Wirklich diese Nachricht löschen? + Wirklich diese Nachrichten löschen? + Wirklich diese Nachricht bei allen löschen? + Wirklich diese Nachrichten bei allen löschen? + Widerrufe meine Nachrichten + Auch bei %1$s löschen + Verlauf auch bei %1$s leeren Nachricht an %1$s senden? Spiel mit %1$s teilen? Kontakt senden an %1$s? @@ -2255,6 +2359,24 @@ %1$d Chats %1$d Chats %1$d Chats + %1$d Chats + %1$d Chat + %1$d Chats + %1$d Chats + %1$d Chats + %1$d Chats + %1$d Chats + %1$d Chat + %1$d Chats + %1$d Chats + %1$d Chats + %1$d Chats + %1$d Chats + %1$d Chat + %1$d Chats + %1$d Chats + %1$d Chats + %1$d Chats %1$d Chats %1$d Chat %1$d Chats @@ -2381,6 +2503,12 @@ %1$d Sticker %1$d Sticker %1$d Sticker + %1$d masks + %1$d mask + %1$d masks + %1$d masks + %1$d masks + %1$d masks %1$d Abonnenten %1$d Abonnent %1$d Abonnenten @@ -2448,6 +2576,12 @@ %1$d Bilder %1$d Bilder %1$d Bilder + %1$d Bilder + %1$d Bild + %1$d Bilder + %1$d Bilder + %1$d Bilder + %1$d Bilder %1$d Dateien %1$d Datei %1$d Dateien @@ -2526,6 +2660,88 @@ und %1$d andere und %1$d andere und %1$d andere + + Gruppe + Kanal + Geheimer Chat + Gesendet %s + Empfangen %s + Zurückgehen + Navigationsmenü öffnen + %2$s von %1$s + Weitere Optionen + Abspielen + Pause + Download + Download abbrechen + Datei öffnen + Nachrichtenoptionen + Auswahlmodus aufrufen + Emoji, Sticker und GIFs + Medien anhängen + Ohne Benachrichtigung senden + Benachrichtigungen senden + Bot-Befehle + Bot-Tastatur + Tastatur anzeigen + Sprachnachricht aufnehmen + Videonachricht aufnehmen + Chat öffnen + Profilbild + Profilbild ändern + Sortierung ändern + Konten zeigen + Konten verstecken + Zur Nachricht wechseln + Antwort abbrechen + Weiterleitung abbrechen + Bearbeitung abbrechen + Antworten auf + Weitergeleitet von + Bearbeitung + App sperren + App freigeben + Rücktaste + Vorherige + Nicht mehr wiederholen + Playlist wiederholen + 1x wiederholen + Audioplayer schliessen + Doppelte Wiedergabegeschwindigkeit + Live Standort nicht mehr teilen + Sofortkamera + Verschluss + Kamera wechseln + Blitz, ausgeschaltet + Blitz, automatisch + Blitz, eingeschaltet + Sticker-Paket + GIFs + Sticker + Panel erweitern + Panel einklappen + Benutzeroptionen + Drehen + Bildbearbeitung + Anpassungen + Bildbetrachter + Zum Ende wechseln + Gehe zur nächsten Erwähnung + Mikrofon stumm schalten + Titel + Überschrift + Mein Standort + Videoqualität + Seitenverhältnis + Nimm ein weiteres Bild auf + Gesehen + Noch nicht gesehen + Noch nicht abgespielt + Nächstes Suchergebnis + Vorheriges Suchergebnis + Nach Nutzern filtern + Bild aufnehmen + Video aufnehmen dd. MMM yyyy, h:mm a dd. MMM yyyy, HH:mm diff --git a/TMessagesProj/src/main/res/values-es/strings.xml b/TMessagesProj/src/main/res/values-es/strings.xml index 2ca3ab8b2..7df0dbfa6 100644 --- a/TMessagesProj/src/main/res/values-es/strings.xml +++ b/TMessagesProj/src/main/res/values-es/strings.xml @@ -24,7 +24,7 @@ Verificación Enviamos un SMS con el código de activación al **%1$s**. - Enviamos el código a la aplicación **Telegram** en tu otro dispositivo. + Enviamos el código a la app de **Telegram** en tu otro dispositivo. Revisa tus mensajes en Telegram Pon el código Estamos llamando al número **%1$s**.\n\nNo contestes. Telegram hará todo el proceso automáticamente. @@ -142,14 +142,28 @@ Intercambiando claves de cifrado... %s se unió a tu chat secreto. Te uniste al chat secreto. - Eliminar historial + Vaciar chat Historial borrado. + Silenciar + Activar Chat eliminado. Grupo eliminado. Canal eliminado. - DESHACER + Archivo anclado. + Desliza el archivo hacia la izquierda para ocultarlo. + Archivo oculto. + Desliza hacia abajo para ver el archivo. + Chat archivado. + Chats archivados. + Oculta el archivo deslizándolo a la izquierda. + ANULAR Eliminar de la caché Eliminar y salir + Ocultar + Anclar + Archivar + Desarchivar + Chats archivados Eliminar chat Cuenta eliminada Elige el chat @@ -162,7 +176,7 @@ Buscar Silenciar notificaciones Silenciar %1$s - No silenciar + Activar notificaciones En %1$s Desactivar HASHTAGS @@ -176,6 +190,7 @@ %1$s por %2$s Enviar comentarios sobre esta vista previa Enviar sticker + Enviar GIF Ver pack Anclar Lo sentimos, no puedes anclar más de %1$s chats arriba. @@ -190,6 +205,12 @@ AHORA NO CONTINUAR Tus contactos en Telegram + Este es tu Archivo + Los chats con notificaciones activas se\ndesarchivan al recibir mensajes nuevos. + Chats silenciados + Los chats silenciados se mantienen\narchivados al recibir mensajes nuevos. + Chats anclados + Puedes anclar un número ilimitado de\nchats archivados en la parte superior. Promover a administrador Permisos de administrador @@ -281,6 +302,11 @@ Añadir excepción Buscar excepciones Usuarios eliminados + Contactos en este canal + Contactos en este grupo + Bots + Otros miembros + Otros suscriptores Usuarios restringidos Administradores Eliminar canal @@ -299,7 +325,7 @@ Creador Administrador SILENCIAR - NO SILENCIAR + ACTIVAR NOTIFICACIONES Añadir administrador Eliminar usuario Quitar suspensión @@ -330,13 +356,14 @@ %1$s publicó un mensaje %1$s publicó una foto %1$s publicó un video - %1$s publicó un contacto - %1$s publicó una encuesta + %1$s publicó un contacto %2$s + %1$s publicó una encuesta %2$s %1$s publicó una ubicación %1$s publicó una ubicación en tiempo real %1$s publicó un archivo %1$s publicó un GIF %1$s publicó %2$s + %1$s publicó un álbum %1$s publicó un mensaje de voz %1$s publicó un videomensaje %1$s publicó un audio @@ -377,7 +404,7 @@ Enviar encuestas Enviar stickers y GIF Incrustar enlaces - Cambiar información del chat + Cambiar info. del chat Anclar mensajes Añadir usuarios no puede leer @@ -521,8 +548,8 @@ Incrustar enlaces Leer mensajes cambió los privilegios de %1$s - Cambiar la información del canal - Cambiar la información del grupo + Cambiar info. del canal + Cambiar info. del grupo Publicar mensajes Editar mensajes Eliminar mensajes @@ -589,7 +616,7 @@ %1$s está grabando un videomensaje... %1$s está enviando un audio... %1$s está enviando una foto... - VISTA RÁPIDA + INSTANT VIEW VER GRUPO VER FONDO VER CANAL @@ -679,6 +706,14 @@ Reportar spam Eliminar todo lo de %1$s ¿Eliminar los emojis recientes? + Emoticonos y personas + Animales y naturaleza + Comida y bebida + Actividades + Viajes y destinos + Objetos + Símbolos + Banderas Reportar Reporte enviado Spam @@ -727,19 +762,23 @@ Los administradores del grupo han restringido que envíes multimedia hasta el %1$s Los administradores del grupo han restringido que envíes contenido integrado hasta el %1$s Los administradores del grupo han restringido que envíes stickers hasta el %1$s + Los administradores del grupo han restringido que envíes GIF hasta el %1$s Los administradores del grupo han restringido que escribas hasta el %1$s - Los administradores del grupo han restringido que envíes multimedia aquí. + Los administradores del grupo han restringido que envíes multimedia. Los administradores del grupo han restringido que envíes contenido integrado Los administradores del grupo han restringido que envíes stickers. - Los administradores del grupo han restringido que escribas aquí. + Los administradores del grupo han restringido que envíes GIF. + Los administradores del grupo han restringido que escribas. No se puede enviar multimedia en este grupo. No se puede usar bots integrados en este grupo. No se puede usar stickers en este grupo. - No se puede escribir mensajes en este grupo. + No se puede enviar GIF en este grupo. + No se puede enviar mensajes en este grupo. administrador La instalación de APK está restringida para esta aplicación. Puedes habilitarla en los ajustes del sistema. Mensajes no leídos Buscar packs de stickers + Buscar emoji URL Vista previa del mapa Elige el proveedor de vista previa del mapa @@ -748,6 +787,7 @@ Yandex Ninguno ¿Instalar Google Maps? + ESTAFA %1$s activó la autodestrucción en %2$s Activaste la autodestrucción en %1$s @@ -756,6 +796,7 @@ Tienes un mensaje nuevo %1$s: %2$s %1$s te envió %2$s + %1$s te envió un álbum %1$s te reenvió %2$s %1$s te envió un mensaje %1$s te envió una foto @@ -763,11 +804,12 @@ %1$s te envió una factura por %2$s %1$s te envió una foto con autodestrucción %1$s te envió un video con autodestrucción - %1$s compartió un contacto contigo - %1$s te envió una encuesta + %1$s compartió un contacto %2$s contigo + %1$s te envió una encuesta %2$s %1$s te envió una ubicación %1$s te envió una ubicación en tiempo real %1$s te invitó a jugar a %2$s + %1$s puntuó %3$s en el juego %2$s %1$s te envió un archivo %1$s te envió un GIF %1$s te envió un mensaje de voz @@ -779,11 +821,12 @@ %1$s envió un mensaje al grupo %2$s %1$s envió una foto al grupo %2$s %1$s envió un video al grupo %2$s - %1$s envió una encuesta al grupo %2$s - %1$s compartió un contacto en el grupo %2$s + %1$s envió una encuesta %3$s al grupo %2$s + %1$s compartió un contacto %3$s en el grupo %2$s %1$s envió una ubicación al grupo %2$s %1$s compartió una ubicación en tiempo real al grupo %2$s %1$s invitó al grupo %2$s a jugar a %3$s + %1$s puntuó %4$s en el juego %3$s en el grupo %2$s %1$s envió un archivo al grupo %2$s %1$s envió un GIF al grupo %2$s %1$s envió una factura al grupo %2$s por %3$s @@ -806,6 +849,7 @@ %1$s actualizó su foto de perfil %1$s se unió al grupo %2$s con un enlace de invitación %1$s envió %3$s al grupo %2$s + %1$s envió un álbum al grupo %2$s %1$s reenvió %3$s al grupo %2$s Responder Responder a %1$s @@ -814,16 +858,17 @@ %1$s %2$s %1$s ancló \"%2$s\" en el grupo %3$s %1$s ancló un mensaje en el grupo %2$s - %1$s ancló una encuesta en el grupo %2$s + %1$s ancló una encuesta %3$s en el grupo %2$s %1$s ancló una foto en el grupo %2$s %1$s ancló un juego en el grupo %2$s + %1$s ancló una puntuación en el grupo %2$s %1$s ancló un video en el grupo %2$s %1$s ancló un archivo en el grupo %2$s %1$s ancló un sticker en el grupo %2$s %1$s ancló un %3$s sticker en el grupo %2$s %1$s ancló un mensaje de voz en el grupo %2$s %1$s ancló un videomensaje en el grupo %2$s - %1$s ancló un contacto en el grupo %2$s + %1$s ancló un contacto %3$s en el grupo %2$s %1$s ancló un mapa en el grupo %2$s %1$s ancló una ubicación en tiempo real en el grupo %2$s %1$s ancló un GIF en el grupo %2$s @@ -831,9 +876,10 @@ %1$s ancló una factura en el grupo %2$s %1$s ancló \"%2$s\" %1$s ancló un mensaje - %1$s ancló una encuesta + %1$s ancló una encuesta %2$s %1$s ancló una foto %1$s ancló un juego + %1$s ancló una puntuación %1$s ancló un video %1$s ancló un archivo %1$s ancló una factura @@ -841,7 +887,7 @@ %1$s ancló un %2$s sticker %1$s ancló un mensaje de voz %1$s ancló un videomensaje - %1$s ancló un contacto + %1$s ancló un contacto %2$s %1$s ancló un mapa %1$s ancló una ubicación en tiempo real %1$s ancló un GIF @@ -868,7 +914,7 @@ últ. vez hace unos días últ. vez hace unas semanas últ. vez hace mucho tiempo - Mensaje nuevo + Nuevo mensaje Elige contactos para invitarlos a Telegram INVITAR A TELEGRAM Compartir Telegram... @@ -886,6 +932,8 @@ Lo sentimos. Este grupo está lleno. Lo sentimos, este chat no existe. Enlace copiado al portapapeles + Enlace copiado al portapapeles.\nEste enlace sólo funcionará para miembros de este chat. + Lamentablemente, no puedes acceder a este mensaje. No eres miembro del chat en el que fue publicado. Teléfono copiado al portapapeles Correo copiado al portapapeles Invitar al grupo con un enlace @@ -908,6 +956,7 @@ Administradores SUSPENDER DEL GRUPO Eliminar y salir del grupo + Eliminar y salir del grupo Notificaciones Permisos de usuario Eliminar del grupo @@ -979,6 +1028,8 @@ Stickers y máscaras Añadir stickers + AÑADIR %1$s + ELIMINAR %1$s Añadir máscaras Añadir a stickers Añadir a favoritos @@ -1000,7 +1051,12 @@ Eliminar Aún no hay stickers No se encontraron stickers + No se encontraron GIF + No se encontraron emojis Aún no hay máscaras + Sugerencias de emojis + **Telegram** te permite encontrar emojis a partir de miles de palabras clave, pero siempre puede faltar alguna. Si quieres sugerir una palabra clave, puedes ayudarnos visitando: + https://translations.telegram.org/%1$s/emoji Máscaras Puedes añadir máscaras a las fotos que envías. Para hacerlo, abre el editor de fotos antes de enviar una foto. Stickers destacados @@ -1046,6 +1102,9 @@ GUARDAR TEMA Nuevo tema Tema + Vista de lista de chats + Dos líneas + Tres líneas CREAR TEMA APLICAR Vista previa del tema @@ -1077,7 +1136,7 @@ Vista previa en la app Restablecer Restablecer todas las notificaciones - Deshacer todos los ajustes de notificaciones personalizadas para todos tus contactos, grupos y canales. + Deshace todos los ajustes de notificaciones personalizadas para todos tus contactos, grupos y canales. Notificaciones y sonidos Notificaciones personalizadas Notificaciones emergentes @@ -1100,9 +1159,9 @@ Las notificaciones con prioridad alta funcionarán aunque tu teléfono esté en modo no molestar. General Silenciado - No silenciado - - No + Notificaciones activadas + Activadas + Desactivadas Desactivadas hasta %1$s Por defecto (Sí) Por defecto (No) @@ -1124,7 +1183,7 @@ Vista previa del fondo Pista: algunas imágenes de fondo se ven mejor difuminadas. ¡Woo-hoo! ¡Gracias! - Desliza a la izquierda o derecha para ver más colores + Desliza a la izquierda o derecha para ver más colores. El salmón es un pez, no un color. Lúcio Reinhardt, necesitamos encontrarte algunas nuevas canciones 🎶. @@ -1209,7 +1268,7 @@ Descarga automática de multimedia Autodescargar multimedia Activada en todos los chats - Hasta %1$s para todos los chats + Hasta %1$s en todos los chats Desactivada Hasta %1$s para %2$s Activada para %1$s @@ -1224,6 +1283,9 @@ Fotos Videos Archivos + Fotos + Videos + Archivos Autodescarga de archivos y música Autodescargar fotos Autodescarga de videos y GIF @@ -1250,7 +1312,8 @@ Con itinerancia de datos GIF Videos - Press the volume buttons to turn sound on. + Presiona los botones de volumen para escucharlo. + Cuenta oculta para mensajes reenviados Autorreproducir multimedia Elevar para hablar Guardar en galería @@ -1259,7 +1322,7 @@ Personalizadas Activar notificaciones personalizadas Importancia - Como en Ajustes + Igual que en Ajustes Baja Media Alta @@ -1295,7 +1358,7 @@ Las vistas previas serán generadas en los servidores de Telegram. No almacenamos datos sobre los enlaces que envías. Chats secretos Usar navegador interno - Abrir enlaces externos en la aplicación + Abrir enlaces externos en la app Direct Share Ver chats recientes al compartir en Android Emoji @@ -1358,6 +1421,9 @@ Apariencia Stickers y máscaras Elige esquemas de colores personalizados + Mostrar notificaciones para + Todas las cuentas + Desactívalo si quieres recibir notificaciones sólo de tu cuenta activa. Notificaciones para chats Chats privados Grupos @@ -1372,19 +1438,25 @@ Opciones alternativas Añadir otra cuenta Conecta otras cuentas de Telegram y cambia entre ellas fácilmente. - Poner un código de acceso + Poner un código Bloquea la app con un código para que otros no puedan abrirla. - Eliminar caché + Eliminar la caché Libera espacio en tu dispositivo; tu multimedia permanecerá en la nube. - Cambiar número de teléfono - Mueve tus cuenta, chats y multimedia a un nuevo número. + Cambiar el número de teléfono + Mueve tu cuenta, chats y multimedia a un nuevo número. Contactar al soporte - Dinos cualquier problema; cerrar sesión generalmente no ayuda. + Cuéntanos sobre cualquier problema; cerrar sesión generalmente no ayuda. Cerrar sesión Cerrar sesión desactiva los chats secretos. + Buscar ajustes y FAQ + Búsquedas recientes + Preguntas frecuentes + No se encontraron resultados + No hay búsquedas recientes + FAQ Base de datos local - ¿Eliminar los mensajes en la caché? + ¿Eliminar de la caché los mensajes de texto? Al eliminar la base de datos se eliminarán los mensajes en la caché y se comprimirá la base de datos para liberar espacio de almacenamiento. Telegram requiere algunos datos para funcionar, así que la base de datos nunca podrá llegar a cero.\n\nEsto puede tomar unos minutos. Eliminar caché Eliminar @@ -1398,7 +1470,7 @@ Otros archivos Vacío Conservar multimedia - Las fotos, los videos y los archivos de los chats en la nube a los que **no accedas** durante ese periodo de tiempo se eliminarán del dispositivo para liberar espacio.\n\nToda la multimedia permanecerá en la nube de Telegram y podrás volver a descargarla si la necesitas. + Las fotos, videos y otros archivos de los chats en la nube, a los que **no accedas** durante este periodo, se eliminarán del dispositivo para ahorrar espacio.\n\nToda la multimedia estará en la nube de Telegram y podrás descargarla de nuevo si la necesitas. Siempre Mensajes de voz Videomensajes @@ -1600,7 +1672,7 @@ Salir de todos los dispositivos, excepto este. ¿Quieres terminar todas las otras sesiones? Cerrar todas las otras sesiones - aplicación no oficial + app no oficial Sin sesiones activas. Puedes iniciar sesión en sitios web que permitan registrarse con Telegram. Sitios web conectados @@ -1614,17 +1686,17 @@ Intentos de acceso incompletos Los dispositivos de arriba no tienen acceso a tus mensajes. El código fue ingresado correctamente, pero no se ingresó una contraseña correcta. - Código de acceso - Cambiar código de acceso - Cuando configuras un código, aparece un candado en la pantalla de chats. Toca sobre él para bloquear y desbloquear la aplicación.\n\nNota: Si olvidas el código, tendrás que eliminar y reinstalar la aplicación. Perderás todos los chats secretos. + Código de bloqueo + Cambiar código + Cuando configuras un código, aparece un candado en la pantalla de chats. Toca sobre él para bloquear y desbloquear la app.\n\nNota: Si olvidas el código, tendrás que eliminar y reinstalar la app. Perderás todos los chats secretos. PIN Contraseña - Pon tu código de acceso actual - Pon un código de acceso - Pon tu nuevo código de acceso - Pon tu código de acceso + Pon tu código actual + Pon un código + Pon tu nuevo código + Pon tu código Repite tu nuevo código - Los códigos de acceso no coinciden + Los códigos no coinciden Autobloqueo El bloqueo se activará transcurrido este tiempo. en %1$s @@ -1651,7 +1723,7 @@ Noviembre Diciembre ARCHIVOS - MEDIA + MULTIMEDIA ENLACES AUDIO VOZ @@ -1722,9 +1794,9 @@ La app no logró reproducir este video. ¿Quieres intentarlo con un reproductor externo? No hay fotos recientes No hay GIF recientes - BUSCA FOTOS + BUSCAR FOTOS BÚSQUEDA WEB - BUSCA GIF + BUSCAR GIF Buscar foto Buscar GIF Recortar imagen @@ -1766,7 +1838,7 @@ Normal Restablecer Original - 1:1 + Cuadrada Mostrar multimedia en mensajes por separado Agrupar multimedia en un mensaje @@ -1856,6 +1928,18 @@ Privacidad y seguridad Privacidad Última conexión + Foto de perfil + ¿Quién puede ver mi foto de perfil? + Puedes restringir quién puede ver tu foto de perfil con gran precisión. + Estos ajustes anularán los valores 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. + Estos ajustes anularán los valores de arriba. + Reinhardt, necesitamos encontrarte algunas nuevas canciones 🎶. Peer-to-peer en llamadas Bots y sitios web Eliminar información de pago y envío @@ -1888,6 +1972,7 @@ ¿Quién puede ver mi última conexión? Añadir excepciones Importante: No podrás ver la última conexión de las personas con las que no compartes la tuya. En su lugar, se mostrarán conexiones indeterminadas (recientemente, hace unos días, hace unas semanas). + Has cambiado algunos ajustes de privacidad. ¿Aplicar cambios? Compartir con No compartir con Estos ajustes anularán los valores de arriba. @@ -1957,7 +2042,7 @@ Continuar Crear enlace RECORTAR - Actualizar aplicación + Actualizar app ACTUALIZAR ACTUALIZAR MÁS TARDE @@ -1982,10 +2067,10 @@ Eliminaste a un2 Dejaste el grupo Añadiste a un2 - Has conseguido %1$s - un1 ha conseguido %1$s - Has conseguido %1$s en un2 - un1 ha conseguido %1$s en un2 + Puntuaste %1$s + un1 puntuó %1$s + Puntuaste %1$s en un2 + un1 puntuó %1$s en un2 Eliminaste la foto del grupo Cambiaste la foto del grupo Cambiaste el nombre del grupo a un2 @@ -2032,7 +2117,7 @@ ¿Detener la carga? Actualizar Telegram - Lo sentimos, tu aplicación de Telegram no está actualizada y no puede procesar esta solicitud. Por favor, actualiza Telegram. + Lo sentimos, tu app de Telegram no está actualizada y no puede procesar esta solicitud. Por favor, actualiza Telegram. Número de teléfono inválido. Por favor, revisa el número y reinténtalo. Por favor, inicia sesión en tu cuenta de Telegram para usar Telegram Passport. Este número de teléfono está suspendido. @@ -2055,11 +2140,18 @@ ¿Enviar mensajes a %1$s? ¿Compartir el juego con %1$s? ¿Enviar contacto a %1$s? - ¿Quieres cerrar sesión?\n\nRecuerda que puedes usar Telegram en todos tus dispositivos a la vez.\n\nNo olvides que, al cerrar sesión, eliminas todos tus chats secretos. + ¿Quieres cerrar sesión?\n\nTen en cuenta que puedes usar Telegram en todos tus dispositivos a la vez.\n\nRecuerda, cerrar sesión desactiva los chats secretos. + Eliminar %1$s + Vaciar %1$s + Caché vacía para %1$s + ¿Quieres eliminar los chats seleccionados? + ¿Quieres vaciar el historial en los chats seleccionados? + ¿Eliminar de la caché todo el texto y la multimedia de los chats seleccionados? ¿Quieres eliminar y salir del grupo? ¿Quieres eliminar y salir del grupo **%1$s**? ¿Quieres eliminar este chat? ¿Quieres eliminar el chat con **%1$s**? + ¿Quieres eliminar **Mensajes guardados**? ¿Quieres eliminar el chat secreto con **%1$s**? ¿Quieres eliminar el chat **%1$s**? ¿Quieres eliminar todos los borradores de la nube? @@ -2081,10 +2173,22 @@ ¿Quieres eliminar el historial del chat con **%1$s**? ¿Quieres eliminar el historial del chat secreto para ti y para **%1$s**? ¿Quieres eliminar el historial en **%1$s**? - ¿Quieres eliminar el historial? - ¿Eliminar de la caché los mensajes y multimedia de este canal? - ¿Eliminar todos los mensajes y multimedia en la caché de este grupo? - ¿Quieres eliminar %1$s? + ¿Quieres vaciar el historial? + ¿Quieres eliminar el historial de **Mensajes guardados**? + ¿Eliminar de la caché todo el texto y la multimedia de este canal? + ¿Eliminar de la caché todo el texto y la multimedia de este grupo? + Eliminar %1$s + Eliminar mensaje + “Eliminar para todos” también eliminará los %1$s para los otros miembros del grupo. + “Retirar mis mensajes” también eliminará los %1$s que enviaste para los otros miembros del grupo. + “Retirar mis mensajes” también eliminará los %1$s que enviaste para %2$s. + ¿Quieres eliminar este mensaje? + ¿Quieres eliminar estos mensajes? + ¿Quieres eliminar este mensaje para todos? + ¿Quieres eliminar estos mensajes para todos? + Retirar mis mensajes + Eliminar también para %1$s + Vaciar también para %1$s ¿Enviar mensajes a %1$s? ¿Compartir el juego en %1$s? ¿Enviar contacto a %1$s? @@ -2093,8 +2197,8 @@ ¿Quieres permitir las vistas previas ampliadas en chats secretos? Ten en cuenta que son generadas en los servidores de Telegram. Ten en cuenta que los bots integrados son hechos por terceros. Para que funcione, los símbolos escritos después del alias del bot, son enviados al desarrollador respectivo. Lo sentimos, no puedes editar este mensaje. - Por favor, permite a Telegram recibir SMS, para ingresar el código automáticamente. - Por favor, permite a Telegram recibir llamadas para ingresar el código automáticamente. + Por favor, permite a Telegram recibir SMS para que podamos ingresar automáticamente el código por ti. + Por favor, permite a Telegram recibir llamadas para que podamos ingresar automáticamente el código por ti. Por favor, permite a Telegram recibir llamadas para que podamos confirmar tu número de teléfono automáticamente. Por favor, permite a Telegram recibir llamadas para que podamos confirmar tu número de teléfono automáticamente. Lo sentimos, no tienes permitido hacer esto. @@ -2106,9 +2210,9 @@ Los administradores del grupo han restringido que envíes stickers. Lo sentimos, los administradores del grupo han restringido que envíes multimedia. Lo sentimos, los administradores del grupo han restringido que envíes encuestas. - Lo sentimos, no se pueden enviar stickers en este grupo. + Lo sentimos, no se puede enviar stickers en este grupo. Lo sentimos, no se puede enviar multimedia en este grupo. - Lo sentimos, no se pueden enviar encuestas en este grupo. + Lo sentimos, no se puede enviar encuestas en este grupo. Lo sentimos mucho, pero esto significa que no puedes inscribirte en Telegram.\n\nA diferencia de otros, nosotros no usamos los datos para la publicidad dirigida u otros propósitos comerciales. Telegram sólo almacena la información que necesita para funcionar como un servicio en la nube. Puedes ajustar cómo usamos tus datos (por ejemplo, eliminar contactos sincronizados) en los ajustes de privacidad y seguridad.\n\nPero si no estás de acuerdo con los modestos requisitos de Telegram, no podremos brindarte este servicio. Verificación de edad Política de privacidad y términos de servicio @@ -2255,6 +2359,24 @@ %1$d chats %1$d chats %1$d chats + %1$d chats + %1$d chat + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chat + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chat + %1$d chats + %1$d chats + %1$d chats + %1$d chats %1$d chats %1$d chat %1$d chats @@ -2381,6 +2503,12 @@ %1$d stickers %1$d stickers %1$d stickers + %1$d máscaras + %1$d máscara + %1$d máscaras + %1$d máscaras + %1$d máscaras + %1$d máscaras %1$d suscriptores %1$d suscriptor %1$d suscriptores @@ -2399,12 +2527,12 @@ %1$d usuarios eliminados %1$d usuarios eliminados %1$d usuarios eliminados - %1$d puntos - %1$d punto - %1$d puntos - %1$d puntos - %1$d puntos - %1$d puntos + %1$d + %1$d + %1$d + %1$d + %1$d + %1$d hace %1$d minutos hace %1$d minuto hace %1$d minutos @@ -2448,6 +2576,12 @@ %1$d fotos %1$d fotos %1$d fotos + %1$d fotos + %1$d foto + %1$d fotos + %1$d fotos + %1$d fotos + %1$d fotos %1$d archivos %1$d archivo %1$d archivos @@ -2526,6 +2660,88 @@ y otros %1$d y otros %1$d y otros %1$d + + Grupo + Canal + Chat secreto + Enviado el %s + Recibido el %s + Volver atrás + Abrir menú de navegación + %2$s por %1$s + Más opciones + Reproducir + Pausar + Descargar + Cancelar descarga + Abrir archivo + Opciones de mensaje + Entrar en modo selección + Emoji, stickers y GIF + Adjuntar multimedia + Enviar silenciosamente + Enviar notificaciones + Comandos del bot + Teclado del bot + Mostrar teclado + Grabar mensaje de voz + Grabar videomensaje + Abrir chat + Foto de perfil + Cambiar foto de perfil + Cambiar orden + Mostrar cuentas + Ocultar cuentas + Ir al mensaje + Cancelar respuesta + Cancelar reenvío + Cancelar edición + Respondiendo a + Reenviando desde + Editando + Bloquear aplicación + Desbloquear aplicación + Retroceso + Anterior + Repetir, desactivado + Repetir, lista de reproducción + Repetir, una + Cerrar reproductor de audio + Velocidad doble + Dejar de compartir la ubicación en tiempo real + Cámara instantánea + Obturador + Cambiar cámara + Flash, desactivado + Flash, automático + Flash, activado + Pack de stickers + GIF + Stickers + Expandir panel + Contraer panel + Opciones de usuario + Rotar + Editor de fotos + Ajustes + Visor de fotos + Ir al final + Ir a la próxima mención + Silenciar micrófono + Título + Encabezado + Mi ubicación + Calidad de video + Relación de aspecto + Tomar una foto más + Visto + No visto + No reproducido + Siguiente resultado de búsqueda + Anterior resultado de búsqueda + Filtrar por usuario + Tomar una foto + Grabar video dd MMM yyyy, h:mm a dd MMM yyyy, HH:mm diff --git a/TMessagesProj/src/main/res/values-it/strings.xml b/TMessagesProj/src/main/res/values-it/strings.xml index fd0f6ed49..40be96bb8 100644 --- a/TMessagesProj/src/main/res/values-it/strings.xml +++ b/TMessagesProj/src/main/res/values-it/strings.xml @@ -144,12 +144,26 @@ Ti sei unito alla chat segreta. Cancella cronologia Cronologia cancellata. + Silenzia + Suona Chat eliminata. Gruppo eliminato. Canale eliminato. + Archivio fissato. + Scorri a sinistra sull\'archivio per nasconderlo. + Archivio nascosto. + Scorri in basso per vedere l\'archivio. + Chat archiviata. + Chat archiviate. + Nascondi l\'archivio scorrendo a sinistra su di esso. ANNULLA Elimina dalla cache Elimina ed esci + Nascondi + Fissa + Archivia + Estrai + Chat archiviate Elimina chat Account eliminato Seleziona chat @@ -168,7 +182,7 @@ HASHTAG Recenti Persone - Eliminare %1$s dai suggerimenti? + Rimuovere %1$s dai suggerimenti? Anteprima link Bozza Cronologia eliminata @@ -176,6 +190,7 @@ %1$s da %2$s Lascia un feedback su questa anteprima Invia sticker + Invia GIF Visualizza pacchetto Fissa in alto Spiacenti, non puoi fissare più di %1$s in alto. @@ -190,6 +205,12 @@ NON ADESSO CONTINUA I tuoi contatti su Telegram + Questo è il tuo archivio + Le chat con le notifiche attive vengono estratte quando arrivano nuovi messaggi. + Chat silenziate + Le chat con le notifiche disattivate rimangono archiviate quando arrivano nuovi messaggi. + Chat fissate + Puoi fissare in alto un numero illimitato di chat archiviate. Rendi amministratore Modifica permessi amministratore @@ -231,8 +252,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 è 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. 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. @@ -281,6 +302,11 @@ Aggiungi eccezione Cerca eccezioni Utenti rimossi + Contatti in questo canale + Contatti in questo gruppo + Bot + Altri membri + Altri iscritti Utenti limitati Amministratori Elimina canale @@ -330,13 +356,14 @@ %1$s ha pubblicato un messaggio %1$s ha pubblicato una foto %1$s ha pubblicato un video - %1$s ha pubblicato un contatto - %1$s ha pubblicato un sondaggio + %1$s pha pubblicato un contatto %2$s + %1$s ha pubblicato un sondaggio %2$s %1$s ha pubblicato una posizione %1$s ha pubblicato una posizione attuale %1$s ha pubblicato un file %1$s ha pubblicato una GIF %1$s ha pubblicato %2$s + %1$s ha pubblicato un album %1$s ha pubblicato un messaggio vocale %1$s ha pubblicato un videomessaggio %1$s ha pubblicato una file audio @@ -679,6 +706,14 @@ Segnala come spam Elimina tutto da %1$s Cancellare le emoji recenti? + Emoticon e persone + Animali e natura + Cibo e bevande + Attività + Viaggi e luoghi + Oggetti + Simboli + Bandiere Segnala Segnalazione inviata Spam @@ -693,7 +728,7 @@ Modifica messaggio Modifica didascalia Tocca per modificare - Scorri verso il basso per i bot + Scorri in basso per i bot %1$s Spiacenti, tempo di modifica scaduto. Aggiungi alla home @@ -727,19 +762,23 @@ Gli amministratori di questo gruppo ti hanno vietato di inviare media qui fino al %1$s Gli amministratori di questo gruppo ti hanno vietato di inviare contenuti inline qui fino al %1$s Gli amministratori di questo gruppo ti hanno vietato di inviare sticker qui fino al %1$s + Gli amministratori di questo gruppo ti hanno vietato di inviare GIF qui fino a %1$s. Gli amministratori di questo gruppo ti hanno vietato di scrivere qui fino al %1$s Gli amministratori di questo gruppo ti hanno vietato di inviare media qui. Gli amministratori di questo gruppo ti hanno vietato di inviare contenuti inline qui Gli amministratori di questo gruppo ti hanno vietato di inviare sticker. + Gli amministratori di questo gruppo ti hanno vietato di inviare GIF. Gli amministratori di questo gruppo ti hanno vietato di scrivere qui. I media non sono permessi in questo gruppo. I bot inline non sono permessi in questo gruppo. Gli sticker non sono permessi in questo gruppo. + Le GIF non sono permesse in questo gruppo. Non è permesso scrivere messaggi in questo gruppo. amministratore L\'installazione di APK è disattivata per questa app. Puoi attivarla nelle impostazioni di sistema. Messaggi non letti Cerca set di sticker + Cerca emoji URL Fornitore anteprima mappa Scegli fornitore anteprima mappa @@ -748,6 +787,7 @@ Yandex Nessuna anteprima Installare Google Maps? + TRUFFA %1$s ha impostato il timer di autodistruzione a %2$s Hai impostato il timer di autodistruzione a %1$s @@ -756,6 +796,7 @@ Hai un nuovo messaggio %1$s: %2$s %1$s ti ha inviato %2$s + %1$s ti ha inviato un album %1$s ti ha inoltrato %2$s %1$s ti ha inviato un messaggio %1$s ti ha inviato una foto @@ -763,11 +804,12 @@ %1$s ti ha inviato una fattura per %2$s %1$s ti ha inviato una foto con autodistruzione %1$s ti ha inviato un video con autodistruzione - %1$s ha condiviso un contatto con te - %1$s ti ha inviato un sondaggio + %1$s ha condiviso il contatto %2$s con te + %1$s ti ha inviato un sondaggio %2$s %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 ti ha inviato un file %1$s ti ha inviato una GIF %1$s ti ha inviato un messaggio vocale @@ -779,11 +821,12 @@ %1$s ha inviato un messaggio nel gruppo %2$s %1$s ha inviato una foto nel gruppo %2$s %1$s ha inviato un video nel gruppo %2$s - %1$s ha inviato un sondaggio nel gruppo %2$s - %1$s ha condiviso un contatto con il gruppo %2$s + %1$s ha inviato un sondaggio %3$s nel gruppo %2$s + %1$s ha condiviso un contatto %3$s nel gruppo %2$s %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 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 @@ -806,6 +849,7 @@ %1$s ha aggiornato la foto del profilo %1$s si è unito al gruppo %2$s tramite link d\'invito %1$s ha inviato %3$s nel gruppo %2$s + %1$s ha inviato un album nel gruppo %2$s %1$s ha inoltrato %3$s nel gruppo %2$s Rispondi Rispondi a %1$s @@ -814,16 +858,17 @@ %1$s %2$s %1$s ha fissato \"%2$s\" nel gruppo %3$s %1$s ha fissato un messaggio nel gruppo %2$s - %1$s ha fissato un sondaggio nel gruppo %2$s + %1$s ha fissato un sondaggio %3$s nel gruppo %2$s %1$s ha fissato una foto nel gruppo %2$s %1$s ha fissato un gioco nel gruppo %2$s + %1$s ha fissato un punteggio nel gruppo %2$s %1$s ha fissato un video nel gruppo %2$s %1$s ha fissato un file nel gruppo %2$s %1$s ha fissato uno sticker nel gruppo %2$s %1$s ha fissato uno %3$s sticker nel gruppo %2$s %1$s ha fissato un messaggio vocale nel gruppo %2$s %1$s ha fissato un videomessaggio nel gruppo %2$s - %1$s ha fissato un contatto nel gruppo %2$s + %1$s ha fissato un contatto %3$s nel gruppo %2$s %1$s ha fissato una posizione nel gruppo %2$s %1$s ha fissato una posizione attuale nel gruppo %2$s %1$s ha fissato una GIF nel gruppo %2$s @@ -831,9 +876,10 @@ %1$s ha fissato una fattura nel gruppo %2$s %1$s ha fissato \"%2$s\" %1$s ha fissato un messaggio - %1$s ha fissato un sondaggio + %1$s ha fissato un sondaggio %2$s %1$s ha fissato una foto %1$s ha fissato un gioco + %1$s ha fissato un punteggio %1$s ha fissato un video %1$s ha fissato un file %1$s ha fissato una fattura @@ -841,7 +887,7 @@ %1$s ha fissato uno %2$s sticker %1$s ha fissato un messaggio vocale %1$s ha fissato un videomessaggio - %1$s ha fissato un contatto + %1$s ha fissato un contatto %2$s %1$s ha fissato una posizione %1$s ha fissato una posizione attuale %1$s ha fissato una GIF @@ -874,8 +920,8 @@ Condividi Telegram... Aggiornare i contatti? Telegram ha trovato molti contatti non sincronizzati, vorresti sincronizzarli adesso? Scegli \'OK\' se stai usando il tuo dispositivo, la tua SIM e il tuo account Google. - Ordinato per nome - Ordinato per ultimo accesso + Ordinati per nome + Ordinati per ultimo accesso Aggiungi persone... Potrai aggiungere più utenti dopo aver creato il gruppo e averlo convertito in supergruppo. @@ -886,6 +932,8 @@ Spiacenti, questo gruppo è già pieno. Spiacenti, sembra che questa chat non esista. Link copiato negli appunti + Link copiato negli appunti.\nQuesto link funzionerà solo per i membri di questa chat. + Sfortunatamente, non puoi accedere a questo messaggio. Non sei membro della chat in cui è stato pubblicato. Numero copiato negli appunti Email copiata negli appunti Invita nel gruppo tramite link @@ -908,6 +956,7 @@ Imposta amministratori RIMUOVI DAL GRUPPO Elimina e lascia il gruppo + Elimina e lascia il gruppo Notifiche Cambia permessi Rimuovi dal gruppo @@ -979,6 +1028,8 @@ Sticker e maschere Aggiungi sticker + AGGIUNGI %1$s + RIMUOVI %1$s Aggiungi maschere Aggiungi agli sticker Aggiungi ai preferiti @@ -1000,7 +1051,12 @@ Rimuovi Ancora nessuno sticker Nessuno sticker trovato + Nessuna GIF trovata + Nessuna emoji trovata Ancora nessuna maschera + Suggerimenti emoji + **Telegram** ti permette di cercare emoji usando migliaia di parole chiave, ma c\'è sempre qualcosa mancante. Se vuoi suggerire nuovi sinonimi per le emoji, puoi aiutarci visitando: + https://translations.telegram.org/%1$s/emoji Maschere Puoi aggiungere maschere alle foto che invii. Per farlo, apri l\'editor fotografico prima di inviare una foto. Sticker in primo piano @@ -1046,6 +1102,9 @@ SALVA TEMA Nuovo tema Tema + Visualizzazione lista chat + Due righe + Tre righe CREA TEMA APPLICA Anteprima tema @@ -1056,7 +1115,7 @@ Ripristina tutte le impostazioni di notifica predefinite Sei sicuro di voler ripristinare tutte le impostazioni di notifica sui valori predefiniti? - Dimensione testo messaggi + Dimensione testo messaggio Fai una domanda Attiva animazioni Impostazioni chat @@ -1173,10 +1232,10 @@ Questa lingua non esiste. Stai già usando questa lingua (**%1$s**). Puoi cambiare la tua lingua in qualsiasi momento nelle Impostazioni. Sfortunatamente, questa lingua personalizza (**%1$s**) non contiene dati per Telegram Android. - Per favore nota che l\'assistenza di Telegram è gestita da volontari. Proviamo a rispondere quanto prima, ma potrebbe volerci del tempo.\n\nDai un\'occhiata alle domande frequenti di Telegram]]>: contengono suggerimenti importanti per risolvere i problemi]]> e risposte a quasi tutte le domande. + Per favore nota che l\'assistenza di Telegram è gestita da volontari. Proviamo a rispondere quanto prima, ma potrebbe volerci del tempo.\n\nDai un\'occhiata alle FAQ di Telegram]]>: contengono suggerimenti importanti per risolvere i problemi]]> e risposte a quasi tutte le domande. Chiedi a un volontario - Domande frequenti - Domande frequenti + FAQ Telegram + FAQ Telegram Aggiungi account Seleziona Account https://telegram.org/faq/it @@ -1224,6 +1283,9 @@ Foto Video File + Foto + Video + File Download automatico file e musica Download automatico foto Download automatico video e GIF @@ -1250,7 +1312,8 @@ In roaming GIF Video - Press the volume buttons to turn sound on. + Premi i tasti del volume per attivare il suono. + Il mittente ha nascosto il suo account Autoriproduzione media Alza per registrare Salva nella galleria @@ -1358,6 +1421,9 @@ Aspetto Sticker e maschere Scegli combinazioni di colori personalizzate + Mostra notifiche da + Tutti gli account + Disattiva se vuoi ricevere notifiche solo dal tuo account attivo. Notifiche per le chat Chat private Gruppi @@ -1382,6 +1448,12 @@ Segnalaci qualsiasi problema; disconnettersi solitamente non aiuta. Esci Uscendo disattiverai tutte le chat segrete. + Cerca impostazioni e FAQ + Ricerche recenti + Domande frequenti + Nessun risultato trovato + Nessuna ricerca recente + FAQ Database locale Cancellare i messaggi salvati nella cache? @@ -1412,7 +1484,7 @@ Per favore crea una password per rendere sicuri i tuoi dati personali tramite crittografia end-to-end.\n\nQuesta password sarà inoltre richiesta ogni volta che accedi a Telegram su un nuovo dispositivo. CREA UNA PASSWORD Elimina Telegram Passport - Sei sicuro di voler cancellare il tuo Telegram Passport? + Sei sicuro di voler eliminare il tuo Telegram Passport? Usare solo caratteri latini. Carica le scansioni di una traduzione inglese verificata del tuo passaporto. Carica le scansioni di una traduzione inglese verificata del tuo passaporto nazionale. @@ -1598,7 +1670,7 @@ Premi su una sessione per terminarla. Terminare questa sessione? Esce da tutti i dispositivi tranne questo. - Terminare tutte le altre sessioni? + Sicuro di voler terminare tutte le altre sessioni? Termina le altre sessioni app non ufficiale Nessun accesso attivo. @@ -1619,7 +1691,7 @@ Quando imposti un codice aggiuntivo, apparirà un\'icona col lucchetto nella pagina delle chat. Premila per bloccare e sbloccare l\'app.\n\nNota: se ti dimentichi il codice, dovrai eliminare e reinstallare l\'app. Tutte le chat segrete verranno perse. PIN Password - Inserisci il tuo codice corrente + Inserisci il tuo codice attuale Inserisci un codice Inserisci il nuovo codice Inserisci il tuo codice @@ -1856,6 +1928,18 @@ Privacy e sicurezza Privacy Ultimo accesso + Foto profilo + Chi può vedere la mia foto profilo? + Puoi decidere chi può vedere la tua foto profilo con precisione granulare. + Queste impostazioni annulleranno i valori 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. + Queste impostazioni annulleranno i valori precedenti. + Reinhardt, dobbiamo trovarti qualche nuova canzone 🎶. Peer-to-peer nelle chiamate Bot e siti web Cancella info di pagamento e spedizione @@ -1888,6 +1972,7 @@ Chi può vedere il tuo ultimo accesso? Aggiungi eccezioni Importante: non potrai vedere l\'ultimo accesso delle persone con cui non condividi l\'ultimo accesso. Verrà mostrato un orario approssimativo (di recente, entro una settimana, entro un mese). + Hai modificato alcune impostazioni della privacy. Applicare le modifiche? Condividi con Non condividere con Queste impostazioni annulleranno i valori precedenti. @@ -1946,7 +2031,7 @@ Elimina Elimina e arresta Inoltra - Riprova + Reinvia Dalla fotocamera Dalla galleria Elimina foto @@ -1995,7 +2080,7 @@ un1 è tornato nel gruppo un1 si è unito al gruppo Sei tornato nel gruppo - Hai consentito a questo bot di scriverti quando ti sei collegato su %1$s. + Hai permesso a questo bot di scriverti quando ti sei collegato su %1$s. %1$s ha ricevuto i seguenti documenti: %2$s Dettagli personali Indirizzo @@ -2056,10 +2141,17 @@ Condividere il gioco con %1$s? Inviare contatto a %1$s? Sei sicuro di voler uscire?\n\nNota che puoi usare Telegram su tutti i tuoi dispositivi contemporaneamente.\n\nRicorda, uscendo eliminerai tutte le chat segrete. + Elimina %1$s + Svuota %1$s + Svuota la cache per %1$s + Sei sicuro di voler eliminare le chat selezionate? + Sei sicuro di voler eliminare la cronologia nelle chat selezionate? + Eliminare tutti i testi e i media dalle chat selezionate? Sei sicuro di voler uscire ed eliminare il gruppo? Sei sicuro di voler eliminare e lasciare il gruppo **%1$s**? Sei sicuro di voler eliminare questa chat? Sei sicuro di voler eliminare la chat con **%1$s**? + Sei sicuro di voler eliminare i **Messaggi salvati**? Sei sicuro di voler eliminare la chat segreta con **%1$s**? Sei sicuro di voler eliminare la chat **%1$s**? Sei sicuro di voler eliminare tutte le bozze? @@ -2072,7 +2164,7 @@ Il bot saprà il tuo numero di telefono. Questo può essere utile per l\'integrazione con altri servizi. Sicuro di voler condividere il tuo numero di telefono %1$s con **%2$s**? Sei sicuro di voler condividere il tuo numero di telefono? - Vuoi bloccare questo contatto? + Sei sicuro di voler bloccare questo contatto? Vuoi sbloccare questo contatto? Sei sicuro di voler eliminare questo contatto? Iniziare una chat segreta? @@ -2082,9 +2174,21 @@ Sei sicuro di voler eliminare la tua cronologia della chat segreta con **%1$s**? Sei sicuro di voler cancellare la cronologia chat di **%1$s**? Sei sicuro di voler eliminare la cronologia? + Sei sicuro di voler pulire i **Messaggi salvati**? Eliminare tutti i testi e i media di questo canale dalla cache? Eliminare tutti i testi e i media di questo gruppo dalla cache? - Sei sicuro di voler eliminare %1$s? + Elimina %1$s + Elimina messaggio + Puoi eliminare %1$s che hai inviato anche dalla cronologia degli altri membri del gruppo selezionando \"Elimina per tutti i membri\". + Puoi eliminare %1$s che hai inviato anche dalla cronologia degli altri membri del gruppo selezionando \"Ritira i miei messaggi\". + Puoi eliminare %1$s che hai inviato anche dalla cronologia di **%2$s** selezionando \"Ritira i miei messaggi\". + Sei sicuro di voler eliminare questo messaggio? + Sei sicuro di voler eliminare questi messaggi? + Sei sicuro di voler eliminare questo messaggio per tutti? + Sei sicuro di voler eliminare questi messaggi per tutti? + Ritira i miei messaggi + Elimina anche per %1$s + Elimina la cronologia anche per %1$s Inviare i messaggi a %1$s? Condividere il gioco con %1$s? Inviare contatto a %1$s? @@ -2106,14 +2210,14 @@ Spiacenti, gli amministratori di questo gruppo ti hanno vietato di inviare sticker. Spiacenti, gli amministratori di questo gruppo ti hanno vietato di inviare media. Spiacenti, gli amministratori di questo gruppo ti hanno vietato di inviare sondaggi. - Spiacenti, non è consentito inviare sticker in questo gruppo. - Spiacenti, non è consentito inviare media in questo gruppo. + Spiacenti, non è permesso inviare sticker in questo gruppo. + Spiacenti, non è permesso inviare media in questo gruppo. Spiacenti, non è permesso inviare sondaggi in questo gruppo. Siamo spiacenti, ma questo significa che non puoi iscriverti a Telegram.\n\nA differenza di altri, non utilizziamo i tuoi dati per il targeting degli annunci o altri scopi commerciali. Telegram conserva solo le informazioni di cui ha bisogno per funzionare come servizio cloud ricco di funzionalità. Puoi regolare il modo in cui utilizziamo i tuoi dati (ad esempio, eliminando i contatti sincronizzati) nelle impostazioni di Privacy e sicurezza.\n\nMa se in genere non sei d\'accordo con le modeste esigenze di Telegram, non sarà possibile per noi fornirti questo servizio. Verifica età Informativa sulla privacy e Termini di servizio Tocca Accetta per confermare di avere almeno %1$s anni. - Siamo molto dispiaciuti, ma questo significa che dobbiamo separarci qui. A differenza di altri, non utilizziamo i tuoi dati per il targeting degli annunci o altri scopi commerciali. Telegram memorizza solo le informazioni necessarie per funzionare come servizio cloud ricco di funzionalità. Puoi regolare il modo in cui utilizziamo i tuoi dati (ad esempio, eliminando i contatti sincronizzati) nelle impostazioni di Privacy e sicurezza.\n\nMa se in genere non sei d\'accordo con le modeste esigenze di Telegram, non sarà possibile per noi fornire questo servizio. Puoi cancellare il tuo account ora - o guardarti intorno ancora e cancellarlo più tardi se ritieni di non essere soddisfatto del modo in cui usiamo i tuoi dati. + Siamo molto dispiaciuti, ma questo significa che dobbiamo separarci qui. A differenza di altri, non utilizziamo i tuoi dati per il targeting degli annunci o altri scopi commerciali. Telegram memorizza solo le informazioni necessarie per funzionare come servizio cloud ricco di funzionalità. Puoi regolare il modo in cui utilizziamo i tuoi dati (ad esempio, eliminando i contatti sincronizzati) nelle impostazioni di Privacy e sicurezza.\n\nMa se in genere non sei d\'accordo con le modeste esigenze di Telegram, non sarà possibile per noi fornire questo servizio. Puoi eliminare il tuo account ora - o guardarti intorno ancora e cancellarlo più tardi se ritieni di non essere soddisfatto del modo in cui usiamo i tuoi dati. Attenzione, questo cancellerà irreversibilmente il tuo account Telegram insieme a tutti i dati che archivi nel cloud di Telegram.\n\nImportante: Puoi annullare adesso ed esportare i tuoi dati prima di eliminare il tuo account invece che perdere tutto. (Per farlo, apri l\'ultima versione di Telegram Desktop e vai in Impostazioni > Esporta dati Telegram.) Per farti connettere con i tuoi amici su tutti i tuoi dispositivi, i tuoi contatti verranno sincronizzati di continuo con i server cloud fortemente criptati di Telegram. @@ -2255,6 +2359,24 @@ %1$d chat %1$d chat %1$d chat + %1$d chat + %1$d chat + %1$d chat + %1$d chat + %1$d chat + %1$d chat + %1$d chat + %1$d chat + %1$d chat + %1$d chat + %1$d chat + %1$d chat + %1$d chat + %1$d chat + %1$d chat + %1$d chat + %1$d chat + %1$d chat %1$d chat %1$d chat %1$d chat @@ -2381,6 +2503,12 @@ %1$d sticker %1$d sticker %1$d sticker + %1$d masks + %1$d mask + %1$d masks + %1$d masks + %1$d masks + %1$d masks %1$d iscritti %1$d iscritto %1$d iscritti @@ -2448,6 +2576,12 @@ %1$d foto %1$d foto %1$d foto + %1$d foto + %1$d foto + %1$d foto + %1$d foto + %1$d foto + %1$d foto %1$d file %1$d file %1$d file @@ -2526,6 +2660,88 @@ e altri %1$d e altri %1$d e altri %1$d + + Gruppo + Canale + Chat segreta + Inviato %s + Ricevuto %s + Torna indietro + Apri menù di navigazione + %2$s di %1$s + Altre opzioni + Play + Pausa + Download + Annulla download + Apri file + Opzioni messaggio + Attiva modalità di selezione + Emoji, sticker, e GIF + Allega media + Invia silenziosamente + Invia notifiche + Comandi del bot + Tastiera del bot + Mostra tastiera + Registra un messaggio vocale + Registra videomessaggio + Apri chat + Foto profilo + Cambia foto profilo + Cambia ordine + Mostra account + Nascondi account + Vai al messaggio + Annulla risposta + Annulla inoltro + Annulla modifica + Rispondendo a + Inoltrando da + Modifica + Blocca applicazione + Sblocca applicazione + Backspace + Precedente + Ripeti, spento + Ripeti, playlist + Ripeti, una + Chiudi lettore musicale + Riproduzione 2X + Arresta condivisione posizione attuale + Fotocamera istantanea + Pulsante di scatto + Cambia fotocamera + Flash, No + Flash, Auto + Flash, Sì + Set di sticker + GIF + Sticker + Espandi pannello + Chiudi pannello + Opzioni utente + Ruota + Editor foto + Aggiustamenti + Visualizzatore foto + Vai in fondo + Vai alla menzione successiva + Silenzia microfono + Titolo + Titolo + La mia posizione + Qualità video + Proporzioni + Scatta un\'altra foto + Visto + Non visto + Non riprodotto + Risultato della ricerca successivo + Risultato della ricerca precedente + Filtra per utente + Scatta una foto + Registra un video dd MMM yyyy, h:mm a dd MMM yyyy, HH:mm diff --git a/TMessagesProj/src/main/res/values-ko/strings.xml b/TMessagesProj/src/main/res/values-ko/strings.xml index ae598cc87..bd4ea41ce 100644 --- a/TMessagesProj/src/main/res/values-ko/strings.xml +++ b/TMessagesProj/src/main/res/values-ko/strings.xml @@ -144,12 +144,26 @@ 비밀 대화에 들어오셨습니다. 대화 내용 비우기 내용을 비웠습니다. + Mute + Unmute 대화방을 삭제했습니다. 그룹을 삭제했습니다. 채널을 삭제했습니다. + Archive pinned. + Swipe left on the archive to hide it. + Archive hidden. + Swipe down to see the archive. + Chat archived. + Chats archived. + Hide the archive by swiping left on it. 되돌리기 캐시에서 삭제 삭제하고 나가기 + Hide + Pin + Archive + Unarchive + Archived Chats 대화방 삭제 탈퇴한 계정 대화방 선택 @@ -176,6 +190,7 @@ %1$s, %2$s 작성 미리보기에 대한 의견 남기기 스티커 보내기 + GIF 보내기 묶음 들여다보기 맨 위에 고정 죄송합니다. %1$s까지 위쪽에 고정하실 수 있습니다. @@ -186,10 +201,16 @@ 기울임꼴 고정폭 일반 - 회원님이 모든 기기에 걸쳐 친구들과 소통하려면 **텔레그램**에게 회원님의 연락처에 접근할 권한을 부여해 주세요. 단단히 암호화된 텔레그램 서버로 회원님의 연락처가 지속적으로 동기화될 것입니다. - 나중에 + 모든 기기에 걸쳐 친구들과 소통하려면 **텔레그램**의 연락처 접근을 허용해 주세요. 단단히 암호화된 텔레그램 서버로 회원님의 연락처가 지속적으로 동기화될 것입니다. + 지금 안 함 계속 텔레그램에 있는 회원님의 연락처 + This is your Archive + Chats with enabled notifications get unarchived when new messages arrive. + Muted chats + Chats with disabled notifications stay archived when new messages arrive. + Pinned chats + You can pin an unlimited number of archived chats to the top. 관리자로 승격 관리자 권한 수정 @@ -204,7 +225,7 @@ un1 님이 회원님을 이 그룹에 초대했습니다 정말 그룹에서 나가시겠습니까? 정말 **%1$s** 그룹에서 나가시겠습니까? - 죄송합니다. 이 사용자는 그룹에 추가하실 수 없습니다. + 죄송합니다. 이 사용자를 그룹에 추가하실 수 없습니다. 죄송합니다, 그룹의 인원이 최대치입니다. 죄송합니다. 이 사용자는 스스로 그룹에서 나갔기에, 다시 초대하실 수 없습니다. 죄송합니다, 그룹에 너무 많은 관리자가 있습니다. @@ -268,7 +289,7 @@ 채널명은 숫자로 시작할 수 없습니다. 그룹명은 5자 이상이어야 합니다. 그룹명은 숫자로 시작 할 수 없습니다. - 이름 확인 중.. + 이름 확인 중... %1$s을(를) 사용하실 수 있습니다. 참가자 그룹에 추가 @@ -281,6 +302,11 @@ 예외 추가 예외 검색 추방된 사용자 + Contacts in this channel + Contacts in this group + Bots + Other members + Other subscribers 제한된 사용자 관리자 채널 삭제 @@ -295,7 +321,7 @@ 채널 사진이 바뀌었습니다 채널 사진이 제거되었습니다 채널명이 un2(으)로 바뀌었습니다 - 죄송하지만, 너무 많은 공개 사용자명을 가지셨습니다. 다른 그룹이나 채널의 링크를 하나 폐기하거나 비공개로 바꾸세요. + 죄송하지만, 공개 사용자명을 너무 많이 가지셨습니다. 다른 그룹이나 채널의 링크를 하나 폐기하거나, 비공개 그룹으로 바꾸세요. 생성자 관리자 음소거 @@ -330,13 +356,14 @@ %1$s 채널이 메시지를 게시했습니다 %1$s 채널이 사진을 게시했습니다 %1$s 채널이 동영상을 게시했습니다 - %1$s 채널이 연락처를 게시했습니다 - %1$s 님이 설문을 게시했습니다 + %1$s posted a contact %2$s + %1$s posted a poll %2$s %1$s 채널이 위치를 게시했습니다 %1$s 채널이 실시간 위치를 게시했습니다 %1$s 채널이 파일을 게시했습니다 %1$s 채널에서 GIF를 게시했습니다 %1$s 님이 %2$s을(를) 게시했습니다 + %1$s posted an album %1$s 채널에 음성 메시지를 게시했습니다 %1$s 채널이 동영상 메시지를 게시했습니다 %1$s 채널이 오디오 파일을 게시했습니다 @@ -376,7 +403,7 @@ 미디어 보내기 설문 보내기 스티커 및 GIF 보내기 - 링크 저장 + 링크 보내기 대화방 정보 수정 메시지 고정 사용자 추가 @@ -385,7 +412,7 @@ 미디어 금지 설문 금지 스티커 및 GIF 금지 - 링크 추가 금지 + 링크 보내기 금지 정보 수정 금지 고정 금지 사용자 추가 금지 @@ -398,12 +425,12 @@ 채널 관리 그룹 관리 채널 관리 - 새로운 참가자에게 이전 대화 내용을 + 새로운 참가자에게 기존 대화 내용을 보임 새로운 참가자는 들어오기 전부터 있던 메시지를 볼 수 있습니다. 숨김 새로운 참가자는 이전 메시지를 볼 수 없습니다. - 새로 온 참가자는 100개 이전의 메시지를 볼 수 없습니다. + 새로운 참가자는 100개 이전의 메시지를 볼 수 없습니다. 채널 들어가기 그룹 들어가기 그룹 종류 @@ -439,8 +466,8 @@ 설문 마감 설문을 마감할까요? 지금 설문을 마감하시면, 더 이상 다른 사람이 투표할 수 없습니다. 이 작업은 되돌릴 수 없습니다. - 설문을 버릴까요? - 정말로 설문을 버리시겠습니까? + 설문 삭제 + 정말 이 설문을 삭제하시겠습니까? 투표 취소 최종 결과 투표자 없음 @@ -503,8 +530,8 @@ un1 님이 그룹 설명을 바꿨습니다: un1 님이 채널 안내를 수정했습니다: 기존 안내 - un1 님이 새로운 참가자에게 이전 대화 내용을 보이도록 설정했습니다 - un1 님이 새로운 참가자에게 이전 대화 내용이 보이지 않도록 설정했습니다 + un1 님이 새로운 참가자에게 기존 대화 내용이 보이도록 했습니다 + un1 님이 새로운 참가자에게 기존 대화 내용이 보이지 않도록 했습니다 un1 님이 그룹 초대를 허용함 un1 님이 그룹 초대 기능을 껐습니다 un1 님이 서명 기능을 켰습니다 @@ -518,7 +545,7 @@ 메시지 고정 설문 보내기 메시지 보내기 - 링크 넣기 + 링크 보내기 메시지 읽기 %1$s 님의 권한을 수정했습니다 채널 정보 수정 @@ -658,11 +685,11 @@ 스팸 신고하고 나가기 연락처에 추가 연락처 보기 - 이 사용자가 보낸 메시지를 스팸 신고하시겠습니까? + 정말 이 사용자가 보낸 스팸을 신고하시겠습니까? 이 그룹 메시지를 스팸신고 하시겠습니까? 이 채널을 스팸 신고하시겠습니까? - 죄송합니다. 지금은 서로 연락처를 교환한 경우에만 메시지를 보내실 수 있습니다. - 죄송합니다. 서로의 연락처를 공유해야만 그룹에 초대하실 수 있습니다. + 죄송합니다. 연락처를 교환한 상대에게만 메시지를 보내실 수 있습니다. + 죄송합니다. 연락처를 교환한 상대만 그룹에 초대하실 수 있습니다. 죄송합니다. 현재 회원님은 공개 그룹에 게시하실 수 없습니다. 더 알아보기 대화방 선택 @@ -679,6 +706,14 @@ 스팸 신고 %1$s 님의 메시지 모두 삭제 최근에 사용한 이모지를 비울까요? + 스마일리와 사람 + 동물과 자연 + 음식과 음료 + 활동 + 여행과 장소 + 사물 + 특수문자 + 깃발 신고 신고가 접수되었습니다 스팸 @@ -703,11 +738,11 @@ 저장하려면 여기로 전달하세요 **그룹**을 만드셨습니다. - 그룹에는 + 그룹은 200,000명까지 참가할 수 있습니다 대화 내용이 보존됩니다 - 공개 링크를 t.me/제목 따위로 둘 수 있습니다 - 관리자를 세울 수 있습니다 + 공개 링크를 t.me/제목으로 둘 수 있습니다 + 여러 권한의 관리자를 세울 수 있습니다 여기로 메시지를 전달해 저장하세요 미디어와 파일을 보내어 저장하세요 어느 기기에서나 이 대화방에 드나드세요. @@ -719,27 +754,31 @@ 텍스트를 클립보드에 복사했습니다 꾹 눌러 음성을 녹음하세요. 짧게 눌러 녹화로 바꾸세요. 꾹 눌러 동영상을 녹화하세요. 짧게 눌러 녹음으로 바꾸세요. - 음성 메시지 버리기 - 정말로 녹음을 멈추고 음성 메시지를 버리시겠습니까? - 동영상 메시지 버리기 - 정말로 녹화를 멈추고 동영상 메시지를 버리시겠습니까? - 버리기 - 그룹 관리자가 회원님의 미디어 전송을 %1$s까지 제한했습니다. - 그룹 관리자가 회원님의 인라인 명령어 전송을 %1$s까지 제한했습니다. - 그룹 관리자가 회원님의 스티커 전송을 %1$s까지 제한합니다 - 그룹 관리자가 회원님의 메시지 작성을 %1$s까지 제한했습니다. - 그룹의 관리자가 회원님이 미디어를 보내실 수 없도록 제한했습니다. - 그룹 관리자가 회원님의 인라인 명령어 전송을 제한했습니다. - 그룹의 관리자가 회원님이 스티커를 보내시지 못하도록 제한했습니다. - 그룹의 관리자가 회원님이 메시지를 적으실 수 없도록 제한했습니다. + 음성 메시지 삭제 + 정말 녹음을 멈추고 음성 메시지를 삭제하시겠습니까? + 동영상 메시지 삭제 + 정말 녹화를 멈추고 동영상 메시지를 삭제하시겠습니까? + 삭제 + 그룹 관리자의 제한으로 여기에 미디어를 %1$s까지 보내실 수 없습니다 + 그룹 관리자의 제한으로 여기에 인라인 명령을 %1$s까지 보내실 수 없습니다 + 그룹 관리자의 제한으로 여기에 스티커를 %1$s까지 보내실 수 없습니다 + 그룹 관리자의 제한으로 여기에 GIF를 %1$s까지 보내실 수 없습니다 + 그룹 관리자의 제한으로 메시지를 %1$s까지 작성하실 수 없습니다 + 그룹 관리자의 제한으로 여기에 미디어를 보내실 수 없습니다. + 그룹 관리자의 제한으로 여기에 인라인 콘텐츠를 보내실 수 없습니다 + 그룹 관리자의 제한으로 스티커를 보내실 수 없습니다. + 그룹 관리자의 제한으로 GIF를 보내실 수 없습니다. + 그룹 관리자의 제한으로 메시지를 작성하실 수 없습니다. 이 그룹에서는 미디어를 보내실 수 없습니다. 그룹에서 인라인 봇을 금지합니다. 그룹에서 스티커를 금지합니다. + 본 그룹에는 GIF가 허용되지 않습니다. 이 그룹에서는 메시지를 작성하실 수 없습니다. 관리자 이 앱에서는 APK 설치가 제한됩니다. 시스템 설정에서 이를 허용하실 수 있습니다. 읽지 않은 메시지 스티커 묶음 검색 + 이모지 검색 URL 지도 미리보기 제공 기관 지도 미리보기 제공 기관을 선택하세요 @@ -748,6 +787,7 @@ Yandex 미리보기 없음 Google 지도를 설치할까요? + SCAM %1$s 님이 자동 삭제 타이머를 %2$s(으)로 맞췄습니다 자동 삭제 타이머를 %1$s(으)로 맞추셨습니다 @@ -756,6 +796,7 @@ 새로운 메시지가 왔습니다 %1$s: %2$s %1$s 님이 회원님에게 %2$s을(를) 보냈습니다 + %1$s sent you an album %1$s 님이 회원님에게 %2$s을(를) 전달했습니다 %1$s님이 메시지를 보냈습니다 %1$s님이 사진을 보냈습니다 @@ -763,11 +804,12 @@ %1$s 님이 회원님에게 %2$s에 대한 인보이스를 보냈습니다 %1$s 님이 자동 삭제되는 사진을 보냈습니다 %1$s 님이 자동 삭제되는 동영상을 보냈습니다 - %1$s 님이 연락처를 공유했습니다 - %1$s 님이 설문을 보냈습니다 + %1$s shared a contact %2$s with you + %1$s sent you a poll %2$s %1$s님이 위치를 보냈습니다 %1$s 님이 실시간 위치를 보냈습니다 %1$s님이 %2$s 게임으로 초대했습니다 + %1$s scored %3$s in game %2$s %1$s님이 파일을 보냈습니다 %1$s 님이 회원님에게 GIF를 보냈습니다 %1$s님이 음성 메시지를 보냈습니다 @@ -779,11 +821,12 @@ %1$s님이 %2$s 그룹에 메시지를 보냈습니다 %1$s 님이 %2$s 그룹에 사진을 보냈습니다 %1$s님이 %2$s 그룹에 동영상을 보냈습니다 - %1$s 님이 %2$s 그룹에 설문을 보냈습니다 - %1$s님이 %2$s 그룹에 연락처를 공유했습니다 + %1$s sent a poll %3$s to the group %2$s + %1$s shared a contact %3$s in the group %2$s %1$s님이 %2$s 그룹에 위치를 보냈습니다 %1$s 님이 %2$s 그룹과 실시간 위치를 공유했습니다 %1$s 님이 %2$s 그룹에 %3$s 게임으로 초대했습니다 + %1$s scored %4$s in game %3$s in the group %2$s %1$s님이 %2$s 그룹에 파일을 보냈습니다 %1$s 님이 %2$s 그룹에 GIF를 보냈습니다 %1$s 님이 %2$s 그룹에 %3$s에 대한 인보이스를 보냈습니다 @@ -806,6 +849,7 @@ %1$s 님이 프로필 사진을 업데이트했습니다 초대 링크를 통해 %1$s 님이 %2$s 그룹에 들어왔습니다. %1$s 님이 %2$s 그룹에 %3$s을(를) 보냈습니다 + %1$s sent an album to the group %2$s %1$s 님이 %2$s 그룹에 %3$s을(를) 전달했습니다 답장 %1$s 그룹에 답장 @@ -814,16 +858,17 @@ %2$s %1$s %1$s 님이 %3$s 그룹에 \"%2$s\"을(를) 고정했습니다 %1$s 님이 %2$s 그룹에 메시지를 고정했습니다 - %1$s 님이 %2$s 그룹에 설문을 고정했습니다 + %1$s pinned a poll %3$s in the group %2$s %1$s 님이 %2$s 그룹에 사진을 고정했습니다 %1$s 님이 %2$s 그룹에 게임을 고정함 + %1$s pinned a game score in the group %2$s %1$s 님이 %2$s 그룹에 동영상을 고정했습니다 %1$s 님이 %2$s 그룹에 파일을 고정했습니다 %1$s 님이 %2$s 그룹에 스티커를 고정했습니다 %1$s 님이 %2$s 그룹에 %3$s 스티커를 고정했습니다 %1$s 님이 %2$s 그룹에 음성 메시지를 고정했습니다 %1$s 님이 %2$s 그룹에 동영상 메시지를 고정했습니다 - %1$s 님이 %2$s 그룹에 연락처를 고정했습니다 + %1$s pinned a contact %3$s in the group %2$s %1$s 님이 %2$s 그룹에 지도를 고정했습니다 %1$s 님이 %2$s 그룹에 실시간 위치를 고정했습니다 %1$s 님이 %2$s 그룹에 GIF를 고정했습니다 @@ -831,9 +876,10 @@ %1$s 님이 %2$s 그룹에 인보이스를 공지했습니다 %1$s 님이 \"%2$s\"을(를) 고정했습니다 %1$s 님이 메시지를 고정했습니다 - %1$s 님이 설문을 고정했습니다 + %1$s pinned a poll %2$s %1$s 님이 사진을 고정했습니다 %1$s 님이 게임을 고정했습니다 + %1$s pinned a game score %1$s 님이 동영상을 고정했습니다 %1$s 님이 파일을 고정했습니다 %1$s 님이 인보이스를 공지했습니다 @@ -841,7 +887,7 @@ %1$s 님이 %2$s 스티커를 고정했습니다 %1$s 님이 음성 메시지를 고정했습니다 %1$s 님이 동영상 메시지를 고정했습니다 - %1$s 님이 연락처를 고정했습니다 + %1$s pinned a contact %2$s %1$s 님이 지도를 고정했습니다 %1$s 님이 실시간 위치를 고정했습니다 %1$s 님이 GIF를 고정했습니다 @@ -886,12 +932,14 @@ 죄송합니다. 그룹이 가득 차 있습니다. 죄송하지만, 대화방이 없어진 모양입니다. 링크를 클립보드에 복사했습니다 + Link copied to clipboard.\nThis link will only work for members of this chat. + Unfortunately, you can\'t access this message. You are not a member of the chat where it was posted. 전화번호를 클립보드에 복사했습니다 이메일을 클립보드에 복사했습니다 - 링크로 그룹에 초대 + 링크로 그룹에 초대하기 초대 링크 정말 이 초대 링크를 폐기할까요? 폐기하면 누구도 이 링크로 들어올 수 없습니다. - 이전 초대 링크는 현재 비활성화됐습니다. 새 초대 링크가 만들어졌습니다. + 이전 초대 링크는 이제 비활성화되었습니다. 새 초대 링크가 만들어졌습니다. 폐기 링크 폐기 정말 **%1$s** 링크를 폐기하시겠습니까?\n\n\"**%2$s**\" 그룹은 비공개가 됩니다. @@ -908,6 +956,7 @@ 관리자 설정 그룹에서 차단 그룹 삭제하고 나가기 + 그룹 삭제 및 나가기 알림 권한 수정 그룹에서 추방 @@ -915,7 +964,7 @@ 슈퍼그룹으로 변환 슈퍼그룹으로 변환 경고 - 이 작업은 되돌릴 수 없습니다. 슈퍼그룹에서 일반 그룹으로 내리기는 불가능합니다. + 이 작업은 되돌릴 수 없습니다. 슈퍼그룹에서 일반 그룹으로는 내리실 수 없습니다. **참가자 수 제한에 다다랐습니다.**\n\n더 많은 참가자를 추가하고 추가 기능을 사용하려면, 슈퍼그룹으로 업그레이드하세요.\n\n• 슈퍼그룹은 %1$s명 까지도 수용할 수 있습니다\n• 새로운 참가자가 대화 내용 전체를 볼 수 있습니다\n• 한 사람이 메시지를 지우면 모두에게서도 사라집니다\n• 생성자가 그룹의 공개 링크를 둘 수 있습니다 **슈퍼그룹에서는**\n\n• 새로운 참가자가 대화 내용 전체를 볼 수 있습니다\n• 한 사람이 메시지를 삭제하면 모두에게서도 사라집니다\n• 생성자가 그룹에 공개 링크를 둘 수 있습니다 **주의:** 이 작업은 되돌릴 수 없습니다. @@ -923,7 +972,7 @@ 공유 추가 연락처 추가 - 아직 %1$s님이 텔레그램에 가입하시지 않았습니다. 초대하시겠습니까? + %1$s 님은 아직 텔레그램에 가입하지 않았습니다. 초대하시겠습니까? 초대 차단 연락처 수정 @@ -936,7 +985,7 @@ 직장 생일 제목 - 새 연락처 만들기 + 새 연락처 등록 기존 연락처에 추가 자기소개 본인에 대해 몇 마디 적어 보세요 @@ -979,6 +1028,8 @@ 스티커 및 마스크 스티커 추가 + ADD %1$s + REMOVE %1$s 마스크 추가 스티커에 추가 즐겨찾기에 추가 @@ -1000,7 +1051,12 @@ 삭제 스티커 없음 스티커를 찾지 못했습니다 + GIF를 찾지 못했습니다 + 이모지 없음 마스크 없음 + 이모지 추천 + **텔레그램**에서 여러분이 이모지를 손쉽게 찾으실 수 있도록 수천 개의 키워드를 지원해 드리지만, 누락된 키워드들이란 있기 마련입니다. 이모지 대치어를 새로 제안하려면 다음 사이트를 방문해 주세요: + https://translations.telegram.org/%1$s/emoji 마스크 보내고자 하는 사진에 마스크를 추가하실 수 있습니다. 사진을 보내기 전에 사진 편집기를 열어 보세요. 인기 스티커 @@ -1046,6 +1102,9 @@ 테마 저장 새로운 색 테마 색 테마 + Chat list view + Two lines + Three lines 새로운 테마 적용 테마 미리보기 @@ -1157,7 +1216,7 @@ 이미지 업로드 이미지 선택 이미지 전체 불러오는 중... - 색 설정 + 색 설정하기 메시지 엔터 키로 보내기 이벤트 @@ -1218,12 +1277,15 @@ 낮음 중간 높음 - 보통 + 맞춤 개인 그룹 사진 동영상 파일 + Photos + Videos + Files 파일과 음악 자동 다운로드 사진 자동 다운로드 동영상과 GIF 자동 다운로드 @@ -1231,8 +1293,8 @@ 최대 파일 크기 다음 트랙 미리 불러오기 오디오 파일을 듣고 계시는 동안 그다음 트랙을 다운로드합니다. - 큰 동영상 미리 불러오기 - %1$s보다 큰 동영상은 바로 재생하기 위해 처음 몇 초를 미리 불러옵니다. + 보다 큰 동영상 미리 불러오기 + %1$s보다 큰 동영상은 바로 재생할 수 있도록 처음 몇 초를 미리 불러옵니다. 모바일 데이터를 사용할 때 미디어를 자동으로 다운로드하려면 이 설정을 켜세요. 로밍했을 때 미디어를 자동으로 다운로드하려면 이 설정을 켜세요. Wi-Fi에 연결했을 때 미디어를 자동으로 다운로드하려면 이 설정을 켜세요. @@ -1250,7 +1312,8 @@ 로밍할 때 GIF 동영상 - Press the volume buttons to turn sound on. + 소리를 켜려면 음량 버튼을 누르세요. + 사용자가 계정을 숨겼습니다 미디어 자동 재생 기기 들어 말하기 갤러리에 저장 @@ -1266,8 +1329,8 @@ 긴급 사용 안 함 알림 반복 - 텔레그램 번호를 여기서 바꾸실 수 있습니다. 회원님의 계정과 메시지와 미디어, 연락처 따위의 모든 클라우드 데이터가 새 번호로 옮겨집니다.\n\n**중요:** 텔레그램 연락 상대 중에서 회원님의 옛 전화번호가 있으며 차단되지 않은 모두에게 회원님의 **새 전화번호**가 추가됩니다. - 텔레그램 연락 상대 중에서 회원님의 옛 전화번호가 있고 차단되지 않은 모두에게 회원님의 새 전화번호가 저장됩니다. + 텔레그램 번호를 여기서 바꾸실 수 있습니다. 회원님의 계정과 함께 메시지와 미디어, 연락처 따위의 모든 클라우드 데이터가 새 번호로 옮겨집니다.\n\n**중요:** 텔레그램 연락 상대 중에서 회원님의 옛 전화번호가 있으며 차단되지 않은 모두에게 회원님의 **새 전화번호**가 등록됩니다. + 텔레그램 연락 상대 중에서 회원님의 옛 전화번호가 있으며 차단되지 않은 모두에게 회원님의 새 전화번호가 등록됩니다. 번호 바꾸기 새 번호 회원님의 새 번호로 인증 코드가 담긴 SMS를 보내겠습니다. @@ -1334,10 +1397,10 @@ MTProto 프록시 사용하고 계신 프록시는 올바르게 설정되지 않았기에 비활성화될 것입니다. 다른 프록시를 사용해 주세요. 프록시 협찬 - 이 채널은 회원님의 프록시 서버로 인해 나타났습니다. 채널을 대화방 목록에서 제거하려면, 텔레그램 설정에서 프록시를 비활성화하세요. + 이 채널은 회원님의 프록시 서버로 인해 나타났습니다. 채널을 대화방 목록에서 제거하려면, 텔레그램 설정에서 프록시 사용을 해제하세요. SOCKS5 프록시 설정입니다. MTProto 프록시 설정입니다. - 이 프록시를 사용하시면 대화방 목록에 협찬 채널이 표시될 수 있습니다. 이는 회원님의 텔레그램 트래픽을 공개하지 않습니다. + 이 프록시를 사용하시면 후원 받은 채널이 대화방 목록에 표시될 수 있습니다. 이는 회원님의 텔레그램 트래픽을 공개하지 않습니다. 전화에 프록시 사용 프록시 서버는 통화 품질을 저하시킬 수 있습니다. 사용 @@ -1358,6 +1421,9 @@ 외관 스티커 및 마스크 맞춤 색 배합 선택 + 다음으로 알림 보내기 + 모든 계정 + 이용하고 계신 계정에만 알림을 받고 싶다면 이 설정을 끄세요. 대화방 알림 개인 대화방 그룹 @@ -1373,15 +1439,21 @@ 다른 계정 추가 다른 텔레그램 계정을 연결하여 두 계정 간 손쉽게 전환하세요. 암호 설정 - 앱을 암호로 잠그시면 다른 사람이 열 수 없습니다. + 다른 사람이 열 수 없도록 앱을 암호로 잠그세요. 캐시 비우기 기기의 저장 공간을 확보하세요. 미디어는 클라우드에 보존됩니다. 전화번호 바꾸기 - 연락처와 그룹, 메시지, 미디어를 새 번호로 이동하세요. - 지원 문의 + 연락처와 그룹, 메시지, 미디어를 새 번호로 옮기세요. + 문의하기 문제가 있으면 알려 주세요. 로그아웃은 대개 도움이 되지 않습니다. 로그아웃 로그아웃하시면 비밀 대화가 모두 사라집니다. + 설정과 자주 묻는 질문들 검색 + 최근 검색들 + 자주 묻는 질문들 + 결과 없음 + 최근 검색 없음 + 자주 묻는 질문 로컬 데이터베이스 캐시가 된 문자 메시지를 비울까요? @@ -1514,8 +1586,8 @@ 생년월일을 선택하세요 본인 사진을 삭제할까요? 서류에 회원님의 사진과 성명, 생년월일, 서류 번호, 발급 국가, 만기일이 포함되어야 합니다. - 정말 입력하신 정보를 모두 버리시겠습니까? - 버리기 + 정말 입력하신 정보를 모두 삭제하시겠습니까? + 삭제 스캔 서류 삭제 삭제 @@ -1685,7 +1757,7 @@ 선택한 위치 보내기 위치 장소 - %1$s 반경 내 정확함 + 반경 %1$s 내로 정확함 아니면 장소 선택 근처 장소를 보려면 쓸어 올리세요 실시간 위치 @@ -1856,6 +1928,18 @@ 개인 정보 및 보안 개인 정보 마지막 접속 + 프로필 사진 + 내 프로필 사진을 볼 수 있는 사람 + 회원님의 프로필 사진을 볼 수 있는 사람을 세세하게 제한하실 수 있습니다. + 이 설정은 앞선 설정보다 우선합니다. + 전달된 메시지 + 회원님 계정으로 연결합니다 + 아래 설정이 허용할 시 연결합니다 + 회원님의 계정으로 연결하지 않습니다 + 내 메시지를 전달할 때 내 계정으로 연결시킬 수 있는 사람 + 회원님이 보낸 메시지가 다른 대화방으로 전달되었을 때 회원님의 계정으로 연결되지 않습니다. + 이 설정은 앞선 설정보다 우선합니다. + 라인하르트, 새 음악도 좀 들어보시지 그래요 🎶? 단대단 통화 봇 및 웹 사이트 결제 및 배송 정보 초기화 @@ -1888,6 +1972,7 @@ 내 마지막 접속 시간을 볼 수 있는 사람 예외 추가 중요: 회원님의 마지막 접속 시간을 공유받지 않는 사람의 마지막 접속 시간은 보실 수 없습니다. 대신 최근, 일주일 이내, 한달 이내와 같이 간략하게 보일 것입니다. + 일부 개인 정보 설정을 바꾸셨습니다. 변경 사항을 적용할까요? 항상 공유 절대 공유하지 않음 이는 앞선 설정을 무시하고 작동합니다. @@ -1907,14 +1992,14 @@ 항상 거부... 위 사용자는 앞선 설정과 무관하게 회원님을 그룹과 채널에 추가하지 못합니다. 회원님을 그룹과 채널에 추가할 수 있는 사람을 정하세요. - 죄송합니다, 이 이용자는 개인 설정으로 인하여 그룹에 초대 할 수 없습니다. - 죄송합니다, 이 이용자는 개인 설정으로 인하여 채널에 초대 할 수 없습니다. + 죄송합니다. 사용자의 개인 정보 보호 설정으로 인해 이 사용자를 그룹에 추가하실 수 없습니다. + 죄송합니다. 이 사용자는 그룹의 참가자가 아니며 회원님에게 초대할 권한이 없기에 관리자에 추가하실 수 없습니다. 죄송합니다. 이 사용자들의 개인 설정으로 인해 함께 그룹을 만드실 수 없습니다. 단대단을 끄시면, 회원님의 IP 주소를 노출시키지 않도록 모든 전화가 텔레그램 서버를 통해 전달됩니다. 다만 음성 품질이 약간 저하될 수 있습니다. 동기화된 연락처 삭제 자주 이용하는 연락처 추천 "신속한 연락을 위해 검색 구역 위쪽에 자주 대화하는 사람을 내보이세요. " - 즐겨 사용하시는 인라인 봇과 자주 메시지하시는 사람들의 데이터가 삭제됩니다. + 즐겨 사용하시는 인라인 봇과 자주 메시지하시는 대화 상대들의 데이터가 삭제됩니다. 동영상 보내는 중... GIF 보내는 중... @@ -2056,10 +2141,17 @@ %1$s 님에게 게임을 공유할까요? %1$s 님에게 연락처를 보낼까요? 정말 로그아웃하시겠습니까?\n\n텔레그램은 여러 기기에서 동시에 이용하실 수 있습니다.\n\n로그아웃 시 모든 비밀 대화가 사라지는 점을 유의하시기 바랍니다. + Delete %1$s + Clear %1$s + Empty cache for %1$s + Are you sure you want to delete selected chats? + Are you sure you want to clear history in selected chats? + Delete all cached text and media from selected chats? 이 그룹에서 정말 나가시겠습니까? 정말 **%1$s** 그룹을 삭제하고 나가시겠습니까? 정말 이 대화방을 삭제하시겠습니까? 정말 **%1$s** 님과의 대화방을 삭제하시겠습니까? + 정말 **저장한 메시지**를 삭제하시겠습니까? 정말 **%1$s** 님과의 비밀 대화를 삭제하시겠습니까? 정말 **%1$s** 대화방을 삭제하시겠습니까? 정말 클라우드 임시 저장을 모두 삭제하시겠습니까? @@ -2082,9 +2174,21 @@ 정말 **%1$s** 님과의 대화 내용을 비우시겠습니까? 정말 **%1$s**의 대화 내용을 비우시겠습니까? 정말 대화 내용을 비우시겠습니까? + 정말 **저장한 메시지**를 비우시겠습니까? 이 채널에서 캐시된 텍스트와 미디어를 모두 삭제할까요? 이 그룹에 저장된 텍스트와 미디어 캐시를 모두 삭제할까요? - 정말 %1$s를 삭제하시겠습니까? + %1$s 삭제 + 메시지 삭제 + \"모든 참가자에게서 삭제를 체크하여\" %1$s을(를) 나머지 그룹 참가자들의 수신함에서도 삭제하실 수도 있습니다. + \"보낸 메시지 회수\"를 체크하여 %1$s을(를) 나머지 그룹 참가자들의 대화방에서도 삭제하실 수 있습니다. + \"보낸 메시지 회수\"를 체크하여 %1$s을(를) **%2$s** 님의 대화방에서도 삭제하실 수 있습니다. + 정말 이 메시지를 삭제하시겠습니까? + 정말 이 메시지들을 삭제하시겠습니까? + 정말 이 메시지를 모두에게서 삭제하시겠습니까? + 정말 이 메시지들을 모두에게서 삭제하시겠습니까? + 보낸 메시지 회수 + %1$s 님에게서도 삭제 + %1$s 님의 대화 내용도 비우기 %1$s 그룹에 메시지를 보낼까요? %1$s 님에게 게임을 공유할까요? %1$s 님에게 연락처를 보낼까요? @@ -2098,14 +2202,14 @@ 텔레그램이 전화를 받을 수 있도록 허용해 주셔야 회원님의 전화번호를 자동으로 확인할 수 있습니다. 텔레그램이 전화를 받을 수 있도록 허용해 주시면 전화번호가 자동으로 확인됩니다. 죄송합니다. 이 작업은 진행하실 수 없습니다. - 죄송합니다. 차단된 사용자나 봇은 그룹에 추가하실 수 없습니다. 먼저 차단을 해제하세요. + 죄송합니다. 차단된 사용자나 봇은 그룹에 추가하실 수 없습니다. 먼저 차단을 해제해 주세요. 그룹 들어가기 - 죄송합니다. 이 사용자는 그룹의 참가자가 아니며 회원님이 초대할 수 없기에 관리자로 추가하실 수 없습니다. - 죄송합니다, 이 사용자는 블랙리스트에 있으며 해제가 가능하지 않기 떄문에 관리자로 추가할 수 없습니다. + 죄송합니다. 이 사용자는 그룹의 참가자가 아니며 회원님에게 사용자를 초대할 권한이 없기에 관리자에 추가하실 수 없습니다. + 죄송합니다. 이 사용자는 블랙리스트에 있으며 회원님이 차단 해제할 수 없기에 관리자로 추가하실 수 없습니다. 죄송합니다. 그룹 관리자인 이 사용자를 강등할 권한이 없으므로 차단하실 수 없습니다. - 죄송합니다. 이 그룹의 관리자가 회원님의 스티커 전송을 제한했습니다. - 죄송합니다. 이 그룹의 관리자가 회원님이 미디어를 보내실 수 없도록 제한했습니다. - 죄송합니다. 그룹의 관리자가 회원님이 설문을 보내실 수 없도록 제한했습니다. + 죄송합니다. 그룹 관리자의 제한으로 스티커를 보내실 수 없습니다. + 죄송합니다. 그룹 관리자의 제한으로 미디어를 보내실 수 없습니다. + 죄송합니다. 그룹 관리자의 제한으로 설문을 보내실 수 없습니다. 죄송합니다. 이 그룹에서는 스티커를 보내실 수 없습니다. 죄송합니다. 이 그룹에서는 미디어를 보내실 수 없습니다. 죄송합니다. 이 그룹에서는 설문을 보내실 수 없습니다. @@ -2174,7 +2278,7 @@ 받기 거부 회원님은 현재 오프라인이십니다. 전화를 걸려면 인터넷에 연결해 주세요. - 현재 비행기 모드가 활성화 되어져 있습니다. 모드를 끄시거나 WIFI를 연결하여 전화를 시도해주세요 + 비행기 모드가 현재 켜져 있습니다. 전화를 걸려면 비행기 모드를 끄거나 Wi-Fi에 연결하세요. 오프라인 비행기 모드 설정 @@ -2255,6 +2359,24 @@ 대화방 %1$d개 대화방 %1$d개 대화방 %1$d개 + %1$d chats + %1$d chat + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chat + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chat + %1$d chats + %1$d chats + %1$d chats + %1$d chats 대화방 %1$d개 대화방 %1$d개 대화방 %1$d개 @@ -2381,6 +2503,12 @@ 스티커 %1$d개 스티커 %1$d개 스티커 %1$d개 + %1$d masks + %1$d mask + %1$d masks + %1$d masks + %1$d masks + %1$d masks 구독자 %1$d명 구독자 %1$d명 구독자 %1$d명 @@ -2448,6 +2576,12 @@ 사진 %1$d개 사진 %1$d개 사진 %1$d개 + %1$d photos + %1$d photo + %1$d photos + %1$d photos + %1$d photos + %1$d photos 파일 %1$d개 파일 %1$d개 파일 %1$d개 @@ -2514,18 +2648,100 @@ 전달할 스티커 %1$d개 전달할 스티커 %1$d개 전달할 스티커 %1$d개 - %1$d 님이 설문을 전달했습니다 - %1$d 님이 설문을 전달했습니다 - %1$d 님이 설문을 전달했습니다 - %1$d 님이 설문을 전달했습니다 - %1$d 님이 설문을 전달했습니다 - %1$d 님이 설문을 전달했습니다 + 전달할 설문 %1$d개 + 전달할 설문 %1$d개 + 전달할 설문 %1$d개 + 전달할 설문 %1$d개 + 전달할 설문 %1$d개 + 전달할 설문 %1$d개 및 %1$d 개 및 %1$d 개 및 %1$d 개 및 %1$d 개 및 %1$d 개 및 %1$d 개 + + 그룹 + 채널 + 비밀 대화 + %s 보냄 + %s 받음 + 돌아가기 + 네비게이션 메뉴 열기 + %2$s로 %1$s + 옵션 더 보기 + 재생 + 정지 + 다운로드 + 다운로드 취소 + 파일 열기 + 메시지 옵션 + 선택 모드로 들어가기 + 이모지, 스티커 및 GIF + 미디어 첨부 + 조용히 보내기 + 알림 보내기 + 봇 명령어 + 봇 키보드 + 키보드 보이기 + 음성 메시지 녹음 + 동영상 메시지 녹화 + 대화방 열기 + 프로필 사진 + 프로필 사진 바꾸기 + 정렬 바꾸기 + 계정 보이기 + 계정 숨기기 + 메시지로 + 답장 취소 + 전달 취소 + 편집 취소 + 답장 중 + 전달 중 + 편집 중 + 애플리케이션 잠금 + 애플리케이션 잠금 해제 + 뒤로가기 + 이전 + 반복, 끔 + 반복, 재생 목록 + 반복, 한 번 + 오디오 재생기 닫기 + 2배 속도로 재생 + 실시간 위치 공유 중단 + 즉석 카메라 + 셔터 + 카메라 전환 + 플래시, 끔 + 플래시, 자동 + 플래시, 켬 + 스티커 묶음 + GIF + 스티커 + 확장 패널 + 패널 모으기 + 사용자 옵션 + 회전 + 사진 편집기 + 조정 + 사진 뷰어 + 맨 밑으로 + 다음 언급으로 + 마이크 음소거 + 제목 + 표제 + 내 위치 + 동영상 품질 + 종횡비 + 사진 한 장 더 찍기 + Seen + Not seen + Not played + Next search result + Previous search result + Filter by user + 사진 촬영 + 동영상 녹화 yyyy년 MMM dd일, a h:mm yyyy년 MM dd일, HH:mm diff --git a/TMessagesProj/src/main/res/values-nl/strings.xml b/TMessagesProj/src/main/res/values-nl/strings.xml index d70ac9231..c74283840 100644 --- a/TMessagesProj/src/main/res/values-nl/strings.xml +++ b/TMessagesProj/src/main/res/values-nl/strings.xml @@ -144,12 +144,26 @@ Toegevoegd aan de geheime chat. Geschiedenis wissen Geschiedenis gewist. + Stil + Geluid aan Chat verwijderd. Groep verwijderd. Kanaal verwijderd + Archief vastgezet. + Veeg naar links om het archief te verbergen. + Archief verborgen + Veeg naar beneden voor het archief + Chat gearchiveerd + Chats gearchiveerd + Veeg naar links om het archief te verbergen ONGEDAAN MAKEN Cache opschonen Verwijder en verlaat + Verbergen + Vastzetten + Archiveren + Dearchiveren + Gearchiveerde chats Chat verwijderen Verwijderd account Kies een chat @@ -176,6 +190,7 @@ %1$s door %2$s Feedback over dit voorbeeld Sticker sturen + GIF sturen Bundel bekijken Vastzetten Je kunt maxmimaal %1$s vastzetten. @@ -190,6 +205,12 @@ NU NIET DOORGAAN Je contacten op Telegram + Dit is je archief + Chats met ingeschakelde melding worden gedearchiveerd bij nieuwe meldingen. + Stille chats + Stille chats blijven gearchiveerd bij nieuwe berichten. + Vastgezette chats + Je kunt een ongelimteerd aantal gearchiveerde chats vastzetten. Promoveren tot beheerder Beheerdersrechten aanpassen @@ -281,6 +302,11 @@ Uitzondering toevoegen Uitzonderingen zoeken Verwijderde gebruikers + Contacten in dit kanaal + Contacten in deze groep + Bots + Andere leden + Andere abonnees Beperkt Beheerders Kanaal verwijderen @@ -330,13 +356,14 @@ %1$s plaatste een bericht %1$s plaatste een foto %1$s plaatste een video - %1$s plaatste een contact - %1$s heeft een poll geplaatst + %1$s plaatste een contact %2$s + %1$s plaatste een poll %2$s %1$s plaatste een locatie %1$ plaatste een live-locatie %1$s plaatste een bestand %1$s plaatste een GIF %1$s plaatste %2$s + %1$s plaatste een album %1$s plaatste een spraakbericht %1$s plaatste een videobericht %1$s plaatste een muziekbestand @@ -679,6 +706,14 @@ Spam melden Alles verwijderen van %1$s Recente emoji\'s wissen? + Smiley\'s en mensen + Dieren en natuur + Eten en drinken + Activiteit + Reizen en plekken + Dingen + Symbolen + Vlaggen Melden Melding verzonden Spam @@ -727,19 +762,23 @@ Je bent beperkt in het sturen van media door de groepsbeheerders tot %1$s Je bent beperkt in het sturen van inline-content door de groepsbeheerders tot %1$s Je bent beperkt in het sturen van stickers door de groepsbeheerders tot %1$s + De beheerders van deze groep hebben je beperkt in het sturen van GIF\'s tot %1$s Je bent beperkt in het plaatsen van berichten door de groepsbeheerders tot%1$s Je bent beperkt in het sturen van media door de groepsbeheerders. Je bent beperkt in het sturen van inline-content door de groepsbeheerders. Je bent beperkt in het sturen van stickers door de groepsbeheerders. + De beheerders van deze groep hebben je beperkt in het sturen van GIF\'s Je bent beperkt in het plaatsen van berichten door de groepsbeheerders. Media sturen is niet toegestaan in deze groep. Inline-bots zijn niet toegestaan in deze groep. Stickers zijn niet toegestaan in deze groep. + GIF\'s zijn niet toegestaan in deze groep Berichten schrijven is niet toegestaan in deze groep. beheerder APK-installatie is beperkt voor deze app. Je kunt dit inschakelen via de systeeminstellingen. Ongelezen berichten Zoek stickerbundels + Emoji zoeken URL Kaartvoorvertoning Kies kaartvoorvertoning @@ -748,6 +787,7 @@ Yandex Geen Google Maps installeren? + OPLICHTING %1$s heeft de zelfvernietigingstimer ingesteld op %2$s Je hebt de zelfvernietigingstimer ingesteld op %1$s @@ -756,6 +796,7 @@ Je hebt een nieuw bericht %1$s: %2$s %1$s heeft je %2$s gestuurd + %1$s stuurde je een album %1$s heeft %2$s naar je doorgestuurd %1$s heeft je een bericht gestuurd %1$s heeft je een foto gestuurd @@ -763,11 +804,12 @@ %1$s heeft je een factuur voor %2$s gestuurd %1$s heeft je een zelfvernietigende foto gestuurd %1$s heeft je een zelfvernietigende video gestuurd - %1$s heeft een contact met je gedeeld - %1$s heeft je een poll gestuurd + %1$s deelde een contact %2$s met je + %1$s stuurde je een poll %2$s %1$s heeft je een locatie gestuurd %1$s deelt een live-locatie met je %1$s wil %2$s met je spelen + %1$s behaalde %3$s punten met het spel %2$s %1$s heeft je een bestand gestuurd %1$s heeft je een GIF gestuurd %1$s heeft je een spraakbericht gestuurd @@ -779,11 +821,12 @@ %1$s heeft een bericht gestuurd naar de groep %2$s %1$s heeft een foto gestuurd naar de groep %2$s %1$s heeft een video gestuurd naar de groep %2$s - %1$s heeft een poll gestuurd naar de groep %2$s - %1$s heeft een contact gedeeld met de groep %2$s + %1$s stuurde een poll %3$s naar de groep %2$s + %1$s deelde een contact %3$s in de groep %2$s %1$s heeft een locatie gestuurd naar de groep %2$s %1$s deelt een live-locatie met groep %2$s %1$s wil %3$s met de groep %2$s spelen + %1$s behaalde %4$s punten met het spel %3$s in de groep %2$s %1$s heeft een bestand gestuurd naar de groep %2$s %1$s heeft een GIF gestuurd naar de groep %2$s %1$s heeft een factuur naar de groep %2$s voor %3$s gestuurd @@ -806,6 +849,7 @@ %1$s heeft zijn/haar profielfoto gewijzigd %1$s is nu lid van de groep %2$s via uitnodigingslink %1$s heeft %3$s naar de groep %2$s gestuurd + %1$s heeft een album naar de groep %2$s gestuurd %1$s heeft %3$s naar de groep %2$s doorgestuurd Antwoord Antwoord op %1$s @@ -814,16 +858,17 @@ %1$s %2$s %1$s heeft \"%2$s\" vastgezet in de groep %3$s %1$s heeft bericht vastgezet in de groep %2$s - %1$s heeft poll vastgezet in de groep %2$s + %1$s heeft een poll %3$s vastgezet in de groep %2$s %1$s heeft foto vastgezet in de groep %2$s %1$s heeft een spel in de groep %2$s vastgezet + %1$s heeft een score vastgezet in de groep %2$s %1$s heeft video vastgezet in de groep %2$s %1$s heeft bestand vastgezet in de groep %2$s %1$s heeft sticker vastgezet in de groep %2$s %1$s heeft een %3$s sticker vastgezet in de groep %2$s %1$s heeft spraakbericht vastgezet in de groep %2$s %1$s heeft videobericht vastgezet in de groep %2$s - %1$s heeft contact vastgezet in de groep %2$s + %1$s heeft een contact %3$s vastgezet in de groep %2$s %1$s heeft locatie vastgezet in de groep %2$s %1$s heeft live-locatie vastgezet in de groep %2$s %1$s heeft GIF vastgezet in de groep %2$s @@ -831,9 +876,10 @@ %1$s heeft een factuur in de groep %2$s vastgezet %1$s heeft \"%2$s\" vastgezet %1$s heeft bericht vastgezet - %1$s heeft een poll vastgezet + %1$s heeft een poll vastgezet %2$s %1$s heeft foto vastgezet %1$s heeft een spel vastgezet + %1$s heeft een score vastgezet %1$s heeft video vastgezet %1$s heeft bestand vastgezet %1$s heeft een factuur vastgezet @@ -841,7 +887,7 @@ %1$s heeft een %2$s sticker vastgezet %1$s heeft spraakbericht vastgezet %1$s heeft videobericht vastgezet - %1$s heeft contact vastgezet + %1$s heeft een contact vastgezet %2$s %1$s heeft locatie vastgezet %1$s heeft een live-locatie vastgezet %1$s heeft GIF vastgezet @@ -886,6 +932,8 @@ Sorry, deze groep is al vol. Sorry, deze groep bestaat niet. Link gekopieerd naar klembord. + Link gekopiëerd naar klembord.\nDeze link werkt alleen voor leden van deze chat. + Je kunt dit bericht niet openen omdat je geen lid bent van de chat waar dit bericht is geplaatst. Nummer gekopieerd naar klembord E-mail gekopieerd naar klembord Uitnodigingslink sturen @@ -908,6 +956,7 @@ Beheerders instellen LID BEPERKEN Groep verwijderen en verlaten + Verwijder en verlaat groep Meldingen Rechten aanpassen Verwijderen uit groep @@ -979,6 +1028,8 @@ Stickers en Maskers Stickers toevoegen + VOEG %1$s TOE + VERWIJDER %1$s Maskers toevoegen Toevoegen aan stickers Toevoegen aan favorieten @@ -1000,7 +1051,12 @@ Verwijder Nog geen stickers Geen stickers gevonden + Geen GIF\'s gevonden + Geen Emoji gevonden Nog geen maskers + Emojisuggesties + **Telegram** maakt het mogelijk om emoji te vinden op basis van duizenden woorden, maar er zullen er altijd wat missen. Als je suggesties wilt doen om emoji\'s nog makkelijker te vinden kan dat via:\n + https://translations.telegram.org/%1$s/emoji Maskers Je kunt maskers toevoegen aan foto\'s , gebruik de fotobewerkingsoptie en verstuur ze. Populaire stickers @@ -1046,6 +1102,9 @@ THEME OPSLAAN Nieuw kleurenthema Kleurenthema + Weergave chatoverzicht + Twee regels + Drie regels THEMA MAKEN TOEPASSEN Thema-voorbeeld @@ -1056,7 +1115,7 @@ Meldingen gereset Alle meldingsinstellingen herstellen naar de standaardwaarden? - Berichttekstgrootte + Tekstgrootte berichten Een vraag stellen Animaties Chatinstellingen @@ -1224,6 +1283,9 @@ Foto\'s Video\'s Bestanden + Foto\'s + Video\'s + Bestanden Autom bestanden en muziek downloaden Autom. Foto\'s downloaden Autom. video\'s en GIF\'s downloaden @@ -1250,7 +1312,8 @@ Bij roaming GIF\'s Video\'s - Press the volume buttons to turn sound on. + Gebruik de volumeknoppen voor geluid. + Account verborgen door gebruiker Autom. media afspelen Houd bij oor Opslaan in galerij @@ -1358,6 +1421,9 @@ Uiterlijk Stickers and Maskers Kies aangepast kleurenthema + Meldingen weergeven van + Alle accounts + Uitschakelen als je alleen meldingen wilt ontvangen voor je actieve account. Berichtmeldingen voor chats Privéchats Groepen @@ -1382,6 +1448,12 @@ Vertel ons over eventuele problemen; uitloggen helpt meestal niet. Uitloggen Uitloggen deactiveert al je geheime chats. + Instellingen en veelgestelde vragen zoeken + Recente zoekopdrachten + Veelgestelde vragen + Geen resultaten + Geen recente zoekopdrachten + Veelgestelde vragen Lokale database Gecachet tekstberichten wissen? @@ -1856,6 +1928,18 @@ Privacy en veiligheid Privacy Laatst gezien + Profielfoto + Wie kan mijn profielfoto zien + Je kunt nauwkeurig beperken wie je profielfoto kan zien. + Deze instelling overschrijft de bovenstaande. + Doorgestuurde berichten + Link naar je account + Link indien hieronder toegestaan + Geen link naar je account + Wie voegt een link naar mijn account toe bij het doorsturen van mijn berichten + Berichten van je die worden doorgestuurd linken niet terug naar je account. + Deze instelling overschrijft de bovenstaande. + Godfried, verveel je je? Peer-to-Peer in oproepen Bots en websites Betaal- en verzendinfo wissen @@ -1888,6 +1972,7 @@ Wie kan mijn laatst gezien tijd zien? Uitzonderingen toevoegen Let op: van mensen waarmee je je laatst gezien tijd niet deelt is deze voor jou ook niet zichtbaar. In plaats daarvan krijg je tijden bij benadering te zien (recent, afgelopen week, afgelopen maand). + Je hebt privacyinstellingen aangepast. Wijzigingen toepassen? Altijd delen met Nooit delen met Deze instelling overschrijft de bovenstaande. @@ -2056,10 +2141,17 @@ Spel delen met %1$s? Contact delen met %1$s? Weet je zeker dat je wilt uitloggen?\n\nTelegram kun je naadloos op al je apparaten tegelijkertijd gebruiken.\n\nLet op! Als je uitlogt worden al je geheime chats verwijderd. + Verwijder %1$s + Wis %1$s + Lege cache voor %1$s + Geselecteerde chats echt verwijderen? + Geschiedenis van geselecteerde chats echt wissen? + Alle gecachete tekst en media van de geselecteerde chats verwijderen? Verwijderen en de groep verlaten? Groep **%1$s** echt verwijderen en verlaten? Chat echt verwijderen? Chat met **%1$s** echt wissen? + " **Bewaarde berichten** echt verwijderen?" Geheime chat met **%1$s** echt wissen? Chat **%1$s** echt wissen? Echt alle Cloud-conceptberichten wissen? @@ -2082,9 +2174,21 @@ Geheime chatgeschiedenis met **%1$s** echt wissen? Chatgeschiedenis in **%1$s** echt wissen? "Geschiedenis echt wissen? " + **Bewaarde berichten** echt wissen? Kanaalcache opschonen? Gecachet tekst en media van deze groep wissen? - %1$s echt verwijderen? + Verwijder %1$s + Bericht verwijderen + Je kunt deze %1$s ook verwijderen bij alle groepsleden via de optie “verwijder voor iedereen”. + Je kunt ook het %1$s dat je hebt gestuurd verwijderen bij de andere groepsleden via de \"Bericht intrekken\"-functie. + Je kunt ook het %1$s dat je hebt gestuurd verwijderen bij **%2$s**\' via de \"Bericht intrekken\"-functie. + Bericht echt verwijderen? + Berichten echt verwijderen? + Bericht echt voor iedereen wissen? + Berichten echt voor iedereen wissen? + Mijn berichten intrekken + Ook verwijderen voor %1$s + Geschiedenis ook voor %1$s wissen Berichten naar %1$s versturen? Spel delen met %1$s? Contact delen met %1$s? @@ -2255,6 +2359,24 @@ %1$d chats %1$d chats %1$d chats + %1$d chats + %1$d chat + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chat + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chat + %1$d chats + %1$d chats + %1$d chats + %1$d chats %1$d chats %1$d chat %1$d chats @@ -2381,6 +2503,12 @@ %1$d stickers %1$d stickers %1$d stickers + %1$d masks + %1$d mask + %1$d masks + %1$d masks + %1$d masks + %1$d masks %1$d abonnees %1$d abonnee %1$d abonnees @@ -2448,6 +2576,12 @@ %1$d foto\'s %1$d foto\'s %1$d foto\'s + %1$d foto\'s + %1$d foto + %1$d foto\'s + %1$d foto\'s + %1$d foto\'s + %1$d foto\'s %1$d bestanden %1$d bestand %1$d bestanden @@ -2526,6 +2660,88 @@ en %1$d anderen en %1$d anderen en %1$d anderen + + Groep + Kanaal + Geheime chat + Gestuurd %s + Ontvangen %s + Ga terug + Navigatiemenu openen + %2$s door %1$s + Meer opties + Afspelen + Pauzeren + Download + Download annuleren + Bestand openen + Berichtopties + Selectiemodus starten + Emoji, stickers, en GIF\'s + Media toevoegen + Stil versturen + Meldingen aan + Botcommando\'s + Botkeyboard + Keyboard weergeven + Spraakbericht opnemen + Videobericht opnemen + Chat openen + Profielfoto + Profielfoto wijzigen + Sortering wijzigen + Accounts weergeven + Accounts verbergen + Naar bericht gaan + Antwoord annuleren + Doorsturen annuleren + Bewerken annuleren + Antwoord aan + Doorsturen van + Bewerken + Applicatie vergrendelen + Applicatie ontgrendelen + Backspace + Vorige + Herhalen, uit + Afspeellijst, herhalen + Herhalen, één keer + Audiospeler sluiten + 2X zo snel + Delen van live-locatie stoppen + Instantcamera + Sluiter + Camera wisselen + Flits, uit + Flits, automatisch + Flits, aan + Stickerbundel + GIF\'s + Stickers + Paneel uitklappen + Paneel inklappen + Gebruikersopties + Draaien + Fotobewerker + Aanpassingen + Fotoviewer + Naar onderen gaan + Naar volgende vermelding + Microfoon dempen + Titel + Titel + Mijn locatie + Videokwaliteit + Beelverhouding + Nog een foto nemen + Gezien + Niet gezien + Niet afgespeeld + Volgende zoekresultaat + Vorig zoekresultaat + Filter op gebruiker + Neem een foto + Video opnemen dd MMM yyyy, h:mm a dd MMM yyyy, 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 cf93c145b..cdafe2a7a 100644 --- a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml +++ b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml @@ -9,10 +9,10 @@ Continuar em Português Seu Número - Confirme o código de seu país e preencha seu número de telefone. + Por favor, confirme o código de seu país e digite seu número de telefone. Escolha um país Código do país inválido - Essa conta já está logada neste aplicativo. + Esta conta já está conectada a partir deste aplicativo. Alternar Sincronizar Contatos Isso removerá os seus contatos dos servidores do Telegram. Se \"Contatos Sincronizados\" estiver ativa, os contatos serão sincronizados novamente. @@ -23,8 +23,8 @@ Contatos deste dispositivo foram adicionados à sua conta. Verificar Número - Enviamos um SMS com um código de ativação para **%1$s**. - Nós enviamos o código para o aplicativo do **Telegram** em seu outro dispositivo. + Nós te enviamos um SMS com um código de ativação para **%1$s**. + Nós enviamos o código para o app do **Telegram** em seu outro dispositivo. Confira suas mensagens no Telegram Inserir código Estamos ligando para o seu telefone **%1$s**.\n\nNão atenda, o Telegram processará tudo automaticamente. @@ -144,12 +144,26 @@ Você entrou no chat secreto Limpar histórico Histórico limpo. + Silenciar + Ativar Som Chat apagado. Grupo apagado. Canal apagado. + Arquivo fixado. + Deslize o arquivo para a esquerda para ocultá-lo. + Arquivo ocultado. + Deslize para baixo para ver o arquivo. + Chat arquivado. + Chats arquivados. + Oculte o arquivo ao arrastá-lo para a esquerda. DESFAZER Apagar do cache Apagar e sair + Ocultar + Fixar + Arquivar + Desarquivar + Chats Arquivados Apagar conversa Conta Excluída Selecione um Chat @@ -168,7 +182,7 @@ HASHTAGS Recente Pessoas - Apagar %1$s das sugestões? + Remover %1$s das sugestões? Prévia do link Rascunho O histórico foi apagado @@ -176,6 +190,7 @@ %1$s por %2$s Deixar um comentário sobre essa prévia Enviar Sticker + Enviar GIF Ver Pacote Fixar no topo Desculpe, você não pode fixar mais que %1$s no topo. @@ -190,6 +205,12 @@ AGORA NÃO CONTINUAR Seus contatos no Telegram + Este é o seu Arquivo + Os chats com notificações ativadas são desarquivados quando novas notificações chegam. + Chats silenciados + Os chats silenciados ficam arquivados quando novas mensagens chegam. + Chats fixados + Você pode fixar uma quantidade ilimitada de chats arquivados no topo. Promover a administrador Editar permissões de admin @@ -281,6 +302,11 @@ Adicionar Exceção Buscar Exceções Usuários removidos + Contatos neste canal + Contatos no grupo + Bots + Outros membros + Outros inscritos Usuários restringidos Administradores Apagar Canal @@ -311,7 +337,7 @@ Qualquer pessoa que tenha o Telegram instalado poderá participar do seu canal seguindo esse link. Você pode adicionar administradores para ajudar você a gerenciar seu canal. Aperte e segure para removê-los. Você deseja entrar no canal \'%1$s\'? - Desculpe, esta conversa não pode mais ser acessada. + Desculpe, este chat não está mais acessível. Infelizmente você foi banido de participar de grupos públicos. Desculpe, este chat não está mais acessível. Adicionar %1$s ao canal? @@ -330,13 +356,14 @@ %1$s postou uma mensagem %1$s postou uma foto %1$s postou um vídeo - %1$s postou um contato - %1$s postou uma enquete + %1$s postou um contato %2$s + %1$s postou uma enquete %2$s %1$s postou uma foto %1$@ postou uma localização em tempo real %1$s postou um arquivo %1$s postou um GIF %1$s postou %2$s + %1$s postou um álbum %1$s postou uma mensagem de voz %1$s postou uma mensagem de vídeo %1$s postou uma música @@ -348,7 +375,7 @@ Os membros serão notificados quando você postar Os inscritos receberão uma notificação silenciosa Assinar Mensagens - Adicionar nomes dos administradores nas mensagens postadas. + Adiciona o nome dos admins às mensagens postadas. Permissões de Admin O que esse admin pode fazer? Alterar Info do Canal @@ -507,8 +534,8 @@ un1 tornou o histórico do grupo escondido para novos membros un1 ativou o convite ao grupo un1 desativou o convite ao grupo - un1 ativou assinaturas - un1 desativou assinaturas + un1 ativou as assinaturas + un1 desativou as assinaturas alterou as permissões de %1$s\n\nDuração: %2$s alterou as permissões padrão Enviar Stickers & GIFs @@ -622,7 +649,7 @@ Mensagem Compartilhar meu contato Adicionar aos contatos - %s convidou você para um chat secreto + %s te convidou para um chat secreto. Você convidou %s para um chat secreto. Chats Secretos: Criptografia de ponta a ponta @@ -657,7 +684,7 @@ DENUNCIAR SPAM DENUNCIAR SPAM E SAIR ADICIONAR CONTATO - Visualizar Contato + VER CONTATO Você tem certeza de que deseja denunciar este usuário por spam? Você tem certeza de que deseja denunciar este grupo por spam? Você tem certeza de que deseja denunciar este canal por spam? @@ -679,6 +706,14 @@ Denunciar spam Apagar tudo de %1$s Limpar emojis recentes? + Carinhas e pessoas + Animais e natureza + Comidas e bebidas + Atividades + Viagem e lugares + Objetos + Símbolos + Bandeiras Denunciar Denúncia enviada. Spam @@ -727,19 +762,23 @@ Os admins do grupo restringiram você de enviar mídias aqui até %1$s Os admins do grupo restringiram você de usar conteúdo inline aqui até %1$s. Os admins do grupo restringiram você de enviar stickers aqui até %1$s + Os admins deste grupo restringiram você de enviar GIFs até %1$s. Os admins do grupo restringiram você de escrever aqui até %1$s Os admins do grupo restringiram você de enviar mídias aqui. Os admins do grupo restringiram você de usar conteúdo inline aqui. Os admins do grupo restringiram você de enviar stickers aqui. + Os admins deste grupo restringiram você de enviar GIFs. Os admins do grupo restringiram você de escrever aqui. Não é permitido enviar mídias neste grupo. Não é permitido enviar conteúdo inline neste grupo. Não é permitido enviar stickers neste grupo. + GIFs não são permitidos neste grupo. Não é permitido enviar mensagens neste grupo. admin A instalação de APKs está restrita nesse aplicativo. Você pode ativar nas configurações de sistema. Mensagens não lidas Buscar pacotes de sticker + Pesquisar emoji URL Provedor de Prévia de Mapas Escolha o Provedor de Prévia de Mapas @@ -748,6 +787,7 @@ Yandex Sem prévias Instalar Google Maps? + GOLPE "%1$s alterou o timer de autodestruição para %2$s " Você alterou o timer de autodestruição para %1$s @@ -756,6 +796,7 @@ Você tem uma nova mensagem %1$s: %2$s %1$s te enviou %2$s + %1$s te enviou um álbum %1$s te encaminhou %2$s %1$s te enviou uma mensagem %1$s te enviou uma foto @@ -763,27 +804,29 @@ %1$s te enviou um recibo para %2$s %1$s te enviou uma foto autodestrutiva %1$s te enviou um video autodestrutivo - %1$s compartilhou um contato com você - %1$s te enviou uma enquete - %1$s enviou uma localização + %1$s compartilhou um contato %2$s com você + %1$s te enviou uma enquete %2$s + %1$s te enviou uma localização %1$s te enviou uma localização em tempo real %1$s te convidou para jogar %2$s - %1$s lhe enviou um arquivo + %1$s marcou %3$s no jogo %2$s + %1$s te enviou um arquivo %1$s te enviou um GIF %1$s enviou uma mensagem de voz %1$s enviou uma mensagem de vídeo %1$s enviou um arquivo de áudio - %1$s lhe enviou um sticker - %1$s lhe enviou um %2$s sticker + %1$s te enviou um sticker + %1$s te enviou um %2$s sticker %1$s @ %2$s: %3$s %1$s enviou uma mensagem para o grupo %2$s %1$s enviou uma foto para o grupo %2$s %1$s enviou um vídeo para o grupo %2$s - %1$s enviou uma enquete ao grupo %2$s - %1$s compartilhou um contato para o grupo %2$s + %1$s enviou uma enquete %3$s no grupo %2$s + %1$s compartilhou um contato %3$s no grupo %2$s %1$s enviou uma localização para o grupo %2$s %1$s compartilhou a localização em tempo real com o grupo %2$s %1$s convidou o grupo %2$s para jogar %3$s + %1$s marcou %4$s no jogo %3$s no grupo %2$s %1$s enviou um arquivo para o grupo %2$s %1$s enviou um GIF para o grupo %2$s %1$s enviou um recibo ao grupo %2$s por %3$s @@ -792,7 +835,7 @@ %1$s enviou um arquivo de áudio ao grupo %2$s %1$s enviou um sticker ao grupo %2$s %1$s enviou um %3$s sticker ao grupo %2$s - %1$s convidou você para o grupo %2$s + %1$s te convidou para o grupo %2$s %1$s renomeou o grupo %2$s %1$s alterou a foto do grupo para %2$s %1$s convidou %3$s para o grupo %2$s @@ -806,6 +849,7 @@ %1$s atualizou a foto do perfil %1$s entrou para o grupo %2$s via link de convite %1$s enviou %3$s ao grupo %2$s + %1$s enviou um álbum para o grupo %2$s %1$s encaminhou %3$s ao grupo %2$s Responder Responder para %1$s @@ -814,16 +858,17 @@ %1$s %2$s %1$s fixou \"%2$s\" no grupo %3$s %1$s fixou uma mensagem no grupo %2$s - %1$s fixou uma enquete no grupo %2$s + %1$s fixou uma enquete %3$s no grupo %2$s %1$s fixou uma foto no grupo %2$s %1$s fixou um jogo no grupo %2$s + %1$s fixou um placar de jogo no grupo %2$s %1$s fixou um vídeo no grupo %2$s %1$s fixou um arquivo no grupo %2$s %1$s fixou um sticker no grupo %2$s %1$s fixou um %3$s sticker no grupo %2$s %1$s fixou uma mensagem de voz no grupo %2$s %1$s fixou uma mensagem de vídeo no grupo %2$s - %1$s fixou um contato no grupo %2$s + %1$s fixou um contato %3$s no grupo %2$s %1$s fixou um mapa no grupo %2$s %1$s fixou uma localização em tempo real no grupo %2$s %1$s fixou um GIF no grupo %2$s @@ -831,9 +876,10 @@ %1$s fixou um recibo no grupo %2$s %1$s fixou \"%2$s\" %1$s fixou uma mensagem - %1$s fixou uma enquete + %1$s fixou uma enquete %2$s %1$s fixou uma foto %1$s fixou um jogo + %1$s fixou um placar de jogo %1$s fixou um vídeo %1$s fixou um arquivo %1$s fixou um recibo @@ -841,7 +887,7 @@ %1$s fixou um %2$s sticker %1$s fixou uma mensagem de voz %1$s fixou uma mensagem de vídeo - %1$s fixou um contato + %1$s fixou um contato %2$s %1$s fixou um mapa %1$s fixou uma localização em tempo real %1$s fixou um GIF @@ -886,6 +932,8 @@ Desculpe, esse grupo já está lotado. Desculpe, parece que esse chat não existe. Link copiado para área de transferência + Link copiado para a área de transferência.\nEste link só funcionará para os membros deste chat. + Infelizmente, você não pode acessar essa mensagem. Você não é um membro do chat no qual ela foi postada. Telefone copiado para a área de transferência Email copiado para a área de transferência Convidar para o Grupo via Link @@ -908,6 +956,7 @@ Definir administradores BANIR DO GRUPO Apagar e sair do grupo + Apagar e Sair do Grupo Notificações Alterar permissões Remover do grupo @@ -970,7 +1019,7 @@ O nome de usuário deve ter pelo menos 5 caracteres. O nome de usuário não pode exceder 32 caracteres. Desculpe, o nome de usuário não pode começar com um número. - Você pode escolher um nome de usuário no **Telegram**. Assim, outras pessoas poderão te encontrar pelo nome de usuário e entrar em contato sem precisar saber seu telefone.\n\nVocê pode usar **a–z**, **0–9** e underline.\nO tamanho mínimo é de **5** caracteres. + Você pode escolher um nome de usuário no **Telegram**. Assim, outras pessoas poderão te encontrar pelo nome de usuário e entrar em contato sem precisar saber seu número de telefone.\n\nVocê pode usar **a–z**, **0–9** e underline.\nO tamanho mínimo é de **5** caracteres. Este link abre um chat com você:\n%1$s Verificando nome de usuário... %1$s está disponível. @@ -979,6 +1028,8 @@ Stickers e Máscaras Adicionar Stickers + ADD %1$s + REMOVER %1$s Adicionar Máscaras Adicionar aos Stickers Adicionar aos Favoritos @@ -1000,7 +1051,12 @@ Remover Nenhum sticker Nenhum sticker encontrado + Nenhum GIF encontrado + Nenhum emoji encontrado Nenhuma máscara + Sugestões de Emoji + O **Telegram** permite que você encontre emojis por milhares de palavras-chave, mas sempre há algo faltando. Se você quiser sugerir uma nova substituição de emoji, você pode nos ajudar visitando: + https://translations.telegram.org/%1$s/emoji Máscaras Você pode adicionar máscaras em fotos que você envia. Para isso, abra o editor de fotos antes de enviar uma foto. Stickers Populares @@ -1046,6 +1102,9 @@ SALVAR TEMA Novo tema de cores Tema de cores + Visão da Lista de Chats + Duas linhas + Três linhas CRIAR TEMA APLICAR Prévia do Tema @@ -1058,7 +1117,7 @@ Tem certeza de que deseja restaurar todas as configurações de notificação para o padrão? Tamanho do texto das mensagens Fazer uma Pergunta - Permitir Animações + Ativar Animações no App Configurações de Chats Ajuda Conta @@ -1159,7 +1218,7 @@ carregando imagem completa... Definir uma cor Mensagens - Enviar usando \'Enter\' + Enviar usando Enter Eventos Contato entrou para o Telegram Mensagens Fixadas @@ -1224,6 +1283,9 @@ Fotos Vídeos Arquivos + Fotos + Vídeos + Arquivos Download automático de arquivos e músicas Download automático de fotos Download automático de vídeos e GIFs @@ -1232,7 +1294,7 @@ Pré-carregar próxima faixa Baixa a próxima faixa enquanto você escuta um arquivo de áudio. Pré-carregar vídeos grandes - Baixa os primeiros segundos (1-2 MB) de vídeos mais pesados do que %1$s para reprodução instantânea. + Baixa os primeiros segundos (1-2 MB) de vídeos maiores que %1$s para reprodução instantânea. Ative esta opção se você quiser que mídias sejam baixadas automaticamente ao usar os dados móveis. Ative esta opção se você quiser que mídias sejam baixadas automaticamente quando em roaming. Ative esta opção se você quiser que mídias sejam baixadas automaticamente ao usar a conexão Wi-Fi. @@ -1250,7 +1312,8 @@ Quando em roaming GIFs Vídeos - Press the volume buttons to turn sound on. + "Use os botões de volume para ativar o som. " + A conta foi oculta pelo usuário Reproduzir automaticamente Levantar para Falar Salvar na Galeria @@ -1346,7 +1409,7 @@ Remover mídias após Nunca remover Contatos - Conversas Privadas + Chats Privados Conversas em Grupo Canais Limitar por Tamanho @@ -1358,6 +1421,9 @@ Aparência Stickers e Máscaras Escolha esquemas de cores personalizados. + Mostrar notificações de + Todas as Contas + Desative essa opção se quiser receber notificações apenas da sua conta ativa. Notificações de chats Chats Privados Grupos @@ -1382,6 +1448,12 @@ Conte-nos sobre quaisquer problemas; sair geralmente não ajuda. Sair Sair encerrará todos os Chats Secretos. + Buscar Configurações e FAQ + Buscas recentes + Perguntas frequentes + Nenhum resultado encontrado + Nenhuma busca recente + FAQ Banco de Dados Local Limpar todos os textos em cache? @@ -1616,25 +1688,25 @@ Senha de Bloqueio Alterar Senha - Quando você define uma senha adicional, um ícone de cadeado aparece na página de chats. Clique para bloquear e desbloquear o app.\n\nNota: se você esquecer a sua senha, terá de apagar e reinstalar o app. Todos os chats secretos serão perdidos. + Quando você define uma senha de bloqueio, o ícone de cadeado aparece na página de chats. Toque nele para bloquear e desbloquear o aplicativo.\n\nNota: se você esquecer a sua senha, terá de apagar e reinstalar o app. Todos os chats secretos serão perdidos. PIN Senha Insira sua senha atual Insira uma senha Insira sua nova senha Insira sua senha - Re-insira sua nova senha + Re-insira a sua nova senha As senhas não são iguais Bloqueio Automático - Requisitar senha se estiver ausente por muito tempo. + Solicita a senha se você ficar ausente por um tempo. em %1$s Desativado Desbloquear com Impressão Digital - Confirme a impressão digital para continuar - Toque o sensor + Por favor, confirme a sua impressão digital. + 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 do chat ficará oculto 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. 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. @@ -1700,7 +1772,7 @@ PARAR TODOS Você está compartilhando sua Localização em %1$s Escolha por quanto tempo %1$s verá sua localização precisa. - Escolha por quanto tempo as pessoas nessa conversa verão sua localização em tempo real. + Escolha por quanto tempo as pessoas nesse chat irão ver a sua localização em tempo real. Seu GPS parece estar desativado, ative-o para acessar as funções de localização. Mostrar todas as mídias @@ -1717,7 +1789,7 @@ Todos os vídeos Ainda não há fotos Por favor, baixe a mídia primeiro - Aguarde que o vídeo seja baixado completamente. + Por favor, aguarde o download completo do vídeo. Este vídeo não está otimizado para streaming. Talvez você precise baixá-lo para assistir. O app não conseguiu reproduzir o vídeo. Deseja abrir em um player externo? Nenhuma foto recente @@ -1786,7 +1858,7 @@ Por favor, adicione seu email válido. Essa é a única forma de recuperar uma senha esquecida. Pular Atenção - É sério!\n\nSe você esquecer a sua senha, você perderá o acesso a sua conta do Telegram. Não há nenhuma forma de recuperá-la. + É sério!\n\nSe você esquecer a sua senha, você perderá o acesso à sua conta do Telegram. Não há nenhuma forma de recuperá-la. Quase lá! Por favor, verifique o seu email (não esqueça da pasta spam) para completar a configuração da verificação em duas etapas. Tudo certo! @@ -1804,8 +1876,8 @@ Crie uma dica para sua senha As senhas não são iguais Cancelar a configuração - Desistir de configurar o email de recuperação - Para completar a Configuração da Verificação em Duas Etapas, verifique o seu email (verifique também a pasta de spam) e digite o código que nós acabamos de te enviar. + Desistir de config. o email de recuperação + Para completar a Configuração da Verificação em Duas Etapas, verifique o seu email (verifique também a pasta de spam) e digite o código que nós te enviamos. Para completar a configuração do email de recuperação, verifique %1$s (não se esqueça da pasta de spam) e digite o código que nós te enviamos. A dica deve ser diferente da sua senha Endereço de email inválido. Por favor, verifique se você digitou corretamente e tente de novo. @@ -1856,6 +1928,18 @@ Privacidade e Segurança Privacidade Último Acesso + Foto de Perfil + Quem pode ver minha foto de perfil? + Você pode restringir quem pode ver sua foto de perfil com precisão granular. + Essas configurações substituirão os valores 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. + Essas configurações substituirão os valores acima. + Reinhardt, precisamos encontrar músicas novas. Ponta a Ponta em Chamadas Bots e sites Limpar Dados de Pagamento e Envio @@ -1887,7 +1971,8 @@ Se você não acessar sua conta ao menos uma vez nesse período, sua conta será apagada junto com todas as suas mensagens e contatos. Quem pode ver o seu Último Acesso? Definir exceções - Importante: você não poderá ver quando foi o Último Acesso das pessoas com quem você não compartilha o seu Último Acesso. Você visualizará o Último acesso aproximado (recentemente, dentro de uma semana, dentro de um mês). + Importante: você não poderá ver quando foi o Último Acesso das pessoas com quem você não compartilha o seu Último Acesso. Em vez disso, você verá o último acesso aproximado (recentemente; há uma semana; há um mês). + Você alterou algumas configurações de privacidade. Aplicar mudanças? Sempre Mostrar Para Nunca Mostrar Para Essas configurações irão sobrepor os valores acima. @@ -1909,7 +1994,7 @@ Altera quem pode te adicionar em grupos ou canais. Desculpe, você não pode adicionar esse usuário a grupos devido às configurações de privacidade dele. Desculpe, você não pode adicionar esse usuário a canais devido às configurações de privacidade dele. - Você não pode criar um grupo com esses usuários devido as configurações de privacidade deles. + Desculpe, você não pode criar um grupo com esses usuários devido às configurações de privacidade deles. Desativar a conexão de ponta a ponta irá transmitir as chamadas através dos servidores do Telegram para evitar que seu endereço de IP seja revelado, mas poderá diminuir a qualidade do áudio. Apagar Contatos Sincronizados Sugerir Contatos Frequentes @@ -1921,7 +2006,7 @@ bot Compartilhar - Adicionar Ao Grupo + Adicionar ao grupo Configurações Ajuda tem acesso às mensagens @@ -2051,15 +2136,22 @@ Você tem certeza? Adicionar %1$s ao chat %2$s? Número de mensagens antigas para encaminhar: - Adicionar %1$s no grupo? + Adicionar %1$s ao grupo? Enviar mensagens para %1$s? Compartilhar jogo com %1$s? Enviar contato para %1$s? Você tem certeza de que desejar sair?\n\nNote que você pode usar o Telegram em todos os seus dispositivos ao mesmo tempo.\n\nLembre-se, sair apaga todos os seus Chats Secretos. + Apagar %1$s + Limpar %1$s + Limpar cache para %1$s + Tem certeza de que deseja apagar os chats selecionados? + Tem certeza de que deseja limpar o histórico dos chats selecionados? + Apagar todo os textos e mídias armazenadas em cache dos chats selecionados? Você tem certeza de que deseja apagar e sair do grupo? Tem certeza de que deseja apagar e sair do grupo **%1$s**? - Você tem certeza de que deseja apagar essa conversa? + Você tem certeza de que deseja apagar esse chat? Tem certeza de que deseja apagar o chat com **%1$s**? + Tem certeza que deseja apagar as **Mensagens Salvas**? Tem certeza de que deseja apagar o histórico do chat secreto com **%1$s**? Tem certeza de que deseja apagar o histórico do chat **%1$s**? Deseja mesmo apagar todos os seus rascunhos da nuvem? @@ -2082,9 +2174,21 @@ Tem certeza de que deseja limpar o histórico do chat secreto com **%1$s**? Tem certeza de que deseja limpar o histórico do chat em **%1$s**? Você tem certeza de que deseja limpar o histórico? + Tem certeza que deseja limpar as **Mensagens Salvas**? Apagar todos os textos e mídias em cache desse canal? Apagar todo o texto e mídia em cache desse grupo? - Você tem certeza de que deseja apagar %1$s? + Apagar %1$s + Apagar mensagem + Você também pode apagar %1$s das caixas de entrada de outros membros do grupo marcando \"Apagar para todos os membros\". + Você também pode apagar %1$s enviadas das caixas de entrada de outros membros do grupo marcando \"Apagar minhas mensagens\". + Você também pode apagar %1$s que você enviou da caixa de entrada de **%2$s** marcando \"Apagar minhas mensagens\". + Tem certeza de que deseja apagar essa mensagem? + Tem certeza de que deseja apagar essas mensagens? + 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 + Limpar também para %1$s Enviar mensagens para %1$s? Compartilhar jogo com %1$s? Enviar contato para %1$s? @@ -2101,7 +2205,7 @@ Desculpe, você bloqueou este usuário ou bot e por isso não pode adicioná-lo a grupos. Desbloqueie para prosseguir. ENTRAR NO GRUPO Desculpe, você não pode adicionar o usuário como admin porque ele não está no grupo e você não tem permissão para adicioná-lo. - Você não pode adicionar esse usuário como admin porque ele está na lista negra e você não pode desbaní-lo. + Você não pode adicionar esse usuário como admin porque ele está na lista de usuários removidos e você não pode desbaní-lo. Você não pode banir esse usuário porque ele é um admin do grupo e você não possui permissão para rebaixá-lo. Desculpe, os admins do grupo te restringiram do envio de stickers. Desculpe, os admins do grupo te restringiram do envio de mídias. @@ -2135,10 +2239,10 @@ Baseado em nuvem O aplicativo de mensagem mais **rápido** do mundo.\nÉ **gratuito** e **seguro**. O **Telegram** envia mensagens mais rápido que qualquer outro aplicativo. - O **Telegram** é grátis para sempre.\nSem anúncios. Sem taxas. + O **Telegram** será grátis para sempre.\nSem anúncios. Sem tarifas. O **Telegram** mantém suas mensagens\nseguras contra ataques de hackers. - O **Telegram** não tem limites no\ntamanho de suas mídias e conversas. - O **Telegram** te permite acessar suas mensagens\nde vários dispositivos. + O **Telegram** não tem limites no tamanho de suas mídias e chats. + O **Telegram** permite que você acesse suas mensagens\natravés de vários dispositivos. Comece a Conversar Configurações de Conta @@ -2173,7 +2277,7 @@ Apenas em roaming Atender Rejeitar - Você está offline. Conecte à internet para poder realizar chamadas. + Você está offline. Por favor, conecte-se à Internet para poder realizar chamadas. Você está com o modo avião ativado. Desative-o ou conecte-se ao Wi-Fi para realizar chamadas. Desconectado Modo Avião @@ -2249,12 +2353,30 @@ Ei, eu estou usando o Telegram para conversar – assim como %1$d dos nossos contatos. Junte-se a nós! Baixe aqui: %2$s Ei, eu estou usando o Telegram para conversar – assim como %1$d dos nossos contatos. Junte-se a nós! Baixe aqui: %2$s Ei, eu estou usando o Telegram para conversar – assim como %1$d dos nossos contatos. Junte-se a nós! Baixe aqui: %2$s - %1$d conversas - %1$d conversa - %1$d conversas - %1$d conversas - %1$d conversas - %1$d conversas + %1$d chats + %1$d chat + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chat + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chat + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chats + %1$d chat + %1$d chats + %1$d chats + %1$d chats + %1$d chats %1$d chats %1$d chat %1$d chats @@ -2381,6 +2503,12 @@ %1$d stickers %1$d stickers %1$d stickers + %1$d masks + %1$d mask + %1$d masks + %1$d masks + %1$d masks + %1$d masks %1$d inscritos %1$d inscrito %1$d inscritos @@ -2448,6 +2576,12 @@ %1$d fotos %1$d fotos %1$d fotos + %1$d fotos + %1$d foto + %1$d fotos + %1$d fotos + %1$d fotos + %1$d fotos %1$d arquivos %1$d arquivo %1$d arquivos @@ -2526,6 +2660,88 @@ e %1$d outros e %1$d outros e %1$d outros + + Grupo + Canal + Chat secreto + Enviado %s + Recebido %s + Voltar + Abrir menu de navegação + %2$s por %1$s + Mais opções + Reproduzir + Pausar + Download + Cancelar download + Abrir arquivo + Opções da mensagem + Entrar no modo de seleção + Emojis, figurinhas e GIFs + Anexar mídia + Enviar silenciosamente + Enviar notificações + Comandos do robô + Teclado do robô + Mostrar teclado + Gravar mensagem de voz + Gravar mensagem de vídeo + Abrir chat + Foto de perfil + Alterar foto do perfil + Alterar classificação + Mostrar contas + Ocultar contas + Ir para mensagem + Cancelar resposta + Cancelar encaminhamento + Cancelar edição + Respondendo para + Encaminhando de + Edição + Bloquear aplicativo + Desbloquear aplicativo + Apagar + Anterior + Repetir, desligado + Repetir, playlist + Repetir, uma + Fechar reprodutor de áudio + Velocidade de reprodução em 2X (2 vezes) + Parar de compartilhar localização em tempo real + Câmera instantânea + Obturador + Alternar câmera + Flash, Off + Flash, Auto + Flash, On + Pacote de sticker + GIFs + Stickers + Expandir painel + Colapsar painel + Opções do usuário + Girar + Editor de fotos + Ajustes + Visualizador de fotos + Ir para o final + Ir para a próxima menção + Silenciar microfone + Título + Cabeçalho + Minha localização + Qualidade do vídeo + Proporção da tela + Tirar mais uma foto + Lido + Não lido + Não reproduzido + Próximo resultado de busca + Resultado anterior de busca + Filtrar por usuário + Tirar uma foto + Gravar vídeo dd \'de\' MMM \'de\' yyyy, h:mm a dd \'de\' MMM \'de\' yyyy, HH:mm diff --git a/TMessagesProj/src/main/res/values-v21/styles.xml b/TMessagesProj/src/main/res/values-v21/styles.xml index cd2037595..9786c7c72 100644 --- a/TMessagesProj/src/main/res/values-v21/styles.xml +++ b/TMessagesProj/src/main/res/values-v21/styles.xml @@ -44,6 +44,7 @@ @style/Theme.TMessages.CalendarView #000000 @style/MyTextViewStyle + shortEdges + + + +