update to 10.8.1 (4404)

This commit is contained in:
dkaraush 2024-02-20 12:03:54 +04:00
parent 5dd649197b
commit 4a8efef9d0
219 changed files with 11556 additions and 1754 deletions

View file

@ -20,6 +20,10 @@
<permission android:name="${applicationId}.permission.MAPS_RECEIVE" android:protectionLevel="signature"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<application
android:icon="@mipmap/ic_launcher_sa"
android:roundIcon="@mipmap/ic_launcher_sa"
@ -135,6 +139,12 @@
</intent-filter>
</receiver>
<receiver
android:name="org.telegram.messenger.SMSResultService"
android:exported="false">
</receiver>
<service
tools:replace="android:enabled"
android:name="com.google.android.gms.measurement.AppMeasurementService"

View file

@ -52,6 +52,19 @@ typedef struct {
int copy_comments;
} oe_enc_opt;
typedef struct {
ogg_int32_t _packetId;
opus_int64 bytes_written;
opus_int64 pages_out;
opus_int64 total_samples;
ogg_int64_t enc_granulepos;
int size_segments;
int last_segments;
ogg_int64_t last_granulepos;
opus_int32 min_bytes;
int max_frame_bytes;
} resume_data;
static int write_uint32(Packet *p, ogg_uint32_t val) {
if (p->pos > p->maxlen - 4) {
return 0;
@ -233,6 +246,7 @@ ogg_int32_t _packetId;
OpusEncoder *_encoder = 0;
uint8_t *_packet = 0;
ogg_stream_state os;
const char *_filePath;
FILE *_fileOs = 0;
oe_enc_opt inopt;
OpusHeader header;
@ -277,6 +291,10 @@ void cleanupRecorder() {
size_segments = 0;
last_segments = 0;
last_granulepos = 0;
if (_filePath) {
free(_filePath);
_filePath = 0;
}
memset(&os, 0, sizeof(ogg_stream_state));
memset(&inopt, 0, sizeof(oe_enc_opt));
memset(&header, 0, sizeof(OpusHeader));
@ -294,7 +312,11 @@ int initRecorder(const char *path, opus_int32 sampleRate) {
LOGE("path is null");
return 0;
}
int length = strlen(path);
_filePath = (char*) malloc(length + 1);
strcpy(_filePath, path);
_fileOs = fopen(path, "w");
if (!_fileOs) {
LOGE("error cannot open file: %s", path);
@ -416,6 +438,134 @@ int initRecorder(const char *path, opus_int32 sampleRate) {
return 1;
}
void saveResumeData() {
if (_filePath == NULL) {
return;
}
const char* ext = ".resume";
char* _resumeFilePath = (char*) malloc(strlen(_filePath) + strlen(ext) + 1);
strcpy(_resumeFilePath, _filePath);
strcat(_resumeFilePath, ext);
FILE* resumeFile = fopen(_resumeFilePath, "wb");
if (!resumeFile) {
LOGE("error cannot open resume file to write: %s", _resumeFilePath);
free(_resumeFilePath);
return;
}
resume_data data;
data._packetId = _packetId;
data.bytes_written = bytes_written;
data.pages_out = pages_out;
data.total_samples = total_samples;
data.enc_granulepos = enc_granulepos;
data.size_segments = size_segments;
data.last_segments = last_segments;
data.last_granulepos = last_granulepos;
data.min_bytes = min_bytes;
data.max_frame_bytes = max_frame_bytes;
if (fwrite(&data, sizeof(resume_data), 1, resumeFile) != 1) {
LOGE("error writing resume data to file: %s", _resumeFilePath);
}
fclose(resumeFile);
free(_resumeFilePath);
}
resume_data readResumeData(const char* filePath) {
const char* ext = ".resume";
char* _resumeFilePath = (char*) malloc(strlen(filePath) + strlen(ext) + 1);
strcpy(_resumeFilePath, filePath);
strcat(_resumeFilePath, ext);
resume_data data;
FILE* resumeFile = fopen(_resumeFilePath, "rb");
if (!resumeFile) {
LOGE("error cannot open resume file to read: %s", _resumeFilePath);
memset(&data, 0, sizeof(resume_data));
return data;
}
if (fread(&data, sizeof(resume_data), 1, resumeFile) != 1) {
LOGE("error cannot read resume file: %s", _resumeFilePath);
memset(&data, 0, sizeof(resume_data));
}
fclose(resumeFile);
free(_resumeFilePath);
return data;
}
int resumeRecorder(const char *path, opus_int32 sampleRate) {
cleanupRecorder();
coding_rate = sampleRate;
rate = sampleRate;
if (!path) {
LOGE("path is null");
return 0;
}
int length = strlen(path);
_filePath = (char*) malloc(length + 1);
strcpy(_filePath, path);
resume_data resumeData = readResumeData(path);
_packetId = resumeData._packetId;
bytes_written = resumeData.bytes_written;
pages_out = resumeData.pages_out;
total_samples = resumeData.total_samples;
enc_granulepos = resumeData.enc_granulepos;
size_segments = resumeData.size_segments;
last_segments = resumeData.last_segments;
last_granulepos = resumeData.last_granulepos;
min_bytes = resumeData.min_bytes;
max_frame_bytes = resumeData.max_frame_bytes;
_fileOs = fopen(path, "a");
if (!_fileOs) {
LOGE("error cannot open resume file: %s", path);
return 0;
}
int result = OPUS_OK;
_encoder = opus_encoder_create(coding_rate, 1, OPUS_APPLICATION_VOIP, &result);
if (result != OPUS_OK) {
LOGE("Error cannot create encoder: %s", opus_strerror(result));
return 0;
}
_packet = malloc(max_frame_bytes);
result = opus_encoder_ctl(_encoder, OPUS_SET_BITRATE(bitrate));
//result = opus_encoder_ctl(_encoder, OPUS_SET_COMPLEXITY(10));
if (result != OPUS_OK) {
LOGE("Error OPUS_SET_BITRATE returned: %s", opus_strerror(result));
return 0;
}
#ifdef OPUS_SET_LSB_DEPTH
result = opus_encoder_ctl(_encoder, OPUS_SET_LSB_DEPTH(MAX(8, MIN(24, 16))));
if (result != OPUS_OK) {
LOGE("Warning OPUS_SET_LSB_DEPTH returned: %s", opus_strerror(result));
}
#endif
if (ogg_stream_init(&os, rand()) == -1) {
LOGE("Error: stream init failed");
return 0;
}
return 1;
}
int writeFrame(uint8_t *framePcmBytes, uint32_t frameByteCount) {
size_t cur_frame_size = frame_size;
_packetId++;
@ -433,7 +583,7 @@ int writeFrame(uint8_t *framePcmBytes, uint32_t frameByteCount) {
if (nb_samples != 0) {
uint8_t *paddedFrameBytes = framePcmBytes;
int freePaddedFrameBytes = 0;
if (nb_samples < cur_frame_size) {
paddedFrameBytes = malloc(cur_frame_size * 2);
freePaddedFrameBytes = 1;
@ -503,6 +653,18 @@ JNIEXPORT jint Java_org_telegram_messenger_MediaController_startRecord(JNIEnv *e
const char *pathStr = (*env)->GetStringUTFChars(env, path, 0);
int32_t result = initRecorder(pathStr, sampleRate);
if (pathStr != 0) {
(*env)->ReleaseStringUTFChars(env, path, pathStr);
}
return result;
}
JNIEXPORT jint Java_org_telegram_messenger_MediaController_resumeRecord(JNIEnv *env, jclass class, jstring path, jint sampleRate) {
const char *pathStr = (*env)->GetStringUTFChars(env, path, 0);
int32_t result = resumeRecorder(pathStr, sampleRate);
if (pathStr != 0) {
(*env)->ReleaseStringUTFChars(env, path, pathStr);
@ -516,7 +678,10 @@ JNIEXPORT jint Java_org_telegram_messenger_MediaController_writeFrame(JNIEnv *en
return writeFrame((uint8_t *) frameBytes, (uint32_t) len);
}
JNIEXPORT void Java_org_telegram_messenger_MediaController_stopRecord(JNIEnv *env, jclass class) {
JNIEXPORT void Java_org_telegram_messenger_MediaController_stopRecord(JNIEnv *env, jclass class, jboolean allowResuming) {
if (allowResuming && _filePath != NULL) {
saveResumeData();
}
cleanupRecorder();
}

View file

@ -47,6 +47,8 @@
#include "tuning_parameters.h"
#ifdef FIXED_POINT
#include "fixed/structs_FIX.h"
#include "c_utils.h"
#else
#include "float/structs_FLP.h"
#endif

View file

@ -114,7 +114,7 @@ void Connection::onReceivedData(NativeByteBuffer *buffer) {
parseLaterBuffer = buffer->hasRemaining() ? buffer : nullptr;
buffer = restOfTheData;
} else {
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) received packet size less(%u) then message size(%u)", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType, restOfTheData->position(), lastPacketLength);
// if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) received packet size less(%u) then message size(%u)", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType, restOfTheData->position(), lastPacketLength);
return;
}
}

View file

@ -655,7 +655,12 @@ void ConnectionSocket::onEvent(uint32_t events) {
while (true) {
buffer->rewind();
readCount = recv(socketFd, buffer->bytes(), READ_BUFFER_SIZE, 0);
int err = errno;
// if (LOGS_ENABLED) DEBUG_D("connection(%p) recv resulted with %d, errno=%d", this, readCount, err);
if (readCount < 0) {
if (err == EAGAIN) {
break;
}
closeSocket(1, -1);
if (LOGS_ENABLED) DEBUG_E("connection(%p) recv failed", this);
return;
@ -850,10 +855,12 @@ void ConnectionSocket::onEvent(uint32_t events) {
onReceivedData(buffer);
}
}
}
if (readCount != READ_BUFFER_SIZE) {
} else if (readCount == 0) {
break;
}
// if (readCount != READ_BUFFER_SIZE) {
// break;
// }
}
}
}

View file

@ -970,11 +970,13 @@ void ConnectionsManager::onConnectionDataReceived(Connection *connection, Native
sendMessagesToConnectionWithConfirmation(messages, connection, false);
}
} else {
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) received unparsed packet on 0x%" PRIx64, connection, instanceNum, datacenter->getDatacenterId(), connection->getConnectionType(), messageId);
if (delegate != nullptr) {
delegate->onUnparsedMessageReceived(messageId, data, connection->getConnectionType(), instanceNum);
}
}
} else {
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) received unprocessed packet on 0x%" PRIx64, connection, instanceNum, datacenter->getDatacenterId(), connection->getConnectionType(), messageId);
std::vector<std::unique_ptr<NetworkMessage>> messages;
sendMessagesToConnectionWithConfirmation(messages, connection, false);
}
@ -1052,6 +1054,9 @@ TLObject *ConnectionsManager::TLdeserialize(TLObject *request, uint32_t bytes, N
}
}
} else {
if (constructor == 0x96a18d5) {
if (LOGS_ENABLED) DEBUG_D("not found file 0x%x", constructor);
}
if (LOGS_ENABLED) DEBUG_D("not found request to parse constructor 0x%x", constructor);
}
}
@ -1621,6 +1626,7 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag
processServerResponse(object, messageId, messageSeqNo, messageSalt, connection, innerMsgId, containerMessageId);
delete object;
} else {
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) received unparsed from gzip object on %0x" PRIx64, connection, instanceNum, datacenter->getDatacenterId(), connection->getConnectionType(), messageId);
if (delegate != nullptr) {
delegate->onUnparsedMessageReceived(messageId, data, connection->getConnectionType(), instanceNum);
}
@ -1969,7 +1975,7 @@ bool ConnectionsManager::cancelRequestInternal(int32_t token, int64_t messageId,
Request *request = iter->get();
if ((token != 0 && request->requestToken == token) || (messageId != 0 && request->respondsToMessageId(messageId))) {
request->cancelled = true;
if (LOGS_ENABLED) DEBUG_D("cancelled queued rpc request %p - %s", request->rawRequest, typeid(*request->rawRequest).name());
if (LOGS_ENABLED) DEBUG_D("cancelled queued rpc request %p - %s of messageId 0x%" PRIx64, request->rawRequest, typeid(*request->rawRequest).name(), request->messageId);
requestsQueue.erase(iter);
if (removeFromClass) {
removeRequestFromGuid(token);
@ -1982,7 +1988,7 @@ bool ConnectionsManager::cancelRequestInternal(int32_t token, int64_t messageId,
Request *request = iter->get();
if ((token != 0 && request->requestToken == token) || (messageId != 0 && request->respondsToMessageId(messageId))) {
request->cancelled = true;
if (LOGS_ENABLED) DEBUG_D("cancelled waiting login rpc request %p - %s", request->rawRequest, typeid(*request->rawRequest).name());
if (LOGS_ENABLED) DEBUG_D("cancelled waiting login rpc request %p - %s", request->rawRequest, typeid(*request->rawRequest).name());
waitingLoginRequests.erase(iter);
if (removeFromClass) {
removeRequestFromGuid(token);
@ -2000,7 +2006,7 @@ bool ConnectionsManager::cancelRequestInternal(int32_t token, int64_t messageId,
sendRequest(dropAnswer, nullptr, nullptr, RequestFlagEnableUnauthorized | RequestFlagWithoutLogin | RequestFlagFailOnServerErrors | RequestFlagIsCancel, request->datacenterId, request->connectionType, true);
}
request->cancelled = true;
if (LOGS_ENABLED) DEBUG_D("cancelled running rpc request %p - %s", request->rawRequest, typeid(*request->rawRequest).name());
if (LOGS_ENABLED) DEBUG_D("cancelled running rpc request %p - %s, of messageId 0x%" PRIx64, request->rawRequest, typeid(*request->rawRequest).name(), request->messageId);
runningRequests.erase(iter);
if (removeFromClass) {
removeRequestFromGuid(token);
@ -2352,12 +2358,13 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t
forceThisRequest = false;
}
if (forceThisRequest || (abs(currentTime - request->startTime) > maxTimeout &&
(currentTime >= request->minStartTime ||
(request->failedByFloodWait != 0 && (request->minStartTime - currentTime) > request->failedByFloodWait) ||
(request->failedByFloodWait == 0 && abs(currentTime - request->minStartTime) >= 60))
)
) {
if (forceThisRequest || (
abs(currentTime - request->startTime) > maxTimeout && (
currentTime >= request->minStartTime ||
(request->failedByFloodWait != 0 && (request->minStartTime - currentTime) > request->failedByFloodWait) ||
(request->failedByFloodWait == 0 && abs(currentTime - request->minStartTime) >= 60)
)
)) {
if (!forceThisRequest && request->connectionToken > 0) {
if ((request->connectionType & ConnectionTypeGeneric || request->connectionType & ConnectionTypeTemp) && request->connectionToken == connection->getConnectionToken()) {
if (LOGS_ENABLED) DEBUG_D("request token is valid, not retrying %s (%p)", typeInfo.name(), request->rawRequest);

View file

@ -259,7 +259,6 @@ private:
friend class Config;
friend class FileLog;
friend class Handshake;
};
#ifdef ANDROID

View file

@ -37,15 +37,18 @@ import androidx.multidex.MultiDex;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import org.json.JSONObject;
import org.telegram.messenger.voip.VideoCapturerDevice;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.Adapters.DrawerLayoutAdapter;
import org.telegram.ui.Components.ForegroundDetector;
import org.telegram.ui.Components.Premium.boosts.BoostRepository;
import org.telegram.ui.IUpdateLayout;
import org.telegram.ui.LauncherIconController;
import java.io.File;
import java.util.ArrayList;
public class ApplicationLoader extends Application {
@ -595,4 +598,32 @@ public class ApplicationLoader extends Application {
return null;
}
public TLRPC.Update parseTLUpdate(int constructor) {
return null;
}
public void processUpdate(int currentAccount, TLRPC.Update update) {
}
public boolean onSuggestionFill(String suggestion, String[] output, boolean[] closeable) {
return false;
}
public boolean onSuggestionClick(String suggestion) {
return false;
}
public boolean extendDrawer(ArrayList<DrawerLayoutAdapter.Item> items) {
return false;
}
public boolean checkRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) {
return false;
}
public boolean consumePush(int account, JSONObject json) {
return false;
}
}

View file

@ -135,6 +135,14 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.billingProductDetailsUpdated);
}
private void switchBackFromInvoice() {
if (!billingClientEmpty) {
return;
}
billingClientEmpty = false;
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.billingProductDetailsUpdated);
}
public boolean isReady() {
return billingClient.isReady();
}
@ -328,28 +336,19 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien
AndroidUtilities.runOnUIThread(() -> startConnection(), delay);
}
private int triesLeft = 0;
@Override
public void onBillingSetupFinished(@NonNull BillingResult setupBillingResult) {
FileLog.d("Billing: Setup finished with result " + setupBillingResult);
if (setupBillingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
isDisconnected = false;
queryProductDetails(Collections.singletonList(PREMIUM_PRODUCT), (billingResult, list) -> {
FileLog.d("Billing: Query product details finished " + billingResult + ", " + list);
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
for (ProductDetails details : list) {
if (details.getProductId().equals(PREMIUM_PRODUCT_ID)) {
PREMIUM_PRODUCT_DETAILS = details;
}
}
if (PREMIUM_PRODUCT_DETAILS == null) {
switchToInvoice();
} else {
NotificationCenter.getGlobalInstance().postNotificationNameOnUIThread(NotificationCenter.billingProductDetailsUpdated);
}
} else {
switchToInvoice();
}
});
triesLeft = 3;
try {
queryProductDetails(Collections.singletonList(PREMIUM_PRODUCT), this::onQueriedPremiumProductDetails);
} catch (Exception e) {
FileLog.e(e);
}
queryPurchases(BillingClient.ProductType.INAPP, this::onPurchasesUpdated);
queryPurchases(BillingClient.ProductType.SUBS, this::onPurchasesUpdated);
} else {
@ -358,4 +357,39 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien
}
}
}
private void onQueriedPremiumProductDetails(BillingResult billingResult, List<ProductDetails> list) {
FileLog.d("Billing: Query product details finished " + billingResult + ", " + list);
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
for (ProductDetails details : list) {
if (details.getProductId().equals(PREMIUM_PRODUCT_ID)) {
PREMIUM_PRODUCT_DETAILS = details;
}
}
if (PREMIUM_PRODUCT_DETAILS == null) {
switchToInvoice();
} else {
switchBackFromInvoice();
NotificationCenter.getGlobalInstance().postNotificationNameOnUIThread(NotificationCenter.billingProductDetailsUpdated);
}
} else {
switchToInvoice();
triesLeft--;
if (triesLeft > 0) {
long delay;
if (triesLeft == 2) {
delay = 1000;
} else {
delay = 10000;
}
AndroidUtilities.runOnUIThread(() -> {
try {
queryProductDetails(Collections.singletonList(PREMIUM_PRODUCT), this::onQueriedPremiumProductDetails);
} catch (Exception e) {
FileLog.e(e);
}
}, delay);
}
}
}
}

View file

@ -103,6 +103,23 @@ public class ChannelBoostsController {
public boolean boostedNow;
public boolean isMaxLvl;
public CanApplyBoost copy() {
CanApplyBoost canApplyBoost = new CanApplyBoost();
canApplyBoost.canApply = canApply;
canApplyBoost.empty = empty;
canApplyBoost.replaceDialogId = replaceDialogId;
canApplyBoost.alreadyActive = alreadyActive;
canApplyBoost.needSelector = needSelector;
canApplyBoost.slot = slot;
canApplyBoost.myBoosts = myBoosts;
canApplyBoost.boostCount = boostCount;
canApplyBoost.currentPeer = currentPeer;
canApplyBoost.currentDialogId = currentDialogId;
canApplyBoost.currentChat = currentChat;
canApplyBoost.isMaxLvl = isMaxLvl;
return canApplyBoost;
}
public void setMyBoosts(TL_stories.TL_premium_myBoosts myBoosts) {
this.myBoosts = myBoosts;
boostCount = 0;

View file

@ -76,7 +76,7 @@ public class ChatMessagesMetadataController {
storyItem.dialogId = messageObject.messageOwner.media.user_id;
} else if (messageObject.messageOwner.reply_to != null) {
storyItem = messageObject.messageOwner.replyStory;
storyItem.dialogId = messageObject.messageOwner.reply_to.user_id;
storyItem.dialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.peer);
} else {
continue;
}

View file

@ -97,7 +97,31 @@ public class ChatObject {
}
public static boolean canSendAnyMedia(TLRPC.Chat currentChat) {
return canSendPhoto(currentChat) || canSendVideo(currentChat) || canSendRoundVideo(currentChat)|| canSendVoice(currentChat) || canSendDocument(currentChat) || canSendMusic(currentChat) || canSendStickers(currentChat);
return canSendPhoto(currentChat) || canSendVideo(currentChat) || canSendRoundVideo(currentChat) || canSendVoice(currentChat) || canSendDocument(currentChat) || canSendMusic(currentChat) || canSendStickers(currentChat);
}
public static boolean isIgnoredChatRestrictionsForBoosters(TLRPC.ChatFull chatFull) {
return chatFull != null && chatFull.boosts_unrestrict > 0 && (chatFull.boosts_applied - chatFull.boosts_unrestrict) >= 0;
}
public static boolean isIgnoredChatRestrictionsForBoosters(TLRPC.Chat chat) {
if (chat != null) {
TLRPC.ChatFull chatFull = MessagesController.getInstance(UserConfig.selectedAccount).getChatFull(chat.id);
return isIgnoredChatRestrictionsForBoosters(chatFull);
}
return false;
}
public static boolean isPossibleRemoveChatRestrictionsByBoosts(TLRPC.Chat chat) {
if (chat != null) {
TLRPC.ChatFull chatFull = MessagesController.getInstance(UserConfig.selectedAccount).getChatFull(chat.id);
return isPossibleRemoveChatRestrictionsByBoosts(chatFull);
}
return false;
}
public static boolean isPossibleRemoveChatRestrictionsByBoosts(TLRPC.ChatFull chatFull) {
return chatFull != null && chatFull.boosts_unrestrict > 0;
}
public static String getAllowedSendString(TLRPC.Chat chat) {
@ -1695,6 +1719,18 @@ public class ChatObject {
return isChannel(chat) && !isMegagroup(chat);
}
public static boolean isBoostSupported(TLRPC.Chat chat) {
return isChannelAndNotMegaGroup(chat) || isMegagroup(chat);
}
public static boolean isBoosted(TLRPC.ChatFull chatFull) {
return chatFull != null && chatFull.boosts_applied > 0;
}
public static boolean isGroupAndSupportBoost(TLRPC.Chat chat) {
return isMegagroup(chat);
}
public static boolean isForum(TLRPC.Chat chat) {
return chat != null && chat.forum;
}
@ -1725,49 +1761,79 @@ public class ChatObject {
}
public static boolean canSendStickers(TLRPC.Chat chat) {
if (isIgnoredChatRestrictionsForBoosters(chat)) {
return true;
}
return canUserDoAction(chat, ACTION_SEND_STICKERS);
}
public static boolean canSendEmbed(TLRPC.Chat chat) {
if (isIgnoredChatRestrictionsForBoosters(chat)) {
return true;
}
return canUserDoAction(chat, ACTION_EMBED_LINKS);
}
// public static boolean canSendMedia(TLRPC.Chat chat) {
// return canUserDoAction(chat, ACTION_SEND_MEDIA);
// }
public static boolean canSendPhoto(TLRPC.Chat chat) {
if (isIgnoredChatRestrictionsForBoosters(chat)) {
return true;
}
return canUserDoAction(chat, ACTION_SEND_PHOTO);
}
public static boolean canSendVideo(TLRPC.Chat chat) {
if (isIgnoredChatRestrictionsForBoosters(chat)) {
return true;
}
return canUserDoAction(chat, ACTION_SEND_VIDEO);
}
public static boolean canSendMusic(TLRPC.Chat chat) {
if (isIgnoredChatRestrictionsForBoosters(chat)) {
return true;
}
return canUserDoAction(chat, ACTION_SEND_MUSIC);
}
public static boolean canSendDocument(TLRPC.Chat chat) {
if (isIgnoredChatRestrictionsForBoosters(chat)) {
return true;
}
return canUserDoAction(chat, ACTION_SEND_DOCUMENTS);
}
public static boolean canSendVoice(TLRPC.Chat chat) {
if (isIgnoredChatRestrictionsForBoosters(chat)) {
return true;
}
return canUserDoAction(chat, ACTION_SEND_VOICE);
}
public static boolean canSendRoundVideo(TLRPC.Chat chat) {
if (isIgnoredChatRestrictionsForBoosters(chat)) {
return true;
}
return canUserDoAction(chat, ACTION_SEND_ROUND);
}
public static boolean canSendPolls(TLRPC.Chat chat) {
if (isIgnoredChatRestrictionsForBoosters(chat)) {
return true;
}
return canUserDoAction(chat, ACTION_SEND_POLLS);
}
public static boolean canSendMessages(TLRPC.Chat chat) {
if (isIgnoredChatRestrictionsForBoosters(chat)) {
return true;
}
return canUserDoAction(chat, ACTION_SEND);
}
public static boolean canSendPlain(TLRPC.Chat chat) {
if (isIgnoredChatRestrictionsForBoosters(chat)) {
return true;
}
return canUserDoAction(chat, ACTION_SEND_PLAIN);
}

View file

@ -252,6 +252,8 @@ public class FileLoadOperation {
private int priority;
private FilePathDatabase.FileMeta fileMetadata;
private volatile boolean writingToFilePartsStream, closeFilePartsStreamOnWriteEnd;
private boolean ungzip;
private int currentType;
@ -285,6 +287,7 @@ public class FileLoadOperation {
public FileLoadOperation(ImageLocation imageLocation, Object parent, String extension, long size) {
updateParams();
parentObject = parent;
isStory = parentObject instanceof TL_stories.TL_storyItem;
fileMetadata = FileLoader.getFileMetadataFromParent(currentAccount, parentObject);
isStream = imageLocation.imageType == FileLoader.IMAGE_TYPE_ANIMATION;
if (imageLocation.isEncrypted()) {
@ -392,6 +395,7 @@ public class FileLoadOperation {
updateParams();
try {
parentObject = parent;
isStory = parentObject instanceof TL_stories.TL_storyItem;
fileMetadata = FileLoader.getFileMetadataFromParent(currentAccount, parentObject);
if (documentLocation instanceof TLRPC.TL_documentEncrypted) {
location = new TLRPC.TL_inputEncryptedFileLocation();
@ -583,6 +587,9 @@ public class FileLoadOperation {
if (fileWriteRunnable != null) {
filesQueue.cancelRunnable(fileWriteRunnable);
}
synchronized (FileLoadOperation.this) {
writingToFilePartsStream = true;
}
filesQueue.postRunnable(fileWriteRunnable = () -> {
long time = System.currentTimeMillis();
try {
@ -608,6 +615,16 @@ public class FileLoadOperation {
}
filePartsStream.seek(0);
filePartsStream.write(filesQueueByteBuffer.buf, 0, bufferSize);
writingToFilePartsStream = false;
if (closeFilePartsStreamOnWriteEnd) {
try {
filePartsStream.getChannel().close();
} catch (Exception e) {
FileLog.e(e);
}
filePartsStream.close();
filePartsStream = null;
}
}
} catch (Exception e) {
FileLog.e(e, false);
@ -780,7 +797,6 @@ public class FileLoadOperation {
public boolean start(final FileLoadOperationStream stream, final long streamOffset, final boolean streamPriority) {
startTime = System.currentTimeMillis();
updateParams();
isStory = parentObject instanceof TL_stories.TL_storyItem;
if (currentDownloadChunkSize == 0) {
if (forceSmallChunk) {
if (BuildVars.LOGS_ENABLED) {
@ -1350,7 +1366,7 @@ public class FileLoadOperation {
}
for (int i = 0; i < 2; i++) {
int connectionType = i == 0 ? ConnectionsManager.ConnectionTypeDownload : ConnectionsManager.ConnectionTypeDownload2;
if (waitingDownloadSize[i] > 512 * 1024 * 2) {
if (waitingDownloadSize[i] > 1024 * 1024) {
int datacenterId = isCdn ? cdnDatacenterId : this.datacenterId;
ConnectionsManager.getInstance(currentAccount).discardConnection(datacenterId, connectionType);
}
@ -1402,13 +1418,17 @@ public class FileLoadOperation {
try {
if (filePartsStream != null) {
synchronized (FileLoadOperation.this) {
try {
filePartsStream.getChannel().close();
} catch (Exception e) {
FileLog.e(e);
if (!writingToFilePartsStream) {
try {
filePartsStream.getChannel().close();
} catch (Exception e) {
FileLog.e(e);
}
filePartsStream.close();
filePartsStream = null;
} else {
closeFilePartsStreamOnWriteEnd = true;
}
filePartsStream.close();
filePartsStream = null;
}
}
} catch (Exception e) {
@ -2104,6 +2124,7 @@ public class FileLoadOperation {
MessageObject messageObject = (MessageObject) parentObject;
if (messageObject.getId() < 0 && messageObject.messageOwner != null && messageObject.messageOwner.media != null && messageObject.messageOwner.media.webpage != null) {
parentObject = messageObject.messageOwner.media.webpage;
isStory = false;
}
}
if (BuildVars.LOGS_ENABLED) {

View file

@ -776,7 +776,7 @@ public class FileLoader extends BaseController {
if (priorityChanged) {
operation.getQueue().checkLoadingOperations();
}
FileLog.d("load operation update position fileName=" + finalFileName + " position in queue " + operation.getPositionInQueue() + " preloadFinish " + operation.isPreloadFinished());
FileLog.d("load operation update position fileName=" + finalFileName + " position in queue " + operation.getPositionInQueue() + " preloadFinish " + operation.isPreloadFinished() + " priority=" + operation.getPriority());
return operation;
}
@ -981,10 +981,10 @@ public class FileLoader extends BaseController {
}
loaderQueue.add(operation);
loaderQueue.checkLoadingOperations(operation.isStory && priority >= PRIORITY_HIGH);
loaderQueue.checkLoadingOperations(operation.isStory && priority >= FileLoaderPriorityQueue.PRIORITY_VALUE_MAX);
if (BuildVars.LOGS_ENABLED) {
FileLog.d("create load operation fileName=" + finalFileName + " documentName=" + getDocumentFileName(document) + " size=" + AndroidUtilities.formatFileSize(operation.totalBytesCount) + " position in queue " + operation.getPositionInQueue() + " account=" + currentAccount + " cacheType=" + cacheType);
FileLog.d("create load operation fileName=" + finalFileName + " documentName=" + getDocumentFileName(document) + " size=" + AndroidUtilities.formatFileSize(operation.totalBytesCount) + " position in queue " + operation.getPositionInQueue() + " account=" + currentAccount + " cacheType=" + cacheType + " priority=" + operation.getPriority());
}
return operation;
}
@ -1114,7 +1114,7 @@ public class FileLoader extends BaseController {
fileLoaderQueue.postRunnable(() -> {
if (queue.remove(operation)) {
loadOperationPaths.remove(operation.getFileName());
queue.checkLoadingOperations();
queue.checkLoadingOperations(operation.isStory);
}
}, delay);
}

View file

@ -109,11 +109,17 @@ public class FileLoaderPriorityQueue {
//operation will not use connections
//just skip
max++;
if (BuildVars.DEBUG_PRIVATE_VERSION)
FileLog.d("{"+name+"}.checkLoadingOperationInternal: #" + i + " "+operation.getFileName()+" priority="+operation.getPriority()+" isStory="+operation.isStory+" preFinished="+ operation.preFinished+" pauseAllNextOperations=" + pauseAllNextOperations + " max=" + max + " => skip");
continue;
} else if (!pauseAllNextOperations && i < max) {
if (BuildVars.DEBUG_PRIVATE_VERSION)
FileLog.d("{"+name+"}.checkLoadingOperationInternal: #" + i + " " +operation.getFileName()+" priority="+operation.getPriority()+" isStory="+operation.isStory+" preFinished="+ operation.preFinished+" pauseAllNextOperations=" + pauseAllNextOperations + " max=" + max + " => start");
tmpListOperations.add(operation);
activeCount++;
} else {
if (BuildVars.DEBUG_PRIVATE_VERSION)
FileLog.d("{"+name+"}.checkLoadingOperationInternal: #" + i + " " +operation.getFileName()+" priority="+operation.getPriority()+" isStory="+operation.isStory+" preFinished="+ operation.preFinished+" pauseAllNextOperations=" + pauseAllNextOperations + " max=" + max + " => pause");
if (operation.wasStarted()) {
operation.pause();
}

View file

@ -1644,6 +1644,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
svgDrawable = (SvgHelper.SvgDrawable) drawable;
svgDrawable.setParent(this);
}
if (colorFilter != null && drawable != null) {
drawable.setColorFilter(colorFilter);
}
try {
drawable.setAlpha(alpha);
if (backgroundThreadDrawHolder != null) {

View file

@ -1626,6 +1626,9 @@ public class LocaleController {
}
public static String formatSmallDateChat(long date) {
return formatSmallDateChat(date, false);
}
public static String formatSmallDateChat(long date, boolean full) {
try {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
@ -1633,7 +1636,7 @@ public class LocaleController {
date *= 1000;
calendar.setTimeInMillis(date);
if (currentYear == calendar.get(Calendar.YEAR)) {
if (!full && currentYear == calendar.get(Calendar.YEAR)) {
return getInstance().formatterDayMonth.format(date);
}
return getInstance().formatterDayMonth.format(date) + ", " + calendar.get(Calendar.YEAR);

View file

@ -54,6 +54,8 @@ import android.provider.OpenableColumns;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.Pair;
import android.util.SparseArray;
import android.view.HapticFeedbackConstants;
@ -112,9 +114,11 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
private native int startRecord(String path, int sampleRate);
private native int resumeRecord(String path, int sampleRate);
private native int writeFrame(ByteBuffer frame, int len);
private native void stopRecord();
private native void stopRecord(boolean allowResuming);
public static native int isOpusFile(String path);
@ -755,20 +759,21 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
private boolean audioRecorderPaused;
private AudioRecord audioRecorder;
private TLRPC.TL_document recordingAudio;
public TLRPC.TL_document recordingAudio;
private int recordingGuid = -1;
private int recordingCurrentAccount;
private File recordingAudioFile;
private long recordStartTime;
private long recordTimeCount;
private int writedFrame;
public long recordTimeCount;
public int writedFrame;
private long writedFileLenght;
private long recordDialogId;
private long recordTopicId;
private MessageObject recordReplyingMsg;
private MessageObject recordReplyingTopMsg;
private TL_stories.StoryItem recordReplyingStory;
private short[] recordSamples = new short[1024];
private long samplesCount;
public short[] recordSamples = new short[1024];
public long samplesCount;
private final Object sync = new Object();
@ -1944,7 +1949,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
private void raiseToSpeakUpdated(boolean raised) {
if (recordingAudio != null) {
toggleRecordingPause();
toggleRecordingPause(false);
} else if (raised) {
startRecording(raiseChat.getCurrentAccount(), raiseChat.getDialogId(), null, raiseChat.getThreadMessage(), null, raiseChat.getClassGuid(), false);
} else {
@ -3824,9 +3829,96 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
}
}
public void toggleRecordingPause() {
public void prepareResumedRecording(int currentAccount, MediaDataController.DraftVoice draft, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem replyStory, int guid, boolean manual) {
manualRecording = manual;
requestAudioFocus(true);
recordQueue.cancelRunnable(recordStartRunnable);
recordQueue.postRunnable(() -> {
if (recordingAudio == null || recordingAudioFile == null) {
setBluetoothScoOn(true);
sendAfterDone = 0;
recordingAudio = new TLRPC.TL_document();
recordingGuid = guid;
recordingAudio.dc_id = Integer.MIN_VALUE;
recordingAudio.id = draft.id;
recordingAudio.user_id = UserConfig.getInstance(currentAccount).getClientUserId();
recordingAudio.mime_type = "audio/ogg";
recordingAudio.file_reference = new byte[0];
SharedConfig.saveConfig();
recordingAudioFile = new File(draft.path) {
@Override
public boolean delete() {
if (BuildVars.LOGS_ENABLED) {
FileLog.e("delete voice file");
}
return super.delete();
}
};
FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE).mkdirs();
if (BuildVars.LOGS_ENABLED) {
FileLog.d("start recording internal " + recordingAudioFile.getPath() + " " + recordingAudioFile.exists());
}
AutoDeleteMediaTask.lockFile(recordingAudioFile);
try {
audioRecorderPaused = true;
recordTimeCount = draft.recordTimeCount;
writedFrame = draft.writedFrame;
samplesCount = draft.samplesCount;
recordSamples = draft.recordSamples;
recordDialogId = dialogId;
recordTopicId = replyToTopMsg == null ? 0 : MessageObject.getTopicId(recordingCurrentAccount, replyToTopMsg.messageOwner, false);
recordingCurrentAccount = currentAccount;
recordReplyingMsg = replyToMsg;
recordReplyingTopMsg = replyToTopMsg;
recordReplyingStory = replyStory;
} catch (Exception e) {
FileLog.e(e);
recordingAudio = null;
AutoDeleteMediaTask.unlockFile(recordingAudioFile);
recordingAudioFile.delete();
recordingAudioFile = null;
try {
audioRecorder.release();
audioRecorder = null;
} catch (Exception e2) {
FileLog.e(e2);
}
setBluetoothScoOn(false);
AndroidUtilities.runOnUIThread(() -> {
MediaDataController.getInstance(currentAccount).pushDraftVoiceMessage(dialogId, recordTopicId, null);
recordStartRunnable = null;
});
return;
}
final TLRPC.TL_document audioToSend = recordingAudio;
final File recordingAudioFileToSend = recordingAudioFile;
AndroidUtilities.runOnUIThread(() -> {
boolean fileExist = recordingAudioFileToSend.exists();
if (!fileExist && BuildVars.DEBUG_VERSION) {
FileLog.e(new RuntimeException("file not found :( recordTimeCount " + recordTimeCount + " writedFrames" + writedFrame));
}
audioToSend.date = ConnectionsManager.getInstance(recordingCurrentAccount).getCurrentTime();
audioToSend.size = (int) recordingAudioFileToSend.length();
TLRPC.TL_documentAttributeAudio attributeAudio = new TLRPC.TL_documentAttributeAudio();
attributeAudio.voice = true;
attributeAudio.waveform = getWaveform2(recordSamples, recordSamples.length);
if (attributeAudio.waveform != null) {
attributeAudio.flags |= 4;
}
attributeAudio.duration = recordTimeCount / 1000.0;
audioToSend.attributes.clear();
audioToSend.attributes.add(attributeAudio);
NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.recordPaused);
NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.audioDidSent, recordingGuid, audioToSend, recordingAudioFileToSend.getAbsolutePath(), true);
});
});
}
public void toggleRecordingPause(boolean voiceOnce) {
recordQueue.postRunnable(() -> {
if (audioRecorder == null || recordingAudio == null || recordingAudioFile == null) {
return;
}
audioRecorderPaused = !audioRecorderPaused;
@ -3836,38 +3928,62 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
audioRecorder.stop();
audioRecorder.release();
audioRecorder = null;
recordQueue.postRunnable(() -> {
stopRecord(true);
final TLRPC.TL_document audioToSend = recordingAudio;
final File recordingAudioFileToSend = recordingAudioFile;
AndroidUtilities.runOnUIThread(() -> {
boolean fileExist = recordingAudioFileToSend.exists();
if (!fileExist && BuildVars.DEBUG_VERSION) {
FileLog.e(new RuntimeException("file not found :( recordTimeCount " + recordTimeCount + " writedFrames" + writedFrame));
final TLRPC.TL_document audioToSend = recordingAudio;
final File recordingAudioFileToSend = recordingAudioFile;
if (recordingAudio == null || recordingAudioFile == null) {
return;
}
audioToSend.date = ConnectionsManager.getInstance(recordingCurrentAccount).getCurrentTime();
audioToSend.size = (int) recordingAudioFileToSend.length();
TLRPC.TL_documentAttributeAudio attributeAudio = new TLRPC.TL_documentAttributeAudio();
attributeAudio.voice = true;
attributeAudio.waveform = getWaveform2(recordSamples, recordSamples.length);
if (attributeAudio.waveform != null) {
attributeAudio.flags |= 4;
}
attributeAudio.duration = recordTimeCount / 1000.0;
audioToSend.attributes.clear();
audioToSend.attributes.add(attributeAudio);
NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.recordPaused);
NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.audioDidSent, recordingGuid, audioToSend, recordingAudioFileToSend.getAbsolutePath());
AndroidUtilities.runOnUIThread(() -> {
boolean fileExist = recordingAudioFileToSend.exists();
if (!fileExist && BuildVars.DEBUG_VERSION) {
FileLog.e(new RuntimeException("file not found :( recordTimeCount " + recordTimeCount + " writedFrames" + writedFrame));
}
if (fileExist) {
MediaDataController.getInstance(recordingCurrentAccount).pushDraftVoiceMessage(recordDialogId, recordTopicId, MediaDataController.DraftVoice.of(this, recordingAudioFileToSend.getAbsolutePath(), voiceOnce));
}
audioToSend.date = ConnectionsManager.getInstance(recordingCurrentAccount).getCurrentTime();
audioToSend.size = (int) recordingAudioFileToSend.length();
TLRPC.TL_documentAttributeAudio attributeAudio = new TLRPC.TL_documentAttributeAudio();
attributeAudio.voice = true;
attributeAudio.waveform = getWaveform2(recordSamples, recordSamples.length);
if (attributeAudio.waveform != null) {
attributeAudio.flags |= 4;
}
attributeAudio.duration = recordTimeCount / 1000.0;
audioToSend.attributes.clear();
audioToSend.attributes.add(attributeAudio);
NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.recordPaused);
NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.audioDidSent, recordingGuid, audioToSend, recordingAudioFileToSend.getAbsolutePath());
});
});
} else {
recordQueue.cancelRunnable(recordRunnable);
audioRecorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, sampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, recordBufferSize);
recordStartTime = System.currentTimeMillis();
fileBuffer.rewind();
audioRecorder.startRecording();
recordQueue.postRunnable(recordRunnable);
recordQueue.postRunnable(() -> {
if (resumeRecord(recordingAudioFile.getPath(), sampleRate) == 0) {
AndroidUtilities.runOnUIThread(() -> {
recordStartRunnable = null;
NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.recordStartError, recordingGuid);
});
if (BuildVars.LOGS_ENABLED) {
FileLog.d("cant resume encoder");
}
return;
}
AndroidUtilities.runOnUIThread(() -> {
NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.recordResumed);
AndroidUtilities.runOnUIThread(() -> {
MediaDataController.getInstance(recordingCurrentAccount).pushDraftVoiceMessage(recordDialogId, recordTopicId, null);
audioRecorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, sampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, recordBufferSize);
recordStartTime = System.currentTimeMillis();
fileBuffer.rewind();
audioRecorder.startRecording();
recordQueue.postRunnable(recordRunnable);
NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.recordResumed);
});
});
}
});
@ -3943,6 +4059,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
writedFrame = 0;
samplesCount = 0;
recordDialogId = dialogId;
recordTopicId = replyToTopMsg == null ? 0 : MessageObject.getTopicId(recordingCurrentAccount, replyToTopMsg.messageOwner, false);
recordingCurrentAccount = currentAccount;
recordReplyingMsg = replyToMsg;
recordReplyingTopMsg = replyToTopMsg;
@ -3953,7 +4070,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
} catch (Exception e) {
FileLog.e(e);
recordingAudio = null;
stopRecord();
stopRecord(false);
AutoDeleteMediaTask.unlockFile(recordingAudioFile);
recordingAudioFile.delete();
recordingAudioFile = null;
@ -4028,7 +4145,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
FileLog.d("stop recording internal filename " + recordingAudioFile.getPath());
}
fileEncodingQueue.postRunnable(() -> {
stopRecord();
stopRecord(false);
if (BuildVars.LOGS_ENABLED) {
FileLog.d("stop recording internal in queue " + recordingAudioFileToSend.exists() + " " + recordingAudioFileToSend.length());
}
@ -4040,6 +4157,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
if (!fileExist && BuildVars.DEBUG_VERSION) {
FileLog.e(new RuntimeException("file not found :( recordTimeCount " + recordTimeCount + " writedFrames" + writedFrame));
}
MediaDataController.getInstance(recordingCurrentAccount).pushDraftVoiceMessage(recordDialogId, recordTopicId, null);
audioToSend.date = ConnectionsManager.getInstance(recordingCurrentAccount).getCurrentTime();
audioToSend.size = (int) recordingAudioFileToSend.length();
TLRPC.TL_documentAttributeAudio attributeAudio = new TLRPC.TL_documentAttributeAudio();
@ -4187,7 +4305,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
if (path == null || path.length() == 0) {
path = null;
TLRPC.Document document = message.getDocument();
if (!TextUtils.isEmpty(FileLoader.getDocumentFileName(document)) && FileLoader.canSaveAsFile(message)) {
if (!TextUtils.isEmpty(FileLoader.getDocumentFileName(document)) && !(message.messageOwner instanceof TLRPC.TL_message_secret) && FileLoader.canSaveAsFile(message)) {
String filename = FileLoader.getDocumentFileName(document);
File newDir = FileLoader.getDirectory(FileLoader.MEDIA_DIR_FILES);
if (newDir != null) {

View file

@ -75,6 +75,7 @@ import org.telegram.ui.Components.StickersArchiveAlert;
import org.telegram.ui.Components.TextStyleSpan;
import org.telegram.ui.Components.URLSpanReplacement;
import org.telegram.ui.Components.URLSpanUserMention;
import org.telegram.ui.Components.voip.PrivateVideoPreviewDialog;
import org.telegram.ui.LaunchActivity;
import org.telegram.ui.PremiumPreviewFragment;
import org.telegram.ui.Stories.StoriesStorage;
@ -89,6 +90,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
@ -5840,7 +5842,7 @@ public class MediaDataController extends BaseController {
}
} else if (messageObject.getId() > 0 && messageObject.isReplyToStory()) {
if (messageObject.messageOwner.replyStory == null) {
long storyDialogId = messageObject.messageOwner.reply_to.user_id;
long storyDialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.peer);
if (messagesWithUnknownStories == null) {
messagesWithUnknownStories = new LongSparseArray<>();
}
@ -5851,7 +5853,7 @@ public class MediaDataController extends BaseController {
}
array.add(messageObject);
} else {
long storyDialogId = messageObject.messageOwner.reply_to.user_id;
long storyDialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.peer);
messageObject.messageOwner.replyStory = StoriesStorage.checkExpiredStateLocal(currentAccount, storyDialogId, messageObject.messageOwner.replyStory);
}
} else if (messageObject.getId() > 0 && messageObject.isReply()) {
@ -7078,7 +7080,7 @@ public class MediaDataController extends BaseController {
return a.reply_to_msg_id == b.reply_to_msg_id;
}
if (a instanceof TLRPC.TL_inputReplyToStory) {
return a.user_id == b.user_id && a.story_id == b.story_id;
return MessageObject.peersEqual(a.peer, b.peer) && a.story_id == b.story_id;
}
return true;
}
@ -7086,7 +7088,7 @@ public class MediaDataController extends BaseController {
private static TLRPC.InputReplyTo toInputReplyTo(int currentAccount, TLRPC.MessageReplyHeader reply_to) {
if (reply_to instanceof TLRPC.TL_messageReplyStoryHeader) {
TLRPC.TL_inputReplyToStory inputReplyTo = new TLRPC.TL_inputReplyToStory();
inputReplyTo.user_id = MessagesController.getInstance(currentAccount).getInputUser(reply_to.user_id);
inputReplyTo.peer = MessagesController.getInstance(currentAccount).getInputPeer(reply_to.peer);
inputReplyTo.story_id = reply_to.story_id;
return inputReplyTo;
} else if (reply_to instanceof TLRPC.TL_messageReplyHeader) {
@ -8996,4 +8998,107 @@ public class MediaDataController extends BaseController {
}));
}
}
private boolean draftVoicesLoaded = false;
public LongSparseArray<DraftVoice> draftVoices = new LongSparseArray<>();
private void loadDraftVoiceMessages() {
if (draftVoicesLoaded) return;
SharedPreferences prefs = ApplicationLoader.applicationContext.getSharedPreferences("voicedrafts_" + currentAccount, Context.MODE_PRIVATE);
Set<? extends Map.Entry<String, ?>> entries = prefs.getAll().entrySet();
draftVoices.clear();
for (Map.Entry<String, ?> entry : entries) {
String key = entry.getKey();
String value = (String) entry.getValue();
DraftVoice draft = DraftVoice.fromString(value);
if (draft == null) continue;
draftVoices.put(Long.parseLong(key), draft);
}
draftVoicesLoaded = true;
}
public void toggleDraftVoiceOnce(long dialog_id, long topic_id, boolean once) {
DraftVoice draft = getDraftVoice(dialog_id, topic_id);
if (draft != null && draft.once != once) {
draft.once = once;
SharedPreferences prefs = ApplicationLoader.applicationContext.getSharedPreferences("voicedrafts_" + currentAccount, Context.MODE_PRIVATE);
prefs.edit().putString(Objects.hash(dialog_id, topic_id) + "", draft.toString()).apply();
}
}
public void pushDraftVoiceMessage(long dialog_id, long topic_id, DraftVoice draft) {
SharedPreferences prefs = ApplicationLoader.applicationContext.getSharedPreferences("voicedrafts_" + currentAccount, Context.MODE_PRIVATE);
final long hash = Objects.hash(dialog_id, topic_id);
final String key = hash + "";
if (draft == null) {
prefs.edit().remove(key).apply();
draftVoices.remove(hash);
} else {
prefs.edit().putString(key, draft.toString()).apply();
draftVoices.put(hash, draft);
}
}
public DraftVoice getDraftVoice(long dialog_id, long topic_id) {
loadDraftVoiceMessages();
return draftVoices.get(Objects.hash(dialog_id, topic_id));
}
public static class DraftVoice {
public String path;
public long samplesCount;
public int writedFrame;
public long recordTimeCount;
public long id;
public short[] recordSamples;
public boolean once;
public static DraftVoice of(MediaController mediaController, String path, boolean once) {
if (mediaController.recordingAudio == null) {
return null;
}
DraftVoice draft = new DraftVoice();
draft.path = path;
draft.samplesCount = mediaController.samplesCount;
draft.writedFrame = mediaController.writedFrame;
draft.recordTimeCount = mediaController.recordTimeCount;
draft.id = mediaController.recordingAudio.id;
draft.recordSamples = mediaController.recordSamples;
draft.once = once;
return draft;
}
@NonNull
@Override
public String toString() {
char[] recordSamplesArray = new char[recordSamples.length];
for (int i = 0; i < recordSamples.length; ++i) {
recordSamplesArray[i] = (char) recordSamples[i];
}
return path + "\n" + samplesCount + "\n" + writedFrame + "\n" + recordTimeCount + "\n" + (once ? 1 : 0) + "\n" + new String(recordSamplesArray);
}
public static DraftVoice fromString(String string) {
try {
if (string == null) return null;
String[] parts = string.split("\n");
if (parts.length < 6) return null;
DraftVoice draft = new DraftVoice();
draft.path = parts[0];
draft.samplesCount = Long.parseLong(parts[1]);
draft.writedFrame = Integer.parseInt(parts[2]);
draft.recordTimeCount = Long.parseLong(parts[3]);
draft.once = Integer.parseInt(parts[4]) != 0;
String[] recordSamplesParts = new String[parts.length - 5];
for (int i = 0; i < recordSamplesParts.length; ++i) {
recordSamplesParts[i] = parts[5 + i];
}
String recordSamplesString = TextUtils.join("\n", recordSamplesParts);
draft.recordSamples = new short[recordSamplesString.length()];
for (int i = 0; i < draft.recordSamples.length; ++i) {
draft.recordSamples[i] = (short) recordSamplesString.charAt(i);
}
return draft;
} catch (Exception e) {
FileLog.e(e);
return null;
}
}
}
}

View file

@ -1979,18 +1979,18 @@ public class MessageObject {
rights.append('\n').append(n.edit_messages ? '+' : '-').append(' ');
rights.append(LocaleController.getString("EventLogPromotedEditMessages", R.string.EventLogPromotedEditMessages));
}
if (o.post_stories != n.post_stories) {
rights.append('\n').append(n.post_stories ? '+' : '-').append(' ');
rights.append(LocaleController.getString("EventLogPromotedPostStories", R.string.EventLogPromotedPostStories));
}
if (o.edit_stories != n.edit_stories) {
rights.append('\n').append(n.edit_messages ? '+' : '-').append(' ');
rights.append(LocaleController.getString("EventLogPromotedEditStories", R.string.EventLogPromotedEditStories));
}
if (o.delete_stories != n.delete_stories) {
rights.append('\n').append(n.delete_stories ? '+' : '-').append(' ');
rights.append(LocaleController.getString("EventLogPromotedDeleteStories", R.string.EventLogPromotedDeleteStories));
}
}
if (o.post_stories != n.post_stories) {
rights.append('\n').append(n.post_stories ? '+' : '-').append(' ');
rights.append(LocaleController.getString("EventLogPromotedPostStories", R.string.EventLogPromotedPostStories));
}
if (o.edit_stories != n.edit_stories) {
rights.append('\n').append(n.edit_stories ? '+' : '-').append(' ');
rights.append(LocaleController.getString("EventLogPromotedEditStories", R.string.EventLogPromotedEditStories));
}
if (o.delete_stories != n.delete_stories) {
rights.append('\n').append(n.delete_stories ? '+' : '-').append(' ');
rights.append(LocaleController.getString("EventLogPromotedDeleteStories", R.string.EventLogPromotedDeleteStories));
}
if (o.delete_messages != n.delete_messages) {
rights.append('\n').append(n.delete_messages ? '+' : '-').append(' ');
@ -2474,6 +2474,14 @@ public class MessageObject {
message.media.webpage.display_url = "";
message.media.webpage.url = "";
}
} else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeEmojiStickerSet) {
TLRPC.InputStickerSet newPack = ((TLRPC.TL_channelAdminLogEventActionChangeEmojiStickerSet) event.action).new_stickerset;
TLRPC.InputStickerSet oldPack = ((TLRPC.TL_channelAdminLogEventActionChangeEmojiStickerSet) event.action).new_stickerset;
if (newPack == null || newPack instanceof TLRPC.TL_inputStickerSetEmpty) {
messageText = replaceWithLink(LocaleController.getString("EventLogRemovedEmojiPack", R.string.EventLogRemovedEmojiPack), "un1", fromUser);
} else {
messageText = replaceWithLink(LocaleController.getString("EventLogChangedEmojiPack", R.string.EventLogChangedEmojiPack), "un1", fromUser);
}
} else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeStickerSet) {
TLRPC.InputStickerSet newStickerset = ((TLRPC.TL_channelAdminLogEventActionChangeStickerSet) event.action).new_stickerset;
TLRPC.InputStickerSet oldStickerset = ((TLRPC.TL_channelAdminLogEventActionChangeStickerSet) event.action).new_stickerset;
@ -2784,11 +2792,13 @@ public class MessageObject {
fromUser
);
} else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeColor) {
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
TLRPC.TL_channelAdminLogEventActionChangeColor action = (TLRPC.TL_channelAdminLogEventActionChangeColor) event.action;
messageText = replaceWithLink(LocaleController.formatString(R.string.EventLogChangedColor, AvatarDrawable.colorName(action.prev_value).toLowerCase(), AvatarDrawable.colorName(action.new_value).toLowerCase()), "un1", fromUser);
messageText = replaceWithLink(LocaleController.formatString(isChannel ? R.string.EventLogChangedColor : R.string.EventLogChangedColorGroup, AvatarDrawable.colorName(action.prev_value).toLowerCase(), AvatarDrawable.colorName(action.new_value).toLowerCase()), "un1", fromUser);
} else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangePeerColor) {
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
TLRPC.TL_channelAdminLogEventActionChangePeerColor action = (TLRPC.TL_channelAdminLogEventActionChangePeerColor) event.action;
SpannableStringBuilder ssb = new SpannableStringBuilder(LocaleController.getString(R.string.EventLogChangedPeerColorIcon));
SpannableStringBuilder ssb = new SpannableStringBuilder(LocaleController.getString(isChannel ? R.string.EventLogChangedPeerColorIcon : R.string.EventLogChangedPeerColorIconGroup));
SpannableStringBuilder prev = new SpannableStringBuilder();
if ((action.prev_value.flags & 1) != 0) {
@ -2825,8 +2835,9 @@ public class MessageObject {
messageText = replaceWithLink(ssb, "un1", fromUser);
} else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeProfilePeerColor) {
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
TLRPC.TL_channelAdminLogEventActionChangeProfilePeerColor action = (TLRPC.TL_channelAdminLogEventActionChangeProfilePeerColor) event.action;
SpannableStringBuilder ssb = new SpannableStringBuilder(LocaleController.getString(R.string.EventLogChangedProfileColorIcon));
SpannableStringBuilder ssb = new SpannableStringBuilder(LocaleController.getString(isChannel ? R.string.EventLogChangedProfileColorIcon : R.string.EventLogChangedProfileColorIconGroup));
SpannableStringBuilder prev = new SpannableStringBuilder();
if ((action.prev_value.flags & 1) != 0) {
@ -2863,6 +2874,7 @@ public class MessageObject {
messageText = replaceWithLink(ssb, "un1", fromUser);
} else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeEmojiStatus) {
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
TLRPC.TL_channelAdminLogEventActionChangeEmojiStatus action = (TLRPC.TL_channelAdminLogEventActionChangeEmojiStatus) event.action;
boolean prevNone = false;
@ -2887,9 +2899,9 @@ public class MessageObject {
SpannableStringBuilder ssb = new SpannableStringBuilder(LocaleController.getString(
prevNone ? (
hasUntil ? R.string.EventLogChangedEmojiStatusFor : R.string.EventLogChangedEmojiStatus
hasUntil ? (isChannel ? R.string.EventLogChangedEmojiStatusFor : R.string.EventLogChangedEmojiStatusForGroup) : (isChannel ? R.string.EventLogChangedEmojiStatus : R.string.EventLogChangedEmojiStatusGroup)
) : (
hasUntil ? R.string.EventLogChangedEmojiStatusFromFor : R.string.EventLogChangedEmojiStatusFrom
hasUntil ? (isChannel ? R.string.EventLogChangedEmojiStatusFromFor : R.string.EventLogChangedEmojiStatusFromForGroup) : (isChannel ? R.string.EventLogChangedEmojiStatusFrom : R.string.EventLogChangedEmojiStatusFromGroup)
)
));
@ -2903,19 +2915,21 @@ public class MessageObject {
messageText = replaceWithLink(ssb, "un1", fromUser);
} else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeWallpaper) {
TLRPC.TL_channelAdminLogEventActionChangeWallpaper action = (TLRPC.TL_channelAdminLogEventActionChangeWallpaper) event.action;
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
if (action.new_value instanceof TLRPC.TL_wallPaperNoFile && action.new_value.id == 0 && action.new_value.settings == null) {
messageText = replaceWithLink(LocaleController.getString(R.string.EventLogRemovedWallpaper), "un1", fromUser);
messageText = replaceWithLink(LocaleController.getString(isChannel ? R.string.EventLogRemovedWallpaper : R.string.EventLogRemovedWallpaperGroup), "un1", fromUser);
} else {
photoThumbs = new ArrayList<>();
if (action.new_value.document != null) {
photoThumbs.addAll(action.new_value.document.thumbs);
photoThumbsObject = action.new_value.document;
}
messageText = replaceWithLink(LocaleController.getString(R.string.EventLogChangedWallpaper), "un1", fromUser);
messageText = replaceWithLink(LocaleController.getString(isChannel ? R.string.EventLogChangedWallpaper : R.string.EventLogChangedWallpaperGroup), "un1", fromUser);
}
} else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeBackgroundEmoji) {
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
TLRPC.TL_channelAdminLogEventActionChangeBackgroundEmoji action = (TLRPC.TL_channelAdminLogEventActionChangeBackgroundEmoji) event.action;
messageText = replaceWithLink(LocaleController.getString(R.string.EventLogChangedEmoji), "un1", fromUser);
messageText = replaceWithLink(LocaleController.getString(isChannel ? R.string.EventLogChangedEmoji : R.string.EventLogChangedEmojiGroup), "un1", fromUser);
SpannableString emoji1;
if (action.prev_value == 0) {
@ -3789,7 +3803,9 @@ public class MessageObject {
messageText = LocaleController.formatString(R.string.ActionSetSameWallpaperForThisChat, user.first_name);
}
} else if (fromChat != null) {
messageText = LocaleController.getString(R.string.ActionSetWallpaperForThisChannel);
messageText = LocaleController.getString(ChatObject.isChannelAndNotMegaGroup(fromChat) ? R.string.ActionSetWallpaperForThisChannel : R.string.ActionSetWallpaperForThisGroup);
} else if (fromUser != null) {
messageText = LocaleController.formatString(R.string.ActionSetWallpaperForThisGroupByUser, UserObject.getFirstName(fromUser));
}
} else if (messageOwner.action instanceof TLRPC.TL_messageActionSetChatWallPaper) {
contentType = 1;
@ -3829,7 +3845,9 @@ public class MessageObject {
messageText = AndroidUtilities.replaceCharSequence("%s", messageText, userName);
}
} else if (fromChat != null) {
messageText = LocaleController.getString(R.string.ActionSetWallpaperForThisChannel);
messageText = LocaleController.getString(ChatObject.isChannelAndNotMegaGroup(fromChat) ? R.string.ActionSetWallpaperForThisChannel : R.string.ActionSetWallpaperForThisGroup);
} else if (fromUser != null) {
messageText = LocaleController.formatString(R.string.ActionSetWallpaperForThisGroupByUser, UserObject.getFirstName(fromUser));
}
} else if (messageOwner.action instanceof TLRPC.TL_messageActionGroupCallScheduled) {
TLRPC.TL_messageActionGroupCallScheduled action = (TLRPC.TL_messageActionGroupCallScheduled) messageOwner.action;
@ -4017,14 +4035,43 @@ public class MessageObject {
}
} else if (messageOwner.action instanceof TLRPC.TL_messageActionGiveawayLaunch) {
TLRPC.Chat chat = messageOwner.peer_id != null && messageOwner.peer_id.channel_id != 0 ? getChat(chats, sChats, messageOwner.peer_id.channel_id) : null;
messageText = LocaleController.formatString("BoostingGiveawayJustStarted", R.string.BoostingGiveawayJustStarted, chat != null ? chat.title : "");
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
messageText = LocaleController.formatString(isChannel ? R.string.BoostingGiveawayJustStarted : R.string.BoostingGiveawayJustStartedGroup, chat != null ? chat.title : "");
} else if (messageOwner.action instanceof TLRPC.TL_messageActionBoostApply) {
TLRPC.Chat chat = messageOwner.peer_id != null && messageOwner.peer_id.channel_id != 0 ? getChat(chats, sChats, messageOwner.peer_id.channel_id) : null;
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
TLRPC.TL_messageActionBoostApply messageActionBoostApply = (TLRPC.TL_messageActionBoostApply) messageOwner.action;
String name = "";
boolean self = false;
if (fromObject instanceof TLRPC.User) {
TLRPC.User user = (TLRPC.User) fromObject;
self = UserObject.isUserSelf(user);
name = UserObject.getFirstName(user);
} else if (fromObject instanceof TLRPC.Chat) {
name = ((TLRPC.Chat) fromObject).title;
}
if (self) {
if (messageActionBoostApply.boosts <= 1) {
messageText = LocaleController.getString(isChannel ? R.string.BoostingBoostsChannelByYouServiceMsg : R.string.BoostingBoostsGroupByYouServiceMsg);
} else {
messageText = LocaleController.formatPluralString(isChannel ? "BoostingBoostsChannelByYouServiceMsgCount" : "BoostingBoostsGroupByYouServiceMsgCount", messageActionBoostApply.boosts);
}
} else {
if (messageActionBoostApply.boosts <= 1) {
messageText = LocaleController.formatString(isChannel ? R.string.BoostingBoostsChannelByUserServiceMsg : R.string.BoostingBoostsGroupByUserServiceMsg, name);
} else {
messageText = LocaleController.formatPluralString(isChannel ? "BoostingBoostsChannelByUserServiceMsgCount" : "BoostingBoostsGroupByUserServiceMsgCount", messageActionBoostApply.boosts, name);
}
}
} else if (messageOwner.action instanceof TLRPC.TL_messageActionGiveawayResults) {
TLRPC.Chat chat = messageOwner.peer_id != null && messageOwner.peer_id.channel_id != 0 ? getChat(chats, sChats, messageOwner.peer_id.channel_id) : null;
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
TLRPC.TL_messageActionGiveawayResults giveawayResults = (TLRPC.TL_messageActionGiveawayResults) messageOwner.action;
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
stringBuilder.append(LocaleController.formatPluralString("BoostingGiveawayServiceWinnersSelected", giveawayResults.winners_count));
if (giveawayResults.unclaimed_count > 0) {
stringBuilder.append("\n");
stringBuilder.append(LocaleController.formatPluralString("BoostingGiveawayServiceUndistributed", giveawayResults.unclaimed_count));
stringBuilder.append(LocaleController.formatPluralString(isChannel ? "BoostingGiveawayServiceUndistributed" : "BoostingGiveawayServiceUndistributedGroup", giveawayResults.unclaimed_count));
}
messageText = stringBuilder;
} else if (messageOwner.action instanceof TLRPC.TL_messageActionGiftCode && ((TLRPC.TL_messageActionGiftCode) messageOwner.action).boost_peer != null) {
@ -4537,7 +4584,14 @@ public class MessageObject {
} else if (!isMediaEmpty()) {
// messageText = getMediaTitle(getMedia(messageOwner)); // I'm afraid doing this
if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGiveaway) {
messageText = LocaleController.getString("BoostingGiveawayChannelStarted", R.string.BoostingGiveawayChannelStarted);
boolean isChannel;
if (messageOwner.fwd_from != null && messageOwner.fwd_from.from_id instanceof TLRPC.TL_peerChannel) {
TLRPC.Chat chat = getChat(chats, sChats, messageOwner.fwd_from.from_id.channel_id);
isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
} else {
isChannel = ChatObject.isChannelAndNotMegaGroup(fromChat);
}
messageText = LocaleController.getString(isChannel ? R.string.BoostingGiveawayChannelStarted : R.string.BoostingGiveawayGroupStarted);
} else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGiveawayResults) {
messageText = LocaleController.getString("BoostingGiveawayResults", R.string.BoostingGiveawayResults);
} else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaStory) {
@ -7294,8 +7348,12 @@ public class MessageObject {
return isOutOwnerCached;
}
long selfUserId = UserConfig.getInstance(currentAccount).getClientUserId();
if ((isSaved || getDialogId() == selfUserId) && messageOwner.fwd_from != null) {
return isOutOwnerCached = messageOwner.fwd_from.from_id != null && messageOwner.fwd_from.from_id.user_id == selfUserId || messageOwner.fwd_from.saved_out;
if ((isSaved || getDialogId() == selfUserId)) {
if (messageOwner.fwd_from != null) {
return isOutOwnerCached = messageOwner.fwd_from.from_id != null && messageOwner.fwd_from.from_id.user_id == selfUserId || messageOwner.fwd_from.saved_out;
} else {
return isOutOwnerCached = true;
}
}
TLRPC.Chat chat = messageOwner.peer_id != null && messageOwner.peer_id.channel_id != 0 ? getChat(null, null, messageOwner.peer_id.channel_id) : null;
if (!messageOwner.out || !(messageOwner.from_id instanceof TLRPC.TL_peerUser) && (!(messageOwner.from_id instanceof TLRPC.TL_peerChannel) || ChatObject.isChannel(chat) && !chat.megagroup) || messageOwner.post) {
@ -9844,6 +9902,7 @@ public class MessageObject {
!"telegram_user".equals(webpageType) && // drawInstantViewType = 13
!"telegram_story".equals(webpageType) && // drawInstantViewType = 17
!"telegram_channel_boost".equals(webpageType) && // drawInstantViewType = 18
!"telegram_group_boost".equals(webpageType) && // drawInstantViewType = 21
!"telegram_chat".equals(webpageType)
;
}
@ -9857,7 +9916,7 @@ public class MessageObject {
"article".equals(webpageType) || "telegram_bot".equals(webpageType) ||
"telegram_user".equals(webpageType) || "telegram_channel".equals(webpageType) ||
"telegram_megagroup".equals(webpageType) || "telegram_voicechat".equals(webpageType) ||
"telegram_livestream".equals(webpageType) || "telegram_channel_boost".equals(webpageType) ||
"telegram_livestream".equals(webpageType) || "telegram_channel_boost".equals(webpageType) || "telegram_group_boost".equals(webpageType) ||
"telegram_chat".equals(webpageType)
);
}

View file

@ -69,6 +69,7 @@ import org.telegram.ui.Components.AnimatedEmojiDrawable;
import org.telegram.ui.Components.BulletinFactory;
import org.telegram.ui.Components.ImageUpdater;
import org.telegram.ui.Components.JoinCallAlert;
import org.telegram.ui.Components.JoinGroupAlert;
import org.telegram.ui.Components.MotionBackgroundDrawable;
import org.telegram.ui.Components.Premium.LimitReachedBottomSheet;
import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
@ -84,8 +85,6 @@ import org.telegram.ui.Stories.StoriesController;
import org.telegram.ui.TopicsFragment;
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -581,6 +580,13 @@ public class MessagesController extends BaseController implements NotificationCe
public int channelEmojiStatusLevelMin;
public int channelWallpaperLevelMin;
public int channelCustomWallpaperLevelMin;
public int groupProfileBgIconLevelMin;
public int groupEmojiStatusLevelMin;
public int groupEmojiStickersLevelMin;
public int groupWallpaperLevelMin;
public int groupCustomWallpaperLevelMin;
public int groupTranscribeLevelMin;
public int savedDialogsPinnedLimitDefault;
public int savedDialogsPinnedLimitPremium;
@ -1453,6 +1459,12 @@ public class MessagesController extends BaseController implements NotificationCe
channelBgIconLevelMin = mainPreferences.getInt("channelBgIconLevelMin", 1);
channelProfileIconLevelMin = mainPreferences.getInt("channelProfileIconLevelMin", 1);
channelEmojiStatusLevelMin = mainPreferences.getInt("channelEmojiStatusLevelMin", 1);
groupProfileBgIconLevelMin = mainPreferences.getInt("groupProfileBgIconLevelMin", 1);
groupEmojiStatusLevelMin = mainPreferences.getInt("groupEmojiStatusLevelMin", 1);
groupEmojiStickersLevelMin = mainPreferences.getInt("groupEmojiStickersLevelMin", 1);
groupWallpaperLevelMin = mainPreferences.getInt("groupWallpaperLevelMin", 1);
groupCustomWallpaperLevelMin = mainPreferences.getInt("groupCustomWallpaperLevelMin", 1);
groupTranscribeLevelMin = mainPreferences.getInt("groupTranscribeLevelMin", 1);
channelWallpaperLevelMin = mainPreferences.getInt("channelWallpaperLevelMin", 1);
channelCustomWallpaperLevelMin = mainPreferences.getInt("channelCustomWallpaperLevelMin", 1);
chatlistInvitesLimitPremium = mainPreferences.getInt("chatlistInvitesLimitPremium", isTest ? 5 : 20);
@ -3664,6 +3676,72 @@ public class MessagesController extends BaseController implements NotificationCe
}
break;
}
case "group_custom_wallpaper_level_min": {
if (value.value instanceof TLRPC.TL_jsonNumber) {
TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value;
if (num.value != groupCustomWallpaperLevelMin) {
groupCustomWallpaperLevelMin = (int) num.value;
editor.putInt("groupCustomWallpaperLevelMin", groupCustomWallpaperLevelMin);
changed = true;
}
}
break;
}
case "group_transcribe_level_min": {
if (value.value instanceof TLRPC.TL_jsonNumber) {
TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value;
if (num.value != groupTranscribeLevelMin) {
groupTranscribeLevelMin = (int) num.value;
editor.putInt("groupTranscribeLevelMin", groupTranscribeLevelMin);
changed = true;
}
}
break;
}
case "group_wallpaper_level_min": {
if (value.value instanceof TLRPC.TL_jsonNumber) {
TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value;
if (num.value != groupWallpaperLevelMin) {
groupWallpaperLevelMin = (int) num.value;
editor.putInt("groupWallpaperLevelMin", groupWallpaperLevelMin);
changed = true;
}
}
break;
}
case "group_emoji_status_level_min": {
if (value.value instanceof TLRPC.TL_jsonNumber) {
TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value;
if (num.value != groupEmojiStatusLevelMin) {
groupEmojiStatusLevelMin = (int) num.value;
editor.putInt("groupEmojiStatusLevelMin", groupEmojiStatusLevelMin);
changed = true;
}
}
break;
}
case "group_emoji_stickers_level_min": {
if (value.value instanceof TLRPC.TL_jsonNumber) {
TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value;
if (num.value != groupEmojiStickersLevelMin) {
groupEmojiStickersLevelMin = (int) num.value;
editor.putInt("groupEmojiStickersLevelMin", groupEmojiStickersLevelMin);
changed = true;
}
}
break;
}
case "group_profile_bg_icon_level_min": {
if (value.value instanceof TLRPC.TL_jsonNumber) {
TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value;
if (num.value != groupProfileBgIconLevelMin) {
groupProfileBgIconLevelMin = (int) num.value;
editor.putInt("groupProfileBgIconLevelMin", groupProfileBgIconLevelMin);
changed = true;
}
}
break;
}
case "channel_wallpaper_level_min": {
if (value.value instanceof TLRPC.TL_jsonNumber) {
TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value;
@ -3794,20 +3872,31 @@ public class MessagesController extends BaseController implements NotificationCe
boolean noLevels = true;
boolean hasStandardColors = false;
for (int i = 0; i < colors.size(); ++i) {
if (colors.get(i).lvl > 0) {
if (colors.get(i).channelLvl > 0) {
noLevels = false;
}
if (colors.get(i).id < 7) {
hasStandardColors = true;
}
}
if (type == TYPE_PROFILE && !noLevels) {
noLevels = true;
for (PeerColor color : colors) {
if (color.groupLvl > 0) {
noLevels = false;
break;
}
}
}
return noLevels || type == TYPE_NAME && !hasStandardColors;
}
public int colorsAvailable(int lvl) {
public int colorsAvailable(int lvl, boolean isGroup) {
int count = 0;
for (int i = 0; i < colors.size(); ++i) {
if (!colors.get(i).hidden && lvl >= colors.get(i).lvl) {
MessagesController.PeerColor peerColor = colors.get(i);
if (!peerColor.hidden && lvl >= peerColor.getLvl(isGroup)) {
count++;
}
}
@ -3815,20 +3904,30 @@ public class MessagesController extends BaseController implements NotificationCe
}
public int maxLevel() {
return maxLevel(false);
}
public int maxLevel(boolean isGroup) {
int maxLvl = 0;
for (int i = 0; i < colors.size(); ++i) {
if (!colors.get(i).hidden) {
maxLvl = Math.max(maxLvl, colors.get(i).lvl);
MessagesController.PeerColor peerColor = colors.get(i);
if (!peerColor.hidden) {
maxLvl = Math.max(maxLvl, peerColor.getLvl(isGroup));
}
}
return maxLvl;
}
public int minLevel() {
int minLvl = maxLevel();
return minLevel(false);
}
public int minLevel(boolean isGroup) {
int minLvl = maxLevel(isGroup);
for (int i = 0; i < colors.size(); ++i) {
if (!colors.get(i).hidden) {
minLvl = Math.min(minLvl, colors.get(i).lvl);
MessagesController.PeerColor peerColor = colors.get(i);
if (!peerColor.hidden) {
minLvl = Math.min(minLvl, peerColor.getLvl(isGroup));
}
}
return minLvl;
@ -3980,7 +4079,8 @@ public class MessagesController extends BaseController implements NotificationCe
public boolean isDefaultName;
public int id;
public boolean hidden;
public int lvl;
public int channelLvl;
public int groupLvl;
private final int[] colors = new int[6];
private final int[] darkColors = new int[6];
public int getColor(int i, Theme.ResourcesProvider resourcesProvider) {
@ -3991,6 +4091,9 @@ public class MessagesController extends BaseController implements NotificationCe
final boolean isDark = resourcesProvider != null ? resourcesProvider.isDark() : Theme.isCurrentThemeDark();
return (isDark ? darkColors : colors)[i];
}
public int getLvl(boolean isGroup) {
return isGroup ? groupLvl : channelLvl;
}
public int getColor1(boolean isDark) {
return (isDark ? darkColors : colors)[0];
}
@ -4060,8 +4163,8 @@ public class MessagesController extends BaseController implements NotificationCe
public void appendString(StringBuilder sb) {
sb.append("#");
if (hidden) sb.append("H");
if (lvl > 0) {
sb.append("[").append(lvl).append("]");
if (channelLvl != 0 || groupLvl != 0) {
sb.append("[").append(channelLvl).append(",").append(groupLvl).append("]");
}
sb.append(id);
sb.append("{");
@ -4112,7 +4215,10 @@ public class MessagesController extends BaseController implements NotificationCe
peerColor.id = tl.color_id;
peerColor.hidden = tl.hidden;
if ((tl.flags & 8) != 0) {
peerColor.lvl = tl.channel_min_level;
peerColor.channelLvl = tl.channel_min_level;
}
if ((tl.flags & 16) != 0) {
peerColor.groupLvl = tl.group_min_level;
}
System.arraycopy(optionToColors(tl.colors), 0, peerColor.colors, 0, 6);
@ -4162,11 +4268,19 @@ public class MessagesController extends BaseController implements NotificationCe
if (hidden) {
startIndex++;
}
int lvl = 0;
int channelLvl = 0;
int groupLvl = 0;
if (string.length() > startIndex && string.charAt(startIndex) == '[') {
int eindex = string.indexOf(']');
if (eindex > startIndex) {
lvl = Utilities.parseInt(string.substring(startIndex + 1, eindex));
String subStr = string.substring(startIndex + 1, eindex);
if (subStr.contains(",")) {
String[] splits = subStr.split(",");
channelLvl = Utilities.parseInt(splits[0]);
groupLvl = Utilities.parseInt(splits[1]);
} else {
channelLvl = Utilities.parseInt(subStr);
}
startIndex = eindex + 1;
}
}
@ -4176,7 +4290,8 @@ public class MessagesController extends BaseController implements NotificationCe
final PeerColor peerColor = new PeerColor();
peerColor.id = Utilities.parseInt(string.substring(startIndex, index));
peerColor.hidden = hidden;
peerColor.lvl = lvl;
peerColor.channelLvl = channelLvl;
peerColor.groupLvl = groupLvl;
final String[] parts = string.substring(index + 1, string.length() - 1).split("@");
String[] colorsString = parts[0].split(",");
for (int i = 0; i < 6; ++i)
@ -5997,6 +6112,9 @@ public class MessagesController extends BaseController implements NotificationCe
if (res.full_chat.stickerset != null) {
getMediaDataController().getGroupStickerSetById(res.full_chat.stickerset);
}
if (res.full_chat.emojiset != null) {
getMediaDataController().getGroupStickerSetById(res.full_chat.emojiset);
}
getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, res.full_chat, classGuid, false, true);
TLRPC.Dialog dialog = dialogs_dict.get(-chatId);
@ -6972,6 +7090,18 @@ public class MessagesController extends BaseController implements NotificationCe
});
}
public void setBoostsToUnblockRestrictions(long chatId, int boosts) {
TLRPC.TL_channels_setBoostsToUnblockRestrictions req = new TLRPC.TL_channels_setBoostsToUnblockRestrictions();
req.boosts = boosts;
req.channel = getInputChannel(chatId);
getConnectionsManager().sendRequest(req, (response, error) -> {
if (error == null) {
getMessagesController().processUpdates((TLRPC.Updates) response, false);
AndroidUtilities.runOnUIThread(() -> loadFullChat(chatId, 0, true), 1000);
}
});
}
public void setDefaultBannedRole(long chatId, TLRPC.TL_chatBannedRights rights, boolean isChannel, BaseFragment parentFragment) {
if (rights == null) {
return;
@ -8305,6 +8435,9 @@ public class MessagesController extends BaseController implements NotificationCe
if (info.stickerset != null) {
getMediaDataController().getGroupStickerSetById(info.stickerset);
}
if (info.emojiset != null) {
getMediaDataController().getGroupStickerSetById(info.emojiset);
}
getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, byChannelUsers, false);
}
if (pinnedMessages != null) {
@ -9397,7 +9530,7 @@ public class MessagesController extends BaseController implements NotificationCe
if (loadDialog && isTopic && load_type == 2 && last_message_id == 0) {
TLRPC.TL_forumTopic topic = topicsController.findTopic(-dialogId, threadMessageId);
if (topic != null) {
loadMessagesInternal(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, false, minDate, classGuid, load_type, topic.top_message, 0, threadMessageId, loadIndex, first_unread, topic.unread_count, last_date, queryFromServer, topic.unread_mentions_count, false, processMessages, isTopic, loaderLogger, 0L);
loadMessagesInternal(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, false, minDate, classGuid, load_type, topic.top_message, mode, threadMessageId, loadIndex, first_unread, topic.unread_count, last_date, queryFromServer, topic.unread_mentions_count, false, processMessages, isTopic, loaderLogger, 0L);
return;
}
}
@ -11657,12 +11790,12 @@ public class MessagesController extends BaseController implements NotificationCe
for (int a = 0; a < dialogsRes.messages.size(); a++) {
TLRPC.Message message = dialogsRes.messages.get(a);
if (promoDialogId == 0 || promoDialogId != message.dialog_id) {
if (message.peer_id.channel_id != 0) {
if (message.peer_id != null && message.peer_id.channel_id != 0) {
TLRPC.Chat chat = chatsDict.get(message.peer_id.channel_id);
if (chat != null && ChatObject.isNotInChat(chat)) {
continue;
}
} else if (message.peer_id.chat_id != 0) {
} else if (message.peer_id != null && message.peer_id.chat_id != 0) {
TLRPC.Chat chat = chatsDict.get(message.peer_id.chat_id);
if (chat != null && (chat.migrated_to != null || ChatObject.isNotInChat(chat))) {
continue;
@ -16220,16 +16353,6 @@ public class MessagesController extends BaseController implements NotificationCe
getNotificationCenter().postNotificationName(NotificationCenter.blockedUsersDidLoad);
getStoriesController().updateBlockUser(id, finalUpdate.blocked_my_stories_from, false);
}));
} else if (baseUpdate instanceof TLRPC.TL_updateNotifySettings) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateNewAuthorization) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateServiceNotification) {
TLRPC.TL_updateServiceNotification update = (TLRPC.TL_updateServiceNotification) baseUpdate;
if (update.popup && update.message != null && update.message.length() > 0) {
@ -16282,32 +16405,12 @@ public class MessagesController extends BaseController implements NotificationCe
}
pushMessages.add(obj);
}
} else if (baseUpdate instanceof TL_stories.TL_updateStoriesStealthMode) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateDialogPinned) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updatePinnedDialogs) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateFolderPeers) {
TLRPC.TL_updateFolderPeers update = (TLRPC.TL_updateFolderPeers) baseUpdate;
if (folderUpdates == null) {
folderUpdates = new ArrayList<>();
}
folderUpdates.add(update);
} else if (baseUpdate instanceof TLRPC.TL_updatePrivacy) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateWebPage) {
TLRPC.TL_updateWebPage update = (TLRPC.TL_updateWebPage) baseUpdate;
if (webPages == null) {
@ -16470,36 +16573,6 @@ public class MessagesController extends BaseController implements NotificationCe
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateStickerSets) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateStickerSetsOrder) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateNewStickerSet) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateDraftMessage) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateMoveStickerSetToTop) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateSavedGifs) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateEditChannelMessage || baseUpdate instanceof TLRPC.TL_updateEditMessage) {
TLRPC.Message message;
if (baseUpdate instanceof TLRPC.TL_updateEditChannelMessage) {
@ -16592,54 +16665,14 @@ public class MessagesController extends BaseController implements NotificationCe
} else if (baseUpdate instanceof TLRPC.TL_updatePinnedMessages) {
TLRPC.TL_updatePinnedMessages update = (TLRPC.TL_updatePinnedMessages) baseUpdate;
getMessagesStorage().updatePinnedMessages(MessageObject.getPeerId(update.peer), update.messages, update.pinned, -1, 0, false, null);
} else if (baseUpdate instanceof TLRPC.TL_updateReadFeaturedStickers) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateReadFeaturedEmojiStickers) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updatePhoneCall) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateGroupCallParticipants) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateGroupCall) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateGroupCallConnection) {
} else if (baseUpdate instanceof TLRPC.TL_updateBotCommands) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updatePhoneCallSignalingData) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateLangPack) {
TLRPC.TL_updateLangPack update = (TLRPC.TL_updateLangPack) baseUpdate;
AndroidUtilities.runOnUIThread(() -> LocaleController.getInstance().saveRemoteLocaleStringsForCurrentLocale(update.difference, currentAccount));
} else if (baseUpdate instanceof TLRPC.TL_updateLangPackTooLong) {
TLRPC.TL_updateLangPackTooLong update = (TLRPC.TL_updateLangPackTooLong) baseUpdate;
LocaleController.getInstance().reloadCurrentRemoteLocale(currentAccount, update.lang_code, false, null);
} else if (baseUpdate instanceof TLRPC.TL_updateRecentReactions || baseUpdate instanceof TLRPC.TL_updateSavedReactionTags) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateFavedStickers) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
@ -16710,53 +16743,8 @@ public class MessagesController extends BaseController implements NotificationCe
}
updatesOnMainThread.add(baseUpdate);
}
} else if (baseUpdate instanceof TLRPC.TL_updatePeerLocated) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateTheme) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateGeoLiveViewed) {
getLocationController().setNewLocationEndWatchTime();
} else if (baseUpdate instanceof TLRPC.TL_updateDialogFilter) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateDialogFilterOrder) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateDialogFilters) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateRecentEmojiStatuses) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateWebViewResultSent) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateAttachMenuBots) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateBotMenuButton) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateReadChannelDiscussionInbox) {
TLRPC.TL_updateReadChannelDiscussionInbox update = (TLRPC.TL_updateReadChannelDiscussionInbox) baseUpdate;
if (updatesOnMainThread == null) {
@ -16782,42 +16770,51 @@ public class MessagesController extends BaseController implements NotificationCe
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updatePeerHistoryTTL) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updatePendingJoinRequests) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateSavedRingtones) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateTranscribeAudio) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateTranscribedAudio) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateChannelViewForumAsMessages) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updatePinnedSavedDialogs) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateSavedDialogPinned) {
// } else if (
// baseUpdate instanceof TLRPC.TL_updateStickerSets ||
// baseUpdate instanceof TLRPC.TL_updateStickerSetsOrder ||
// baseUpdate instanceof TLRPC.TL_updateNewStickerSet ||
// baseUpdate instanceof TLRPC.TL_updateDraftMessage ||
// baseUpdate instanceof TLRPC.TL_updateMoveStickerSetToTop ||
// baseUpdate instanceof TLRPC.TL_updateSavedGifs ||
// baseUpdate instanceof TLRPC.TL_updateReadFeaturedStickers ||
// baseUpdate instanceof TLRPC.TL_updatePhoneCallSignalingData ||
// baseUpdate instanceof TLRPC.TL_updateBotCommands ||
// baseUpdate instanceof TLRPC.TL_updateGroupCall ||
// baseUpdate instanceof TLRPC.TL_updateReadFeaturedEmojiStickers ||
// baseUpdate instanceof TLRPC.TL_updateGroupCallParticipants ||
// baseUpdate instanceof TLRPC.TL_updatePhoneCall ||
// baseUpdate instanceof TLRPC.TL_updateRecentReactions ||
// baseUpdate instanceof TLRPC.TL_updateSavedReactionTags ||
// baseUpdate instanceof TLRPC.TL_updatePeerLocated ||
// baseUpdate instanceof TLRPC.TL_updateTheme ||
// baseUpdate instanceof TLRPC.TL_updateDialogFilter ||
// baseUpdate instanceof TLRPC.TL_updateDialogFilterOrder ||
// baseUpdate instanceof TLRPC.TL_updateDialogFilters ||
// baseUpdate instanceof TLRPC.TL_updateRecentEmojiStatuses ||
// baseUpdate instanceof TLRPC.TL_updateWebViewResultSent ||
// baseUpdate instanceof TLRPC.TL_updateAttachMenuBots ||
// baseUpdate instanceof TLRPC.TL_updateBotMenuButton ||
// baseUpdate instanceof TLRPC.TL_updatePeerHistoryTTL ||
// baseUpdate instanceof TLRPC.TL_updatePendingJoinRequests ||
// baseUpdate instanceof TLRPC.TL_updateSavedRingtones ||
// baseUpdate instanceof TLRPC.TL_updateTranscribedAudio ||
// baseUpdate instanceof TLRPC.TL_updateTranscribeAudio ||
// baseUpdate instanceof TLRPC.TL_updateChannelViewForumAsMessages ||
// baseUpdate instanceof TLRPC.TL_updatePinnedSavedDialogs ||
// baseUpdate instanceof TLRPC.TL_updateSavedDialogPinned ||
// baseUpdate instanceof TLRPC.TL_updateNewAuthorization ||
// baseUpdate instanceof TLRPC.TL_updateNotifySettings ||
// baseUpdate instanceof TL_stories.TL_updateStoriesStealthMode ||
// baseUpdate instanceof TLRPC.TL_updateDialogPinned ||
// baseUpdate instanceof TLRPC.TL_updatePinnedDialogs ||
// baseUpdate instanceof TLRPC.TL_updatePrivacy
// ) {
// if (updatesOnMainThread == null) {
// updatesOnMainThread = new ArrayList<>();
// }
// updatesOnMainThread.add(baseUpdate);
} else {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
@ -17661,6 +17658,8 @@ public class MessagesController extends BaseController implements NotificationCe
}
} else if (baseUpdate instanceof TLRPC.TL_updatePinnedSavedDialogs || baseUpdate instanceof TLRPC.TL_updateSavedDialogPinned) {
getSavedMessagesController().processUpdate(baseUpdate);
} else if (ApplicationLoader.applicationLoaderInstance != null) {
ApplicationLoader.applicationLoaderInstance.processUpdate(currentAccount, baseUpdate);
}
}
if (editor != null) {

View file

@ -1363,6 +1363,8 @@ public class MessagesStorage extends BaseController {
database.executeFast("DELETE FROM story_pushes").stepThis().dispose();
database.executeFast("DELETE FROM dialog_photos").stepThis().dispose();
database.executeFast("DELETE FROM dialog_photos_count").stepThis().dispose();
database.executeFast("DELETE FROM saved_reaction_tags").stepThis().dispose();
cursor = database.queryFinalized("SELECT did FROM dialogs WHERE 1");
while (cursor.next()) {
@ -14835,6 +14837,9 @@ public class MessagesStorage extends BaseController {
}
}
}
if (message.media.storyItem != null && message.media.storyItem.from_id != null) {
addLoadPeerInfo(message.media.storyItem.from_id, usersToLoad, chatsToLoad);
}
}
if (message.media instanceof TLRPC.TL_messageMediaWebPage && message.media.webpage != null && message.media.webpage.attributes != null) {
for (int i = 0; i < message.media.webpage.attributes.size(); ++i) {
@ -14852,6 +14857,9 @@ public class MessagesStorage extends BaseController {
}
}
}
if (attr.storyItem != null && attr.storyItem.from_id != null) {
addLoadPeerInfo(attr.storyItem.from_id, usersToLoad, chatsToLoad);
}
}
}
}
@ -15246,7 +15254,6 @@ public class MessagesStorage extends BaseController {
}
public static void createFirstHoles(long did, SQLitePreparedStatement state5, SQLitePreparedStatement state6, int messageId, long topicId) throws Exception {
FileLog.d("createFirstHoles " + did + " " + messageId + " " + topicId);
state5.requery();
int pointer = 1;
state5.bindLong(pointer++, did);

View file

@ -9,7 +9,6 @@
package org.telegram.messenger;
import android.os.SystemClock;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
@ -231,7 +230,12 @@ public class NotificationCenter {
public static final int userIsPremiumBlockedUpadted = totalEvents++;
public static final int savedMessagesForwarded = totalEvents++;
public static final int emojiKeywordsLoaded = totalEvents++;
public static final int smsJobStatusUpdate = totalEvents++;
public static final int storyQualityUpdate = totalEvents++;
public static final int openBoostForUsersDialog = totalEvents++;
public static final int groupRestrictionsUnlockedByBoosts = totalEvents++;
public static final int chatWasBoostedByUser = totalEvents++;
public static final int groupPackUpdated = totalEvents++;
//global
public static final int pushMessagesUpdated = totalEvents++;

View file

@ -150,6 +150,10 @@ public class PushListenerController {
jsonString = new String(strBytes);
JSONObject json = new JSONObject(jsonString);
if (ApplicationLoader.applicationLoaderInstance != null && ApplicationLoader.applicationLoaderInstance.consumePush(currentAccount, json)) {
return;
}
if (json.has("loc_key")) {
loc_key = json.getString("loc_key");
} else {

View file

@ -492,11 +492,11 @@ public class SavedMessagesController {
}
}
if (d != null) {
if (Math.max(0, d.messagesCount - ids.size()) != d.messagesCount) {
if (d.messagesCountLoaded && Math.max(0, d.messagesCount - ids.size()) != d.messagesCount) {
d.messagesCount = Math.max(0, d.messagesCount - ids.size());
changed = true;
}
if (d.messagesCount <= 0) {
if (d.messagesCountLoaded && d.messagesCount <= 0) {
removeDialog(d.dialogId);
changed = true;
} else if (d.top_message_id <= maxId) {

View file

@ -132,7 +132,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
public TLRPC.InputReplyTo createReplyInput(TL_stories.StoryItem storyItem) {
TLRPC.TL_inputReplyToStory replyTo = new TLRPC.TL_inputReplyToStory();
replyTo.story_id = storyItem.id;
replyTo.user_id = getMessagesController().getInputUser(storyItem.dialogId);
replyTo.peer = getMessagesController().getInputPeer(storyItem.dialogId);
return replyTo;
}
@ -3840,7 +3840,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
if (replyToStoryItem != null) {
newMsg.reply_to = new TLRPC.TL_messageReplyStoryHeader();
newMsg.reply_to.story_id = replyToStoryItem.id;
newMsg.reply_to.user_id = replyToStoryItem.dialogId;
newMsg.reply_to.peer = getMessagesController().getPeer(replyToStoryItem.dialogId);
newMsg.replyStory = replyToStoryItem;
newMsg.flags |= TLRPC.MESSAGE_FLAG_REPLY;
} else if (replyToMsg != null && (replyToTopMsg == null || replyToMsg != replyToTopMsg || replyToTopMsg.getId() != 1)) {

View file

@ -254,6 +254,7 @@ public class SharedConfig {
public static boolean forceDisableTabletMode;
public static boolean updateStickersOrderOnSend = true;
public static boolean bigCameraForRound;
public static boolean useCamera2;
public static boolean useSurfaceInStories;
public static boolean photoViewerBlur = true;
public static boolean payByInvoice;
@ -642,6 +643,7 @@ public class SharedConfig {
updateStickersOrderOnSend = preferences.getBoolean("updateStickersOrderOnSend", true);
dayNightWallpaperSwitchHint = preferences.getInt("dayNightWallpaperSwitchHint", 0);
bigCameraForRound = preferences.getBoolean("bigCameraForRound", false);
useCamera2 = preferences.getBoolean("useCamera2", false);
useSurfaceInStories = preferences.getBoolean("useSurfaceInStories", Build.VERSION.SDK_INT >= 30);
payByInvoice = preferences.getBoolean("payByInvoice", false);
photoViewerBlur = preferences.getBoolean("photoViewerBlur", true);
@ -1737,6 +1739,13 @@ public class SharedConfig {
.apply();
}
public static void toggleUseCamera2() {
ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE)
.edit()
.putBoolean("useCamera2", useCamera2 = !useCamera2)
.apply();
}
@Deprecated
public static int getLegacyDevicePerformanceClass() {

View file

@ -0,0 +1,538 @@
package org.telegram.messenger.camera;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.util.Size;
import android.util.SizeF;
import android.view.Surface;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class Camera2Session {
private boolean isError;
private boolean isSuccess;
private boolean isClosed;
private final CameraManager cameraManager;
private final boolean isFront;
public final String cameraId;
private CameraCharacteristics cameraCharacteristics;
private HandlerThread thread;
private Handler handler;
private CameraDevice cameraDevice;
private SurfaceTexture surfaceTexture;
private CameraCaptureSession captureSession;
private Surface surface;
private final CameraDevice.StateCallback cameraStateCallback;
private final CameraCaptureSession.StateCallback captureStateCallback;
private CaptureRequest.Builder captureRequestBuilder;
private Rect sensorSize;
private float maxZoom = 1f;
private float currentZoom = 1f;
private final Size previewSize;
private ImageReader imageReader;
private long lastTime;
public static Camera2Session create(boolean round, boolean front, int viewWidth, int viewHeight) {
final Context context = ApplicationLoader.applicationContext;
final CameraManager cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
float bestAspectRatio = 0;
Size bestSize = null;
String cameraId = null;
try {
String[] cameraIds = cameraManager.getCameraIdList();
for (int i = 0; i < cameraIds.length; ++i) {
final String id = cameraIds[i];
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(id);
if (characteristics == null) continue;
if (characteristics.get(CameraCharacteristics.LENS_FACING) != (front ? CameraCharacteristics.LENS_FACING_FRONT : CameraCharacteristics.LENS_FACING_BACK)) {
continue;
}
StreamConfigurationMap confMap = (StreamConfigurationMap) characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size pixelSize = characteristics.get(CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE);
float cameraAspectRatio = pixelSize == null ? 0 : (float) pixelSize.getWidth() / pixelSize.getHeight();
final Size targetAspectRatio = round ? new Size(1, 1) : new Size(9, 16);
final int targetWidth = round ? MessagesController.getInstance(UserConfig.selectedAccount).roundVideoSize : viewWidth;
final int targetHeight = round ? MessagesController.getInstance(UserConfig.selectedAccount).roundVideoSize : viewHeight;
if (bestAspectRatio <= 0 || Math.abs((float) targetAspectRatio.getWidth() / targetAspectRatio.getHeight() - bestAspectRatio) > Math.abs((float) targetAspectRatio.getWidth() / targetAspectRatio.getHeight() - cameraAspectRatio)) {
if (confMap != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Size size = chooseOptimalSize(confMap.getOutputSizes(SurfaceTexture.class), targetWidth, targetHeight, targetAspectRatio, false);
if (size != null) {
bestAspectRatio = cameraAspectRatio;
cameraId = id;
bestSize = size;
}
}
} else {
}
}
} catch (Exception e) {
FileLog.e(e);
}
if (cameraId == null || bestSize == null) {
return null;
}
return new Camera2Session(context, front, cameraId, bestSize);
}
private Camera2Session(Context context, boolean isFront, String cameraId, Size size) {
thread = new HandlerThread("tg_camera2");
thread.start();
handler = new Handler(thread.getLooper());
cameraStateCallback = new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
Camera2Session.this.cameraDevice = camera;
Camera2Session.this.lastTime = System.currentTimeMillis();
FileLog.d("Camera2Session camera #" + cameraId + " opened");
checkOpen();
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
Camera2Session.this.cameraDevice = camera;
FileLog.d("Camera2Session camera #" + cameraId + " disconnected");
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
Camera2Session.this.cameraDevice = camera;
FileLog.e("Camera2Session camera #" + cameraId + " received " + error + " error");
AndroidUtilities.runOnUIThread(() -> {
isError = true;
});
}
};
captureStateCallback = new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
captureSession = session;
FileLog.e("Camera2Session camera #" + cameraId + " capture session configured");
Camera2Session.this.lastTime = System.currentTimeMillis();
try {
updateCaptureRequest();
AndroidUtilities.runOnUIThread(() -> {
isSuccess = true;
if (doneCallback != null) {
doneCallback.run();
doneCallback = null;
}
});
} catch (Exception e) {
FileLog.e(e);
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
captureSession = session;
FileLog.e("Camera2Session camera #" + cameraId + " capture session failed to configure");
AndroidUtilities.runOnUIThread(() -> {
isError = true;
});
}
};
this.isFront = isFront;
this.cameraId = cameraId;
this.previewSize = size;
this.lastTime = System.currentTimeMillis();
this.imageReader = ImageReader.newInstance(size.getWidth(), size.getHeight(), ImageFormat.JPEG, 1);
cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
try {
cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
sensorSize = cameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
final Float value = cameraCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
maxZoom = (value == null || value < 1f) ? 1f : value;
cameraManager.openCamera(cameraId, cameraStateCallback, handler);
} catch (Exception e) {
FileLog.e(e);
AndroidUtilities.runOnUIThread(() -> {
isError = true;
});
}
}
private Runnable doneCallback;
public void whenDone(Runnable doneCallback) {
if (isInitiated()) {
doneCallback.run();
this.doneCallback = null;
} else {
this.doneCallback = doneCallback;
}
}
public void open(SurfaceTexture surfaceTexture) {
handler.post(() -> {
this.surfaceTexture = surfaceTexture;
if (surfaceTexture != null) {
surfaceTexture.setDefaultBufferSize(getPreviewWidth(), getPreviewHeight());
}
checkOpen();
});
}
private boolean opened = false;
private void checkOpen() {
if (opened) return;
if (surfaceTexture == null || cameraDevice == null) return;
opened = true;
surface = new Surface(surfaceTexture);
try {
ArrayList<Surface> surfaces = new ArrayList<>();
surfaces.add(surface);
surfaces.add(imageReader.getSurface());
cameraDevice.createCaptureSession(surfaces, captureStateCallback, null);
} catch (Exception e) {
FileLog.e(e);
AndroidUtilities.runOnUIThread(() -> {
isError = true;
});
}
}
public boolean isInitiated() {
return !isError && isSuccess && !isClosed;
}
public int getDisplayOrientation() {
// TODO
return 0;
}
public int getWorldAngle() {
// TODO
return 0;
}
public int getCurrentOrientation() {
// TODO
return 0;
}
private final Rect cropRegion = new Rect();
public void setZoom(float value) {
if (!isInitiated()) return;
if (captureRequestBuilder == null || cameraDevice == null || sensorSize == null) return;
currentZoom = Utilities.clamp(value, maxZoom, 1f);
updateCaptureRequest();
try {
captureSession.setRepeatingRequest(captureRequestBuilder.build(), null, handler);
} catch (Exception e) {
FileLog.e(e);
}
}
public float getZoom() {
return currentZoom;
}
public float getMaxZoom() {
return maxZoom;
}
public float getMinZoom() {
// TODO: support wide zoom camera switching
return 1f;
}
public int getPreviewWidth() {
return previewSize.getWidth();
}
public int getPreviewHeight() {
return previewSize.getHeight();
}
public void destroy(boolean async) {
destroy(async, null);
}
public void destroy(boolean async, Runnable afterCallback) {
isClosed = true;
if (async) {
handler.post(() -> {
if (captureSession != null) {
captureSession.close();
captureSession = null;
}
if (cameraDevice != null) {
cameraDevice.close();
cameraDevice = null;
}
if (imageReader != null) {
imageReader.close();
imageReader = null;
}
AndroidUtilities.runOnUIThread(() -> {
thread.quitSafely();
try {
thread.join();
} catch (Exception e) {
FileLog.e(e);
}
if (afterCallback != null) {
afterCallback.run();
}
});
});
} else {
if (captureSession != null) {
captureSession.close();
captureSession = null;
}
if (cameraDevice != null) {
cameraDevice.close();
cameraDevice = null;
}
if (imageReader != null) {
imageReader.close();
imageReader = null;
}
thread.quitSafely();
try {
thread.join();
} catch (Exception e) {
FileLog.e(e);
}
if (afterCallback != null) {
AndroidUtilities.runOnUIThread(afterCallback);
}
}
}
private boolean recordingVideo;
public void setRecordingVideo(boolean recording) {
if (recordingVideo != recording) {
recordingVideo = recording;
updateCaptureRequest();
}
}
private boolean scanningBarcode;
public void setScanningBarcode(boolean scanning) {
if (scanningBarcode != scanning) {
scanningBarcode = scanning;
updateCaptureRequest();
}
}
private boolean nightMode;
public void setNightMode(boolean enable) {
if (nightMode != enable) {
nightMode = enable;
updateCaptureRequest();
}
}
private void updateCaptureRequest() {
if (cameraDevice == null || surface == null || captureSession == null) return;
try {
int template;
if (recordingVideo) {
template = CameraDevice.TEMPLATE_RECORD;
} else if (scanningBarcode) {
template = CameraDevice.TEMPLATE_STILL_CAPTURE;
} else {
template = CameraDevice.TEMPLATE_PREVIEW;
}
captureRequestBuilder = cameraDevice.createCaptureRequest(template);
if (scanningBarcode) {
captureRequestBuilder.set(CaptureRequest.CONTROL_SCENE_MODE, CameraMetadata.CONTROL_SCENE_MODE_BARCODE);
} else if (nightMode) {
captureRequestBuilder.set(CaptureRequest.CONTROL_SCENE_MODE, isFront ? CameraMetadata.CONTROL_SCENE_MODE_NIGHT_PORTRAIT : CameraMetadata.CONTROL_SCENE_MODE_NIGHT);
}
if (sensorSize != null && Math.abs(currentZoom - 1f) >= 0.01f) {
final int centerX = sensorSize.width() / 2;
final int centerY = sensorSize.height() / 2;
final int deltaX = (int) ((0.5f * sensorSize.width()) / currentZoom);
final int deltaY = (int) ((0.5f * sensorSize.height()) / currentZoom);
cropRegion.set(
centerX - deltaX,
centerY - deltaY,
centerX + deltaX,
centerY + deltaY
);
captureRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, cropRegion);
}
captureRequestBuilder.addTarget(surface);
captureSession.setRepeatingRequest(captureRequestBuilder.build(), null, handler);
} catch (Exception e) {
FileLog.e("Camera2Sessions setRepeatingRequest error in updateCaptureRequest", e);
}
}
public boolean takePicture(final File file, Utilities.Callback<Integer> whenDone) {
if (cameraDevice == null || captureSession == null) return false;
try {
CaptureRequest.Builder captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
FileOutputStream output = null;
try {
output = new FileOutputStream(file);
output.write(bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
image.close();
if (null != output) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
AndroidUtilities.runOnUIThread(() -> {
if (whenDone != null) {
whenDone.run(0);
}
});
}
}, null);
if (scanningBarcode) {
captureRequestBuilder.set(CaptureRequest.CONTROL_SCENE_MODE, CameraMetadata.CONTROL_SCENE_MODE_BARCODE);
}
captureRequestBuilder.addTarget(imageReader.getSurface());
captureSession.capture(captureRequestBuilder.build(), new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureStarted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, long timestamp, long frameNumber) {
super.onCaptureStarted(session, request, timestamp, frameNumber);
}
@Override
public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) {
super.onCaptureProgressed(session, request, partialResult);
}
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
}
@Override
public void onCaptureFailed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureFailure failure) {
super.onCaptureFailed(session, request, failure);
}
@Override
public void onCaptureSequenceCompleted(@NonNull CameraCaptureSession session, int sequenceId, long frameNumber) {
super.onCaptureSequenceCompleted(session, sequenceId, frameNumber);
}
@Override
public void onCaptureSequenceAborted(@NonNull CameraCaptureSession session, int sequenceId) {
super.onCaptureSequenceAborted(session, sequenceId);
}
@Override
public void onCaptureBufferLost(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull Surface target, long frameNumber) {
super.onCaptureBufferLost(session, request, target, frameNumber);
}
}, null);
return true;
} catch (Exception e) {
FileLog.e("Camera2Sessions takePicture error", e);
return false;
}
}
public static Size chooseOptimalSize(Size[] choices, int width, int height, Size aspectRatio, boolean notBigger) {
List<Size> bigEnoughWithAspectRatio = new ArrayList<>(choices.length);
List<Size> bigEnough = new ArrayList<>(choices.length);
int w = aspectRatio.getWidth();
int h = aspectRatio.getHeight();
for (int a = 0; a < choices.length; a++) {
Size option = choices[a];
if (notBigger && (option.getHeight() > height || option.getWidth() > width)) {
continue;
}
if (option.getHeight() == option.getWidth() * h / w && option.getWidth() >= width && option.getHeight() >= height) {
bigEnoughWithAspectRatio.add(option);
} else if (option.getHeight() * option.getWidth() <= width * height * 4 && option.getWidth() >= width && option.getHeight() >= height) {
bigEnough.add(option);
}
}
if (bigEnoughWithAspectRatio.size() > 0) {
return Collections.min(bigEnoughWithAspectRatio, new CompareSizesByArea());
} else if (bigEnough.size() > 0) {
return Collections.min(bigEnough, new CompareSizesByArea());
} else {
return Collections.max(Arrays.asList(choices), new CompareSizesByArea());
}
}
static class CompareSizesByArea implements Comparator<Size> {
@Override
public int compare(Size lhs, Size rhs) {
return Long.signum((long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight());
}
}
}

View file

@ -401,90 +401,99 @@ public class CameraController implements MediaRecorder.OnInfoListener {
return value;
}
public boolean takePicture(final File path, final boolean ignoreOrientation, final CameraSession session, final Utilities.Callback<Integer> callback) {
if (session == null) {
public boolean takePicture(final File path, final boolean ignoreOrientation, final Object sessionObject, final Utilities.Callback<Integer> callback) {
if (sessionObject == null) {
return false;
}
final CameraInfo info = session.cameraInfo;
final boolean flipFront = session.isFlipFront();
Camera camera = info.camera;
try {
camera.takePicture(null, null, (data, camera1) -> {
Bitmap bitmap = null;
int orientation = 0;
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);
}
try {
orientation = getOrientation(data);
if (info.frontCamera != 0 && flipFront) {
try {
Matrix matrix = new Matrix();
if (!ignoreOrientation && orientation != -1) {
matrix.setRotate(orientation);
if (sessionObject instanceof CameraSession) {
CameraSession session = (CameraSession) sessionObject;
final CameraInfo info = session.cameraInfo;
final boolean flipFront = session.isFlipFront();
Camera camera = info.camera;
try {
camera.takePicture(null, null, (data, camera1) -> {
Bitmap bitmap = null;
int orientation = 0;
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);
}
try {
orientation = getOrientation(data);
if (info.frontCamera != 0 && flipFront) {
try {
Matrix matrix = new Matrix();
if (!ignoreOrientation && orientation != -1) {
matrix.setRotate(orientation);
}
orientation = 0;
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, false);
}
if (callback != null) {
callback.run(orientation);
}
return;
} catch (Throwable e) {
FileLog.e(e);
}
orientation = 0;
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, false);
}
if (callback != null) {
callback.run(orientation);
}
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, false);
}
} catch (Exception 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, false);
if (callback != null) {
callback.run(orientation);
}
} catch (Exception e) {
FileLog.e(e);
}
if (callback != null) {
callback.run(orientation);
}
});
return true;
} catch (Exception e) {
FileLog.e(e);
});
return true;
} catch (Exception e) {
FileLog.e(e);
}
return false;
} else if (sessionObject instanceof Camera2Session) {
Camera2Session session = (Camera2Session) sessionObject;
return session.takePicture(path, callback);
} else {
return false;
}
return false;
}
public void startPreview(final CameraSession session) {
if (session == null) {
public void startPreview(final Object sessionObject) {
if (sessionObject == null || !(sessionObject instanceof CameraSession)) {
return;
}
CameraSession session = (CameraSession) sessionObject;
threadPool.execute(() -> {
Camera camera = session.cameraInfo.camera;
try {
@ -503,10 +512,11 @@ public class CameraController implements MediaRecorder.OnInfoListener {
});
}
public void stopPreview(final CameraSession session) {
if (session == null) {
public void stopPreview(final Object sessionObject) {
if (sessionObject == null || !(sessionObject instanceof CameraSession)) {
return;
}
CameraSession session = (CameraSession) sessionObject;
threadPool.execute(() -> {
Camera camera = session.cameraInfo.camera;
try {
@ -615,39 +625,44 @@ public class CameraController implements MediaRecorder.OnInfoListener {
});
}
public void recordVideo(final CameraSession session, final File path, boolean mirror, final VideoTakeCallback callback, final Runnable onVideoStartRecord, ICameraView cameraView) {
public void recordVideo(final Object session, final File path, boolean mirror, final VideoTakeCallback callback, final Runnable onVideoStartRecord, ICameraView cameraView) {
recordVideo(session, path, mirror, callback, onVideoStartRecord, cameraView, true);
}
public void recordVideo(final CameraSession session, final File path, boolean mirror, final VideoTakeCallback callback, final Runnable onVideoStartRecord, ICameraView cameraView, boolean createThumbnail) {
if (session == null) {
public void recordVideo(final Object sessionObject, final File path, boolean mirror, final VideoTakeCallback callback, final Runnable onVideoStartRecord, ICameraView cameraView, boolean createThumbnail) {
if (sessionObject == null) {
return;
}
final CameraInfo info = session.cameraInfo;
final Camera camera = info.camera;
if (cameraView != null) {
recordingCurrentCameraView = cameraView;
onVideoTakeCallback = callback;
recordedFile = path.getAbsolutePath();
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);
session.onStartRecord();
} catch (Exception e) {
FileLog.e(e);
}
AndroidUtilities.runOnUIThread(() -> {
cameraView.startRecording(path, () -> finishRecordingVideo(createThumbnail));
if (onVideoStartRecord != null) {
onVideoStartRecord.run();
if (sessionObject instanceof CameraSession) {
CameraSession session = (CameraSession) sessionObject;
final CameraInfo info = session.cameraInfo;
final Camera camera = info.camera;
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);
session.onStartRecord();
} catch (Exception e) {
FileLog.e(e);
}
});
}
} else if (sessionObject instanceof Camera2Session) {
Camera2Session session = (Camera2Session) sessionObject;
session.setRecordingVideo(true);
}
AndroidUtilities.runOnUIThread(() -> {
cameraView.startRecording(path, () -> finishRecordingVideo(createThumbnail));
if (onVideoStartRecord != null) {
onVideoStartRecord.run();
}
});
} catch (Exception e) {
FileLog.e(e);
}
@ -656,60 +671,66 @@ public class CameraController implements MediaRecorder.OnInfoListener {
return;
}
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();
if (sessionObject instanceof CameraSession) {
CameraSession session = (CameraSession) sessionObject;
final CameraInfo info = session.cameraInfo;
final Camera camera = info.camera;
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 {
mirrorRecorderVideo = mirror;
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, false);
int bitrate;
if (Math.min(pictureSize.mHeight,pictureSize.mWidth) >= 720) {
bitrate = 3500000;
} else {
bitrate = 1800000;
}
recorder.setVideoEncodingBitRate(bitrate);
recorder.setVideoSize(pictureSize.getWidth(), pictureSize.getHeight());
recorder.setOnInfoListener(CameraController.this);
recorder.prepare();
recorder.start();
try {
mirrorRecorderVideo = mirror;
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, false);
int bitrate;
if (Math.min(pictureSize.mHeight, pictureSize.mWidth) >= 720) {
bitrate = 3500000;
} else {
bitrate = 1800000;
}
recorder.setVideoEncodingBitRate(bitrate);
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);
onVideoTakeCallback = callback;
recordedFile = path.getAbsolutePath();
if (onVideoStartRecord != null) {
AndroidUtilities.runOnUIThread(onVideoStartRecord);
}
} catch (Exception e) {
recorder.release();
recorder = null;
FileLog.e(e);
}
} catch (Exception e) {
recorder.release();
recorder = null;
FileLog.e(e);
}
} catch (Exception e) {
FileLog.e(e);
}
} catch (Exception e) {
FileLog.e(e);
}
});
});
} else {
return;
}
}
private void finishRecordingVideo(boolean createThumbnail) {
@ -796,11 +817,11 @@ public class CameraController implements MediaRecorder.OnInfoListener {
}
}
public void stopVideoRecording(final CameraSession session, final boolean abandon) {
stopVideoRecording(session, abandon, true);
public void stopVideoRecording(final Object sessionObject, final boolean abandon) {
stopVideoRecording(sessionObject, abandon, true);
}
public void stopVideoRecording(final CameraSession session, final boolean abandon, final boolean createThumbnail) {
public void stopVideoRecording(final Object sessionObject, final boolean abandon, final boolean createThumbnail) {
if (recordingCurrentCameraView != null) {
recordingCurrentCameraView.stopRecording();
recordingCurrentCameraView = null;
@ -808,9 +829,7 @@ public class CameraController implements MediaRecorder.OnInfoListener {
}
threadPool.execute(() -> {
try {
CameraInfo info = session.cameraInfo;
final Camera camera = info.camera;
if (camera != null && recorder != null) {
if (recorder != null) {
MediaRecorder tempRecorder = recorder;
recorder = null;
try {
@ -823,34 +842,44 @@ public class CameraController implements MediaRecorder.OnInfoListener {
} 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(() -> {
if (sessionObject instanceof CameraSession) {
CameraSession session = (CameraSession) sessionObject;
CameraInfo info = session.cameraInfo;
final Camera camera = info.camera;
if (camera != null) {
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(session.getCurrentFlashMode());
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(session.getCurrentFlashMode());
camera.setParameters(params);
} catch (Exception e) {
FileLog.e(e);
}
});
} else if (sessionObject instanceof Camera2Session) {
Camera2Session session = (Camera2Session) sessionObject;
session.setRecordingVideo(false);
}
if (!abandon && onVideoTakeCallback != null) {
finishRecordingVideo(createThumbnail);
} else {
@ -894,7 +923,7 @@ public class CameraController implements MediaRecorder.OnInfoListener {
}
public interface ErrorCallback {
public default void onError(int errorId, Camera camera, CameraSession cameraSession) {
public default void onError(int errorId, Camera camera, CameraSessionWrapper cameraSession) {
}
}
@ -920,7 +949,7 @@ public class CameraController implements MediaRecorder.OnInfoListener {
for (int i = 0; i < errorCallbacks.size(); ++i) {
ErrorCallback callback = errorCallbacks.get(i);
if (callback != null) {
callback.onError(errorId, camera, session);
callback.onError(errorId, camera, CameraSessionWrapper.of(session));
}
}
}

View file

@ -0,0 +1,206 @@
package org.telegram.messenger.camera;
import android.hardware.Camera;
import androidx.annotation.Nullable;
import org.telegram.messenger.AndroidUtilities;
import java.util.concurrent.CountDownLatch;
public class CameraSessionWrapper {
public CameraSession camera1Session;
public Camera2Session camera2Session;
public boolean isInitiated() {
if (camera2Session != null) {
return camera2Session.isInitiated();
} else if (camera1Session != null) {
return camera1Session.isInitied();
} else {
return false;
}
}
public int getWorldAngle() {
if (camera2Session != null) {
return camera2Session.getWorldAngle();
} else if (camera1Session != null) {
return camera1Session.getWorldAngle();
} else {
return 0;
}
}
public int getCurrentOrientation() {
if (camera2Session != null) {
return camera2Session.getCurrentOrientation();
} else if (camera1Session != null) {
return camera1Session.getCurrentOrientation();
} else {
return 0;
}
}
public int getDisplayOrientation() {
if (camera2Session != null) {
return camera2Session.getDisplayOrientation();
} else if (camera1Session != null) {
return camera1Session.getDisplayOrientation();
} else {
return 0;
}
}
@Deprecated
public int getCameraId() {
if (camera2Session != null) {
return camera2Session.cameraId.hashCode();
} else if (camera1Session != null) {
return camera1Session.cameraInfo.cameraId;
} else {
return 0;
}
}
public void stopVideoRecording() {
if (camera2Session != null) {
camera2Session.setRecordingVideo(false);
} else if (camera1Session != null) {
camera1Session.stopVideoRecording();
}
}
public void setOptimizeForBarcode(boolean optimize) {
if (camera2Session != null) {
camera2Session.setScanningBarcode(optimize);
} else if (camera1Session != null) {
camera1Session.setOptimizeForBarcode(optimize);
}
}
public void setCurrentFlashMode(String flashMode) {
if (camera2Session != null) {
// TODO
} else if (camera1Session != null) {
camera1Session.setCurrentFlashMode(flashMode);
}
}
public String getCurrentFlashMode() {
if (camera2Session != null) {
// TODO
return Camera.Parameters.FLASH_MODE_OFF;
} else if (camera1Session != null) {
return camera1Session.getNextFlashMode();
}
return null;
}
public String getNextFlashMode() {
if (camera2Session != null) {
// TODO
return Camera.Parameters.FLASH_MODE_OFF;
} else if (camera1Session != null) {
return camera1Session.getNextFlashMode();
}
return null;
}
public boolean hasFlashModes() {
if (camera2Session != null) {
// TODO
return false;
} else if (camera1Session != null) {
return !camera1Session.availableFlashModes.isEmpty();
}
return false;
}
public void setFlipFront(boolean flip) {
if (camera2Session != null) {
// TODO
} else if (camera1Session != null) {
camera1Session.setFlipFront(flip);
}
}
public boolean isSameTakePictureOrientation() {
if (camera2Session != null) {
// TODO
} else if (camera1Session != null) {
return camera1Session.isSameTakePictureOrientation();
}
return true;
}
public void updateRotation() {
if (camera2Session != null) {
// TODO
} else if (camera1Session != null) {
camera1Session.updateRotation();
}
}
public void setZoom(float zoom) {
if (camera2Session != null) {
camera2Session.setZoom(AndroidUtilities.lerp(camera2Session.getMinZoom(), camera2Session.getMaxZoom(), zoom));
} else if (camera1Session != null) {
camera1Session.setZoom(zoom);
}
}
public void focusToRect(android.graphics.Rect focusRect, android.graphics.Rect meteringRect) {
if (camera2Session != null) {
// TODO
} else if (camera1Session != null) {
camera1Session.focusToRect(focusRect, meteringRect);
}
}
public void destroy(boolean async, Runnable before, Runnable after) {
if (camera2Session != null) {
if (before != null) {
before.run();
}
camera2Session.destroy(async, after);
} else if (camera1Session != null) {
CameraController.getInstance().close(camera1Session, !async ? new CountDownLatch(1) : null, before, after);
}
}
public Object getObject() {
if (camera2Session != null) {
return camera2Session;
} else if (camera1Session != null) {
return camera1Session;
}
return null;
}
public static CameraSessionWrapper of(CameraSession session) {
CameraSessionWrapper wrapper = new CameraSessionWrapper();
wrapper.camera1Session = session;
return wrapper;
}
public static CameraSessionWrapper of(Camera2Session session) {
CameraSessionWrapper wrapper = new CameraSessionWrapper();
wrapper.camera2Session = session;
return wrapper;
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof CameraSession) {
return obj == camera1Session;
} else if (obj instanceof Camera2Session) {
return obj == camera2Session;
} else if (obj instanceof CameraSessionWrapper) {
CameraSessionWrapper wrapper = (CameraSessionWrapper) obj;
return wrapper == this || wrapper.camera1Session == camera1Session && wrapper.camera2Session == camera2Session;
}
return false;
}
}

View file

@ -98,7 +98,7 @@ import javax.microedition.khronos.egl.EGLSurface;
import javax.microedition.khronos.opengles.GL;
@SuppressLint("NewApi")
public class CameraView extends FrameLayout implements TextureView.SurfaceTextureListener, CameraController.ICameraView {
public class CameraView extends FrameLayout implements TextureView.SurfaceTextureListener, CameraController.ICameraView, CameraController.ErrorCallback {
public boolean WRITE_TO_FILE_IN_BACKGROUND = false;
@ -110,7 +110,6 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
private boolean lazy;
private TextureView textureView;
private ImageView blurredStubView;
private CameraSession[] cameraSession = new CameraSession[2];
private boolean inited;
private CameraViewDelegate delegate;
private int clipTop;
@ -121,6 +120,10 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
private int focusAreaSize;
private Drawable thumbDrawable;
private final boolean useCamera2 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && SharedConfig.useCamera2;
private final CameraSessionWrapper[] cameraSession = new CameraSessionWrapper[2];
private CameraSessionWrapper cameraSessionRecording;
private boolean useMaxPreview;
private long lastDrawTime;
@ -162,8 +165,6 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
Runnable onRecordingFinishRunnable;
private CameraSession cameraSessionRecording;
public boolean startRecording(File path, Runnable onFinished) {
cameraSessionRecording = cameraSession[0];
cameraThread.startRecording(path);
@ -267,7 +268,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
return;
}
closingDualCamera = true;
CameraController.getInstance().close(cameraSession[1], null, null, () -> {
cameraSession[1].destroy(false, null, () -> {
closingDualCamera = false;
enableDualInternal();
});
@ -283,11 +284,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
if (handler != null) {
cameraThread.sendMessage(handler.obtainMessage(cameraThread.BLUR_CAMERA1), 0);
}
CameraController.getInstance().close(cameraSession[0], null, null, () -> {
// inited = false;
// synchronized (layoutLock) {
// firstFrameRendered = false;
// }
cameraSession[0].destroy(false, null, () -> {
initFirstCameraAfterSecond = true;
updateCameraInfoSize(1);
if (handler != null) {
@ -322,7 +319,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
}
enableDualInternal();
} else {
if (cameraSession[1] == null || !cameraSession[1].isInitied()) {
if (cameraSession[1] == null || !cameraSession[1].isInitiated()) {
dual = !dual;
return;
}
@ -331,7 +328,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
if (cameraSessionRecording == cameraSession[1]) {
cameraSessionRecording = null;
}
CameraController.getInstance().close(cameraSession[1], null, null, () -> {
cameraSession[1].destroy(false, null, () -> {
closingDualCamera = false;
dualCameraAppeared = false;
addToDualWait(400L);
@ -390,6 +387,9 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
public CameraView(Context context, boolean frontface, boolean lazy) {
super(context, null);
CameraController.getInstance().addOnErrorListener(this);
initialFrontface = isFrontface = frontface;
textureView = new TextureView(context);
if (!(this.lazy = lazy)) {
@ -603,7 +603,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
pictureSize[0] = pictureSize[1];
pictureSize[1] = pictureSize0;
CameraSession cameraSession0 = cameraSession[0];
CameraSessionWrapper cameraSession0 = cameraSession[0];
cameraSession[0] = cameraSession[1];
cameraSession[1] = cameraSession0;
@ -620,7 +620,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
if (cameraSessionRecording == cameraSession[0]) {
cameraSessionRecording = null;
}
CameraController.getInstance().close(cameraSession[0], null, null, () -> {
cameraSession[0].destroy(false, null, () -> {
inited = false;
synchronized (layoutLock) {
firstFrameRendered = false;
@ -642,7 +642,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
if (handler != null) {
cameraThread.sendMessage(handler.obtainMessage(cameraThread.BLUR_CAMERA1), 0);
}
CameraController.getInstance().close(cameraSession[0], null, null, () -> {
cameraSession[0].destroy(false, null, () -> {
inited = false;
synchronized (layoutLock) {
firstFrameRendered = false;
@ -770,17 +770,17 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
cameraThread.postRunnable(() -> this.cameraThread = null);
}
if (cameraSession[0] != null) {
CameraController.getInstance().close(cameraSession[0], null, null);
cameraSession[0].destroy(false, null, null);
}
if (cameraSession[1] != null) {
CameraController.getInstance().close(cameraSession[1], null, null);
cameraSession[1].destroy(false, null, null);
}
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
if (!inited && cameraSession[0] != null && cameraSession[0].isInitied()) {
if (!inited && cameraSession[0] != null && cameraSession[0].isInitiated()) {
if (delegate != null) {
delegate.onCameraInit();
}
@ -931,25 +931,30 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
return inited;
}
public CameraSession getCameraSession() {
public CameraSessionWrapper getCameraSession() {
return getCameraSession(0);
}
public CameraSession getCameraSession(int i) {
public Object getCameraSessionObject() {
if (cameraSession[0] == null) return null;
return cameraSession[0].getObject();
}
public CameraSessionWrapper getCameraSession(int i) {
return cameraSession[i];
}
public CameraSession getCameraSessionRecording() {
public CameraSessionWrapper getCameraSessionRecording() {
return cameraSessionRecording;
}
public void destroy(boolean async, final Runnable beforeDestroyRunnable) {
for (int i = 0; i < 2; ++i) {
if (cameraSession[i] != null) {
cameraSession[i].destroy();
CameraController.getInstance().close(cameraSession[i], !async ? new CountDownLatch(1) : null, beforeDestroyRunnable);
cameraSession[i].destroy(async, beforeDestroyRunnable, null);
}
}
CameraController.getInstance().removeOnErrorListener(this);
}
public Matrix getMatrix() {
@ -1068,7 +1073,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
private EGLConfig eglConfig;
private boolean initied;
private CameraSession currentSession[] = new CameraSession[2];
private final CameraSessionWrapper currentSession[] = new CameraSessionWrapper[2];
private final SurfaceTexture[] cameraSurface = new SurfaceTexture[2];
@ -1381,7 +1386,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
}
}
public void setCurrentSession(CameraSession session, int i) {
public void setCurrentSession(CameraSessionWrapper session, int i) {
Handler handler = getHandler();
if (handler != null) {
sendMessage(handler.obtainMessage(DO_SETSESSION_MESSAGE, i, 0, session), 0);
@ -1460,7 +1465,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
}
}
if (currentSession[0] == null || currentSession[0].cameraInfo.cameraId != cameraId1) {
if (currentSession[0] == null || currentSession[0].getCameraId() != cameraId1) {
return;
}
@ -1497,7 +1502,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
if (cameraSurface[i] == null) {
continue;
}
if (i != 0 && (currentSession[i] == null || !currentSession[i].isInitied()) || i == 0 && cameraId1 < 0 && !dual || i == 1 && cameraId2 < 0) {
if (i != 0 && (currentSession[i] == null || !currentSession[i].isInitiated()) || i == 0 && cameraId1 < 0 && !dual || i == 1 && cameraId2 < 0) {
continue;
}
@ -1677,13 +1682,13 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
}
case DO_SETSESSION_MESSAGE: {
final int i = inputMessage.arg1;
CameraSession newSession = (CameraSession) inputMessage.obj;
CameraSessionWrapper newSession = (CameraSessionWrapper) inputMessage.obj;
if (newSession == null) {
return;
}
if (currentSession[i] != newSession) {
currentSession[i] = newSession;
cameraId[i] = newSession.cameraInfo.cameraId;
cameraId[i] = newSession.getCameraId();
}
// currentSession[i].updateRotation();
int rotationAngle = currentSession[i].getWorldAngle();
@ -1752,7 +1757,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
cameraId[0] = cameraId[1];
cameraId[1] = cameraId0;
CameraSession cameraSession0 = currentSession[0];
CameraSessionWrapper cameraSession0 = currentSession[0];
currentSession[0] = currentSession[1];
currentSession[1] = cameraSession0;
@ -1935,39 +1940,58 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
return;
}
if (BuildVars.LOGS_ENABLED) {
FileLog.d("CameraView " + "create camera session " + i);
FileLog.d("CameraView " + "create camera"+(useCamera2 ? "2" : "")+" session " + i);
}
if (previewSize[i] == null) {
updateCameraInfoSize(i);
}
if (previewSize[i] == null) {
return;
}
surfaceTexture.setDefaultBufferSize(previewSize[i].getWidth(), previewSize[i].getHeight());
cameraSession[i] = new CameraSession(info[i], previewSize[i], pictureSize[i], ImageFormat.JPEG, false);
cameraSession[i].setCurrentFlashMode(Camera.Parameters.FLASH_MODE_OFF);
cameraThread.setCurrentSession(cameraSession[i], i);
requestLayout();
CameraController.getInstance().open(cameraSession[i], surfaceTexture, () -> {
if (cameraSession[i] != null) {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("CameraView " + "camera initied " + i);
}
cameraSession[i].setInitied();
if (useCamera2) {
Camera2Session session = Camera2Session.create(false, i == 0 ? isFrontface : !isFrontface, surfaceWidth, surfaceHeight);
if (session == null) return;
cameraSession[i] = CameraSessionWrapper.of(session);
cameraThread.setCurrentSession(cameraSession[i], i);
session.whenDone(() -> {
requestLayout();
if (dual && i == 1 && initFirstCameraAfterSecond) {
initFirstCameraAfterSecond = false;
AndroidUtilities.runOnUIThread(() -> {
updateCameraInfoSize(0);
cameraThread.reinitForNewCamera();
addToDualWait(350L);
});
}
});
session.open(surfaceTexture);
} else {
if (previewSize[i] == null) {
updateCameraInfoSize(i);
}
if (previewSize[i] == null) {
return;
}
surfaceTexture.setDefaultBufferSize(previewSize[i].getWidth(), previewSize[i].getHeight());
CameraSession session = new CameraSession(info[i], previewSize[i], pictureSize[i], ImageFormat.JPEG, false);
session.setCurrentFlashMode(Camera.Parameters.FLASH_MODE_OFF);
cameraSession[i] = CameraSessionWrapper.of(session);
cameraThread.setCurrentSession(cameraSession[i], i);
requestLayout();
CameraController.getInstance().open(session, surfaceTexture, () -> {
if (cameraSession[i] != null) {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("CameraView " + "camera initied " + i);
}
session.setInitied();
requestLayout();
}
if (dual && i == 1 && initFirstCameraAfterSecond) {
initFirstCameraAfterSecond = false;
AndroidUtilities.runOnUIThread(() -> {
updateCameraInfoSize(0);
cameraThread.reinitForNewCamera();
addToDualWait(350L);
});
}
}, () -> cameraThread.setCurrentSession(cameraSession[i], i));
if (dual && i == 1 && initFirstCameraAfterSecond) {
initFirstCameraAfterSecond = false;
AndroidUtilities.runOnUIThread(() -> {
updateCameraInfoSize(0);
cameraThread.reinitForNewCamera();
addToDualWait(350L);
});
}
}, () -> cameraThread.setCurrentSession(cameraSession[i], i));
}
});
}
@ -3039,4 +3063,9 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
cameraThread.pause(600);
}
}
@Override
public void onError(int errorId, Camera camera, CameraSessionWrapper cameraSession) {
}
}

View file

@ -1,4 +0,0 @@
package org.telegram.messenger.camera;
public class DefaultCameraAPI {
}

View file

@ -77,7 +77,7 @@ public class TLRPC {
public static final int MESSAGE_FLAG_HAS_BOT_ID = 0x00000800;
public static final int MESSAGE_FLAG_EDITED = 0x00008000;
public static final int LAYER = 173;
public static final int LAYER = 175;
public static class TL_stats_megagroupStats extends TLObject {
public static final int constructor = 0xef7ff916;
@ -13103,7 +13103,9 @@ public class TLRPC {
public ChatReactions available_reactions;
public TL_stories.PeerStories stories;
public WallPaper wallpaper;
public int boosts_applied;
public int boosts_unrestrict;
public StickerSet emojiset;
public long inviterId; //custom
public int invitesCount; //custom
@ -13119,6 +13121,9 @@ public class TLRPC {
case TL_channelFull_layer167.constructor:
result = new TL_channelFull_layer167();
break;
case TL_channelFull_layer173.constructor:
result = new TL_channelFull_layer173();
break;
case 0xf2355507:
result = new TL_channelFull_layer162();
break;
@ -15567,6 +15572,302 @@ public class TLRPC {
}
public static class TL_channelFull extends ChatFull {
public static final int constructor = 0x44c054a7;
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_set_location = (flags & 65536) != 0;
has_scheduled = (flags & 524288) != 0;
can_view_stats = (flags & 1048576) != 0;
blocked = (flags & 4194304) != 0;
flags2 = stream.readInt32(exception);
can_delete_channel = (flags2 & 1) != 0;
antispam = (flags2 & 2) != 0;
participants_hidden = (flags2 & 4) != 0;
translations_disabled = (flags2 & 8) != 0;
stories_pinned_available = (flags2 & 32) != 0;
view_forum_as_messages = (flags2 & 64) != 0;
id = stream.readInt64(exception);
about = stream.readString(exception);
if ((flags & 1) != 0) {
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);
if ((flags & 8388608) != 0) {
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.readInt64(exception);
}
if ((flags & 16) != 0) {
migrated_from_max_id = stream.readInt32(exception);
}
if ((flags & 32) != 0) {
pinned_msg_id = stream.readInt32(exception);
}
if ((flags & 256) != 0) {
stickerset = StickerSet.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 512) != 0) {
available_min_id = stream.readInt32(exception);
}
if ((flags & 2048) != 0) {
folder_id = stream.readInt32(exception);
}
if ((flags & 16384) != 0) {
linked_chat_id = stream.readInt64(exception);
}
if ((flags & 32768) != 0) {
location = ChannelLocation.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 131072) != 0) {
slowmode_seconds = stream.readInt32(exception);
}
if ((flags & 262144) != 0) {
slowmode_next_send_date = stream.readInt32(exception);
}
if ((flags & 4096) != 0) {
stats_dc = stream.readInt32(exception);
}
pts = stream.readInt32(exception);
if ((flags & 2097152) != 0) {
call = TL_inputGroupCall.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 16777216) != 0) {
ttl_period = stream.readInt32(exception);
}
if ((flags & 33554432) != 0) {
magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
count = stream.readInt32(exception);
for (int a = 0; a < count; a++) {
pending_suggestions.add(stream.readString(exception));
}
}
if ((flags & 67108864) != 0) {
groupcall_default_join_as = Peer.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 134217728) != 0) {
theme_emoticon = stream.readString(exception);
}
if ((flags & 268435456) != 0) {
requests_pending = stream.readInt32(exception);
}
if ((flags & 268435456) != 0) {
magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
count = stream.readInt32(exception);
for (int a = 0; a < count; a++) {
recent_requesters.add(stream.readInt64(exception));
}
}
if ((flags & 536870912) != 0) {
default_send_as = Peer.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 1073741824) != 0) {
available_reactions = ChatReactions.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags2 & 16) != 0) {
stories = TL_stories.PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags2 & 128) != 0) {
wallpaper = WallPaper.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags2 & 256) != 0) {
boosts_applied = stream.readInt32(exception);
}
if ((flags2 & 512) != 0) {
boosts_unrestrict = stream.readInt32(exception);
}
if ((flags2 & 1024) != 0) {
emojiset = StickerSet.TLdeserialize(stream, stream.readInt32(exception), exception);
}
}
public void serializeToStream(AbstractSerializedData stream) {
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_set_location ? (flags | 65536) : (flags &~ 65536);
flags = has_scheduled ? (flags | 524288) : (flags &~ 524288);
flags = can_view_stats ? (flags | 1048576) : (flags &~ 1048576);
flags = blocked ? (flags | 4194304) : (flags &~ 4194304);
stream.writeInt32(flags);
flags2 = can_delete_channel ? (flags2 | 1) : (flags2 &~ 1);
flags2 = antispam ? (flags2 | 2) : (flags2 &~ 2);
flags2 = participants_hidden ? (flags2 | 4) : (flags2 &~ 4);
flags2 = translations_disabled ? (flags2 | 8) : (flags2 &~ 8);
flags2 = stories_pinned_available ? (flags2 | 32) : (flags2 &~ 32);
flags2 = view_forum_as_messages ? (flags2 | 64) : (flags2 &~ 64);
stream.writeInt32(flags2);
stream.writeInt64(id);
stream.writeString(about);
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);
if ((flags & 8388608) != 0) {
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.writeInt64(migrated_from_chat_id);
}
if ((flags & 16) != 0) {
stream.writeInt32(migrated_from_max_id);
}
if ((flags & 32) != 0) {
stream.writeInt32(pinned_msg_id);
}
if ((flags & 256) != 0) {
stickerset.serializeToStream(stream);
}
if ((flags & 512) != 0) {
stream.writeInt32(available_min_id);
}
if ((flags & 2048) != 0) {
stream.writeInt32(folder_id);
}
if ((flags & 16384) != 0) {
stream.writeInt64(linked_chat_id);
}
if ((flags & 32768) != 0) {
location.serializeToStream(stream);
}
if ((flags & 131072) != 0) {
stream.writeInt32(slowmode_seconds);
}
if ((flags & 262144) != 0) {
stream.writeInt32(slowmode_next_send_date);
}
if ((flags & 4096) != 0) {
stream.writeInt32(stats_dc);
}
stream.writeInt32(pts);
if ((flags & 2097152) != 0) {
call.serializeToStream(stream);
}
if ((flags & 16777216) != 0) {
stream.writeInt32(ttl_period);
}
if ((flags & 33554432) != 0) {
stream.writeInt32(0x1cb5c415);
count = pending_suggestions.size();
stream.writeInt32(count);
for (int a = 0; a < count; a++) {
stream.writeString(pending_suggestions.get(a));
}
}
if ((flags & 67108864) != 0) {
groupcall_default_join_as.serializeToStream(stream);
}
if ((flags & 134217728) != 0) {
stream.writeString(theme_emoticon);
}
if ((flags & 268435456) != 0) {
stream.writeInt32(requests_pending);
}
if ((flags & 268435456) != 0) {
stream.writeInt32(0x1cb5c415);
count = recent_requesters.size();
stream.writeInt32(count);
for (int a = 0; a < count; a++) {
stream.writeInt64(recent_requesters.get(a));
}
}
if ((flags & 536870912) != 0) {
default_send_as.serializeToStream(stream);
}
if ((flags & 1073741824) != 0) {
available_reactions.serializeToStream(stream);
}
if ((flags2 & 16) != 0) {
stories.serializeToStream(stream);
}
if ((flags2 & 128) != 0) {
wallpaper.serializeToStream(stream);
}
if ((flags2 & 256) != 0) {
stream.writeInt32(boosts_applied);
}
if ((flags2 & 512) != 0) {
stream.writeInt32(boosts_unrestrict);
}
if ((flags2 & 1024) != 0) {
emojiset.serializeToStream(stream);
}
}
}
public static class TL_channelFull_layer173 extends ChatFull {
public static final int constructor = 0xf2bcb6f;
public void readParams(AbstractSerializedData stream, boolean exception) {
@ -26725,6 +27026,9 @@ public class TLRPC {
case 0xb3a07661:
result = new TL_messageActionGroupCallScheduled();
break;
case TL_messageActionBoostApply.constructor:
result = new TL_messageActionBoostApply();
break;
case 0x8f31b327:
result = new TL_messageActionPaymentSentMe();
break;
@ -27784,6 +28088,21 @@ public class TLRPC {
}
}
public static class TL_messageActionBoostApply extends MessageAction {
public static final int constructor = 0xcc02aa6d;
public int boosts;
public void readParams(AbstractSerializedData stream, boolean exception) {
boosts = stream.readInt32(exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(boosts);
}
}
public static class TL_messageActionPaymentSentMe extends MessageAction {
public static final int constructor = 0x8f31b327;
@ -29645,7 +29964,7 @@ public class TLRPC {
public ArrayList<MessageEntity> quote_entities = new ArrayList<>();
public int quote_offset;
public long user_id;
public Peer peer;
public int story_id;
public static MessageReplyHeader TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
@ -29654,6 +29973,9 @@ public class TLRPC {
case TL_messageReplyStoryHeader.constructor:
result = new TL_messageReplyStoryHeader();
break;
case TL_messageReplyStoryHeader_layer174.constructor:
result = new TL_messageReplyStoryHeader_layer174();
break;
case TL_messageReplyHeader.constructor:
result = new TL_messageReplyHeader();
break;
@ -29677,17 +29999,33 @@ public class TLRPC {
}
}
public static class TL_messageReplyStoryHeader extends MessageReplyHeader {
public static class TL_messageReplyStoryHeader_layer174 extends TL_messageReplyStoryHeader {
public static final int constructor = 0x9c98bfc1;
public void readParams(AbstractSerializedData stream, boolean exception) {
user_id = stream.readInt64(exception);
peer = new TLRPC.TL_peerUser();
peer.user_id = stream.readInt64(exception);
story_id = stream.readInt32(exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt64(user_id);
stream.writeInt64(peer == null ? 0 : peer.user_id);
stream.writeInt32(story_id);
}
}
public static class TL_messageReplyStoryHeader extends MessageReplyHeader {
public static final int constructor = 0xe5af939;
public void readParams(AbstractSerializedData stream, boolean exception) {
peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception);
story_id = stream.readInt32(exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
peer.serializeToStream(stream);
stream.writeInt32(story_id);
}
}
@ -34635,6 +34973,9 @@ public class TLRPC {
result = new TL_updatePinnedSavedDialogs();
break;
}
if (result == null && ApplicationLoader.applicationLoaderInstance != null) {
result = ApplicationLoader.applicationLoaderInstance.parseTLUpdate(constructor);
}
if (result == null && exception) {
throw new RuntimeException(String.format("can't parse magic %x in Update", constructor));
}
@ -44985,6 +45326,9 @@ public class TLRPC {
case 0xb1c3caa7:
result = new TL_channelAdminLogEventActionChangeStickerSet();
break;
case TL_channelAdminLogEventActionChangeEmojiStickerSet.constructor:
result = new TL_channelAdminLogEventActionChangeEmojiStickerSet();
break;
case 0xf92424d2:
result = new TL_channelAdminLogEventActionParticipantMute();
break;
@ -45170,6 +45514,24 @@ public class TLRPC {
}
}
public static class TL_channelAdminLogEventActionChangeEmojiStickerSet extends ChannelAdminLogEventAction {
public static final int constructor = 0x46d840ab;
public InputStickerSet prev_stickerset;
public InputStickerSet new_stickerset;
public void readParams(AbstractSerializedData stream, boolean exception) {
prev_stickerset = InputStickerSet.TLdeserialize(stream, stream.readInt32(exception), exception);
new_stickerset = InputStickerSet.TLdeserialize(stream, stream.readInt32(exception), exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
prev_stickerset.serializeToStream(stream);
new_stickerset.serializeToStream(stream);
}
}
public static class TL_channelAdminLogEventActionParticipantMute extends ChannelAdminLogEventAction {
public static final int constructor = 0xf92424d2;
@ -62102,6 +62464,27 @@ public class TLRPC {
}
}
public static class TL_messages_searchEmojiStickerSets extends TLObject {
public static int constructor = 0x92b4494c;
public int flags;
public boolean exclude_featured;
public String q;
public long hash;
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return messages_FoundStickerSets.TLdeserialize(stream, constructor, exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
flags = exclude_featured ? (flags | 1) : (flags &~ 1);
stream.writeInt32(flags);
stream.writeString(q);
stream.writeInt64(hash);
}
}
public static class TL_messages_markDialogUnread extends TLObject {
public static final int constructor = 0xc286d98f;
@ -65304,6 +65687,7 @@ public class TLRPC {
public static class Message extends TLObject {
public int id;
public Peer from_id;
public int from_boosts_applied;
public Peer peer_id;
public Peer saved_peer_id;
public int date;
@ -65460,6 +65844,9 @@ public class TLRPC {
case TL_message_layer169.constructor:
result = new TL_message_layer169();
break;
case TL_message_layer173.constructor:
result = new TL_message_layer173();
break;
case 0x9e19a1f6:
result = new TL_messageService_layer118();
break;
@ -66160,6 +66547,202 @@ public class TLRPC {
}
public static class TL_message extends Message {
public static final int constructor = 0x1e4c8a69;
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
out = (flags & 2) != 0;
mentioned = (flags & 16) != 0;
media_unread = (flags & 32) != 0;
silent = (flags & 8192) != 0;
post = (flags & 16384) != 0;
from_scheduled = (flags & 262144) != 0;
legacy = (flags & 524288) != 0;
edit_hide = (flags & 2097152) != 0;
pinned = (flags & 16777216) != 0;
noforwards = (flags & 67108864) != 0;
invert_media = (flags & 134217728) != 0;
id = stream.readInt32(exception);
if ((flags & 256) != 0) {
from_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 536870912) != 0) {
from_boosts_applied = stream.readInt32(exception);
}
peer_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception);
if ((flags & 268435456) != 0) {
saved_peer_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 4) != 0) {
fwd_from = MessageFwdHeader.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 2048) != 0) {
via_bot_id = stream.readInt64(exception);
}
if ((flags & 8) != 0) {
reply_to = MessageReplyHeader.TLdeserialize(stream, stream.readInt32(exception), exception);
}
date = stream.readInt32(exception);
message = stream.readString(exception);
if ((flags & 512) != 0) {
media = MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception);
if (media != null) {
ttl = media.ttl_seconds;
}
if (media != null && !TextUtils.isEmpty(media.captionLegacy)) {
message = media.captionLegacy;
}
}
if ((flags & 64) != 0) {
reply_markup = ReplyMarkup.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 128) != 0) {
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
int count = stream.readInt32(exception);
for (int a = 0; a < count; a++) {
MessageEntity object = MessageEntity.TLdeserialize(stream, stream.readInt32(exception), exception);
if (object == null) {
return;
}
entities.add(object);
}
}
if ((flags & 1024) != 0) {
views = stream.readInt32(exception);
}
if ((flags & 1024) != 0) {
forwards = stream.readInt32(exception);
}
if ((flags & 8388608) != 0) {
replies = MessageReplies.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 32768) != 0) {
edit_date = stream.readInt32(exception);
}
if ((flags & 65536) != 0) {
post_author = stream.readString(exception);
}
if ((flags & 131072) != 0) {
grouped_id = stream.readInt64(exception);
}
if ((flags & 1048576) != 0) {
reactions = MessageReactions.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 4194304) != 0) {
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
int count = stream.readInt32(exception);
for (int a = 0; a < count; a++) {
TL_restrictionReason object = TL_restrictionReason.TLdeserialize(stream, stream.readInt32(exception), exception);
if (object == null) {
return;
}
restriction_reason.add(object);
}
}
if ((flags & 33554432) != 0) {
ttl_period = stream.readInt32(exception);
}
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
flags = out ? (flags | 2) : (flags &~ 2);
flags = mentioned ? (flags | 16) : (flags &~ 16);
flags = media_unread ? (flags | 32) : (flags &~ 32);
flags = silent ? (flags | 8192) : (flags &~ 8192);
flags = post ? (flags | 16384) : (flags &~ 16384);
flags = from_scheduled ? (flags | 262144) : (flags &~ 262144);
flags = legacy ? (flags | 524288) : (flags &~ 524288);
flags = edit_hide ? (flags | 2097152) : (flags &~ 2097152);
flags = pinned ? (flags | 16777216) : (flags &~ 16777216);
flags = noforwards ? (flags | 67108864) : (flags &~ 67108864);
flags = invert_media ? (flags | 134217728) : (flags &~ 134217728);
stream.writeInt32(flags);
stream.writeInt32(id);
if ((flags & 256) != 0) {
from_id.serializeToStream(stream);
}
if ((flags & 536870912) != 0) {
stream.writeInt32(from_boosts_applied);
}
peer_id.serializeToStream(stream);
if ((flags & 268435456) != 0) {
saved_peer_id.serializeToStream(stream);
}
if ((flags & 4) != 0) {
fwd_from.serializeToStream(stream);
}
if ((flags & 2048) != 0) {
stream.writeInt64(via_bot_id);
}
if ((flags & 8) != 0) {
reply_to.serializeToStream(stream);
}
stream.writeInt32(date);
stream.writeString(message);
if ((flags & 512) != 0) {
media.serializeToStream(stream);
}
if ((flags & 64) != 0) {
reply_markup.serializeToStream(stream);
}
if ((flags & 128) != 0) {
stream.writeInt32(0x1cb5c415);
int count = entities.size();
stream.writeInt32(count);
for (int a = 0; a < count; a++) {
entities.get(a).serializeToStream(stream);
}
}
if ((flags & 1024) != 0) {
stream.writeInt32(views);
}
if ((flags & 1024) != 0) {
stream.writeInt32(forwards);
}
if ((flags & 8388608) != 0) {
replies.serializeToStream(stream);
}
if ((flags & 32768) != 0) {
stream.writeInt32(edit_date);
}
if ((flags & 65536) != 0) {
stream.writeString(post_author);
}
if ((flags & 131072) != 0) {
stream.writeInt64(grouped_id);
}
if ((flags & 1048576) != 0) {
reactions.serializeToStream(stream);
}
if ((flags & 4194304) != 0) {
stream.writeInt32(0x1cb5c415);
int count = restriction_reason.size();
stream.writeInt32(count);
for (int a = 0; a < count; a++) {
restriction_reason.get(a).serializeToStream(stream);
}
}
if ((flags & 33554432) != 0) {
stream.writeInt32(ttl_period);
}
writeAttachPath(stream);
}
}
public static class TL_message_layer173 extends TL_message {
public static final int constructor = 0x76bec211;
public void readParams(AbstractSerializedData stream, boolean exception) {
@ -72323,6 +72906,40 @@ public class TLRPC {
}
}
public static class TL_channels_setEmojiStickers extends TLObject {
public static final int constructor = 0x3cd930b7;
public InputChannel channel;
public InputStickerSet stickerset;
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return Bool.TLdeserialize(stream, constructor, exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
channel.serializeToStream(stream);
stickerset.serializeToStream(stream);
}
}
public static class TL_channels_setBoostsToUnblockRestrictions extends TLObject {
public static final int constructor = 0xad399cee;
public InputChannel channel;
public int boosts;
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return Updates.TLdeserialize(stream, constructor, exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
channel.serializeToStream(stream);
stream.writeInt32(boosts);
}
}
public static class TL_account_reorderUsernames extends TLObject {
public static final int constructor = 0xef500eab;
@ -73108,7 +73725,7 @@ public class TLRPC {
public ArrayList<MessageEntity> quote_entities = new ArrayList<>();
public int quote_offset;
public InputUser user_id;
public InputPeer peer;
public int story_id;
public static InputReplyTo TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
@ -73257,16 +73874,16 @@ public class TLRPC {
}
public static class TL_inputReplyToStory extends InputReplyTo {
public static final int constructor = 0x15b0f283;
public static final int constructor = 0x5881323a;
public void readParams(AbstractSerializedData stream, boolean exception) {
user_id = InputUser.TLdeserialize(stream, stream.readInt32(exception), exception);
peer = InputPeer.TLdeserialize(stream, stream.readInt32(exception), exception);
story_id = stream.readInt32(exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
user_id.serializeToStream(stream);
peer.serializeToStream(stream);
stream.writeInt32(story_id);
}
}
@ -74528,7 +75145,7 @@ public class TLRPC {
}
public static class TL_help_peerColorOption extends TLObject {
public static final int constructor = 0xef8430ab;
public static final int constructor = 0xadec6ebe;
public int flags;
public boolean hidden;
@ -74536,6 +75153,7 @@ public class TLRPC {
public help_PeerColorSet colors;
public help_PeerColorSet dark_colors;
public int channel_min_level;
public int group_min_level;
public static TL_help_peerColorOption TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
if (TL_help_peerColorOption.constructor != constructor) {
@ -74550,7 +75168,6 @@ public class TLRPC {
return result;
}
@Override
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
hidden = (flags & 1) != 0;
@ -74564,9 +75181,11 @@ public class TLRPC {
if ((flags & 8) != 0) {
channel_min_level = stream.readInt32(exception);
}
if ((flags & 16) != 0) {
group_min_level = stream.readInt32(exception);
}
}
@Override
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
flags = hidden ? (flags | 1) : (flags &~ 1);
@ -74581,6 +75200,9 @@ public class TLRPC {
if ((flags & 8) != 0) {
stream.writeInt32(channel_min_level);
}
if ((flags & 16) != 0) {
stream.writeInt32(group_min_level);
}
}
}

View file

@ -1926,6 +1926,7 @@ public class TL_stories {
public boolean out;
public int id;
public int date;
public TLRPC.Peer from_id;
public StoryFwdHeader fwd_from;
public int expire_date;
public String caption;
@ -1953,19 +1954,22 @@ public class TL_stories {
public static StoryItem TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
StoryItem result = null;
switch (constructor) {
case 0xaf6365a1:
case TL_storyItem.constructor:
result = new TL_storyItem();
break;
case 0x44c457ce:
case TL_storyItem_layer174.constructor:
result = new TL_storyItem_layer174();
break;
case TL_storyItem_layer166.constructor:
result = new TL_storyItem_layer166();
break;
case 0x562aa637:
case TL_storyItem_layer160.constructor:
result = new TL_storyItem_layer160();
break;
case 0x51e6ee4f:
case TL_storyItemDeleted.constructor:
result = new TL_storyItemDeleted();
break;
case 0xffadc913:
case TL_storyItemSkipped.constructor:
result = new TL_storyItemSkipped();
break;
}
@ -2241,6 +2245,150 @@ public class TL_stories {
}
public static class TL_storyItem extends StoryItem {
public static final int constructor = 0x79b26a24;
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
pinned = (flags & 32) != 0;
isPublic = (flags & 128) != 0;
close_friends = (flags & 256) != 0;
min = (flags & 512) != 0;
noforwards = (flags & 1024) != 0;
edited = (flags & 2048) != 0;
contacts = (flags & 4096) != 0;
selected_contacts = (flags & 8192) != 0;
out = (flags & 65536) != 0;
id = stream.readInt32(exception);
date = stream.readInt32(exception);
if ((flags & 262144) != 0) {
from_id = TLRPC.Peer.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 131072) != 0) {
fwd_from = TL_storyFwdHeader.TLdeserialize(stream, stream.readInt32(exception), exception);
}
expire_date = stream.readInt32(exception);
if ((flags & 1) != 0) {
caption = stream.readString(exception);
}
if ((flags & 2) != 0) {
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
int count = stream.readInt32(exception);
for (int a = 0; a < count; a++) {
TLRPC.MessageEntity object = TLRPC.MessageEntity.TLdeserialize(stream, stream.readInt32(exception), exception);
if (object == null) {
return;
}
entities.add(object);
}
}
media = TLRPC.MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception);
if ((flags & 16384) != 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++) {
MediaArea object = MediaArea.TLdeserialize(stream, stream.readInt32(exception), exception);
if (object == null) {
return;
}
media_areas.add(object);
}
}
if ((flags & 4) != 0) {
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
int count = stream.readInt32(exception);
for (int a = 0; a < count; a++) {
TLRPC.PrivacyRule object = TLRPC.PrivacyRule.TLdeserialize(stream, stream.readInt32(exception), exception);
if (object == null) {
return;
}
privacy.add(object);
}
}
if ((flags & 8) != 0) {
views = StoryViews.TLdeserialize(stream, stream.readInt32(exception), exception);
}
if ((flags & 32768) != 0) {
sent_reaction = TLRPC.Reaction.TLdeserialize(stream, stream.readInt32(exception), exception);
}
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
flags = pinned ? (flags | 32) : (flags &~ 32);
flags = isPublic ? (flags | 128) : (flags &~ 128);
flags = close_friends ? (flags | 256) : (flags &~ 256);
flags = min ? (flags | 512) : (flags &~ 512);
flags = noforwards ? (flags | 1024) : (flags &~ 1024);
flags = edited ? (flags | 2048) : (flags &~ 2048);
flags = contacts ? (flags | 4096) : (flags &~ 4096);
flags = selected_contacts ? (flags | 8192) : (flags &~ 8192);
flags = out ? (flags | 65536) : (flags &~ 65536);
stream.writeInt32(flags);
stream.writeInt32(id);
stream.writeInt32(date);
if ((flags & 262144) != 0) {
from_id.serializeToStream(stream);
}
if ((flags & 131072) != 0) {
fwd_from.serializeToStream(stream);
}
stream.writeInt32(expire_date);
if ((flags & 1) != 0) {
stream.writeString(caption);
}
if ((flags & 2) != 0) {
stream.writeInt32(0x1cb5c415);
int count = entities.size();
stream.writeInt32(count);
for (int a = 0; a < count; a++) {
entities.get(a).serializeToStream(stream);
}
}
media.serializeToStream(stream);
if ((flags & 16384) != 0) {
stream.writeInt32(0x1cb5c415);
int count = media_areas.size();
stream.writeInt32(count);
for (int a = 0; a < count; a++) {
media_areas.get(a).serializeToStream(stream);
}
}
if ((flags & 4) != 0) {
stream.writeInt32(0x1cb5c415);
int count = privacy.size();
stream.writeInt32(count);
for (int a = 0; a < count; a++) {
privacy.get(a).serializeToStream(stream);
}
}
if ((flags & 8) != 0) {
views.serializeToStream(stream);
}
if ((flags & 32768) != 0) {
sent_reaction.serializeToStream(stream);
}
}
}
public static class TL_storyItem_layer174 extends TL_storyItem {
public static final int constructor = 0xaf6365a1;
public void readParams(AbstractSerializedData stream, boolean exception) {

View file

@ -2456,6 +2456,9 @@ public class ActionBarMenuItem extends FrameLayout {
public Item lazilyAddSubItem(int id, int icon, CharSequence text) {
return lazilyAddSubItem(id, icon, null, text, true, false);
}
public Item lazilyAddSubItem(int id, Drawable iconDrawable, CharSequence text) {
return lazilyAddSubItem(id, 0, iconDrawable, text, true, false);
}
public Item lazilyAddSubItem(int id, int icon, Drawable iconDrawable, CharSequence text, boolean dismiss, boolean needCheck) {
return putLazyItem(Item.asSubItem(id, icon, iconDrawable, text, dismiss, needCheck));
}

View file

@ -32,6 +32,7 @@ public class ActionBarMenuSubItem extends FrameLayout {
private int iconColor;
private int selectorColor;
int selectorRad = 6;
boolean top;
boolean bottom;
@ -281,8 +282,18 @@ public class ActionBarMenuSubItem extends FrameLayout {
updateBackground();
}
public void updateSelectorBackground(boolean top, boolean bottom, int selectorRad) {
if (this.top == top && this.bottom == bottom && this.selectorRad == selectorRad) {
return;
}
this.top = top;
this.bottom = bottom;
this.selectorRad = selectorRad;
updateBackground();
}
public void updateBackground() {
setBackground(Theme.createRadSelectorDrawable(selectorColor, top ? 6 : 0, bottom ? 6 : 0));
setBackground(Theme.createRadSelectorDrawable(selectorColor, top ? selectorRad : 0, bottom ? selectorRad : 0));
}
private int getThemedColor(int key) {

View file

@ -400,7 +400,7 @@ public class ActionBarPopupWindow extends PopupWindow {
}
public int precalculateHeight() {
int MOST_SPEC = View.MeasureSpec.makeMeasureSpec(999999, View.MeasureSpec.AT_MOST);
int MOST_SPEC = View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST);
linearLayout.measure(MOST_SPEC, MOST_SPEC);
return linearLayout.getMeasuredHeight();
}

View file

@ -26,7 +26,10 @@ import java.util.ArrayList;
public class EmojiThemes {
public static final String REMOVED_EMOJI = "";
public boolean showAsDefaultStub;
public boolean showAsRemovedStub;
public String emoji;
public TLRPC.WallPaper wallpaper;
int currentIndex = 0;
@ -65,6 +68,10 @@ public class EmojiThemes {
}
}
public boolean isAnyStub() {
return showAsDefaultStub || showAsRemovedStub;
}
public static EmojiThemes createPreviewFullTheme(int currentAccount, TLRPC.TL_theme tl_theme) {
EmojiThemes chatTheme = new EmojiThemes(currentAccount);
chatTheme.emoji = tl_theme.emoticon;
@ -82,7 +89,7 @@ public class EmojiThemes {
public static EmojiThemes createChatThemesDefault(int currentAccount) {
EmojiThemes themeItem = new EmojiThemes(currentAccount);
themeItem.emoji = "";
themeItem.emoji = REMOVED_EMOJI;
themeItem.showAsDefaultStub = true;
ThemeItem lightTheme = new ThemeItem();
@ -96,6 +103,23 @@ public class EmojiThemes {
return themeItem;
}
public static EmojiThemes createChatThemesRemoved(int currentAccount) {
EmojiThemes themeItem = new EmojiThemes(currentAccount);
themeItem.emoji = REMOVED_EMOJI;
themeItem.showAsRemovedStub = true;
ThemeItem lightTheme = new ThemeItem();
lightTheme.themeInfo = getDefaultThemeInfo(true);
themeItem.items.add(lightTheme);
ThemeItem darkTheme = new ThemeItem();
darkTheme.themeInfo = getDefaultThemeInfo(false);
themeItem.items.add(darkTheme);
return themeItem;
}
public static EmojiThemes createPreviewCustom(int currentAccount) {
EmojiThemes themeItem = new EmojiThemes(currentAccount);
themeItem.emoji = "\uD83C\uDFA8";

View file

@ -1095,7 +1095,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
return rightDrawableY;
}
private int getMaxTextWidth() {
public int getMaxTextWidth() {
return getMeasuredWidth() - (rightDrawableOutside && rightDrawable != null ? rightDrawable.getIntrinsicWidth() + drawablePadding : 0) - (rightDrawableOutside && rightDrawable2 != null ? rightDrawable2.getIntrinsicWidth() + drawablePadding : 0);
}

View file

@ -323,6 +323,11 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter {
items.add(new Item(16, LocaleController.getString("ProfileMyStories", R.string.ProfileMyStories), R.drawable.msg_menu_stories));
showDivider = true;
}
if (ApplicationLoader.applicationLoaderInstance != null) {
if (ApplicationLoader.applicationLoaderInstance.extendDrawer(items)) {
showDivider = true;
}
}
TLRPC.TL_attachMenuBots menuBots = MediaDataController.getInstance(UserConfig.selectedAccount).getAttachMenuBots();
if (menuBots != null && menuBots.bots != null) {
for (int i = 0; i < menuBots.bots.size(); i++) {
@ -351,6 +356,22 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter {
items.add(new Item(13, LocaleController.getString("TelegramFeatures", R.string.TelegramFeatures), helpIcon));
}
public boolean click(View view, int position) {
position -= 2;
if (accountsShown) {
position -= getAccountRowsCount();
}
if (position < 0 || position >= items.size()) {
return false;
}
Item item = items.get(position);
if (item != null && item.listener != null) {
item.listener.onClick(view);
return true;
}
return false;
}
public int getId(int position) {
position -= 2;
if (accountsShown) {
@ -389,13 +410,14 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter {
return item != null ? item.bot : null;
}
private static class Item {
public static class Item {
public int icon;
public String text;
public CharSequence text;
public int id;
TLRPC.TL_attachMenuBot bot;
View.OnClickListener listener;
public Item(int id, String text, int icon) {
public Item(int id, CharSequence text, int icon) {
this.icon = icon;
this.id = id;
this.text = text;
@ -413,5 +435,10 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter {
actionCell.setTextAndIcon(id, text, icon);
}
}
public Item onClick(View.OnClickListener listener) {
this.listener = listener;
return this;
}
}
}

View file

@ -3807,7 +3807,13 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
boolean allowPlayer = !PhotoViewer.getInstance().isVisibleOrAnimating();
if (!allowPlayer || (currentPlayer != null && currentPlayer != bestView && videoPlayer != null)) {
if (videoPlayer != null) {
currentPlayer.playFrom = videoPlayer.getCurrentPosition();
videoStates.put(currentPlayer.currentBlock.video_id, currentPlayer.setState(BlockVideoCellState.fromPlayer(videoPlayer, currentPlayer)));
if (currentPlayer.videoState != null) {
if (currentPlayer.videoState.lastFrameBitmap != null) {
currentPlayer.imageView.setImageBitmap(currentPlayer.videoState.lastFrameBitmap);
}
currentPlayer.updateButtonState(false);
}
videoPlayer.release(null);
}
videoPlayer = null;
@ -4724,6 +4730,15 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
containerView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
animatorSet.start();
for (int i = 0; i < videoStates.size(); ++i) {
BlockVideoCellState state = videoStates.valueAt(i);
if (state.lastFrameBitmap != null) {
state.lastFrameBitmap.recycle();
state.lastFrameBitmap = null;
}
}
videoStates.clear();
}
private void onClosed() {
@ -4963,6 +4978,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
}
}
private LongSparseArray<BlockVideoCellState> videoStates = new LongSparseArray<>();
private class WebpageAdapter extends RecyclerListView.SelectionAdapter {
private Context context;
@ -5729,7 +5746,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
}
case 5: {
BlockVideoCell cell = (BlockVideoCell) holder.itemView;
cell.setBlock((TLRPC.TL_pageBlockVideo) block, position == 0, position == total - 1);
TLRPC.TL_pageBlockVideo blockVideo = (TLRPC.TL_pageBlockVideo) block;
cell.setBlock(blockVideo, videoStates.get(blockVideo.video_id), position == 0, position == total - 1);
cell.setParentBlock(channelBlock, originalBlock);
break;
}
@ -6044,9 +6062,58 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
}
}
private static class BlockVideoCellState {
long playFrom;
Bitmap lastFrameBitmap;
public static BlockVideoCellState fromPlayer(VideoPlayerHolderBase player, BlockVideoCell videoCell) {
BlockVideoCellState state = new BlockVideoCellState();
state.playFrom = player.getCurrentPosition();
if (player.firstFrameRendered && videoCell.textureView != null && videoCell.textureView.getSurfaceTexture() != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Surface surface = new Surface(videoCell.textureView.getSurfaceTexture());
Bitmap bitmap = Bitmap.createBitmap(videoCell.textureView.getMeasuredWidth(), videoCell.textureView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
AndroidUtilities.getBitmapFromSurface(surface, bitmap);
surface.release();
state.lastFrameBitmap = bitmap;
} else {
state.lastFrameBitmap = videoCell.textureView.getBitmap();
}
}
return state;
}
public static BlockVideoCellState fromPlayer(VideoPlayer player, BlockVideoCell videoCell, TextureView textureView) {
BlockVideoCellState state = new BlockVideoCellState();
state.playFrom = player.getCurrentPosition();
if (textureView != null && textureView.getSurfaceTexture() != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Surface surface = new Surface(textureView.getSurfaceTexture());
Bitmap bitmap = Bitmap.createBitmap(textureView.getMeasuredWidth(), textureView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
AndroidUtilities.getBitmapFromSurface(surface, bitmap);
surface.release();
state.lastFrameBitmap = bitmap;
} else {
state.lastFrameBitmap = textureView.getBitmap();
}
}
return state;
}
public static BlockVideoCellState fromPlayer(VideoPlayer player, BlockVideoCell videoCell, SurfaceView surfaceView) {
BlockVideoCellState state = new BlockVideoCellState();
state.playFrom = player.getCurrentPosition();
if (surfaceView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Bitmap bitmap = Bitmap.createBitmap(surfaceView.getMeasuredWidth(), surfaceView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
AndroidUtilities.getBitmapFromSurface(surfaceView, bitmap);
state.lastFrameBitmap = bitmap;
}
return state;
}
}
private class BlockVideoCell extends FrameLayout implements DownloadController.FileDownloadProgressListener, TextSelectionHelper.ArticleSelectableView {
public long playFrom;
private DrawingText captionLayout;
private DrawingText creditLayout;
private ImageReceiver imageView;
@ -6070,6 +6137,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
private int TAG;
private TLRPC.TL_pageBlockVideo currentBlock;
private BlockVideoCellState videoState;
private TLRPC.PageBlock parentBlock;
private TLRPC.Document currentDocument;
private boolean isGif;
@ -6118,8 +6186,12 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
return super.drawChild(canvas, child, drawingTime);
}
public void setBlock(TLRPC.TL_pageBlockVideo block, boolean first, boolean last) {
public void setBlock(TLRPC.TL_pageBlockVideo block, BlockVideoCellState state, boolean first, boolean last) {
if (currentBlock != null && videoPlayer != null && currentPlayer == this) {
videoStates.put(currentBlock.video_id, videoState = BlockVideoCellState.fromPlayer(videoPlayer, this));
}
currentBlock = block;
videoState = state;
parentBlock = null;
currentDocument = parentAdapter.getDocumentWithId(currentBlock.video_id);
isGif = MessageObject.isVideoDocument(currentDocument) || MessageObject.isGifDocument(currentDocument)/* && currentBlock.autoplay*/;
@ -6255,15 +6327,20 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
int photoY = (isFirst || currentType == 1 || currentType == 2 || currentBlock.level > 0) ? 0 : AndroidUtilities.dp(8);
imageView.setImageCoords(photoX, photoY, photoWidth, photoHeight);
if (isGif) {
autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(DownloadController.AUTODOWNLOAD_TYPE_VIDEO, currentDocument.size);
File path = FileLoader.getInstance(currentAccount).getPathToAttach(currentDocument);
File path2 = FileLoader.getInstance(currentAccount).getPathToAttach(currentDocument, true);
if (autoDownload || path.exists() || path2.exists()) {
if (videoState != null && videoState.lastFrameBitmap != null) {
imageView.setStrippedLocation(null);
imageView.setImage(null, null, ImageLocation.getForDocument(currentDocument), "200_200_pframe", ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", null, currentDocument.size, null, parentAdapter.currentPage, 1);
imageView.setImageBitmap(videoState.lastFrameBitmap);
} else {
imageView.setStrippedLocation(ImageLocation.getForDocument(currentDocument));
imageView.setImage(null, null, null, null, ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", null, currentDocument.size, null, parentAdapter.currentPage, 1);
autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(DownloadController.AUTODOWNLOAD_TYPE_VIDEO, currentDocument.size);
File path = FileLoader.getInstance(currentAccount).getPathToAttach(currentDocument);
File path2 = FileLoader.getInstance(currentAccount).getPathToAttach(currentDocument, true);
if (autoDownload || path.exists() || path2.exists()) {
imageView.setStrippedLocation(null);
imageView.setImage(null, null, ImageLocation.getForDocument(currentDocument), "200_200_pframe", ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", null, currentDocument.size, null, parentAdapter.currentPage, 1);
} else {
imageView.setStrippedLocation(ImageLocation.getForDocument(currentDocument));
imageView.setImage(null, null, null, null, ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", null, currentDocument.size, null, parentAdapter.currentPage, 1);
}
}
} else {
imageView.setStrippedLocation(null);
@ -6382,7 +6459,9 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
DownloadController.getInstance(currentAccount).addLoadingFileObserver(fileName, null, this);
float setProgress = 0;
boolean progressVisible = false;
if (!FileLoader.getInstance(currentAccount).isLoadingFile(fileName)) {
if (videoState != null && videoState.lastFrameBitmap != null) {
buttonState = -1;
} else if (!FileLoader.getInstance(currentAccount).isLoadingFile(fileName)) {
if (!cancelLoading && autoDownload && isGif) {
progressVisible = true;
buttonState = 1;
@ -6437,13 +6516,28 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
@Override
protected void onDetachedFromWindow() {
if (currentBlock != null && videoPlayer != null && currentPlayer == this) {
videoStates.put(currentBlock.video_id, setState(BlockVideoCellState.fromPlayer(videoPlayer, this)));
}
super.onDetachedFromWindow();
imageView.onDetachedFromWindow();
DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this);
playFrom = 0;
firstFrameRendered = false;
}
public BlockVideoCellState setState(BlockVideoCellState newState) {
if (videoState != null && newState != null && newState.lastFrameBitmap != null && videoState.lastFrameBitmap != null && newState.lastFrameBitmap != videoState.lastFrameBitmap) {
videoState.lastFrameBitmap.recycle();
videoState.lastFrameBitmap = null;
}
if (videoState != null && newState != null && newState.lastFrameBitmap == null && videoState.lastFrameBitmap != null) {
newState.playFrom = videoState.playFrom;
newState.lastFrameBitmap = videoState.lastFrameBitmap;
}
videoState = newState;
return videoState;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@ -6470,6 +6564,10 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
if (!firstFrameRendered) {
firstFrameRendered = true;
textureView.setAlpha(1f);
if (currentBlock != null) {
videoStates.put(currentBlock.video_id, setState(BlockVideoCellState.fromPlayer(videoPlayer, BlockVideoCell.this)));
}
}
}
}.with(textureView);
@ -6486,7 +6584,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
return;
}
videoPlayer.seekTo(playFrom);
videoPlayer.seekTo(videoState == null ? 0 : videoState.playFrom);
videoPlayer.preparePlayer(uri, true, 1f);
videoPlayer.play();
@ -8398,7 +8496,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
default: {
BlockVideoCell cell = (BlockVideoCell) holder.itemView;
cell.groupPosition = group.positions.get(pageBlock);
cell.setBlock((TLRPC.TL_pageBlockVideo) pageBlock, true, true);
TLRPC.TL_pageBlockVideo blockVideo = (TLRPC.TL_pageBlockVideo) pageBlock;
cell.setBlock(blockVideo, videoStates.get(blockVideo.video_id), true, true);
break;
}
}
@ -8637,7 +8736,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
((BlockPhotoCell) view).setBlock((TLRPC.TL_pageBlockPhoto) block, true, true);
} else {
view = new BlockVideoCell(getContext(), parentAdapter, 1);
((BlockVideoCell) view).setBlock((TLRPC.TL_pageBlockVideo) block, true, true);
TLRPC.TL_pageBlockVideo videoBlock = (TLRPC.TL_pageBlockVideo) block;
((BlockVideoCell) view).setBlock(videoBlock, videoStates.get(videoBlock.video_id), true, true);
}
container.addView(view);
ObjectContainer objectContainer = new ObjectContainer();
@ -11680,28 +11780,20 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
SurfaceView surfaceView = PhotoViewer.getInstance().getVideoSurfaceView();
BlockVideoCell videoCell = getViewFromListView(listView[0], pageBlock);
if (videoCell != null && player != null && textureView != null) {
videoCell.playFrom = player.getCurrentPosition();
videoStates.put(videoCell.currentBlock.video_id, videoCell.setState(BlockVideoCellState.fromPlayer(player, videoCell, textureView)));
videoCell.firstFrameRendered = false;
videoCell.textureView.setAlpha(0);
if (textureView.getSurfaceTexture() != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Surface surface = new Surface(textureView.getSurfaceTexture());
Bitmap bitmap = Bitmap.createBitmap(textureView.getMeasuredWidth(), textureView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
AndroidUtilities.getBitmapFromSurface(surface, bitmap);
surface.release();
videoCell.imageView.setImageBitmap(bitmap);
} else {
videoCell.imageView.setImageBitmap(textureView.getBitmap());
}
if (videoCell.videoState != null && videoCell.videoState.lastFrameBitmap != null) {
videoCell.imageView.setImageBitmap(videoCell.videoState.lastFrameBitmap);
}
}
if (videoCell != null && player != null && surfaceView != null) {
videoCell.playFrom = player.getCurrentPosition();
videoStates.put(videoCell.currentBlock.video_id, videoCell.setState(BlockVideoCellState.fromPlayer(player, videoCell, surfaceView)));
videoCell.firstFrameRendered = false;
videoCell.textureView.setAlpha(0);
Bitmap bitmap = Bitmap.createBitmap(surfaceView.getMeasuredWidth(), surfaceView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
AndroidUtilities.getBitmapFromSurface(surfaceView, bitmap);
videoCell.imageView.setImageBitmap(bitmap);
if (videoCell.videoState != null && videoCell.videoState.lastFrameBitmap != null) {
videoCell.imageView.setImageBitmap(videoCell.videoState.lastFrameBitmap);
}
}
checkVideoPlayer();
}

View file

@ -0,0 +1,846 @@
package org.telegram.ui;
import static org.telegram.messenger.AndroidUtilities.dp;
import static org.telegram.tgnet.TLRPC.TL_payments_checkedGiftCode.NO_USER_ID;
import static org.telegram.ui.Components.Premium.LimitReachedBottomSheet.TYPE_FEATURES;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChannelBoostsController;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
import org.telegram.tgnet.tl.TL_stories;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.FixedHeightEmptyCell;
import org.telegram.ui.Cells.ManageChatTextCell;
import org.telegram.ui.Cells.ShadowSectionCell;
import org.telegram.ui.Cells.TextCell;
import org.telegram.ui.Cells.TextInfoPrivacyCell;
import org.telegram.ui.Charts.view_data.ChartHeaderView;
import org.telegram.ui.Components.Bulletin;
import org.telegram.ui.Components.CircularProgressDrawable;
import org.telegram.ui.Components.CombinedDrawable;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.LinkActionView;
import org.telegram.ui.Components.ListView.AdapterWithDiffUtils;
import org.telegram.ui.Components.Premium.LimitPreviewView;
import org.telegram.ui.Components.Premium.LimitReachedBottomSheet;
import org.telegram.ui.Components.Premium.boosts.BoostDialogs;
import org.telegram.ui.Components.Premium.boosts.BoostPagerBottomSheet;
import org.telegram.ui.Components.Premium.boosts.GiftInfoBottomSheet;
import org.telegram.ui.Components.Premium.boosts.cells.statistics.GiftedUserCell;
import org.telegram.ui.Components.Premium.boosts.cells.statistics.GiveawayCell;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.ScrollSlidingTextTabStrip;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
public class BoostsActivity extends GradientHeaderActivity implements NotificationCenter.NotificationCenterDelegate {
private final static int OVERVIEW_TYPE = 0;
private final static int HEADER_VIEW_TYPE = 1;
private final static int DIVIDER_VIEW_TYPE = 2;
private final static int LINK_VIEW_TYPE = 3;
private final static int BOOST_VIEW = 4;
private final static int USER_VIEW_TYPE = 5;
private final static int DIVIDER_TEXT_VIEW_TYPE = 6;
private final static int EMPTY_VIEW_8DP = 7;
private final static int NO_USERS_HINT = 8;
private final static int SHOW_MORE_VIEW_TYPE = 9;
private final static int SHOW_BOOST_BY_GIFTS = 10;
private final static int SHOW_PREPARED_GIVE_AWAY = 11;
private final static int HEADER_VIEW_TYPE_SMALL = 12;
private final static int HEADER_VIEW_TYPE_TABS = 13;
private final static int HEADER_PADDING = 14;
private final static int BOTTOM_PADDING = 15;
private final static int HEADER_VIEW_TYPE_OVERVIEW = 16;
private static final int TAB_BOOSTS = 0;
private static final int TAB_GIFTS = 1;
private final long dialogId;
int currentAccount = UserConfig.selectedAccount;
private TL_stories.TL_premium_boostsStatus boostsStatus;
private ChannelBoostsController.CanApplyBoost canApplyBoost;
private ScrollSlidingTextTabStrip boostsTabs;
private final ArrayList<TL_stories.TL_boost> boosters = new ArrayList<>();
private final ArrayList<TL_stories.TL_boost> gifts = new ArrayList<>();
private boolean hasBoostsNext;
private int nextBoostRemaining;
private boolean hasGiftsNext;
private int nextGiftsRemaining;
private final ArrayList<ItemInternal> items = new ArrayList<>();
private int selectedTab = TAB_BOOSTS;
private LimitPreviewView limitPreviewView;
public void setBoostsStatus(TL_stories.TL_premium_boostsStatus boostsStatus) {
this.boostsStatus = boostsStatus;
loadCanApplyBoosts();
}
AdapterWithDiffUtils adapter = new AdapterWithDiffUtils() {
@Override
public boolean isEnabled(RecyclerView.ViewHolder holder) {
return items.get(holder.getAdapterPosition()).selectable;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case BOTTOM_PADDING:
view = new View(getContext()) {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int h = Math.max(0, layoutManager.getLastItemHeight()) ;
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY));
}
};
view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
break;
case HEADER_PADDING:
view = getHeader(getContext());
break;
case DIVIDER_TEXT_VIEW_TYPE:
view = new TextInfoPrivacyCell(parent.getContext(), 20, resourceProvider);
break;
case DIVIDER_VIEW_TYPE:
view = new ShadowSectionCell(parent.getContext(), 12, Theme.getColor(Theme.key_windowBackgroundGray));
break;
case OVERVIEW_TYPE:
view = new StatisticActivity.OverviewCell(getContext());
break;
case HEADER_VIEW_TYPE_OVERVIEW:
case HEADER_VIEW_TYPE:
view = new ChartHeaderView(getContext());
view.setPadding(view.getPaddingLeft(), AndroidUtilities.dp(16), view.getRight(), AndroidUtilities.dp(16));
break;
case HEADER_VIEW_TYPE_SMALL:
view = new ChartHeaderView(getContext());
view.setPadding(view.getPaddingLeft(), AndroidUtilities.dp(16), view.getRight(), AndroidUtilities.dp(8));
break;
case HEADER_VIEW_TYPE_TABS:
boostsTabs = new ScrollSlidingTextTabStrip(getContext(), resourceProvider);
boostsTabs.setColors(Theme.key_profile_tabSelectedLine, Theme.key_profile_tabSelectedText, Theme.key_profile_tabText, Theme.key_profile_tabSelector);
FrameLayout frameLayoutWrapper = new FrameLayout(getContext()) {
private final Paint dividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
dividerPaint.setColor(Theme.getColor(Theme.key_windowBackgroundGray, resourceProvider));
canvas.drawRect(0, getHeight() - 2, getWidth(), getHeight(), dividerPaint);
}
};
boostsTabs.setDelegate(new ScrollSlidingTextTabStrip.ScrollSlidingTabStripDelegate() {
@Override
public void onPageSelected(int id, boolean forward) {
selectedTab = id;
updateRows(true);
}
@Override
public void onSamePageSelected() {
}
@Override
public void onPageScrolled(float progress) {
}
});
frameLayoutWrapper.addView(boostsTabs, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 48));
view = frameLayoutWrapper;
break;
case SHOW_BOOST_BY_GIFTS:
TextCell textCell = new TextCell(getContext());
textCell.setTextAndIcon(LocaleController.formatString("BoostingGetBoostsViaGifts", R.string.BoostingGetBoostsViaGifts), R.drawable.msg_gift_premium, false);
textCell.offsetFromImage = 64;
textCell.setColors(Theme.key_windowBackgroundWhiteBlueText4, Theme.key_windowBackgroundWhiteBlueText4);
view = textCell;
break;
case LINK_VIEW_TYPE:
LinkActionView linkActionView = new LinkActionView(getContext(), BoostsActivity.this, null, 0, false, false);
view = linkActionView;
linkActionView.hideOptions();
view.setPadding(AndroidUtilities.dp(11), 0, AndroidUtilities.dp(11), AndroidUtilities.dp(24));
break;
case SHOW_PREPARED_GIVE_AWAY:
view = new GiveawayCell(getContext(), 0, 0, false);
break;
case USER_VIEW_TYPE:
view = new GiftedUserCell(getContext(), 0, 0, false);
break;
case EMPTY_VIEW_8DP:
view = new FixedHeightEmptyCell(getContext(), 8);
break;
case NO_USERS_HINT:
FrameLayout frameLayout = new FrameLayout(getContext()) {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), MeasureSpec.EXACTLY));
}
};
TextView textView = new TextView(getContext());
textView.setText(LocaleController.getString(isChannel() ? R.string.NoBoostersHint : R.string.NoBoostersGroupHint));
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText));
textView.setGravity(Gravity.CENTER);
frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 16, 0, 0));
view = frameLayout;
break;
case SHOW_MORE_VIEW_TYPE:
ManageChatTextCell actionCell = new ManageChatTextCell(getContext()) {
@Override
protected int getFullHeight() {
return AndroidUtilities.dp(50);
}
};
actionCell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton);
view = actionCell;
break;
default:
throw new UnsupportedOperationException();
}
view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
return new RecyclerListView.Holder(view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder.getItemViewType() == BOOST_VIEW || holder.getItemViewType() == HEADER_PADDING || holder.getItemViewType() == BOTTOM_PADDING) {
} else if (holder.getItemViewType() == HEADER_VIEW_TYPE || holder.getItemViewType() == HEADER_VIEW_TYPE_SMALL || holder.getItemViewType() == HEADER_VIEW_TYPE_OVERVIEW) {
ChartHeaderView headerCell = (ChartHeaderView) holder.itemView;
headerCell.setTitle(items.get(position).title);
headerCell.showDate(false);
if (holder.getItemViewType() == HEADER_VIEW_TYPE_SMALL) {
headerCell.setPadding(dp(3), headerCell.getPaddingTop(), headerCell.getPaddingRight(), headerCell.getPaddingBottom());
}
if (holder.getItemViewType() == HEADER_VIEW_TYPE_OVERVIEW) {
headerCell.setPadding(dp(6), 0, dp(6), headerCell.getPaddingBottom());
}
} else if (holder.getItemViewType() == OVERVIEW_TYPE) {
StatisticActivity.OverviewCell overviewCell = (StatisticActivity.OverviewCell) holder.itemView;
overviewCell.setData(0, Integer.toString(boostsStatus.level), null, LocaleController.getString("BoostsLevel2", R.string.BoostsLevel2));
if (boostsStatus.premium_audience != null && boostsStatus.premium_audience.total != 0) {
float percent = (((float) boostsStatus.premium_audience.part / (float) boostsStatus.premium_audience.total) * 100f);
overviewCell.setData(1, "~" + (int) boostsStatus.premium_audience.part, String.format(Locale.US, "%.1f", percent) + "%", LocaleController.getString(isChannel() ? R.string.PremiumSubscribers : R.string.PremiumMembers));
} else {
overviewCell.setData(1, "~0", "0%", LocaleController.getString(isChannel() ? R.string.PremiumSubscribers : R.string.PremiumMembers));
}
overviewCell.setData(2, String.valueOf(boostsStatus.boosts), null, LocaleController.getString("BoostsExisting", R.string.BoostsExisting));
overviewCell.setData(3, String.valueOf(Math.max(0, boostsStatus.next_level_boosts - boostsStatus.boosts)), null, LocaleController.getString("BoostsToLevel", R.string.BoostsToLevel));
overviewCell.setPadding(dp(23), overviewCell.getPaddingTop(), dp(23), overviewCell.getPaddingBottom());
} else if (holder.getItemViewType() == USER_VIEW_TYPE) {
TL_stories.TL_boost booster = items.get(position).booster;
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(booster.user_id);
GiftedUserCell userCell = (GiftedUserCell) holder.itemView;
String str = booster.multiplier > 1
? LocaleController.formatString("BoostsExpireOn", R.string.BoostsExpireOn, LocaleController.formatDate(booster.expires))
: LocaleController.formatString("BoostExpireOn", R.string.BoostExpireOn, LocaleController.formatDate(booster.expires));
userCell.setData(user, ContactsController.formatName(user), str, 0, !items.get(position).isLast);
userCell.setStatus(booster);
userCell.setAvatarPadding(5);
} else if (holder.getItemViewType() == DIVIDER_TEXT_VIEW_TYPE) {
TextInfoPrivacyCell privacyCell = (TextInfoPrivacyCell) holder.itemView;
privacyCell.setText(items.get(position).title);
boolean isLast = position == items.size() - 2;
Drawable shadowDrawable = Theme.getThemedDrawable(getContext(), isLast ? R.drawable.greydivider_bottom : R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourceProvider));
Drawable background = new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray));
CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0);
combinedDrawable.setFullsize(true);
privacyCell.setBackground(combinedDrawable);
} else if (holder.getItemViewType() == SHOW_MORE_VIEW_TYPE) {
ManageChatTextCell actionCell = (ManageChatTextCell) holder.itemView;
if (selectedTab == TAB_BOOSTS) {
actionCell.setText(LocaleController.formatPluralString("BoostingShowMoreBoosts", nextBoostRemaining), null, R.drawable.arrow_more, false);
} else {
actionCell.setText(LocaleController.formatPluralString("BoostingShowMoreGifts", nextGiftsRemaining), null, R.drawable.arrow_more, false);
}
} else if (holder.getItemViewType() == LINK_VIEW_TYPE) {
LinkActionView linkActionView = (LinkActionView) holder.itemView;
linkActionView.setLink(items.get(position).title);
} else if (holder.getItemViewType() == SHOW_PREPARED_GIVE_AWAY) {
ItemInternal item = items.get(position);
TL_stories.TL_prepaidGiveaway prepaidGiveaway = item.prepaidGiveaway;
GiveawayCell giveawayCell = (GiveawayCell) holder.itemView;
String name = LocaleController.formatPluralString("BoostingTelegramPremiumCountPlural", prepaidGiveaway.quantity);
String info = LocaleController.formatPluralString("BoostingSubscriptionsCountPlural", prepaidGiveaway.quantity, LocaleController.formatPluralString("PrepaidGiveawayMonths", prepaidGiveaway.months));
giveawayCell.setData(prepaidGiveaway, name, info, 0, !item.isLast);
giveawayCell.setImage(prepaidGiveaway);
giveawayCell.setAvatarPadding(5);
} else if (holder.getItemViewType() == HEADER_VIEW_TYPE_TABS) {
if (boostsTabs.getTag() == null || (int) boostsTabs.getTag() != Objects.hash(totalBoosts, totalGifts)) {
boostsTabs.setTag(Objects.hash(totalBoosts, totalGifts));
boostsTabs.removeTabs();
boostsTabs.addTextTab(TAB_BOOSTS, LocaleController.formatPluralString("BoostingBoostsCount", totalBoosts));
if (MessagesController.getInstance(currentAccount).giveawayGiftsPurchaseAvailable && totalGifts > 0 && totalGifts != totalBoosts) {
boostsTabs.addTextTab(TAB_GIFTS, LocaleController.formatPluralString("BoostingGiftsCount", totalGifts));
}
boostsTabs.setInitialTabId(selectedTab);
boostsTabs.finishAddingTabs();
}
}
}
@Override
public int getItemCount() {
return items.size();
}
@Override
public int getItemViewType(int position) {
return items.get(position).viewType;
}
};
boolean usersLoading;
private LinearLayout progressLayout;
private final TLRPC.Chat currentChat;
public BoostsActivity(long dialogId) {
this.dialogId = dialogId;
this.currentChat = MessagesController.getInstance(currentAccount).getChat(-dialogId);
}
public void updateRows(boolean animated) {
ArrayList<ItemInternal> oldItems = new ArrayList<>(items);
items.clear();
items.add(new ItemInternal(HEADER_PADDING, false));
if (boostsStatus != null) {
items.add(new ItemInternal(HEADER_VIEW_TYPE_OVERVIEW, LocaleController.getString("StatisticOverview", R.string.StatisticOverview)));
items.add(new ItemInternal(OVERVIEW_TYPE, false));
items.add(new ItemInternal(DIVIDER_VIEW_TYPE, false));
if (boostsStatus.prepaid_giveaways.size() > 0) {
items.add(new ItemInternal(HEADER_VIEW_TYPE_SMALL, LocaleController.getString("BoostingPreparedGiveaways", R.string.BoostingPreparedGiveaways)));
for (int i = 0; i < boostsStatus.prepaid_giveaways.size(); i++) {
TL_stories.TL_prepaidGiveaway prepaidGiveaway = boostsStatus.prepaid_giveaways.get(i);
items.add(new ItemInternal(SHOW_PREPARED_GIVE_AWAY, prepaidGiveaway, i == boostsStatus.prepaid_giveaways.size() - 1));
}
items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString("BoostingSelectPaidGiveaway", R.string.BoostingSelectPaidGiveaway)));
}
items.add(new ItemInternal(HEADER_VIEW_TYPE_TABS, LocaleController.getString("Boosters", R.string.Boosters)));
if (selectedTab == TAB_BOOSTS) {
if (boosters.isEmpty()) {
items.add(new ItemInternal(NO_USERS_HINT, false));
items.add(new ItemInternal(DIVIDER_VIEW_TYPE, false));
} else {
for (int i = 0; i < boosters.size(); i++) {
items.add(new ItemInternal(USER_VIEW_TYPE, boosters.get(i), i == boosters.size() - 1 && !hasBoostsNext, selectedTab));
}
if (hasBoostsNext) {
items.add(new ItemInternal(SHOW_MORE_VIEW_TYPE, true));
} else {
items.add(new ItemInternal(EMPTY_VIEW_8DP, false));
}
items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString(isChannel() ? R.string.BoostersInfoDescription : R.string.BoostersInfoGroupDescription)));
}
} else {
if (gifts.isEmpty()) {
items.add(new ItemInternal(NO_USERS_HINT, false));
items.add(new ItemInternal(DIVIDER_VIEW_TYPE, false));
} else {
for (int i = 0; i < gifts.size(); i++) {
items.add(new ItemInternal(USER_VIEW_TYPE, gifts.get(i), i == gifts.size() - 1 && !hasGiftsNext, selectedTab));
}
if (hasGiftsNext) {
items.add(new ItemInternal(SHOW_MORE_VIEW_TYPE, true));
} else {
items.add(new ItemInternal(EMPTY_VIEW_8DP, false));
}
items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString(isChannel() ? R.string.BoostersInfoDescription : R.string.BoostersInfoGroupDescription)));
}
}
items.add(new ItemInternal(HEADER_VIEW_TYPE, LocaleController.getString("LinkForBoosting", R.string.LinkForBoosting)));
items.add(new ItemInternal(LINK_VIEW_TYPE, boostsStatus.boost_url));
if (MessagesController.getInstance(currentAccount).giveawayGiftsPurchaseAvailable && ChatObject.hasAdminRights(currentChat)) {
items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString(isChannel() ? R.string.BoostingShareThisLink : R.string.BoostingShareThisLinkGroup)));
items.add(new ItemInternal(SHOW_BOOST_BY_GIFTS, true));
items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString(isChannel() ? R.string.BoostingGetMoreBoosts : R.string.BoostingGetMoreBoostsGroup)));
} else {
items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, ""));
}
items.add(new ItemInternal(BOTTOM_PADDING, false));
}
if (animated) {
adapter.setItems(oldItems, items);
} else {
adapter.notifyDataSetChanged();
}
}
private boolean isChannel() {
return ChatObject.isChannelAndNotMegaGroup(currentChat);
}
private void loadStatistic() {
progressLayout.setAlpha(0);
if (boostsStatus == null) {
progressLayout.animate().alpha(1f).setDuration(200).setStartDelay(500).start();
getMessagesController().getBoostsController().getBoostsStats(dialogId, tl_stories_boostsStatus -> AndroidUtilities.runOnUIThread(() -> {
boostsStatus = tl_stories_boostsStatus;
loadCanApplyBoosts();
progressLayout.animate().cancel();
progressLayout.animate().alpha(0).setDuration(100).setStartDelay(0).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
progressLayout.setVisibility(View.GONE);
}
});
resetHeader(true);
updateRows(true);
loadUsers(null);
}));
} else {
progressLayout.setVisibility(View.GONE);
loadUsers(null);
}
}
private void loadCanApplyBoosts() {
if (boostsStatus == null) {
return;
}
getMessagesController().getBoostsController().userCanBoostChannel(dialogId, boostsStatus, canApplyBoost -> this.canApplyBoost = canApplyBoost);
}
private String lastBoostsOffset = "";
private String lastGiftsOffset = "";
private int limitGifts = 5;
private int limitBoosts = 5;
private int totalGifts;
private int totalBoosts;
private void loadUsers(Boolean isGift) {
if (usersLoading) {
return;
}
usersLoading = true;
if (isGift == null) {
Utilities.globalQueue.postRunnable(() -> {
CountDownLatch latch = new CountDownLatch(2);
loadOnlyBoosts(latch, null);
loadOnlyGifts(latch, null);
try {
latch.await();
} catch (InterruptedException ignore) {
}
NotificationCenter.getInstance(currentAccount).doOnIdle(() -> AndroidUtilities.runOnUIThread(() -> {
usersLoading = false;
updateRows(true);
}));
});
} else if (isGift) {
loadOnlyGifts(null, () -> {
usersLoading = false;
updateRows(true);
});
} else {
loadOnlyBoosts(null, () -> {
usersLoading = false;
updateRows(true);
});
}
}
private void loadOnlyBoosts(CountDownLatch latch, Runnable after) {
TL_stories.TL_premium_getBoostsList listReq = new TL_stories.TL_premium_getBoostsList();
listReq.limit = limitBoosts;
listReq.offset = lastBoostsOffset;
listReq.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId);
ConnectionsManager.getInstance(currentAccount).sendRequest(listReq, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
if (latch != null) {
latch.countDown();
}
if (response != null) {
limitBoosts = 20;
TL_stories.TL_premium_boostsList list = (TL_stories.TL_premium_boostsList) response;
MessagesController.getInstance(currentAccount).putUsers(list.users, false);
lastBoostsOffset = list.next_offset;
boosters.addAll(list.boosts);
int shownBoosts = 0;
for (TL_stories.TL_boost booster : boosters) {
shownBoosts += booster.multiplier > 0 ? booster.multiplier : 1;
}
nextBoostRemaining = Math.max(0, list.count - shownBoosts);
hasBoostsNext = !TextUtils.isEmpty(list.next_offset) && nextBoostRemaining > 0;
totalBoosts = list.count;
if (after != null) {
after.run();
}
}
}), ConnectionsManager.RequestFlagFailOnServerErrors);
}
private void loadOnlyGifts(CountDownLatch latch, Runnable after) {
TL_stories.TL_premium_getBoostsList listReq = new TL_stories.TL_premium_getBoostsList();
listReq.limit = limitGifts;
listReq.gifts = true;
listReq.offset = lastGiftsOffset;
listReq.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId);
ConnectionsManager.getInstance(currentAccount).sendRequest(listReq, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
if (latch != null) {
latch.countDown();
}
if (response != null) {
limitGifts = 20;
TL_stories.TL_premium_boostsList list = (TL_stories.TL_premium_boostsList) response;
MessagesController.getInstance(currentAccount).putUsers(list.users, false);
lastGiftsOffset = list.next_offset;
gifts.addAll(list.boosts);
int shownGifts = 0;
for (TL_stories.TL_boost booster : gifts) {
shownGifts += booster.multiplier > 0 ? booster.multiplier : 1;
}
nextGiftsRemaining = Math.max(0, list.count - shownGifts);
hasGiftsNext = !TextUtils.isEmpty(list.next_offset) && nextGiftsRemaining > 0;
totalGifts = list.count;
if (after != null) {
after.run();
}
}
}), ConnectionsManager.RequestFlagFailOnServerErrors);
}
@Override
public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.boostByChannelCreated) {
TLRPC.Chat chat = (TLRPC.Chat) args[0];
boolean isGiveaway = (boolean) args[1];
List<BaseFragment> fragmentStack = getParentLayout().getFragmentStack();
BaseFragment chatEditFragment = fragmentStack.size() >= 2 ? fragmentStack.get(fragmentStack.size() - 2) : null;
if (chatEditFragment instanceof ChatEditActivity) {
getParentLayout().removeFragmentFromStack(chatEditFragment);
}
fragmentStack = getParentLayout().getFragmentStack();
BaseFragment secondFragment = fragmentStack.size() >= 2 ? fragmentStack.get(fragmentStack.size() - 2) : null;
if (isGiveaway) {
BaseFragment thirdFragment = fragmentStack.size() >= 3 ? fragmentStack.get(fragmentStack.size() - 3) : null;
if (secondFragment instanceof ProfileActivity) {
getParentLayout().removeFragmentFromStack(secondFragment);
}
finishFragment();
if (thirdFragment instanceof ChatActivity) {
BoostDialogs.showBulletin(thirdFragment, chat, true);
}
if (secondFragment instanceof ChatActivity) {
BoostDialogs.showBulletin(secondFragment, chat, true);
}
} else {
finishFragment();
if (secondFragment instanceof ProfileActivity || secondFragment instanceof ChatActivity) {
BoostDialogs.showBulletin(secondFragment, chat, false);
}
}
} else if (id == NotificationCenter.chatWasBoostedByUser) {
if (dialogId == (long) args[2]) {
boostsStatus = (TL_stories.TL_premium_boostsStatus) args[0];
canApplyBoost = (ChannelBoostsController.CanApplyBoost) args[1];
}
}
}
@Override
public boolean onFragmentCreate() {
getNotificationCenter().addObserver(this, NotificationCenter.boostByChannelCreated);
getNotificationCenter().addObserver(this, NotificationCenter.chatWasBoostedByUser);
return super.onFragmentCreate();
}
@Override
public void onFragmentDestroy() {
getNotificationCenter().removeObserver(this, NotificationCenter.boostByChannelCreated);
getNotificationCenter().removeObserver(this, NotificationCenter.chatWasBoostedByUser);
super.onFragmentDestroy();
}
private class ItemInternal extends AdapterWithDiffUtils.Item {
String title;
TL_stories.TL_boost booster;
TL_stories.TL_prepaidGiveaway prepaidGiveaway;
boolean isLast;
int tab;
public ItemInternal(int viewType, String title) {
super(viewType, false);
this.title = title;
}
public ItemInternal(int viewType, TL_stories.TL_boost booster, boolean isLast, int tab) {
super(viewType, true);
this.booster = booster;
this.isLast = isLast;
this.tab = tab;
}
public ItemInternal(int viewType, TL_stories.TL_prepaidGiveaway prepaidGiveaway, boolean isLast) {
super(viewType, true);
this.prepaidGiveaway = prepaidGiveaway;
this.isLast = isLast;
}
public ItemInternal(int viewType, boolean selectable) {
super(viewType, selectable);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ItemInternal that = (ItemInternal) o;
if (prepaidGiveaway != null && that.prepaidGiveaway != null) {
return prepaidGiveaway.id == that.prepaidGiveaway.id && isLast == that.isLast;
} else if (booster != null && that.booster != null) {
return booster.id.hashCode() == that.booster.id.hashCode() && isLast == that.isLast && tab == that.tab;
} else {
return true;
}
}
@Override
public int hashCode() {
return Objects.hash(title, booster, prepaidGiveaway, isLast, tab);
}
}
public void createEmptyView(Context context) {
progressLayout = new LinearLayout(context);
progressLayout.setOrientation(LinearLayout.VERTICAL);
View view = new View(context) {
private final CircularProgressDrawable drawable;
{
drawable = new CircularProgressDrawable(dp(30), dp(3), Theme.getColor(Theme.key_dialogTextBlue));
}
@Override
protected void onDraw(Canvas canvas) {
drawable.setBounds(0, 0, getWidth(), getHeight());
drawable.setAlpha(255);
drawable.draw(canvas);
invalidate();
super.onDraw(canvas);
}
};
progressLayout.addView(view, LayoutHelper.createLinear(100, 100, Gravity.CENTER, 0, 120, 0, 0));
((ViewGroup) fragmentView).addView(progressLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER));
}
@Override
protected RecyclerView.Adapter<?> createAdapter() {
return adapter;
}
private void resetHeader(boolean animate) {
if (getContext() == null) return;
if (limitPreviewView == null) {
limitPreviewView = new LimitPreviewView(getContext(), R.drawable.filled_limit_boost, 0, 0, resourceProvider);
limitPreviewView.isStatistic = true;
limitPreviewView.setDarkGradientProvider(this::setDarkGradientLocation);
}
if (limitPreviewView.getParent() != null) {
((ViewGroup) limitPreviewView.getParent()).removeView(limitPreviewView);
}
if (boostsStatus != null) {
limitPreviewView.setBoosts(boostsStatus, false);
if (animate) {
limitPreviewView.setAlpha(0f);
limitPreviewView.animate().alpha(1f).start();
}
}
CharSequence title = LocaleController.getString(isChannel() ? R.string.BoostingBoostForChannels : R.string.BoostingBoostForGroups);
CharSequence subTitle = AndroidUtilities.replaceTags(LocaleController.getString(isChannel() ? R.string.BoostingBoostForChannelsInfo : R.string.BoostingBoostForGroupsInfo));
View aboveTitleView = new FrameLayout(getContext()) {
{
addView(boostsStatus != null ? limitPreviewView : new View(getContext()), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, boostsStatus != null ? LayoutHelper.WRAP_CONTENT : 110, 0, 8, 46, 8, 33));
}
};
View underSubTitleView = new FrameLayout(getContext()) {
private final HeaderButtonView buttonView1;
private final HeaderButtonView buttonView2;
private final HeaderButtonView buttonView3;
{
setWillNotDraw(false);
buttonView1 = new HeaderButtonView(getContext());
buttonView2 = new HeaderButtonView(getContext());
buttonView3 = new HeaderButtonView(getContext());
buttonView1.setTextAndIcon(LocaleController.getString(R.string.BoostBtn), R.drawable.filled_boost_plus);
buttonView2.setTextAndIcon(LocaleController.getString(R.string.GiveawayBtn), R.drawable.filled_gift_premium);
buttonView3.setTextAndIcon(LocaleController.getString(R.string.FeaturesBtn), R.drawable.filled_info);
buttonView1.setOnClickListener(v -> {
LimitReachedBottomSheet.openBoostsForUsers(BoostsActivity.this, true, dialogId, canApplyBoost, boostsStatus, null);
});
buttonView2.setOnClickListener(v -> {
updateDialogVisibility(true);
BoostPagerBottomSheet.show(BoostsActivity.this, dialogId, resourceProvider);
BoostPagerBottomSheet.getInstance().setOnHideListener(dialog -> updateDialogVisibility(false));
});
buttonView3.setOnClickListener(v -> {
LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(BoostsActivity.this, getContext(), TYPE_FEATURES, currentAccount, getResourceProvider());
limitReachedBottomSheet.setBoostsStats(boostsStatus, true);
limitReachedBottomSheet.setDialogId(dialogId);
showDialog(limitReachedBottomSheet);
});
LinearLayout linearLayout = new LinearLayout(getContext());
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
linearLayout.addView(buttonView1, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 6, 0, 6, 0));
if (MessagesController.getInstance(currentAccount).giveawayGiftsPurchaseAvailable && ChatObject.hasAdminRights(currentChat)) {
linearLayout.addView(buttonView2, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 6, 0, 6, 0));
}
linearLayout.addView(buttonView3, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 6, 0, 6, 0));
addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 19, 0, 0));
}
};
configureHeader(title, subTitle, aboveTitleView, underSubTitleView);
}
private class HeaderButtonView extends FrameLayout {
private final ImageView imageView;
private final TextView textView;
private final RectF rect = new RectF();
public HeaderButtonView(@NonNull Context context) {
super(context);
setWillNotDraw(false);
imageView = new ImageView(context);
textView = new TextView(context);
textView.setTextColor(Color.WHITE);
textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
addView(imageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL));
addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 25, 0, 0));
setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8));
setMinimumWidth(AndroidUtilities.dp(100));
setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(10), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Color.BLACK, 80)));
}
public void setTextAndIcon(CharSequence text, int icon) {
textView.setText(text);
imageView.setImageDrawable(ContextCompat.getDrawable(getContext(), icon));
}
@Override
public void draw(Canvas canvas) {
rect.set(0, 0, getWidth(), getHeight());
Paint p = setDarkGradientLocation((((ViewGroup) getParent()).getX() + getX()), ((ViewGroup) getParent().getParent().getParent()).getY());
canvas.drawRoundRect(rect, AndroidUtilities.dp(10), AndroidUtilities.dp(10), p);
invalidate();
super.draw(canvas);
}
}
@Override
public View createView(Context context) {
View rootView = super.createView(context);
resetHeader(false);
DefaultItemAnimator defaultItemAnimator = new DefaultItemAnimator();
defaultItemAnimator.setSupportsChangeAnimations(false);
defaultItemAnimator.setDelayAnimations(false);
listView.setItemAnimator(defaultItemAnimator);
listView.setOnItemClickListener((view, position) -> {
if (view instanceof GiftedUserCell) {
GiftedUserCell cell = (GiftedUserCell) view;
TL_stories.TL_boost boost = cell.getBoost();
if (((boost.gift || boost.giveaway) && boost.user_id >= 0) || boost.unclaimed) {
TLRPC.TL_payments_checkedGiftCode giftCode = new TLRPC.TL_payments_checkedGiftCode();
giftCode.giveaway_msg_id = boost.giveaway_msg_id;
giftCode.to_id = boost.user_id;
giftCode.from_id = MessagesController.getInstance(UserConfig.selectedAccount).getPeer(-currentChat.id);
giftCode.date = boost.date;
giftCode.via_giveaway = boost.giveaway;
giftCode.months = (boost.expires - boost.date) / 30 / 86400;
if (boost.unclaimed) {
giftCode.to_id = NO_USER_ID;
giftCode.flags = -1;
} else {
giftCode.boost = boost;
}
new GiftInfoBottomSheet(this, false, true, giftCode, boost.used_gift_slug).show();
} else if (boost.giveaway && boost.user_id == NO_USER_ID) {
final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(getParentActivity(), getResourceProvider());
layout.setAnimation(R.raw.chats_infotip, 36, 36);
layout.textView.setText(LocaleController.getString("BoostingRecipientWillBeSelected", R.string.BoostingRecipientWillBeSelected));
layout.textView.setSingleLine(false);
layout.textView.setMaxLines(2);
Bulletin.make(this, layout, Bulletin.DURATION_LONG).show();
} else if (!boost.gift && !boost.giveaway) {
presentFragment(ProfileActivity.of(cell.getDialogId()));
}
}
if (view instanceof TextCell) {
BoostPagerBottomSheet.show(this, dialogId, resourceProvider);
}
if (view instanceof GiveawayCell) {
BoostPagerBottomSheet.show(this, resourceProvider, dialogId, ((GiveawayCell) view).getPrepaidGiveaway());
}
if (items.get(position).viewType == SHOW_MORE_VIEW_TYPE) {
loadUsers(selectedTab == TAB_GIFTS);
}
});
createEmptyView(getContext());
loadStatistic();
updateRows(false);
return rootView;
}
}

View file

@ -24,6 +24,7 @@ import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.ShapeDrawable;
import android.hardware.Camera;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
@ -74,6 +75,7 @@ import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.Utilities;
import org.telegram.messenger.camera.CameraController;
import org.telegram.messenger.camera.CameraSession;
import org.telegram.messenger.camera.CameraSessionWrapper;
import org.telegram.messenger.camera.CameraView;
import org.telegram.messenger.camera.Size;
import org.telegram.ui.ActionBar.ActionBar;
@ -710,7 +712,7 @@ public class CameraScanActivity extends BaseFragment {
if (cameraView == null) {
return;
}
CameraSession session = cameraView.getCameraSession();
CameraSessionWrapper session = cameraView.getCameraSession();
if (session != null) {
ShapeDrawable shapeDrawable = (ShapeDrawable) flashButton.getBackground();
if (flashAnimator != null) {
@ -732,10 +734,10 @@ public class CameraScanActivity extends BaseFragment {
flashAnimator.start();
if (flashButton.getTag() == null) {
flashButton.setTag(1);
session.setTorchEnabled(true);
session.setCurrentFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
} else {
flashButton.setTag(null);
session.setTorchEnabled(false);
session.setCurrentFlashMode(Camera.Parameters.FLASH_MODE_OFF);
}
}
});

View file

@ -62,7 +62,7 @@ import android.text.style.CharacterStyle;
import android.text.style.ClickableSpan;
import android.text.style.LeadingMarginSpan;
import android.text.style.URLSpan;
import android.util.Log;
import android.util.Pair;
import android.util.Property;
import android.util.SparseArray;
import android.util.StateSet;
@ -154,6 +154,7 @@ import org.telegram.ui.Components.MessageBackgroundDrawable;
import org.telegram.ui.Components.MotionBackgroundDrawable;
import org.telegram.ui.Components.MsgClockDrawable;
import org.telegram.ui.Components.Point;
import org.telegram.ui.Components.Premium.boosts.BoostCounterSpan;
import org.telegram.ui.Components.Premium.boosts.cells.msg.GiveawayMessageCell;
import org.telegram.ui.Components.Premium.boosts.cells.msg.GiveawayResultsMessageCell;
import org.telegram.ui.Components.QuoteHighlight;
@ -473,6 +474,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
default void didPressViaBot(ChatMessageCell cell, String username) {
}
default void didPressBoostCounter(ChatMessageCell cell) {
}
default void didPressChannelAvatar(ChatMessageCell cell, TLRPC.Chat chat, int postId, float touchX, float touchY) {
}
@ -937,6 +941,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
private int nameLayoutSelectorColor;
private Drawable nameLayoutSelector;
private boolean nameLayoutPressed;
private boolean boostCounterPressed;
private int boostCounterSelectorColor;
private Drawable boostCounterLayoutSelector;
private int nameStatusSelectorColor;
private Drawable nameStatusSelector;
@ -1262,6 +1269,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
private StaticLayout nameLayout;
private int nameLayoutWidth;
private StaticLayout adminLayout;
private RectF boostCounterBounds;
private BoostCounterSpan boostCounterSpan;
private int nameWidth;
private float nameOffsetX;
private float nameX;
@ -1666,6 +1675,38 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
return new int[]{start, end};
}
private boolean checkAdminMotionEvent(MotionEvent event) {
if (adminLayout == null || boostCounterBounds == null || currentUser == null && currentChat == null) {
boostCounterPressed = false;
return false;
}
final boolean pressed = boostCounterBounds.contains((int) event.getX(), (int) event.getY());
if (event.getAction() == MotionEvent.ACTION_DOWN) {
SpannableString spannableString = new SpannableString(adminLayout.getText());
BoostCounterSpan[] spans = spannableString.getSpans(0, spannableString.length(), BoostCounterSpan.class);
boostCounterPressed = pressed && spans != null && spans.length > 0;
if (boostCounterPressed) {
if (boostCounterLayoutSelector != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
boostCounterLayoutSelector.setHotspot((int) event.getX(), (int) event.getY());
}
boostCounterLayoutSelector.setState(pressedState);
}
}
} else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
if (event.getAction() == MotionEvent.ACTION_UP && boostCounterPressed) {
if (delegate != null) {
delegate.didPressBoostCounter(this);
}
}
if (boostCounterLayoutSelector != null) {
boostCounterLayoutSelector.setState(StateSet.NOTHING);
}
boostCounterPressed = false;
}
return boostCounterPressed;
}
private boolean checkNameMotionEvent(MotionEvent event) {
if (!drawNameLayout || nameLayout == null || nameLayoutSelector == null || currentUser == null && currentChat == null) {
nameLayoutPressed = false;
@ -2301,7 +2342,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
if (delegate != null) {
delegate.didPressInstantButton(this, drawInstantViewType);
}
} else if (drawPhotoImage && authorLayout == null && titleLayout == null && descriptionLayout == null && siteNameLayout == null) {
} else if (drawPhotoImage && (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || authorLayout == null && titleLayout == null && descriptionLayout == null && siteNameLayout == null)) {
if (delegate != null) {
delegate.didPressImage(this, lastTouchX, lastTouchY);
}
@ -3421,6 +3462,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
disallowLongPress = true;
}
}
if(!result) {
result = checkAdminMotionEvent(event);
}
if (!result) {
result = checkNameMotionEvent(event);
}
@ -5022,6 +5066,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
isReplyQuote = false;
replyNameLayout = null;
adminLayout = null;
boostCounterBounds = null;
boostCounterSpan = null;
checkOnlyButtonPressed = false;
replyTextLayout = null;
AnimatedEmojiSpan.release(this, animatedEmojiReplyStack);
@ -5424,6 +5470,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
} else if ("telegram_channel_boost".equals(webpageType)) {
drawInstantView = true;
drawInstantViewType = 18;
} else if ("telegram_group_boost".equals(webpageType)) {
drawInstantView = true;
drawInstantViewType = 22;
} else if ("telegram_giftcode".equals(webpageType)) {
drawInstantView = true;
drawInstantViewType = 20;
@ -5787,8 +5836,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
"article".equals(type) || "telegram_bot".equals(type) ||
"telegram_user".equals(type) || "telegram_channel".equals(type) ||
"telegram_megagroup".equals(type) || "telegram_voicechat".equals(type) ||
"telegram_livestream".equals(type) || "telegram_channel_boost".equals(type);
smallImage = !slideshow && (!drawInstantView || drawInstantViewType == 1 || drawInstantViewType == 2 || drawInstantViewType == 9 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 18 || drawInstantViewType == 20) && document == null && isSmallImageType;
"telegram_livestream".equals(type) || "telegram_channel_boost".equals(type) || "telegram_group_boost".equals(type);
smallImage = !slideshow && (!drawInstantView || drawInstantViewType == 1 || drawInstantViewType == 2 || drawInstantViewType == 9 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 18 || drawInstantViewType == 20 || drawInstantViewType == 22) && document == null && isSmallImageType;
TLRPC.MessageMedia media = MessageObject.getMedia(messageObject.messageOwner);
if (media != null) {
if (media.force_large_media) {
@ -5835,6 +5884,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
if (drawInstantViewType == 18) {
site_name = LocaleController.getString("BoostChannel", R.string.BoostChannel);
} else if (drawInstantViewType == 22) {
site_name = LocaleController.getString("BoostGroup", R.string.BoostGroup);
} else if (drawInstantViewType == 11) {
site_name = LocaleController.getString("VoipChannelVoiceChat", R.string.VoipChannelVoiceChat);
} else if (drawInstantViewType == 9) {
@ -6029,15 +6080,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
totalHeight += height;
descriptionLayoutWidth = 0;
descriptionLayoutLeft = descriptionLayout.getWidth();
int descriptionLayoutLeft = descriptionLayout.getWidth(), descriptionLayoutRight = 0;
for (int a = 0; a < descriptionLayout.getLineCount(); a++) {
descriptionLayoutLeft = (int) Math.min(descriptionLayoutLeft, descriptionLayout.getLineLeft(a));
float width = Math.min(descriptionLayout.getWidth(), descriptionLayout.getLineWidth(a));
int addright = 0;
if (a < restLines || restLines != 0 && descriptionLayoutLeft != 0 && isSmallImage) {
width += smallImageSide + smallSideMargin;
addright = smallImageSide + smallSideMargin;
}
descriptionLayoutWidth = (int) Math.max(descriptionLayoutWidth, width);
descriptionLayoutRight = (int) Math.max(descriptionLayoutRight, descriptionLayout.getLineRight(a) + addright);
}
descriptionLayoutWidth = Math.abs(descriptionLayoutRight - descriptionLayoutLeft);
this.descriptionLayoutLeft = descriptionLayoutLeft;
if (maxWebWidth < descriptionLayoutWidth + additinalWidth) {
maxWebWidth = descriptionLayoutWidth + additinalWidth;
}
@ -8983,6 +9036,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
if (nameLayoutSelector != null) {
nameLayoutSelector.setState(StateSet.NOTHING);
}
if (boostCounterLayoutSelector != null) {
boostCounterLayoutSelector.setState(StateSet.NOTHING);
}
resetCodeSelectors();
if (replyBounce != null) {
replyBounce.setPressed(false);
@ -10099,7 +10155,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
str = LocaleController.getString("OpenLink").toUpperCase();
} else if (drawInstantViewType == 17) {
str = LocaleController.getString("ViewStory").toUpperCase();
} else if (drawInstantViewType == 18) {
} else if (drawInstantViewType == 18 || drawInstantViewType == 22) {
str = LocaleController.getString("BoostLinkButton", R.string.BoostLinkButton);
} else if (drawInstantViewType == 19) {
str = LocaleController.getString("BoostingHowItWork", R.string.BoostingHowItWork);
@ -11820,8 +11876,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
Theme.chat_replyNamePaint.setColor(linkLine.check(currentMessageObject, currentUser, currentChat, resourcesProvider, ReplyMessageLine.TYPE_LINK));
final boolean drawPhotoImageBefore = drawInstantView && (drawInstantViewType != 9 && drawInstantViewType != 2 && drawInstantViewType != 13 && drawInstantViewType != 11 && drawInstantViewType != 1 && drawInstantViewType != 18) || drawInstantViewType == 6 && imageBackgroundColor != 0;
final boolean drawPhotoImageAfter = !drawInstantView || drawInstantViewType == 9 || drawInstantViewType == 2 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 1 || drawInstantViewType == 18 || isSmallImage;
final boolean drawPhotoImageBefore = drawInstantView && (drawInstantViewType != 9 && drawInstantViewType != 2 && drawInstantViewType != 13 && drawInstantViewType != 11 && drawInstantViewType != 1 && drawInstantViewType != 18 && drawInstantViewType != 22) || drawInstantViewType == 6 && imageBackgroundColor != 0;
final boolean drawPhotoImageAfter = !drawInstantView || drawInstantViewType == 9 || drawInstantViewType == 2 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 1 || drawInstantViewType == 18 || drawInstantViewType == 22 || isSmallImage;
boolean restore = false;
boolean drawInstantButtonInside = false;
@ -14499,27 +14555,39 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
if (nameWidth < 0) {
nameWidth = AndroidUtilities.dp(100);
}
int adminWidth;
String adminString;
int adminWidth = 0;
SpannableStringBuilder adminString = null;
String adminLabel;
if (isMegagroup && currentChat != null && messageObject.messageOwner.post_author != null && currentChat.id == -currentMessageObject.getFromChatId()) {
adminString = messageObject.messageOwner.post_author.replace("\n", "");
adminWidth = (int) Math.ceil(Theme.chat_adminPaint.measureText(adminString));
nameWidth -= adminWidth;
adminString = new SpannableStringBuilder(messageObject.messageOwner.post_author.replace("\n", ""));
} else if (isMegagroup && currentChat != null && currentMessageObject.isForwardedChannelPost()) {
adminString = LocaleController.getString("DiscussChannel", R.string.DiscussChannel);
adminWidth = (int) Math.ceil(Theme.chat_adminPaint.measureText(adminString));
nameWidth -= adminWidth;
adminString = new SpannableStringBuilder(LocaleController.getString("DiscussChannel", R.string.DiscussChannel));
} else if ((currentUser != null || currentChat != null) && !currentMessageObject.isOutOwner() && !currentMessageObject.isAnyKindOfSticker() && currentMessageObject.type != MessageObject.TYPE_ROUND_VIDEO && delegate != null && (adminLabel = delegate.getAdminRank(currentUser != null ? currentUser.id : currentChat.id)) != null) {
if (adminLabel.length() == 0) {
adminLabel = LocaleController.getString("ChatAdmin", R.string.ChatAdmin);
}
adminString = adminLabel;
adminWidth = (int) Math.ceil(Theme.chat_adminPaint.measureText(adminString));
adminString = new SpannableStringBuilder(adminLabel);
}
int boosts = currentMessageObject.messageOwner.from_boosts_applied;
if (boosts > 0) {
if (adminString == null) {
adminString = new SpannableStringBuilder();
}
Pair<SpannableString, BoostCounterSpan> pair = BoostCounterSpan.create(this, Theme.chat_namePaint, boosts);
boostCounterSpan = pair.second;
boostCounterSpan.isRtl = AndroidUtilities.isRTL(adminString);
if (boostCounterSpan.isRtl) {
adminString.insert(0, pair.first);
} else {
adminString.append(pair.first);
}
}
if (adminString != null) {
StaticLayout staticLayout = new StaticLayout(adminString, Theme.chat_adminPaint, dp(300), Layout.Alignment.ALIGN_NORMAL, 0f, 0f, false);
adminWidth = (int) staticLayout.getLineWidth(0);
nameWidth -= adminWidth;
} else {
adminString = null;
adminWidth = 0;
}
currentNameStatus = null;
@ -14585,8 +14653,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
if (adminString != null) {
adminLayout = new StaticLayout(adminString, Theme.chat_adminPaint, adminWidth + AndroidUtilities.dp(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
nameWidth += adminLayout.getLineWidth(0) + AndroidUtilities.dp(8);
boostCounterBounds = new RectF();
} else {
adminLayout = null;
boostCounterBounds = null;
}
} catch (Exception e) {
FileLog.e(e);
@ -14797,7 +14867,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
final TextPaint textPaint = isReplyQuote && messageObject.shouldDrawWithoutBackground() ? Theme.chat_quoteTextPaint : Theme.chat_replyTextPaint;
if (messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.story_id != 0) {
name = getNameFromDialogId(messageObject.messageOwner.reply_to.user_id);
name = getNameFromDialogId(DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.peer));
if (messageObject.messageOwner.replyStory == null || messageObject.messageOwner.replyStory instanceof TL_stories.TL_storyItemDeleted) {
if (messageObject.messageOwner.replyStory == null) {
stringFinalText = LocaleController.getString("Loading", R.string.Loading);
@ -16916,7 +16986,24 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
Theme.chat_adminPaint.setColor(color);
canvas.save();
final float ax = end - AndroidUtilities.dp(11) - adminLayout.getLineWidth(0);
final float ax = end - dp(11) - adminLayout.getLineWidth(0);
final float ay = nameY + dp(0.5f);
if (boostCounterSpan != null && boostCounterBounds != null) {
final float bx = end - dp(boostCounterSpan.isRtl ? 5f : 7.5f) - boostCounterSpan.getWidth();
boostCounterBounds.set(bx, ay, bx + boostCounterSpan.getWidth(), ay + adminLayout.getHeight());
int selectorColor = Theme.multAlpha(Theme.chat_namePaint.getColor(), .12f);
if (boostCounterLayoutSelector == null) {
boostCounterLayoutSelector = Theme.createRadSelectorDrawable(boostCounterSelectorColor = selectorColor, 6, 6);
boostCounterLayoutSelector.setCallback(this);
} else if (boostCounterSelectorColor != selectorColor) {
Theme.setSelectorDrawableColor(boostCounterLayoutSelector, boostCounterSelectorColor = selectorColor, true);
}
boostCounterLayoutSelector.setBounds((int) boostCounterBounds.left - dp(4), (int) boostCounterBounds.top, (int) (int) boostCounterBounds.right, (int) boostCounterBounds.bottom);
boostCounterLayoutSelector.setAlpha((int) (0xFF * nameAlpha));
boostCounterLayoutSelector.draw(canvas);
}
canvas.translate(ax, nameY + AndroidUtilities.dp(0.5f));
if (transitionParams.animateSign) {
Theme.chat_adminPaint.setAlpha((int) (Color.alpha(color) * transitionParams.animateChangeProgress));
@ -20047,6 +20134,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
AndroidUtilities.rectTmp.set(radialProgress.getProgressRect());
AndroidUtilities.rectTmp.inset(-dp(15), -dp(15));
canvas.saveLayerAlpha(AndroidUtilities.rectTmp, (int) (0xFF * radialProgressAlpha), Canvas.ALL_SAVE_FLAG);
} else {
canvas.save();
final int type = currentMessageObject.type;
if (drawPhotoImage && (type == MessageObject.TYPE_VIDEO || type == MessageObject.TYPE_PHOTO || type == MessageObject.TYPE_GIF)) {
canvas.clipRect(photoImage.getImageX(), photoImage.getImageY(), photoImage.getImageX2(), photoImage.getImageY2());
}
}
if (currentMessageObject.needDrawBluredPreview()) {
@ -20091,9 +20184,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
oncePeriod.draw(canvas, 1f);
canvas.restore();
canvas.restore();
}
canvas.restore();
}
protected void drawPhotoBlurRect(Canvas canvas, RectF rect) {

View file

@ -403,6 +403,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
private TLRPC.EncryptedChat encryptedChat;
private CharSequence lastPrintString;
private int printingStringType;
private boolean draftVoice;
private TLRPC.DraftMessage draftMessage;
private final AnimatedFloat premiumBlockedT = new AnimatedFloat(this, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
@ -1228,24 +1229,29 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
}
if (isTopic) {
draftMessage = MediaDataController.getInstance(currentAccount).getDraft(currentDialogId, getTopicId());
draftVoice = MediaDataController.getInstance(currentAccount).getDraftVoice(currentDialogId, getTopicId()) != null;
draftMessage = !draftVoice ? MediaDataController.getInstance(currentAccount).getDraft(currentDialogId, getTopicId()) : null;
if (draftMessage != null && TextUtils.isEmpty(draftMessage.message)) {
draftMessage = null;
}
} else if (isDialogCell || isSavedDialogCell) {
draftMessage = MediaDataController.getInstance(currentAccount).getDraft(currentDialogId, 0);
draftVoice = MediaDataController.getInstance(currentAccount).getDraftVoice(currentDialogId, getTopicId()) != null;
draftMessage = !draftVoice ? MediaDataController.getInstance(currentAccount).getDraft(currentDialogId, 0) : null;
} else {
draftVoice = false;
draftMessage = null;
}
if (draftMessage != null && (TextUtils.isEmpty(draftMessage.message) && (draftMessage.reply_to == null || draftMessage.reply_to.reply_to_msg_id == 0) || lastDate > draftMessage.date && unreadCount != 0) ||
if ((draftVoice || draftMessage != null) && (!draftVoice && draftMessage != null && TextUtils.isEmpty(draftMessage.message) && (draftMessage.reply_to == null || draftMessage.reply_to.reply_to_msg_id == 0) || draftMessage != null && lastDate > draftMessage.date && unreadCount != 0) ||
ChatObject.isChannel(chat) && !chat.megagroup && !chat.creator && (chat.admin_rights == null || !chat.admin_rights.post_messages) ||
chat != null && (chat.left || chat.kicked) || forbidDraft || ChatObject.isForum(chat) && !isTopic) {
draftMessage = null;
draftVoice = false;
}
if (isForumCell()) {
draftMessage = null;
draftVoice = false;
needEmoji = true;
updateMessageThumbs();
messageNameString = getMessageNameString();
@ -1285,10 +1291,10 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
lastPrintString = null;
printingStringType = -1;
}
if (draftMessage != null) {
if (draftVoice || draftMessage != null) {
checkMessage = false;
messageNameString = LocaleController.getString("Draft", R.string.Draft);
if (TextUtils.isEmpty(draftMessage.message)) {
if (draftMessage != null && TextUtils.isEmpty(draftMessage.message)) {
if (useForceThreeLines || SharedConfig.useThreeLinesLayout) {
messageString = "";
} else {
@ -1297,14 +1303,25 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
messageString = stringBuilder;
}
} else {
String mess = draftMessage.message;
if (mess.length() > 150) {
mess = mess.substring(0, 150);
String mess;
if (draftVoice) {
mess = LocaleController.getString(R.string.AttachAudio);
} else if (draftMessage != null) {
mess = draftMessage.message;
if (mess.length() > 150) {
mess = mess.substring(0, 150);
}
} else {
mess = "";
}
Spannable messSpan = new SpannableStringBuilder(mess);
MediaDataController.addTextStyleRuns(draftMessage, messSpan, TextStyleSpan.FLAG_STYLE_SPOILER | TextStyleSpan.FLAG_STYLE_STRIKE);
if (draftMessage != null && draftMessage.entities != null) {
MediaDataController.addAnimatedEmojiSpans(draftMessage.entities, messSpan, currentMessagePaint == null ? null : currentMessagePaint.getFontMetricsInt());
if (draftMessage != null) {
MediaDataController.addTextStyleRuns(draftMessage, messSpan, TextStyleSpan.FLAG_STYLE_SPOILER | TextStyleSpan.FLAG_STYLE_STRIKE);
if (draftMessage != null && draftMessage.entities != null) {
MediaDataController.addAnimatedEmojiSpans(draftMessage.entities, messSpan, currentMessagePaint == null ? null : currentMessagePaint.getFontMetricsInt());
}
} else if (draftVoice) {
messSpan.setSpan(new ForegroundColorSpanThemable(Theme.key_chats_actionMessage, resourcesProvider), 0, messSpan.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
SpannableStringBuilder stringBuilder = formatInternal(messageFormatType, AndroidUtilities.replaceNewLines(messSpan), messageNameString);
@ -1556,7 +1573,13 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
currentMessagePaint = Theme.dialogs_messagePrintingPaint[paintIndex];
} else {
if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGiveaway) {
messageString = LocaleController.getString("BoostingGiveawayChannelStarted", R.string.BoostingGiveawayChannelStarted);
boolean isChannel;
if (message.messageOwner.fwd_from != null && message.messageOwner.fwd_from.from_id instanceof TLRPC.TL_peerChannel) {
isChannel = ChatObject.isChannelAndNotMegaGroup(message.messageOwner.fwd_from.from_id.channel_id, currentAccount);
} else {
isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
}
messageString = LocaleController.getString(isChannel ? R.string.BoostingGiveawayChannelStarted : R.string.BoostingGiveawayGroupStarted);
} else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGiveawayResults) {
messageString = LocaleController.getString("BoostingGiveawayResults", R.string.BoostingGiveawayResults);
} else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) {
@ -2800,7 +2823,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
}
if (!continueUpdate && (mask & MessagesController.UPDATE_MASK_CHAT) != 0 && chat != null) {
TLRPC.Chat newChat = MessagesController.getInstance(currentAccount).getChat(chat.id);
if ((newChat.call_active && newChat.call_not_empty) != hasCall) {
if ((newChat != null && newChat.call_active && newChat.call_not_empty) != hasCall) {
continueUpdate = true;
}
}
@ -5162,14 +5185,17 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
}
}
boolean draftVoice = false;
TLRPC.DraftMessage draftMessage = null;
if (isTopic) {
draftMessage = MediaDataController.getInstance(currentAccount).getDraft(currentDialogId, getTopicId());
draftVoice = MediaDataController.getInstance(currentAccount).getDraftVoice(currentDialogId, getTopicId()) != null;
draftMessage = !draftVoice ? MediaDataController.getInstance(currentAccount).getDraft(currentDialogId, getTopicId()) : null;
if (draftMessage != null && TextUtils.isEmpty(draftMessage.message)) {
draftMessage = null;
}
} else if (isDialogCell) {
draftMessage = MediaDataController.getInstance(currentAccount).getDraft(currentDialogId, 0);
draftVoice = MediaDataController.getInstance(currentAccount).getDraftVoice(currentDialogId, 0) != null;
draftMessage = !draftVoice ? MediaDataController.getInstance(currentAccount).getDraft(currentDialogId, 0) : null;
}
int draftHash = draftMessage == null ? 0 : draftMessage.message.hashCode() + (draftMessage.reply_to != null ? (draftMessage.reply_to.reply_to_msg_id << 16) : 0);
boolean hasCall = chat != null && chat.call_active && chat.call_not_empty;
@ -5184,7 +5210,8 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
lastTopicsCount == topicCount &&
draftHash == lastDrawnDraftHash &&
lastDrawnPinned == drawPin &&
lastDrawnHasCall == hasCall) {
lastDrawnHasCall == hasCall &&
DialogCell.this.draftVoice == draftVoice) {
return false;
}

View file

@ -19,6 +19,7 @@ import androidx.annotation.NonNull;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.LayoutHelper;
@ -53,6 +54,15 @@ public class DialogsHintCell extends FrameLayout {
messageView.setEllipsize(TextUtils.TruncateAt.END);
contentView.addView(messageView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, Gravity.TOP));
NotificationCenter.getGlobalInstance().listen(this, NotificationCenter.emojiLoaded, args -> {
if (titleView != null) {
titleView.invalidate();
}
if (messageView != null) {
messageView.invalidate();
}
});
chevronView = new ImageView(context);
chevronView.setImageResource(R.drawable.arrow_newchat);
addView(chevronView, LayoutHelper.createFrame(16, 16, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL));
@ -83,15 +93,10 @@ public class DialogsHintCell extends FrameLayout {
closeView.setVisibility(GONE);
}
public void setChristmasStyle(OnClickListener closeListener) {
public void setOnCloseListener(OnClickListener closeListener) {
chevronView.setVisibility(INVISIBLE);
closeView.setVisibility(VISIBLE);
closeView.setOnClickListener(closeListener);
Emoji.EmojiDrawable drawable = Emoji.getEmojiDrawable("\uD83C\uDF84");
if (drawable != null) {
drawable.setBounds(dp(2), -dp(2), Emoji.drawImgSize + dp(2), Emoji.drawImgSize - dp(2));
titleView.setCompoundDrawables(null, null, drawable, null);
}
}
@Override

View file

@ -112,6 +112,16 @@ public class DrawerActionCell extends FrameLayout {
}
}
public void setTextAndIcon(int id, CharSequence text, int resId) {
currentId = id;
try {
textView.setText(text);
imageView.setImageResource(resId);
} catch (Throwable e) {
FileLog.e(e);
}
}
public void updateTextAndIcon(String text, int resId) {
try {
textView.setText(text);

View file

@ -26,7 +26,7 @@ public class LanguageCell extends FrameLayout {
private RadioButton radioButton;
private TextView textView;
private TextView textView2;
public TextView textView2;
private boolean needDivider;
private LocaleController.LocaleInfo currentLocale;
private int marginStartDp = 62, marginEndDp = 23;
@ -73,7 +73,7 @@ public class LanguageCell extends FrameLayout {
needDivider = divider;
}
public void setValue(String name, String nameEnglish) {
public void setValue(CharSequence name, CharSequence nameEnglish) {
textView.setText(name);
textView2.setText(nameEnglish);
radioButton.setChecked(false, false);

View file

@ -61,7 +61,6 @@ public class MentionCell extends LinearLayout {
super.setText(text, type);
}
};
NotificationCenter.listenEmojiLoading(nameTextView);
nameTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText));
nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
nameTextView.setSingleLine(true);
@ -78,6 +77,11 @@ public class MentionCell extends LinearLayout {
addView(usernameTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 12, 0, 8, 0));
}
public void invalidateEmojis() {
nameTextView.invalidate();
usernameTextView.invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(36), MeasureSpec.EXACTLY));

View file

@ -8,6 +8,8 @@
package org.telegram.ui.Cells;
import static org.telegram.messenger.AndroidUtilities.dp;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@ -42,9 +44,11 @@ import org.telegram.messenger.MessageObject;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.SvgHelper;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.AnimatedEmojiDrawable;
import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.CheckBox2;
import org.telegram.ui.Components.Easings;
@ -71,6 +75,7 @@ public class StickerSetCell extends FrameLayout {
private ImageView optionsButton;
private ImageView reorderButton;
private TLRPC.TL_messages_stickerSet stickersSet;
private boolean groupSearch;
private Rect rect = new Rect();
private boolean emojis;
@ -78,6 +83,7 @@ public class StickerSetCell extends FrameLayout {
private TextView addButtonView;
private TextView removeButtonView;
private PremiumButtonView premiumButtonView;
private ImageView deleteView;
public StickerSetCell(Context context, int option) {
this(context, null, option);
@ -201,7 +207,15 @@ public class StickerSetCell extends FrameLayout {
valueTextView.setSingleLine(true);
valueTextView.setGravity(LayoutHelper.getAbsoluteGravityStart());
addView(valueTextView, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START, 71, 32, 70, 0));
if (option == 3) {
deleteView = new ImageView(context);
deleteView.setImageResource(R.drawable.msg_close);
deleteView.setPadding(dp(8), dp(8), dp(8), dp(8));
deleteView.setColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText), PorterDuff.Mode.SRC_IN);
deleteView.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector)));
deleteView.setVisibility(GONE);
addView(deleteView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 4 : 0, 0, LocaleController.isRTL ? 0 : 4, 0));
}
updateButtonState(BUTTON_STATE_EMPTY, false);
}
@ -276,9 +290,10 @@ public class StickerSetCell extends FrameLayout {
}
@SuppressLint("SetTextI18n")
public void setStickersSet(TLRPC.TL_messages_stickerSet set, boolean divider, boolean groupSearch) {
public void setStickersSet(TLRPC.TL_messages_stickerSet set, boolean divider, boolean search) {
needDivider = divider;
stickersSet = set;
groupSearch = search;
imageView.setVisibility(VISIBLE);
if (progressView != null) {
@ -305,7 +320,6 @@ public class StickerSetCell extends FrameLayout {
ArrayList<TLRPC.Document> documents = set.documents;
if (documents != null && !documents.isEmpty()) {
valueTextView.setText(LocaleController.formatPluralString(emojis ? "EmojiCount" : "Stickers", documents.size()));
TLRPC.Document sticker = null;
for (int i = 0; i < documents.size(); ++i) {
TLRPC.Document d = documents.get(i);
@ -352,6 +366,17 @@ public class StickerSetCell extends FrameLayout {
} else {
valueTextView.setText(LocaleController.formatPluralString(set.set.emojis ? "EmojiCount" : "Stickers", 0));
imageView.setImageDrawable(null);
if (set.set.thumb_document_id != 0) {
AnimatedEmojiDrawable.getDocumentFetcher(UserConfig.selectedAccount)
.fetchDocument(set.set.thumb_document_id, document -> {
AndroidUtilities.runOnUIThread(() -> {
if (stickersSet.documents.isEmpty() && stickersSet.set.thumb_document_id == document.id) {
stickersSet.documents.add(document);
setStickersSet(stickersSet, needDivider, groupSearch);
}
});
});
}
}
if (groupSearch) {
valueTextView.setText((set.set.emojis ? LINK_PREFIX_EMOJI : LINK_PREFIX) + set.set.short_name);
@ -375,39 +400,16 @@ public class StickerSetCell extends FrameLayout {
return false;
}
public void setDeleteAction(OnClickListener action) {
if (deleteView != null) {
deleteView.setVisibility(action == null ? View.GONE : View.VISIBLE);
deleteView.setOnClickListener(action);
}
}
public void setChecked(boolean checked, boolean animated) {
if (option == 1) {
checkBox.setChecked(checked, animated);
} else if (emojis) {
if (animated) {
sideButtons.animate().cancel();
sideButtons.animate().setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (!checked) {
sideButtons.setVisibility(INVISIBLE);
}
}
@Override
public void onAnimationStart(Animator animation) {
if (checked) {
sideButtons.setVisibility(VISIBLE);
}
}
}).alpha(checked ? 1 : 0).scaleX(checked ? 1 : 0.1f).scaleY(checked ? 1 : 0.1f).setDuration(150).start();
} else {
sideButtons.setVisibility(checked ? VISIBLE : INVISIBLE);
if (!checked) {
sideButtons.setAlpha(0f);
sideButtons.setScaleX(0.1f);
sideButtons.setScaleY(0.1f);
} else {
sideButtons.setAlpha(1f);
sideButtons.setScaleX(1f);
sideButtons.setScaleY(1f);
}
}
} else if (option == 3) {
if (animated) {
optionsButton.animate().cancel();
@ -438,6 +440,36 @@ public class StickerSetCell extends FrameLayout {
optionsButton.setScaleY(1f);
}
}
} else if (emojis) {
if (animated) {
sideButtons.animate().cancel();
sideButtons.animate().setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (!checked) {
sideButtons.setVisibility(INVISIBLE);
}
}
@Override
public void onAnimationStart(Animator animation) {
if (checked) {
sideButtons.setVisibility(VISIBLE);
}
}
}).alpha(checked ? 1 : 0).scaleX(checked ? 1 : 0.1f).scaleY(checked ? 1 : 0.1f).setDuration(150).start();
} else {
sideButtons.setVisibility(checked ? VISIBLE : INVISIBLE);
if (!checked) {
sideButtons.setAlpha(0f);
sideButtons.setScaleX(0.1f);
sideButtons.setScaleY(0.1f);
} else {
sideButtons.setAlpha(1f);
sideButtons.setScaleX(1f);
sideButtons.setScaleY(1f);
}
}
}
}

View file

@ -286,7 +286,7 @@ public class TextCell extends FrameLayout {
private CharSequence valueText;
public void setText(String text, boolean divider) {
public void setText(CharSequence text, boolean divider) {
imageLeft = 21;
textView.setText(text);
textView.setRightDrawable(null);
@ -300,8 +300,12 @@ public class TextCell extends FrameLayout {
}
public void setLockLevel(boolean plus, int level) {
textView.setRightDrawable(new PeerColorActivity.LevelLock(getContext(), plus, level, resourcesProvider));
textView.setDrawablePadding(dp(6));
if (level <= 0) {
textView.setRightDrawable(null);
} else {
textView.setRightDrawable(new PeerColorActivity.LevelLock(getContext(), plus, level, resourcesProvider));
textView.setDrawablePadding(dp(6));
}
}
public void setTextAndIcon(CharSequence text, int resId, boolean divider) {
@ -382,6 +386,10 @@ public class TextCell extends FrameLayout {
}
}
public void setValue(String value, boolean animated) {
valueTextView.setText(TextUtils.ellipsize(valueText = value, valueTextView.getPaint(), AndroidUtilities.displaySize.x / 2.5f, TextUtils.TruncateAt.END), animated);
}
public void setTextAndValueAndColorfulIcon(String text, CharSequence value, boolean animated, int resId, int color, boolean divider) {
imageLeft = 21;
offsetFromImage = getOffsetFromImage(false);

View file

@ -1424,6 +1424,10 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
menu.getItem(1).setVisible(canShowQuote());
MenuItem copyItem = menu.findItem(android.R.id.copy);
if (copyItem != null) {
copyItem.setVisible(canCopy());
}
if (selectedView != null) {
CharSequence charSequence = getText(selectedView, false);
if (multiselect || selectionStart <= 0 && selectionEnd >= charSequence.length() - 1) {
@ -3304,4 +3308,8 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
protected Theme.ResourcesProvider getResourcesProvider() {
return resourcesProvider;
}
protected boolean canCopy() {
return true;
}
}

View file

@ -47,6 +47,7 @@ public class ThemePreviewMessagesCell extends LinearLayout {
public final static int TYPE_REACTIONS_DOUBLE_TAP = 2;
public final static int TYPE_PEER_COLOR = 3;
public final static int TYPE_GROUP_PEER_COLOR = 4;
private final Runnable invalidateRunnable = this::invalidate;
@ -278,6 +279,12 @@ public class ThemePreviewMessagesCell extends LinearLayout {
message2.eventId = 1;
message2.resetLayout();
message2.replyMessageObject = replyMessageObject;
if (type == TYPE_GROUP_PEER_COLOR) {
TLRPC.User user = new TLRPC.TL_user();
user.first_name = LocaleController.getString(R.string.GroupThemePreviewSenderName);
message2.customName = user.first_name;
message2.customAvatarDrawable = new AvatarDrawable(user, false);
}
}
for (int a = 0; a < cells.length; a++) {
@ -418,7 +425,7 @@ public class ThemePreviewMessagesCell extends LinearLayout {
return type == progress;
}
});
cells[a].isChat = type == TYPE_REACTIONS_DOUBLE_TAP;
cells[a].isChat = type == TYPE_REACTIONS_DOUBLE_TAP || type == TYPE_GROUP_PEER_COLOR;
cells[a].setFullyDraw(true);
MessageObject messageObject = a == 0 ? message2 : message1;
if (messageObject == null) {

View file

@ -1247,6 +1247,13 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
showDialog(new StickersAlert(getParentActivity(), ChannelAdminLogActivity.this, stickerSet, null, null));
return true;
}
} else if (selectedObject.currentEvent != null && selectedObject.currentEvent.action instanceof TLRPC.TL_channelAdminLogEventActionChangeEmojiStickerSet) {
GroupStickersActivity fragment = new GroupStickersActivity(currentChat.id, true);
TLRPC.ChatFull chatInfo = getMessagesController().getChatFull(currentChat.id);
if (chatInfo != null) {
fragment.setInfo(chatInfo);
presentFragment(fragment);
}
} else if (selectedObject.currentEvent != null && selectedObject.currentEvent.action instanceof TLRPC.TL_channelAdminLogEventActionChangeHistoryTTL) {
if (ChatObject.canUserDoAdminAction(currentChat, ChatObject.ACTION_DELETE_MESSAGES)) {
ClearHistoryAlert alert = new ClearHistoryAlert(getParentActivity(), null, currentChat, false, null);

View file

@ -152,7 +152,6 @@ public class ChannelBoostLayout extends FrameLayout {
break;
case HEADER_VIEW_TYPE_TABS:
boostsTabs = new ScrollSlidingTextTabStrip(fragment.getContext(), resourcesProvider);
boostsTabs.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider));
boostsTabs.setColors(Theme.key_profile_tabSelectedLine, Theme.key_profile_tabSelectedText, Theme.key_profile_tabText, Theme.key_profile_tabSelector);
FrameLayout frameLayoutWrapper = new FrameLayout(fragment.getContext()) {
private final Paint dividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@ -214,7 +213,7 @@ public class ChannelBoostLayout extends FrameLayout {
}
};
TextView textView = new TextView(getContext());
textView.setText(LocaleController.getString("NoBoostersHint", R.string.NoBoostersHint));
textView.setText(LocaleController.getString(isChannel() ? R.string.NoBoostersHint : R.string.NoBoostersGroupHint));
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText));
textView.setGravity(Gravity.CENTER);
@ -256,9 +255,9 @@ public class ChannelBoostLayout extends FrameLayout {
overviewCell.setData(0, Integer.toString(boostsStatus.level), null, LocaleController.getString("BoostsLevel2", R.string.BoostsLevel2));
if (boostsStatus.premium_audience != null && boostsStatus.premium_audience.total != 0) {
float percent = (((float) boostsStatus.premium_audience.part / (float) boostsStatus.premium_audience.total) * 100f);
overviewCell.setData(1, "~" + (int) boostsStatus.premium_audience.part, String.format(Locale.US, "%.1f", percent) + "%", LocaleController.getString("PremiumSubscribers", R.string.PremiumSubscribers));
overviewCell.setData(1, "~" + (int) boostsStatus.premium_audience.part, String.format(Locale.US, "%.1f", percent) + "%", LocaleController.getString(isChannel() ? R.string.PremiumSubscribers : R.string.PremiumMembers));
} else {
overviewCell.setData(1, "~0", "0%", LocaleController.getString("PremiumSubscribers", R.string.PremiumSubscribers));
overviewCell.setData(1, "~0", "0%", LocaleController.getString(isChannel() ? R.string.PremiumSubscribers : R.string.PremiumMembers));
}
overviewCell.setData(2, String.valueOf(boostsStatus.boosts), null, LocaleController.getString("BoostsExisting", R.string.BoostsExisting));
overviewCell.setData(3, String.valueOf(Math.max(0, boostsStatus.next_level_boosts - boostsStatus.boosts)), null, LocaleController.getString("BoostsToLevel", R.string.BoostsToLevel));
@ -388,6 +387,10 @@ public class ChannelBoostLayout extends FrameLayout {
progressLayout.animate().alpha(1f).setDuration(200).setStartDelay(500).start();
}
private boolean isChannel() {
return ChatObject.isChannelAndNotMegaGroup(currentChat);
}
public void updateRows(boolean animated) {
ArrayList<ItemInternal> oldItems = new ArrayList<>(items);
items.clear();
@ -420,7 +423,7 @@ public class ChannelBoostLayout extends FrameLayout {
} else {
items.add(new ItemInternal(EMPTY_VIEW_8DP, false));
}
items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString("BoostersInfoDescription", R.string.BoostersInfoDescription)));
items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString(isChannel() ? R.string.BoostersInfoDescription : R.string.BoostersInfoGroupDescription)));
}
} else {
if (gifts.isEmpty()) {
@ -435,16 +438,16 @@ public class ChannelBoostLayout extends FrameLayout {
} else {
items.add(new ItemInternal(EMPTY_VIEW_8DP, false));
}
items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString("BoostersInfoDescription", R.string.BoostersInfoDescription)));
items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString(isChannel() ? R.string.BoostersInfoDescription : R.string.BoostersInfoGroupDescription)));
}
}
items.add(new ItemInternal(HEADER_VIEW_TYPE, LocaleController.getString("LinkForBoosting", R.string.LinkForBoosting)));
items.add(new ItemInternal(LINK_VIEW_TYPE, boostsStatus.boost_url));
if (MessagesController.getInstance(currentAccount).giveawayGiftsPurchaseAvailable && ChatObject.hasAdminRights(currentChat) && ChatObject.canPost(currentChat)) {
items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString("BoostingShareThisLink", R.string.BoostingShareThisLink)));
if (MessagesController.getInstance(currentAccount).giveawayGiftsPurchaseAvailable && ChatObject.hasAdminRights(currentChat)) {
items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString(isChannel() ? R.string.BoostingShareThisLink : R.string.BoostingShareThisLinkGroup)));
items.add(new ItemInternal(SHOW_BOOST_BY_GIFTS, true));
items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString("BoostingGetMoreBoosts", R.string.BoostingGetMoreBoosts)));
items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString(isChannel() ? R.string.BoostingGetMoreBoosts : R.string.BoostingGetMoreBoostsGroup)));
}
}
if (animated) {

View file

@ -2,6 +2,7 @@ package org.telegram.ui;
import static org.telegram.messenger.AndroidUtilities.dp;
import static org.telegram.messenger.AndroidUtilities.dpf2;
import static org.telegram.ui.Components.Premium.LimitReachedBottomSheet.TYPE_BOOSTS_FOR_CUSTOM_EMOJI_PACK;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@ -11,6 +12,7 @@ import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
@ -22,21 +24,22 @@ import android.graphics.PorterDuffXfermode;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.util.SparseIntArray;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
@ -54,7 +57,6 @@ import org.telegram.messenger.MessageObject;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.UserObject;
import org.telegram.messenger.Utilities;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.ResultCallback;
@ -75,6 +77,7 @@ import org.telegram.ui.Cells.ThemePreviewMessagesCell;
import org.telegram.ui.Cells.ThemesHorizontalListCell;
import org.telegram.ui.Components.AnimatedEmojiDrawable;
import org.telegram.ui.Components.AnimatedFloat;
import org.telegram.ui.Components.Bulletin;
import org.telegram.ui.Components.BulletinFactory;
import org.telegram.ui.Components.ButtonBounce;
import org.telegram.ui.Components.ChatThemeBottomSheet;
@ -97,11 +100,12 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class ChannelColorActivity extends BaseFragment {
public class ChannelColorActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
public final long dialogId;
public int currentLevel;
public TL_stories.TL_premium_boostsStatus boostsStatus;
protected boolean isGroup;
public int currentReplyColor, selectedReplyColor;
public long currentReplyEmoji, selectedReplyEmoji;
@ -119,7 +123,7 @@ public class ChannelColorActivity extends BaseFragment {
MessagesController.PeerColors peerColors = getMessagesController().peerColors;
MessagesController.PeerColor peerColor = peerColors == null ? null : peerColors.getColor(selectedReplyColor);
if (peerColor != null) {
lvl = Math.max(lvl, peerColor.lvl);
lvl = Math.max(lvl, peerColor.getLvl(isGroup));
}
}
if (currentReplyEmoji != selectedReplyEmoji) {
@ -129,25 +133,45 @@ public class ChannelColorActivity extends BaseFragment {
MessagesController.PeerColors peerColors = getMessagesController().profilePeerColors;
MessagesController.PeerColor peerColor = peerColors == null ? null : peerColors.getColor(selectedProfileColor);
if (peerColor != null) {
lvl = Math.max(lvl, peerColor.lvl);
lvl = Math.max(lvl, peerColor.getLvl(isGroup));
}
}
if (currentProfileEmoji != selectedProfileEmoji) {
lvl = Math.max(lvl, getMessagesController().channelProfileIconLevelMin);
lvl = Math.max(lvl, getProfileIconLevelMin());
}
if (!DialogObject.emojiStatusesEqual(currentStatusEmoji, selectedStatusEmoji)) {
lvl = Math.max(lvl, getMessagesController().channelEmojiStatusLevelMin);
lvl = Math.max(lvl, getEmojiStatusLevelMin());
}
if (!ChatThemeController.wallpaperEquals(currentWallpaper, selectedWallpaper)) {
if (!TextUtils.isEmpty(ChatThemeController.getWallpaperEmoticon(selectedWallpaper))) {
lvl = Math.max(lvl, getMessagesController().channelWallpaperLevelMin);
lvl = Math.max(lvl, getWallpaperLevelMin());
} else {
lvl = Math.max(lvl, getMessagesController().channelCustomWallpaperLevelMin);
lvl = Math.max(lvl, getCustomWallpaperLevelMin());
}
}
return lvl;
}
protected int getProfileIconLevelMin() {
return getMessagesController().channelProfileIconLevelMin;
}
protected int getCustomWallpaperLevelMin() {
return getMessagesController().channelCustomWallpaperLevelMin;
}
protected int getWallpaperLevelMin() {
return getMessagesController().channelWallpaperLevelMin;
}
protected int getEmojiStatusLevelMin() {
return getMessagesController().channelEmojiStatusLevelMin;
}
protected int getEmojiStickersLevelMin() {
return 0;
}
private SpannableStringBuilder lock;
public void updateButton(boolean animated) {
if (boostsStatus == null) {
@ -190,6 +214,20 @@ public class ChannelColorActivity extends BaseFragment {
if (drawableKey.equals(Theme.key_drawable_msgInSelected)) {
return msgInDrawableSelected;
}
if (drawableKey.equals(Theme.key_drawable_msgOut)) {
return msgOutDrawable;
}
if (drawableKey.equals(Theme.key_drawable_msgOutSelected)) {
return msgOutDrawableSelected;
}
if (drawableKey.equals(Theme.key_drawable_msgOutCheckRead)) {
msgOutCheckReadDrawable.setColorFilter(getColor(Theme.key_chat_outSentCheckRead), PorterDuff.Mode.MULTIPLY);
return msgOutCheckReadDrawable;
}
if (drawableKey.equals(Theme.key_drawable_msgOutHalfCheck)) {
msgOutHalfCheckDrawable.setColorFilter(getColor(Theme.key_chat_outSentCheckRead), PorterDuff.Mode.MULTIPLY);
return msgOutHalfCheckDrawable;
}
if (parentResourcesProvider != null) {
return parentResourcesProvider.getDrawable(drawableKey);
}
@ -219,9 +257,18 @@ public class ChannelColorActivity extends BaseFragment {
@Override
public boolean onFragmentCreate() {
getMediaDataController().loadRestrictedStatusEmojis();
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.boostByChannelCreated);
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.chatWasBoostedByUser);
return super.onFragmentCreate();
}
@Override
public void onFragmentDestroy() {
super.onFragmentDestroy();
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.boostByChannelCreated);
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.chatWasBoostedByUser);
}
public ChannelColorActivity(long dialogId) {
super();
this.dialogId = dialogId;
@ -247,6 +294,8 @@ public class ChannelColorActivity extends BaseFragment {
resourceProvider = new ThemeDelegate();
msgInDrawable = new Theme.MessageDrawable(Theme.MessageDrawable.TYPE_TEXT, false, false, resourceProvider);
msgInDrawableSelected = new Theme.MessageDrawable(Theme.MessageDrawable.TYPE_TEXT, false, true, resourceProvider);
msgOutDrawable = new Theme.MessageDrawable(Theme.MessageDrawable.TYPE_TEXT, true, false, resourceProvider);
msgOutDrawableSelected = new Theme.MessageDrawable(Theme.MessageDrawable.TYPE_TEXT, true, true, resourceProvider);
}
@Override
@ -258,10 +307,14 @@ public class ChannelColorActivity extends BaseFragment {
private RLottieDrawable sunDrawable;
private ActionBarMenuItem dayNightItem;
private RecyclerListView listView;
private Adapter adapter;
private FrameLayout buttonContainer;
private ButtonWithCounterView button;
protected RecyclerListView listView;
protected Adapter adapter;
protected FrameLayout buttonContainer;
protected ButtonWithCounterView button;
protected void createListView() {
listView = new RecyclerListView(getContext(), resourceProvider);
}
@Override
public View createView(Context context) {
@ -318,7 +371,7 @@ public class ChannelColorActivity extends BaseFragment {
FrameLayout contentView = new FrameLayout(context);
updateRows();
listView = new RecyclerListView(context, resourceProvider);
createListView();
listView.setAdapter(adapter = new Adapter());
listView.setLayoutManager(new LinearLayoutManager(context));
listView.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundGray));
@ -333,6 +386,20 @@ public class ChannelColorActivity extends BaseFragment {
} else if (position == statusEmojiRow) {
selectedEmojiId = DialogObject.getEmojiStatusDocumentId(selectedStatusEmoji);
}
if (position == packEmojiRow) {
final int requiredLvl = getEmojiStickersLevelMin();
if (boostsStatus != null && boostsStatus.level < requiredLvl) {
LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(this, getContext(), TYPE_BOOSTS_FOR_CUSTOM_EMOJI_PACK, currentAccount, getResourceProvider());
limitReachedBottomSheet.setBoostsStats(boostsStatus, true);
limitReachedBottomSheet.setDialogId(dialogId);
showDialog(limitReachedBottomSheet);
return;
}
GroupStickersActivity fragment = new GroupStickersActivity(-dialogId, true);
fragment.setInfo(chatFull);
presentFragment(fragment);
return;
}
showSelectStatusDialog((EmojiCell) view, selectedEmojiId, position == statusEmojiRow, (documentId, until) -> {
if (position == replyEmojiRow) {
selectedReplyEmoji = documentId;
@ -365,18 +432,33 @@ public class ChannelColorActivity extends BaseFragment {
updateButton(true);
updateRows();
} else if (position == wallpaperRow) {
ChannelWallpaperActivity activity = new ChannelWallpaperActivity(dialogId, boostsStatus);
activity.setResourceProvider(resourceProvider);
activity.setSelectedWallpaper(selectedWallpaper, galleryWallpaper);
activity.setOnSelectedWallpaperChange((currentWallpaper, selectedWallpaper, galleryWallpaper) -> {
this.currentWallpaper = currentWallpaper;
this.selectedWallpaper = selectedWallpaper;
this.galleryWallpaper = galleryWallpaper;
ChatThemeBottomSheet.openGalleryForBackground(getParentActivity(), this, dialogId, resourceProvider, wallpaper -> {
this.currentWallpaper = wallpaper;
this.selectedWallpaper = wallpaper;
this.galleryWallpaper = wallpaper;
updateButton(false);
updateMessagesPreview(false);
});
presentFragment(activity);
AndroidUtilities.runOnUIThread(() -> BulletinFactory.of(this).createSimpleBulletin(R.raw.done, LocaleController.getString(R.string.ChannelWallpaperUpdated)).show(), 350);
}, new ThemePreviewActivity.DayNightSwitchDelegate() {
@Override
public boolean isDark() {
return ChannelColorActivity.this.resourceProvider != null ? ChannelColorActivity.this.resourceProvider.isDark() : Theme.isCurrentThemeDark();
}
@Override
public void switchDayNight(boolean animated) {
if (resourceProvider instanceof ChannelColorActivity.ThemeDelegate) {
((ChannelColorActivity.ThemeDelegate) resourceProvider).toggle();
}
setForceDark(isDark(), false);
updateColors();
}
@Override
public boolean supportsAnimation() {
return false;
}
}, boostsStatus);
}
});
DefaultItemAnimator itemAnimator = new DefaultItemAnimator();
@ -396,6 +478,12 @@ public class ChannelColorActivity extends BaseFragment {
buttonContainer.addView(button, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM, 10, 10, 10, 10));
contentView.addView(buttonContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 68, Gravity.BOTTOM));
Bulletin.addDelegate(this, new Bulletin.Delegate() {
@Override
public int getBottomOffset(int tag) {
return buttonContainer.getMeasuredHeight();
}
});
return fragmentView = contentView;
}
@ -623,26 +711,26 @@ public class ChannelColorActivity extends BaseFragment {
if (currentReplyColor != selectedReplyColor) {
MessagesController.PeerColors peerColors = getMessagesController().peerColors;
MessagesController.PeerColor peerColor = peerColors == null ? null : peerColors.getColor(selectedReplyColor);
if (peerColor != null && peerColor.lvl > currentLevel) {
if (peerColor != null && peerColor.getLvl(isGroup) > currentLevel) {
type = LimitReachedBottomSheet.TYPE_BOOSTS_FOR_COLOR;
lvl = peerColor.lvl;
lvl = peerColor.getLvl(isGroup);
}
}
if (currentProfileColor != selectedProfileColor) {
MessagesController.PeerColors peerColors = getMessagesController().profilePeerColors;
MessagesController.PeerColor peerColor = peerColors == null ? null : peerColors.getColor(selectedProfileColor);
if (peerColor != null && peerColor.lvl > currentLevel) {
if (peerColor != null && peerColor.getLvl(isGroup) > currentLevel) {
type = LimitReachedBottomSheet.TYPE_BOOSTS_FOR_PROFILE_COLOR;
lvl = peerColor.lvl;
lvl = peerColor.getLvl(isGroup);
}
}
if (currentReplyEmoji != selectedReplyEmoji && getMessagesController().channelBgIconLevelMin > currentLevel) {
type = LimitReachedBottomSheet.TYPE_BOOSTS_FOR_REPLY_ICON;
}
if (currentProfileEmoji != selectedProfileEmoji && getMessagesController().channelProfileIconLevelMin > currentLevel) {
if (currentProfileEmoji != selectedProfileEmoji && getProfileIconLevelMin() > currentLevel) {
type = LimitReachedBottomSheet.TYPE_BOOSTS_FOR_PROFILE_ICON;
}
if (!DialogObject.emojiStatusesEqual(currentStatusEmoji, selectedStatusEmoji) && getMessagesController().channelEmojiStatusLevelMin > currentLevel) {
if (!DialogObject.emojiStatusesEqual(currentStatusEmoji, selectedStatusEmoji) && getEmojiStatusLevelMin() > currentLevel) {
type = LimitReachedBottomSheet.TYPE_BOOSTS_FOR_EMOJI_STATUS;
}
if (!ChatThemeController.wallpaperEquals(currentWallpaper, selectedWallpaper)) {
@ -653,6 +741,7 @@ public class ChannelColorActivity extends BaseFragment {
}
}
final int level = lvl;
if (getContext() == null || getParentActivity() == null) return;
LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(this, getContext(), type, currentAccount, getResourceProvider()) {
@Override
protected int channelColorLevelMin() {
@ -665,16 +754,7 @@ public class ChannelColorActivity extends BaseFragment {
TLRPC.Chat channel = getMessagesController().getChat(-dialogId);
if (channel != null) {
limitReachedBottomSheet.showStatisticButtonInLink(() -> {
Bundle args = new Bundle();
args.putLong("chat_id", -dialogId);
args.putBoolean("is_megagroup", channel.megagroup);
args.putBoolean("start_from_boosts", true);
TLRPC.ChatFull chatInfo = getMessagesController().getChatFull(-dialogId);
if (chatInfo == null || !chatInfo.can_view_stats) {
args.putBoolean("only_boosts", true);
}
StatisticActivity fragment = new StatisticActivity(args);
presentFragment(fragment);
presentFragment(StatisticActivity.create(channel));
});
}
showDialog(limitReachedBottomSheet);
@ -714,6 +794,7 @@ public class ChannelColorActivity extends BaseFragment {
final int popupHeight = (int) Math.min(AndroidUtilities.dp(410 - 16 - 64), AndroidUtilities.displaySize.y * .75f);
final int popupWidth = (int) Math.min(dp(340 - 16), AndroidUtilities.displaySize.x * .95f);
if (cell != null) {
cell.imageDrawable.removeOldDrawable();
scrimDrawable = cell.imageDrawable;
scrimDrawableParent = cell;
if (cell.imageDrawable != null) {
@ -775,29 +856,32 @@ public class ChannelColorActivity extends BaseFragment {
private static final int VIEW_TYPE_BUTTON_EMOJI = 6;
private static final int VIEW_TYPE_SHADOW = 7;
private int rowsCount = 0;
protected int rowsCount = 0;
private int messagesPreviewRow;
private int replyColorListRow;
private int replyEmojiRow;
private int replyHintRow;
protected int messagesPreviewRow;
protected int replyColorListRow;
protected int replyEmojiRow;
protected int replyHintRow;
private int wallpaperThemesRow;
private int wallpaperRow;
private int wallpaperHintRow;
protected int wallpaperThemesRow;
protected int wallpaperRow;
protected int wallpaperHintRow;
private int profilePreviewRow;
private int profileColorGridRow;
private int profileEmojiRow;
private int profileHintRow;
protected int profilePreviewRow;
protected int profileColorGridRow;
protected int profileEmojiRow;
protected int profileHintRow;
private int removeProfileColorRow;
private int removeProfileColorShadowRow;
protected int removeProfileColorRow;
protected int removeProfileColorShadowRow;
private int statusEmojiRow;
private int statusHintRow;
protected int statusEmojiRow;
protected int statusHintRow;
private void updateRows() {
protected int packEmojiRow;
protected int packEmojiHintRow;
protected void updateRows() {
rowsCount = 0;
messagesPreviewRow = rowsCount++;
replyColorListRow = rowsCount++;
@ -829,28 +913,69 @@ public class ChannelColorActivity extends BaseFragment {
statusHintRow = rowsCount++;
}
private class Adapter extends RecyclerListView.SelectionAdapter {
protected int getProfileInfoStrRes() {
return R.string.ChannelProfileInfo;
}
protected int getEmojiStatusStrRes() {
return R.string.ChannelEmojiStatus;
}
protected int getEmojiPackStrRes() {
return 0;
}
protected int getEmojiPackInfoStrRes() {
return 0;
}
protected int getEmojiStatusInfoStrRes() {
return R.string.ChannelEmojiStatusInfo;
}
protected int getWallpaperStrRes() {
return R.string.ChannelWallpaper;
}
protected int getWallpaper2InfoStrRes() {
return R.string.ChannelWallpaper2Info;
}
protected int getMessagePreviewType() {
return ThemePreviewMessagesCell.TYPE_PEER_COLOR;
}
private String getThemeChooserEmoticon() {
String emoticon = ChatThemeController.getWallpaperEmoticon(selectedWallpaper);
if (emoticon == null && selectedWallpaper == null && galleryWallpaper != null) {
return EmojiThemes.REMOVED_EMOJI;
}
return emoticon;
}
protected class Adapter extends RecyclerListView.SelectionAdapter {
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view;
if (viewType == VIEW_TYPE_MESSAGE_PREVIEW) {
ThemePreviewMessagesCell messagesCell = new ThemePreviewMessagesCell(getContext(), parentLayout, ThemePreviewMessagesCell.TYPE_PEER_COLOR, dialogId, resourceProvider);
ThemePreviewMessagesCell messagesCell = new ThemePreviewMessagesCell(getContext(), parentLayout, getMessagePreviewType(), dialogId, resourceProvider);
messagesCell.customAnimation = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
messagesCell.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
}
messagesCell.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
messagesCell.fragment = ChannelColorActivity.this;
messagesCell.setOverrideBackground(backgroundDrawable = PreviewView.getBackgroundDrawable(backgroundDrawable, currentAccount, selectedWallpaper, isDark));
view = messagesCell;
} else if (viewType == VIEW_TYPE_WALLPAPER_THEMES) {
ThemeChooser themesWallpaper = new ThemeChooser(getContext(), false, currentAccount, resourceProvider);
themesWallpaper.setSelectedEmoticon(ChatThemeController.getWallpaperEmoticon(selectedWallpaper), false);
themesWallpaper.setWithRemovedStub(true);
themesWallpaper.setSelectedEmoticon(getThemeChooserEmoticon(), false);
themesWallpaper.setGalleryWallpaper(galleryWallpaper);
themesWallpaper.setOnEmoticonSelected(emoticon -> {
if (emoticon == null) {
selectedWallpaper = galleryWallpaper;
} else if (emoticon.equals(EmojiThemes.REMOVED_EMOJI)) {
selectedWallpaper = null;
} else {
selectedWallpaper = new TLRPC.TL_wallPaperNoFile();
selectedWallpaper.id = 0;
@ -922,9 +1047,11 @@ public class ChannelColorActivity extends BaseFragment {
if (position == removeProfileColorRow) {
textCell.setText(LocaleController.getString(R.string.ChannelProfileColorReset), false);
} else {
textCell.setText(LocaleController.getString(R.string.ChannelWallpaper), false);
if (currentLevel < getMessagesController().channelWallpaperLevelMin) {
textCell.setLockLevel(false, getMessagesController().channelWallpaperLevelMin);
textCell.setText(LocaleController.getString(getWallpaperStrRes()), false);
if (currentLevel < getCustomWallpaperLevelMin()) {
textCell.setLockLevel(false, getCustomWallpaperLevelMin());
} else {
textCell.setLockLevel(false, 0);
}
}
break;
@ -936,23 +1063,43 @@ public class ChannelColorActivity extends BaseFragment {
emojiCell.setText(LocaleController.getString(R.string.ChannelReplyLogo));
if (currentLevel < getMessagesController().channelBgIconLevelMin) {
emojiCell.setLockLevel(getMessagesController().channelBgIconLevelMin);
} else {
emojiCell.setLockLevel(0);
}
emojiCell.setEmoji(selectedReplyEmoji, false);
} else if (position == profileEmojiRow) {
emojiCell.setAdaptiveEmojiColor(currentAccount, selectedProfileColor, false);
emojiCell.setText(LocaleController.getString(R.string.ChannelProfileLogo));
emojiCell.setDivider(removeProfileColorRow >= 0);
if (currentLevel < getMessagesController().channelProfileIconLevelMin) {
emojiCell.setLockLevel(getMessagesController().channelProfileIconLevelMin);
if (currentLevel < getProfileIconLevelMin()) {
emojiCell.setLockLevel(getProfileIconLevelMin());
} else {
emojiCell.setLockLevel(0);
}
emojiCell.setEmoji(selectedProfileEmoji, false);
} else if (position == statusEmojiRow) {
emojiCell.setAdaptiveEmojiColor(currentAccount, selectedProfileColor, false);
emojiCell.setText(LocaleController.getString(R.string.ChannelEmojiStatus));
if (currentLevel < getMessagesController().channelEmojiStatusLevelMin) {
emojiCell.setLockLevel(getMessagesController().channelEmojiStatusLevelMin);
emojiCell.setText(LocaleController.getString(getEmojiStatusStrRes()));
if (currentLevel < getEmojiStatusLevelMin()) {
emojiCell.setLockLevel(getEmojiStatusLevelMin());
} else {
emojiCell.setLockLevel(0);
}
emojiCell.setEmoji(DialogObject.getEmojiStatusDocumentId(selectedStatusEmoji), false);
} else if (position == packEmojiRow) {
emojiCell.setAdaptiveEmojiColor(currentAccount, selectedProfileColor, false);
emojiCell.setText(LocaleController.getString(getEmojiPackStrRes()));
if (currentLevel < getEmojiStickersLevelMin()) {
emojiCell.setLockLevel(getEmojiStickersLevelMin());
} else {
emojiCell.setLockLevel(0);
}
TLRPC.ChatFull chatFull = getMessagesController().getChatFull(-dialogId);
if (chatFull != null && chatFull.emojiset != null) {
emojiCell.setEmoji(getEmojiSetThumbId(chatFull.emojiset), false);
} else {
emojiCell.setEmoji(0, false);
}
}
break;
case VIEW_TYPE_SHADOW:
@ -961,11 +1108,13 @@ public class ChannelColorActivity extends BaseFragment {
if (position == replyHintRow) {
infoCell.setText(LocaleController.getString(R.string.ChannelReplyInfo));
} else if (position == wallpaperHintRow) {
infoCell.setText(LocaleController.getString(R.string.ChannelWallpaper2Info));
infoCell.setText(LocaleController.getString(getWallpaper2InfoStrRes()));
} else if (position == profileHintRow) {
infoCell.setText(LocaleController.getString(R.string.ChannelProfileInfo));
infoCell.setText(LocaleController.getString(getProfileInfoStrRes()));
} else if (position == statusHintRow) {
infoCell.setText(LocaleController.getString(R.string.ChannelEmojiStatusInfo));
infoCell.setText(LocaleController.getString(getEmojiStatusInfoStrRes()));
} else if (position == packEmojiHintRow) {
infoCell.setText(LocaleController.getString(getEmojiPackInfoStrRes()));
} else if (position == removeProfileColorShadowRow) {
infoCell.setText("");
infoCell.setFixedSize(12);
@ -1019,7 +1168,7 @@ public class ChannelColorActivity extends BaseFragment {
return VIEW_TYPE_COLOR_REPLY_GRID;
} else if (position == profileColorGridRow) {
return VIEW_TYPE_COLOR_PROFILE_GRID;
} else if (position == replyEmojiRow || position == profileEmojiRow || position == statusEmojiRow) {
} else if (position == replyEmojiRow || position == profileEmojiRow || position == statusEmojiRow || position == packEmojiRow) {
return VIEW_TYPE_BUTTON_EMOJI;
} else if (position == wallpaperRow || position == removeProfileColorRow) {
return VIEW_TYPE_BUTTON;
@ -1073,7 +1222,7 @@ public class ChannelColorActivity extends BaseFragment {
((EmojiCell) emojiPicker).setEmoji(selectedReplyEmoji, animated);
}
if (wallpaperPicker instanceof ThemeChooser) {
((ThemeChooser) wallpaperPicker).setSelectedEmoticon(ChatThemeController.getWallpaperEmoticon(selectedWallpaper), animated);
((ThemeChooser) wallpaperPicker).setSelectedEmoticon(getThemeChooserEmoticon(), animated);
((ThemeChooser) wallpaperPicker).setGalleryWallpaper(galleryWallpaper);
}
}
@ -1083,6 +1232,7 @@ public class ChannelColorActivity extends BaseFragment {
View colorPicker = findChildAt(profileColorGridRow);
View emojiPicker = findChildAt(profileEmojiRow);
View emojiStatusPicker = findChildAt(statusEmojiRow);
View packEmojiPicker = findChildAt(packEmojiRow);
if (profilePreview instanceof ProfilePreview) {
((ProfilePreview) profilePreview).setColor(selectedProfileColor, animated);
@ -1103,10 +1253,33 @@ public class ChannelColorActivity extends BaseFragment {
((EmojiCell) emojiStatusPicker).setAdaptiveEmojiColor(currentAccount, selectedProfileColor, false);
((EmojiCell) emojiStatusPicker).setEmoji(DialogObject.getEmojiStatusDocumentId(selectedStatusEmoji), animated);
}
if (packEmojiPicker instanceof EmojiCell) {
((EmojiCell) packEmojiPicker).setAdaptiveEmojiColor(currentAccount, selectedProfileColor, false);
TLRPC.ChatFull chatFull = getMessagesController().getChatFull(-dialogId);
if (chatFull != null && chatFull.emojiset != null) {
((EmojiCell) packEmojiPicker).setEmoji(getEmojiSetThumbId(chatFull.emojiset), false);
} else {
((EmojiCell) packEmojiPicker).setEmoji(0, false);
}
}
updateRows();
}
private long getEmojiSetThumbId(TLRPC.StickerSet emojiSet) {
if (emojiSet == null) {
return 0;
}
long thumbDocumentId = emojiSet.thumb_document_id;
if (thumbDocumentId == 0) {
TLRPC.TL_messages_stickerSet stickerSet = getMediaDataController().getGroupStickerSetById(emojiSet);
if (!stickerSet.documents.isEmpty()) {
thumbDocumentId = stickerSet.documents.get(0).id;
}
}
return thumbDocumentId;
}
public View findChildAt(int position) {
for (int i = 0; i < listView.getChildCount(); ++i) {
View child = listView.getChildAt(i);
@ -1117,23 +1290,74 @@ public class ChannelColorActivity extends BaseFragment {
return null;
}
private class ProfilePreview extends FrameLayout {
protected boolean needBoostInfoSection() {
return false;
}
protected class ProfilePreview extends FrameLayout {
public final PeerColorActivity.ColoredActionBar backgroundView;
public final PeerColorActivity.ProfilePreview profileView;
public SimpleTextView title;
public TextView textInfo1;
public TextView textInfo2;
public LinearLayout infoLayout;
public void setTitleSize() {
boolean isLandScape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
title.setTextSize(!AndroidUtilities.isTablet() && isLandScape ? 18 : 20);
title.setTranslationY(dp(AndroidUtilities.isTablet() ? -2 : (isLandScape ? 4 : 0)));
}
public ProfilePreview(Context context) {
super(context);
backgroundView = new PeerColorActivity.ColoredActionBar(getContext(), resourceProvider);
backgroundView.setProgressToGradient(1f);
backgroundView.ignoreMeasure = true;
addView(backgroundView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 134, Gravity.FILL));
profileView = new PeerColorActivity.ProfilePreview(getContext(), currentAccount, dialogId, resourceProvider);
addView(profileView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 104, Gravity.BOTTOM));
addView(backgroundView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, isGroup ? 194 : 134, Gravity.FILL));
profileView = new PeerColorActivity.ProfilePreview(getContext(), currentAccount, dialogId, resourceProvider){
@Override
public void setColor(int colorId, boolean animated) {
super.setColor(colorId, animated);
if (textInfo1 != null) {
textInfo1.setTextColor(profileView.subtitleView.getTextColor());
}
}
};
addView(profileView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 104, Gravity.BOTTOM, 0, 0, 0, isGroup ? 24: 0));
if (needBoostInfoSection()) {
title = new SimpleTextView(getContext());
title.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
title.setTextColor(getThemedColor(Theme.key_actionBarDefaultTitle));
title.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
title.setText(LocaleController.getString(R.string.ChangeChannelNameColor2));
title.setAlpha(0f);
setTitleSize();
addView(title, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM,72,0,0,16));
infoLayout = new LinearLayout(context);
infoLayout.setOrientation(LinearLayout.HORIZONTAL);
infoLayout.setBackground(Theme.createSelectorWithBackgroundDrawable(Theme.multAlpha(Color.BLACK, 0.15f), Theme.multAlpha(Color.BLACK, 0.35f)));
infoLayout.setGravity(Gravity.CENTER);
infoLayout.setPadding(dp(4), dp(4), dp(4), dp(4));
textInfo1 = new TextView(context);
textInfo1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
textInfo1.setTextColor(profileView.subtitleView.getTextColor());
textInfo2 = new TextView(context);
textInfo2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
textInfo2.setTextColor(Color.WHITE);
textInfo1.setText(AndroidUtilities.replaceTags(LocaleController.formatPluralString("BoostingGroupBoostCount", boostsStatus != null ? boostsStatus.boosts : 0)));
textInfo2.setText(LocaleController.getString(R.string.BoostingGroupBoostWhatAreBoosts));
infoLayout.addView(textInfo1);
infoLayout.addView(textInfo2, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 3,0,0,0));
addView(infoLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM));
}
}
public void setColor(int colorId, boolean animated) {
profileView.setColor(colorId, animated);
backgroundView.setColor(currentAccount, colorId, animated);
}
public void setEmoji(long emojiId, boolean animated) {
profileView.setEmoji(emojiId, animated);
}
@ -1282,6 +1506,7 @@ public class ChannelColorActivity extends BaseFragment {
public final List<ChatThemeBottomSheet.ChatThemeItem> items = new ArrayList<>();
private final RecyclerListView listView;
private FlickerLoadingView progressView;
private boolean withRemovedStub;
private final RecyclerListView.SelectionAdapter adapter;
@ -1290,6 +1515,10 @@ public class ChannelColorActivity extends BaseFragment {
private Utilities.Callback<String> onEmoticonSelected;
private String currentEmoticon;
public void setWithRemovedStub(boolean withRemovedStub) {
this.withRemovedStub = withRemovedStub;
}
public void setOnEmoticonSelected(Utilities.Callback<String> callback) {
onEmoticonSelected = callback;
}
@ -1316,9 +1545,13 @@ public class ChannelColorActivity extends BaseFragment {
this.fallbackWallpaper = wallPaper;
AndroidUtilities.forEachViews(listView, child -> {
if (child instanceof ThemeSmallPreviewView) {
((ThemeSmallPreviewView) child).setFallbackWallpaper(fallbackWallpaper);
((ThemeSmallPreviewView) child).setFallbackWallpaper(((ThemeSmallPreviewView) child).chatThemeItem.chatTheme.showAsRemovedStub ? null : fallbackWallpaper);
}
});
if (fallbackWallpaper != null && (items.isEmpty() || items.get(0).chatTheme.showAsDefaultStub) && withRemovedStub) {
items.add(0, new ChatThemeBottomSheet.ChatThemeItem(EmojiThemes.createChatThemesRemoved(currentAccount)));
adapter.notifyDataSetChanged();
}
}
private void updateSelected() {
@ -1415,7 +1648,7 @@ public class ChannelColorActivity extends BaseFragment {
view.setBackgroundColor(Theme.getColor(Theme.key_dialogBackgroundGray));
view.setItem(newItem, false);
view.setSelected(newItem.isSelected, false);
view.setFallbackWallpaper(fallbackWallpaper);
view.setFallbackWallpaper(newItem.chatTheme.showAsRemovedStub ? null : fallbackWallpaper);
}
@Override
@ -1426,7 +1659,7 @@ public class ChannelColorActivity extends BaseFragment {
}
ChatThemeBottomSheet.ChatThemeItem newItem = items.get(position);
((ThemeSmallPreviewView) holder.itemView).setSelected(newItem.isSelected, false);
((ThemeSmallPreviewView) holder.itemView).setFallbackWallpaper(fallbackWallpaper);
((ThemeSmallPreviewView) holder.itemView).setFallbackWallpaper(newItem.chatTheme.showAsRemovedStub ? null : fallbackWallpaper);
}
@Override
@ -1501,6 +1734,10 @@ public class ChannelColorActivity extends BaseFragment {
ChatThemeBottomSheet.ChatThemeItem noThemeItem = new ChatThemeBottomSheet.ChatThemeItem(result.get(0));
items.add(0, noThemeItem);
if (fallbackWallpaper != null && withRemovedStub) {
items.add(0, new ChatThemeBottomSheet.ChatThemeItem(EmojiThemes.createChatThemesRemoved(currentAccount)));
}
final boolean isDark = resourcesProvider != null ? resourcesProvider.isDark() : Theme.isCurrentThemeDark();
for (int i = 1; i < result.size(); ++i) {
EmojiThemes chatTheme = result.get(i);
@ -1711,8 +1948,8 @@ public class ChannelColorActivity extends BaseFragment {
((ChatEditActivity) bulletinFragment).updateColorCell();
}
BulletinFactory.of(bulletinFragment).createSimpleBulletin(
R.raw.contact_check,
LocaleController.getString(R.string.ChannelAppearanceUpdated)
R.raw.contact_check,
LocaleController.getString(isGroup ? R.string.GroupAppearanceUpdated : R.string.ChannelAppearanceUpdated)
).show();
bulletinFragment = null;
}
@ -2120,10 +2357,14 @@ public class ChannelColorActivity extends BaseFragment {
private Theme.ResourcesProvider parentResourcesProvider;
private final SparseIntArray currentColors = new SparseIntArray();
private final Theme.MessageDrawable msgInDrawable, msgInDrawableSelected;
private final Theme.MessageDrawable msgOutDrawable, msgOutDrawableSelected;
private final Drawable msgOutCheckReadDrawable, msgOutHalfCheckDrawable;
private final Paint dividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
{
dividerPaint.setStrokeWidth(1);
dividerPaint.setColor(Theme.getColor(Theme.key_divider, resourceProvider));
msgOutCheckReadDrawable = ContextCompat.getDrawable(ApplicationLoader.applicationContext, R.drawable.msg_check_s).mutate();
msgOutHalfCheckDrawable = ContextCompat.getDrawable(ApplicationLoader.applicationContext, R.drawable.msg_halfcheck).mutate();
}
public void updateThemeColors() {
@ -2182,4 +2423,33 @@ public class ChannelColorActivity extends BaseFragment {
((ThemePreviewMessagesCell) messagesCellPreview).setOverrideBackground(backgroundDrawable);
}
}
@Override
public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.chatWasBoostedByUser) {
if (dialogId == (long) args[2]) {
updateBoostsAndLevels((TL_stories.TL_premium_boostsStatus) args[0]);
}
} else if (id == NotificationCenter.boostByChannelCreated) {
boolean isGiveaway = (boolean) args[1];
if (!isGiveaway) {
getMessagesController().getBoostsController().getBoostsStats(dialogId, this::updateBoostsAndLevels);
}
}
}
private void updateBoostsAndLevels(TL_stories.TL_premium_boostsStatus boostsStatus) {
if (boostsStatus != null) {
TLRPC.Chat chat = getMessagesController().getChat(-dialogId);
this.boostsStatus = boostsStatus;
this.currentLevel = boostsStatus.level;
if (chat != null) {
chat.level = currentLevel;
}
if (adapter != null) {
adapter.notifyDataSetChanged();
}
updateButton(true);
}
}
}

View file

@ -25,6 +25,7 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.ChatThemeController;
import org.telegram.messenger.DialogObject;
import org.telegram.messenger.LocaleController;
@ -55,12 +56,14 @@ public class ChannelWallpaperActivity extends BaseFragment {
public TL_stories.TL_premium_boostsStatus boostsStatus;
public TLRPC.WallPaper galleryWallpaper;
public TLRPC.WallPaper currentWallpaper, selectedWallpaper;
private boolean isChannel;
public ChannelWallpaperActivity(long dialogId, TL_stories.TL_premium_boostsStatus boostsStatus) {
super();
this.dialogId = dialogId;
TLRPC.Chat chat = getMessagesController().getChat(-dialogId);
if (chat != null) {
isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
currentLevel = chat.level;
}
this.boostsStatus = boostsStatus;
@ -111,7 +114,7 @@ public class ChannelWallpaperActivity extends BaseFragment {
@Override
public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setTitle(LocaleController.getString(R.string.ChannelWallpaper));
actionBar.setTitle(LocaleController.getString(isChannel ? R.string.ChannelWallpaper : R.string.GroupWallpaper));
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
@Override
public void onItemClick(int id) {
@ -308,7 +311,7 @@ public class ChannelWallpaperActivity extends BaseFragment {
((TextCell) holder.itemView).setTextAndIcon(LocaleController.getString(R.string.ChannelWallpaperRemove), R.drawable.msg_delete, false);
((TextCell) holder.itemView).setColors(Theme.key_text_RedRegular, Theme.key_text_RedRegular);
} else if (position == infoRow) {
((TextInfoPrivacyCell) holder.itemView).setText(LocaleController.getString(R.string.ChannelWallpaperInfo));
((TextInfoPrivacyCell) holder.itemView).setText(LocaleController.getString(isChannel ? R.string.ChannelWallpaperInfo : R.string.GroupWallpaperInfo));
((TextInfoPrivacyCell) holder.itemView).setBackgroundColor(getThemedColor(Theme.key_windowBackgroundGray));
((TextInfoPrivacyCell) holder.itemView).setForeground(Theme.getThemedDrawableByKey(getContext(), R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow, resourceProvider));
} else if (position == themesRow) {

View file

@ -71,7 +71,6 @@ import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
import android.text.style.URLSpan;
import android.util.Log;
import android.util.Pair;
import android.util.Property;
import android.util.SparseArray;
@ -107,6 +106,7 @@ import androidx.collection.LongSparseArray;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.core.graphics.ColorUtils;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.dynamicanimation.animation.FloatValueHolder;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
@ -127,6 +127,7 @@ import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.BotWebViewVibrationEffect;
import org.telegram.messenger.BuildVars;
import org.telegram.messenger.ChannelBoostsController;
import org.telegram.messenger.ChatMessageSharedResources;
import org.telegram.messenger.ChatMessagesMetadataController;
import org.telegram.messenger.ChatObject;
@ -203,12 +204,14 @@ import org.telegram.ui.Cells.DialogCell;
import org.telegram.ui.Cells.MentionCell;
import org.telegram.ui.Cells.ShareDialogCell;
import org.telegram.ui.Cells.StickerCell;
import org.telegram.ui.Cells.TextCell;
import org.telegram.ui.Cells.TextSelectionHelper;
import org.telegram.ui.Components.*;
import org.telegram.ui.Components.FloatingDebug.FloatingDebugController;
import org.telegram.ui.Components.FloatingDebug.FloatingDebugProvider;
import org.telegram.ui.Components.Forum.ForumUtilities;
import org.telegram.ui.Components.Premium.GiftPremiumBottomSheet;
import org.telegram.ui.Components.Premium.LimitReachedBottomSheet;
import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet;
import org.telegram.ui.Components.Premium.PremiumPreviewBottomSheet;
import org.telegram.ui.Components.Premium.boosts.BoostDialogs;
@ -365,12 +368,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private HintView2 savedMessagesHint;
private HintView2 savedMessagesSearchHint;
private HintView2 savedMessagesTagHint;
private HintView2 groupEmojiPackHint;
private int reactionsMentionCount;
private FrameLayout reactionsMentiondownButton;
private CounterView reactionsMentiondownButtonCounter;
private ImageView reactionsMentiondownButtonImage;
private TL_stories.TL_premium_boostsStatus boostsStatus;
private ChannelBoostsController.CanApplyBoost canApplyBoosts;
private BackupImageView replyImageView;
private SimpleTextView replyNameTextView;
private SimpleTextView replyObjectTextView;
@ -1297,6 +1304,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private final static int auto_delete_timer = 26;
private final static int change_colors = 27;
private final static int tag_message = 28;
private final static int boost_group = 29;
private final static int bot_help = 30;
private final static int bot_settings = 31;
@ -1708,6 +1716,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
@Override
public boolean checkCanRemoveRestrictionsByBoosts() {
return ChatActivity.this.checkCanRemoveRestrictionsByBoosts();
}
@Override
public void onTextSelectionChanged(int start, int end) {
if (editTextItem == null) {
@ -2382,6 +2395,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
getNotificationCenter().addObserver(this, NotificationCenter.messageReceivedByAck);
getNotificationCenter().addObserver(this, NotificationCenter.messageSendError);
getNotificationCenter().addObserver(this, NotificationCenter.chatInfoDidLoad);
getNotificationCenter().addObserver(this, NotificationCenter.groupRestrictionsUnlockedByBoosts);
getNotificationCenter().addObserver(this, NotificationCenter.contactsDidLoad);
getNotificationCenter().addObserver(this, NotificationCenter.messagePlayingProgressDidChanged);
getNotificationCenter().addObserver(this, NotificationCenter.messagePlayingDidReset);
@ -2404,6 +2418,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
getNotificationCenter().addObserver(this, NotificationCenter.userInfoDidLoad);
getNotificationCenter().addObserver(this, NotificationCenter.pinnedInfoDidLoad);
getNotificationCenter().addObserver(this, NotificationCenter.topicsDidLoaded);
getNotificationCenter().addObserver(this, NotificationCenter.chatWasBoostedByUser);
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didSetNewWallpapper);
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didApplyNewTheme);
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.goingToPreviewTheme);
@ -2459,7 +2474,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
} else {
getMessagesController().setLastCreatedDialogId(dialog_id, chatMode == MODE_SCHEDULED, true);
if (chatMode == 0) {
if (chatMode == 0 || chatMode == MODE_SAVED) {
if (currentEncryptedChat == null) {
getMediaDataController().loadBotKeyboard(MessagesStorage.TopicKey.of(dialog_id, getTopicId()));
}
@ -2742,6 +2757,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
getNotificationCenter().removeObserver(this, NotificationCenter.messageReceivedByAck);
getNotificationCenter().removeObserver(this, NotificationCenter.messageSendError);
getNotificationCenter().removeObserver(this, NotificationCenter.chatInfoDidLoad);
getNotificationCenter().removeObserver(this, NotificationCenter.groupRestrictionsUnlockedByBoosts);
getNotificationCenter().removeObserver(this, NotificationCenter.didLoadChatInviter);
getNotificationCenter().removeObserver(this, NotificationCenter.groupCallUpdated);
getNotificationCenter().removeObserver(this, NotificationCenter.encryptedChatUpdated);
@ -2778,6 +2794,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
getNotificationCenter().removeObserver(this, NotificationCenter.userInfoDidLoad);
getNotificationCenter().removeObserver(this, NotificationCenter.pinnedInfoDidLoad);
getNotificationCenter().removeObserver(this, NotificationCenter.topicsDidLoaded);
getNotificationCenter().removeObserver(this, NotificationCenter.chatWasBoostedByUser);
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didSetNewWallpapper);
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didApplyNewTheme);
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.goingToPreviewTheme);
@ -3183,6 +3200,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
} catch (Exception e) {
FileLog.e(e);
}
} else if (id == boost_group) {
if (ChatObject.hasAdminRights(currentChat)) {
BoostsActivity boostsActivity = new BoostsActivity(dialog_id);
boostsActivity.setBoostsStatus(boostsStatus);
presentFragment(boostsActivity);
} else {
getNotificationCenter().postNotificationName(NotificationCenter.openBoostForUsersDialog, dialog_id);
}
} else if (id == report) {
AlertsCreator.createReportAlert(getParentActivity(), dialog_id, 0, 0, ChatActivity.this, themeDelegate, null);
} else if (id == star) {
@ -3354,7 +3379,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
@Override
protected boolean canSearch() {
return searchItem != null && !searching;
return !isInsideContainer && !isInPreviewMode() && !inBubbleMode && searchItem != null && !searching;
}
@Override
@ -3588,6 +3613,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (searchItem != null) {
headerItem.lazilyAddSubItem(search, R.drawable.msg_search, LocaleController.getString(R.string.Search));
}
if (ChatObject.isGroupAndSupportBoost(currentChat) && (getUserConfig().isPremium() || ChatObject.isBoosted(chatInfo) || ChatObject.hasAdminRights(currentChat))) {
RLottieDrawable drawable = new RLottieDrawable(R.raw.boosts, "" + R.raw.boosts, dp(24), dp(24));
headerItem.lazilyAddSubItem(boost_group, drawable, TextCell.applyNewSpan(LocaleController.getString("BoostingBoostGroupMenu", R.string.BoostingBoostGroupMenu)));
}
translateItem = headerItem.lazilyAddSubItem(translate, R.drawable.msg_translate, LocaleController.getString("TranslateMessage", R.string.TranslateMessage));
updateTranslateItemVisibility();
if (currentChat != null && !currentChat.creator && !ChatObject.hasAdminRights(currentChat)) {
@ -5681,6 +5710,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
updateVisibleRows();
scrollByTouch = false;
} else {
if (groupEmojiPackHint != null && groupEmojiPackHint.shown()) {
groupEmojiPackHint.hide();
}
if (searchOtherButton != null && searchOtherButton.getVisibility() == View.VISIBLE && isKeyboardVisible()) {
AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus());
}
@ -7102,7 +7134,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
bottomOverlayText.setEllipsize(TextUtils.TruncateAt.END);
bottomOverlayText.setLineSpacing(AndroidUtilities.dp(2), 1);
bottomOverlayText.setTextColor(getThemedColor(Theme.key_chat_secretChatStatusText));
bottomOverlay.addView(bottomOverlayText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 24, 0, 24, 0));
bottomOverlayText.setPadding(dp(24), 0, dp(24), 0);
bottomOverlay.addView(bottomOverlayText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER, 0, 0, 0, 0));
bottomOverlayChat = new BlurredFrameLayout(context, contentView) {
@Override
@ -7707,7 +7740,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
setFilterMessages(filter, false, true);
}
private void setFilterMessages(boolean filter, boolean ignoreMessageNotFound, boolean animated) {
if (chatAdapter.isFiltered == filter) return;
if (chatAdapter == null || chatAdapter.isFiltered == filter) return;
chatAdapter.isFiltered = filter;
createEmptyView(true);
if (filter) {
@ -10482,7 +10515,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
presentFragment(fragment);
}
private void showBottomOverlayProgress(boolean show, boolean animated) {
public void showBottomOverlayProgress(boolean show, boolean animated) {
if (show && bottomOverlayProgress.getTag() != null || !show && bottomOverlayProgress.getTag() == null) {
return;
}
@ -10911,7 +10944,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (inlineReturn != 0) {
getMessagesController().sendBotStart(currentUser, value);
} else {
botUser = value;
sentBotStart = true;
getMessagesController().sendBotStart(currentUser, botUser = value);
updateBottomOverlay();
}
}
@ -11240,6 +11274,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (userInfo != null && userInfo.voice_messages_forbidden) {
mediaBanTooltip.setText(AndroidUtilities.replaceTags(LocaleController.formatString(chatActivityEnterView.isInVideoMode() ? R.string.VideoMessagesRestrictedByPrivacy : R.string.VoiceMessagesRestrictedByPrivacy, currentUser.first_name)));
} else if (!ChatObject.canSendVoice(currentChat) && !ChatObject.canSendRoundVideo(currentChat)) {
if (checkCanRemoveRestrictionsByBoosts()) {
return;
}
if (chatActivityEnterView.isInVideoMode()) {
mediaBanTooltip.setText(ChatObject.getRestrictedErrorText(currentChat, ChatObject.ACTION_SEND_ROUND));
} else {
@ -15843,6 +15880,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
return;
}
boolean hideKeyboard = false;
bottomOverlayText.setBackground(null);
bottomOverlayText.setOnClickListener(null);
if (chatMode == MODE_SAVED && getSavedDialogId() == UserObject.ANONYMOUS) {
bottomOverlayText.setText(LocaleController.getString(R.string.AuthorHiddenDescription));
bottomOverlay.setVisibility(View.VISIBLE);
@ -15859,7 +15898,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
} else if (currentChat != null && !ChatObject.canSendMessages(currentChat) && !ChatObject.canSendAnyMedia(currentChat) && !currentChat.gigagroup && (!ChatObject.isChannel(currentChat) || currentChat.megagroup)) {
if (currentChat.default_banned_rights != null && currentChat.default_banned_rights.send_messages) {
bottomOverlayText.setText(LocaleController.getString("GlobalSendMessageRestricted", R.string.GlobalSendMessageRestricted));
boolean unlockByBoosts = ChatObject.isPossibleRemoveChatRestrictionsByBoosts(currentChat);
if (unlockByBoosts) {
Drawable drawable = ContextCompat.getDrawable(getContext(), R.drawable.filled_limit_boost).mutate();
DrawableCompat.setTint(drawable, getThemedColor(Theme.key_featuredStickers_addButton));
drawable.setBounds(0, 0, dp(14), dp(14));
CombinedDrawable combinedDrawable = new CombinedDrawable(null, drawable, dp(-6), dp(-6));
combinedDrawable.setIconSize(dp(14), dp(14));
combinedDrawable.setCustomSize(dp(14), dp(14));
SpannableStringBuilder builder = new SpannableStringBuilder("d " + LocaleController.getString(R.string.BoostingBoostToSendMessages));
builder.setSpan(new ForegroundColorSpan(getThemedColor(Theme.key_featuredStickers_addButton)), 0, builder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), 0, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.setSpan(new ImageSpan(combinedDrawable, ImageSpan.ALIGN_BASELINE), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
bottomOverlayText.setBackground(Theme.createSelectorWithBackgroundDrawable(Theme.getColor(Theme.key_windowBackgroundWhite), Theme.getColor(Theme.key_listSelector)));
bottomOverlayText.setText(builder);
bottomOverlayText.setOnClickListener(v -> LimitReachedBottomSheet.openBoostsForRemoveRestrictions(this, boostsStatus, canApplyBoosts, dialog_id, false));
} else {
bottomOverlayText.setText(LocaleController.getString("GlobalSendMessageRestricted", R.string.GlobalSendMessageRestricted));
}
} else if (AndroidUtilities.isBannedForever(currentChat.banned_rights)) {
bottomOverlayText.setText(LocaleController.getString("SendMessageRestrictedForever", R.string.SendMessageRestrictedForever));
} else {
@ -17268,6 +17326,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
boolean visible = (!endReached[0] || mergeDialogId != 0 && !endReached[1] || messages.isEmpty()) && loading && maxTop > chatListViewPaddingTop && (messages.isEmpty() ? animateProgressViewTo : childHeight != 0);
if (visible && inTransitionAnimation && emptyViewContainer != null && emptyViewContainer.getVisibility() == View.VISIBLE && emptyViewContainer.getChildCount() > 0) {
return false;
}
if (!visible && startMessageAppearTransitionMs == 0) {
checkDispatchHideSkeletons(fragmentBeginToShow);
}
@ -18986,9 +19047,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
updateInfoTopView(openAnimationStartTime != 0 && SystemClock.elapsedRealtime() >= openAnimationStartTime + 150);
}
} else if (id == NotificationCenter.groupRestrictionsUnlockedByBoosts) {
if (chatActivityEnterView != null) {
chatActivityEnterView.checkChannelRights();
chatActivityEnterView.setSlowModeTimer(0);
}
dismissCurrentDialog();
updateSecretStatus();
} else if (id == NotificationCenter.chatInfoDidLoad) {
TLRPC.ChatFull chatFull = (TLRPC.ChatFull) args[0];
if (currentChat != null && chatFull.id == currentChat.id) {
checkGroupEmojiPackHint();
if (chatFull instanceof TLRPC.TL_channelFull) {
if (currentChat.megagroup) {
int lastDate = 0;
@ -19008,6 +19077,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
showGigagroupConvertAlert();
long prevLinkedChatId = chatInfo != null ? chatInfo.linked_chat_id : 0;
chatInfo = chatFull;
if (ChatObject.isBoostSupported(currentChat)) {
getMessagesController().getBoostsController().getBoostsStats(dialog_id, boostsStatus -> {
if (boostsStatus == null) {
return;
}
this.boostsStatus = boostsStatus;
getMessagesController().getBoostsController().userCanBoostChannel(dialog_id, boostsStatus, canApplyBoost -> this.canApplyBoosts = canApplyBoost);
});
}
groupCall = getMessagesController().getGroupCall(currentChat.id, true);
if (ChatObject.isChannel(currentChat) && currentChat.megagroup && fragmentContextView != null) {
fragmentContextView.checkCall(openAnimationStartTime == 0 || SystemClock.elapsedRealtime() < openAnimationStartTime + 150);
@ -19040,7 +19118,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
if (chatActivityEnterView != null) {
chatActivityEnterView.setChatInfo(chatInfo);
chatActivityEnterView.checkChannelRights();
}
updateSecretStatus();
if (mentionContainer != null && mentionContainer.getAdapter() != null) {
mentionContainer.getAdapter().setChatInfo(chatInfo);
}
@ -19743,7 +19823,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (messagePreviewParams != null) {
messagePreviewParams.checkEdits(messageObjects);
}
if (did != dialog_id && did != mergeDialogId || chatMode == MODE_SAVED) {
if (did != dialog_id && did != mergeDialogId) {
return;
}
int loadIndex = did == dialog_id ? 0 : 1;
@ -20542,6 +20622,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
updateReactionsMentionButton(true);
}
} else if (id == NotificationCenter.chatWasBoostedByUser) {
if (dialog_id == (long) args[2]) {
boostsStatus = (TL_stories.TL_premium_boostsStatus) args[0];
canApplyBoosts = (ChannelBoostsController.CanApplyBoost) args[1];
}
} else if (id == NotificationCenter.topicsDidLoaded) {
if (isTopic) {
if (getParentActivity() == null) {
@ -21386,7 +21471,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (newChat != null) {
currentChat = newChat;
if (!newChat.gigagroup && newChat.slowmode_enabled && messageObject.isSent() && chatMode != MODE_SCHEDULED) {
if (chatInfo != null) {
if (chatInfo != null && !ChatObject.isIgnoredChatRestrictionsForBoosters(chatInfo)) {
int date = messageObject.messageOwner.date + chatInfo.slowmode_seconds;
int currentTime = getConnectionsManager().getCurrentTime();
if (date > getConnectionsManager().getCurrentTime()) {
@ -23010,6 +23095,65 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
openAttachBotLayout(attachMenuBotToOpen);
attachMenuBotToOpen = null;
}
checkGroupEmojiPackHint();
}
private void checkGroupEmojiPackHint() {
if (groupEmojiPackHint == null && ChatObject.isMegagroup(currentChat)) {
final TLRPC.ChatFull chatFull = getMessagesController().getChatFull(currentChat.id);
if (chatFull == null || chatFull.emojiset == null || chatActivityEnterView == null || getContext() == null) {
return;
}
if (MessagesController.getGlobalMainSettings().getBoolean("groupEmojiPackHintShown", false)) {
return;
}
TLRPC.StickerSet emojiSet = chatFull.emojiset;
long thumbDocumentId = emojiSet.thumb_document_id;
if (thumbDocumentId == 0) {
TLRPC.TL_messages_stickerSet stickerSet = getMediaDataController().getGroupStickerSetById(emojiSet);
if (stickerSet != null && !stickerSet.documents.isEmpty()) {
thumbDocumentId = stickerSet.documents.get(0).id;
}
}
if (thumbDocumentId == 0) {
return;
}
MessagesController.getGlobalMainSettings().edit().putBoolean("groupEmojiPackHintShown", true).apply();
groupEmojiPackHint = new HintView2(getContext(), HintView2.DIRECTION_BOTTOM);
groupEmojiPackHint.setCloseButton(true);
groupEmojiPackHint.setMultilineText(true);
groupEmojiPackHint.setTextAlign(Layout.Alignment.ALIGN_CENTER);
groupEmojiPackHint.setRounding(12);
SpannableStringBuilder packFullName = new SpannableStringBuilder("d");
packFullName.setSpan(new AnimatedEmojiSpan(thumbDocumentId, groupEmojiPackHint.getTextPaint().getFontMetricsInt()), 0, packFullName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
SpannableStringBuilder titleBuilder = new SpannableStringBuilder(chatFull.emojiset.title);
titleBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), 0, titleBuilder.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
packFullName.append(" ");
packFullName.append(titleBuilder);
groupEmojiPackHint.setText(AndroidUtilities.replaceCharSequence("%s", LocaleController.getString(R.string.GroupEmojiPackHint), packFullName));
groupEmojiPackHint.setMaxWidthPx(HintView2.cutInFancyHalf(groupEmojiPackHint.getText(), groupEmojiPackHint.getTextPaint()));
groupEmojiPackHint.setDuration(-1);
groupEmojiPackHint.setPadding(dp(6), 0, dp(6), 0);
AndroidUtilities.runOnUIThread(() -> {
FrameLayout.LayoutParams lp = LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, 0, 0, 0, 0);
lp.bottomMargin = chatActivityEnterView.getMeasuredHeight();
contentView.addView(groupEmojiPackHint, lp);
groupEmojiPackHint.setJointPx(0, chatActivityEnterView.getEmojiButton().getX() + dp(18));
groupEmojiPackHint.show();
}, 300);
}
}
public boolean groupEmojiPackHintWasVisible() {
boolean result = false;
if (groupEmojiPackHint != null) {
result = true;
if (groupEmojiPackHint.shown()) {
groupEmojiPackHint.hide();
}
}
groupEmojiPackHint = null;
return result;
}
public void openAttachBotLayout(String botUsername) {
@ -23306,6 +23450,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
} else {
bottomOverlayChatText.setText(LocaleController.getString("Unblock", R.string.Unblock));
}
bottomOverlayChatText.setVisibility(View.VISIBLE);
if (botButtons != null) {
botButtons = null;
if (chatActivityEnterView != null) {
@ -23513,8 +23658,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
if (sentBotStart) {
getMessagesController().sendBotStart(currentUser, botUser);
bottomOverlayChat.setVisibility(View.GONE);
chatActivityEnterView.setVisibility(View.VISIBLE);
chatActivityEnterView.setBotInfo(botInfo);
@ -25351,7 +25494,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
getMediaDataController().saveDraft(dialog_id, draftThreadId, message[0], entities, (replyMessage != null && !replyMessage.isTopicMainMessage && replyMessage.replyToForumTopic == null && !ignoreDraft) ? replyMessage.messageOwner : null, replyingQuote, !searchWebpage, false);
getMessagesController().cancelTyping(0, dialog_id, threadMessageId);
}
if (chatMode == 0 || chatMode == MODE_SAVED) {
if (!pausedOnLastMessage && !firstLoading && (!isThreadChat() || isTopic)) {
SharedPreferences.Editor editor = MessagesController.getNotificationsSettings(currentAccount).edit();
int messageId = 0;
@ -25460,9 +25604,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
} else {
draftMessage = getMediaDataController().getDraft(dialog_id, chatMode == MODE_SAVED ? 0 : threadMessageId);
}
MediaDataController.DraftVoice voiceDraft = MediaDataController.getInstance(currentAccount).getDraftVoice(dialog_id, getTopicId());
TLRPC.Message draftReplyMessage = draftMessage != null && draftMessage.reply_to != null && draftMessage.reply_to.reply_to_msg_id != 0 ? getMediaDataController().getDraftMessage(dialog_id, topicId != null ? topicId : threadMessageId) : null;
if (chatActivityEnterView.getFieldText() == null || chatMode == 0 && getUserConfig().getClientUserId() == getDialogId() && draftMessage != null && appliedDraftDate < draftMessage.date) {
if (draftMessage != null) {
if (voiceDraft != null) {
chatActivityEnterView.setVoiceDraft(voiceDraft);
} else if (draftMessage != null) {
appliedDraftDate = draftMessage.date;
chatActivityEnterView.setWebPage(null, !draftMessage.no_webpage);
CharSequence message;
@ -25914,6 +26061,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (!single && (message.messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium || message.messageOwner.action instanceof TLRPC.TL_messageActionGiftCode)) {
return false;
}
FileLog.d("open menu msg_id=" + message.getId());
final int type = getMessageType(message);
if (single) {
boolean isGiveawayResultsMessage = false;
@ -25972,9 +26120,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
return true;
}
} else if (message.messageOwner.action instanceof TLRPC.TL_messageActionSetChatTheme) {
if (currentChat == null || ChatObject.canChangeChatInfo(currentChat)) {
showChatThemeBottomSheet();
}
showChatThemeBottomSheet();
return true;
}
}
@ -27215,7 +27361,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
Layout layout = getLayout();
int width = 0;
for (int i = 0; i < layout.getLineCount(); ++i) {
width = Math.max(width, (int) layout.getLineWidth(i));
width = Math.max(width, (int) Math.ceil(layout.getLineWidth(i)));
}
widthMeasureSpec = MeasureSpec.makeMeasureSpec(getPaddingLeft() + width + getPaddingRight(), MeasureSpec.EXACTLY);
}
@ -27560,6 +27706,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
showDialog(alert);
});
popupLayout.addView(button, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
popupLayout.precalculateHeight();
}
}
}
@ -27769,9 +27916,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (emptyViewContainer == null) {
emptyViewContainer = new FrameLayout(getContext());
emptyViewContainer.setOnTouchListener((v, event) -> true);
// emptyViewContainer.setOnTouchListener((v, event) -> true);
emptyViewContainer.setVisibility(View.INVISIBLE);
contentView.addView(emptyViewContainer, 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER));
contentView.addView(emptyViewContainer, 3, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER));
} else {
emptyViewContainer.removeAllViews();
}
@ -30922,7 +31069,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
if (cell.hasButton()) {
ThemePreviewActivity.showFor(ChatActivity.this, message);
} else if (currentChat == null || ChatObject.canChangeChatInfo(currentChat)) {
} else {
showChatThemeBottomSheet();
}
return;
@ -33160,7 +33307,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
@Override
public void didPressChannelRecommendation(ChatMessageCell cell, TLRPC.Chat chat, boolean longPress) {
if (chat == null || parentLayout != null && parentLayout.isInPreviewMode()) {
if (getContext() == null || chat == null || parentLayout != null && parentLayout.isInPreviewMode()) {
return;
}
Bundle args = new Bundle();
@ -33322,7 +33469,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
BulletinFactory.of(ChatActivity.this).createSimpleBulletin(R.raw.story_bomb1, LocaleController.getString("StoryNotFound", R.string.StoryNotFound)).show();
} else {
TL_stories.StoryItem storyItem = messageObject.messageOwner.replyStory;
storyItem.dialogId = messageObject.messageOwner.reply_to.user_id;
storyItem.dialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.peer);
storyItem.messageId = messageObject.getId();
storyItem.messageType = 3;
StoriesUtilities.applyViewedUser(storyItem, currentUser);
@ -33479,6 +33626,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
@Override
public void didPressBoostCounter(ChatMessageCell cell) {
getNotificationCenter().postNotificationName(NotificationCenter.openBoostForUsersDialog, dialog_id, cell);
}
@Override
public void didStartVideoStream(MessageObject message) {
if (message.isVideo()) {
@ -33776,7 +33928,42 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
} else if (messageObject.sponsoredWebPage != null) {
Browser.openUrl(getContext(), messageObject.sponsoredWebPage.url, true, false);
} else if (messageObject.sponsoredChatInvite != null) {
showDialog(new JoinGroupAlert(getContext(), messageObject.sponsoredChatInvite, messageObject.sponsoredChatInviteHash, ChatActivity.this, themeDelegate));
final TLRPC.TL_messages_checkChatInvite req = new TLRPC.TL_messages_checkChatInvite();
req.hash = messageObject.sponsoredChatInviteHash;
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
if (error == null) {
TLRPC.ChatInvite invite = (TLRPC.ChatInvite) response;
if (invite.chat != null && (!ChatObject.isLeftFromChat(invite.chat) || !invite.chat.kicked && (ChatObject.isPublic(invite.chat) || invite instanceof TLRPC.TL_chatInvitePeek || invite.chat.has_geo))) {
MessagesController.getInstance(currentAccount).putChat(invite.chat, false);
ArrayList<TLRPC.Chat> chats = new ArrayList<>();
chats.add(invite.chat);
MessagesStorage.getInstance(currentAccount).putUsersAndChats(null, chats, false, true);
args.putLong("chat_id", invite.chat.id);
if (MessagesController.getInstance(currentAccount).checkCanOpenChat(args, ChatActivity.this)) {
ChatActivity fragment = new ChatActivity(args);
if (invite instanceof TLRPC.TL_chatInvitePeek) {
fragment.setChatInvite(invite);
}
presentFragment(fragment);
}
} else {
showDialog(new JoinGroupAlert(getContext(), messageObject.sponsoredChatInvite, messageObject.sponsoredChatInviteHash, ChatActivity.this, themeDelegate, JoinGroupAlert.ORIGINATION_SPONSORED_CHAT));
}
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate);
builder.setTitle(LocaleController.getString("AppName", R.string.AppName));
if (error.text.startsWith("FLOOD_WAIT")) {
builder.setMessage(LocaleController.getString("FloodWait", R.string.FloodWait));
} else if (error.text.startsWith("INVITE_HASH_EXPIRED")) {
builder.setTitle(LocaleController.getString("ExpiredLink", R.string.ExpiredLink));
builder.setMessage(LocaleController.getString("InviteExpired", R.string.InviteExpired));
} else {
builder.setMessage(LocaleController.getString("JoinToGroupErrorNotExist", R.string.JoinToGroupErrorNotExist));
}
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);
showDialog(builder.create());
}
}), ConnectionsManager.RequestFlagFailOnServerErrors);
} else {
long peerId = MessageObject.getPeerId(messageObject.messageOwner.from_id);
if (peerId == getDialogId() && messageObject.sponsoredChannelPost != 0) {
@ -35009,8 +35196,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
});
switchingFromTopics = true;
actionBar.invalidate();
contentView.invalidate();
if (actionBar != null) {
actionBar.invalidate();
}
if (contentView != null) {
contentView.invalidate();
}
fragmentTransition = new AnimatorSet();
fragmentTransition.addListener(new AnimatorListenerAdapter() {
@ -35063,7 +35254,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private void showChatThemeBottomSheet() {
if (currentChat != null) {
presentFragment(new ChannelColorActivity(getDialogId()).setOnApplied(ChatActivity.this));
if (ChatObject.isMegagroup(currentChat)) {
if (ChatObject.hasAdminRights(currentChat)) {
presentFragment(new GroupColorActivity(getDialogId()).setOnApplied(ChatActivity.this));
}
} else {
if (ChatObject.canChangeChatInfo(currentChat)) {
presentFragment(new ChannelColorActivity(getDialogId()).setOnApplied(ChatActivity.this));
}
}
return;
}
chatThemeBottomSheet = new ChatThemeBottomSheet(ChatActivity.this, themeDelegate);
@ -36130,4 +36329,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
return;
getMessagesController().invalidateUserPremiumBlocked(getDialogId(), classGuid);
}
public boolean checkCanRemoveRestrictionsByBoosts() {
boolean result = ChatObject.isPossibleRemoveChatRestrictionsByBoosts(chatInfo);
if (result) {
AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus());
LimitReachedBottomSheet.openBoostsForRemoveRestrictions(ChatActivity.this, boostsStatus, canApplyBoosts, dialog_id, false);
}
return result;
}
}

View file

@ -45,7 +45,6 @@ import android.widget.ScrollView;
import androidx.annotation.NonNull;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChannelBoostsController;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.Emoji;
@ -60,6 +59,7 @@ import org.telegram.messenger.R;
import org.telegram.messenger.browser.Browser;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.tgnet.tl.TL_stories;
import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.ActionBarMenu;
import org.telegram.ui.ActionBar.AlertDialog;
@ -105,7 +105,6 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
private AlertDialog progressDialog;
private UndoView undoView;
private LinearLayout avatarContainer;
private BackupImageView avatarImage;
private View avatarOverlay;
@ -174,6 +173,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
private boolean historyHidden;
private TLRPC.ChatReactions availableReactions;
private TL_stories.TL_premium_boostsStatus boostsStatus;
private boolean createAfterUpload;
private boolean donePressed;
@ -890,7 +890,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
if (ChatObject.isChannelAndNotMegaGroup(currentChat) && ChatObject.canChangeChatInfo(currentChat)) {
colorCell = new PeerColorActivity.ChangeNameColorCell(currentAccount, -currentChat.id, context, getResourceProvider());
colorCell.setBackgroundDrawable(Theme.getSelectorDrawable(true));
colorCell.setBackground(Theme.getSelectorDrawable(true));
typeEditContainer.addView(colorCell, LayoutHelper.createLinear(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
colorCell.setOnClickListener(v -> {
presentFragment(new ChannelColorActivity(-currentChat.id).setOnApplied(this));
@ -952,6 +952,19 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
});
}
if (ChatObject.isMegagroup(currentChat) && ChatObject.hasAdminRights(currentChat)) {
MessagesController.getInstance(currentAccount).getBoostsController().getBoostsStats(-currentChat.id, boostsStatus -> this.boostsStatus = boostsStatus);
colorCell = new PeerColorActivity.ChangeNameColorCell(currentAccount, -currentChat.id, context, getResourceProvider());
colorCell.setBackground(Theme.getSelectorDrawable(true));
typeEditContainer.addView(colorCell, LayoutHelper.createLinear(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
colorCell.setOnClickListener(v -> {
GroupColorActivity activity = new GroupColorActivity(-currentChat.id);
activity.boostsStatus = boostsStatus;
activity.setOnApplied(this);
presentFragment(activity);
});
}
if (isChannel) {
signCell = new TextCell(context, 23, false, true, null);
signCell.setBackgroundDrawable(Theme.getSelectorDrawable(true));
@ -1088,19 +1101,12 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
logCell.setOnClickListener(v -> presentFragment(new ChannelAdminLogActivity(currentChat)));
}
if (ChatObject.isChannelAndNotMegaGroup(currentChat)) {
if (ChatObject.isBoostSupported(currentChat)) {
statsAndBoosts = new TextCell(context);
statsAndBoosts.setTextAndIcon(LocaleController.getString("StatisticsAndBoosts", R.string.StatisticsAndBoosts), R.drawable.msg_stats, true);
statsAndBoosts.setBackground(Theme.getSelectorDrawable(false));
statsAndBoosts.setOnClickListener(v -> {
Bundle args = new Bundle();
args.putLong("chat_id", chatId);
args.putBoolean("is_megagroup", currentChat.megagroup);
TLRPC.ChatFull chatInfo = getMessagesController().getChatFull(chatId);
if (chatInfo == null || !chatInfo.can_view_stats) {
args.putBoolean("only_boosts", true);
};
presentFragment(new StatisticActivity(args));
presentFragment(StatisticActivity.create(currentChat, false));
});
}
@ -1138,6 +1144,9 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
groupStickersActivity.setInfo(info);
presentFragment(groupStickersActivity);
});
if (statsAndBoosts != null) {
infoContainer.addView(statsAndBoosts, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
}
} else {
if (statsAndBoosts != null) {
infoContainer.addView(statsAndBoosts, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));

View file

@ -1181,6 +1181,12 @@ public class ChatRightsEditActivity extends BaseFragment {
banUsersRow = rowCount++;
addUsersRow = rowCount++;
pinMessagesRow = rowCount++;
channelStoriesRow = rowCount++;
if (channelStoriesExpanded) {
channelPostStoriesRow = rowCount++;
channelEditStoriesRow = rowCount++;
channelDeleteStoriesRow = rowCount++;
}
startVoiceChatRow = rowCount++;
addAdminsRow = rowCount++;
anonymousRow = rowCount++;

View file

@ -15,6 +15,7 @@ import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
@ -29,6 +30,7 @@ import android.widget.EditText;
import android.widget.FrameLayout;
import androidx.collection.LongSparseArray;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.LinearLayoutManager;
@ -88,6 +90,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
private static final int VIEW_TYPE_INNER_CHECK = 13;
private static final int VIEW_TYPE_EXPANDABLE_SWITCH = 14;
private static final int VIEW_TYPE_NOT_RESTRICT_BOOSTERS_SLIDER = 15;
private ListAdapter listViewAdapter;
private StickerEmptyView emptyView;
@ -163,6 +166,9 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
private int slowmodeRow;
private int slowmodeSelectRow;
private int slowmodeInfoRow;
private int dontRestrictBoostersRow;
private int dontRestrictBoostersInfoRow;
private int dontRestrictBoostersSliderRow;
private int contactsHeaderRow;
private int contactsStartRow;
@ -192,6 +198,8 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
private int selectedSlowmode;
private int initialSlowmode;
private boolean isEnabledNotRestrictBoosters;
private int notRestrictBoosters;
private final static int search_button = 0;
private final static int done_button = 1;
@ -314,6 +322,9 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
slowmodeRow = -1;
slowmodeSelectRow = -1;
slowmodeInfoRow = -1;
dontRestrictBoostersRow = -1;
dontRestrictBoostersInfoRow = -1;
dontRestrictBoostersSliderRow = -1;
loadingProgressRow = -1;
loadingUserCellRow = -1;
loadingHeaderRow = -1;
@ -367,6 +378,18 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
slowmodeSelectRow = rowCount++;
slowmodeInfoRow = rowCount++;
}
if (isNotRestrictBoostersVisible()) {
if (participantsDivider2Row == -1) {
participantsDivider2Row = rowCount++;
}
dontRestrictBoostersRow = rowCount++;
if (isEnabledNotRestrictBoosters) {
dontRestrictBoostersSliderRow = rowCount++;
}
dontRestrictBoostersInfoRow = rowCount++;
}
if (ChatObject.isChannel(currentChat)) {
if (participantsDivider2Row == -1) {
participantsDivider2Row = rowCount++;
@ -754,6 +777,17 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
checkBoxCell.setChecked(!checkBoxCell.isChecked(), true);
AndroidUtilities.updateVisibleRows(listView);
DiffCallback diffCallback = saveState();
updateRows();
updateListAnimated(diffCallback);
} else if (position == dontRestrictBoostersRow) {
TextCheckCell2 checkBoxCell = (TextCheckCell2) view;
isEnabledNotRestrictBoosters = !checkBoxCell.isChecked();
checkBoxCell.setChecked(isEnabledNotRestrictBoosters);
AndroidUtilities.updateVisibleRows(listView);
DiffCallback diffCallback = saveState();
updateRows();
updateListAnimated(diffCallback);
} else if (position == addNewRow) {
if (type == TYPE_BANNED || type == TYPE_KICKED) {
Bundle bundle = new Bundle();
@ -1048,6 +1082,9 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
if (sendMediaRow >= 0) {
listViewAdapter.notifyItemChanged(sendMediaRow);
}
DiffCallback diffCallback = saveState();
updateRows();
updateListAnimated(diffCallback);
} else if (position == sendMediaRow) {
DiffCallback diffCallback = saveState();
sendMediaExpanded = !sendMediaExpanded;
@ -1854,6 +1891,8 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
info = chatFull;
if (!hadInfo) {
selectedSlowmode = initialSlowmode = getCurrentSlowmode();
isEnabledNotRestrictBoosters = info.boosts_unrestrict > 0;
notRestrictBoosters = info.boosts_unrestrict;
}
AndroidUtilities.runOnUIThread(() -> loadChatParticipants(0, 200));
}
@ -1917,7 +1956,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
private boolean checkDiscard() {
String newBannedRights = ChatObject.getBannedRightsString(defaultBannedRights);
if (!newBannedRights.equals(initialBannedRights) || initialSlowmode != selectedSlowmode) {
if (!newBannedRights.equals(initialBannedRights) || initialSlowmode != selectedSlowmode || hasNotRestrictBoostersChanges()) {
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
builder.setTitle(LocaleController.getString("UserRestrictionsApplyChanges", R.string.UserRestrictionsApplyChanges));
if (isChannel) {
@ -2064,13 +2103,40 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
info.flags |= 131072;
getMessagesController().setChannelSlowMode(chatId, info.slowmode_seconds);
}
if (hasNotRestrictBoostersChanges()) {
boolean isEnabledNotRestrictBoosters = this.isEnabledNotRestrictBoosters && isNotRestrictBoostersVisible();
if (isEnabledNotRestrictBoosters && notRestrictBoosters == 0) {
getMessagesController().setBoostsToUnblockRestrictions(chatId, 1);
} else if (!isEnabledNotRestrictBoosters && notRestrictBoosters != 0) {
getMessagesController().setBoostsToUnblockRestrictions(chatId, 0);
} else {
getMessagesController().setBoostsToUnblockRestrictions(chatId, notRestrictBoosters);
}
}
finishFragment();
}
private boolean hasNotRestrictBoostersChanges() {
boolean isEnabledNotRestrictBoosters = this.isEnabledNotRestrictBoosters && isNotRestrictBoostersVisible();
return info != null && (info.boosts_unrestrict != notRestrictBoosters
|| (isEnabledNotRestrictBoosters && notRestrictBoosters == 0)
|| (!isEnabledNotRestrictBoosters && notRestrictBoosters != 0));
}
private boolean isNotRestrictBoostersVisible() {
return currentChat.megagroup && !currentChat.gigagroup && ChatObject.canUserDoAdminAction(currentChat,ChatObject.ACTION_DELETE_MESSAGES) &&
(selectedSlowmode > 0 || defaultBannedRights.send_plain || defaultBannedRights.send_media || defaultBannedRights.send_photos || defaultBannedRights.send_videos
|| defaultBannedRights.send_stickers || defaultBannedRights.send_audios || defaultBannedRights.send_docs
|| defaultBannedRights.send_voices || defaultBannedRights.send_roundvideos || defaultBannedRights.embed_links || defaultBannedRights.send_polls);
}
public void setInfo(TLRPC.ChatFull chatFull) {
info = chatFull;
if (info != null) {
selectedSlowmode = initialSlowmode = getCurrentSlowmode();
isEnabledNotRestrictBoosters = info.boosts_unrestrict > 0;
notRestrictBoosters = info.boosts_unrestrict;
}
}
@ -3062,10 +3128,33 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
if (info == null) {
return;
}
boolean needRowsUpdate = (selectedSlowmode > 0 && which == 0) || (selectedSlowmode == 0 && which > 0);
selectedSlowmode = which;
if (needRowsUpdate) {
DiffCallback diffCallback = saveState();
updateRows();
updateListAnimated(diffCallback);
}
listViewAdapter.notifyItemChanged(slowmodeInfoRow);
});
break;
case VIEW_TYPE_NOT_RESTRICT_BOOSTERS_SLIDER: {
SlideChooseView slider = new SlideChooseView(mContext);
view = slider;
slider.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
Drawable[] drawables = new Drawable[]{
ContextCompat.getDrawable(getContext(), R.drawable.mini_boost_profile_badge),
ContextCompat.getDrawable(getContext(), R.drawable.mini_boost_profile_badge2),
ContextCompat.getDrawable(getContext(), R.drawable.mini_boost_profile_badge2),
ContextCompat.getDrawable(getContext(), R.drawable.mini_boost_profile_badge2),
ContextCompat.getDrawable(getContext(), R.drawable.mini_boost_profile_badge2)
};
slider.setOptions(notRestrictBoosters > 0 ? (notRestrictBoosters - 1) : 0, drawables, "1", "2", "3", "4", "5");
slider.setCallback(which -> {
notRestrictBoosters = which + 1;
});
break;
}
case VIEW_TYPE_INNER_CHECK:
CheckBoxCell checkBoxCell = new CheckBoxCell(mContext, 4, 21, getResourceProvider());
checkBoxCell.getCheckBoxRound().setDrawBackgroundAsArc(14);
@ -3218,6 +3307,13 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
privacyCell.setText(LocaleController.getString("ChannelHideMembersInfo", R.string.ChannelHideMembersInfo));
} else if (position == gigaInfoRow) {
privacyCell.setText(LocaleController.getString("BroadcastGroupConvertInfo", R.string.BroadcastGroupConvertInfo));
} else if (position == dontRestrictBoostersInfoRow) {
privacyCell.setBackground(Theme.getThemedDrawableByKey(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
if (isEnabledNotRestrictBoosters) {
privacyCell.setText(LocaleController.getString(R.string.GroupNotRestrictBoostersInfo2));
} else {
privacyCell.setText(LocaleController.getString(R.string.GroupNotRestrictBoostersInfo));
}
}
break;
case 2:
@ -3288,6 +3384,8 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
case VIEW_TYPE_EXPANDABLE_SWITCH:
case 7:
TextCheckCell2 checkCell = (TextCheckCell2) holder.itemView;
checkCell.getCheckBox().setDrawIconType(1);
checkCell.getCheckBox().setColors(Theme.key_fill_RedNormal, Theme.key_switch2TrackChecked, Theme.key_windowBackgroundWhite, Theme.key_windowBackgroundWhite);
boolean animated = checkCell.getTag() != null && (Integer) checkCell.getTag() == position;
checkCell.setTag(position);
if (position == changeInfoRow) {
@ -3298,6 +3396,10 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
checkCell.setTextAndCheck(LocaleController.getString("UserRestrictionsPinMessages", R.string.UserRestrictionsPinMessages), !defaultBannedRights.pin_messages && !ChatObject.isPublic(currentChat), true, animated);
} else if (position == sendMessagesRow) {
checkCell.setTextAndCheck(LocaleController.getString("UserRestrictionsSendText", R.string.UserRestrictionsSendText), !defaultBannedRights.send_plain, true, animated);
} else if(position == dontRestrictBoostersRow) {
checkCell.setTextAndCheck(LocaleController.getString(R.string.GroupNotRestrictBoosters), isEnabledNotRestrictBoosters, false, animated);
checkCell.getCheckBox().setDrawIconType(0);
checkCell.getCheckBox().setColors(Theme.key_switchTrack, Theme.key_switchTrackChecked, Theme.key_windowBackgroundWhite, Theme.key_windowBackgroundWhite);
} else if (position == sendMediaRow) {
int sentMediaCount = getSendMediaSelectedCount();
checkCell.setTextAndCheck(LocaleController.getString("UserRestrictionsSendMedia", R.string.UserRestrictionsSendMedia), sentMediaCount > 0, true, animated);
@ -3307,7 +3409,6 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
boolean checked = !checkCell.isChecked();
checkCell.setChecked(checked);
setSendMediaEnabled(checked);
}
});
} else if (position == sendStickersRow) {
@ -3419,14 +3520,14 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
return 3;
} else if (position == restricted1SectionRow || position == permissionsSectionRow || position == slowmodeRow || position == gigaHeaderRow) {
return 5;
} else if (position == participantsInfoRow || position == slowmodeInfoRow || position == gigaInfoRow || position == antiSpamInfoRow || position == hideMembersInfoRow) {
} else if (position == participantsInfoRow || position == slowmodeInfoRow || position == dontRestrictBoostersInfoRow || position == gigaInfoRow || position == antiSpamInfoRow || position == hideMembersInfoRow) {
return 1;
} else if (position == blockedEmptyRow) {
return 4;
} else if (position == removedUsersRow) {
return 6;
} else if (position == changeInfoRow || position == addUsersRow || position == pinMessagesRow || position == sendMessagesRow ||
position == sendStickersRow || position == embedLinksRow || position == manageTopicsRow) {
position == sendStickersRow || position == embedLinksRow || position == manageTopicsRow || position == dontRestrictBoostersRow) {
return 7;
} else if (position == membersHeaderRow || position == contactsHeaderRow || position == botHeaderRow || position == loadingHeaderRow) {
return 8;
@ -3442,6 +3543,8 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
return VIEW_TYPE_INNER_CHECK;
} else if (position == sendMediaRow) {
return VIEW_TYPE_EXPANDABLE_SWITCH;
} else if (position == dontRestrictBoostersSliderRow) {
return VIEW_TYPE_NOT_RESTRICT_BOOSTERS_SLIDER;
}
return 0;
}
@ -3460,6 +3563,9 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
private void setSendMediaEnabled(boolean enabled) {
defaultBannedRights.send_media = !enabled;
defaultBannedRights.send_gifs = !enabled;
defaultBannedRights.send_inline = !enabled;
defaultBannedRights.send_games = !enabled;
defaultBannedRights.send_photos = !enabled;
defaultBannedRights.send_videos = !enabled;
defaultBannedRights.send_stickers = !enabled;
@ -3470,6 +3576,9 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
defaultBannedRights.embed_links = !enabled;
defaultBannedRights.send_polls = !enabled;
AndroidUtilities.updateVisibleRows(listView);
DiffCallback diffCallback = saveState();
updateRows();
updateListAnimated(diffCallback);
}
private boolean isExpandableSendMediaRow(int position) {
@ -3609,6 +3718,9 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
put(++pointer, slowmodeRow, sparseIntArray);
put(++pointer, slowmodeSelectRow, sparseIntArray);
put(++pointer, slowmodeInfoRow, sparseIntArray);
put(++pointer, dontRestrictBoostersRow, sparseIntArray);
put(++pointer, dontRestrictBoostersSliderRow, sparseIntArray);
put(++pointer, dontRestrictBoostersInfoRow, sparseIntArray);
put(++pointer, loadingProgressRow, sparseIntArray);
put(++pointer, loadingUserCellRow, sparseIntArray);
put(++pointer, loadingHeaderRow, sparseIntArray);

View file

@ -1112,6 +1112,15 @@ public class AnimatedEmojiDrawable extends Drawable {
set(document, cacheType, animated);
}
public void removeOldDrawable() {
if (drawables[1] != null) {
if (drawables[1] instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) drawables[1]).removeView(this);
}
drawables[1] = null;
}
}
public void set(TLRPC.Document document, int cacheType, boolean animated) {
if (drawables[0] instanceof AnimatedEmojiDrawable && document != null && ((AnimatedEmojiDrawable) drawables[0]).getDocumentId() == document.id) {
return;

View file

@ -80,10 +80,14 @@ public final class BulletinFactory {
if (BuildVars.DEBUG_VERSION) {
createErrorBulletin(error.code + " " + error.text).show();
} else {
createErrorBulletin(LocaleController.getString("UnknownError", R.string.UnknownError)).show();
createErrorBulletin(LocaleController.getString(R.string.UnknownError)).show();
}
}
public static void showError(TLRPC.TL_error error) {
global().createErrorBulletin(LocaleController.formatString(R.string.UnknownErrorCode, error.text)).show();
}
public enum FileType {
PHOTO("PhotoSavedHint", R.string.PhotoSavedHint, Icon.SAVED_TO_GALLERY),

View file

@ -96,6 +96,7 @@ import androidx.annotation.Nullable;
import androidx.collection.LongSparseArray;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.math.MathUtils;
import androidx.core.os.BuildCompat;
import androidx.core.view.ViewCompat;
@ -156,6 +157,7 @@ import org.telegram.ui.BasePermissionsActivity;
import org.telegram.ui.ChatActivity;
import org.telegram.ui.Components.Premium.GiftPremiumBottomSheet;
import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet;
import org.telegram.ui.Components.Premium.PremiumGradient;
import org.telegram.ui.ContentPreviewViewer;
import org.telegram.ui.DialogsActivity;
import org.telegram.ui.GroupStickersActivity;
@ -171,6 +173,8 @@ import org.telegram.ui.Stories.recorder.HintView2;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -264,6 +268,10 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
void onUpdateSlowModeButton(View button, boolean show, CharSequence time);
default boolean checkCanRemoveRestrictionsByBoosts() {
return false;
}
default void scrollToSendingMessage() {
}
@ -392,7 +400,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
private boolean sendRoundEnabled = true;
private boolean sendVoiceEnabled = true;
private boolean sendPlainEnabled = true;
public boolean sendPlainEnabled = true;
private boolean emojiButtonRestricted;
@ -451,6 +459,92 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
}
private static class SlowModeBtn extends FrameLayout {
private final SimpleTextView textView;
private final RectF bgRect = new RectF();
private final Paint gradientPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Drawable closeDrawable;
private boolean isPremiumMode = false;
public SlowModeBtn(@NonNull Context context) {
super(context);
textView = new SimpleTextView(context);
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
setWillNotDraw(false);
closeDrawable = ContextCompat.getDrawable(context, R.drawable.msg_mini_close_tooltip);
closeDrawable.setBounds(0, 0, closeDrawable.getIntrinsicWidth(), closeDrawable.getIntrinsicHeight());
setClipToPadding(false);
setClipChildren(false);
ScaleStateListAnimator.apply(this);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
gradientPaint.setShader(new LinearGradient(0, 0, getMeasuredWidth(), 0, new int[]{0xff7593ff, 0xffa472ff}, new float[]{0f, 1f}, Shader.TileMode.CLAMP));
}
public void setTextSize(int size) {
textView.setTextSize(size);
invalidate();
}
public void setTextColor(int color) {
textView.setTextColor(color);
invalidate();
}
public void setGravity(int gravity) {
textView.setGravity(gravity);
invalidate();
}
public void setText(CharSequence text) {
textView.setText(text);
invalidate();
}
public void setPremiumMode(boolean premiumMode) {
this.isPremiumMode = premiumMode;
invalidate();
}
public CharSequence getText() {
return textView.getText();
}
@Override
protected void onDraw(Canvas canvas) {
if (isPremiumMode) {
canvas.save();
int heightRect = dp(26);
canvas.translate(0, ((getMeasuredHeight() - heightRect) / 2f) - dp(1));
bgRect.set(0, 0f, (float) getMeasuredWidth() - getPaddingEnd(), (float) heightRect);
canvas.drawRoundRect(bgRect, heightRect / 2f, heightRect / 2f, gradientPaint);
canvas.translate(getMeasuredWidth() - getPaddingEnd() - dp(6) - closeDrawable.getIntrinsicWidth(), dp(5));
closeDrawable.draw(canvas);
canvas.restore();
}
}
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (child instanceof SimpleTextView && isPremiumMode) {
SimpleTextView simpleTextView = (SimpleTextView) child;
canvas.save();
canvas.scale(0.8f, 0.8f);
canvas.translate(-dp(16), dp(5));
int oldColor = simpleTextView.getTextPaint().getColor();
simpleTextView.getTextPaint().setColor(Color.WHITE);
boolean result = super.drawChild(canvas, child, drawingTime);
simpleTextView.getTextPaint().setColor(oldColor);
canvas.restore();
return result;
}
return super.drawChild(canvas, child, drawingTime);
}
}
@SuppressWarnings("FieldCanBeLocal")
private View.AccessibilityDelegate mediaMessageButtonsDelegate = new View.AccessibilityDelegate() {
@Override
@ -464,7 +558,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
@Nullable
protected EditTextCaption messageEditText;
private SimpleTextView slowModeButton;
private SlowModeBtn slowModeButton;
private int slowModeTimer;
private Runnable updateSlowModeRunnable;
private View sendButton;
@ -799,7 +893,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
if (!recordingAudioVideo) {
recordingAudioVideo = true;
updateRecordInterface(RECORD_STATE_ENTER);
updateRecordInterface(RECORD_STATE_ENTER, true);
if (recordCircle != null) {
recordCircle.showWaves(false, false);
}
@ -818,7 +912,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
TL_stories.StoryItem storyItem = delegate != null ? delegate.getReplyToStory() : null;
MediaController.getInstance().startRecording(currentAccount, dialog_id, replyingMessageObject, getThreadMessage(), storyItem, recordingGuid, true);
recordingAudioVideo = true;
updateRecordInterface(RECORD_STATE_ENTER);
updateRecordInterface(RECORD_STATE_ENTER, true);
if (recordTimerView != null) {
recordTimerView.start(0);
}
@ -1559,7 +1653,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
delegate.toggleVideoRecordingPause();
} else {
MediaController.getInstance().toggleRecordingPause();
MediaController.getInstance().toggleRecordingPause(voiceOnce);
delegate.needStartRecordAudio(0);
if (slideText != null) {
slideText.setEnabled(false);
@ -1570,6 +1664,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
} else if (oncePressed && onceRect.contains(x, y)) {
voiceOnce = !voiceOnce;
periodDrawable.setValue(1, voiceOnce, true);
MediaDataController.getInstance(currentAccount).toggleDraftVoiceOnce(dialog_id, parentFragment != null && parentFragment.isTopic ? parentFragment.getTopicId() : 0, voiceOnce);
if (voiceOnce) {
showHintView();
} else {
@ -2520,7 +2615,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
if (!isPopupShowing() || currentPopupContentType != 0) {
showPopup(1, 0);
emojiView.onOpen(messageEditText != null && messageEditText.length() > 0);
emojiView.onOpen(messageEditText != null && messageEditText.length() > 0, parentFragment != null && parentFragment.groupEmojiPackHintWasVisible());
} else {
if (searchingType != 0) {
setSearchingTypeInternal(0, true);
@ -2668,7 +2763,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
messageTransitionIsRunning = false;
AndroidUtilities.runOnUIThread(moveToSendStateRunnable = () -> {
moveToSendStateRunnable = null;
updateRecordInterface(RECORD_STATE_SENDING);
updateRecordInterface(RECORD_STATE_SENDING, true);
}, 200);
}
getParent().requestDisallowInterceptTouchEvent(true);
@ -2702,7 +2797,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
millisecondsRecorded = 0;
recordingAudioVideo = false;
updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE);
updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE, true);
} else {
sendButtonVisible = true;
startLockTransition();
@ -2729,7 +2824,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
millisecondsRecorded = 0;
recordingAudioVideo = false;
updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE);
updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE, true);
} else {
if (recordAudioVideoRunnableStarted) {
AndroidUtilities.cancelRunOnUIThread(recordAudioVideoRunnable);
@ -2759,7 +2854,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
messageTransitionIsRunning = false;
AndroidUtilities.runOnUIThread(moveToSendStateRunnable = () -> {
moveToSendStateRunnable = null;
updateRecordInterface(RECORD_STATE_SENDING);
updateRecordInterface(RECORD_STATE_SENDING, true);
}, shouldDrawBackground ? 500 : 0);
}
}
@ -2809,7 +2904,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
MediaController.getInstance().stopRecording(0, false, 0, voiceOnce);
}
recordingAudioVideo = false;
updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE);
updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE, true);
}
return true;
}
@ -3172,19 +3267,22 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
});
sendButton.setOnLongClickListener(this::onSendLongClick);
slowModeButton = new SimpleTextView(context);
slowModeButton = new SlowModeBtn(context);
slowModeButton.setTextSize(18);
slowModeButton.setVisibility(INVISIBLE);
slowModeButton.setSoundEffectsEnabled(false);
slowModeButton.setScaleX(0.1f);
slowModeButton.setScaleY(0.1f);
slowModeButton.setAlpha(0.0f);
slowModeButton.setPadding(0, 0, dp(13), 0);
slowModeButton.setPadding(0, 0, dp(10), 0);
slowModeButton.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
slowModeButton.setTextColor(getThemedColor(Theme.key_chat_messagePanelIcons));
sendButtonContainer.addView(slowModeButton, LayoutHelper.createFrame(64, 48, Gravity.RIGHT | Gravity.TOP));
sendButtonContainer.addView(slowModeButton, LayoutHelper.createFrame(74, 48, Gravity.RIGHT | Gravity.TOP));
slowModeButton.setOnClickListener(v -> {
if (delegate != null) {
if (delegate.checkCanRemoveRestrictionsByBoosts()) {
return;
}
delegate.onUpdateSlowModeButton(slowModeButton, true, slowModeButton.getText());
}
});
@ -3550,6 +3648,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
new File(audioToSendPath).delete();
}
MediaDataController.getInstance(currentAccount).pushDraftVoiceMessage(dialog_id, parentFragment != null && parentFragment.isTopic ? parentFragment.getTopicId() : 0, null);
MediaController.getInstance().stopRecording(0, false, 0, false);
millisecondsRecorded = 0;
hideRecordedAudioPanel(false);
@ -3933,6 +4032,9 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
private void showRestrictedHint() {
if (delegate != null && delegate.checkCanRemoveRestrictionsByBoosts()) {
return;
}
if (DialogObject.isChatDialog(dialog_id)) {
TLRPC.Chat chat = accountInstance.getMessagesController().getChat(-dialog_id);
BulletinFactory.of(parentFragment).createSimpleBulletin(R.raw.passcode_lock_close, LocaleController.formatString("SendPlainTextRestrictionHint", R.string.SendPlainTextRestrictionHint, ChatObject.getAllowedSendString(chat)), 3).show();
@ -5104,7 +5206,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
MediaController.getInstance().stopRecording(0, false, 0, false);
}
recordingAudioVideo = false;
updateRecordInterface(RECORD_STATE_CANCEL);
updateRecordInterface(RECORD_STATE_CANCEL, true);
}
public void showContextProgress(boolean show) {
@ -5144,7 +5246,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
(isUploading = SendMessagesHelper.getInstance(currentAccount).isUploadingMessageIdDialog(dialog_id)) ||
SendMessagesHelper.getInstance(currentAccount).isSendingMessageIdDialog(dialog_id))) {
TLRPC.Chat chat = accountInstance.getMessagesController().getChat(info.id);
if (!ChatObject.hasAdminRights(chat)) {
if (!ChatObject.hasAdminRights(chat) && !ChatObject.isIgnoredChatRestrictionsForBoosters(info)) {
currentTime = info.slowmode_seconds;
slowModeTimer = isUploading ? Integer.MAX_VALUE : Integer.MAX_VALUE - 1;
} else {
@ -5598,13 +5700,12 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
stickersEnabled = ChatObject.canSendStickers(chat);
sendPlainEnabled = ChatObject.canSendPlain(chat);
sendPlainEnabled = ChatObject.canSendPlain(chat);
emojiButtonRestricted = !stickersEnabled && !sendPlainEnabled;
emojiButtonAlpha = emojiButtonRestricted ? 0.5f : 1.0f;
updateEmojiButtonParams();
if (!emojiButtonRestricted) {
if (emojiView != null) {
emojiView.setStickersBanned(!ChatObject.canSendPlain(chat), !ChatObject.canSendStickers(chat), chat.id);
emojiView.setStickersBanned(!sendPlainEnabled, !stickersEnabled, -dialog_id);
}
}
sendRoundEnabled = ChatObject.canSendRoundVideo(chat);
@ -5758,6 +5859,12 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
if (emojiView != null) {
emojiView.setChatInfo(info);
}
if (slowModeButton != null) {
slowModeButton.setPremiumMode(ChatObject.isPossibleRemoveChatRestrictionsByBoosts(chatInfo));
}
if (ChatObject.isIgnoredChatRestrictionsForBoosters(chatInfo)) {
return;
}
setSlowModeTimer(chatInfo.slowmode_next_send_date);
}
@ -6243,12 +6350,14 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
recordCircle.setSendButtonInvisible();
}
}, 100);
millisecondsRecorded = 0;
return;
} else if (audioToSend != null) {
MessageObject playing = MediaController.getInstance().getPlayingMessageObject();
if (playing != null && playing == audioToSendMessageObject) {
MediaController.getInstance().cleanupPlayer(true, true);
}
MediaDataController.getInstance(currentAccount).pushDraftVoiceMessage(dialog_id, parentFragment != null && parentFragment.isTopic ? parentFragment.getTopicId() : 0, null);
SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(audioToSend, null, audioToSendPath, dialog_id, replyingMessageObject, getThreadMessage(), null, null, null, null, notify, scheduleDate, voiceOnce ? 0x7FFFFFFF : 0, null, null, false);
applyStoryToSendMessageParams(params);
SendMessagesHelper.getInstance(currentAccount).sendMessage(params);
@ -6262,6 +6371,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
recordCircle.setSendButtonInvisible();
}
}, 100);
millisecondsRecorded = 0;
return;
}
CharSequence message = messageEditText == null ? "" : messageEditText.getText();
@ -6382,6 +6492,21 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
}
}
if (emoji != null) {
TLRPC.ChatFull chatFull = MessagesController.getInstance(currentAccount).getChatFull(-dialogId);
if (chatFull != null && chatFull.emojiset != null) {
TLRPC.TL_messages_stickerSet stickerSet = MediaDataController.getInstance(currentAccount).getGroupStickerSetById(chatFull.emojiset);
if (stickerSet != null) {
for (TLRPC.Document document : stickerSet.documents) {
if (document.id == documentId) {
return false;
}
}
}
}
}
if (emoji == null || !MessageObject.isFreeEmoji(emoji)) {
BulletinFactory.of(parentFragment)
.createEmojiBulletin(
@ -7361,7 +7486,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
private void setSlowModeButtonVisible(boolean visible) {
slowModeButton.setVisibility(visible ? VISIBLE : GONE);
int padding = visible ? dp(16) : 0;
int padding = visible ? dp(slowModeButton.isPremiumMode ? 26 : 16) : 0;
if (messageEditText != null && messageEditText.getPaddingRight() != padding) {
messageEditText.setPadding(0, dp(11), padding, dp(12));
}
@ -7417,7 +7542,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
private int lastRecordState;
protected void updateRecordInterface(int recordState) {
protected void updateRecordInterface(int recordState, boolean animated) {
if (moveToSendStateRunnable != null) {
AndroidUtilities.cancelRunOnUIThread(moveToSendStateRunnable);
moveToSendStateRunnable = null;
@ -7437,6 +7562,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
if (controlsView != null) {
controlsView.periodDrawable.setValue(1, false, false);
}
MediaDataController.getInstance(currentAccount).toggleDraftVoiceOnce(dialog_id, parentFragment != null && parentFragment.isTopic ? parentFragment.getTopicId() : 0, voiceOnce);
millisecondsRecorded = 0;
}
@ -7702,10 +7828,11 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
isRecordingStateChanged();
runningAnimationAudio.setDuration(150);
} else if (recordState == RECORD_STATE_PREPARING) {
createRecordAudioPanel();
createRecordCircle();
if (slideText != null) {
slideText.setEnabled(false);
}
createRecordAudioPanel();
if (isInVideoMode()) {
if (recordedAudioBackground != null) {
recordedAudioBackground.setVisibility(GONE);
@ -7775,29 +7902,6 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
recordDeleteImageView.stopAnimation();
}
ValueAnimator transformToSeekbar = ValueAnimator.ofFloat(0, 1f);
transformToSeekbar.addUpdateListener(animation -> {
float value = (float) animation.getAnimatedValue();
recordCircle.setTransformToSeekbar(value);
if (!isInVideoMode()) {
seekBarWaveform.setWaveScaling(recordCircle.getTransformToSeekbarProgressStep3());
recordedAudioTimeTextView.setAlpha(recordCircle.getTransformToSeekbarProgressStep3());
recordedAudioPlayButton.setAlpha(recordCircle.getTransformToSeekbarProgressStep3());
recordedAudioPlayButton.setScaleX(recordCircle.getTransformToSeekbarProgressStep3());
recordedAudioPlayButton.setScaleY(recordCircle.getTransformToSeekbarProgressStep3());
recordedAudioSeekBar.setAlpha(recordCircle.getTransformToSeekbarProgressStep3());
recordedAudioSeekBar.invalidate();
}
isRecordingStateChanged();
});
transformToSeekbar.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
recordCircle.setTransformToSeekbar(1);
isRecordingStateChanged();
}
});
ViewGroup.LayoutParams oldLayoutParams = null;
ViewGroup parent = null;
if (!isInVideoMode() && !shouldDrawRecordedAudioPanelInParent) {
@ -7814,108 +7918,200 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
isRecordingStateChanged();
if (recordDeleteImageView != null) {
recordDeleteImageView.setAlpha(0f);
recordDeleteImageView.setScaleX(0f);
recordDeleteImageView.setScaleY(0f);
}
AnimatorSet videoAdditionalAnimations = new AnimatorSet();
if (!animated) {
createRecordPanel();
AnimatorSet iconsAnimator = new AnimatorSet();
recordCircleScale.set(recordCircle, 1f);
recordCircle.setTransformToSeekbar(1f);
if (!isInVideoMode()) {
if (transformToSeekbar != 0 && recordedAudioBackground != null) {
float step1Time = 0.38f;
float step2Time = 0.25f;
float step3Time = 1f - step1Time - step2Time;
iconsAnimator.playTogether(
ObjectAnimator.ofFloat(recordDot, View.SCALE_Y, 0),
ObjectAnimator.ofFloat(recordDot, View.SCALE_X, 0),
ObjectAnimator.ofFloat(recordTimerView, View.ALPHA, 0.0f),
ObjectAnimator.ofFloat(recordTimerView, View.TRANSLATION_X, -dp(20)),
ObjectAnimator.ofFloat(slideText, View.ALPHA, 0),
ObjectAnimator.ofFloat(recordDeleteImageView, View.ALPHA, 1),
ObjectAnimator.ofFloat(recordDeleteImageView, View.SCALE_Y, 1f),
ObjectAnimator.ofFloat(recordDeleteImageView, View.SCALE_X, 1f),
ObjectAnimator.ofFloat(emojiButton, EMOJI_BUTTON_SCALE, 0),
ObjectAnimator.ofFloat(emojiButton, EMOJI_BUTTON_ALPHA, 0),
ObjectAnimator.ofFloat(messageEditText, View.ALPHA, 0)
);
if (audioVideoSendButton != null) {
iconsAnimator.playTogether(
ObjectAnimator.ofFloat(audioVideoSendButton, View.ALPHA, 1),
ObjectAnimator.ofFloat(audioVideoSendButton, View.SCALE_X, 1),
ObjectAnimator.ofFloat(audioVideoSendButton, View.SCALE_Y, 1)
);
audioVideoSendButton.setState(isInVideoMode() ? ChatActivityEnterViewAnimatedIconView.State.VIDEO : ChatActivityEnterViewAnimatedIconView.State.VOICE, true);
}
float progressToSeekbarStep3 = Math.max(0, (transformToSeekbar - step1Time - step2Time) / step3Time);
progressToSeekbarStep3 = CubicBezierInterpolator.EASE_BOTH.getInterpolation(progressToSeekbarStep3);
if (botCommandsMenuButton != null) {
iconsAnimator.playTogether(
ObjectAnimator.ofFloat(botCommandsMenuButton, View.ALPHA, 0),
ObjectAnimator.ofFloat(botCommandsMenuButton, View.SCALE_X, 0),
ObjectAnimator.ofFloat(botCommandsMenuButton, View.SCALE_Y, 0)
);
}
iconsAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (audioVideoSendButton != null) {
audioVideoSendButton.setScaleX(1f);
audioVideoSendButton.setScaleY(1f);
seekBarWaveform.setWaveScaling(progressToSeekbarStep3);
recordedAudioTimeTextView.setAlpha(progressToSeekbarStep3);
recordedAudioPlayButton.setAlpha(progressToSeekbarStep3);
recordedAudioPlayButton.setScaleX(progressToSeekbarStep3);
recordedAudioPlayButton.setScaleY(progressToSeekbarStep3);
recordedAudioSeekBar.setAlpha(progressToSeekbarStep3);
recordedAudioSeekBar.invalidate();
}
}
});
iconsAnimator.setDuration(150);
iconsAnimator.setStartDelay(150);
recordDot.setScaleY(0);
recordDot.setScaleX(0);
recordTimerView.setAlpha(0f);
recordTimerView.setTranslationX(-dp(20));
slideText.setAlpha(0);
recordDeleteImageView.setAlpha(1f);
recordDeleteImageView.setScaleY(1f);
recordDeleteImageView.setScaleX(1f);
EMOJI_BUTTON_SCALE.set(emojiButton, 0f);
EMOJI_BUTTON_ALPHA.set(emojiButton, 0f);
messageEditText.setAlpha(0f);
AnimatorSet videoAdditionalAnimations = new AnimatorSet();
if (isInVideoMode()) {
recordedAudioTimeTextView.setAlpha(0);
videoTimelineView.setAlpha(0);
videoAdditionalAnimations.playTogether(
if (audioVideoSendButton != null) {
audioVideoSendButton.setState(isInVideoMode() ? ChatActivityEnterViewAnimatedIconView.State.VIDEO : ChatActivityEnterViewAnimatedIconView.State.VOICE, animated);
audioVideoSendButton.setAlpha(1f);
audioVideoSendButton.setScaleX(1f);
audioVideoSendButton.setScaleY(1f);
}
if (botCommandsMenuButton != null) {
botCommandsMenuButton.setAlpha(0f);
botCommandsMenuButton.setScaleX(0f);
botCommandsMenuButton.setScaleY(0f);
}
if (isInVideoMode()) {
recordedAudioTimeTextView.setAlpha(1f);
videoTimelineView.setAlpha(1f);
}
ViewGroup finalParent = parent;
ViewGroup.LayoutParams finalOldLayoutParams = oldLayoutParams;
if (finalParent != null) {
sizeNotifierLayout.removeView(recordedAudioPanel);
finalParent.addView(recordedAudioPanel, finalOldLayoutParams);
}
recordedAudioPanel.setAlpha(1.0f);
recordedAudioBackground.setAlpha(1f);
recordedAudioTimeTextView.setAlpha(1f);
recordedAudioPlayButton.setAlpha(1f);
recordedAudioPlayButton.setScaleY(1f);
recordedAudioPlayButton.setScaleX(1f);
recordedAudioSeekBar.setAlpha(1f);
emojiButtonAlpha = emojiButtonScale = 0f;
updateEmojiButtonParams();
isRecordingStateChanged();
} else {
ValueAnimator transformToSeekbar = ValueAnimator.ofFloat(0, 1f);
transformToSeekbar.addUpdateListener(animation -> {
float value = (float) animation.getAnimatedValue();
recordCircle.setTransformToSeekbar(value);
if (!isInVideoMode()) {
seekBarWaveform.setWaveScaling(recordCircle.getTransformToSeekbarProgressStep3());
recordedAudioTimeTextView.setAlpha(recordCircle.getTransformToSeekbarProgressStep3());
recordedAudioPlayButton.setAlpha(recordCircle.getTransformToSeekbarProgressStep3());
recordedAudioPlayButton.setScaleX(recordCircle.getTransformToSeekbarProgressStep3());
recordedAudioPlayButton.setScaleY(recordCircle.getTransformToSeekbarProgressStep3());
recordedAudioSeekBar.setAlpha(recordCircle.getTransformToSeekbarProgressStep3());
recordedAudioSeekBar.invalidate();
}
isRecordingStateChanged();
});
transformToSeekbar.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
recordCircle.setTransformToSeekbar(1);
isRecordingStateChanged();
}
});
transformToSeekbar.setDuration(isInVideoMode() ? 490 : 580);
AnimatorSet iconsAnimator = new AnimatorSet();
iconsAnimator.playTogether(
ObjectAnimator.ofFloat(recordDot, View.SCALE_Y, 0),
ObjectAnimator.ofFloat(recordDot, View.SCALE_X, 0),
ObjectAnimator.ofFloat(recordTimerView, View.ALPHA, 0.0f),
ObjectAnimator.ofFloat(recordTimerView, View.TRANSLATION_X, -dp(20)),
ObjectAnimator.ofFloat(slideText, View.ALPHA, 0),
ObjectAnimator.ofFloat(recordDeleteImageView, View.ALPHA, 1),
ObjectAnimator.ofFloat(recordDeleteImageView, View.SCALE_Y, 1f),
ObjectAnimator.ofFloat(recordDeleteImageView, View.SCALE_X, 1f),
ObjectAnimator.ofFloat(emojiButton, EMOJI_BUTTON_SCALE, 0),
ObjectAnimator.ofFloat(emojiButton, EMOJI_BUTTON_ALPHA, 0),
ObjectAnimator.ofFloat(messageEditText, View.ALPHA, 0)
);
if (recordDeleteImageView != null) {
recordDeleteImageView.setAlpha(0f);
recordDeleteImageView.setScaleX(0f);
recordDeleteImageView.setScaleY(0f);
}
if (audioVideoSendButton != null) {
iconsAnimator.playTogether(
ObjectAnimator.ofFloat(audioVideoSendButton, View.ALPHA, 1),
ObjectAnimator.ofFloat(audioVideoSendButton, View.SCALE_X, 1),
ObjectAnimator.ofFloat(audioVideoSendButton, View.SCALE_Y, 1)
);
audioVideoSendButton.setState(isInVideoMode() ? ChatActivityEnterViewAnimatedIconView.State.VIDEO : ChatActivityEnterViewAnimatedIconView.State.VOICE, true);
}
if (botCommandsMenuButton != null) {
iconsAnimator.playTogether(
ObjectAnimator.ofFloat(botCommandsMenuButton, View.ALPHA, 0),
ObjectAnimator.ofFloat(botCommandsMenuButton, View.SCALE_X, 0),
ObjectAnimator.ofFloat(botCommandsMenuButton, View.SCALE_Y, 0)
);
}
iconsAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (audioVideoSendButton != null) {
audioVideoSendButton.setScaleX(1f);
audioVideoSendButton.setScaleY(1f);
}
}
});
iconsAnimator.setDuration(150);
iconsAnimator.setStartDelay(150);
if (isInVideoMode()) {
recordedAudioTimeTextView.setAlpha(0);
videoTimelineView.setAlpha(0);
videoAdditionalAnimations.playTogether(
ObjectAnimator.ofFloat(recordedAudioTimeTextView, View.ALPHA, 1),
ObjectAnimator.ofFloat(videoTimelineView, View.ALPHA, 1)
);
videoAdditionalAnimations.setDuration(150);
videoAdditionalAnimations.setStartDelay(430);
}
transformToSeekbar.setDuration(isInVideoMode() ? 490 : 580);
runningAnimationAudio.playTogether(
iconsAnimator,
transformToSeekbar,
videoAdditionalAnimations
);
ViewGroup finalParent = parent;
ViewGroup.LayoutParams finalOldLayoutParams = oldLayoutParams;
runningAnimationAudio.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (finalParent != null) {
sizeNotifierLayout.removeView(recordedAudioPanel);
finalParent.addView(recordedAudioPanel, finalOldLayoutParams);
}
recordedAudioPanel.setAlpha(1.0f);
recordedAudioBackground.setAlpha(1f);
recordedAudioTimeTextView.setAlpha(1f);
recordedAudioPlayButton.setAlpha(1f);
recordedAudioPlayButton.setScaleY(1f);
recordedAudioPlayButton.setScaleX(1f);
recordedAudioSeekBar.setAlpha(1f);
emojiButtonAlpha = emojiButtonScale = 0f;
updateEmojiButtonParams();
if (botCommandsMenuButton != null) {
botCommandsMenuButton.setAlpha(0f);
botCommandsMenuButton.setScaleX(0f);
botCommandsMenuButton.setScaleY(0f);
}
if (controlsView != null && onceVisible && !voiceOnce && (MessagesController.getGlobalMainSettings().getInt("voiceoncehint", 0) < 3)) {
controlsView.showHintView();
}
);
videoAdditionalAnimations.setDuration(150);
videoAdditionalAnimations.setStartDelay(430);
}
});
runningAnimationAudio.playTogether(
iconsAnimator,
transformToSeekbar,
videoAdditionalAnimations
);
ViewGroup finalParent = parent;
ViewGroup.LayoutParams finalOldLayoutParams = oldLayoutParams;
runningAnimationAudio.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (finalParent != null) {
sizeNotifierLayout.removeView(recordedAudioPanel);
finalParent.addView(recordedAudioPanel, finalOldLayoutParams);
}
recordedAudioPanel.setAlpha(1.0f);
recordedAudioBackground.setAlpha(1f);
recordedAudioTimeTextView.setAlpha(1f);
recordedAudioPlayButton.setAlpha(1f);
recordedAudioPlayButton.setScaleY(1f);
recordedAudioPlayButton.setScaleX(1f);
recordedAudioSeekBar.setAlpha(1f);
emojiButtonAlpha = emojiButtonScale = 0f;
updateEmojiButtonParams();
if (botCommandsMenuButton != null) {
botCommandsMenuButton.setAlpha(0f);
botCommandsMenuButton.setScaleX(0f);
botCommandsMenuButton.setScaleY(0f);
}
if (controlsView != null && onceVisible && !voiceOnce && (MessagesController.getGlobalMainSettings().getInt("voiceoncehint", 0) < 3)) {
controlsView.showHintView();
}
}
});
}
} else if (recordState == RECORD_STATE_CANCEL || recordState == RECORD_STATE_CANCEL_BY_GESTURE) {
if (audioVideoSendButton != null) {
@ -8654,6 +8850,16 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
}
public void setVoiceDraft(MediaDataController.DraftVoice draft) {
if (draft == null) return;
voiceOnce = draft.once;
if (controlsView != null) {
controlsView.periodDrawable.setValue(1, voiceOnce, true);
}
TL_stories.StoryItem storyItem = delegate != null ? delegate.getReplyToStory() : null;
MediaController.getInstance().prepareResumedRecording(currentAccount, draft, dialog_id, replyingMessageObject, getThreadMessage(), storyItem, recordingGuid, true);
}
public void setSelection(int start) {
if (messageEditText == null) {
return;
@ -9873,6 +10079,9 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
return stickersTabOpen && !(!stickersExpanded && messageEditText != null && messageEditText.length() > 0) && emojiView.areThereAnyStickers() && !waitingForKeyboardOpen;
}
});
if (emojiView != null) {
emojiView.setStickersBanned(!sendPlainEnabled, !stickersEnabled, -dialog_id);
}
attachEmojiView();
checkChannelRights();
}
@ -10614,10 +10823,10 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
}
if (state != RECORD_STATE_PREPARING) {
updateRecordInterface(state);
updateRecordInterface(state, true);
}
} else {
updateRecordInterface(RECORD_STATE_CANCEL);
updateRecordInterface(RECORD_STATE_CANCEL, true);
}
}
} else if (id == NotificationCenter.recordStarted) {
@ -10632,7 +10841,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
if (!recordingAudioVideo) {
recordingAudioVideo = true;
updateRecordInterface(RECORD_STATE_ENTER);
updateRecordInterface(RECORD_STATE_ENTER, true);
} else if (recordCircle != null) {
recordCircle.showWaves(true, true);
}
@ -10651,7 +10860,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
videoToSendMessageObject = null;
checkSendButton(true);
recordingAudioVideo = true;
updateRecordInterface(RECORD_STATE_ENTER);
updateRecordInterface(RECORD_STATE_ENTER, true);
} else if (id == NotificationCenter.audioDidSent) {
int guid = (Integer) args[0];
if (guid != recordingGuid) {
@ -10673,11 +10882,12 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
videoTimelineView.setMinProgressDiff(1000.0f / videoToSendMessageObject.estimatedDuration);
isRecordingStateChanged();
}
updateRecordInterface(RECORD_STATE_PREPARING);
updateRecordInterface(RECORD_STATE_PREPARING, true);
checkSendButton(false);
} else {
audioToSend = (TLRPC.TL_document) args[1];
audioToSendPath = (String) args[2];
boolean fromDraft = args.length >= 4 && (boolean) args[3];
if (audioToSend != null) {
createRecordAudioPanel();
if (recordedAudioPanel == null) {
@ -10727,7 +10937,19 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
millisecondsRecorded = (long) (duration * 1000L);
recordedAudioTimeTextView.setText(AndroidUtilities.formatShortDuration((int) (duration)));
checkSendButton(false);
updateRecordInterface(RECORD_STATE_PREPARING);
if (fromDraft) {
createRecordCircle();
createRecordPanel();
createRecordAudioPanel();
recordInterfaceState = 1;
recordCircle.resetLockTranslation(false);
recordControlsCircleScale.set(recordCircle, 1f);
if (controlsView != null) {
controlsView.setVisibility(VISIBLE);
controlsView.setAlpha(1f);
}
}
updateRecordInterface(RECORD_STATE_PREPARING, !fromDraft);
} else {
if (delegate != null) {
delegate.onMessageSend(null, true, 0);
@ -10773,7 +10995,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
long did = (Long) args[3];
if (did == dialog_id && info != null && info.slowmode_seconds != 0) {
TLRPC.Chat chat = accountInstance.getMessagesController().getChat(info.id);
if (chat != null && !ChatObject.hasAdminRights(chat)) {
if (chat != null && !ChatObject.hasAdminRights(chat) && !ChatObject.isIgnoredChatRestrictionsForBoosters(chat)) {
info.slowmode_next_send_date = ConnectionsManager.getInstance(currentAccount).getCurrentTime() + info.slowmode_seconds;
info.flags |= 262144;
setSlowModeTimer(info.slowmode_next_send_date);
@ -10786,7 +11008,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
} else if (id == NotificationCenter.audioRecordTooShort) {
audioToSend = null;
videoToSendMessageObject = null;
updateRecordInterface(RECORD_STATE_CANCEL_BY_TIME);
updateRecordInterface(RECORD_STATE_CANCEL_BY_TIME, true);
} else if (id == NotificationCenter.updateBotMenuButton) {
long botId = (long) args[0];
TLRPC.BotMenuButton botMenuButton = (TLRPC.BotMenuButton) args[1];
@ -10971,7 +11193,9 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
stickersExpansionProgress = 1;
setTranslationY(-(stickersExpandedHeight - origHeight));
emojiView.setTranslationY(-(stickersExpandedHeight - origHeight));
stickersArrow.setAnimationProgress(1);
if (stickersArrow != null) {
stickersArrow.setAnimationProgress(1);
}
}
} else {
if (stopAllHeavy) {
@ -11029,7 +11253,9 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
sizeNotifierLayout.requestLayout();
sizeNotifierLayout.setForeground(null);
sizeNotifierLayout.setWillNotDraw(false);
stickersArrow.setAnimationProgress(0);
if (stickersArrow != null) {
stickersArrow.setAnimationProgress(0);
}
}
}
if (expandStickersButton != null) {
@ -11203,7 +11429,8 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
videoToSendMessageObject = null;
millisecondsRecorded = 0;
recordingAudioVideo = false;
updateRecordInterface(RECORD_STATE_CANCEL);
MediaDataController.getInstance(currentAccount).pushDraftVoiceMessage(dialog_id, parentFragment != null && parentFragment.isTopic ? parentFragment.getTopicId() : 0, null);
updateRecordInterface(RECORD_STATE_CANCEL, true);
checkSendButton(true);
}

View file

@ -144,9 +144,16 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
public boolean destroyed;
public boolean allowEnterCaption;
private ChatAttachAlertDocumentLayout.DocumentSelectActivityDelegate documentsDelegate;
private long dialogId;
public long dialogId;
private boolean overrideBackgroundColor;
public TLRPC.Chat getChat() {
if (baseFragment instanceof ChatActivity) {
return ((ChatActivity) baseFragment).getCurrentChat();
} else {
return MessagesController.getInstance(currentAccount).getChat(-dialogId);
}
}
public void setCanOpenPreview(boolean canOpenPreview) {
this.canOpenPreview = canOpenPreview;
selectedArrowImageView.setVisibility(canOpenPreview && avatarPicker != 2 ? View.VISIBLE : View.GONE);
@ -2186,11 +2193,17 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
final Activity activity = lastFragment.getParentActivity();
int num = (Integer) view.getTag();
if (num == 1) {
if (!photosEnabled && !videosEnabled && checkCanRemoveRestrictionsByBoosts()) {
return;
}
if (!photosEnabled && !videosEnabled) {
showLayout(restrictedLayout = new ChatAttachRestrictedLayout(1, this, getContext(), resourcesProvider));
}
showLayout(photoLayout);
} else if (num == 3) {
if (!musicEnabled && checkCanRemoveRestrictionsByBoosts()) {
return;
}
if (Build.VERSION.SDK_INT >= 33) {
if (activity.checkSelfPermission(Manifest.permission.READ_MEDIA_AUDIO) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[]{Manifest.permission.READ_MEDIA_AUDIO}, BasePermissionsActivity.REQUEST_CODE_EXTERNAL_STORAGE);
@ -2202,6 +2215,9 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
}
openAudioLayout(true);
} else if (num == 4) {
if (!documentsEnabled && checkCanRemoveRestrictionsByBoosts()) {
return;
}
if (Build.VERSION.SDK_INT >= 33) {
if (activity.checkSelfPermission(Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED ||
activity.checkSelfPermission(Manifest.permission.READ_MEDIA_VIDEO) != PackageManager.PERMISSION_GRANTED) {
@ -2214,6 +2230,9 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
}
openDocumentsLayout(true);
} else if (num == 5) {
if (!plainTextEnabled && checkCanRemoveRestrictionsByBoosts()) {
return;
}
if (Build.VERSION.SDK_INT >= 23 && plainTextEnabled) {
if (getContext().checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
AndroidUtilities.findActivity(getContext()).requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, BasePermissionsActivity.REQUEST_CODE_ATTACH_CONTACT);
@ -2222,6 +2241,9 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
}
openContactsLayout();
} else if (num == 6) {
if (!plainTextEnabled && checkCanRemoveRestrictionsByBoosts()) {
return;
}
if (!AndroidUtilities.isMapsInstalled(baseFragment)) {
return;
}
@ -2236,6 +2258,9 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
showLayout(locationLayout);
}
} else if (num == 9) {
if (!pollsEnabled && checkCanRemoveRestrictionsByBoosts()) {
return;
}
if (!pollsEnabled) {
restrictedLayout = new ChatAttachRestrictedLayout(9, this, getContext(), resourcesProvider);
showLayout(restrictedLayout);
@ -3230,6 +3255,10 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
showLayout(contactsLayout);
}
public boolean checkCanRemoveRestrictionsByBoosts() {
return (baseFragment instanceof ChatActivity) && ((ChatActivity) baseFragment).checkCanRemoveRestrictionsByBoosts();
}
private void openAudioLayout(boolean show) {
if (!musicEnabled) {
if (show) {
@ -4119,9 +4148,20 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
shadow.setAlpha(1f);
shadow.setTranslationY(0);
if (baseFragment instanceof ChatActivity && avatarPicker != 2) {
TLRPC.Chat chat = ((ChatActivity) baseFragment).getCurrentChat();
TLRPC.User user = ((ChatActivity) baseFragment).getCurrentUser();
TLRPC.Chat chat = null;
TLRPC.User user = null;
if (avatarPicker != 2) {
if (baseFragment instanceof ChatActivity) {
chat = ((ChatActivity) baseFragment).getCurrentChat();
user = ((ChatActivity) baseFragment).getCurrentUser();
} else if (dialogId >= 0) {
user = MessagesController.getInstance(currentAccount).getUser(dialogId);
} else if (dialogId < 0) {
chat = MessagesController.getInstance(currentAccount).getChat(-dialogId);
}
}
if (baseFragment instanceof ChatActivity && avatarPicker != 2 || (chat != null || user != null)) {
if (chat != null) {
// mediaEnabled = ChatObject.canSendMedia(chat);
photosEnabled = ChatObject.canSendPhoto(chat);
@ -4133,12 +4173,9 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
} else {
pollsEnabled = user != null && user.bot;
}
} else {
if (allowEnterCaption) {
commentTextView.setVisibility(View.VISIBLE);
} else {
commentTextView.setVisibility(View.INVISIBLE);
}
}
if (!(baseFragment instanceof ChatActivity && avatarPicker != 2)) {
commentTextView.setVisibility(allowEnterCaption ? View.VISIBLE : View.INVISIBLE);
}
photoLayout.onInit(videosEnabled, photosEnabled, documentsEnabled);
commentTextView.hidePopup(true);
@ -4238,6 +4275,9 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
currentAttachLayout.onOpenAnimationEnd();
AndroidUtilities.makeAccessibilityAnnouncement(LocaleController.getString("AccDescrAttachButton", R.string.AccDescrAttachButton));
openTransitionFinished = true;
if (!videosEnabled && !photosEnabled) {
checkCanRemoveRestrictionsByBoosts();
}
}
@Override

View file

@ -82,6 +82,7 @@ import org.telegram.messenger.Utilities;
import org.telegram.messenger.VideoEditedInfo;
import org.telegram.messenger.camera.CameraController;
import org.telegram.messenger.camera.CameraSession;
import org.telegram.messenger.camera.CameraSessionWrapper;
import org.telegram.messenger.camera.CameraView;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBar;
@ -1032,7 +1033,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
return;
}
openPhotoViewer(null, false, false);
CameraController.getInstance().stopPreview(cameraView.getCameraSession());
CameraController.getInstance().stopPreview(cameraView.getCameraSessionObject());
});
zoomControlView = new ZoomControlView(context);
@ -1094,7 +1095,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
AndroidUtilities.runOnUIThread(videoRecordRunnable, 1000);
};
AndroidUtilities.lockOrientation(baseFragment.getParentActivity());
CameraController.getInstance().recordVideo(cameraView.getCameraSession(), outputFile, parentAlert.avatarPicker != 0, (thumbPath, duration) -> {
CameraController.getInstance().recordVideo(cameraView.getCameraSessionObject(), outputFile, parentAlert.avatarPicker != 0, (thumbPath, duration) -> {
if (outputFile == null || parentAlert.destroyed || cameraView == null) {
return;
}
@ -1151,7 +1152,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
final File cameraFile = AndroidUtilities.generatePicturePath(parentAlert.baseFragment instanceof ChatActivity && ((ChatActivity) parentAlert.baseFragment).isSecretChat(), null);
final boolean sameTakePictureOrientation = cameraView.getCameraSession().isSameTakePictureOrientation();
cameraView.getCameraSession().setFlipFront(parentAlert.baseFragment instanceof ChatActivity || parentAlert.avatarPicker == 2);
takingPhoto = CameraController.getInstance().takePicture(cameraFile, false, cameraView.getCameraSession(), (orientation) -> {
takingPhoto = CameraController.getInstance().takePicture(cameraFile, false, cameraView.getCameraSessionObject(), (orientation) -> {
takingPhoto = false;
if (cameraFile == null || parentAlert.destroyed) {
return;
@ -1484,11 +1485,17 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
private boolean checkSendMediaEnabled(MediaController.PhotoEntry photoEntry) {
if (!videoEnabled && photoEntry.isVideo) {
if (parentAlert.checkCanRemoveRestrictionsByBoosts()) {
return true;
}
BulletinFactory.of(parentAlert.sizeNotifierFrameLayout, resourcesProvider).createErrorBulletin(
LocaleController.getString("GlobalAttachVideoRestricted", R.string.GlobalAttachVideoRestricted)
).show();
return true;
} else if (!photoEnabled && !photoEntry.isVideo) {
if (parentAlert.checkCanRemoveRestrictionsByBoosts()) {
return true;
}
BulletinFactory.of(parentAlert.sizeNotifierFrameLayout, resourcesProvider).createErrorBulletin(
LocaleController.getString("GlobalAttachPhotoRestricted", R.string.GlobalAttachPhotoRestricted)
).show();
@ -1744,7 +1751,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
zoomControlView.setZoom(0.0f, false);
cameraZoom = 0.0f;
cameraView.setZoom(0.0f);
CameraController.getInstance().startPreview(cameraView.getCameraSession());
CameraController.getInstance().startPreview(cameraView.getCameraSessionObject());
}
return;
}
@ -2288,6 +2295,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
public void onCameraInit() {
String current = cameraView.getCameraSession().getCurrentFlashMode();
String next = cameraView.getCameraSession().getNextFlashMode();
if (current == null || next == null) return;
if (current.equals(next)) {
for (int a = 0; a < 2; a++) {
flashModeButton[a].setVisibility(View.INVISIBLE);
@ -3002,9 +3010,8 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
@Override
void onMenuItemClick(int id) {
if (id == group || id == compress) {
if (parentAlert.maxSelectedPhotos > 0 && selectedPhotosOrder.size() > 1 && parentAlert.baseFragment instanceof ChatActivity) {
ChatActivity chatActivity = (ChatActivity) parentAlert.baseFragment;
TLRPC.Chat chat = chatActivity.getCurrentChat();
if (parentAlert.maxSelectedPhotos > 0 && selectedPhotosOrder.size() > 1) {
TLRPC.Chat chat = parentAlert.getChat();
if (chat != null && !ChatObject.hasAdminRights(chat) && chat.slowmode_enabled) {
AlertsCreator.createSimpleAlert(getContext(), LocaleController.getString("Slowmode", R.string.Slowmode), LocaleController.getString("SlowmodeSendError", R.string.SlowmodeSendError), resourcesProvider).show();
return;
@ -3325,13 +3332,13 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
cameraIcon.setAlpha(mediaEnabled ? 1.0f : 0.2f);
cameraIcon.setEnabled(mediaEnabled);
}
if (parentAlert.baseFragment instanceof ChatActivity && parentAlert.avatarPicker == 0) {
if ((parentAlert.baseFragment instanceof ChatActivity || parentAlert.getChat() != null) && parentAlert.avatarPicker == 0) {
galleryAlbumEntry = MediaController.allMediaAlbumEntry;
if (mediaEnabled) {
progressView.setText(LocaleController.getString("NoPhotos", R.string.NoPhotos));
progressView.setLottie(0, 0, 0);
} else {
TLRPC.Chat chat = ((ChatActivity) parentAlert.baseFragment).getCurrentChat();
TLRPC.Chat chat = parentAlert.getChat();
progressView.setLottie(R.raw.media_forbidden, 150, 150);
if (ChatObject.isActionBannedByDefault(chat, ChatObject.ACTION_SEND_MEDIA)) {
progressView.setText(LocaleController.getString("GlobalAttachMediaRestricted", R.string.GlobalAttachMediaRestricted));
@ -3538,10 +3545,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
private void pauseCameraPreview() {
try {
if (cameraView != null) {
CameraSession cameraSession = cameraView.getCameraSession();
if (cameraSession != null) {
CameraController.getInstance().stopPreview(cameraSession);
}
CameraController.getInstance().stopPreview(cameraView.getCameraSessionObject());
}
} catch (Exception e) {
FileLog.e(e);
@ -3552,10 +3556,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
try {
checkCamera(false);
if (cameraView != null) {
CameraSession cameraSession = cameraView.getCameraSession();
if (cameraSession != null) {
CameraController.getInstance().startPreview(cameraSession);
}
CameraController.getInstance().startPreview(cameraView.getCameraSessionObject());
}
} catch (Exception e) {
FileLog.e(e);

View file

@ -15,6 +15,7 @@ import androidx.recyclerview.widget.RecyclerView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.R;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBar;
@ -39,7 +40,7 @@ public class ChatAttachRestrictedLayout extends ChatAttachAlert.AttachAlertLayou
addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
progressView.setLottie(R.raw.media_forbidden, 150, 150);
TLRPC.Chat chat = ((ChatActivity) parentAlert.baseFragment).getCurrentChat();
TLRPC.Chat chat = parentAlert.getChat();
if (id == 1) {
progressView.setText(ChatObject.getRestrictedErrorText(chat, ChatObject.ACTION_SEND_MEDIA));
} else if (id == 3) {

View file

@ -316,14 +316,6 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent
}
emojiStatusDrawable = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(titleTextView, AndroidUtilities.dp(24));
setOnLongClickListener(v -> {
if (canSearch()) {
openSearch();
return true;
}
return false;
});
}
private ButtonBounce bounce = new ButtonBounce(this);

View file

@ -12,6 +12,7 @@ import android.graphics.PorterDuffColorFilter;
import android.text.Layout;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
@ -75,6 +76,7 @@ public class ChatGreetingsView extends LinearLayout {
descriptionView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
descriptionView.setGravity(Gravity.CENTER_HORIZONTAL);
stickerToSendView = new BackupImageView(context);
ScaleStateListAnimator.apply(stickerToSendView);
updateLayout();
updateColors();

View file

@ -934,16 +934,7 @@ public class ChatThemeBottomSheet extends BottomSheet implements NotificationCen
limitReachedBottomSheet.setDialogId(chatActivity.getDialogId());
limitReachedBottomSheet.showStatisticButtonInLink(() -> {
TLRPC.Chat chat = chatActivity.getMessagesController().getChat(-chatActivity.getDialogId());
Bundle args = new Bundle();
args.putLong("chat_id", -chatActivity.getDialogId());
args.putBoolean("is_megagroup", chat.megagroup);
args.putBoolean("start_from_boosts", true);
TLRPC.ChatFull chatInfo = chatActivity.getMessagesController().getChatFull(-chatActivity.getDialogId());
if (chatInfo == null || !chatInfo.can_view_stats) {
args.putBoolean("only_boosts", true);
};
StatisticActivity fragment = new StatisticActivity(args);
showAsSheet(fragment);
showAsSheet(StatisticActivity.create(chat));
});
limitReachedBottomSheet.show();
});

View file

@ -307,7 +307,7 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not
}
} else if (!isPopupShowing()) {
showPopup(1);
emojiView.onOpen(editText.length() > 0);
emojiView.onOpen(editText.length() > 0, false);
editText.requestFocus();
} else {
openKeyboardInternal();

View file

@ -500,6 +500,7 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView {
} else {
currentPackButton.setAnimatedEmojiDocument(thumbDocument);
}
currentPackButton.id = newPack.forGroup ? (long) "forGroup".hashCode() : null;
currentPackButton.updateSelect(selected == i, false);
if (currentType == SelectAnimatedEmojiDialog.TYPE_AVATAR_CONSTRUCTOR || currentType == SelectAnimatedEmojiDialog.TYPE_CHAT_REACTIONS || currentType == SelectAnimatedEmojiDialog.TYPE_SET_REPLY_ICON || currentType == SelectAnimatedEmojiDialog.TYPE_SET_REPLY_ICON_BOTTOM) {
currentPackButton.setLock(null, false);

View file

@ -34,7 +34,6 @@ import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
@ -49,29 +48,24 @@ import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo;
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.PopupWindow;
import android.widget.TextView;
import androidx.annotation.IntDef;
@ -134,14 +128,12 @@ import org.telegram.ui.Cells.StickerSetNameCell;
import org.telegram.ui.ChatActivity;
import org.telegram.ui.Components.ListView.RecyclerListViewWithOverlayDraw;
import org.telegram.ui.Components.Premium.PremiumButtonView;
import org.telegram.ui.Components.Premium.PremiumGradient;
import org.telegram.ui.ContentPreviewViewer;
import org.telegram.ui.SelectAnimatedEmojiDialog;
import org.telegram.ui.StickersActivity;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -149,7 +141,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
@ -1282,6 +1273,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
long documentId = imageViewEmoji.getSpan().documentId;
TLRPC.Document document = imageViewEmoji.getSpan().document;
String emoticon = null;
boolean isGroupEmojis = imageViewEmoji.pack != null && imageViewEmoji.pack.forGroup;
if (document == null) {
for (int i = 0; i < emojipacksProcessed.size(); ++i) {
EmojiPack pack = emojipacksProcessed.get(i);
@ -1299,7 +1291,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
if (emoticon == null && document != null) {
emoticon = MessageObject.findAnimatedEmojiEmoticon(document);
}
if (!MessageObject.isFreeEmoji(document) && !UserConfig.getInstance(currentAccount).isPremium() && !(delegate != null && delegate.isUserSelf()) && !allowEmojisForNonPremium) {
if (!MessageObject.isFreeEmoji(document) && !UserConfig.getInstance(currentAccount).isPremium() && !(delegate != null && delegate.isUserSelf()) && !allowEmojisForNonPremium && !isGroupEmojis) {
showBottomTab(false, true);
BulletinFactory factory = fragment != null ? BulletinFactory.of(fragment) : BulletinFactory.of(bulletinContainer, resourcesProvider);
if (premiumBulletin || fragment == null) {
@ -3610,6 +3602,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
RLottieImageView lockView;
SimpleTextView headerView;
TextView markView;
FrameLayout buttonsView;
TextView addButtonView;
@ -3638,8 +3631,17 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
openEmojiPackAlert(this.pack.set);
}
});
markView = new TextView(context);
markView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 11);
markView.setTextColor(getThemedColor(Theme.key_chat_emojiPanelStickerSetName));
markView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
markView.setBackground(Theme.createRoundRectDrawable(dp(8), Theme.multAlpha(getThemedColor(Theme.key_chat_emojiPanelIcon), .12f)));
markView.setPadding(dp(6), dp(1.5f), dp(6), dp(1.5f));
markView.setText(LocaleController.getString(R.string.GroupEmoji));
headerView.setEllipsizeByGradient(true);
addView(headerView, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.START, 15, 15, 0, 0));
addView(markView, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START, 15, 10, 0, 0));
buttonsView = new FrameLayout(context);
buttonsView.setPadding(AndroidUtilities.dp(11), AndroidUtilities.dp(11), AndroidUtilities.dp(11), 0);
@ -3778,7 +3780,15 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
headerView.setRightPadding(buttonsView.getWidth() + AndroidUtilities.dp(11));
int padding = buttonsView.getWidth() + AndroidUtilities.dp(11) + (markView.getVisibility() == View.VISIBLE ? markView.getMeasuredWidth() : 0);
headerView.setRightPadding(padding);
if (markView.getVisibility() == View.VISIBLE) {
markView.setTranslationX(headerView.getTextWidth() + dp(4));
int max = headerView.getMaxTextWidth() - padding + dp(4);
if (markView.getTranslationX() > max) {
markView.setTranslationX(max);
}
}
}
public void setStickerSet(EmojiPack pack, boolean divider) {
@ -3789,6 +3799,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
this.pack = pack;
this.divider = divider;
headerView.setText(pack.set.title);
markView.setVisibility(pack.forGroup ? View.VISIBLE : View.GONE);
if (pack.installed && !pack.set.official) {
premiumButtonView.setButton(LocaleController.getString("Restore", R.string.Restore), e -> openPremiumAnimatedEmojiFeature());
@ -5632,7 +5643,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
forseMultiwindowLayout = value;
}
public void onOpen(boolean forceEmoji) {
public void onOpen(boolean forceEmoji, boolean groupEmojiHintWasVisible) {
if (currentPage != 0 && stickersBanned) {
currentPage = 0;
}
@ -5645,6 +5656,21 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
if (pager.getCurrentItem() != 0) {
pager.setCurrentItem(0, !forceEmoji);
}
if (groupEmojiHintWasVisible) {
AndroidUtilities.runOnUIThread(() -> {
ArrayList<EmojiPack> packs = getEmojipacks();
for (int i = 0; i < packs.size(); i++) {
EmojiPack pack = packs.get(i);
if (pack.forGroup) {
int pos = emojiAdapter.sectionToPosition.get(i + EmojiData.dataColored.length);
emojiGridView.stopScroll();
updateEmojiTabsPosition(pos);
scrollEmojisToPosition(pos, dp(-9));
checkEmojiTabY(null, 0);
}
}
}, 350);
}
} else if (currentPage == 1) {
showBackspaceButton(false, false);
showStickerSettingsButton(shouldDrawBackground, false);
@ -5684,6 +5710,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
super.onAttachedToWindow();
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded);
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.newEmojiSuggestionsAvailable);
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.groupPackUpdated);
if (stickersGridAdapter != null) {
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.stickersDidLoad);
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.recentDocumentsDidLoad);
@ -5734,6 +5761,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded);
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.newEmojiSuggestionsAvailable);
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.stickersDidLoad);
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.groupPackUpdated);
if (stickersGridAdapter != null) {
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.recentDocumentsDidLoad);
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.featuredStickersDidLoad);
@ -5851,6 +5879,9 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
if (show) {
if (!ChatObject.hasAdminRights(chat) && chat.default_banned_rights != null && (chat.default_banned_rights.send_stickers || (emoji && chat.default_banned_rights.send_plain))) {
if (fragment instanceof ChatActivity && ((ChatActivity) fragment).checkCanRemoveRestrictionsByBoosts()) {
return;
}
if (emoji) {
mediaBanTooltip.setText(LocaleController.getString("GlobalAttachEmojiRestricted", R.string.GlobalAttachEmojiRestricted));
} else if (gif) {
@ -5980,6 +6011,12 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
emojiAdapter.notifyDataSetChanged(false);
}
}
} else if (id == NotificationCenter.groupPackUpdated) {
long chatId = (long) args[0];
boolean isEmoji = (boolean) args[1];
if (info != null && info.id == chatId && isEmoji) {
emojiAdapter.notifyDataSetChanged(true);
}
} else if (id == NotificationCenter.recentDocumentsDidLoad) {
boolean isGif = (Boolean) args[0];
int type = (Integer) args[1];
@ -6671,6 +6708,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
public boolean installed;
public boolean featured;
public boolean expanded;
public boolean forGroup;
public int resId;
}
@ -6986,6 +7024,16 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
return VIEW_TYPE_EMOJI;
}
private void removeGroupEmojiPackFromInstalled(TLRPC.StickerSet pack, ArrayList<TLRPC.TL_messages_stickerSet> installedEmojipacks) {
for (int i = 0; i < installedEmojipacks.size(); i++) {
TLRPC.TL_messages_stickerSet set = installedEmojipacks.get(i);
if (set != null && set.set.id == pack.id) {
installedEmojipacks.remove(i);
break;
}
}
}
public void processEmoji(boolean updateEmojipacks) {
emojipacksProcessed.clear();
if (!allowAnimatedEmoji) {
@ -6999,6 +7047,24 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
ArrayList<TLRPC.TL_messages_stickerSet> installedEmojipacks = frozenEmojiPacks;
boolean isPremium = UserConfig.getInstance(currentAccount).isPremium() || allowEmojisForNonPremium;
int index = 0;
if (info != null && info.emojiset != null) {
TLRPC.TL_messages_stickerSet stickerSet = mediaDataController.getGroupStickerSetById(info.emojiset);
if (stickerSet != null) {
EmojiPack pack = new EmojiPack();
pack.index = index++;
pack.set = info.emojiset;
pack.documents = new ArrayList<>(stickerSet.documents);
pack.free = true;
pack.installed = true;
pack.featured = false;
pack.expanded = true;
pack.forGroup = true;
emojipacksProcessed.add(pack);
removeGroupEmojiPackFromInstalled(pack.set, installedEmojipacks);
}
}
if (!isPremium) {
for (int i = 0; i < installedEmojipacks.size(); ++i) {
TLRPC.TL_messages_stickerSet set = installedEmojipacks.get(i);
@ -7224,7 +7290,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
if (!pack.expanded && pack.documents.size() > maxlen) {
count--;
}
rowHashCodes.add(Objects.hash(pack.featured ? 56345 : -495231, (pack.set == null ? b : pack.set.id)));
rowHashCodes.add(Objects.hash(pack.featured ? 56345 : -495231, (pack.set == null ? b : pack.set.id), pack.forGroup));
for (int i = 1; i < count; ++i) {
rowHashCodes.add(Objects.hash(pack.featured ? 3442 : -9964, pack.documents.get(i - 1).id));
}
@ -7234,11 +7300,6 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
rowHashCodes.add(Objects.hash(pack.featured ? -65174 : 92242, pack.set.id));
itemCount++;
}
// if (!pack.installed) {
// positionToUnlock.put(itemCount, b);
// itemCount++;
// rowHashCodes.add(Objects.hash(7, pack.set.id));
// }
}
}
}

View file

@ -89,6 +89,7 @@ import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.messenger.VideoEditedInfo;
import org.telegram.messenger.camera.Camera2Session;
import org.telegram.messenger.camera.CameraController;
import org.telegram.messenger.camera.CameraInfo;
import org.telegram.messenger.camera.CameraSession;
@ -99,6 +100,7 @@ import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.voip.CellFlickerDrawable;
import org.telegram.ui.Stories.recorder.DualCameraView;
import org.telegram.ui.Stories.recorder.StoryEntry;
import java.io.File;
@ -168,14 +170,26 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
private boolean cancelled;
private CameraGLThread cameraThread;
private volatile int previewWidth, previewHeight;
private Size previewSize;
private Size pictureSize;
private Size aspectRatio = SharedConfig.roundCamera16to9 ? new Size(16, 9) : new Size(4, 3);
private TextureView textureView;
private BackupImageView textureOverlayView;
private final boolean useCamera2 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && SharedConfig.useCamera2;
private final boolean supportHotSwap = useCamera2 && DualCameraView.dualAvailableStatic(ApplicationLoader.applicationContext);
private CameraSession cameraSession;
private Camera2Session camera2Session;
private boolean needDrawFlickerStub;
private boolean isCameraSessionInitiated() {
if (useCamera2) {
return camera2Session != null && camera2Session.isInitiated();
} else {
return cameraSession != null && cameraSession.isInitied();
}
}
private float panTranslationY;
private float animationTranslationY;
@ -330,7 +344,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
switchCameraButton.setContentDescription(LocaleController.getString("AccDescrSwitchCamera", R.string.AccDescrSwitchCamera));
addView(switchCameraButton, LayoutHelper.createFrame(62, 62, Gravity.LEFT | Gravity.BOTTOM, 8, 0, 0, 0));
switchCameraButton.setOnClickListener(v -> {
if (!cameraReady || cameraSession == null || !cameraSession.isInitied() || cameraThread == null) {
if (!cameraReady || !isCameraSessionInitiated() || cameraThread == null) {
return;
}
switchCamera();
@ -487,10 +501,17 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
}
}
public void destroy(boolean async, final Runnable beforeDestroyRunnable) {
if (cameraSession != null) {
cameraSession.destroy();
CameraController.getInstance().close(cameraSession, !async ? new CountDownLatch(1) : null, beforeDestroyRunnable);
public void destroy(boolean async) {
if (useCamera2) {
if (camera2Session != null) {
camera2Session.destroy(async);
camera2Session = null;
}
} else {
if (cameraSession != null) {
cameraSession.destroy();
CameraController.getInstance().close(cameraSession, !async ? new CountDownLatch(1) : null, null);
}
}
}
@ -666,6 +687,13 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
FileLog.d("InstantCamera show round camera " + cameraFile.getAbsolutePath());
}
if (useCamera2) {
camera2Session = Camera2Session.create(true, isFrontface, AndroidUtilities.roundPlayingMessageSize, AndroidUtilities.roundPlayingMessageSize);
if (camera2Session == null) return;
camera2Session.setRecordingVideo(true);
previewWidth = camera2Session.getPreviewWidth();
previewHeight = camera2Session.getPreviewHeight();
}
textureView = new TextureView(getContext());
textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
@ -699,8 +727,14 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
cameraThread.shutdown(0, 0);
cameraThread = null;
}
if (cameraSession != null) {
CameraController.getInstance().close(cameraSession, null, null);
if (useCamera2) {
if (camera2Session != null) {
camera2Session.destroy(false);
}
} else {
if (cameraSession != null) {
CameraController.getInstance().close(cameraSession, null, null);
}
}
return true;
}
@ -957,7 +991,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
}
public void hideCamera(boolean async) {
destroy(async, null);
destroy(async);
cameraContainer.setTranslationX(0);
textureOverlayView.setTranslationX(0);
animationTranslationY = 0;
@ -981,18 +1015,36 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
textureOverlayView.setImageBitmap(lastBitmap);
textureOverlayView.setAlpha(1f);
}
if (cameraSession != null) {
cameraSession.destroy();
CameraController.getInstance().close(cameraSession, null, null);
cameraSession = null;
}
isFrontface = !isFrontface;
if (useCamera2) {
if (camera2Session != null) {
camera2Session.destroy(false);
camera2Session = null;
}
camera2Session = Camera2Session.create(true, isFrontface, AndroidUtilities.roundPlayingMessageSize, AndroidUtilities.roundPlayingMessageSize);
if (camera2Session == null) return;
camera2Session.setRecordingVideo(true);
previewWidth = camera2Session.getPreviewWidth();
previewHeight = camera2Session.getPreviewHeight();
cameraThread.setCurrentSession(camera2Session);
} else {
if (cameraSession != null) {
cameraSession.destroy();
CameraController.getInstance().close(cameraSession, null, null);
cameraSession = null;
}
}
initCamera();
cameraReady = false;
cameraThread.reinitForNewCamera();
}
// Old Camera1 API
@Deprecated
private boolean initCamera() {
if (useCamera2) {
return true;
}
ArrayList<CameraInfo> cameraInfos = CameraController.getInstance().getCameras();
if (cameraInfos == null) {
return false;
@ -1063,6 +1115,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
return true;
}
@Deprecated // used for old Camera1 API only
private Size chooseOptimalSize(ArrayList<Size> previewSizes) {
ArrayList<Size> sortedSizes = new ArrayList<>();
boolean allowBigSizeCamera = allowBigSizeCamera();
@ -1103,6 +1156,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
return sortedSizes.get(0);
}
@Deprecated // used for old Camera1 API only
private boolean allowBigSizeCamera() {
if (SharedConfig.bigCameraForRound) {
return true;
@ -1123,6 +1177,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
return false;
}
@Deprecated // used for old Camera1 API only
public static boolean allowBigSizeCameraDebug() {
int devicePerformanceClass = Math.max(SharedConfig.getDevicePerformanceClass(), SharedConfig.getLegacyDevicePerformanceClass());
if (devicePerformanceClass == SharedConfig.PERFORMANCE_CLASS_HIGH) {
@ -1146,47 +1201,52 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
FileLog.d("InstantCamera create camera session");
}
surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
cameraSession = new CameraSession(selectedCamera, previewSize, pictureSize, ImageFormat.JPEG, true);
cameraThread.setCurrentSession(cameraSession);
CameraController.getInstance().openRound(cameraSession, surfaceTexture, () -> {
if (cameraSession != null) {
boolean updateScale = false;
try {
Camera.Size size = cameraSession.getCurrentPreviewSize();
if (size.width != previewSize.getWidth() || size.height != previewSize.getHeight()) {
previewSize = new Size(size.width, size.height);
FileLog.d("InstantCamera change preview size to w = " + previewSize.getWidth() + " h = " + previewSize.getHeight());
if (useCamera2) {
cameraThread.setCurrentSession(camera2Session);
camera2Session.open(surfaceTexture);
} else {
surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
cameraSession = new CameraSession(selectedCamera, previewSize, pictureSize, ImageFormat.JPEG, true);
cameraThread.setCurrentSession(cameraSession);
CameraController.getInstance().openRound(cameraSession, surfaceTexture, () -> {
if (cameraSession != null) {
boolean updateScale = false;
try {
Camera.Size size = cameraSession.getCurrentPreviewSize();
if (size.width != previewSize.getWidth() || size.height != previewSize.getHeight()) {
previewSize = new Size(size.width, size.height);
FileLog.d("InstantCamera change preview size to w = " + previewSize.getWidth() + " h = " + previewSize.getHeight());
}
} catch (Exception e) {
FileLog.e(e);
}
} catch (Exception e) {
FileLog.e(e);
}
try {
Camera.Size size = cameraSession.getCurrentPictureSize();
if (size.width != pictureSize.getWidth() || size.height != pictureSize.getHeight()) {
pictureSize = new Size(size.width, size.height);
FileLog.d("InstantCamera change picture size to w = " + pictureSize.getWidth() + " h = " + pictureSize.getHeight());
updateScale = true;
try {
Camera.Size size = cameraSession.getCurrentPictureSize();
if (size.width != pictureSize.getWidth() || size.height != pictureSize.getHeight()) {
pictureSize = new Size(size.width, size.height);
FileLog.d("InstantCamera change picture size to w = " + pictureSize.getWidth() + " h = " + pictureSize.getHeight());
updateScale = true;
}
} catch (Exception e) {
FileLog.e(e);
}
} catch (Exception e) {
FileLog.e(e);
}
if (BuildVars.LOGS_ENABLED) {
FileLog.d("InstantCamera camera initied");
}
cameraSession.setInitied();
if (updateScale) {
if (cameraThread != null) {
cameraThread.reinitForNewCamera();
if (BuildVars.LOGS_ENABLED) {
FileLog.d("InstantCamera camera initied");
}
cameraSession.setInitied();
if (updateScale) {
if (cameraThread != null) {
cameraThread.reinitForNewCamera();
}
}
}
}
}, () -> {
if (cameraThread != null) {
cameraThread.setCurrentSession(cameraSession);
}
});
}, () -> {
if (cameraThread != null) {
cameraThread.setCurrentSession(cameraSession);
}
});
}
});
}
@ -1293,7 +1353,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
private EGLSurface eglSurface;
private boolean initied;
private CameraSession currentSession;
private Object currentSession;
private SurfaceTexture cameraSurface;
@ -1326,8 +1386,18 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
}
private void updateScale() {
int width = previewSize.getWidth();
int height = previewSize.getHeight();
int width, height;
if (useCamera2) {
width = previewWidth;
height = previewHeight;
} else {
if (previewSize != null) {
width = previewSize.getWidth();
height = previewSize.getHeight();
} else {
return;
}
}
float scale = surfaceWidth / (float) Math.min(width, height);
@ -1552,6 +1622,13 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
}
}
public void setCurrentSession(Camera2Session session) {
Handler handler = getHandler();
if (handler != null) {
sendMessage(handler.obtainMessage(DO_SETSESSION_MESSAGE, session), 0);
}
}
private void onDraw(Integer cameraId) {
if (!initied) {
return;
@ -1581,7 +1658,14 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
captureFirstFrameThumb = true;
}
videoEncoder.startRecording(cameraFile, EGL14.eglGetCurrentContext());
int orientation = currentSession.getCurrentOrientation();
int orientation;
if (currentSession instanceof CameraSession) {
orientation = ((CameraSession) currentSession).getCurrentOrientation();
} else if (currentSession instanceof Camera2Session) {
orientation = ((Camera2Session) currentSession).getCurrentOrientation();
} else {
orientation = 0;
}
if (orientation == 90 || orientation == 270) {
float temp = scaleX;
scaleX = scaleY;
@ -1688,7 +1772,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
cameraSurface.setOnFrameAvailableListener(surfaceTexture -> requestRender());
createCamera(cameraSurface);
cameraThread.updateScale();
updateScale();
float tX = 1.0f / scaleX / 2.0f;
float tY = 1.0f / scaleY / 2.0f;
@ -1708,9 +1792,16 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
if (BuildVars.LOGS_ENABLED) {
FileLog.d("InstantCamera set gl rednderer session");
}
CameraSession newSession = (CameraSession) inputMessage.obj;
Object newSession = inputMessage.obj;
if (currentSession == newSession) {
int rotationAngle = currentSession.getWorldAngle();
int rotationAngle;
if (currentSession instanceof CameraSession) {
rotationAngle = ((CameraSession) currentSession).getWorldAngle();
} else if (currentSession instanceof Camera2Session) {
rotationAngle = ((Camera2Session) currentSession).getWorldAngle();
} else {
rotationAngle = 0;
}
android.opengl.Matrix.setIdentityM(mMVPMatrix, 0);
if (rotationAngle != 0) {
android.opengl.Matrix.rotateM(mMVPMatrix, 0, rotationAngle, 0, 0, 1);
@ -1718,6 +1809,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
} else {
currentSession = newSession;
}
updateScale();
break;
}
}
@ -3021,6 +3113,10 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER);
Size previewSize = InstantCameraView.this.previewSize;
if (previewSize == null && useCamera2) {
previewSize = new Size(previewWidth, previewHeight);
}
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, createFragmentShader(previewSize));
if (vertexShader != 0 && fragmentShader != 0) {
drawProgram = GLES20.glCreateProgram();
@ -3280,7 +3376,10 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
}
private String createFragmentShader(Size previewSize) {
if (SharedConfig.deviceIsLow() || !allowBigSizeCamera() || Math.max(previewSize.getHeight(), previewSize.getWidth()) * 0.7f < MessagesController.getInstance(currentAccount).roundVideoSize) {
if (useCamera2) {
// TODO: lanczos
}
if (SharedConfig.deviceIsLow() || !allowBigSizeCamera() || previewSize != null && Math.max(previewSize.getHeight(), previewSize.getWidth()) * 0.7f < MessagesController.getInstance(currentAccount).roundVideoSize) {
return "#extension GL_OES_EGL_image_external : require\n" +
"precision highp float;\n" +
"varying vec2 vTextureCoord;\n" +
@ -3443,9 +3542,15 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
return false;
}
pinchScale = (float) Math.hypot(ev.getX(index2) - ev.getX(index1), ev.getY(index2) - ev.getY(index1)) / pinchStartDistance;
float zoom = Math.min(1f, Math.max(0, pinchScale - 1f));
cameraSession.setZoom(zoom);
if (useCamera2) {
if (camera2Session != null) {
float zoom = Utilities.clamp(pinchScale, camera2Session.getMaxZoom(), camera2Session.getMinZoom());
camera2Session.setZoom(zoom);
}
} else {
float zoom = Math.min(1f, Math.max(0, pinchScale - 1f));
cameraSession.setZoom(zoom);
}
} else if ((ev.getActionMasked() == MotionEvent.ACTION_UP || (ev.getActionMasked() == MotionEvent.ACTION_POINTER_UP && checkPointerIds(ev)) || ev.getActionMasked() == MotionEvent.ACTION_CANCEL) && isInPinchToZoomTouchMode) {
isInPinchToZoomTouchMode = false;
finishZoom();
@ -3460,13 +3565,25 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
return;
}
float zoom = Math.min(1f, Math.max(0, pinchScale - 1f));
float zoom;
if (useCamera2) {
if (camera2Session == null) return;
zoom = Utilities.clamp(pinchScale, camera2Session.getMaxZoom(), camera2Session.getMinZoom());
} else {
zoom = Math.min(1f, Math.max(0, pinchScale - 1f));
}
if (zoom > 0f) {
finishZoomTransition = ValueAnimator.ofFloat(zoom, 0);
finishZoomTransition.addUpdateListener(valueAnimator -> {
if (cameraSession != null) {
cameraSession.setZoom((float) valueAnimator.getAnimatedValue());
if (useCamera2) {
if (camera2Session != null) {
camera2Session.setZoom((float) valueAnimator.getAnimatedValue());
}
} else {
if (cameraSession != null) {
cameraSession.setZoom((float) valueAnimator.getAnimatedValue());
}
}
});
finishZoomTransition.addListener(new AnimatorListenerAdapter() {

View file

@ -37,11 +37,13 @@ import org.telegram.ui.ActionBar.SimpleTextView;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ChatActivity;
import androidx.core.content.ContextCompat;
import androidx.core.widget.NestedScrollView;
public class JoinGroupAlert extends BottomSheet {
public static final int ORIGINATION_OTHER = -1;
public static final int ORIGINATION_SPONSORED_CHAT = 0;
private final String hash;
private final BaseFragment fragment;
private TLRPC.ChatInvite chatInvite;
@ -50,6 +52,10 @@ public class JoinGroupAlert extends BottomSheet {
private RadialProgressView requestProgressView;
public JoinGroupAlert(final Context context, TLObject obj, String group, BaseFragment parentFragment, Theme.ResourcesProvider resourcesProvider) {
this(context, obj, group, parentFragment, resourcesProvider, ORIGINATION_OTHER);
}
public JoinGroupAlert(final Context context, TLObject obj, String group, BaseFragment parentFragment, Theme.ResourcesProvider resourcesProvider, int origination) {
super(context, false, resourcesProvider);
setApplyBottomPadding(false);
setApplyTopPadding(false);
@ -146,10 +152,15 @@ public class JoinGroupAlert extends BottomSheet {
textView.setTextColor(getThemedColor(Theme.key_dialogTextGray3));
textView.setSingleLine(true);
textView.setEllipsize(TextUtils.TruncateAt.END);
textView.setText(isChannel
? LocaleController.getString("ChannelPrivate", R.string.ChannelPrivate).toLowerCase()
: LocaleController.getString("MegaPrivate", R.string.MegaPrivate).toLowerCase()
);
if (chatInvite != null && origination == ORIGINATION_SPONSORED_CHAT) {
textView.setText(LocaleController.getString("ChannelPublic", R.string.ChannelPublic).toLowerCase());
} else {
textView.setText(isChannel
? LocaleController.getString("ChannelPrivate", R.string.ChannelPrivate).toLowerCase()
: LocaleController.getString("MegaPrivate", R.string.MegaPrivate).toLowerCase()
);
}
linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 10, 0, 10, hasAbout ? 0 : 20));
if (hasAbout) {
@ -317,15 +328,14 @@ public class JoinGroupAlert extends BottomSheet {
chat.kicked = false;
MessagesController.getInstance(currentAccount).putUsers(updates.users, false);
MessagesController.getInstance(currentAccount).putChats(updates.chats, false);
Bundle args = new Bundle();
args.putLong("chat_id", chat.id);
if (MessagesController.getInstance(currentAccount).checkCanOpenChat(args, fragment)) {
ChatActivity chatActivity = new ChatActivity(args);
fragment.presentFragment(chatActivity, fragment instanceof ChatActivity);
}
openChat(chat.id);
}
} else {
AlertsCreator.processError(currentAccount, error, fragment, req);
if ("USER_ALREADY_PARTICIPANT".equals(error.text) && origination == ORIGINATION_SPONSORED_CHAT && chatInvite != null && chatInvite.chat != null) {
openChat(chatInvite.chat.id);
} else {
AlertsCreator.processError(currentAccount, error, fragment, req);
}
}
});
}, ConnectionsManager.RequestFlagFailOnServerErrors);
@ -372,4 +382,13 @@ public class JoinGroupAlert extends BottomSheet {
// scamDrawable.setColor(getThemedColor(Theme.key_avatar_subtitleInProfileBlue));
return type == 0 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable;
}
private void openChat(long chatId) {
Bundle args = new Bundle();
args.putLong("chat_id", chatId);
if (MessagesController.getInstance(currentAccount).checkCanOpenChat(args, fragment)) {
ChatActivity chatActivity = new ChatActivity(args);
fragment.presentFragment(chatActivity, fragment instanceof ChatActivity);
}
}
}

View file

@ -0,0 +1,6 @@
package org.telegram.ui.Components;
public interface Loadable {
void setLoading(boolean loading);
boolean isLoading();
}

View file

@ -62,6 +62,7 @@ import org.telegram.ui.Components.FloatingDebug.FloatingDebugProvider;
import org.telegram.ui.Components.Paint.ShapeDetector;
import org.telegram.ui.ProfileActivity;
import org.telegram.ui.Stories.recorder.ButtonWithCounterView;
import org.telegram.ui.Stories.recorder.KeyboardNotifier;
import org.telegram.ui.Stories.recorder.StoryRecorder;
import java.util.ArrayList;

View file

@ -44,6 +44,7 @@ import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Adapters.MentionsAdapter;
import org.telegram.ui.Adapters.PaddedListAdapter;
import org.telegram.ui.Cells.ContextLinkCell;
import org.telegram.ui.Cells.MentionCell;
import org.telegram.ui.Cells.StickerCell;
import org.telegram.ui.ChatActivity;
import org.telegram.ui.ContentPreviewViewer;
@ -882,7 +883,13 @@ public class MentionsContainerView extends BlurredFrameLayout implements Notific
@Override
public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.emojiLoaded) {
getListView().invalidateViews();
AndroidUtilities.forEachViews(listView, view -> {
if (view instanceof MentionCell) {
((MentionCell) view).invalidateEmojis();
} else {
view.invalidate();
}
});
}
}

View file

@ -303,6 +303,11 @@ public class MessagePreviewView extends FrameLayout {
resourcesProvider = MessagePreviewView.this.resourcesProvider;
}
@Override
protected boolean canCopy() {
return messagePreviewParams == null || !messagePreviewParams.noforwards;
}
@Override
protected Theme.ResourcesProvider getResourcesProvider() {
return resourcesProvider;

View file

@ -1,5 +1,6 @@
package org.telegram.ui.Components.Premium;
import static android.graphics.Canvas.ALL_SAVE_FLAG;
import static org.telegram.messenger.AndroidUtilities.dp;
import android.animation.Animator;
@ -13,6 +14,8 @@ import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.text.Layout;
import android.text.SpannableStringBuilder;
import android.text.StaticLayout;
@ -30,6 +33,8 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.math.MathUtils;
import com.google.android.exoplayer2.util.Log;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.R;
@ -46,6 +51,10 @@ import java.util.ArrayList;
public class LimitPreviewView extends LinearLayout {
public interface DarkGradientProvider {
Paint setDarkGradientLocation(float x, float y);
}
private float percent;
private final int premiumLimit;
private int currentValue;
@ -72,6 +81,7 @@ public class LimitPreviewView extends LinearLayout {
private final TextView defaultText;
private final TextView premiumText;
private boolean isBoostsStyle;
private boolean isSimpleStyle;
Theme.ResourcesProvider resourcesProvider;
private boolean animateIncrease;
@ -79,6 +89,7 @@ public class LimitPreviewView extends LinearLayout {
float limitIconRotation;
public boolean isStatistic;
public boolean invalidationEnabled = true;
private DarkGradientProvider darkGradientProvider;
public LimitPreviewView(@NonNull Context context, int icon, int currentValue, int premiumLimit, Theme.ResourcesProvider resourcesProvider) {
this(context, icon, currentValue, premiumLimit, .5f, resourcesProvider);
@ -105,7 +116,7 @@ public class LimitPreviewView extends LinearLayout {
addView(limitIcon, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, Gravity.LEFT));
}
final FrameLayout defaultLayout = new FrameLayout(context);
final FrameLayout defaultLayout = new TextViewHolder(context, true);
defaultText = new TextView(context);
defaultText.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
@ -127,7 +138,7 @@ public class LimitPreviewView extends LinearLayout {
defaultLayout.addView(defaultCount, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 30, Gravity.RIGHT, 12, 0, 12, 0));
}
final FrameLayout premiumLayout = new FrameLayout(context);
final FrameLayout premiumLayout = new TextViewHolder(context, false);
premiumText = new TextView(context);
premiumText.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
@ -135,7 +146,22 @@ public class LimitPreviewView extends LinearLayout {
premiumText.setGravity(Gravity.CENTER_VERTICAL);
premiumText.setTextColor(Color.WHITE);
premiumCount = new TextView(context);
premiumCount = new TextView(context) {
@Override
public void setAlpha(float alpha) {
super.setAlpha(alpha);
}
@Override
public void setTextColor(int color) {
super.setTextColor(color);
}
@Override
public void setText(CharSequence text, BufferType type) {
super.setText(text, type);
}
};
premiumCount.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
premiumCount.setText(String.format("%d", premiumLimit));
premiumCount.setGravity(Gravity.CENTER_VERTICAL);
@ -152,6 +178,11 @@ public class LimitPreviewView extends LinearLayout {
limitsContainer = new FrameLayout(context) {
Paint grayPaint = new Paint();
Paint whitePaint = new Paint();
{
whitePaint.setColor(Color.WHITE);
}
@Override
protected void dispatchDraw(Canvas canvas) {
@ -165,13 +196,19 @@ public class LimitPreviewView extends LinearLayout {
grayPaint.setColor(Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider));
}
AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
canvas.drawRoundRect(AndroidUtilities.rectTmp, dp(6), dp(6), grayPaint);
if (hasDarkGradientProvider()) {
Paint p = darkGradientProvider.setDarkGradientLocation((((ViewGroup) getParent()).getX() + getX()), (((ViewGroup) getParent()).getY() + getY()));
canvas.drawRoundRect(AndroidUtilities.rectTmp, dp(6), dp(6), p);
} else {
canvas.drawRoundRect(AndroidUtilities.rectTmp, dp(6), dp(6), grayPaint);
}
canvas.save();
if (!isBoostsStyle) {
canvas.clipRect(width1, 0, getMeasuredWidth(), getMeasuredHeight());
}
Paint paint = PremiumGradient.getInstance().getMainGradientPaint();
Paint paint = hasDarkGradientProvider() ? whitePaint : PremiumGradient.getInstance().getMainGradientPaint();
if (parentVideForGradient != null) {
View parent = parentVideForGradient;
if (staticGradient != null) {
@ -218,14 +255,14 @@ public class LimitPreviewView extends LinearLayout {
if (isBoostsStyle) {
if (percent == 0) {
width1 = 0;
premiumCount.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
defaultText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
premiumCount.setTextColor(hasDarkGradientProvider() ? Color.WHITE : Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
defaultText.setTextColor(hasDarkGradientProvider() ? Color.WHITE : Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
} else if (percent < 1f) {
float leftWidth = defaultLayout.getMeasuredWidth() - AndroidUtilities.dp(8);
float rightWidth = premiumLayout.getMeasuredWidth() - AndroidUtilities.dp(8);
float availableWidth = width - leftWidth - rightWidth;
width1 = (int) (leftWidth + availableWidth * percent);
premiumCount.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
premiumCount.setTextColor(hasDarkGradientProvider() ? Color.WHITE : Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
defaultText.setTextColor(Color.WHITE);
} else {
width1 = width;
@ -268,6 +305,14 @@ public class LimitPreviewView extends LinearLayout {
addView(limitsContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 30, 0, 0, 14, icon == 0 ? 0 : 12, 14, 0));
}
public void setDarkGradientProvider(DarkGradientProvider darkGradientProvider) {
this.darkGradientProvider = darkGradientProvider;
}
private boolean hasDarkGradientProvider() {
return darkGradientProvider != null;
}
public void setIconValue(int currentValue, boolean animated) {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("d").setSpan(new ColoredImageSpan(icon), 0, 1, 0);
@ -300,6 +345,10 @@ public class LimitPreviewView extends LinearLayout {
super.dispatchDraw(canvas);
}
private ValueAnimator arrowAnimator;
private boolean animatingRotation;
private boolean lastProgressCenter;
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
@ -311,13 +360,25 @@ public class LimitPreviewView extends LinearLayout {
float toX = padding + Math.max(width1, (getMeasuredWidth() - padding * 2) * position) - limitIcon.getMeasuredWidth() / 2f;
float fromProgressCenter = 0.5f;
float toProgressCenter = 0.5f;
if (toX < padding) {
toX = padding;
fromProgressCenter = toProgressCenter = 0f;
}
if (toX > getMeasuredWidth() - padding - limitIcon.getMeasuredWidth()) {
toX = getMeasuredWidth() - padding - limitIcon.getMeasuredWidth();
toProgressCenter = 1f;
if (isSimpleStyle) {
fromProgressCenter = limitIcon.getArrowCenter();
toX = Utilities.clamp(toX, getMeasuredWidth() - padding - limitIcon.getMeasuredWidth(), padding);
if (width1 <= 0) {
toProgressCenter = 0f;
} else if (width1 >= getMeasuredWidth() - padding * 2) {
toProgressCenter = 1f;
} else {
toProgressCenter = Utilities.clamp((float) (width1 - (toX - padding)) / limitIcon.getMeasuredWidth(), 1f, 0f);
}
} else {
if (toX < padding) {
toX = padding;
fromProgressCenter = toProgressCenter = 0f;
}
if (toX > getMeasuredWidth() - padding - limitIcon.getMeasuredWidth()) {
toX = getMeasuredWidth() - padding - limitIcon.getMeasuredWidth();
toProgressCenter = 1f;
}
}
limitIcon.setAlpha(1f);
limitIcon.setTranslationX(fromX);
@ -329,7 +390,7 @@ public class LimitPreviewView extends LinearLayout {
limitIcon.createAnimationLayouts();
}
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1f);
arrowAnimator = ValueAnimator.ofFloat(0, 1f);
float finalToX = toX;
float finalToProgressCenter = toProgressCenter;
float toWidth = width1;
@ -337,21 +398,28 @@ public class LimitPreviewView extends LinearLayout {
width1 = animateIncreaseWidth;
}
float finalFromProgressCenter = fromProgressCenter;
valueAnimator.addUpdateListener(animation -> {
final boolean animatingRotate = !animatingRotation;
animatingRotation = true;
arrowAnimator.addUpdateListener(animation -> {
float v = (float) animation.getAnimatedValue();
float moveValue = Math.min(1f, v);
if (v > 1f) {
if (!wasHaptic) {
wasHaptic = true;
limitIcon.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
if (animatingRotate) {
if (v > 1f) {
if (!wasHaptic) {
wasHaptic = true;
limitIcon.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
}
limitIcon.setRotation(limitIconRotation + (v - 1f) * 60);
} else {
limitIcon.setRotation(limitIconRotation);
}
limitIcon.setRotation(limitIconRotation + (v - 1f) * 60);
} else {
limitIcon.setRotation(limitIconRotation);
}
limitIcon.setTranslationX(fromX * (1f - moveValue) + finalToX * moveValue);
float arrowCenter = finalFromProgressCenter * (1f - moveValue) + finalToProgressCenter * moveValue;
limitIcon.setArrowCenter(arrowCenter);
if (animation == arrowAnimator) {
limitIcon.setTranslationX(fromX * (1f - moveValue) + finalToX * moveValue);
float arrowCenter = finalFromProgressCenter * (1f - moveValue) + finalToProgressCenter * moveValue;
limitIcon.setArrowCenter(arrowCenter);
limitIcon.setPivotX(limitIcon.getMeasuredWidth() * arrowCenter);
}
float scale = Math.min(1, moveValue * 2f);
if (!animateIncreaseFinal) {
limitIcon.setScaleX(scale);
@ -360,10 +428,17 @@ public class LimitPreviewView extends LinearLayout {
width1 = (int) AndroidUtilities.lerp(animateIncreaseWidth, toWidth, moveValue);
limitsContainer.invalidate();
}
limitIcon.setPivotX(limitIcon.getMeasuredWidth() * arrowCenter);
});
arrowAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (animatingRotate) {
animatingRotation = false;
}
}
});
valueAnimator.setInterpolator(new OvershootInterpolator());
arrowAnimator.setInterpolator(new OvershootInterpolator());
if (animateIncreaseFinal) {
ValueAnimator valueAnimator1 = ValueAnimator.ofFloat(0, 1f);
valueAnimator1.addUpdateListener(animation -> {
@ -374,12 +449,12 @@ public class LimitPreviewView extends LinearLayout {
});
valueAnimator1.setDuration(500);
valueAnimator1.start();
valueAnimator.setDuration(600);
arrowAnimator.setDuration(600);
} else {
valueAnimator.setDuration(1000);
valueAnimator.setStartDelay(200);
arrowAnimator.setDuration(1000);
arrowAnimator.setStartDelay(200);
}
valueAnimator.start();
arrowAnimator.start();
wasAnimation = true;
} else if (isBoostsStyle) {
@ -477,6 +552,30 @@ public class LimitPreviewView extends LinearLayout {
isBoostsStyle = true;
}
public void setStatus(int currentLevel, int maxLevel, boolean animated) {
if (currentValue == currentLevel) {
animated = false;
}
currentValue = currentLevel;
percent = MathUtils.clamp(currentLevel / (float) maxLevel, 0, 1f);
if (animated) {
animateIncrease = true;
animateIncreaseWidth = width1;
limitsContainer.requestLayout();
requestLayout();
}
((FrameLayout.LayoutParams) premiumCount.getLayoutParams()).gravity = Gravity.RIGHT;
defaultCount.setVisibility(View.GONE);
premiumText.setVisibility(View.GONE);
defaultText.setText("0");
premiumCount.setText("" + maxLevel);
setIconValue(currentLevel, false);
isBoostsStyle = true;
isSimpleStyle = true;
}
public void increaseCurrentValue(int boosts, int value, int maxValue) {
currentValue++;
percent = MathUtils.clamp(value / (float) maxValue, 0f, 1f);
@ -487,6 +586,37 @@ public class LimitPreviewView extends LinearLayout {
requestLayout();
}
private class TextViewHolder extends FrameLayout {
private final Paint paint = new Paint();
private final boolean isLeft;
public TextViewHolder(@NonNull Context context, boolean isLeft) {
super(context);
setLayerType(LAYER_TYPE_HARDWARE, null);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
this.isLeft = isLeft;
}
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (child instanceof TextView) {
boolean result = super.drawChild(canvas, child, drawingTime);
boolean leftGradient = percent != 0 && percent <= 1f && isLeft;
boolean rightGradient = percent == 1f && !isLeft;
if ((leftGradient || rightGradient) && hasDarkGradientProvider()) {
canvas.saveLayer(child.getLeft(), child.getTop(), child.getRight(), child.getBottom(), paint, ALL_SAVE_FLAG);
Paint p = darkGradientProvider.setDarkGradientLocation((((ViewGroup) getParent()).getX() + getX()), (((ViewGroup) getParent()).getY() + getY()));
canvas.drawRect(child.getLeft(), child.getTop(), child.getRight(), child.getBottom(), p);
canvas.restore();
invalidate();
}
return result;
}
return super.drawChild(canvas, child, drawingTime);
}
}
private class CounterView extends View {
Path path = new Path();
@ -503,12 +633,16 @@ public class LimitPreviewView extends LinearLayout {
float arrowCenter;
boolean invalidatePath;
Paint dstOutPaint = new Paint();
Paint overlayPaint = new Paint();
public CounterView(Context context) {
super(context);
textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
textPaint.setTextSize(dp(22));
textPaint.setColor(Color.WHITE);
dstOutPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
overlayPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.OVERLAY));
}
@Override
@ -523,8 +657,8 @@ public class LimitPreviewView extends LinearLayout {
int h = getMeasuredHeight() - dp(8);
float widthHalf = getMeasuredWidth() * arrowCenter;
float x2 = Utilities.clamp(widthHalf + dp(8), getMeasuredWidth(), 0);
float x3 = Utilities.clamp(widthHalf + dp(10), getMeasuredWidth(), AndroidUtilities.dp(24));
float x4 = Utilities.clamp(widthHalf - dp(24), getMeasuredWidth(), 0);
float x3 = Utilities.clamp(widthHalf + dp(10), getMeasuredWidth(), dp(24));
float x4 = Utilities.clamp(widthHalf - dp(arrowCenter < 0.7f ? 10 : 24), getMeasuredWidth(), 0);
float x5 = Utilities.clamp(widthHalf - dp(8), getMeasuredWidth(), 0);
path.rewind();
@ -555,15 +689,25 @@ public class LimitPreviewView extends LinearLayout {
}
PremiumGradient.getInstance().updateMainGradientMatrix(0, 0, LimitPreviewView.this.getMeasuredWidth(), LimitPreviewView.this.getMeasuredHeight(), getGlobalXOffset() - getX(), -getTop());
AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), h);
canvas.drawRoundRect(AndroidUtilities.rectTmp, h / 2f, h / 2f, PremiumGradient.getInstance().getMainGradientPaint());
canvas.drawRoundRect(AndroidUtilities.rectTmp, h / 2f, h / 2f, hasDarkGradientProvider() ? textPaint : PremiumGradient.getInstance().getMainGradientPaint());
PremiumGradient.getInstance().getMainGradientPaint().setPathEffect(pathEffect);
canvas.drawPath(path, PremiumGradient.getInstance().getMainGradientPaint());
if (hasDarkGradientProvider()) {
textPaint.setPathEffect(pathEffect);
}
canvas.drawPath(path, hasDarkGradientProvider() ? textPaint : PremiumGradient.getInstance().getMainGradientPaint());
PremiumGradient.getInstance().getMainGradientPaint().setPathEffect(null);
if (hasDarkGradientProvider()) {
textPaint.setPathEffect(null);
}
if (invalidationEnabled) {
invalidate();
}
}
if (hasDarkGradientProvider()) {
canvas.saveLayer(0, 0, getMeasuredWidth(), getMeasuredHeight(), dstOutPaint, ALL_SAVE_FLAG);
}
float x = (getMeasuredWidth() - textLayout.getWidth()) / 2f;
float y = (h - textLayout.getHeight()) / 2f;
if (!animationInProgress) {
@ -609,6 +753,14 @@ public class LimitPreviewView extends LinearLayout {
canvas.restore();
}
if (hasDarkGradientProvider()) {
canvas.restore();
canvas.saveLayer(0, 0, getMeasuredWidth(), getMeasuredHeight(), overlayPaint, ALL_SAVE_FLAG);
Paint p = darkGradientProvider.setDarkGradientLocation(getX(), getY());
canvas.drawRect(dp(12), dp(10), getMeasuredWidth() - dp(12), getMeasuredHeight() - dp(10), p);
canvas.restore();
}
}
@Override
@ -730,7 +882,6 @@ public class LimitPreviewView extends LinearLayout {
}
}
private void checkAnimationComplete() {
for (int i = 0; i < animatedLayouts.size(); i++) {
if (animatedLayouts.get(i).valueAnimator != null) {
@ -760,6 +911,10 @@ public class LimitPreviewView extends LinearLayout {
}
}
public float getArrowCenter() {
return arrowCenter;
}
private class AnimatedLayout {
public boolean replace;
ArrayList<StaticLayout> staticLayouts = new ArrayList<>();

View file

@ -27,10 +27,11 @@ import org.telegram.ui.Components.CircularProgressDrawable;
import org.telegram.ui.Components.CounterView;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.Loadable;
import org.telegram.ui.Components.RLottieImageView;
import org.telegram.ui.Components.voip.CellFlickerDrawable;
public class PremiumButtonView extends FrameLayout {
public class PremiumButtonView extends FrameLayout implements Loadable {
private Paint paintOverlayPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@ -39,7 +40,6 @@ public class PremiumButtonView extends FrameLayout {
public AnimatedTextView buttonTextView;
public AnimatedTextView overlayTextView;
private int radius;
private boolean showOverlay;
private float overlayProgress;
public FrameLayout buttonLayout;
@ -158,6 +158,10 @@ public class PremiumButtonView extends FrameLayout {
}
}
public boolean isShowOverlay() {
return showOverlay;
}
public RLottieImageView getIconView() {
return iconView;
}

View file

@ -2,6 +2,7 @@ package org.telegram.ui.Components.Premium;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
@ -160,6 +161,7 @@ public class PremiumGradient {
final int colorKey1, colorKey2, colorKey3, colorKey4, colorKey5;
final int colors[] = new int[5];
public boolean exactly;
public boolean darkColors;
public float x1 = 0f, y1 = 1f, x2 = 1.5f, y2 = 0f;
@ -217,12 +219,28 @@ public class PremiumGradient {
}
}
protected int getThemeColorByKey(int key) {
return Theme.getColor(key, resourcesProvider);
}
private int getColor(int key) {
int color = getThemeColorByKey(key);
if (darkColors) {
float a = Color.alpha(color);
float r = Color.red(color) - 15;
float g = Color.green(color) - 15;
float b = Color.blue(color) - 15;
return Color.argb((int) a, (int) r, (int) g, (int) b);
}
return color;
}
private void chekColors() {
int c1 = Theme.getColor(colorKey1, resourcesProvider);
int c2 = Theme.getColor(colorKey2, resourcesProvider);
int c3 = colorKey3 < 0 ? 0 : Theme.getColor(colorKey3, resourcesProvider);
int c4 = colorKey4 < 0 ? 0 : Theme.getColor(colorKey4, resourcesProvider);
int c5 = colorKey5 < 0 ? 0 : Theme.getColor(colorKey5, resourcesProvider);
int c1 = getColor(colorKey1);
int c2 = getColor(colorKey2);
int c3 = colorKey3 < 0 ? 0 : getColor(colorKey3);
int c4 = colorKey4 < 0 ? 0 : getColor(colorKey4);
int c5 = colorKey5 < 0 ? 0 : getColor(colorKey5);
if (colors[0] != c1 || colors[1] != c2 || colors[2] != c3 || colors[3] != c4 || colors[4] != c5) {
colors[0] = c1;
colors[1] = c2;

View file

@ -67,7 +67,7 @@ public class StarParticlesView extends View {
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int sizeInternal = getMeasuredWidth() << 16 + getMeasuredHeight();
drawable.rect.set(0, 0, AndroidUtilities.dp(140), AndroidUtilities.dp(140));
drawable.rect.set(0, 0, getStarsRectWidth(), AndroidUtilities.dp(140));
drawable.rect.offset((getMeasuredWidth() - drawable.rect.width()) / 2, (getMeasuredHeight() - drawable.rect.height()) / 2);
drawable.rect2.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
if (size != sizeInternal) {
@ -76,6 +76,10 @@ public class StarParticlesView extends View {
}
}
protected int getStarsRectWidth() {
return AndroidUtilities.dp(140);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
@ -329,11 +333,7 @@ public class StarParticlesView extends View {
paint1.setPathEffect(null);
paint1.setAlpha(255);
} else {
if (type == 100) {
paint.setColor(ColorUtils.setAlphaComponent(Theme.getColor(colorKey, resourcesProvider), 200));
} else {
paint.setColor(Theme.getColor(colorKey, resourcesProvider));
}
paint.setColor(getPathColor());
if (roundEffect) {
paint.setPathEffect(new CornerPathEffect(AndroidUtilities.dpf2(size1 / 5f)));
}
@ -345,6 +345,13 @@ public class StarParticlesView extends View {
}
}
protected int getPathColor() {
if (type == 100) {
return ColorUtils.setAlphaComponent(Theme.getColor(colorKey, resourcesProvider), 200);
} else {
return Theme.getColor(colorKey, resourcesProvider);
}
}
public void resetPositions() {
long time = System.currentTimeMillis();

View file

@ -0,0 +1,100 @@
package org.telegram.ui.Components.Premium.boosts;
import static org.telegram.messenger.AndroidUtilities.dp;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.style.ReplacementSpan;
import android.util.Pair;
import android.view.Gravity;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.R;
import org.telegram.ui.Components.AnimatedTextView;
import org.telegram.ui.Components.CubicBezierInterpolator;
public class BoostCounterSpan extends ReplacementSpan {
private final Drawable boostProfileBadge;
private final Drawable boostProfileBadge2;
public boolean isRtl;
public static Pair<SpannableString, BoostCounterSpan> create(View parent, TextPaint paint, int count) {
SpannableString spannableString = new SpannableString("d");
BoostCounterSpan span = new BoostCounterSpan(parent, paint, count);
spannableString.setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return new Pair<>(spannableString, span);
}
private final AnimatedTextView.AnimatedTextDrawable countText;
private final TextPaint namePaint;
private final View parent;
private int currentCount;
public BoostCounterSpan(View parent, TextPaint namePaint, int count) {
this.namePaint = namePaint;
this.parent = parent;
countText = new AnimatedTextView.AnimatedTextDrawable(false, false, true);
countText.setAnimationProperties(.3f, 0, 250, CubicBezierInterpolator.EASE_OUT_QUINT);
countText.setCallback(parent);
countText.setTextSize(dp(11.5f));
countText.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
countText.setText("");
countText.setGravity(Gravity.CENTER);
boostProfileBadge = ContextCompat.getDrawable(parent.getContext(), R.drawable.mini_boost_profile_badge).mutate();
boostProfileBadge2 = ContextCompat.getDrawable(parent.getContext(), R.drawable.mini_boost_profile_badge2).mutate();
boostProfileBadge.setBounds(0, 0, boostProfileBadge.getIntrinsicWidth(), boostProfileBadge.getIntrinsicHeight());
boostProfileBadge2.setBounds(0, 0, boostProfileBadge2.getIntrinsicWidth(), boostProfileBadge2.getIntrinsicHeight());
setCount(count, false);
}
public void setCount(int count, boolean animated) {
currentCount = count;
countText.setText(count <= 1 ? "" : String.valueOf(count), animated);
}
public void setColor(int color) {
countText.setTextColor(color);
}
@Override
public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, @Nullable Paint.FontMetricsInt fm) {
return getWidth();
}
public int getWidth() {
return (int) (dp(16) + countText.getWidth());
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float _x, int top, int _y, int bottom, @NonNull Paint paint) {
if (this.namePaint.getColor() != countText.getTextColor()) {
countText.setTextColor(this.namePaint.getColor());
boostProfileBadge.setColorFilter(new PorterDuffColorFilter(countText.getTextColor(), PorterDuff.Mode.MULTIPLY));
boostProfileBadge2.setColorFilter(new PorterDuffColorFilter(countText.getTextColor(), PorterDuff.Mode.MULTIPLY));
}
canvas.save();
canvas.translate(_x, -dp(0.2f));
if (currentCount == 1) {
canvas.translate(dp(1.5f), 0);
boostProfileBadge.draw(canvas);
} else {
boostProfileBadge2.draw(canvas);
}
canvas.translate(dp(16), 0);
AndroidUtilities.rectTmp2.set(0, 0, (int) countText.getCurrentWidth(), (int) countText.getHeight());
countText.setBounds(AndroidUtilities.rectTmp2);
countText.draw(canvas);
canvas.restore();
}
}

View file

@ -29,6 +29,7 @@ import android.widget.Toast;
import androidx.core.graphics.ColorUtils;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.DialogObject;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.LocaleController;
@ -45,6 +46,7 @@ import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.BottomSheet;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.BoostsActivity;
import org.telegram.ui.Components.AlertsCreator;
import org.telegram.ui.Components.Bulletin;
import org.telegram.ui.Components.BulletinFactory;
@ -104,19 +106,13 @@ public class BoostDialogs {
isGiveaway ? getString("BoostingGiveawayCreated", R.string.BoostingGiveawayCreated)
: getString("BoostingAwardsCreated", R.string.BoostingAwardsCreated),
AndroidUtilities.replaceSingleTag(
isGiveaway ? getString("BoostingCheckStatistic", R.string.BoostingCheckStatistic) :
getString("BoostingCheckGiftsStatistic", R.string.BoostingCheckGiftsStatistic),
isGiveaway ? getString(ChatObject.isChannelAndNotMegaGroup(chat) ? R.string.BoostingCheckStatistic : R.string.BoostingCheckStatisticGroup) :
getString(ChatObject.isChannelAndNotMegaGroup(chat) ? R.string.BoostingCheckGiftsStatistic : R.string.BoostingCheckGiftsStatisticGroup),
Theme.key_undo_cancelColor, 0, () -> {
if (chat != null) {
Bundle args = new Bundle();
args.putLong("chat_id", chat.id);
args.putBoolean("is_megagroup", chat.megagroup);
args.putBoolean("start_from_boosts", true);
args.putBoolean("only_boosts", true);
StatisticActivity fragment = new StatisticActivity(args);
BaseFragment.BottomSheetParams params = new BaseFragment.BottomSheetParams();
params.transitionFromLeft = true;
LaunchActivity.getLastFragment().showAsSheet(fragment, params);
LaunchActivity.getLastFragment().showAsSheet(new BoostsActivity(-chat.id), params);
}
}, resourcesProvider)
).setDuration(Bulletin.DURATION_PROLONG).show(), 300);
@ -506,7 +502,7 @@ public class BoostDialogs {
return false;
}
public static void showAbout(String from, long msgDate, TLRPC.TL_payments_giveawayInfo giveawayInfo, TLRPC.TL_messageMediaGiveaway giveaway, Context context, Theme.ResourcesProvider resourcesProvider) {
public static void showAbout(boolean isChannel, String from, long msgDate, TLRPC.TL_payments_giveawayInfo giveawayInfo, TLRPC.TL_messageMediaGiveaway giveaway, Context context, Theme.ResourcesProvider resourcesProvider) {
int quantity = giveaway.quantity;
String months = formatPluralString("BoldMonths", giveaway.months);
String endDate = LocaleController.getInstance().formatterGiveawayMonthDay.format(new Date(giveaway.until_date * 1000L));
@ -518,7 +514,7 @@ public class BoostDialogs {
builder.setTitle(getString("BoostingGiveAwayAbout", R.string.BoostingGiveAwayAbout));
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksText", quantity, from, quantity, months)));
stringBuilder.append(replaceTags(formatPluralString(isChannel ? "BoostingGiveawayHowItWorksText" : "BoostingGiveawayHowItWorksTextGroup", quantity, from, quantity, months)));
stringBuilder.append("\n\n");
if (giveaway.prize_description != null && !giveaway.prize_description.isEmpty()) {
@ -555,7 +551,7 @@ public class BoostDialogs {
} else if (giveawayInfo.admin_disallowed_chat_id != 0) {
TLRPC.Chat badChat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(giveawayInfo.admin_disallowed_chat_id);
String title = badChat != null ? badChat.title : "";
stringBuilder.append(replaceTags(formatString("BoostingGiveawayNotEligibleAdmin", R.string.BoostingGiveawayNotEligibleAdmin, title)));
stringBuilder.append(replaceTags(formatString(isChannel ? R.string.BoostingGiveawayNotEligibleAdmin : R.string.BoostingGiveawayNotEligibleAdminGroup, title)));
} else if (giveawayInfo.joined_too_early_date != 0) {
String date = LocaleController.getInstance().formatterGiveawayMonthDayYear.format(new Date(giveawayInfo.joined_too_early_date * 1000L));
stringBuilder.append(replaceTags(formatString("BoostingGiveawayNotEligible", R.string.BoostingGiveawayNotEligible, date)));
@ -574,7 +570,7 @@ public class BoostDialogs {
applyDialogStyle(builder.show(), false);
}
public static void showAboutEnd(String from, long msgDate, TLRPC.TL_payments_giveawayInfoResults giveawayInfo, TLRPC.TL_messageMediaGiveaway giveaway, Context context, Theme.ResourcesProvider resourcesProvider) {
public static void showAboutEnd(boolean isChannel, String from, long msgDate, TLRPC.TL_payments_giveawayInfoResults giveawayInfo, TLRPC.TL_messageMediaGiveaway giveaway, Context context, Theme.ResourcesProvider resourcesProvider) {
if (giveaway.until_date == 0) {
giveaway.until_date = giveawayInfo.finish_date;
}
@ -589,7 +585,7 @@ public class BoostDialogs {
builder.setTitle(getString("BoostingGiveawayEnd", R.string.BoostingGiveawayEnd));
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksTextEnd", quantity, from, quantity, months)));
stringBuilder.append(replaceTags(formatPluralString(isChannel ? "BoostingGiveawayHowItWorksTextEnd" : "BoostingGiveawayHowItWorksTextEndGroup", quantity, from, quantity, months)));
stringBuilder.append("\n\n");
if (giveaway.prize_description != null && !giveaway.prize_description.isEmpty()) {
@ -676,11 +672,12 @@ public class BoostDialogs {
}
}
public static void showPrivateChannelAlert(Context context, Theme.ResourcesProvider resourcesProvider, Runnable onCanceled, Runnable onAccepted) {
public static void showPrivateChannelAlert(TLRPC.Chat chat, Context context, Theme.ResourcesProvider resourcesProvider, Runnable onCanceled, Runnable onAccepted) {
final AtomicBoolean isAddButtonClicked = new AtomicBoolean(false);
AlertDialog.Builder builder = new AlertDialog.Builder(context, resourcesProvider);
builder.setTitle(getString("BoostingGiveawayPrivateChannel", R.string.BoostingGiveawayPrivateChannel));
builder.setMessage(getString("BoostingGiveawayPrivateChannelWarning", R.string.BoostingGiveawayPrivateChannelWarning));
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
builder.setTitle(getString(isChannel ? R.string.BoostingGiveawayPrivateChannel : R.string.BoostingGiveawayPrivateGroup));
builder.setMessage(getString(isChannel ? R.string.BoostingGiveawayPrivateChannelWarning : R.string.BoostingGiveawayPrivateGroupWarning));
builder.setPositiveButton(getString("Add", R.string.Add), (dialogInterface, i) -> {
isAddButtonClicked.set(true);
onAccepted.run();
@ -715,6 +712,7 @@ public class BoostDialogs {
}
final String fromName = getGiveawayCreatorName(messageObject);
final boolean isChannel = isChannel(messageObject);
final long msgDate = messageObject.messageOwner.date * 1000L;
BoostRepository.getGiveawayInfo(messageObject, result -> {
if (isCanceled.get()) {
@ -723,10 +721,10 @@ public class BoostDialogs {
progress.end();
if (result instanceof TLRPC.TL_payments_giveawayInfo) {
TLRPC.TL_payments_giveawayInfo giveawayInfo = (TLRPC.TL_payments_giveawayInfo) result;
showAbout(fromName, msgDate, giveawayInfo, giveaway, context, resourcesProvider);
showAbout(isChannel, fromName, msgDate, giveawayInfo, giveaway, context, resourcesProvider);
} else if (result instanceof TLRPC.TL_payments_giveawayInfoResults) {
TLRPC.TL_payments_giveawayInfoResults giveawayInfoResults = (TLRPC.TL_payments_giveawayInfoResults) result;
showAboutEnd(fromName, msgDate, giveawayInfoResults, giveaway, context, resourcesProvider);
showAboutEnd(isChannel, fromName, msgDate, giveawayInfoResults, giveaway, context, resourcesProvider);
}
}, error -> {
if (isCanceled.get()) {
@ -736,6 +734,15 @@ public class BoostDialogs {
});
}
private static boolean isChannel(MessageObject messageObject) {
if (messageObject == null) {
return false;
}
final long chatId = messageObject.getFromChatId();
TLRPC.Chat chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-chatId);
return chat != null && ChatObject.isChannelAndNotMegaGroup(chat);
}
private static String getGiveawayCreatorName(MessageObject messageObject) {
if (messageObject == null) {
return "";
@ -743,7 +750,7 @@ public class BoostDialogs {
String forwardedName = messageObject.getForwardedName();
final String name;
if (forwardedName == null) {
final long chatId = messageObject.getFromChatId();
final long chatId = MessageObject.getPeerId(messageObject.messageOwner.peer_id);
TLRPC.Chat chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-chatId);
name = chat != null ? chat.title : "";
} else {
@ -775,6 +782,7 @@ public class BoostDialogs {
return;
}
final String fromName = getGiveawayCreatorName(messageObject);
final boolean isChannel = isChannel(messageObject);
final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(fragment.getParentActivity(), fragment.getResourceProvider());
if (result instanceof TLRPC.TL_payments_giveawayInfoResults) {
@ -799,10 +807,10 @@ public class BoostDialogs {
.setUndoAction(() -> {
if (result instanceof TLRPC.TL_payments_giveawayInfo) {
TLRPC.TL_payments_giveawayInfo giveawayInfo = (TLRPC.TL_payments_giveawayInfo) result;
showAbout(fromName, msgDate, giveawayInfo, giveaway, fragment.getParentActivity(), fragment.getResourceProvider());
showAbout(isChannel, fromName, msgDate, giveawayInfo, giveaway, fragment.getParentActivity(), fragment.getResourceProvider());
} else if (result instanceof TLRPC.TL_payments_giveawayInfoResults) {
TLRPC.TL_payments_giveawayInfoResults giveawayInfoResults = (TLRPC.TL_payments_giveawayInfoResults) result;
showAboutEnd(fromName, msgDate, giveawayInfoResults, giveaway, fragment.getParentActivity(), fragment.getResourceProvider());
showAboutEnd(isChannel, fromName, msgDate, giveawayInfoResults, giveaway, fragment.getParentActivity(), fragment.getResourceProvider());
}
}));
Bulletin.make(fragment, layout, Bulletin.DURATION_LONG).show();

View file

@ -95,7 +95,7 @@ public class BoostRepository {
TLRPC.Dialog dialog = dialogs.get(i);
if (DialogObject.isChatDialog(dialog.id)) {
TLRPC.Chat chat = messagesController.getChat(-dialog.id);
if (ChatObject.isChannelAndNotMegaGroup(chat) && -dialog.id != currentChatId) {
if (ChatObject.isBoostSupported(chat) && -dialog.id != currentChatId) {
peers.add(messagesController.getInputPeer(dialog.id));
}
}
@ -602,7 +602,7 @@ public class BoostRepository {
for (int a = 0; a < res.chats.size(); a++) {
TLRPC.Chat chat = res.chats.get(a);
TLRPC.InputPeer inputPeer = MessagesController.getInputPeer(chat);
if (chat.id != currentChatId && ChatObject.isChannelAndNotMegaGroup(chat)) {
if (chat.id != currentChatId && ChatObject.isBoostSupported(chat)) {
result.add(inputPeer);
}
}
@ -676,9 +676,8 @@ public class BoostRepository {
ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount);
MessagesController controller = MessagesController.getInstance(UserConfig.selectedAccount);
TLRPC.TL_payments_getGiveawayInfo req = new TLRPC.TL_payments_getGiveawayInfo();
long selfId = UserConfig.getInstance(UserConfig.selectedAccount).getClientUserId();
req.msg_id = messageObject.getId();
req.peer = controller.getInputPeer(messageObject.getFromChatId());
req.peer = controller.getInputPeer(MessageObject.getPeerId(messageObject.messageOwner.peer_id));
int reqId = connection.sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
if (error != null) {
onError.run(error);
@ -726,6 +725,6 @@ public class BoostRepository {
controller.putChats(myBoosts.chats, false);
onDone.run(myBoosts);
}
}), ConnectionsManager.RequestFlagDoNotWaitFloodWait);
}), ConnectionsManager.RequestFlagInvokeAfter | ConnectionsManager.RequestFlagFailOnServerErrors);
}
}

View file

@ -11,6 +11,7 @@ import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
@ -168,7 +169,7 @@ public class BoostViaGiftsBottomSheet extends BottomSheetWithRecyclerListView im
}
});
this.currentChat = MessagesController.getInstance(currentAccount).getChat(-dialogId);
this.adapter.setItems(items, recyclerListView, sliderIndex -> {
this.adapter.setItems(currentChat, items, recyclerListView, sliderIndex -> {
selectedSliderIndex = sliderIndex;
actionBtn.updateCounter(getSelectedSliderValueWithBoosts());
updateRows(false, false);
@ -332,13 +333,14 @@ public class BoostViaGiftsBottomSheet extends BottomSheetWithRecyclerListView im
items.add(Item.asBoost(BoostTypeCell.TYPE_SPECIFIC_USERS, selectedUsers.size(), selectedUsers.size() > 0 ? selectedUsers.get(0) : null, selectedBoostType));
}
items.add(Item.asDivider());
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(currentChat);
if (selectedBoostType == BoostTypeCell.TYPE_GIVEAWAY) {
if (!isPreparedGiveaway()) {
items.add(Item.asSubTitleWithCounter(LocaleController.getString("BoostingQuantityPrizes", R.string.BoostingQuantityPrizes), getSelectedSliderValueWithBoosts()));
items.add(Item.asSlider(sliderValues, selectedSliderIndex));
items.add(Item.asDivider(LocaleController.getString("BoostingChooseHowMany", R.string.BoostingChooseHowMany), false));
}
items.add(Item.asSubTitle(LocaleController.getString("BoostingChannelsIncludedGiveaway", R.string.BoostingChannelsIncludedGiveaway)));
items.add(Item.asSubTitle(LocaleController.getString("BoostingChannelsGroupsIncludedGiveaway", R.string.BoostingChannelsGroupsIncludedGiveaway)));
if (isPreparedGiveaway()) {
items.add(Item.asChat(currentChat, false, prepaidGiveaway.quantity * BoostRepository.giveawayBoostsPerPremium()));
} else {
@ -355,11 +357,11 @@ public class BoostViaGiftsBottomSheet extends BottomSheetWithRecyclerListView im
if (selectedChats.size() < BoostRepository.giveawayAddPeersMax()) {
items.add(Item.asAddChannel());
}
items.add(Item.asDivider(LocaleController.getString("BoostingChooseChannelsNeedToJoin", R.string.BoostingChooseChannelsNeedToJoin), false));
items.add(Item.asDivider(LocaleController.getString("BoostingChooseChannelsGroupsNeedToJoin", R.string.BoostingChooseChannelsGroupsNeedToJoin), false));
items.add(Item.asSubTitle(LocaleController.getString("BoostingEligibleUsers", R.string.BoostingEligibleUsers)));
items.add(Item.asParticipants(ParticipantsTypeCell.TYPE_ALL, selectedParticipantsType, true, selectedCountries));
items.add(Item.asParticipants(ParticipantsTypeCell.TYPE_NEW, selectedParticipantsType, false, selectedCountries));
items.add(Item.asDivider(LocaleController.getString("BoostingChooseLimitGiveaway", R.string.BoostingChooseLimitGiveaway), false));
items.add(Item.asDivider(LocaleController.getString(isChannel ? R.string.BoostingChooseLimitGiveaway : R.string.BoostingChooseLimitGiveawayGroups), false));
}
if (!isPreparedGiveaway()) {
@ -406,10 +408,10 @@ public class BoostViaGiftsBottomSheet extends BottomSheetWithRecyclerListView im
items.add(Item.asDateEnd(selectedEndDate));
if (!isPreparedGiveaway()) {
items.add(Item.asDivider(LocaleController.formatPluralString("BoostingChooseRandom", getSelectedSliderValue()), false));
items.add(Item.asDivider(LocaleController.formatPluralString(isChannel ? "BoostingChooseRandom" : "BoostingChooseRandomGroup", getSelectedSliderValue()), false));
} else {
items.add(Item.asDivider(AndroidUtilities.replaceSingleTag(
LocaleController.formatPluralString("BoostingChooseRandom", prepaidGiveaway.quantity) + "\n\n" + LocaleController.getString("BoostingStoriesFeaturesAndTerms", R.string.BoostingStoriesFeaturesAndTerms),
LocaleController.formatPluralString(isChannel ? "BoostingChooseRandom" : "BoostingChooseRandomGroup", prepaidGiveaway.quantity) + "\n\n" + LocaleController.getString("BoostingStoriesFeaturesAndTerms", R.string.BoostingStoriesFeaturesAndTerms),
Theme.key_chat_messageLinkIn, 0, () -> {
PremiumPreviewBottomSheet previewBottomSheet = new PremiumPreviewBottomSheet(getBaseFragment(), currentAccount, null, resourcesProvider);
previewBottomSheet.setOnDismissListener(dialog -> adapter.setPausedStars(false));

View file

@ -71,7 +71,7 @@ public class DiscountSpan extends ReplacementSpan {
}
bgPaint.setColor(color);
textPaint.setColor(AndroidUtilities.computePerceivedBrightness(color) > .721f ? Color.BLACK : Color.WHITE);
float x = _x + dp(6), y = _y - height + dp(2f);
float x = _x + dp(10), y = _y - height + dp(2f);
AndroidUtilities.rectTmp.set(x, y, x + width, y + height);
float r = dp(4f);
AndroidUtilities.rectTmp.inset(dp(-4.5f), dp(-1.66f));

View file

@ -178,7 +178,7 @@ public class SelectorBottomSheet extends BottomSheetWithRecyclerListView {
searchField.updateSpans(true, selectedIds, () -> updateList(true, false), null);
updateList(true, false);
if (chat != null && !ChatObject.isPublic(chat) && selectedIds.contains(id)) {
BoostDialogs.showPrivateChannelAlert(getBaseFragment().getContext(), resourcesProvider, () -> {
BoostDialogs.showPrivateChannelAlert(chat, getBaseFragment().getContext(), resourcesProvider, () -> {
selectedIds.remove(id);
searchField.updateSpans(true, selectedIds, () -> updateList(true, false), null);
updateList(true, false);
@ -439,11 +439,12 @@ public class SelectorBottomSheet extends BottomSheetWithRecyclerListView {
String text;
switch (type) {
case TYPE_CHANNEL:
text = LocaleController.formatPluralString("BoostingSelectUpToPlural", (int) BoostRepository.giveawayAddPeersMax());
text = LocaleController.formatPluralString("BoostingSelectUpToGroupChannelPlural", (int) BoostRepository.giveawayAddPeersMax());
sectionCell.setLayerHeight(32);
break;
case TYPE_USER:
text = LocaleController.formatPluralStringComma("Subscribers", Math.max(0, selectorAdapter.getParticipantsCount(currentChat) - 1));
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(currentChat);
text = LocaleController.formatPluralStringComma(isChannel ? "Subscribers" : "Members", Math.max(0, selectorAdapter.getParticipantsCount(currentChat) - 1));
sectionCell.setLayerHeight(32);
break;
case TYPE_COUNTRY:
@ -460,7 +461,7 @@ public class SelectorBottomSheet extends BottomSheetWithRecyclerListView {
String text = "";
switch (type) {
case TYPE_CHANNEL:
text = LocaleController.formatPluralString("BoostingSelectUpToWarningChannelsPlural", (int) BoostRepository.giveawayAddPeersMax());
text = LocaleController.formatPluralString("BoostingSelectUpToWarningChannelsGroupsPlural", (int) BoostRepository.giveawayAddPeersMax());
break;
case TYPE_USER:
text = LocaleController.getString("BoostingSelectUpToWarningUsers", R.string.BoostingSelectUpToWarningUsers);
@ -671,7 +672,7 @@ public class SelectorBottomSheet extends BottomSheetWithRecyclerListView {
protected CharSequence getTitle() {
switch (type) {
case TYPE_CHANNEL:
return LocaleController.getString("BoostingAddChannel", R.string.BoostingAddChannel);
return LocaleController.getString("BoostingAddChannelOrGroup", R.string.BoostingAddChannelOrGroup);
case TYPE_USER:
return LocaleController.getString("GiftPremium", R.string.GiftPremium);
case TYPE_COUNTRY:

View file

@ -18,6 +18,7 @@ import org.telegram.tgnet.tl.TL_stories;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.ShadowSectionCell;
import org.telegram.ui.Components.ListView.AdapterWithDiffUtils;
import org.telegram.ui.Components.Premium.boosts.BoostRepository;
import org.telegram.ui.Components.Premium.boosts.cells.AddChannelCell;
import org.telegram.ui.Components.Premium.boosts.cells.BoostTypeCell;
import org.telegram.ui.Components.Premium.boosts.cells.BoostTypeSingleCell;
@ -35,6 +36,7 @@ import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.SlideChooseView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class BoostAdapter extends AdapterWithDiffUtils {
@ -64,19 +66,39 @@ public class BoostAdapter extends AdapterWithDiffUtils {
private ChatCell.ChatDeleteListener chatDeleteListener;
private HeaderCell headerCell;
private EnterPrizeCell.AfterTextChangedListener afterTextChangedListener;
private TLRPC.Chat currentChat;
private HashMap<Long, Integer> chatsParticipantsCount = new HashMap<>();
public BoostAdapter(Theme.ResourcesProvider resourcesProvider) {
this.resourcesProvider = resourcesProvider;
BoostRepository.loadParticipantsCount(result -> {
chatsParticipantsCount.clear();
chatsParticipantsCount.putAll(result);
});
}
public void setItems(List<Item> items, RecyclerListView recyclerListView, SlideChooseView.Callback sliderCallback, ChatCell.ChatDeleteListener chatDeleteListener, EnterPrizeCell.AfterTextChangedListener afterTextChangedListener) {
public void setItems(TLRPC.Chat currentChat, List<Item> items, RecyclerListView recyclerListView, SlideChooseView.Callback sliderCallback, ChatCell.ChatDeleteListener chatDeleteListener, EnterPrizeCell.AfterTextChangedListener afterTextChangedListener) {
this.items = items;
this.currentChat = currentChat;
this.recyclerListView = recyclerListView;
this.sliderCallback = sliderCallback;
this.chatDeleteListener = chatDeleteListener;
this.afterTextChangedListener = afterTextChangedListener;
}
private int getParticipantsCount(TLRPC.Chat chat) {
TLRPC.ChatFull chatFull = MessagesController.getInstance(UserConfig.selectedAccount).getChatFull(chat.id);
if (chatFull != null && chatFull.participants_count > 0) {
return chatFull.participants_count;
} else if (!chatsParticipantsCount.isEmpty()) {
Integer count = chatsParticipantsCount.get(chat.id);
if (count != null) {
return count;
}
}
return chat.participants_count;
}
public void updateBoostCounter(int value) {
for (int i = 0; i < recyclerListView.getChildCount(); ++i) {
View child = recyclerListView.getChildAt(i);
@ -84,7 +106,8 @@ public class BoostAdapter extends AdapterWithDiffUtils {
((SubtitleWithCounterCell) child).updateCounter(true, value);
}
if (child instanceof ChatCell) {
((ChatCell) child).setCounter(value);
ChatCell chatCell = ((ChatCell) child);
chatCell.setCounter(value, getParticipantsCount(chatCell.getChat()));
}
}
notifyItemChanged(8); //update main channel
@ -256,7 +279,7 @@ public class BoostAdapter extends AdapterWithDiffUtils {
switch (viewType) {
case HOLDER_TYPE_HEADER: {
headerCell = (HeaderCell) holder.itemView;
headerCell.setBoostViaGifsText();
headerCell.setBoostViaGifsText(currentChat);
break;
}
case HOLDER_TYPE_BOOST_TYPE: {
@ -297,19 +320,21 @@ public class BoostAdapter extends AdapterWithDiffUtils {
if (item.peer != null) {
TLRPC.InputPeer peer = item.peer;
if (peer instanceof TLRPC.TL_inputPeerChat) {
cell.setChat(MessagesController.getInstance(UserConfig.selectedAccount).getChat(peer.chat_id), item.intValue, item.boolValue);
TLRPC.Chat chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(peer.chat_id);
cell.setChat(chat, item.intValue, item.boolValue, getParticipantsCount(chat));
} else if (peer instanceof TLRPC.TL_inputPeerChannel) {
cell.setChat(MessagesController.getInstance(UserConfig.selectedAccount).getChat(peer.channel_id), item.intValue, item.boolValue);
TLRPC.Chat chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(peer.channel_id);
cell.setChat(chat, item.intValue, item.boolValue, getParticipantsCount(chat));
}
} else {
cell.setChat(item.chat, item.intValue, item.boolValue);
cell.setChat(item.chat, item.intValue, item.boolValue, getParticipantsCount(item.chat));
}
cell.setChatDeleteListener(chatDeleteListener);
break;
}
case HOLDER_TYPE_PARTICIPANTS: {
ParticipantsTypeCell cell = (ParticipantsTypeCell) holder.itemView;
cell.setType(item.subType, item.selectable, item.boolValue, (List<TLRPC.TL_help_country>) item.user);
cell.setType(item.subType, item.selectable, item.boolValue, (List<TLRPC.TL_help_country>) item.user, currentChat);
break;
}
case HOLDER_TYPE_DATE_END: {

View file

@ -37,7 +37,7 @@ public class AddChannelCell extends FrameLayout {
imageView.setScaleType(ImageView.ScaleType.CENTER);
addView(imageView);
textView.setText(LocaleController.getString("BoostingAddChannel", R.string.BoostingAddChannel));
textView.setText(LocaleController.getString("BoostingAddChannelOrGroup", R.string.BoostingAddChannelOrGroup));
Drawable drawable1 = getResources().getDrawable(R.drawable.poll_add_circle);
Drawable drawable2 = getResources().getDrawable(R.drawable.poll_add_plus);

View file

@ -8,8 +8,10 @@ import android.view.Gravity;
import android.widget.ImageView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.TLRPC;
@ -53,7 +55,11 @@ public class ChatCell extends BaseCell {
return false;
}
public void setChat(TLRPC.Chat chat, int boosts, boolean removable) {
public TLRPC.Chat getChat() {
return chat;
}
public void setChat(TLRPC.Chat chat, int boosts, boolean removable, int participants_count) {
this.removable = removable;
this.chat = chat;
avatarDrawable.setInfo(chat);
@ -64,10 +70,17 @@ public class ChatCell extends BaseCell {
text = Emoji.replaceEmoji(text, titleTextView.getPaint().getFontMetricsInt(), false);
titleTextView.setText(text);
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
if (removable) {
setSubtitle(null);
String subtitle;
if (participants_count >= 1) {
subtitle = LocaleController.formatPluralString(isChannel ? "Subscribers" : "Members", participants_count);
} else {
subtitle = LocaleController.getString(isChannel ? R.string.DiscussChannel : R.string.AccDescrGroup);
}
setSubtitle(subtitle);
} else {
setSubtitle(LocaleController.formatPluralString("BoostingChannelWillReceiveBoost", boosts));
setSubtitle(LocaleController.formatPluralString(isChannel ? "BoostingChannelWillReceiveBoost" : "BoostingGroupWillReceiveBoost", boosts));
}
subtitleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray3, resourcesProvider));
@ -88,11 +101,18 @@ public class ChatCell extends BaseCell {
this.chatDeleteListener = chatDeleteListener;
}
public void setCounter(int count) {
public void setCounter(int count, int participants_count) {
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
if (removable) {
setSubtitle(null);
String subtitle;
if (participants_count >= 1) {
subtitle = LocaleController.formatPluralString(isChannel ? "Subscribers" : "Members", participants_count);
} else {
subtitle = LocaleController.getString(isChannel ? R.string.DiscussChannel : R.string.AccDescrGroup);
}
setSubtitle(subtitle);
} else {
setSubtitle(LocaleController.formatPluralString("BoostingChannelWillReceiveBoost", count));
setSubtitle(LocaleController.formatPluralString(isChannel ? "BoostingChannelWillReceiveBoost" : "BoostingGroupWillReceiveBoost", count));
}
}
}

View file

@ -2,6 +2,7 @@ package org.telegram.ui.Components.Premium.boosts.cells;
import android.annotation.SuppressLint;
import android.content.Context;
import android.text.SpannableStringBuilder;
import android.view.Gravity;
import android.view.View;
@ -38,6 +39,7 @@ public class DurationWithDiscountCell extends DurationCell {
super.updateLayouts();
titleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 20 : 102, 0, LocaleController.isRTL ? 102 : 20, 0));
subtitleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 20 : 102, 0, LocaleController.isRTL ? 102 : 20, 0));
if (checkBox != null) {
checkBox.setLayoutParams(LayoutHelper.createFrame(22, 22, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 15 : 20, 0, LocaleController.isRTL ? 20 : 15, 0));
}
@ -54,19 +56,14 @@ public class DurationWithDiscountCell extends DurationCell {
this.option = option;
long price = option.amount;
CharSequence currency = option.currency;
titleTextView.setText(LocaleController.formatPluralString("Months", option.months));
SpannableStringBuilder titleBuilder = new SpannableStringBuilder(LocaleController.formatPluralString("Months", option.months)) ;
int discount = (int) ((1.0 - (option.amount / (double) option.months) / (minOption.amount / (double) minOption.months)) * 100);
String subTitle;
if (usersCount > 1) {
subTitle = BillingController.getInstance().formatCurrency(price / usersCount, currency.toString()) + " x " + usersCount;
} else {
subTitle = LocaleController.formatString(R.string.PricePerMonth, BillingController.getInstance().formatCurrency(price / option.months, currency.toString()));
}
if (discount > 0) {
setSubtitle(DiscountSpan.applySpan(subTitle, discount));
titleTextView.setText(titleBuilder.append(DiscountSpan.applySpan("", discount)));
} else {
setSubtitle(subTitle);
titleTextView.setText(titleBuilder);
}
setSubtitle(null);
totalTextView.setText(BillingController.getInstance().formatCurrency(usersCount > 0 ? price : 0, currency.toString()));
setDivider(needDivider);
checkBox.setChecked(selected, false);

View file

@ -22,6 +22,7 @@ import androidx.annotation.NonNull;
import androidx.core.graphics.ColorUtils;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.R;
@ -126,7 +127,7 @@ public class HeaderCell extends FrameLayout {
setWillNotDraw(false);
}
public void setBoostViaGifsText() {
public void setBoostViaGifsText(TLRPC.Chat currentChat) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setOutlineProvider(new ViewOutlineProvider() {
@Override
@ -142,7 +143,8 @@ public class HeaderCell extends FrameLayout {
setLayoutParams(lp);
setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider));
titleView.setText(LocaleController.formatString("BoostingBoostsViaGifts", R.string.BoostingBoostsViaGifts));
subtitleView.setText(LocaleController.formatString("BoostingGetMoreBoost", R.string.BoostingGetMoreBoost));
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(currentChat);
subtitleView.setText(LocaleController.formatString(isChannel ? R.string.BoostingGetMoreBoost : R.string.BoostingGetMoreBoostGroup));
subtitleView.setTextColor(Theme.getColor(Theme.key_dialogTextGray3, resourcesProvider));
}

View file

@ -6,6 +6,7 @@ import android.annotation.SuppressLint;
import android.content.Context;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.R;
@ -32,12 +33,13 @@ public class ParticipantsTypeCell extends BaseCell {
return selectedType;
}
public void setType(int type, boolean isSelected, boolean needDivider, List<TLRPC.TL_help_country> countries) {
public void setType(int type, boolean isSelected, boolean needDivider, List<TLRPC.TL_help_country> countries, TLRPC.Chat chat) {
selectedType = type;
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
if (type == TYPE_ALL) {
titleTextView.setText(LocaleController.formatString("BoostingAllSubscribers", R.string.BoostingAllSubscribers));
titleTextView.setText(LocaleController.formatString(isChannel ? R.string.BoostingAllSubscribers : R.string.BoostingAllMembers));
} else if (type == TYPE_NEW) {
titleTextView.setText(LocaleController.formatString("BoostingNewSubscribers", R.string.BoostingNewSubscribers));
titleTextView.setText(LocaleController.formatString(isChannel ? R.string.BoostingNewSubscribers : R.string.BoostingNewMembers));
}
radioButton.setChecked(isSelected, false);
setDivider(needDivider);

View file

@ -28,6 +28,7 @@ import androidx.annotation.NonNull;
import androidx.core.graphics.ColorUtils;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.DialogObject;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.LocaleController;
@ -208,7 +209,8 @@ public class TableCell extends FrameLayout {
dateTextView.setText(LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, monthTxt, timeTxt));
reasonTextView.setTextColor(Theme.getColor(giftCode.via_giveaway ? Theme.key_dialogTextBlue : Theme.key_dialogTextBlack, resourcesProvider));
TLRPC.Chat fromChat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-DialogObject.getPeerDialogId(giftCode.from_id));
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(fromChat);
if (giftCode.via_giveaway) {
SpannableStringBuilder builder = new SpannableStringBuilder();
builder.append("**");
@ -218,14 +220,13 @@ public class TableCell extends FrameLayout {
reasonTextView.setText(builder);
reasonTextView.setOnClickListener(v -> onObjectClicked.run(giftCode));
} else {
reasonTextView.setText(LocaleController.getString("BoostingYouWereSelected", R.string.BoostingYouWereSelected));
reasonTextView.setText(LocaleController.getString(isChannel ? R.string.BoostingYouWereSelected : R.string.BoostingYouWereSelectedGroup));
reasonTextView.setOnClickListener(null);
}
String monthsStr = giftCode.months == 12 ? LocaleController.formatPluralString("Years", 1) : LocaleController.formatPluralString("Months", giftCode.months);
giftTextView.setText(LocaleController.formatString("BoostingTelegramPremiumFor", R.string.BoostingTelegramPremiumFor, monthsStr));
TLRPC.Chat fromChat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-DialogObject.getPeerDialogId(giftCode.from_id));
if (fromChat != null) {
SpannableStringBuilder builder = new SpannableStringBuilder();
builder.append("**");

View file

@ -278,6 +278,9 @@ public class GiveawayMessageCell {
maxWidth = parentWidth - AndroidUtilities.dp(80);
}
MessagesController controller = MessagesController.getInstance(UserConfig.selectedAccount);
TLRPC.Chat fromChat = controller.getChat(-MessageObject.getPeerId(messageObject.isForwarded() ? messageObject.messageOwner.fwd_from.from_id : messageObject.messageOwner.peer_id));
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(fromChat);
CharSequence giveawayPrizes = replaceTags(getString("BoostingGiveawayPrizes", R.string.BoostingGiveawayPrizes));
SpannableStringBuilder titleStringBuilder = new SpannableStringBuilder(giveawayPrizes);
titleStringBuilder.setSpan(new RelativeSizeSpan(1.05f), 0, giveawayPrizes.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
@ -299,9 +302,9 @@ public class GiveawayMessageCell {
topStringBuilder.append("\n");
if (giveaway.only_new_subscribers) {
topStringBuilder.append(formatPluralString("BoostingGiveawayMsgNewSubsPlural", giveaway.channels.size()));
topStringBuilder.append(formatPluralString(isChannel ? "BoostingGiveawayMsgNewSubsPlural" : "BoostingGiveawayMsgNewSubsGroupPlural", giveaway.channels.size()));
} else {
topStringBuilder.append(formatPluralString("BoostingGiveawayMsgAllSubsPlural", giveaway.channels.size()));
topStringBuilder.append(formatPluralString(isChannel ? "BoostingGiveawayMsgAllSubsPlural" : "BoostingGiveawayMsgAllSubsGroupPlural", giveaway.channels.size()));
}
CharSequence dateTitle = replaceTags(getString("BoostingWinnersDate", R.string.BoostingWinnersDate));

View file

@ -21,6 +21,7 @@ import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.CheckBox2;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.Premium.boosts.cells.BaseCell;
import org.telegram.ui.Components.StatusBadgeComponent;
import java.util.Date;
@ -32,9 +33,11 @@ public class SelectorUserCell extends BaseCell {
private TLRPC.User user;
private TLRPC.Chat chat;
private TL_stories.TL_myBoost boost;
StatusBadgeComponent statusBadgeComponent;
public SelectorUserCell(Context context, Theme.ResourcesProvider resourcesProvider, boolean isGreen) {
super(context, resourcesProvider);
statusBadgeComponent = new StatusBadgeComponent(this);
titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
radioButton.setVisibility(View.GONE);
checkBox = new CheckBox2(context, 21, resourcesProvider);
@ -50,6 +53,18 @@ public class SelectorUserCell extends BaseCell {
checkBox.setLayoutParams(LayoutHelper.createFrame(24, 24, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), 13, 0, 14, 0));
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
statusBadgeComponent.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
statusBadgeComponent.onDetachedFromWindow();
}
public TLRPC.User getUser() {
return user;
}
@ -91,6 +106,7 @@ public class SelectorUserCell extends BaseCell {
setSubtitle(LocaleController.formatUserStatus(UserConfig.selectedAccount, user, isOnline));
subtitleTextView.setTextColor(Theme.getColor(isOnline[0] ? Theme.key_dialogTextBlue2 : Theme.key_dialogTextGray3, resourcesProvider));
checkBox.setAlpha(1f);
titleTextView.setRightDrawable(statusBadgeComponent.updateDrawable(user, Theme.getColor(Theme.key_chats_verifiedBackground), false));
}
public void setChat(TLRPC.Chat chat, int participants_count) {
@ -106,10 +122,11 @@ public class SelectorUserCell extends BaseCell {
if (participants_count <= 0) {
participants_count = chat.participants_count;
}
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(chat);
if (participants_count >= 1) {
subtitle = LocaleController.formatPluralString("Subscribers", participants_count);
subtitle = LocaleController.formatPluralString(isChannel? "Subscribers" : "Members", participants_count);
} else {
subtitle = LocaleController.getString(R.string.DiscussChannel);
subtitle = LocaleController.getString(isChannel ? R.string.DiscussChannel : R.string.AccDescrGroup);
}
setSubtitle(subtitle);
subtitleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray3, resourcesProvider));

View file

@ -122,15 +122,7 @@ public class ReactionsUtils {
limitReachedBottomSheet.setDialogId(dialogId);
limitReachedBottomSheet.showStatisticButtonInLink(() -> {
TLRPC.Chat chat = fragment.getMessagesController().getChat(-dialogId);
Bundle args = new Bundle();
args.putLong("chat_id", -dialogId);
args.putBoolean("is_megagroup", chat.megagroup);
args.putBoolean("start_from_boosts", true);
TLRPC.ChatFull chatInfo = fragment.getMessagesController().getChatFull(-dialogId);
if (chatInfo == null || !chatInfo.can_view_stats) {
args.putBoolean("only_boosts", true);
}
fragment.presentFragment(new StatisticActivity(args));
fragment.presentFragment(StatisticActivity.create(chat));
});
limitReachedBottomSheet.show();
}

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