1
0
mirror of https://github.com/MGislv/NekoX.git synced 2024-07-02 10:33:36 +00:00

Update to 8.6.2

This commit is contained in:
xaxtix 2022-03-20 23:22:37 +03:00
parent 5d5527525f
commit 0abe4541dd
116 changed files with 2864 additions and 1676 deletions

View File

@ -300,7 +300,7 @@ android {
}
}
defaultConfig.versionCode = 2594
defaultConfig.versionCode = 2600
applicationVariants.all { variant ->
variant.outputs.all { output ->
@ -319,7 +319,7 @@ android {
defaultConfig {
minSdkVersion 16
targetSdkVersion 30
versionName "8.6.1"
versionName "8.6.2"
vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi']

View File

@ -453,6 +453,10 @@ add_library(tgcalls STATIC
voip/tgcalls/group/AVIOContextImpl.cpp
voip/tgcalls/group/StreamingMediaContext.cpp
voip/tgcalls/group/VideoStreamingPart.cpp
voip/tgcalls/v2/InstanceV2Impl.cpp
voip/tgcalls/v2/NativeNetworkingImpl.cpp
voip/tgcalls/v2/Signaling.cpp
voip/tgcalls/v2/SignalingEncryption.cpp
voip/webrtc/rtc_base/bitstream_reader.cc
voip/webrtc/rtc_base/async_invoker.cc
voip/webrtc/rtc_base/system_time.cc

View File

@ -23,11 +23,13 @@
#include "libtgvoip/os/android/AudioInputOpenSLES.h"
#include "libtgvoip/os/android/JNIUtilities.h"
#include "tgcalls/VideoCaptureInterface.h"
#include "tgcalls/v2/InstanceV2Impl.h"
using namespace tgcalls;
const auto RegisterTag = Register<InstanceImpl>();
const auto RegisterTagLegacy = Register<InstanceImplLegacy>();
const auto RegisterTagV2 = Register<InstanceV2Impl>();
jclass TrafficStatsClass;
jclass FingerprintClass;

View File

@ -1191,7 +1191,8 @@ public:
_createAudioDeviceModule(descriptor.createAudioDeviceModule),
_eventLog(std::make_unique<webrtc::RtcEventLogNull>()),
_taskQueueFactory(webrtc::CreateDefaultTaskQueueFactory()),
_videoCapture(descriptor.videoCapture) {
_videoCapture(descriptor.videoCapture),
_platformContext(descriptor.platformContext) {
}
~InstanceV2ImplInternal() {
@ -1293,8 +1294,8 @@ public:
mediaDeps.audio_encoder_factory = webrtc::CreateAudioEncoderFactory<webrtc::AudioEncoderOpus, webrtc::AudioEncoderL16>();
mediaDeps.audio_decoder_factory = webrtc::CreateAudioDecoderFactory<webrtc::AudioDecoderOpus, webrtc::AudioDecoderL16>();
mediaDeps.video_encoder_factory = PlatformInterface::SharedInstance()->makeVideoEncoderFactory(true);
mediaDeps.video_decoder_factory = PlatformInterface::SharedInstance()->makeVideoDecoderFactory();
mediaDeps.video_encoder_factory = PlatformInterface::SharedInstance()->makeVideoEncoderFactory(_platformContext, true);
mediaDeps.video_decoder_factory = PlatformInterface::SharedInstance()->makeVideoDecoderFactory(_platformContext);
_audioDeviceModule = createAudioDeviceModule();
/*if (!_audioDeviceModule) {
@ -1964,7 +1965,7 @@ public:
}
}
void setIncomingVideoOutput(std::weak_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) {
void setIncomingVideoOutput(std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) {
_currentSink = sink;
if (_incomingVideoChannel) {
_incomingVideoChannel->addSink(sink);
@ -2095,6 +2096,7 @@ private:
std::shared_ptr<VideoCaptureInterface> _videoCapture;
std::shared_ptr<VideoCaptureInterface> _screencastCapture;
std::shared_ptr<PlatformContext> _platformContext;
};
InstanceV2Impl::InstanceV2Impl(Descriptor &&descriptor) {
@ -2150,7 +2152,7 @@ void InstanceV2Impl::setMuteMicrophone(bool muteMicrophone) {
});
}
void InstanceV2Impl::setIncomingVideoOutput(std::weak_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) {
void InstanceV2Impl::setIncomingVideoOutput(std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) {
_internal->perform(RTC_FROM_HERE, [sink](InstanceV2ImplInternal *internal) {
internal->setIncomingVideoOutput(sink);
});

View File

@ -27,7 +27,7 @@ public:
bool supportsVideo() override {
return true;
}
void setIncomingVideoOutput(std::weak_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) override;
void setIncomingVideoOutput(std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) override;
void setAudioOutputGainControlEnabled(bool enabled) override;
void setEchoCancellationStrength(int strength) override;
void setAudioInputDevice(std::string id) override;

View File

@ -14,6 +14,8 @@
#if defined(WEBRTC_POSIX)
#include <pthread.h>
#include <android/api-level.h>
#if defined(WEBRTC_MAC)
#include <pthread_spis.h>
#endif
@ -24,6 +26,14 @@
namespace webrtc {
struct pthread_mutex_internal_t {
std::atomic<uint16_t> state;
} __attribute__((aligned(4)));
static inline pthread_mutex_internal_t* __get_internal_mutex(pthread_mutex_t* mutex_interface) {
return reinterpret_cast<pthread_mutex_internal_t*>(mutex_interface);
}
class RTC_LOCKABLE MutexImpl final {
public:
MutexImpl() {
@ -38,10 +48,16 @@ class RTC_LOCKABLE MutexImpl final {
}
MutexImpl(const MutexImpl&) = delete;
MutexImpl& operator=(const MutexImpl&) = delete;
~MutexImpl() { pthread_mutex_destroy(&mutex_); }
~MutexImpl() {
if (mutexEnabled()) {
pthread_mutex_destroy(&mutex_);
}
}
void Lock() RTC_EXCLUSIVE_LOCK_FUNCTION() {
pthread_mutex_lock(&mutex_);
if (mutexEnabled()) {
pthread_mutex_lock(&mutex_);
}
owner_.SetOwner();
}
ABSL_MUST_USE_RESULT bool TryLock() RTC_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
@ -54,10 +70,21 @@ class RTC_LOCKABLE MutexImpl final {
void AssertHeld() const RTC_ASSERT_EXCLUSIVE_LOCK() { owner_.AssertOwned(); }
void Unlock() RTC_UNLOCK_FUNCTION() {
owner_.ClearOwner();
pthread_mutex_unlock(&mutex_);
if (mutexEnabled()) {
pthread_mutex_unlock(&mutex_);
}
}
private:
// pthread mutex lead to crash when try use destroyed instance on android 9 and above
bool mutexEnabled() {
if (android_get_device_api_level() >= 28) {
pthread_mutex_internal_t *mutex = __get_internal_mutex(&mutex_);
uint16_t mutex_state = std::atomic_load_explicit(&mutex->state, std::memory_order_relaxed);
return mutex_state != 0xffff;
}
return true;
}
class OwnerRecord {
public:
#if !RTC_DCHECK_IS_ON

View File

@ -62,6 +62,7 @@ public class ChatListItemAnimator extends DefaultItemAnimator {
this.activity = activity;
this.recyclerListView = listView;
translationInterpolator = DEFAULT_INTERPOLATOR;
alwaysCreateMoveAnimationIfPossible = true;
setSupportsChangeAnimations(false);
}

View File

@ -39,6 +39,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {
private static final String TAG = "SimpleItemAnimator";
boolean mSupportsChangeAnimations = true;
protected boolean alwaysCreateMoveAnimationIfPossible;
/**
* Returns whether this ItemAnimator supports animations of change events.
@ -113,8 +114,8 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {
@Override
public boolean animateAppearance(@NonNull RecyclerView.ViewHolder viewHolder,
@Nullable ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
if (preLayoutInfo != null && (preLayoutInfo.left != postLayoutInfo.left
|| preLayoutInfo.top != postLayoutInfo.top)) {
if (preLayoutInfo != null && ((preLayoutInfo.left != postLayoutInfo.left
|| preLayoutInfo.top != postLayoutInfo.top) || alwaysCreateMoveAnimationIfPossible)) {
// slide items in if before/after locations differ
if (DEBUG) {
Log.d(TAG, "APPEARING: " + viewHolder + " with view " + viewHolder);

View File

@ -83,7 +83,7 @@ public class PhoneRule {
}
}
if (intlPrefix != null && !hadC) {
res.insert(0, String.format("%s ", intlPrefix));
res.insert(0, intlPrefix + " ");
} else if (trunkPrefix != null && !hadN) {
res.insert(0, trunkPrefix);
}

View File

@ -12,6 +12,7 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.KeyguardManager;
@ -119,6 +120,7 @@ import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.TextDetailSettingsCell;
import org.telegram.ui.Components.AlertsCreator;
import org.telegram.ui.Components.BackgroundGradientDrawable;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.ForegroundColorSpanThemable;
import org.telegram.ui.Components.ForegroundDetector;
import org.telegram.ui.Components.HideViewAfterAnimation;
@ -2663,12 +2665,16 @@ public class AndroidUtilities {
return generateVideoPath(false);
}
private static SimpleDateFormat generatingVideoPathFormat;
public static File generateVideoPath(boolean secretChat) {
try {
File storageDir = getAlbumDir(secretChat);
Date date = new Date();
date.setTime(System.currentTimeMillis() + Utilities.random.nextInt(1000) + 1);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss_SSS", Locale.US).format(date);
if (generatingVideoPathFormat == null) {
generatingVideoPathFormat = new SimpleDateFormat("yyyyMMdd_HHmmss_SSS", Locale.US);
}
String timeStamp = generatingVideoPathFormat.format(date);
return new File(storageDir, "VID_" + timeStamp + ".mp4");
} catch (Exception e) {
FileLog.e(e);
@ -3826,7 +3832,7 @@ public class AndroidUtilities {
final boolean value = flagSecureReasons.containsKey(window) && flagSecureReasons.get(window).size() > 0;
try {
if (value) {
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE);
} else {
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
@ -3961,6 +3967,46 @@ public class AndroidUtilities {
}
}
private static HashMap<Window, ValueAnimator> navigationBarColorAnimators;
public static void setNavigationBarColor(Window window, int color) {
setNavigationBarColor(window, color, true);
}
public static void setNavigationBarColor(Window window, int color, boolean animated) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (navigationBarColorAnimators != null) {
ValueAnimator animator = navigationBarColorAnimators.get(window);
if (animator != null) {
animator.cancel();
navigationBarColorAnimators.remove(window);
}
}
if (!animated) {
window.setNavigationBarColor(color);
} else {
ValueAnimator animator = ValueAnimator.ofArgb(window.getNavigationBarColor(), color);
animator.addUpdateListener(a -> window.setNavigationBarColor((int) a.getAnimatedValue()));
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (navigationBarColorAnimators != null) {
navigationBarColorAnimators.remove(window);
}
}
});
animator.setDuration(200);
animator.setInterpolator(CubicBezierInterpolator.DEFAULT);
animator.start();
if (navigationBarColorAnimators == null) {
navigationBarColorAnimators = new HashMap<>();
}
navigationBarColorAnimators.put(window, animator);
}
}
}
public static boolean checkHostForPunycode(String url) {
if (url == null) {
return false;

View File

@ -95,7 +95,7 @@ public class ApplicationLoader extends Application {
}
public static void postInitApplication() {
if (applicationInited) {
if (applicationInited || applicationContext == null) {
return;
}
applicationInited = true;

View File

@ -20,8 +20,8 @@ public class BuildVars {
public static boolean USE_CLOUD_STRINGS = true;
public static boolean CHECK_UPDATES = true;
public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29;
public static int BUILD_VERSION = 2594;
public static String BUILD_VERSION_STRING = "8.6.1";
public static int BUILD_VERSION = 2600;
public static String BUILD_VERSION_STRING = "8.6.2";
public static int APP_ID = 4;
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";

View File

@ -13,6 +13,7 @@ import android.os.SystemClock;
import android.text.TextUtils;
import android.util.SparseArray;
import androidx.annotation.IntDef;
import androidx.collection.LongSparseArray;
import com.google.android.exoplayer2.util.Log;
@ -22,6 +23,8 @@ import org.telegram.messenger.voip.VoIPService;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.GroupCallActivity;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@ -59,6 +62,18 @@ public class ChatObject {
private static final int MAX_PARTICIPANTS_COUNT = 5000;
public static class Call {
public final static int RECORD_TYPE_AUDIO = 0,
RECORD_TYPE_VIDEO_PORTAIT = 1,
RECORD_TYPE_VIDEO_LANDSCAPE = 2;
@Retention(RetentionPolicy.SOURCE)
@IntDef({
RECORD_TYPE_AUDIO,
RECORD_TYPE_VIDEO_PORTAIT,
RECORD_TYPE_VIDEO_LANDSCAPE
})
public @interface RecordType {}
public TLRPC.GroupCall call;
public long chatId;
public LongSparseArray<TLRPC.TL_groupCallParticipant> participants = new LongSparseArray<>();
@ -1333,7 +1348,7 @@ public class ChatObject {
}
}
public void toggleRecord(String title, int type) {
public void toggleRecord(String title, @RecordType int type) {
recording = !recording;
TLRPC.TL_phone_toggleGroupCallRecord req = new TLRPC.TL_phone_toggleGroupCallRecord();
req.call = getInputGroupCall();
@ -1342,10 +1357,10 @@ public class ChatObject {
req.title = title;
req.flags |= 2;
}
if (type == 1 || type == 2) {
if (type == RECORD_TYPE_VIDEO_PORTAIT || type == RECORD_TYPE_VIDEO_LANDSCAPE) {
req.flags |= 4;
req.video = true;
req.video_portrait = type == 1;
req.video_portrait = type == RECORD_TYPE_VIDEO_PORTAIT;
}
currentAccount.getConnectionsManager().sendRequest(req, (response, error) -> {
if (response != null) {

View File

@ -118,4 +118,8 @@ public class DispatchQueue extends Thread {
syncLatch.countDown();
Looper.loop();
}
public boolean isReady() {
return syncLatch.getCount() == 0;
}
}

View File

@ -17,13 +17,19 @@ import android.net.ConnectivityManager;
import android.util.Pair;
import android.util.SparseArray;
import org.telegram.tgnet.TLRPC;
import androidx.collection.LongSparseArray;
import org.telegram.SQLite.SQLiteCursor;
import org.telegram.SQLite.SQLitePreparedStatement;
import org.telegram.tgnet.NativeByteBuffer;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.Components.Bulletin;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import androidx.collection.LongSparseArray;
import java.util.Locale;
public class DownloadController extends BaseController implements NotificationCenter.NotificationCenterDelegate {
@ -70,6 +76,10 @@ public class DownloadController extends BaseController implements NotificationCe
private LongSparseArray<Long> typingTimes = new LongSparseArray<>();
public final ArrayList<MessageObject> downloadingFiles = new ArrayList<>();
public final ArrayList<MessageObject> recentDownloadingFiles = new ArrayList<>();
public final SparseArray<MessageObject> unviewedDownloads = new SparseArray<>();
public static class Preset {
public int[] mask = new int[4];
public int[] sizes = new int[4];
@ -1094,4 +1104,298 @@ public class DownloadController extends BaseController implements NotificationCe
}
return Math.min(1f, progressSizes[0] / (float) progressSizes[1]);
}
public void startDownloadFile(TLRPC.Document document, MessageObject parentObject) {
AndroidUtilities.runOnUIThread(() -> {
boolean contains = false;
for (int i = 0; i < recentDownloadingFiles.size(); i++) {
if (recentDownloadingFiles.get(i).getDocument().id == parentObject.getDocument().id) {
if (parentObject.mediaExists) {
contains = true;
} else {
recentDownloadingFiles.remove(i);
}
break;
}
}
if (!contains) {
for (int i = 0; i < downloadingFiles.size(); i++) {
if (downloadingFiles.get(i).getDocument().id == parentObject.getDocument().id) {
contains = true;
break;
}
}
}
if (!contains) {
downloadingFiles.add(parentObject);
getMessagesStorage().getStorageQueue().postRunnable(() -> {
try {
NativeByteBuffer data = new NativeByteBuffer(parentObject.messageOwner.getObjectSize());
parentObject.messageOwner.serializeToStream(data);
SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("REPLACE INTO downloading_documents VALUES(?, ?, ?, ?, ?)");
state.bindByteBuffer(1, data);
state.bindInteger(2, parentObject.getDocument().dc_id);
state.bindLong(3, parentObject.getDocument().id);
state.bindLong(4, System.currentTimeMillis());
state.bindInteger(4, 0);
state.step();
state.dispose();
data.reuse();
} catch (Exception e) {
FileLog.e(e);
}
});
}
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
});
}
public void onDownloadComplete(MessageObject parentObject) {
if (parentObject == null) {
return;
}
AndroidUtilities.runOnUIThread(() -> {
boolean removed = false;
for (int i = 0; i < downloadingFiles.size(); i++) {
if (downloadingFiles.get(i).getDocument().id == parentObject.getDocument().id) {
downloadingFiles.remove(i);
removed = true;
break;
}
}
if (removed) {
boolean contains = false;
for (int i = 0; i < recentDownloadingFiles.size(); i++) {
if (recentDownloadingFiles.get(i).getDocument().id == parentObject.getDocument().id) {
contains = true;
break;
}
}
if (!contains) {
recentDownloadingFiles.add(0, parentObject);
putToUnviewedDownloads(parentObject);
}
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
}
});
getMessagesStorage().getStorageQueue().postRunnable(() -> {
try {
String req = String.format(Locale.ENGLISH, "UPDATE downloading_documents SET state = 1, date = %d WHERE hash = %d AND id = %d", System.currentTimeMillis(), parentObject.getDocument().dc_id, parentObject.getDocument().id);
getMessagesStorage().getDatabase().executeFast(req).stepThis().dispose();
SQLiteCursor cursor = getMessagesStorage().getDatabase().queryFinalized("SELECT COUNT(*) FROM downloading_documents WHERE state = 1");
int count = 0;
if (cursor.next()) {
count = cursor.intValue(0);
}
cursor.dispose();
cursor = getMessagesStorage().getDatabase().queryFinalized("SELECT state FROM downloading_documents WHERE state = 1");
if (cursor.next()) {
int state = cursor.intValue(0);
}
cursor.dispose();
int limitDownloadsDocuments = 100;
if (count > limitDownloadsDocuments) {
cursor = getMessagesStorage().getDatabase().queryFinalized("SELECT hash, id FROM downloading_documents WHERE state = 1 ORDER BY date ASC LIMIT " + (limitDownloadsDocuments - count));
ArrayList<DownloadingDocumentEntry> entriesToRemove = new ArrayList<>();
while (cursor.next()) {
DownloadingDocumentEntry entry = new DownloadingDocumentEntry();
entry.hash = cursor.intValue(0);
entry.id = cursor.longValue(1);
entriesToRemove.add(entry);
}
cursor.dispose();
SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("DELETE FROM downloading_documents WHERE hash = ? AND id = ?");
for (int i = 0; i < entriesToRemove.size(); i++) {
state.requery();
state.bindInteger(1, entriesToRemove.get(i).hash);
state.bindLong(2, entriesToRemove.get(i).id);
state.step();
}
state.dispose();
}
} catch (Exception e) {
FileLog.e(e);
}
});
}
public void onDownloadFail(MessageObject parentObject, int reason) {
if (parentObject == null) {
return;
}
AndroidUtilities.runOnUIThread(() -> {
boolean removed = false;
for (int i = 0; i < downloadingFiles.size(); i++) {
if (downloadingFiles.get(i).getDocument().id == parentObject.getDocument().id) {
downloadingFiles.remove(i);
removed = true;
break;
}
}
if (removed) {
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
if (reason == 0) {
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.showBulletin, Bulletin.TYPE_ERROR, LocaleController.formatString("MessageNotFound", R.string.MessageNotFound));
}
}
});
getMessagesStorage().getStorageQueue().postRunnable(() -> {
try {
SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("DELETE FROM downloading_documents WHERE hash = ? AND id = ?");
state.bindInteger(1, parentObject.getDocument().dc_id);
state.bindLong(2, parentObject.getDocument().id);
state.step();
state.dispose();
} catch (Exception e) {
FileLog.e(e);
}
});
}
Runnable clearUnviewedDownloadsRunnbale = new Runnable() {
@Override
public void run() {
clearUnviewedDownloads();
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
}
};
private void putToUnviewedDownloads(MessageObject parentObject) {
unviewedDownloads.put(parentObject.getId(), parentObject);
AndroidUtilities.cancelRunOnUIThread(clearUnviewedDownloadsRunnbale);
AndroidUtilities.runOnUIThread(clearUnviewedDownloadsRunnbale, 60000);
}
public void clearUnviewedDownloads() {
unviewedDownloads.clear();
}
public void checkUnviewedDownloads(int messageId, long dialogId) {
MessageObject messageObject = unviewedDownloads.get(messageId);
if (messageObject != null && messageObject.getDialogId() == dialogId) {
unviewedDownloads.remove(messageId);
if (unviewedDownloads.size() == 0) {
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
}
}
}
public boolean hasUnviewedDownloads() {
return unviewedDownloads.size() > 0;
}
private class DownloadingDocumentEntry {
long id;
int hash;
}
public void loadDownloadingFiles() {
getMessagesStorage().getStorageQueue().postRunnable(() -> {
ArrayList<MessageObject> downloadingMessages = new ArrayList<>();
ArrayList<MessageObject> recentlyDownloadedMessages = new ArrayList<>();
try {
SQLiteCursor cursor2 = getMessagesStorage().getDatabase().queryFinalized("SELECT data, state FROM downloading_documents ORDER BY date DESC");
while (cursor2.next()) {
NativeByteBuffer data = cursor2.byteBufferValue(0);
int state = cursor2.intValue(1);
if (data != null) {
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
if (message != null) {
message.readAttachPath(data, UserConfig.getInstance(currentAccount).clientUserId);
MessageObject messageObject = new MessageObject(currentAccount, message, false, true);
if (state == 0) {
downloadingMessages.add(messageObject);
} else if (messageObject.mediaExists) {
recentlyDownloadedMessages.add(messageObject);
}
}
data.reuse();
}
}
cursor2.dispose();
} catch (Exception e) {
FileLog.e(e);
}
AndroidUtilities.runOnUIThread(() -> {
downloadingFiles.clear();
downloadingFiles.addAll(downloadingMessages);
recentDownloadingFiles.clear();
recentDownloadingFiles.addAll(recentlyDownloadedMessages);
});
});
}
public void clearRecentDownloadedFiles() {
recentDownloadingFiles.clear();
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
getMessagesStorage().getStorageQueue().postRunnable(() -> {
try {
getMessagesStorage().getDatabase().executeFast("DELETE FROM downloading_documents WHERE state = 1").stepThis().dispose();
} catch (Exception e) {
FileLog.e(e);
}
});
}
public void deleteRecentFiles(ArrayList<MessageObject> messageObjects) {
for (int i = 0; i < messageObjects.size(); i++) {
boolean found = false;
for (int j = 0; j < recentDownloadingFiles.size(); j++) {
if (messageObjects.get(i).getId() == recentDownloadingFiles.get(j).getId()) {
recentDownloadingFiles.remove(j);
found = true;
break;
}
}
if (!found) {
for (int j = 0; j < downloadingFiles.size(); j++) {
if (messageObjects.get(i).getId() == downloadingFiles.get(j).getId()) {
downloadingFiles.remove(j);
found = true;
break;
}
}
}
messageObjects.get(i).putInDownloadsStore = false;
FileLoader.getInstance(currentAccount).loadFile(messageObjects.get(i).getDocument(), messageObjects.get(i), 0, 0);
FileLoader.getInstance(currentAccount).cancelLoadFile(messageObjects.get(i).getDocument(), true);
}
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
getMessagesStorage().getStorageQueue().postRunnable(() -> {
try {
SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("DELETE FROM downloading_documents WHERE hash = ? AND id = ?");
for (int i = 0; i < messageObjects.size(); i++) {
state.requery();
state.bindInteger(1, messageObjects.get(i).getDocument().dc_id);
state.bindLong(2, messageObjects.get(i).getDocument().id);
state.step();
try {
File file = FileLoader.getPathToMessage(messageObjects.get(i).messageOwner);
file.delete();
} catch (Exception e) {
FileLog.e(e);
}
}
state.dispose();
} catch (Exception e) {
FileLog.e(e);
}
});
}
}

View File

@ -8,13 +8,6 @@
package org.telegram.messenger;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@ -34,6 +27,13 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
public class Emoji {
private static HashMap<CharSequence, DrawableInfo> rects = new HashMap<>();
@ -51,6 +51,7 @@ public class Emoji {
private static boolean recentEmojiLoaded;
private static Runnable invalidateUiRunnable = () -> NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.emojiLoaded);
public static float emojiDrawingYOffset;
public static boolean emojiDrawingUseAlpha = true;
private final static int MAX_RECENT_EMOJI_COUNT = 48;
@ -246,11 +247,6 @@ public class Emoji {
@Override
public void draw(Canvas canvas) {
/*if (MessagesController.getInstance().useSystemEmoji) {
//textPaint.setTextSize(getBounds().width());
canvas.drawText(EmojiData.data[info.page][info.emojiIndex], getBounds().left, getBounds().bottom, textPaint);
return;
}*/
if (!isLoaded()) {
loadEmoji(info.page, info.page2);
canvas.drawRect(getBounds(), placeholderPaint);
@ -541,7 +537,7 @@ public class Emoji {
@Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
boolean restoreAlpha = false;
if (paint.getAlpha() != 255) {
if (paint.getAlpha() != 255 && emojiDrawingUseAlpha) {
restoreAlpha = true;
getDrawable().setAlpha(paint.getAlpha());
}

View File

@ -603,7 +603,7 @@ public class FileLoader extends BaseController {
}
if (document != null && parentObject instanceof MessageObject && ((MessageObject) parentObject).putInDownloadsStore) {
getMessagesStorage().startDownloadFile(document, (MessageObject) parentObject);
getDownloadController().startDownloadFile(document, (MessageObject) parentObject);
}
FileLoadOperation operation = loadOperationPaths.get(fileName);
@ -708,7 +708,7 @@ public class FileLoader extends BaseController {
return;
}
if (document != null && parentObject instanceof MessageObject) {
getMessagesStorage().onDownloadComplete((MessageObject) parentObject);
getDownloadController().onDownloadComplete((MessageObject) parentObject);
}
if (!operation.isPreloadVideoOperation()) {
@ -728,6 +728,10 @@ public class FileLoader extends BaseController {
if (delegate != null) {
delegate.fileDidFailedLoad(fileName, reason);
}
if (document != null && parentObject instanceof MessageObject && reason == 0) {
getDownloadController().onDownloadFail((MessageObject) parentObject, reason);
}
}
@Override
@ -1122,6 +1126,9 @@ public class FileLoader extends BaseController {
}
public static String getDocumentFileName(TLRPC.Document document) {
if (document == null) {
return null;
}
if (document.file_name_fixed != null) {
return document.file_name_fixed;
}
@ -1395,7 +1402,7 @@ public class FileLoader extends BaseController {
public void getCurrentLoadingFiles(ArrayList<MessageObject> currentLoadingFiles) {
currentLoadingFiles.clear();
currentLoadingFiles.addAll(getMessagesStorage().downloadingFiles);
currentLoadingFiles.addAll(getDownloadController().downloadingFiles);
for (int i = 0; i < currentLoadingFiles.size(); i++) {
currentLoadingFiles.get(i).isDownloadingFile = true;
}
@ -1403,7 +1410,7 @@ public class FileLoader extends BaseController {
public void getRecentLoadingFiles(ArrayList<MessageObject> recentLoadingFiles) {
recentLoadingFiles.clear();
recentLoadingFiles.addAll(getMessagesStorage().recentDownloadingFiles);
recentLoadingFiles.addAll(getDownloadController().recentDownloadingFiles);
for (int i = 0; i < recentLoadingFiles.size(); i++) {
recentLoadingFiles.get(i).isDownloadingFile = true;
}
@ -1411,7 +1418,7 @@ public class FileLoader extends BaseController {
public void checkCurrentDownloadsFiles() {
ArrayList<MessageObject> messagesToRemove = new ArrayList<>();
ArrayList<MessageObject> messageObjects = new ArrayList<>(getMessagesStorage().recentDownloadingFiles);
ArrayList<MessageObject> messageObjects = new ArrayList<>(getDownloadController().recentDownloadingFiles);
for (int i = 0 ; i < messageObjects.size(); i++) {
messageObjects.get(i).checkMediaExistance();
if (messageObjects.get(i).mediaExists) {
@ -1420,15 +1427,14 @@ public class FileLoader extends BaseController {
}
if (!messagesToRemove.isEmpty()) {
AndroidUtilities.runOnUIThread(() -> {
getMessagesStorage().recentDownloadingFiles.removeAll(messagesToRemove);
getDownloadController().recentDownloadingFiles.removeAll(messagesToRemove);
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
});
}
}
public void clearRecentDownloadedFiles() {
getMessagesStorage().clearRecentDownloadedFiles();
getDownloadController().clearRecentDownloadedFiles();
}
}

View File

@ -9,6 +9,8 @@ import android.security.keystore.KeyProperties;
import androidx.annotation.RequiresApi;
import org.telegram.messenger.support.fingerprint.FingerprintManagerCompat;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
@ -100,7 +102,8 @@ public class FingerprintController {
}
public static void checkKeyReady(boolean notifyCheckFingerprint) {
if (!isKeyReady() && AndroidUtilities.isKeyguardSecure()) {
if (!isKeyReady() && AndroidUtilities.isKeyguardSecure() && FingerprintManagerCompat.from(ApplicationLoader.applicationContext).isHardwareDetected()
&& FingerprintManagerCompat.from(ApplicationLoader.applicationContext).hasEnrolledFingerprints()) {
Utilities.globalQueue.postRunnable(() -> generateNewKey(notifyCheckFingerprint));
}
}

View File

@ -82,7 +82,7 @@ import java.util.zip.GZIPInputStream;
* isc - ignore cache for small images
* b - need blur image
* g - autoplay
* firstframe - return firstframe for Lottie anjimation
* lastframe - return firstframe for Lottie animation
*/
public class ImageLoader {
@ -843,7 +843,7 @@ public class ImageLoader {
int h = Math.min(512, AndroidUtilities.dp(170.6f));
boolean precache = false;
boolean limitFps = false;
boolean firstFrameBitmap = false;
boolean lastFrameBitmap = false;
int autoRepeat = 1;
int[] colors = null;
String diceEmoji = null;
@ -866,8 +866,8 @@ public class ImageLoader {
precache = !cacheImage.filter.contains("nolimit") && SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_HIGH;
}
if (cacheImage.filter.contains("firstframe")) {
firstFrameBitmap = true;
if (cacheImage.filter.contains("lastframe")) {
lastFrameBitmap = true;
}
}
@ -931,14 +931,17 @@ public class ImageLoader {
}
}
}
if (lastFrameBitmap) {
precache = false;
}
if (compressed) {
lottieDrawable = new RLottieDrawable(cacheImage.finalFilePath, decompressGzip(cacheImage.finalFilePath), w, h, precache, limitFps, null, fitzModifier);
} else {
lottieDrawable = new RLottieDrawable(cacheImage.finalFilePath, w, h, precache, limitFps, null, fitzModifier);
}
}
if (firstFrameBitmap) {
loadFirstFrame(lottieDrawable, h, w);
if (lastFrameBitmap) {
loadLastFrame(lottieDrawable, h, w);
} else {
lottieDrawable.setAutoRepeat(autoRepeat);
onPostExecute(lottieDrawable);
@ -1455,7 +1458,7 @@ public class ImageLoader {
}
}
private void loadFirstFrame(RLottieDrawable lottieDrawable, int w, int h) {
private void loadLastFrame(RLottieDrawable lottieDrawable, int w, int h) {
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.scale(2f, 2f, w / 2f, h / 2f);
@ -1472,7 +1475,7 @@ public class ImageLoader {
onPostExecute(bitmapDrawable);
lottieDrawable.recycle();
});
lottieDrawable.setCurrentFrame(lottieDrawable.getFramesCount() - 1, false, true);
lottieDrawable.setCurrentFrame(lottieDrawable.getFramesCount() - 1, true, true);
});
}

View File

@ -13,9 +13,18 @@ public class LanguageDetector {
}
public static void detectLanguage(String text, StringCallback onSuccess, ExceptionCallback onFail) {
com.google.mlkit.nl.languageid.LanguageIdentification.getClient()
.identifyLanguage(text)
.addOnSuccessListener(onSuccess::run)
.addOnFailureListener(onFail::run);
try {
com.google.mlkit.nl.languageid.LanguageIdentification.getClient()
.identifyLanguage(text)
.addOnSuccessListener(str -> {
onSuccess.run(str);
})
.addOnFailureListener(e -> {
onFail.run(e);
});
} catch (Exception e) {
FileLog.e(e);
onFail.run(e);
}
}
}

View File

@ -83,7 +83,6 @@ import org.telegram.ui.PhotoViewer;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
@ -4822,9 +4821,9 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
if (framerate == 0) {
framerate = 25;
}/* else if (framerate > 59) {
} else if (framerate > 59) {
framerate = 59;
}*/
}
if (rotationValue == 90 || rotationValue == 270) {
int temp = resultHeight;
@ -4832,6 +4831,10 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
resultWidth = temp;
}
if (framerate > 30 && (Math.min(resultHeight, resultWidth) <= 480)) {
framerate = 30;
}
boolean needCompress = avatarStartTime != -1 || info.cropState != null || info.mediaEntities != null || info.paintPath != null || info.filterState != null ||
resultWidth != originalWidth || resultHeight != originalHeight || rotationValue != 0 || info.roundVideo || startTime != -1;
@ -4925,13 +4928,13 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
compressFactor = 1f;
minCompressFactor = 1f;
} else if (Math.min(height, width) >= 720) {
maxBitrate = 3200_000;
compressFactor = 1f;
minCompressFactor = 1f;
maxBitrate = 2600_000;
compressFactor = 0.8f;
minCompressFactor = 0.8f;
} else if (Math.min(height, width) >= 480) {
maxBitrate = 1000_000;
compressFactor = 0.8f;
minCompressFactor = 0.9f;
compressFactor = 0.7f;
minCompressFactor = 0.8f;
} else {
maxBitrate = 750_000;
compressFactor = 0.6f;

View File

@ -1024,7 +1024,7 @@ public class MessageObject {
messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false, emojiOnly);
checkEmojiOnly(emojiOnly);
emojiAnimatedSticker = null;
if (emojiOnlyCount == 1 && !(message.media instanceof TLRPC.TL_messageMediaWebPage) && !(message.media instanceof TLRPC.TL_messageMediaInvoice) && message.entities.isEmpty()) {
if (emojiOnlyCount == 1 && !(message.media instanceof TLRPC.TL_messageMediaWebPage) && !(message.media instanceof TLRPC.TL_messageMediaInvoice) && message.entities.isEmpty() && (message.media instanceof TLRPC.TL_messageMediaEmpty || message.media == null) && messageOwner.grouped_id == 0) {
CharSequence emoji = messageText;
int index;
if ((index = TextUtils.indexOf(emoji, "\uD83C\uDFFB")) >= 0) {

View File

@ -86,9 +86,6 @@ public class MessagesStorage extends BaseController {
private boolean databaseMigrationInProgress;
public boolean showClearDatabaseAlert;
public ArrayList<MessageObject> downloadingFiles = new ArrayList<>();
public ArrayList<MessageObject> recentDownloadingFiles = new ArrayList<>();
public SparseArray<MessageObject> unviewedDownloads = new SparseArray<>();
public static MessagesStorage getInstance(int num) {
MessagesStorage localInstance = Instance[num];
@ -2164,259 +2161,7 @@ public class MessagesStorage extends BaseController {
});
}
public void startDownloadFile(TLRPC.Document document, MessageObject parentObject) {
AndroidUtilities.runOnUIThread(() -> {
boolean contains = false;
for (int i = 0; i < recentDownloadingFiles.size(); i++) {
if (recentDownloadingFiles.get(i).getDocument().id == parentObject.getDocument().id) {
recentDownloadingFiles.remove(i);
break;
}
}
for (int i = 0; i < downloadingFiles.size(); i++) {
if (downloadingFiles.get(i).getDocument().id == parentObject.getDocument().id) {
contains = true;
break;
}
}
if (!contains) {
downloadingFiles.add(parentObject);
}
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
});
storageQueue.postRunnable(() -> {
NativeByteBuffer data = null;
try {
data = new NativeByteBuffer(parentObject.messageOwner.getObjectSize());
parentObject.messageOwner.serializeToStream(data);
SQLitePreparedStatement state = database.executeFast("REPLACE INTO downloading_documents VALUES(?, ?, ?, ?, ?)");
state.bindByteBuffer(1, data);
state.bindInteger(2, parentObject.getDocument().dc_id);
state.bindLong(3, parentObject.getDocument().id);
state.bindLong(4, System.currentTimeMillis());
state.bindInteger(4, 0);
state.step();
state.dispose();
data.reuse();
} catch (Exception e) {
FileLog.e(e);
}
});
}
public void onDownloadComplete(MessageObject parentObject) {
AndroidUtilities.runOnUIThread(() -> {
boolean removed = false;
for (int i = 0; i < downloadingFiles.size(); i++) {
if (downloadingFiles.get(i).getDocument().id == parentObject.getDocument().id) {
downloadingFiles.remove(i);
removed = true;
break;
}
}
if (removed) {
boolean contains = false;
for (int i = 0; i < recentDownloadingFiles.size(); i++) {
if (recentDownloadingFiles.get(i).getDocument().id == parentObject.getDocument().id) {
contains = true;
break;
}
}
if (!contains) {
recentDownloadingFiles.add(0, parentObject);
putToUnviewedDownloads(parentObject);
}
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
}
});
storageQueue.postRunnable(() -> {
try {
NativeByteBuffer data = new NativeByteBuffer(parentObject.messageOwner.getObjectSize());
parentObject.messageOwner.serializeToStream(data);
SQLitePreparedStatement state = database.executeFast("UPDATE downloading_documents SET state = 1, date = ? WHERE hash = ? AND id = ?");
state.bindLong(1, System.currentTimeMillis());
state.bindInteger(2, parentObject.getDocument().dc_id);
state.bindLong(3, parentObject.getDocument().id);
state.step();
state.dispose();
data.reuse();
SQLiteCursor cursor = database.queryFinalized("SELECT COUNT(*) FROM downloading_documents WHERE state = 1");
int count = 0;
if (cursor.next()) {
count = cursor.intValue(0);
}
cursor.dispose();
int limitDownloadsDocuments = 100;
if (count > limitDownloadsDocuments) {
cursor = database.queryFinalized("SELECT hash, id FROM downloading_documents WHERE state = 1 ORDER BY date ASC LIMIT " + (limitDownloadsDocuments - count));
ArrayList<DownloadingDocumentEntry> entriesToRemove = new ArrayList<>();
while (cursor.next()) {
DownloadingDocumentEntry entry = new DownloadingDocumentEntry();
entry.hash = cursor.intValue(0);
entry.id = cursor.longValue(1);
entriesToRemove.add(entry);
}
cursor.dispose();
state = database.executeFast("DELETE FROM downloading_documents WHERE hash = ? AND id = ?");
for (int i = 0; i < entriesToRemove.size(); i++) {
state.bindInteger(1, entriesToRemove.get(i).hash);
state.bindLong(2, entriesToRemove.get(i).id);
state.step();
}
state.dispose();
}
} catch (Exception e) {
FileLog.e(e);
}
});
}
Runnable clearUnviewedDownloadsRunnbale = new Runnable() {
@Override
public void run() {
clearUnviewedDownloads();
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
}
};
private void putToUnviewedDownloads(MessageObject parentObject) {
unviewedDownloads.put(parentObject.getId(), parentObject);
AndroidUtilities.cancelRunOnUIThread(clearUnviewedDownloadsRunnbale);
AndroidUtilities.runOnUIThread(clearUnviewedDownloadsRunnbale, 60000);
}
public void clearUnviewedDownloads() {
unviewedDownloads.clear();
}
public void checkUnviewedDownloads(int messageId, long dialogId) {
MessageObject messageObject = unviewedDownloads.get(messageId);
if (messageObject != null && messageObject.getDialogId() == dialogId) {
unviewedDownloads.remove(messageId);
if (unviewedDownloads.size() == 0) {
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
}
}
}
public boolean hasUnviewedDownloads() {
return unviewedDownloads.size() > 0;
}
private class DownloadingDocumentEntry {
long id;
int hash;
}
public void loadDownloadingFiles() {
storageQueue.postRunnable(() -> {
ArrayList<MessageObject> downloadingMessages = new ArrayList<>();
ArrayList<MessageObject> recentlyDownloadedMessages = new ArrayList<>();
try {
SQLiteCursor cursor2 = database.queryFinalized("SELECT data, state FROM downloading_documents ORDER BY date DESC");
while (cursor2.next()) {
NativeByteBuffer data = cursor2.byteBufferValue(0);
int state = cursor2.intValue(1);
if (data != null) {
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
if (message != null) {
message.readAttachPath(data, UserConfig.getInstance(currentAccount).clientUserId);
MessageObject messageObject = new MessageObject(currentAccount, message, false, true);
if (state == 0) {
downloadingMessages.add(messageObject);
} else if (messageObject.mediaExists) {
recentlyDownloadedMessages.add(messageObject);
}
}
data.reuse();
}
}
cursor2.dispose();
} catch (Exception e) {
FileLog.e(e);
}
AndroidUtilities.runOnUIThread(() -> {
downloadingFiles.clear();
downloadingFiles.addAll(downloadingMessages);
recentDownloadingFiles.clear();
recentDownloadingFiles.addAll(recentlyDownloadedMessages);
});
});
}
public void clearRecentDownloadedFiles() {
recentDownloadingFiles.clear();
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
storageQueue.postRunnable(() -> {
try {
database.executeFast("DELETE FROM downloading_documents WHERE state = 1").stepThis().dispose();
} catch (Exception e) {
FileLog.e(e);
}
});
}
public void deleteRecentFiles(ArrayList<MessageObject> messageObjects) {
for (int i = 0; i < messageObjects.size(); i++) {
boolean found = false;
for (int j = 0; j < recentDownloadingFiles.size(); j++) {
if (messageObjects.get(i).getId() == recentDownloadingFiles.get(j).getId()) {
recentDownloadingFiles.remove(j);
found = true;
break;
}
}
if (!found) {
for (int j = 0; j < downloadingFiles.size(); j++) {
if (messageObjects.get(i).getId() == downloadingFiles.get(j).getId()) {
downloadingFiles.remove(j);
found = true;
break;
}
}
}
messageObjects.get(i).putInDownloadsStore = false;
FileLoader.getInstance(currentAccount).loadFile(messageObjects.get(i).getDocument(), messageObjects.get(i), 0, 0);
FileLoader.getInstance(currentAccount).cancelLoadFile(messageObjects.get(i).getDocument(), true);
}
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
storageQueue.postRunnable(() -> {
try {
SQLitePreparedStatement state = database.executeFast("DELETE FROM downloading_documents WHERE hash = ? AND id = ?");
for (int i = 0; i < messageObjects.size(); i++) {
state.bindInteger(1, messageObjects.get(i).getDocument().dc_id);
state.bindLong(2, messageObjects.get(i).getDocument().id);
state.step();
try {
File file = FileLoader.getPathToMessage(messageObjects.get(i).messageOwner);
file.delete();
} catch (Exception e) {
FileLog.e(e);
}
}
state.dispose();
} catch (Exception e) {
FileLog.e(e);
}
});
}
private static class ReadDialog {
public int lastMid;
@ -12817,7 +12562,7 @@ public class MessagesStorage extends BaseController {
storageQueue.postRunnable(() -> {
try {
SQLitePreparedStatement state = database.executeFast("UPDATE dialogs SET unread_reactions = ? WHERE did = ?");
state.bindInteger(1, count);
state.bindInteger(1, Math.max(count, 0));
state.bindLong(2, dialogId);
state.step();
state.dispose();

View File

@ -1225,8 +1225,9 @@ public class NotificationsController extends BaseController {
if (controller.showBadgeMessages) {
if (controller.showBadgeMuted) {
try {
for (int i = 0, N = MessagesController.getInstance(a).allDialogs.size(); i < N; i++) {
TLRPC.Dialog dialog = MessagesController.getInstance(a).allDialogs.get(i);
final ArrayList<TLRPC.Dialog> dialogs = new ArrayList<>(MessagesController.getInstance(a).allDialogs);
for (int i = 0, N = dialogs.size(); i < N; i++) {
TLRPC.Dialog dialog = dialogs.get(i);
if (dialog != null && DialogObject.isChatDialog(dialog.id)) {
TLRPC.Chat chat = getMessagesController().getChat(-dialog.id);
if (ChatObject.isNotInChat(chat)) {

View File

@ -7003,7 +7003,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
boolean isWebP = false;
if (tempPath != null && info.ttl <= 0 && (tempPath.endsWith(".gif") || (isWebP = tempPath.endsWith(".webp")))) {
if (!isWebP || shouldSendWebPAsSticker(tempPath, null)) {
if (media.size() <= 1 && (!isWebP || shouldSendWebPAsSticker(tempPath, null))) {
continue;
} else {
info.forceImage = true;
@ -7012,7 +7012,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
continue;
} else if (tempPath == null && info.uri != null) {
if (MediaController.isGif(info.uri) || (isWebP = MediaController.isWebp(info.uri))) {
if (!isWebP || shouldSendWebPAsSticker(null, info.uri)) {
if (media.size() <= 1 && (!isWebP || shouldSendWebPAsSticker(null, info.uri))) {
continue;
} else {
info.forceImage = true;
@ -7894,16 +7894,16 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
videoEditedInfo.resultHeight, videoEditedInfo.resultWidth
);
if (!needCompress) {
videoEditedInfo.resultWidth = videoEditedInfo.originalWidth;
videoEditedInfo.resultHeight = videoEditedInfo.originalHeight;
videoEditedInfo.bitrate = bitrate;
videoEditedInfo.estimatedSize = (int) (audioFramesSize + videoDuration / 1000.0f * bitrate / 8);
} else {
videoEditedInfo.bitrate = bitrate;
videoEditedInfo.estimatedSize = (int) (audioFramesSize + videoFramesSize);
videoEditedInfo.estimatedSize += videoEditedInfo.estimatedSize / (32 * 1024) * 16;
}
videoEditedInfo.estimatedSize = (int) (audioFramesSize + videoDuration / 1000.0f * bitrate / 8);
if (videoEditedInfo.estimatedSize == 0) {
videoEditedInfo.estimatedSize = 1;
}

View File

@ -401,4 +401,8 @@ public class Utilities {
}
return null;
}
public static float clamp(float value, float top, float bottom) {
return Math.max(Math.min(value, top), bottom);
}
}

View File

@ -63,7 +63,6 @@ public class CameraController implements MediaRecorder.OnInfoListener {
private VideoTakeCallback onVideoTakeCallback;
private boolean cameraInitied;
private boolean loadingCameras;
private boolean previewStarted = false;
private ArrayList<Runnable> onFinishCameraInitRunnables = new ArrayList<>();
CameraView recordingCurrentCameraView;
@ -474,7 +473,6 @@ public class CameraController implements MediaRecorder.OnInfoListener {
camera = session.cameraInfo.camera = Camera.open(session.cameraInfo.cameraId);
}
camera.startPreview();
session.previewStarted = true;
} catch (Exception e) {
session.cameraInfo.camera = null;
if (camera != null) {
@ -496,7 +494,6 @@ public class CameraController implements MediaRecorder.OnInfoListener {
camera = session.cameraInfo.camera = Camera.open(session.cameraInfo.cameraId);
}
camera.stopPreview();
session.previewStarted = false;
} catch (Exception e) {
session.cameraInfo.camera = null;
if (camera != null) {
@ -507,10 +504,6 @@ public class CameraController implements MediaRecorder.OnInfoListener {
});
}
public boolean isPreviewRunning(final CameraSession session) {
return session != null && session.previewStarted;
}
public void openRound(final CameraSession session, final SurfaceTexture texture, final Runnable callback, final Runnable configureCallback) {
if (session == null || texture == null) {
@ -819,8 +812,8 @@ public class CameraController implements MediaRecorder.OnInfoListener {
}
public static Size chooseOptimalSize(List<Size> choices, int width, int height, Size aspectRatio) {
List<Size> bigEnoughWithAspectRatio = new ArrayList<>();
List<Size> bigEnough = new ArrayList<>();
List<Size> bigEnoughWithAspectRatio = new ArrayList<>(choices.size());
List<Size> bigEnough = new ArrayList<>(choices.size());
int w = aspectRatio.getWidth();
int h = aspectRatio.getHeight();
for (int a = 0; a < choices.size(); a++) {

View File

@ -18,7 +18,6 @@ import java.util.ArrayList;
public class CameraInfo {
protected int cameraId;
protected Camera camera;
protected ArrayList<Size> pictureSizes = new ArrayList<>();
@ -30,7 +29,6 @@ public class CameraInfo {
CaptureRequest.Builder captureRequestBuilder;
public CameraCaptureSession cameraCaptureSession;
public CameraInfo(int id, int frontFace) {
cameraId = id;
frontCamera = frontFace;

View File

@ -11,6 +11,7 @@ package org.telegram.messenger.camera;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.hardware.Camera;
import android.media.CamcorderProfile;
@ -51,8 +52,8 @@ public class CameraSession {
private boolean useTorch;
private boolean isRound;
private boolean destroyed;
public boolean previewStarted = false;
private int infoCameraId = -1;
Camera.CameraInfo info = new Camera.CameraInfo();
public static final int ORIENTATION_HYSTERESIS = 5;
@ -103,6 +104,12 @@ public class CameraSession {
}
}
private void updateCameraInfo() {
if (infoCameraId != cameraInfo.getCameraId()) {
Camera.getCameraInfo(infoCameraId = cameraInfo.getCameraId(), this.info);
}
}
private int roundOrientation(int orientation, int orientationHistory) {
boolean changeOrientation;
if (orientationHistory == OrientationEventListener.ORIENTATION_UNKNOWN) {
@ -209,7 +216,7 @@ public class CameraSession {
FileLog.e(e);
}
Camera.getCameraInfo(cameraInfo.getCameraId(), info);
updateCameraInfo();
updateRotation();
if (params != null) {
@ -278,12 +285,12 @@ public class CameraSession {
}
try {
Camera.getCameraInfo(cameraInfo.getCameraId(), info);
updateCameraInfo();
} catch (Throwable throwable) {
FileLog.e(throwable);
return;
}
Camera camera = (cameraInfo == null || destroyed) ? null : cameraInfo.camera;
Camera camera = destroyed ? null : cameraInfo.camera;
displayOrientation = getDisplayOrientation(info, true);
int cameraDisplayOrientation;
@ -322,10 +329,7 @@ public class CameraSession {
if (camera != null) {
try {
camera.setDisplayOrientation(currentOrientation);
} catch (Throwable ignore) {
}
} catch (Throwable ignore) {}
}
diffOrientation = currentOrientation - displayOrientation;
if (diffOrientation < 0) {
@ -344,8 +348,7 @@ public class CameraSession {
FileLog.e(e);
}
Camera.getCameraInfo(cameraInfo.getCameraId(), info);
updateCameraInfo();
updateRotation();
diffOrientation = currentOrientation - displayOrientation;
@ -468,7 +471,7 @@ public class CameraSession {
}
protected void configureRecorder(int quality, MediaRecorder recorder) {
Camera.getCameraInfo(cameraInfo.cameraId, info);
updateCameraInfo();
int outputOrientation = 0;
if (jpegOrientation != OrientationEventListener.ORIENTATION_UNKNOWN) {
@ -547,7 +550,7 @@ public class CameraSession {
public int getDisplayOrientation() {
try {
Camera.getCameraInfo(cameraInfo.getCameraId(), info);
updateCameraInfo();
return getDisplayOrientation(info, true);
} catch (Exception e) {
FileLog.e(e);

View File

@ -42,6 +42,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.util.Log;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.Surface;
@ -128,24 +129,24 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
private float[] mSTMatrix = new float[16];
private float[] moldSTMatrix = new float[16];
private static final String VERTEX_SHADER =
"uniform mat4 uMVPMatrix;\n" +
"uniform mat4 uSTMatrix;\n" +
"attribute vec4 aPosition;\n" +
"attribute vec4 aTextureCoord;\n" +
"varying vec2 vTextureCoord;\n" +
"void main() {\n" +
" gl_Position = uMVPMatrix * aPosition;\n" +
" vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
"}\n";
"uniform mat4 uMVPMatrix;\n" +
"uniform mat4 uSTMatrix;\n" +
"attribute vec4 aPosition;\n" +
"attribute vec4 aTextureCoord;\n" +
"varying vec2 vTextureCoord;\n" +
"void main() {\n" +
" gl_Position = uMVPMatrix * aPosition;\n" +
" vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
"}\n";
private static final String FRAGMENT_SCREEN_SHADER =
"#extension GL_OES_EGL_image_external : require\n" +
"precision lowp float;\n" +
"varying vec2 vTextureCoord;\n" +
"uniform samplerExternalOES sTexture;\n" +
"void main() {\n" +
" gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
"}\n";
"#extension GL_OES_EGL_image_external : require\n" +
"precision lowp float;\n" +
"varying vec2 vTextureCoord;\n" +
"uniform samplerExternalOES sTexture;\n" +
"void main() {\n" +
" gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
"}\n";
private FloatBuffer vertexBuffer;
private FloatBuffer textureBuffer;
@ -272,11 +273,24 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
}
}
private int measurementsCount = 0;
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
measurementsCount = 0;
}
private int lastWidth = -1, lastHeight = -1;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec),
height = MeasureSpec.getSize(heightMeasureSpec);
if (previewSize != null && cameraSession != null) {
int frameWidth, frameHeight;
cameraSession.updateRotation();
if ((lastWidth != width || lastHeight != height) && measurementsCount > 1) {
cameraSession.updateRotation();
}
measurementsCount++;
if (cameraSession.getWorldAngle() == 90 || cameraSession.getWorldAngle() == 270) {
frameWidth = previewSize.getWidth();
frameHeight = previewSize.getHeight();
@ -290,6 +304,8 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
checkPreviewMatrix();
lastWidth = width;
lastHeight = height;
}
public float getTextureHeight(float width, float height) {
@ -371,7 +387,6 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
cameraThread = new CameraGLThread(surface);
checkPreviewMatrix();
}
}
private void updateCameraInfoSize() {
@ -447,7 +462,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
if (cameraThread != null) {
cameraThread.shutdown(0);
cameraThread = null;
cameraThread.postRunnable(() -> this.cameraThread = null);
}
if (cameraSession != null) {
CameraController.getInstance().close(cameraSession, null, null);
@ -473,6 +488,17 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
clipBottom = value;
}
private final Runnable updateRotationMatrix = () -> {
final CameraGLThread cameraThread = this.cameraThread;
if (cameraThread != null && cameraThread.currentSession != null) {
int rotationAngle = cameraThread.currentSession.getWorldAngle();
android.opengl.Matrix.setIdentityM(mMVPMatrix, 0);
if (rotationAngle != 0) {
android.opengl.Matrix.rotateM(mMVPMatrix, 0, rotationAngle, 0, 0, 1);
}
}
};
private void checkPreviewMatrix() {
if (previewSize == null) {
return;
@ -490,16 +516,11 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
matrix.invert(this.matrix);
if (cameraThread != null) {
cameraThread.postRunnable(() -> {
final CameraGLThread cameraThread = this.cameraThread;
if (cameraThread != null && cameraThread.currentSession != null) {
int rotationAngle = cameraThread.currentSession.getWorldAngle();
android.opengl.Matrix.setIdentityM(mMVPMatrix, 0);
if (rotationAngle != 0) {
android.opengl.Matrix.rotateM(mMVPMatrix, 0, rotationAngle, 0, 0, 1);
}
}
});
if (!cameraThread.isReady()) {
updateRotationMatrix.run();
} else {
cameraThread.postRunnable(updateRotationMatrix);
}
}
}
@ -1034,7 +1055,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
}
case DO_SETSESSION_MESSAGE: {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("CameraView " + "set gl rednderer session");
FileLog.d("CameraView " + "set gl renderer session");
}
CameraSession newSession = (CameraSession) inputMessage.obj;
if (currentSession != newSession) {
@ -1539,7 +1560,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
if (currentTimestamp != 0) {
dt = (System.currentTimeMillis() - lastCommitedFrameTime) * 1000000;
} else {
dt = 0;
dt = 0;
}
} else {
dt = (timestampNanos - lastTimestamp);

View File

@ -32,12 +32,16 @@ import javax.crypto.Mac;
public final class FingerprintManagerCompatApi23 {
private static FingerprintManager getFingerprintManager(Context ctx) {
return ctx.getSystemService(FingerprintManager.class);
return (FingerprintManager) ctx.getSystemService(Context.FINGERPRINT_SERVICE);
}
public static boolean hasEnrolledFingerprints(Context context) {
try {
return getFingerprintManager(context).hasEnrolledFingerprints();
FingerprintManager fingerprintManager = getFingerprintManager(context);
if (fingerprintManager == null) {
return false;
}
return fingerprintManager.hasEnrolledFingerprints();
} catch (Exception e) {
FileLog.e(e);
}
@ -46,7 +50,11 @@ public final class FingerprintManagerCompatApi23 {
public static boolean isHardwareDetected(Context context) {
try {
return getFingerprintManager(context).isHardwareDetected();
FingerprintManager fingerprintManager = getFingerprintManager(context);
if (fingerprintManager == null) {
return false;
}
return fingerprintManager.isHardwareDetected();
} catch (Exception e) {
FileLog.e(e);
}

View File

@ -1,46 +1,24 @@
package org.telegram.messenger.video;
import android.annotation.TargetApi;
import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.opengl.EGL14;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.os.Build;
import android.view.Surface;
import com.google.android.exoplayer2.util.Log;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.BuildVars;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.NotificationsController;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.messenger.VideoEditedInfo;
import org.telegram.ui.Components.Bulletin;
import org.telegram.ui.Components.BulletinFactory;
import org.telegram.ui.LaunchActivity;
import java.io.File;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
public class MediaCodecVideoConvertor {
private MP4Builder mediaMuxer;
@ -166,7 +144,7 @@ public class MediaCodecVideoConvertor {
inputSurface.makeCurrent();
encoder.start();
outputSurface = new OutputSurface(savedFilterState, videoPath, paintPath, mediaEntities, null, resultWidth, resultHeight, rotationValue, framerate, true);
outputSurface = new OutputSurface(savedFilterState, videoPath, paintPath, mediaEntities, null, resultWidth, resultHeight, originalWidth, originalHeight, rotationValue, framerate, true);
ByteBuffer[] encoderOutputBuffers = null;
ByteBuffer[] encoderInputBuffers = null;
@ -337,6 +315,7 @@ public class MediaCodecVideoConvertor {
AudioRecoder audioRecoder = null;
ByteBuffer audioBuffer = null;
boolean copyAudioBuffer = true;
long lastFramePts = -1;
if (videoIndex >= 0) {
MediaCodec decoder = null;
@ -421,8 +400,8 @@ public class MediaCodecVideoConvertor {
encoder.start();
decoder = MediaCodec.createDecoderByType(videoFormat.getString(MediaFormat.KEY_MIME));
outputSurface = new OutputSurface(savedFilterState, null, paintPath, mediaEntities, cropState, resultWidth, resultHeight, rotationValue, framerate, false);
outputSurface.changeFragmentShader(createFragmentShader(originalWidth, originalHeight, resultWidth, resultHeight));
outputSurface = new OutputSurface(savedFilterState, null, paintPath, mediaEntities, cropState, resultWidth, resultHeight, originalWidth, originalHeight, rotationValue, framerate, false);
outputSurface.changeFragmentShader(createFragmentShader(originalWidth, originalHeight, resultWidth, resultHeight, true), createFragmentShader(originalWidth, originalHeight, resultWidth, resultHeight, false));
decoder.configure(videoFormat, outputSurface.getSurface(), null, 0);
decoder.start();
@ -702,6 +681,9 @@ public class MediaCodecVideoConvertor {
decoder.flush();
flushed = true;
}
if (lastFramePts > 0 && info.presentationTimeUs - lastFramePts < frameDelta && (info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) == 0) {
doRender = false;
}
trueStartTime = avatarStartTime >= 0 ? avatarStartTime : startTime;
if (trueStartTime > 0 && videoTime == -1) {
if (originalPresentationTime < trueStartTime) {
@ -725,6 +707,7 @@ public class MediaCodecVideoConvertor {
decoder.releaseOutputBuffer(decoderStatus, doRender);
}
if (doRender) {
lastFramePts = info.presentationTimeUs;
if (avatarStartTime >= 0) {
minPresentationTime = Math.max(minPresentationTime, info.presentationTimeUs);
}
@ -983,41 +966,52 @@ public class MediaCodecVideoConvertor {
final int srcWidth,
final int srcHeight,
final int dstWidth,
final int dstHeight) {
final float kernelSizeX = Math.max(2f, (float) srcWidth / (float) dstWidth);
final float kernelSizeY = Math.max(2f, (float) srcHeight / (float) dstHeight);
final int dstHeight, boolean external) {
final String shader;
final int kernelRadiusX = (int) Math.ceil(kernelSizeX - .1f) / 2;
final int kernelRadiusY = (int) Math.ceil(kernelSizeY - .1f) / 2;
final float stepX = kernelSizeX / (1 + 2 * kernelRadiusX) * (1f / srcWidth);
final float stepY = kernelSizeY / (1 + 2 * kernelRadiusY) * (1f / srcHeight);
final float sum = (1 + 2 * kernelRadiusX) * (1 + 2 * kernelRadiusY);
final StringBuilder colorLoop = new StringBuilder();
for (int i = -kernelRadiusX; i <= kernelRadiusX; i++) {
for (int j = -kernelRadiusY; j <= kernelRadiusY; j++) {
if (i != 0 || j != 0) {
colorLoop.append(" + texture2D(sTexture, vTextureCoord.xy + vec2(")
.append(i * stepX).append(", ").append(j * stepY).append("))\n");
}
}
final float kernelSize = Utilities.clamp((float) (Math.max(srcWidth, srcHeight) / (float) Math.max(dstHeight, dstWidth)) * 0.8f, 2f, 1f);
final int kernelRadius = (int) kernelSize;
FileLog.d("source size " + srcWidth + "x" + srcHeight + " dest size " + dstWidth + dstHeight + " kernelRadius " + kernelRadius);
if (external) {
return "#extension GL_OES_EGL_image_external : require\n" +
"precision mediump float;\n" +
"varying vec2 vTextureCoord;\n" +
"const float kernel = " + kernelRadius + ".0;\n" +
"const float pixelSizeX = 1.0 / " + srcWidth + ".0;\n" +
"const float pixelSizeY = 1.0 / " + srcHeight + ".0;\n" +
"uniform samplerExternalOES sTexture;\n" +
"void main() {\n" +
"vec3 accumulation = vec3(0);\n" +
"vec3 weightsum = vec3(0);\n" +
"for (float x = -kernel; x <= kernel; x++){\n" +
" for (float y = -kernel; y <= kernel; y++){\n" +
" accumulation += texture2D(sTexture, vTextureCoord + vec2(x * pixelSizeX, y * pixelSizeY)).xyz;\n" +
" weightsum += 1.0;\n" +
" }\n" +
"}\n" +
"gl_FragColor = vec4(accumulation / weightsum, 1.0);\n" +
"}\n";
} else {
return "precision mediump float;\n" +
"varying vec2 vTextureCoord;\n" +
"const float kernel = " + kernelRadius + ".0;\n" +
"const float pixelSizeX = 1.0 / " + srcHeight + ".0;\n" +
"const float pixelSizeY = 1.0 / " + srcWidth + ".0;\n" +
"uniform sampler2D sTexture;\n" +
"void main() {\n" +
"vec3 accumulation = vec3(0);\n" +
"vec3 weightsum = vec3(0);\n" +
"for (float x = -kernel; x <= kernel; x++){\n" +
" for (float y = -kernel; y <= kernel; y++){\n" +
" accumulation += texture2D(sTexture, vTextureCoord + vec2(x * pixelSizeX, y * pixelSizeY)).xyz;\n" +
" weightsum += 1.0;\n" +
" }\n" +
"}\n" +
"gl_FragColor = vec4(accumulation / weightsum, 1.0);\n" +
"}\n";
}
shader =
"#extension GL_OES_EGL_image_external : require\n" +
"precision mediump float;\n" + // highp here doesn't seem to matter
"varying vec2 vTextureCoord;\n" +
"uniform samplerExternalOES sTexture;\n" +
"void main() {\n" +
" gl_FragColor = (texture2D(sTexture, vTextureCoord)\n" +
colorLoop.toString() +
" ) / " + sum + ";\n" +
"}\n";
return shader;
}
public class ConversionCanceledException extends RuntimeException{
public class ConversionCanceledException extends RuntimeException {
public ConversionCanceledException() {
super("canceled conversion");

View File

@ -36,8 +36,8 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
private boolean mFrameAvailable;
private TextureRenderer mTextureRender;
public OutputSurface(MediaController.SavedFilterState savedFilterState, String imagePath, String paintPath, ArrayList<VideoEditedInfo.MediaEntity> mediaEntities, MediaController.CropState cropState, int w, int h, int rotation, float fps, boolean photo) {
mTextureRender = new TextureRenderer(savedFilterState, imagePath, paintPath, mediaEntities, cropState, w, h, rotation, fps, photo);
public OutputSurface(MediaController.SavedFilterState savedFilterState, String imagePath, String paintPath, ArrayList<VideoEditedInfo.MediaEntity> mediaEntities, MediaController.CropState cropState, int w, int h, int originalW, int originalH, int rotation, float fps, boolean photo) {
mTextureRender = new TextureRenderer(savedFilterState, imagePath, paintPath, mediaEntities, cropState, w, h, originalW, originalH, rotation, fps, photo);
mTextureRender.surfaceCreated();
mSurfaceTexture = new SurfaceTexture(mTextureRender.getTextureId());
mSurfaceTexture.setOnFrameAvailableListener(this);
@ -166,7 +166,7 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
}
}
public void changeFragmentShader(String fragmentShader) {
mTextureRender.changeFragmentShader(fragmentShader);
public void changeFragmentShader(String fragmentExternalShader, String fragmentShader) {
mTextureRender.changeFragmentShader(fragmentExternalShader, fragmentShader);
}
}

View File

@ -131,7 +131,7 @@ public class TextureRenderer {
private boolean firstFrame = true;
public TextureRenderer(MediaController.SavedFilterState savedFilterState, String image, String paint, ArrayList<VideoEditedInfo.MediaEntity> entities, MediaController.CropState cropState, int w, int h, int rotation, float fps, boolean photo) {
public TextureRenderer(MediaController.SavedFilterState savedFilterState, String image, String paint, ArrayList<VideoEditedInfo.MediaEntity> entities, MediaController.CropState cropState, int w, int h, int originalWidth, int originalHeight, int rotation, float fps, boolean photo) {
isPhoto = photo;
float[] texData = {
@ -164,8 +164,10 @@ public class TextureRenderer {
filterShaders = new FilterShaders(true);
filterShaders.setDelegate(FilterShaders.getFilterShadersDelegate(savedFilterState));
}
transformedWidth = originalWidth = w;
transformedHeight = originalHeight = h;
transformedWidth = w;
transformedHeight = h;
this.originalWidth = originalWidth;
this.originalHeight = originalHeight;
imagePath = image;
paintPath = paint;
mediaEntities = entities;
@ -715,8 +717,12 @@ public class TextureRenderer {
}
}
public void changeFragmentShader(String fragmentShader) {
public void changeFragmentShader(String fragmentExternalShader, String fragmentShader) {
GLES20.glDeleteProgram(mProgram[0]);
mProgram[0] = createProgram(VERTEX_SHADER, fragmentShader);
mProgram[0] = createProgram(VERTEX_SHADER, fragmentExternalShader);
if (mProgram.length > 1) {
mProgram[1] = createProgram(VERTEX_SHADER, fragmentShader);
}
}
}

View File

@ -15,7 +15,7 @@ import java.util.List;
public final class Instance {
public static final List<String> AVAILABLE_VERSIONS = Build.VERSION.SDK_INT >= 18 ? Arrays.asList("3.0.0", "2.7.7", "2.4.4") : Arrays.asList("2.4.4");
public static final List<String> AVAILABLE_VERSIONS = Build.VERSION.SDK_INT >= 18 ? Arrays.asList("4.0.0", "3.0.0", "2.7.7", "2.4.4") : Arrays.asList("2.4.4");
public static final int AUDIO_STATE_MUTED = 0;
public static final int AUDIO_STATE_ACTIVE = 1;

View File

@ -94,6 +94,7 @@ import org.telegram.messenger.FileLoader;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.ImageLoader;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.MessagesStorage;
@ -3535,11 +3536,28 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa
if (BuildVars.LOGS_ENABLED) {
FileLog.d("configureDeviceForCall, route to set = " + audioRouteToSet);
}
if (Build.VERSION.SDK_INT >= 21) {
WebRtcAudioTrack.setAudioTrackUsageAttribute(hasRtmpStream() ? AudioAttributes.USAGE_MEDIA : AudioAttributes.USAGE_VOICE_COMMUNICATION);
WebRtcAudioTrack.setAudioStreamType(hasRtmpStream() ? AudioManager.USE_DEFAULT_STREAM_TYPE : AudioManager.STREAM_VOICE_CALL);
}
needPlayEndSound = true;
AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
if (!USE_CONNECTION_SERVICE) {
Utilities.globalQueue.postRunnable(() -> {
try {
if (hasRtmpStream()) {
am.setMode(AudioManager.MODE_NORMAL);
am.setBluetoothScoOn(false);
AndroidUtilities.runOnUIThread(() -> {
if (!MediaController.getInstance().isMessagePaused()) {
MediaController.getInstance().pauseMessage(MediaController.getInstance().getPlayingMessageObject());
}
});
return;
}
am.setMode(AudioManager.MODE_IN_COMMUNICATION);
} catch (Exception e) {
FileLog.e(e);
@ -3687,20 +3705,24 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa
if (BuildVars.LOGS_ENABLED) {
FileLog.d("SCO already active, setting audio routing");
}
am.setSpeakerphoneOn(false);
am.setBluetoothScoOn(true);
if (!hasRtmpStream()) {
am.setSpeakerphoneOn(false);
am.setBluetoothScoOn(true);
}
} else {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("startBluetoothSco");
}
needSwitchToBluetoothAfterScoActivates = true;
AndroidUtilities.runOnUIThread(() -> {
try {
am.startBluetoothSco();
} catch (Throwable ignore) {
if (!hasRtmpStream()) {
needSwitchToBluetoothAfterScoActivates = true;
AndroidUtilities.runOnUIThread(() -> {
try {
am.startBluetoothSco();
} catch (Throwable ignore) {
}
}, 500);
}
}, 500);
}
}
} else {
bluetoothScoActive = false;
@ -4232,6 +4254,9 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa
}
public void updateOutputGainControlState() {
if (hasRtmpStream()) {
return;
}
if (tgVoip[CAPTURE_DEVICE_CAMERA] != null) {
if (!USE_CONNECTION_SERVICE) {
final AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);

View File

@ -503,7 +503,7 @@ public class ActionBar extends FrameLayout {
if (blurredBackground && drawBlur) {
rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
blurScrimPaint.setColor(actionModeColor);
contentView.drawBlur(canvas, 0, rectTmp, blurScrimPaint, true);
contentView.drawBlurRect(canvas, 0, rectTmp, blurScrimPaint, true);
}
super.dispatchDraw(canvas);
}
@ -1589,7 +1589,7 @@ public class ActionBar extends FrameLayout {
if (blurredBackground && actionBarColor != Color.TRANSPARENT) {
rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
blurScrimPaint.setColor(actionBarColor);
contentView.drawBlur(canvas, 0, rectTmp, blurScrimPaint, true);
contentView.drawBlurRect(canvas, getY(), rectTmp, blurScrimPaint, true);
}
super.dispatchDraw(canvas);
}

View File

@ -1347,8 +1347,12 @@ public class ActionBarMenuItem extends FrameLayout {
}
}
};
clearButton.setImageDrawable(progressDrawable = new CloseProgressDrawable2());
clearButton.setColorFilter(new PorterDuffColorFilter(parentMenu.parentActionBar.itemsColor, PorterDuff.Mode.MULTIPLY));
clearButton.setImageDrawable(progressDrawable = new CloseProgressDrawable2() {
@Override
public int getCurrentColor() {
return parentMenu.parentActionBar.itemsColor;
}
});
clearButton.setScaleType(ImageView.ScaleType.CENTER);
clearButton.setAlpha(0.0f);
clearButton.setRotation(45);

View File

@ -103,6 +103,7 @@ public class ActionBarPopupWindow extends PopupWindow {
private int gapStartY = -1000000;
private int gapEndY = -1000000;
private Rect bgPaddings = new Rect();
private onSizeChangedListener onSizeChangedListener;
private PopupSwipeBackLayout swipeBackLayout;
private ScrollView scrollView;
@ -250,50 +251,61 @@ public class ActionBarPopupWindow extends PopupWindow {
@Keep
public void setBackScaleX(float value) {
backScaleX = value;
invalidate();
if (backScaleY != value) {
backScaleY = value;
backScaleX = value;
invalidate();
if (onSizeChangedListener != null) {
onSizeChangedListener.onSizeChanged();
}
}
}
@Keep
public void setBackScaleY(float value) {
backScaleY = value;
if (animationEnabled) {
int height = getMeasuredHeight() - AndroidUtilities.dp(16);
if (shownFromBotton) {
for (int a = lastStartedChild; a >= 0; a--) {
View child = getItemAt(a);
if (child.getVisibility() != VISIBLE) {
continue;
if (backScaleY != value) {
backScaleY = value;
if (animationEnabled) {
int height = getMeasuredHeight() - AndroidUtilities.dp(16);
if (shownFromBotton) {
for (int a = lastStartedChild; a >= 0; a--) {
View child = getItemAt(a);
if (child.getVisibility() != VISIBLE) {
continue;
}
Integer position = positions.get(child);
if (position != null && height - (position * AndroidUtilities.dp(48) + AndroidUtilities.dp(32)) > value * height) {
break;
}
lastStartedChild = a - 1;
startChildAnimation(child);
}
Integer position = positions.get(child);
if (position != null && height - (position * AndroidUtilities.dp(48) + AndroidUtilities.dp(32)) > value * height) {
break;
} else {
int count = getItemsCount();
int h = 0;
for (int a = 0; a < count; a++) {
View child = getItemAt(a);
if (child.getVisibility() != VISIBLE) {
continue;
}
h += child.getMeasuredHeight();
if (a < lastStartedChild) {
continue;
}
Integer position = positions.get(child);
if (position != null && h - AndroidUtilities.dp(24) > value * height) {
break;
}
lastStartedChild = a + 1;
startChildAnimation(child);
}
lastStartedChild = a - 1;
startChildAnimation(child);
}
} else {
int count = getItemsCount();
int h = 0;
for (int a = 0; a < count; a++) {
View child = getItemAt(a);
if (child.getVisibility() != VISIBLE) {
continue;
}
h += child.getMeasuredHeight();
if (a < lastStartedChild) {
continue;
}
Integer position = positions.get(child);
if (position != null && h - AndroidUtilities.dp(24) > value * height) {
break;
}
lastStartedChild = a + 1;
startChildAnimation(child);
}
}
invalidate();
if (onSizeChangedListener != null) {
onSizeChangedListener.onSizeChanged();
}
}
invalidate();
}
public void setBackgroundDrawable(Drawable drawable) {
@ -465,6 +477,14 @@ public class ActionBarPopupWindow extends PopupWindow {
Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null;
return color != null ? color : Theme.getColor(key);
}
public void setOnSizeChangedListener(ActionBarPopupWindow.onSizeChangedListener onSizeChangedListener) {
this.onSizeChangedListener = onSizeChangedListener;
}
public int getVisibleHeight() {
return (int) (getMeasuredHeight() * backScaleY);
}
}
public ActionBarPopupWindow() {
@ -742,4 +762,8 @@ public class ActionBarPopupWindow extends PopupWindow {
public void setEmptyOutAnimation(long time) {
outEmptyTime = time;
}
public interface onSizeChangedListener {
void onSizeChanged();
}
}

View File

@ -20,7 +20,6 @@ import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.UserConfig;
import org.telegram.ui.Components.CubicBezierInterpolator;
import java.util.ArrayList;

View File

@ -623,7 +623,7 @@ public abstract class BaseFragment {
return getAccountInstance().getSecretChatHelper();
}
protected DownloadController getDownloadController() {
public DownloadController getDownloadController() {
return getAccountInstance().getDownloadController();
}

View File

@ -32,6 +32,7 @@ import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.Emoji;
import org.telegram.ui.Cells.DialogCell;
import org.telegram.ui.Components.EmptyStubSpan;
import org.telegram.ui.Components.StaticLayoutEx;
@ -100,6 +101,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
private List<SpoilerEffect> spoilers = new ArrayList<>();
private Stack<SpoilerEffect> spoilersPool = new Stack<>();
private Path path = new Path();
private boolean usaAlphaForEmoji;
public SimpleTextView(Context context) {
super(context);
@ -648,6 +650,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
}
if (layout != null) {
Emoji.emojiDrawingUseAlpha = usaAlphaForEmoji;
if (wrapBackgroundDrawable != null) {
int cx = (int) (offsetX + textOffsetX - scrollingOffset) + textWidth / 2;
int w = Math.max(textWidth + getPaddingLeft() + getPaddingRight(), minWidth);
@ -712,6 +715,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
canvas.restore();
}
updateScrollAnimation();
Emoji.emojiDrawingUseAlpha = true;
}
if (fade) {
canvas.restoreToCount(restore);

View File

@ -161,7 +161,7 @@ public class Theme {
private RectF rect = new RectF();
private Matrix matrix = new Matrix();
private int currentType;
private boolean isSelected;
public boolean isSelected;
private Path path;
private Rect backupRect = new Rect();
@ -1531,10 +1531,7 @@ public class Theme {
if (info != null && info.emoticon != null && !isDarkTheme) {
currentColors.remove(key_chat_selectedBackground);
int gradientAverageColor = 0;
if (gradientAverageColor == 0) {
gradientAverageColor = averageColor(currentColors, key_chat_wallpaper_gradient_to1, key_chat_wallpaper_gradient_to2, key_chat_wallpaper_gradient_to3);
}
int gradientAverageColor = averageColor(currentColors, key_chat_wallpaper_gradient_to1, key_chat_wallpaper_gradient_to2, key_chat_wallpaper_gradient_to3);
if (gradientAverageColor == 0) {
gradientAverageColor = averageColor(currentColors, key_chat_wallpaper);
}
@ -1546,13 +1543,18 @@ public class Theme {
if (outBubble == null) {
outBubble = getColor(key_chat_outBubble);
}
currentColors.put(key_chat_outBubbleSelectedOverlay, bubbleSelectedOverlay(outBubble, gradientAverageColor));
int outOverlay = bubbleSelectedOverlay(outBubble, gradientAverageColor);
currentColors.put(key_chat_outBubbleSelectedOverlay, outOverlay);
currentColors.put(key_chat_outBubbleGradientSelectedOverlay, outOverlay);
currentColors.put(key_chat_outBubbleSelected, Theme.blendOver(outBubble, outOverlay));
Integer inBubble = currentColors.get(key_chat_inBubble);
if (inBubble == null) {
inBubble = getColor(key_chat_inBubble);
}
currentColors.put(key_chat_inBubbleSelectedOverlay, bubbleSelectedOverlay(inBubble, accentColor));
int inOverlay = bubbleSelectedOverlay(inBubble, accentColor);
currentColors.put(key_chat_inBubbleSelectedOverlay, inOverlay);
currentColors.put(key_chat_inBubbleSelected, Theme.blendOver(inBubble, inOverlay));
}
return !isMyMessagesGradientColorsNear;
@ -1686,6 +1688,21 @@ public class Theme {
}
}
public static int blendOver(int y, int x) {
// over operator: https://en.wikipedia.org/wiki/Alpha_compositing#Description
float ax = Color.alpha(x) / 255f,
ay = Color.alpha(y) / 255f,
az = (ax + ay * (1 - ax));
if (az == 0f)
return 0;
return Color.argb(
(int) (az * 255),
(int) ((Color.red(x) * ax + Color.red(y) * ay * (1 - ax)) / az),
(int) ((Color.green(x) * ax + Color.green(y) * ay * (1 - ax)) / az),
(int) ((Color.blue(x) * ax + Color.blue(y) * ay * (1 - ax)) / az)
);
}
public static class OverrideWallpaperInfo {
public String fileName = "";
public String originalFileName = "";

View File

@ -62,6 +62,12 @@ public class FiltersView extends RecyclerListView {
public final static int FILTER_TYPE_DATE = 6;
public final static int FILTER_TYPE_ARCHIVE = 7;
public final static int FILTER_INDEX_MEDIA = 0;
public final static int FILTER_INDEX_LINKS = 1;
public final static int FILTER_INDEX_FILES = 2;
public final static int FILTER_INDEX_MUSIC = 3;
public final static int FILTER_INDEX_VOICE = 4;
public final static MediaFilterData[] filters = new MediaFilterData[]{
new MediaFilterData(R.drawable.search_media, R.drawable.search_media_filled, LocaleController.getString("SharedMediaTab2", R.string.SharedMediaTab2), new TLRPC.TL_inputMessagesFilterPhotoVideo(), FILTER_TYPE_MEDIA),
new MediaFilterData(R.drawable.search_links, R.drawable.search_links_filled, LocaleController.getString("SharedLinksTab2", R.string.SharedLinksTab2), new TLRPC.TL_inputMessagesFilterUrl(), FILTER_TYPE_LINKS),

View File

@ -167,7 +167,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement
};
public MentionsAdapter(Context context, boolean darkTheme, long did, int threadMessageId, MentionsAdapterDelegate mentionsAdapterDelegate, Theme.ResourcesProvider resourcesProvider) {
setHasStableIds(true);
// setHasStableIds(true);
this.resourcesProvider = resourcesProvider;
mContext = context;
delegate = mentionsAdapterDelegate;
@ -252,6 +252,41 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement
}
}
// public long getItemIdInternal(int position) {
// try {
// if (stickers != null) {
// return stickers.get(position).sticker.id;
// } else if (foundContextBot != null && !inlineMediaEnabled) {
// return foundContextBot.id;
// } else if (searchResultBotContext != null) {
// if (position == 0 && searchResultBotContextSwitch != null) {
// return -1;
// }
// return searchResultBotContext.get(position - (searchResultBotContextSwitch != null ? 1 : 0)).query_id;
// } else if (searchResultUsernames != null) {
// TLObject obj = searchResultUsernames.get(position);
// if (obj instanceof TLRPC.User) {
// return ((TLRPC.User) obj).id;
// } else if (obj instanceof TLRPC.Chat) {
// return ((TLRPC.Chat) obj).id;
// }
// return obj.hashCode();
// } else if (searchResultHashtags != null) {
// return searchResultHashtags.get(position).hashCode();
// } else if (searchResultCommands != null) {
// return searchResultCommands.get(position).hashCode();
// } else if (searchResultSuggestions != null) {
// return searchResultSuggestions.get(position).emoji.hashCode();
// }
// } catch (Exception ignore) {}
// return 0;
// }
//
// @Override
// public long getItemId(int position) {
// return Objects.hash(getItemIdInternal(position), getItemCount() < 5 ? getItemCount() - position : position);
// }
private boolean checkStickerFilesExistAndDownload() {
if (stickers == null) {
return false;

View File

@ -3466,8 +3466,12 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
}
}
};
clearButton.setImageDrawable(new CloseProgressDrawable2());
clearButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.MULTIPLY));
clearButton.setImageDrawable(new CloseProgressDrawable2() {
@Override
protected int getCurrentColor() {
return Theme.getColor(Theme.key_windowBackgroundWhiteBlackText);
}
});
clearButton.setScaleType(ImageView.ScaleType.CENTER);
clearButton.setAlpha(0.0f);
clearButton.setRotation(45);

View File

@ -32,7 +32,6 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.DownloadController;
import org.telegram.messenger.FileLoader;
import org.telegram.messenger.ImageLocation;
@ -53,7 +52,6 @@ import org.telegram.ui.ActionBar.SimpleTextView;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Components.AlertsCreator;
import org.telegram.ui.Components.BulletinFactory;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.Easings;
import org.telegram.ui.Components.HideViewAfterAnimation;
@ -61,11 +59,9 @@ import org.telegram.ui.Components.HintView;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.SharedMediaLayout;
import org.telegram.ui.Components.Tooltip;
import java.time.YearMonth;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
public class CalendarActivity extends BaseFragment {
@ -1421,4 +1417,10 @@ public class CalendarActivity extends BaseFragment {
}
return super.onBackPressed();
}
@Override
public boolean isLightStatusBar() {
int color = Theme.getColor(Theme.key_windowBackgroundWhite, null, true);
return ColorUtils.calculateLuminance(color) > 0.7f;
}
}

View File

@ -66,6 +66,7 @@ import org.telegram.messenger.MrzRecognizer;
import org.telegram.messenger.R;
import org.telegram.messenger.SendMessagesHelper;
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.CameraView;
@ -116,16 +117,15 @@ public class CameraScanActivity extends BaseFragment {
private long recognizedStart;
private int recognizeFailed = 0;
private int recognizeIndex = 0;
private ValueAnimator recognizedAnimator;
private String recognizedText;
private int sps; // samples per second
private int sps; // samples per second (already when recognized)
private boolean qrLoading = false;
private boolean qrLoaded = false;
private QRCodeReader qrReader;
private BarcodeDetector visionQrReader;
private QRCodeReader qrReader = null;
private BarcodeDetector visionQrReader = null;
private boolean needGalleryButton;
@ -196,26 +196,27 @@ public class CameraScanActivity extends BaseFragment {
@Override
public void dismiss() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
final Window window = fragment.getParentActivity().getWindow();
fragment.updateNavigationBarColor(fragment.wasNavigationBarColor);
AndroidUtilities.setLightNavigationBar(window, fragment.wasLightNavigationBar);
}
super.dismiss();
actionBarLayout[0] = null;
}
};
AndroidUtilities.setLightNavigationBar(bottomSheet.getWindow(), false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
bottomSheet.getWindow().setNavigationBarColor(0xff000000);
}
bottomSheet.getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
bottomSheet.show();
return actionBarLayout;
}
public CameraScanActivity(int type) {
super();
CameraController.getInstance().initCamera(null);
currentType = type;
if (isQr()) {
qrReader = new QRCodeReader();
visionQrReader = new BarcodeDetector.Builder(ApplicationLoader.applicationContext).setBarcodeFormats(Barcode.QR_CODE).build();
Utilities.globalQueue.postRunnable(() -> {
qrReader = new QRCodeReader();
visionQrReader = new BarcodeDetector.Builder(ApplicationLoader.applicationContext).setBarcodeFormats(Barcode.QR_CODE).build();
});
}
switch (SharedConfig.getDevicePerformanceClass()) {
@ -231,37 +232,6 @@ public class CameraScanActivity extends BaseFragment {
}
}
private int wasNavigationBarColor;
private boolean wasLightNavigationBar;
private float navigationBarColorT = 0;
private ValueAnimator navigationBarColorAnimator;
@Override
public void onResume() {
final Window window = getParentActivity().getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
wasNavigationBarColor = window.getNavigationBarColor();
wasLightNavigationBar = AndroidUtilities.getLightNavigationBar(window);
AndroidUtilities.setLightNavigationBar(window, false);
updateNavigationBarColor(0xff000000);
}
super.onResume();
}
protected void updateNavigationBarColor(int color) {
if (Build.VERSION.SDK_INT >= 21) {
if (navigationBarColorAnimator != null) {
navigationBarColorAnimator.cancel();
}
final Window window = getParentActivity().getWindow();
navigationBarColorAnimator = ValueAnimator.ofArgb(window.getNavigationBarColor(), color);
navigationBarColorAnimator.addUpdateListener(a -> window.setNavigationBarColor((int) a.getAnimatedValue()));
navigationBarColorAnimator.setDuration(200);
navigationBarColorAnimator.setInterpolator(CubicBezierInterpolator.EASE_BOTH);
navigationBarColorAnimator.start();
}
}
@Override
public void onFragmentDestroy() {
super.onFragmentDestroy();
@ -304,9 +274,13 @@ public class CameraScanActivity extends BaseFragment {
int height = MeasureSpec.getSize(heightMeasureSpec);
actionBar.measure(widthMeasureSpec, heightMeasureSpec);
if (currentType == TYPE_MRZ) {
cameraView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((int) (width * 0.704f), MeasureSpec.EXACTLY));
if (cameraView != null) {
cameraView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((int) (width * 0.704f), MeasureSpec.EXACTLY));
}
} else {
cameraView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
if (cameraView != null) {
cameraView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
}
recognizedMrzView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.UNSPECIFIED));
if (galleryButton != null) {
galleryButton.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(60), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(60), MeasureSpec.EXACTLY));
@ -326,34 +300,38 @@ public class CameraScanActivity extends BaseFragment {
int y = 0;
if (currentType == TYPE_MRZ) {
cameraView.layout(0, y, cameraView.getMeasuredWidth(), y + cameraView.getMeasuredHeight());
if (cameraView != null) {
cameraView.layout(0, y, cameraView.getMeasuredWidth(), y + cameraView.getMeasuredHeight());
}
recognizedMrzView.setTextSize(TypedValue.COMPLEX_UNIT_PX, height / 22);
recognizedMrzView.setPadding(0, 0, 0, height / 15);
y = (int) (height * 0.65f);
titleTextView.layout(AndroidUtilities.dp(36), y, AndroidUtilities.dp(36) + titleTextView.getMeasuredWidth(), y + titleTextView.getMeasuredHeight());
recognizedMrzView.setTextSize(TypedValue.COMPLEX_UNIT_PX, cameraView.getMeasuredHeight() / 22);
recognizedMrzView.setPadding(0, 0, 0, cameraView.getMeasuredHeight() / 15);
} else {
actionBar.layout(0, 0, actionBar.getMeasuredWidth(), actionBar.getMeasuredHeight());
cameraView.layout(0, 0, cameraView.getMeasuredWidth(), cameraView.getMeasuredHeight());
int size = (int) (Math.min(cameraView.getWidth(), cameraView.getHeight()) / 1.5f);
if (cameraView != null) {
cameraView.layout(0, 0, cameraView.getMeasuredWidth(), cameraView.getMeasuredHeight());
}
int size = (int) (Math.min(width, height) / 1.5f);
if (currentType == TYPE_QR) {
y = (cameraView.getMeasuredHeight() - size) / 2 - titleTextView.getMeasuredHeight() - AndroidUtilities.dp(30);
y = (height - size) / 2 - titleTextView.getMeasuredHeight() - AndroidUtilities.dp(30);
} else {
y = (cameraView.getMeasuredHeight() - size) / 2 - titleTextView.getMeasuredHeight() - AndroidUtilities.dp(64);
y = (height - size) / 2 - titleTextView.getMeasuredHeight() - AndroidUtilities.dp(64);
}
titleTextView.layout(AndroidUtilities.dp(36), y, AndroidUtilities.dp(36) + titleTextView.getMeasuredWidth(), y + titleTextView.getMeasuredHeight());
recognizedMrzView.layout(0, getMeasuredHeight() - recognizedMrzView.getMeasuredHeight(), getMeasuredWidth(), getMeasuredHeight());
int x;
if (needGalleryButton) {
x = cameraView.getMeasuredWidth() / 2 + AndroidUtilities.dp(35);
x = width / 2 + AndroidUtilities.dp(35);
} else {
x = cameraView.getMeasuredWidth() / 2 - flashButton.getMeasuredWidth() / 2;
x = width / 2 - flashButton.getMeasuredWidth() / 2;
}
y = (cameraView.getMeasuredHeight() - size) / 2 + size + AndroidUtilities.dp(80);
y = (height - size) / 2 + size + AndroidUtilities.dp(80);
flashButton.layout(x, y, x + flashButton.getMeasuredWidth(), y + flashButton.getMeasuredHeight());
if (galleryButton != null) {
x = cameraView.getMeasuredWidth() / 2 - AndroidUtilities.dp(35) - galleryButton.getMeasuredWidth();
x = width / 2 - AndroidUtilities.dp(35) - galleryButton.getMeasuredWidth();
galleryButton.layout(x, y, x + galleryButton.getMeasuredWidth(), y + galleryButton.getMeasuredHeight());
}
}
@ -362,16 +340,7 @@ public class CameraScanActivity extends BaseFragment {
int x = (int) (width * 0.05f);
descriptionText.layout(x, y, x + descriptionText.getMeasuredWidth(), y + descriptionText.getMeasuredHeight());
if (!recognized) {
int side = (int) (Math.min(width, height) / 1.5f);
AndroidUtilities.rectTmp.set(
(width - side) / 2f / (float) width,
(height - side) / 2f / (float) height,
(width + side) / 2f / (float) width,
(height + side) / 2f / (float) height
);
updateBounds(AndroidUtilities.rectTmp);
}
updateNormalBounds();
}
@Override
@ -389,13 +358,15 @@ public class CameraScanActivity extends BaseFragment {
int x = cx - sizex / 2,
y = cy - sizey / 2;
paint.setAlpha((int) (255 * backShadowAlpha * Math.min(1, qrAppearingValue)));
paint.setAlpha((int) (255 * (1f - (1f - backShadowAlpha) * Math.min(1, qrAppearingValue))));
canvas.drawRect(0, 0, child.getMeasuredWidth(), y, paint);
canvas.drawRect(0, y + sizey, child.getMeasuredWidth(), child.getMeasuredHeight(), paint);
canvas.drawRect(0, y, x, y + sizey, paint);
canvas.drawRect(x + sizex, y, child.getMeasuredWidth(), y + sizey, paint);
paint.setAlpha((int) (255 * Math.max(0, 1f - qrAppearingValue)));
canvas.drawRect(x, y, x + sizex, y + sizey, paint);
final int lineWidth = AndroidUtilities.lerp(0, AndroidUtilities.dp(4), (float) Math.pow(qrAppearingValue, 0.125f)),
final int lineWidth = AndroidUtilities.lerp(0, AndroidUtilities.dp(4), Math.min(1, qrAppearingValue * 20f)),
halfLineWidth = lineWidth / 2;
final int lineLength = AndroidUtilities.lerp(Math.min(sizex, sizey), AndroidUtilities.dp(20), Math.min(1.2f, (float) Math.pow(qrAppearingValue, 1.8f)));
@ -446,35 +417,11 @@ public class CameraScanActivity extends BaseFragment {
viewGroup.setOnTouchListener((v, event) -> true);
fragmentView = viewGroup;
cameraView = new CameraView(context, false);
cameraView.setUseMaxPreview(true);
cameraView.setOptimizeForBarcode(true);
cameraView.setDelegate(() -> {
startRecognizing();
if (isQr()) {
if (qrAppearing != null) {
qrAppearing.cancel();
qrAppearing = null;
}
qrAppearing = new SpringAnimation(new FloatValueHolder(0));
qrAppearing.addUpdateListener((animation, value, velocity) -> {
qrAppearingValue = value / 500f;
fragmentView.invalidate();
});
qrAppearing.addEndListener((animation, canceled, value, velocity) -> {
if (qrAppearing != null) {
qrAppearing.cancel();
qrAppearing = null;
}
});
qrAppearing.setSpring(new SpringForce(500f));
qrAppearing.getSpring().setDampingRatio(0.8f);
qrAppearing.getSpring().setStiffness(250.0f);
qrAppearing.start();
}
});
viewGroup.addView(cameraView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
if (currentType == TYPE_QR || currentType == TYPE_QR_LOGIN) {
fragmentView.postDelayed(this::initCameraView, 200);
} else {
initCameraView();
}
if (currentType == TYPE_MRZ) {
actionBar.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
@ -549,7 +496,6 @@ public class CameraScanActivity extends BaseFragment {
descriptionText.setText(LocaleController.getString("PassportScanPassportInfo", R.string.PassportScanPassportInfo));
titleTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
recognizedMrzView.setTypeface(Typeface.MONOSPACE);
cameraView.addView(recognizedMrzView);
} else {
if (needGalleryButton) {
//titleTextView.setText(LocaleController.getString("WalletScanCode", R.string.WalletScanCode));
@ -664,6 +610,9 @@ public class CameraScanActivity extends BaseFragment {
flashButton.setBackgroundDrawable(Theme.createCircleDrawable(AndroidUtilities.dp(60), 0x22ffffff));
viewGroup.addView(flashButton);
flashButton.setOnClickListener(currentImage -> {
if (cameraView == null) {
return;
}
CameraSession session = cameraView.getCameraSession();
if (session != null) {
ShapeDrawable shapeDrawable = (ShapeDrawable) flashButton.getBackground();
@ -703,13 +652,16 @@ public class CameraScanActivity extends BaseFragment {
return fragmentView;
}
private ValueAnimator recognizedAnimator;
private float recognizedT = 0;
private SpringAnimation useRecognizedBoundsAnimator;
private float useRecognizedBounds = 0;
private void updateRecognized() {
if (recognizedAnimator != null) {
recognizedAnimator.cancel();
}
float newRecorgnizedT = recognized ? 1f : 0f;
recognizedAnimator = ValueAnimator.ofFloat(recognizedT, newRecorgnizedT);
float newRecognizedT = recognized ? 1f : 0f;
recognizedAnimator = ValueAnimator.ofFloat(recognizedT, newRecognizedT);
recognizedAnimator.addUpdateListener(a -> {
recognizedT = (float) a.getAnimatedValue();
titleTextView.setAlpha(1f - recognizedT);
@ -717,12 +669,65 @@ public class CameraScanActivity extends BaseFragment {
backShadowAlpha = .5f + recognizedT * .25f;
fragmentView.invalidate();
});
recognizedAnimator.setDuration((long) (200 * Math.abs(recognizedT - newRecorgnizedT)));
recognizedAnimator.setInterpolator(CubicBezierInterpolator.EASE_BOTH);
recognizedAnimator.setDuration((long) (300 * Math.abs(recognizedT - newRecognizedT)));
recognizedAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT);
recognizedAnimator.start();
if (useRecognizedBoundsAnimator != null) {
useRecognizedBoundsAnimator.cancel();
}
final float force = 500f;
useRecognizedBoundsAnimator = new SpringAnimation(new FloatValueHolder((recognized ? useRecognizedBounds : 1f - useRecognizedBounds) * force));
useRecognizedBoundsAnimator.addUpdateListener((animation, value, velocity) -> {
useRecognizedBounds = recognized ? value / force : (1f - value / force);
fragmentView.invalidate();
});
useRecognizedBoundsAnimator.setSpring(new SpringForce(force));
useRecognizedBoundsAnimator.getSpring().setDampingRatio(1f);
useRecognizedBoundsAnimator.getSpring().setStiffness(500.0f);
useRecognizedBoundsAnimator.start();
}
private void updateBounds(RectF newBounds) {
private void initCameraView() {
if (fragmentView == null) {
return;
}
CameraController.getInstance().initCamera(null);
cameraView = new CameraView(fragmentView.getContext(), false);
cameraView.setUseMaxPreview(true);
cameraView.setOptimizeForBarcode(true);
cameraView.setDelegate(() -> {
startRecognizing();
if (isQr()) {
if (qrAppearing != null) {
qrAppearing.cancel();
qrAppearing = null;
}
qrAppearing = new SpringAnimation(new FloatValueHolder(0));
qrAppearing.addUpdateListener((animation, value, velocity) -> {
qrAppearingValue = value / 500f;
fragmentView.invalidate();
});
qrAppearing.addEndListener((animation, canceled, value, velocity) -> {
if (qrAppearing != null) {
qrAppearing.cancel();
qrAppearing = null;
}
});
qrAppearing.setSpring(new SpringForce(500f));
qrAppearing.getSpring().setDampingRatio(0.8f);
qrAppearing.getSpring().setStiffness(250.0f);
qrAppearing.start();
}
});
((ViewGroup) fragmentView).addView(cameraView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
if (currentType == TYPE_MRZ && recognizedMrzView != null) {
cameraView.addView(recognizedMrzView);
}
}
private void updateRecognizedBounds(RectF newBounds) {
final long now = SystemClock.elapsedRealtime();
if (lastBoundsUpdate == 0) {
// first update = set
@ -733,7 +738,7 @@ public class CameraScanActivity extends BaseFragment {
// next updates = interpolate
if (fromBounds != null && now - lastBoundsUpdate < boundsUpdateDuration) {
float t = (now - lastBoundsUpdate) / (float) boundsUpdateDuration;
// t = CubicBezierInterpolator.EASE_BOTH.getInterpolation(t);
t = Math.min(1, Math.max(0, t));
AndroidUtilities.lerp(fromBounds, bounds, t, fromBounds);
} else {
if (fromBounds == null) {
@ -747,20 +752,46 @@ public class CameraScanActivity extends BaseFragment {
fragmentView.invalidate();
}
private RectF getBounds() {
private RectF getRecognizedBounds() {
if (fromBounds == null) {
return bounds;
} else {
float t = (SystemClock.elapsedRealtime() - lastBoundsUpdate) / (float) boundsUpdateDuration;
// t = CubicBezierInterpolator.EASE_BOTH.getInterpolation(t);
t = Math.min(1, Math.max(0, t));
if (t < 1f) {
fragmentView.invalidate();
}
AndroidUtilities.lerp(fromBounds, bounds, Math.min(1, Math.max(0, t)), AndroidUtilities.rectTmp);
AndroidUtilities.lerp(fromBounds, bounds, t, AndroidUtilities.rectTmp);
return AndroidUtilities.rectTmp;
}
}
private RectF normalBounds;
private void updateNormalBounds() {
if (normalBounds == null) {
normalBounds = new RectF();
}
int width = AndroidUtilities.displaySize.x,
height = AndroidUtilities.displaySize.y,
side = (int) (Math.min(width, height) / 1.5f);
normalBounds.set(
(width - side) / 2f / (float) width,
(height - side) / 2f / (float) height,
(width + side) / 2f / (float) width,
(height + side) / 2f / (float) height
);
}
private RectF getBounds() {
RectF recognizedBounds = getRecognizedBounds();
if (useRecognizedBounds < 1f) {
if (normalBounds == null) {
updateNormalBounds();
}
AndroidUtilities.lerp(normalBounds, recognizedBounds, useRecognizedBounds, recognizedBounds);
}
return recognizedBounds;
}
@Override
public void onActivityResultFragment(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK && requestCode == 11 && data != null && data.getData() != null) {
@ -823,6 +854,9 @@ public class CameraScanActivity extends BaseFragment {
private float averageProcessTime = 0;
private long processTimesCount = 0;
public void processShot(Bitmap bitmap) {
if (cameraView == null) {
return;
}
final long from = SystemClock.elapsedRealtime();
try {
Size size = cameraView.getPreviewSize();
@ -869,31 +903,23 @@ public class CameraScanActivity extends BaseFragment {
recognizedStart = SystemClock.elapsedRealtime();
AndroidUtilities.runOnUIThread(this::updateRecognized);
}
AndroidUtilities.runOnUIThread(() -> updateBounds(res.bounds));
AndroidUtilities.runOnUIThread(() -> updateRecognizedBounds(res.bounds));
} else if (recognized) {
recognizeFailed++;
if (recognizeFailed > 4 && !qrLoading) {
recognized = false;
recognizeIndex = 0;
recognizedText = null;
AndroidUtilities.runOnUIThread(() -> {
updateRecognized();
int width = AndroidUtilities.displaySize.x, height = AndroidUtilities.displaySize.y,
_side = (int) (Math.min(width, height) / 1.5f);
AndroidUtilities.rectTmp.set(
(width - _side) / 2f / (float) width,
(height - _side) / 2f / (float) height,
(width + _side) / 2f / (float) width,
(height + _side) / 2f / (float) height
);
updateBounds(AndroidUtilities.rectTmp);
});
AndroidUtilities.runOnUIThread(this::updateRecognized);
AndroidUtilities.runOnUIThread(requestShot, 500);
return;
}
}
if (((recognizeIndex == 0 && res != null && res.bounds == null) || (SystemClock.elapsedRealtime() - recognizedStart > 1000 && !qrLoading)) && recognizedText != null) {
if (( // finish because...
(recognizeIndex == 0 && res != null && res.bounds == null && !qrLoading) || // first recognition doesn't have bounds
(SystemClock.elapsedRealtime() - recognizedStart > 1000 && !qrLoading) // got more than 1 second and nothing is loading
) && recognizedText != null) {
if (cameraView != null && cameraView.getCameraSession() != null) {
CameraController.getInstance().stopPreview(cameraView.getCameraSession());
}
@ -918,7 +944,6 @@ public class CameraScanActivity extends BaseFragment {
final long to = SystemClock.elapsedRealtime();
long timeout = to - from;
averageProcessTime = (averageProcessTime * processTimesCount + timeout) / (++processTimesCount);
FileLog.e("qr scan timeout = " + timeout + "ms (avg=" + averageProcessTime + "ms)");
processTimesCount = Math.max(processTimesCount, 30);
if (!recognized) {
@ -936,7 +961,7 @@ public class CameraScanActivity extends BaseFragment {
String text;
RectF bounds = new RectF();
int width = 1, height = 1;
if (visionQrReader.isOperational()) {
if (visionQrReader != null && visionQrReader.isOperational()) {
Frame frame;
if (bitmap != null) {
frame = new Frame.Builder().setBitmap(bitmap).build();
@ -970,7 +995,7 @@ public class CameraScanActivity extends BaseFragment {
} else {
text = null;
}
} else {
} else if (qrReader != null) {
LuminanceSource source;
if (bitmap != null) {
int[] intArray = new int[bitmap.getWidth() * bitmap.getHeight()];
@ -1005,6 +1030,8 @@ public class CameraScanActivity extends BaseFragment {
}
bounds.set(minX, minY, maxX, maxY);
}
} else {
text = null;
}
if (TextUtils.isEmpty(text)) {
onNoQrFound();

View File

@ -33,7 +33,7 @@ public abstract class BaseCell extends ViewGroup {
public void run() {
if (checkingForLongPress && getParent() != null && currentPressCount == pressCount) {
checkingForLongPress = false;
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
if (onLongPress()) {
MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
onTouchEvent(event);
@ -52,6 +52,7 @@ public abstract class BaseCell extends ViewGroup {
super(context);
setWillNotDraw(false);
setFocusable(true);
setHapticFeedbackEnabled(true);
}
public static void setDrawableBounds(Drawable drawable, int x, int y) {

View File

@ -54,6 +54,7 @@ import android.text.style.URLSpan;
import android.util.Property;
import android.util.SparseArray;
import android.util.StateSet;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
@ -3964,7 +3965,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
totalHeight = messageObject.textHeight + AndroidUtilities.dp(19.5f) + namesOffset;
if (!reactionsLayoutInBubble.isSmall) {
reactionsLayoutInBubble.measure(maxWidth);
reactionsLayoutInBubble.measure(maxWidth, Gravity.LEFT);
if (!reactionsLayoutInBubble.isEmpty) {
reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height + AndroidUtilities.dp(8);
if (reactionsLayoutInBubble.width > backgroundWidth) {
@ -4926,7 +4927,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
if (!reactionsLayoutInBubble.isSmall) {
if (!reactionsLayoutInBubble.isEmpty) {
reactionsLayoutInBubble.measure(backgroundWidth - AndroidUtilities.dp(32));
reactionsLayoutInBubble.measure(backgroundWidth - AndroidUtilities.dp(32), Gravity.LEFT);
reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height + AndroidUtilities.dp(12);
reactionsLayoutInBubble.positionOffsetY += -AndroidUtilities.dp(4);
if (backgroundWidth - AndroidUtilities.dp(32) - reactionsLayoutInBubble.lastLineX < timeWidth) {
@ -4955,7 +4956,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
namesOffset -= AndroidUtilities.dp(1);
}
if (!reactionsLayoutInBubble.isSmall) {
reactionsLayoutInBubble.measure(maxWidth - AndroidUtilities.dp(24));
reactionsLayoutInBubble.measure(maxWidth - AndroidUtilities.dp(24), Gravity.LEFT);
if (!reactionsLayoutInBubble.isEmpty) {
reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height;
if (TextUtils.isEmpty(messageObject.caption)) {
@ -5001,7 +5002,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
namesOffset -= AndroidUtilities.dp(1);
}
if (!reactionsLayoutInBubble.isSmall) {
reactionsLayoutInBubble.measure(maxWidth - AndroidUtilities.dp(24));
reactionsLayoutInBubble.measure(maxWidth - AndroidUtilities.dp(24), Gravity.LEFT);
if (!reactionsLayoutInBubble.isEmpty) {
reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height + AndroidUtilities.dp(12);
measureTime(messageObject);
@ -5289,7 +5290,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
if (!reactionsLayoutInBubble.isSmall) {
if (!reactionsLayoutInBubble.isEmpty) {
reactionsLayoutInBubble.measure(maxWidth);
reactionsLayoutInBubble.measure(maxWidth, Gravity.LEFT);
totalHeight += reactionsLayoutInBubble.height + AndroidUtilities.dp(12);
int timeWidthTotal = timeWidth + (messageObject.isOutOwner() ? AndroidUtilities.dp(20) : 0) + getExtraTimeX();
if (timeWidthTotal >= (backgroundWidth - AndroidUtilities.dp(24) - reactionsLayoutInBubble.lastLineX)) {
@ -5379,7 +5380,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
}
if (!reactionsLayoutInBubble.isSmall) {
reactionsLayoutInBubble.measure(widthForCaption);
reactionsLayoutInBubble.measure(widthForCaption, Gravity.LEFT);
if (!reactionsLayoutInBubble.isEmpty && reactionsLayoutInBubble.width + AndroidUtilities.dp(31) > maxTextWidth) {
maxTextWidth = reactionsLayoutInBubble.width + AndroidUtilities.dp(31);
}
@ -5590,7 +5591,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
}
if (!reactionsLayoutInBubble.isSmall && !reactionsLayoutInBubble.isEmpty) {
reactionsLayoutInBubble.measure(backgroundWidth - AndroidUtilities.dp(16));
reactionsLayoutInBubble.measure(backgroundWidth - AndroidUtilities.dp(16), Gravity.LEFT);
reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height + AndroidUtilities.dp(14);
measureTime(messageObject);
if (reactionsLayoutInBubble.lastLineX + timeWidth + AndroidUtilities.dp(24) > backgroundWidth) {
@ -5710,7 +5711,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
photoImage.setImage(null, null, null, null, messageObject, 0);
}
if (!reactionsLayoutInBubble.isSmall) {
reactionsLayoutInBubble.measure(maxWidth);
reactionsLayoutInBubble.measure(maxWidth, Gravity.LEFT);
reactionsLayoutInBubble.drawServiceShaderBackground = true;
reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height + AndroidUtilities.dp(8);
additionHeight += reactionsLayoutInBubble.totalHeight;
@ -6079,7 +6080,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
if (!reactionsLayoutInBubble.isSmall) {
boolean useBackgroundWidth = backgroundWidth - AndroidUtilities.dp(24) > widthForCaption;
int maxWidth = Math.max(backgroundWidth - AndroidUtilities.dp(36), widthForCaption);
reactionsLayoutInBubble.measure(maxWidth);
reactionsLayoutInBubble.measure(maxWidth, Gravity.LEFT);
if (!reactionsLayoutInBubble.isEmpty) {
if (shouldDrawTimeOnMedia()) {
reactionsLayoutInBubble.drawServiceShaderBackground = true;
@ -6737,6 +6738,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
}
private boolean hadLongPress = false;
@Override
protected boolean onLongPress() {
if (isRoundVideo && isPlayingRound && MediaController.getInstance().isPlayingMessage(currentMessageObject)) {
@ -10256,7 +10259,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
}
if (reactionsLayoutInBubble.isSmall) {
reactionsLayoutInBubble.measure(Integer.MAX_VALUE);
reactionsLayoutInBubble.measure(Integer.MAX_VALUE, Gravity.LEFT);
timeWidth += reactionsLayoutInBubble.width;
}
if (signString != null) {
@ -11165,18 +11168,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
}
if (shouldDrawSelectionOverlay() && currentMessagesGroup == null) {
if (drawBackground && shouldDrawSelectionOverlay() && currentMessagesGroup == null) {
if (selectionOverlayPaint == null) {
selectionOverlayPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
selectionOverlayPaint.setColor(getSelectionOverlayColor());
int wasAlpha = selectionOverlayPaint.getAlpha();
selectionOverlayPaint.setAlpha((int) (wasAlpha * getHighlightAlpha() * getAlpha()));
canvas.save();
canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight());
currentBackgroundDrawable.drawCached(canvas, backgroundCacheParams, selectionOverlayPaint);
if (selectionOverlayPaint.getAlpha() > 0) {
canvas.save();
canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight());
currentBackgroundDrawable.drawCached(canvas, backgroundCacheParams, selectionOverlayPaint);
canvas.restore();
}
selectionOverlayPaint.setAlpha(wasAlpha);
canvas.restore();
}
if (restore != Integer.MIN_VALUE) {
@ -11426,9 +11431,19 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
alphaInternal *= getAlpha();
}
if (hasSelectionOverlay()) {
currentSelectedBackgroundAlpha = 0;
currentBackgroundDrawable.setAlpha((int) (255 * alphaInternal));
currentBackgroundDrawable.drawCached(canvas, backgroundCacheParams);
// if ((isPressed() && isCheckPressed || !isCheckPressed && isPressed) && !textIsSelectionMode()) {
// currentSelectedBackgroundAlpha = 1f;
// currentBackgroundSelectedDrawable.setAlpha((int) (255 * alphaInternal));
// currentBackgroundSelectedDrawable.drawCached(canvas, backgroundCacheParams);
// } else {
currentSelectedBackgroundAlpha = 0;
currentBackgroundDrawable.setAlpha((int) (255 * alphaInternal));
currentBackgroundDrawable.drawCached(canvas, backgroundCacheParams);
// }
if (currentBackgroundShadowDrawable != null && currentPosition == null) {
currentBackgroundShadowDrawable.setAlpha((int) (255 * alphaInternal));
currentBackgroundShadowDrawable.draw(canvas);
}
} else {
if (isHighlightedAnimated) {
currentBackgroundDrawable.setAlpha((int) (255 * alphaInternal));
@ -12048,6 +12063,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
if (currentMessageObject.needDrawForwarded()) {
forwardNameXLocal = forwardNameX = backgroundDrawableLeft + AndroidUtilities.dp(11) + getExtraTextX();
forwardNameXLocal += transitionParams.deltaLeft;
} else {
forwardNameXLocal = transitionParams.animateForwardNameX;
}

View File

@ -1350,7 +1350,7 @@ public class DialogCell extends BaseCell {
} else {
drawMention = false;
}
if (reactionMentionCount != 0) {
if (reactionMentionCount > 0) {
drawReactionMention = true;
} else {
drawReactionMention = false;

View File

@ -36,16 +36,16 @@ public class MemberRequestCell extends FrameLayout {
super(context);
avatarImageView.setRoundRadius(AndroidUtilities.dp(23));
addView(avatarImageView, LayoutHelper.createFrame(46, 46, Gravity.START, 12, 8, 12, 0));
addView(avatarImageView, LayoutHelper.createFrame(46, 46, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 12, 8, 12, 0));
nameTextView.setGravity(Gravity.START);
nameTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
nameTextView.setMaxLines(1);
nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
nameTextView.setTextSize(17);
nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP, LocaleController.isRTL ? 12 : 74, 12, LocaleController.isRTL ? 74 : 12, 0));
statusTextView.setGravity(Gravity.START);
statusTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
statusTextView.setMaxLines(1);
statusTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText));
statusTextView.setTextSize(14);
@ -66,7 +66,7 @@ public class MemberRequestCell extends FrameLayout {
clickListener.onAddClicked(importer);
}
});
addView(addButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 32, Gravity.START, LocaleController.isRTL ? 0 : 73, 62, LocaleController.isRTL ? 73 : 0, 0));
addView(addButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 32, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 0 : 73, 62, LocaleController.isRTL ? 73 : 0, 0));
float addButtonWidth = addButton.getPaint().measureText(addButton.getText().toString()) + btnPadding * 2;
TextView dismissButton = new TextView(getContext());
@ -83,7 +83,7 @@ public class MemberRequestCell extends FrameLayout {
clickListener.onDismissClicked(importer);
}
});
FrameLayout.LayoutParams dismissLayoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, AndroidUtilities.dp(32));
FrameLayout.LayoutParams dismissLayoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, AndroidUtilities.dp(32), LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
dismissLayoutParams.topMargin = AndroidUtilities.dp(62);
dismissLayoutParams.leftMargin = LocaleController.isRTL ? 0 : (int)(addButtonWidth + AndroidUtilities.dp(73 + 6));
dismissLayoutParams.rightMargin = LocaleController.isRTL ? (int)(addButtonWidth + AndroidUtilities.dp(73 + 6)) : 0;

View File

@ -91,6 +91,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
private RLottieDrawable statusDrawable;
private final Theme.ResourcesProvider resourcesProvider;
FlickerLoadingView globalGradientView;
private long downloadedSize;
public SharedDocumentCell(Context context) {
this(context, VIEW_TYPE_DEFAULT);
@ -322,8 +323,8 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
File file = new File(path);
nameTextView.setText(file.getName());
String type = FileLoader.getFileExtension(file);
StringBuilder builder = new StringBuilder();
extTextView.setVisibility(GONE);
StringBuilder builder = new StringBuilder();
if (entry.width != 0 && entry.height != 0) {
if (builder.length() > 0) {
builder.append(", ");
@ -347,8 +348,6 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
}
builder.append(LocaleController.getInstance().formatterStats.format(entry.dateTaken));
dateTextView.setText(builder);
//placeholderImageView.setImageResource(AndroidUtilities.getThumbForNameOrMime(path, null, false));
//placeholderImageView.setVisibility(VISIBLE);
placeholderImageView.setVisibility(GONE);
}
@ -379,6 +378,9 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
message = messageObject;
loaded = false;
loading = false;
if (!animated) {
downloadedSize = 0;
}
TLRPC.Document document = messageObject.getDocument();
if (document != null) {
@ -394,10 +396,17 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
}
}
}
String fileName = FileLoader.getDocumentFileName(document);
String fileName = null;
if (!messageObject.isVideo() && !(messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) && !MessageObject.isGifDocument(document)) {
fileName = FileLoader.getDocumentFileName(document);
}
if (TextUtils.isEmpty(fileName)) {
if (document.mime_type.startsWith("video")) {
fileName = LocaleController.getString("AttachVideo", R.string.AttachVideo);
if (MessageObject.isGifDocument(document)) {
fileName = LocaleController.getString("AttachGif", R.string.AttachGif);
} else {
fileName = LocaleController.getString("AttachVideo", R.string.AttachVideo);
}
} else if (document.mime_type.startsWith("image")) {
fileName = LocaleController.getString("AttachPhoto", R.string.AttachPhoto);
} else if (document.mime_type.startsWith("audio")) {
@ -441,17 +450,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
thumbImageView.setImage(ImageLocation.getForDocument(bigthumb, document), "40_40", ImageLocation.getForDocument(thumb, document), "40_40_b", null, 0, 1, messageObject);
}
}
long date = (long) messageObject.messageOwner.date * 1000;
if (viewType == VIEW_TYPE_GLOBAL_SEARCH) {
CharSequence fromName = FilteredSearchView.createFromInfoString(messageObject);
dateTextView.setText(new SpannableStringBuilder().append(AndroidUtilities.formatFileSize(document.size))
.append(' ').append(dotSpan).append(' ')
.append(fromName));
rightDateTextView.setText(LocaleController.stringForMessageListDate(messageObject.messageOwner.date));
} else {
dateTextView.setText(String.format("%s, %s", AndroidUtilities.formatFileSize(document.size), LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, LocaleController.getInstance().formatterYear.format(new Date(date)), LocaleController.getInstance().formatterDay.format(new Date(date)))));
}
updateDateView();
if (messageObject.hasHighlightedWords() && !TextUtils.isEmpty(message.messageOwner.message)) {
String str = message.messageOwner.message.replace("\n", " ").replaceAll(" +", " ").trim();
@ -485,6 +484,29 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
updateFileExistIcon(animated);
}
private void updateDateView() {
if (message == null || message.getDocument() == null) {
return;
}
long date = (long) message.messageOwner.date * 1000;
String fileSize = null;
if (downloadedSize == 0) {
fileSize = AndroidUtilities.formatFileSize(message.getDocument().size);
} else {
fileSize = String.format(Locale.ENGLISH, "%s / %s", AndroidUtilities.formatFileSize(downloadedSize), AndroidUtilities.formatFileSize(message.getDocument().size));
}
if (viewType == VIEW_TYPE_GLOBAL_SEARCH) {
CharSequence fromName = FilteredSearchView.createFromInfoString(message);
dateTextView.setText(new SpannableStringBuilder().append(fileSize)
.append(' ').append(dotSpan).append(' ')
.append(fromName));
rightDateTextView.setText(LocaleController.stringForMessageListDate(message.messageOwner.date));
} else {
dateTextView.setText(String.format("%s, %s", fileSize, LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, LocaleController.getInstance().formatterYear.format(new Date(date)), LocaleController.getInstance().formatterDay.format(new Date(date)))));
}
}
public void updateFileExistIcon(boolean animated) {
if (animated && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
TransitionSet transition = new TransitionSet();
@ -593,6 +615,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
}
boolean ignoreRequestLayout;
@Override
public void requestLayout() {
if (ignoreRequestLayout) {
@ -604,7 +627,9 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (viewType != VIEW_TYPE_PICKER && ((nameTextView.getLineCount() > 1 || (captionTextView != null && captionTextView.getVisibility() == View.VISIBLE)))); {
if (viewType != VIEW_TYPE_PICKER && ((nameTextView.getLineCount() > 1 || (captionTextView != null && captionTextView.getVisibility() == View.VISIBLE))))
;
{
int y = nameTextView.getMeasuredHeight() - AndroidUtilities.dp(22);
if (captionTextView != null && captionTextView.getVisibility() == View.VISIBLE) {
captionTextView.layout(captionTextView.getLeft(), y + captionTextView.getTop(), captionTextView.getRight(), y + captionTextView.getBottom());
@ -620,12 +645,16 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
@Override
public void onFailedDownload(String name, boolean canceled) {
updateFileExistIcon(true);
downloadedSize = 0;
updateDateView();
}
@Override
public void onSuccessDownload(String name) {
progressView.setProgress(1, true);
updateFileExistIcon(true);
downloadedSize = 0;
updateDateView();
}
@Override
@ -633,6 +662,8 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
if (progressView.getVisibility() != VISIBLE) {
updateFileExistIcon(true);
}
this.downloadedSize = downloadedSize;
updateDateView();
progressView.setProgress(Math.min(1f, downloadedSize / (float) totalSize), true);
}

View File

@ -9,6 +9,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
@ -36,6 +37,7 @@ import android.view.animation.OvershootInterpolator;
import android.widget.Magnifier;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import org.telegram.messenger.AndroidUtilities;
@ -53,6 +55,7 @@ import org.telegram.ui.ActionBar.FloatingToolbar;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ArticleViewer;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.LinkPath;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.RestrictedLanguagesSelectActivity;
@ -77,7 +80,11 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
private int touchSlop;
protected PathWithSavedBottom path = new PathWithSavedBottom();
protected float cornerRadius;
protected Paint selectionPaint = new Paint();
protected Paint selectionHandlePaint = new Paint();
protected Path selectionPath = new Path();
protected PathCopyTo selectionPathMirror = new PathCopyTo(selectionPath);
protected int capturedX;
protected int capturedY;
@ -258,6 +265,7 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
public TextSelectionHelper() {
longpressDelay = ViewConfiguration.getLongPressTimeout();
touchSlop = ViewConfiguration.get(ApplicationLoader.applicationContext).getScaledTouchSlop();
selectionPaint.setPathEffect(new CornerPathEffect(cornerRadius = AndroidUtilities.dp(6)));
}
public interface OnTranslateListener {
@ -1422,11 +1430,13 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
return tmpCoord;
}
protected Path tempPath = new Path();
protected void drawSelection(Canvas canvas, StaticLayout layout, int selectionStart, int selectionEnd) {
selectionPath.reset();
int startLine = layout.getLineForOffset(selectionStart);
int endLine = layout.getLineForOffset(selectionEnd);
if (startLine == endLine) {
drawLine(canvas, layout, startLine, selectionStart, selectionEnd);
drawLine(layout, startLine, selectionStart, selectionEnd);
} else {
int end = layout.getLineEnd(startLine);
if (layout.getParagraphDirection(startLine) != StaticLayout.DIR_RIGHT_TO_LEFT && end > 0) {
@ -1447,35 +1457,63 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
int l = Math.min(s, e);
int r = Math.max(s, e);
if (end > 0 && end < text.length() && !Character.isWhitespace(text.charAt(end - 1))) {
canvas.drawRect(l, layout.getLineTop(startLine), r, layout.getLineBottom(startLine), selectionPaint);
selectionPath.addRect(l, layout.getLineTop(startLine), r, layout.getLineBottom(startLine), Path.Direction.CW);
}
}
drawLine(canvas, layout, startLine, selectionStart, end);
drawLine(canvas, layout, endLine, layout.getLineStart(endLine), selectionEnd);
drawLine(layout, startLine, selectionStart, end);
drawLine(layout, endLine, layout.getLineStart(endLine), selectionEnd);
for (int i = startLine + 1; i < endLine; i++) {
int s = (int) layout.getLineLeft(i);
int e = (int) layout.getLineRight(i);
int l = Math.min(s, e);
int r = Math.max(s, e);
canvas.drawRect(l, layout.getLineTop(i), r, layout.getLineBottom(i), selectionPaint);
selectionPath.addRect(l, layout.getLineTop(i) - 1, r, layout.getLineBottom(i) + 1, Path.Direction.CW);
}
}
canvas.drawPath(selectionPath, selectionPaint);
final int R = (int) (cornerRadius * 1.66f);
float startLeft = layout.getPrimaryHorizontal(selectionStart),
endLeft = layout.getPrimaryHorizontal(selectionEnd);
float x, b;
if (selectionStart + 1 < layout.getLineEnd(startLine) && (startLine == endLine || startLine + 1 == endLine && startLeft > endLeft)) {
x = startLeft;
b = layout.getLineBottom(startLine);
tempPath.reset();
tempPath.moveTo(x + R, b);
tempPath.lineTo(x, b);
tempPath.lineTo(x, b - R);
AndroidUtilities.rectTmp.set(x, b - R, x + R, b);
tempPath.arcTo(AndroidUtilities.rectTmp, 180, -90);
canvas.drawPath(tempPath, selectionHandlePaint);
}
if (layout.getLineStart(endLine) < selectionEnd) {
x = endLeft;
b = layout.getLineBottom(endLine);
tempPath.reset();
tempPath.moveTo(x - R, b);
tempPath.lineTo(x, b);
tempPath.lineTo(x, b - R);
AndroidUtilities.rectTmp.set(x - R, b - R, x, b);
tempPath.arcTo(AndroidUtilities.rectTmp, 0, 90);
canvas.drawPath(tempPath, selectionHandlePaint);
}
}
private void drawLine(Canvas canvas, StaticLayout layout, int line, int start, int end) {
layout.getSelectionPath(start, end, path);
if (path.lastBottom < layout.getLineBottom(line)) {
int lineBottom = layout.getLineBottom(line);
private final ScalablePath tempPath2 = new ScalablePath();
private void drawLine(StaticLayout layout, int line, int start, int end) {
tempPath2.reset();
layout.getSelectionPath(start, end, tempPath2);
if (tempPath2.lastBottom < layout.getLineBottom(line)) {
int lineTop = layout.getLineTop(line);
int lineBottom = layout.getLineBottom(line);
float lineH = lineBottom - lineTop;
float lineHWithoutSpaсing = path.lastBottom - lineTop;
canvas.save();
canvas.scale(1f, lineH / lineHWithoutSpaсing, 0, lineTop);
canvas.drawPath(path, selectionPaint);
canvas.restore();
float lineHWithoutSpacing = tempPath2.lastBottom - lineTop;
tempPath2.scaleY(lineH / lineHWithoutSpacing, lineTop, selectionPath);
} else {
canvas.drawPath(path, selectionPaint);
tempPath2.scaleY(1f, 0, selectionPath);
}
}
@ -1642,8 +1680,10 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
if (selectionStart != selectionEnd) {
if (selectedMessageObject.isOutOwner()) {
selectionPaint.setColor(getThemedColor(Theme.key_chat_outTextSelectionHighlight));
selectionHandlePaint.setColor(getThemedColor(Theme.key_chat_outTextSelectionHighlight));
} else {
selectionPaint.setColor(getThemedColor(key_chat_inTextSelectionHighlight));
selectionHandlePaint.setColor(getThemedColor(key_chat_inTextSelectionHighlight));
}
drawSelection(canvas, block.textLayout, selectionStart, selectionEnd);
}
@ -1826,8 +1866,10 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
}
if (isOut) {
selectionPaint.setColor(getThemedColor(Theme.key_chat_outTextSelectionHighlight));
selectionHandlePaint.setColor(getThemedColor(Theme.key_chat_outTextSelectionHighlight));
} else {
selectionPaint.setColor(getThemedColor(key_chat_inTextSelectionHighlight));
selectionHandlePaint.setColor(getThemedColor(key_chat_inTextSelectionHighlight));
}
drawSelection(canvas, captionLayout, selectionStart, selectionEnd);
}
@ -1838,8 +1880,10 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
}
if (isOut) {
selectionPaint.setColor(getThemedColor(Theme.key_chat_outTextSelectionHighlight));
selectionHandlePaint.setColor(getThemedColor(Theme.key_chat_outTextSelectionHighlight));
} else {
selectionPaint.setColor(getThemedColor(key_chat_inTextSelectionHighlight));
selectionHandlePaint.setColor(getThemedColor(key_chat_inTextSelectionHighlight));
}
drawSelection(canvas, layout, selectionStart, selectionEnd);
}
@ -2118,6 +2162,7 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
public void draw(Canvas canvas, ArticleSelectableView view, int i) {
selectionPaint.setColor(getThemedColor(key_chat_inTextSelectionHighlight));
selectionHandlePaint.setColor(getThemedColor(key_chat_inTextSelectionHighlight));
int position = getAdapterPosition(view);
if (position < 0) {
@ -2649,6 +2694,22 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
}
private static class PathCopyTo extends Path {
private Path destination;
public PathCopyTo(Path destination) {
this.destination = destination;
}
@Override
public void reset() {
super.reset();
}
@Override
public void addRect(float left, float top, float right, float bottom, @NonNull Direction dir) {
this.destination.addRect(left, top, right, bottom, dir);
}
}
private static class PathWithSavedBottom extends Path {
float lastBottom = 0;
@ -2668,6 +2729,45 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
}
}
private static class ScalablePath extends Path {
float lastBottom = 0;
private ArrayList<RectF> rects = new ArrayList<>(1);
private int rectsCount = 0;
@Override
public void reset() {
super.reset();
rects.clear();
rectsCount = 0;
lastBottom = 0;
}
@Override
public void addRect(float left, float top, float right, float bottom, Direction dir) {
rects.add(new RectF(left, top, right, bottom));
rectsCount++;
super.addRect(left, top, right, bottom, dir);
if (bottom > lastBottom) {
lastBottom = bottom;
}
}
public void scaleY(float sy, float cy, Path copyTo) {
if (copyTo != null) {
for (int i = 0; i < rectsCount; ++i) {
RectF rect = rects.get(i);
copyTo.addRect(rect.left, (rect.top - cy) * sy + cy, rect.right, (rect.bottom - cy) * sy + cy, Path.Direction.CW);
}
} else {
super.reset();
for (int i = 0; i < rectsCount; ++i) {
RectF rect = rects.get(i);
super.addRect(rect.left, (rect.top - cy) * sy + cy, rect.right, (rect.bottom - cy) * sy + cy, Path.Direction.CW);
}
}
}
}
public void setKeyboardSize(int keyboardSize) {
this.keyboardSize = keyboardSize;
invalidate();

View File

@ -1376,7 +1376,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
@Override
public void getPaddings(int[] paddings) {
paddings[0] = (int) chatListViewPaddingTop;
paddings[1] = 0;
paddings[1] = blurredViewBottomOffset;
}
@Override
@ -2885,7 +2885,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
blurCanvas.save();
if (top) {
blurCanvas.translate(chatListView.getX() + child.getX(), chatListView.getY() + child.getY());
blurCanvas.translate(chatListView.getX() + child.getX(), chatListView.getY() + child.getY() - contentPanTranslation);
} else {
blurCanvas.translate(chatListView.getX() + child.getX(), chatListView.getTop() + child.getY());
}
@ -6348,29 +6348,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
return true;
});
mentionContainer = new FrameLayout(context) {
private Rect padding;
// private int height = -1, fromHeight = -1, toHeight = -1;
// private long lastHeightUpdate = 0;
// private int getAnimatedHeight(int properHeight) {
// if (height == -1) {
// height = fromHeight = toHeight = properHeight;
// }
// if (height != properHeight) {
// long now = System.currentTimeMillis();
// if (toHeight != properHeight) {
// toHeight = properHeight;
// fromHeight = height;
// lastHeightUpdate = now;
// }
// float t = Math.max(0, Math.min(1, (now - lastHeightUpdate) / 100f));
// t = CubicBezierInterpolator.EASE_BOTH.getInterpolation(t);
// height = AndroidUtilities.lerp(fromHeight, toHeight, t);
// invalidate();
// }
// return height;
// }
@Override
public void onDraw(Canvas canvas) {
@ -6395,7 +6376,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
padding = new Rect();
Theme.chat_composeShadowRoundDrawable.getPadding(padding);
}
int bottom = top + Theme.chat_composeShadowRoundDrawable.getIntrinsicHeight();
Theme.chat_composeShadowRoundDrawable.setBounds(-padding.left, top - padding.top - AndroidUtilities.dp(8), getMeasuredWidth() + padding.right, (int) (bottomPanelTranslationYReverse + getMeasuredHeight()));
Theme.chat_composeShadowRoundDrawable.draw(canvas);
} else {
@ -6405,43 +6385,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
canvas.drawRect(0, bottom, getMeasuredWidth(), bottomPanelTranslationYReverse + getMeasuredHeight(), getThemedPaint(Theme.key_paint_chatComposeBackground));
}
}
// (dkaraush): New design
// int c = canvas.save();
// int scrollY = mentionListView.computeVerticalScrollOffset();
// int scrollOffset;
// if (mentionLayoutManager.getReverseLayout()) {
// scrollOffset = mentionListViewScrollOffsetY;
// float top = mentionListView.getY() + scrollOffset,
// bottom = top + Theme.chat_composeShadowDrawable.getIntrinsicHeight();
// top += AndroidUtilities.dp(2);
// Theme.chat_composeShadowDrawable.setBounds(0, (int) bottom, getMeasuredWidth(), (int) top);
// Theme.chat_composeShadowDrawable.draw(canvas);
// canvas.drawRect(0, 0, getMeasuredWidth(), top, getThemedPaint(Theme.key_paint_chatComposeBackground));
// canvas.clipRect(0, 0, getMeasuredWidth(), top);
// } else {
// scrollOffset = getAnimatedHeight(mentionListViewScrollOffsetY + scrollY) - scrollY;
// float top = mentionListView.getY() + scrollOffset - AndroidUtilities.dp(2);
// if (mentionsAdapter.isMediaLayout()) {
// if ((mentionsAdapter.isStickers() || mentionsAdapter.isBotContext()) && mentionsAdapter.getBotContextSwitch() == null) {
// top -= AndroidUtilities.dp(2);
// }
// if (padding == null) {
// padding = new Rect();
// Theme.chat_composeShadowRoundDrawable.getPadding(padding);
// }
// Theme.chat_composeShadowRoundDrawable.setBounds(-padding.left, (int) top - padding.top - AndroidUtilities.dp(8), getMeasuredWidth() + padding.right, (int) (bottomPanelTranslationYReverse + getMeasuredHeight()));
// Theme.chat_composeShadowRoundDrawable.draw(canvas);
// } else {
// float bottom = top + Theme.chat_composeShadowDrawable.getIntrinsicHeight();
// Theme.chat_composeShadowDrawable.setBounds(0, (int) top, getMeasuredWidth(), (int) bottom);
// Theme.chat_composeShadowDrawable.draw(canvas);
// canvas.drawRect(0, bottom, getMeasuredWidth(), bottomPanelTranslationYReverse + getMeasuredHeight(), getThemedPaint(Theme.key_paint_chatComposeBackground));
// canvas.clipRect(0, bottom, getMeasuredWidth(), bottomPanelTranslationYReverse + getMeasuredHeight());
// }
// }
// super.dispatchDraw(canvas);
// canvas.restoreToCount(c);
}
@Override
@ -6705,14 +6648,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
mentionListView.setClipToPadding(false);
mentionListView.setLayoutManager(mentionLayoutManager);
mentionListView.setOverScrollMode(RecyclerListView.OVER_SCROLL_NEVER);
// DefaultItemAnimator itemAnimator = new DefaultItemAnimator();
// itemAnimator.setRemoveDuration(150);
// itemAnimator.setMoveDuration(150);
// itemAnimator.setAddDuration(150);
// itemAnimator.setChangeDuration(150);
// itemAnimator.setDelayAnimations(false);
// itemAnimator.setTranslationInterpolator(CubicBezierInterpolator.EASE_BOTH);
// mentionListView.setItemAnimator(itemAnimator);
mentionContainer.addView(mentionListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
mentionListView.setAdapter(mentionsAdapter = new MentionsAdapter(context, false, dialog_id, threadMessageId, new MentionsAdapter.MentionsAdapterDelegate() {
@ -6778,11 +6713,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
});
mentionListAnimation.setDuration(200);
// mentionListAnimation.setInterpolator(CubicBezierInterpolator.EASE_BOTH);
mentionListAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT);
mentionListAnimation.start();
} else {
mentionContainer.setAlpha(1.0f);
mentionContainer.setTranslationY(0f);
// mentionContainer.setTranslationY(0f);
mentionContainer.setVisibility(View.INVISIBLE);
updateMessageListAccessibilityVisibility();
}
@ -6820,7 +6755,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
});
mentionListAnimation.setDuration(200);
// mentionListAnimation.setInterpolator(CubicBezierInterpolator.EASE_BOTH);
mentionListAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT);
mentionListAnimation.start();
} else {
mentionContainer.setTag(null);
@ -7141,8 +7076,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
return false;
});
reactionsMentiondownButton.setVisibility(View.INVISIBLE);
contentView.addView(reactionsMentiondownButton, LayoutHelper.createFrame(46, 61, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 7, 5));
reactionsMentiondownButtonImage = new ImageView(context);
reactionsMentiondownButtonImage.setImageResource(R.drawable.reactionbutton);
reactionsMentiondownButtonImage.setScaleType(ImageView.ScaleType.CENTER);
@ -7165,10 +7100,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
drawable = combinedDrawable;
reactionsMentiondownButtonImage.setBackgroundDrawable(drawable);
reactionsMentiondownButton.addView(reactionsMentiondownButtonImage, LayoutHelper.createFrame(46, 46, Gravity.LEFT | Gravity.BOTTOM));
reactionsMentiondownButtonCounter = new CounterView(context, themeDelegate);
reactionsMentiondownButton.addView(reactionsMentiondownButtonCounter, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 28, Gravity.TOP | Gravity.LEFT));
reactionsMentiondownButton.setContentDescription(LocaleController.getString("AccDescrReactionMentionDown", R.string.AccDescrReactionMentionDown));
if (!inMenuMode) {
@ -7256,7 +7189,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
Theme.chat_composeShadowDrawable.setBounds(0, 0, getMeasuredWidth(), bottom);
Theme.chat_composeShadowDrawable.draw(canvas);
AndroidUtilities.rectTmp2.set(0, bottom, getMeasuredWidth(), getMeasuredHeight());
contentView.drawBlur(canvas, getY(), AndroidUtilities.rectTmp2, getThemedPaint(Theme.key_paint_chatComposeBackground), false);
contentView.drawBlurRect(canvas, getY(), AndroidUtilities.rectTmp2, getThemedPaint(Theme.key_paint_chatComposeBackground), false);
}
};
bottomMessagesActionContainer.drawBlur = false;
@ -8015,7 +7948,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
Theme.chat_composeShadowDrawable.draw(canvas);
}
AndroidUtilities.rectTmp2.set(0, bottom, getMeasuredWidth(), getMeasuredHeight());
contentView.drawBlur(canvas, getY(), AndroidUtilities.rectTmp2, getThemedPaint(Theme.key_paint_chatComposeBackground), false);
contentView.drawBlurRect(canvas, getY(), AndroidUtilities.rectTmp2, getThemedPaint(Theme.key_paint_chatComposeBackground), false);
}
@Override
@ -8181,7 +8114,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
backgroundPaint.setColor(getThemedColor(Theme.key_chat_messagePanelBackground));
AndroidUtilities.rectTmp2.set(0, bottom, getMeasuredWidth(), getMeasuredHeight());
contentView.drawBlur(canvas, getY(), AndroidUtilities.rectTmp2, backgroundPaint, false);
contentView.drawBlurRect(canvas, getY(), AndroidUtilities.rectTmp2, backgroundPaint, false);
} else {
canvas.drawRect(0, bottom, getMeasuredWidth(), getMeasuredHeight(), getThemedPaint(Theme.key_paint_chatComposeBackground));
}
@ -9715,16 +9648,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
child = mentionListView.getChildAt(0);
holder = (RecyclerListView.Holder) mentionListView.findContainingViewHolder(child);
int newOffset = child.getBottom() < mentionListView.getMeasuredHeight() && holder != null && holder.getAdapterPosition() == 0 ? child.getBottom() : mentionListView.getMeasuredHeight();;
// if (child.getBottom() < mentionListView.getMeasuredHeight() && holder != null) {
// if (holder.getAdapterPosition() == 0) {
// newOffset = child.getBottom();
// } else {
// newOffset = 0;
// }
// } else {
// newOffset = mentionListView.getMeasuredHeight();
// }
int newOffset = child.getBottom() < mentionListView.getMeasuredHeight() && holder != null && holder.getAdapterPosition() == 0 ? child.getBottom() : mentionListView.getMeasuredHeight();
if (mentionListViewScrollOffsetY != newOffset) {
mentionListView.setBottomGlowOffset(mentionListViewScrollOffsetY = newOffset);
mentionListView.setTopGlowOffset(0);
@ -9741,16 +9665,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
child = mentionListView.getChildAt(0);
holder = (RecyclerListView.Holder) mentionListView.findContainingViewHolder(child);
int newOffset = child.getTop() > 0 && holder != null && holder.getAdapterPosition() == 0 ? child.getTop() : 0;;
// if (child.getTop() > 0 && holder != null) {
// if (holder.getAdapterPosition() == 0) {
// newOffset = child.getTop();
// } else {
// newOffset = mentionListView.getMeasuredHeight();
// }
// } else {
// newOffset = 0;
// }
int newOffset = child.getTop() > 0 && holder != null && holder.getAdapterPosition() == 0 ? child.getTop() : 0;
if (mentionListViewScrollOffsetY != newOffset) {
mentionListView.setTopGlowOffset(mentionListViewScrollOffsetY = newOffset);
mentionListView.setBottomGlowOffset(0);
@ -9887,7 +9802,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
editingMessageObject = chatAttachAlert.getEditingMessageObject();
if (button == 8 || button == 7 || button == 4 && !chatAttachAlert.getPhotoLayout().getSelectedPhotos().isEmpty()) {
if (button != 8) {
chatAttachAlert.dismiss();
chatAttachAlert.dismiss(true);
}
HashMap<Object, Object> selectedPhotos = chatAttachAlert.getPhotoLayout().getSelectedPhotos();
ArrayList<Object> selectedPhotosOrder = chatAttachAlert.getPhotoLayout().getSelectedPhotosOrder();
@ -9899,7 +9814,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (i * 10 + a >= selectedPhotosOrder.size()) {
continue;
}
MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) selectedPhotos.get(selectedPhotosOrder.get(i + a));
MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) selectedPhotos.get(selectedPhotosOrder.get(i * 10 + a));
SendMessagesHelper.SendingMediaInfo info = new SendMessagesHelper.SendingMediaInfo();
if (!photoEntry.isVideo && photoEntry.imagePath != null) {
@ -11518,12 +11433,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
replyCloseImageView.setContentDescription(LocaleController.getString("AccDescrCancelReply", R.string.AccDescrCancelReply));
CharSequence replyObjectText = null;
CharSequence sourceText = null;
if (!TextUtils.isEmpty(restrictionReason)) {
replyObjectText = restrictionReason;
} else if (messageObjectToReply.messageOwner.media instanceof TLRPC.TL_messageMediaGame) {
replyObjectText = Emoji.replaceEmoji(messageObjectToReply.messageOwner.media.game.title, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false);
} else if (messageObjectToReply.messageText != null || messageObjectToReply.caption != null) {
String mess = messageObjectToReply.caption != null ? messageObjectToReply.caption.toString() : messageObjectToReply.messageText.toString();
sourceText = mess;
if (mess.length() > 150) {
mess = mess.substring(0, 150);
}
@ -11532,7 +11449,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
if (replyObjectText != null) {
if (replyObjectText instanceof Spannable)
MediaDataController.addTextStyleRuns(messageObjectToReply.messageOwner.entities, messageObjectToReply.caption != null ? messageObjectToReply.caption : messageObjectToReply.messageText, (Spannable) replyObjectText);
MediaDataController.addTextStyleRuns(messageObjectToReply.messageOwner.entities, sourceText, (Spannable) replyObjectText);
replyObjectTextView.setText(replyObjectText);
}
@ -11673,14 +11590,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
} else {
if ((type == -1 || type == 0 || type == 10 || type == 11) && (messageObjectsToForward.size() == 1 && messageObjectsToForward.get(0).messageText != null)) {
MessageObject messageObject = messageObjectsToForward.get(0);
CharSequence mess = SpannableStringBuilder.valueOf(messageObject.messageText);
MediaDataController.addTextStyleRuns(messageObjectsToForward.get(0), (Spannable) mess);
CharSequence mess = new SpannableStringBuilder(messageObject.messageText.toString());
if (mess.length() > 150) {
mess = mess.subSequence(0, 150);
}
mess = AndroidUtilities.replaceNewLines(mess);
Spannable formatted = AndroidUtilities.formatSpannableSimple(LocaleController.getString("ForwardingFromNameAndMessage", R.string.ForwardingFromNameAndMessage), userNames, mess);
replyObjectTextView.setText(Emoji.replaceEmoji(formatted, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false));
mess = Emoji.replaceEmoji(mess, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false);
if (mess instanceof Spannable) {
MediaDataController.addTextStyleRuns(messageObject.messageOwner.entities, messageObject.messageText, (Spannable) mess);
}
replyObjectTextView.setText(mess);
} else {
replyObjectTextView.setText(LocaleController.formatString("ForwardingFromNames", R.string.ForwardingFromNames, userNames));
}
@ -12237,7 +12155,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
updateReactionsMentionButton(true);
}
getMessagesStorage().checkUnviewedDownloads(messageCell.getId(), dialog_id);
getDownloadController().checkUnviewedDownloads(messageCell.getId(), dialog_id);
} else if (view instanceof ChatActionCell) {
ChatActionCell cell = (ChatActionCell) view;
messageObject = cell.getMessageObject();
@ -17091,7 +17009,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
lastCallCheckFromServer = !openAnimationEnded;
return;
}
VoIPHelper.startCall(currentChat, null, voiceChatHash, createGroupCall, getParentActivity(), ChatActivity.this, getAccountInstance());
VoIPHelper.startCall(currentChat, null, voiceChatHash, createGroupCall, !groupCall.call.rtmp_stream, getParentActivity(), ChatActivity.this, getAccountInstance());
voiceChatHash = null;
}
@ -17795,7 +17713,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
int sponsoredMessagesCount = getSponsoredMessagesCount();
if (!isAd && placeToPaste < sponsoredMessagesCount && (currentChat == null || !ChatObject.isChannelAndNotMegaGroup(currentChat))) {
if (!isAd && placeToPaste < sponsoredMessagesCount && (currentChat == null || ChatObject.isChannelAndNotMegaGroup(currentChat))) {
placeToPaste = sponsoredMessagesCount;
}
if (dayArray == null) {
@ -20773,6 +20691,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
"[\u00A9\u00AE]\uFE0F?|[\u2122\u2139]\uFE0F?|\uD83C\uDC04\uFE0F?|\uD83C\uDCCF\uFE0F?|" +
"[\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA]\uFE0F?)+");
}
@SuppressLint("ClickableViewAccessibility")
private void createMenu(View v, boolean single, boolean listView, float x, float y, boolean searchGroup) {
if (actionBar.isActionModeShowed() || reportType >= 0) {
return;
@ -21419,7 +21338,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
count += r.count;
}
}
boolean hasHeader = count > 10;
boolean hasHeader = count > 10 && message.messageOwner.reactions.results.size() > 1;
LinearLayout linearLayout = new LinearLayout(contentView.getContext()) {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
@ -21427,6 +21346,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (size < AndroidUtilities.dp(240)) {
size = AndroidUtilities.dp(240);
}
if (size < 0) {
size = 0;
}
super.onMeasure(MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY), heightMeasureSpec);
}
};
@ -21449,12 +21371,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
HorizontalScrollView tabsScrollView = new HorizontalScrollView(contentView.getContext());
AtomicBoolean suppressTabsScroll = new AtomicBoolean();
int size = counters.size() + 1;
boolean showAllReactionsTab = counters.size() > 1;
int size = counters.size() + (showAllReactionsTab ? 1 : 0);
for (int i = 0; i < size; i++) {
ReactionTabHolderView hv = new ReactionTabHolderView(contentView.getContext());
if (i == 0) {
int index = i;
if (showAllReactionsTab) {
index--;
}
if (index < 0) {
hv.setCounter(count);
} else hv.setCounter(currentAccount, counters.get(i - 1));
} else {
hv.setCounter(currentAccount, counters.get(index));
}
int finalI = i;
hv.setOnClickListener(v1 -> {
int from = pager.getCurrentItem();
@ -21487,12 +21416,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
int head = AndroidUtilities.dp(44 * 2) + 1;
SparseArray<ReactedUsersListView> cachedViews = new SparseArray<>();
SparseIntArray cachedHeights = new SparseIntArray();
for (int i = 0; i < counters.size() + 1; i++)
for (int i = 0; i < counters.size() + 1; i++) {
cachedHeights.put(i, head + AndroidUtilities.dp(ReactedUsersListView.ITEM_HEIGHT_DP * ReactedUsersListView.VISIBLE_ITEMS));
}
pager.setAdapter(new PagerAdapter() {
@Override
public int getCount() {
return counters.size() + 1;
return size;
}
@Override
@ -21507,7 +21437,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
container.addView(cached);
return cached;
}
ReactedUsersListView v = new ReactedUsersListView(container.getContext(), themeDelegate, currentAccount, message, position == 0 ? null : counters.get(position - 1), true)
int index = position;
if (showAllReactionsTab) {
index--;
}
TLRPC.TL_reactionCount reactionCount = null;
if (index >= 0) {
reactionCount = counters.get(index);
}
ReactedUsersListView v = new ReactedUsersListView(container.getContext(), themeDelegate, currentAccount, message, reactionCount, true)
.setSeenUsers(reactedView.getSeenUsers())
.setOnProfileSelectedListener((view, userId) -> {
Bundle args = new Bundle();
@ -21520,8 +21458,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (pager.getCurrentItem() == position)
popupLayout.getSwipeBack().setNewForegroundHeight(foregroundIndex[0], head + newHeight);
});
if (position == 0)
if (index < 0) {
reactedView.setSeenCallback(v::setSeenUsers);
}
container.addView(v);
cachedViews.put(position, v);
@ -21781,7 +21720,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
},
(Exception e) -> {
FileLog.e("mlkit: failed to detect language in message");
e.printStackTrace();
waitForLangDetection.set(false);
if (onLangDetectionDone.get() != null) {
onLangDetectionDone.get().run();
@ -21867,13 +21805,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
LinearLayout.LayoutParams params = LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 52 + pad, Gravity.RIGHT, 0, 50, 0, -20);
scrimPopupContainerLayout.addView(reactionsLayout, params);
scrimPopupContainerLayout.reactionsLayout = reactionsLayout;
scrimPopupContainerLayout.setReactionsLayout(reactionsLayout);
scrimPopupContainerLayout.setClipChildren(false);
reactionsLayout.setMessage(message, chatInfo);
reactionsLayout.setTransitionProgress(0);
if (popupLayout.getSwipeBack() != null) {
popupLayout.getSwipeBack().setOnSwipeBackProgressListener((layout, toProgress, progress) -> {
popupLayout.getSwipeBack().addOnSwipeBackProgressListener((layout, toProgress, progress) -> {
if (toProgress == 0) {
reactionsLayout.startEnterAnimation();
} else if (toProgress == 1)
@ -21884,7 +21822,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
boolean showNoForwards = noforwards && message.messageOwner.action == null && message.isSent() && !message.isEditing() && chatMode != MODE_SCHEDULED;
scrimPopupContainerLayout.addView(popupLayout, LayoutHelper.createLinearRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT, isReactionsAvailable ? 16 : 0, 0, isReactionsAvailable ? 36 : 0, 0));
scrimPopupContainerLayout.popupWindowLayout = popupLayout;
scrimPopupContainerLayout.setPopupWindowLayout(popupLayout);
if (showNoForwards) {
popupLayout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
boolean isChannel = ChatObject.isChannel(currentChat) && !currentChat.megagroup;
@ -21906,6 +21844,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
fl.setBackground(shadowDrawable2);
fl.addView(tv, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 11, 11, 11, 11));
scrimPopupContainerLayout.addView(fl, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT, isReactionsAvailable ? 16 : 0, -8, isReactionsAvailable ? 36 : 0, 0));
scrimPopupContainerLayout.applyViewBottom(fl);
}
scrimPopupWindow = new ActionBarPopupWindow(scrimPopupContainerLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) {
@ -25908,7 +25847,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
public void notifyDataSetChanged(boolean animated) {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("notify data set changed");
FileLog.d("notify data set changed fragmentOpened=" + fragmentOpened);
}
if (animated && fragmentOpened) {
if (chatListView.getItemAnimator() != chatListItemAnimator) {
@ -26930,6 +26869,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (isOpen && fromPullingDownTransition && getParentLayout().fragmentsStack.size() > 1) {
BaseFragment previousFragment = getParentLayout().fragmentsStack.get(getParentLayout().fragmentsStack.size() - 2);
if (previousFragment instanceof ChatActivity) {
wasManualScroll = true;
ChatActivity previousChat = (ChatActivity) previousFragment;
previousChat.setTransitionToChatActivity(this);
fragmentView.setAlpha(0);
@ -26978,8 +26918,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
@Override
public void onAnimationEnd(Animator animation) {
fragmentOpened = true;
fragmentBeginToShow = true;
fragmentTransition = null;
NotificationCenter.getInstance(currentAccount).onAnimationFinish(index);
AndroidUtilities.runOnUIThread(() -> {
NotificationCenter.getInstance(currentAccount).onAnimationFinish(index);
}, 32);
super.onAnimationEnd(animation);
contentView.invalidate();
contentView.setSkipBackgroundDrawing(false);

View File

@ -614,7 +614,7 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC
canvas.restore();
}
textPaint2.setAlpha(oldAlpha);
textPaint2.setAlpha(oldAlphaText);
composeBackgroundPaint.setAlpha(oldAlpha);
}

View File

@ -76,6 +76,7 @@ import org.telegram.messenger.MessagesController;
import org.telegram.messenger.MessagesStorage;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.NotificationsController;
import org.telegram.messenger.OneUIUtilities;
import org.telegram.messenger.R;
import org.telegram.messenger.SecretChatHelper;
import org.telegram.messenger.SharedConfig;
@ -150,10 +151,11 @@ public class AlertsCreator {
public static Dialog createBackgroundActivityDialog(Context ctx) {
return new AlertDialog.Builder(ctx)
.setTitle(LocaleController.getString("AllowBackgroundActivity", R.string.AllowBackgroundActivity))
.setMessage(LocaleController.getString("AllowBackgroundActivityInfo", R.string.AllowBackgroundActivityInfo))
.setTitle(LocaleController.getString(R.string.AllowBackgroundActivity))
.setMessage(AndroidUtilities.replaceTags(LocaleController.getString(OneUIUtilities.isOneUI() ? Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ? R.string.AllowBackgroundActivityInfoOneUIAboveS :
R.string.AllowBackgroundActivityInfoOneUIBelowS : R.string.AllowBackgroundActivityInfo)))
.setTopAnimation(R.raw.permission_request_apk, PERMISSIONS_REQUEST_TOP_ICON_SIZE, false, Theme.getColor(Theme.key_dialogTopBackground))
.setPositiveButton(LocaleController.getString("PermissionOpenSettings", R.string.PermissionOpenSettings), (dialogInterface, i) -> {
.setPositiveButton(LocaleController.getString(R.string.PermissionOpenSettings), (dialogInterface, i) -> {
try {
Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + ApplicationLoader.applicationContext.getPackageName()));

View File

@ -89,6 +89,7 @@ import org.telegram.ui.ActionBar.BottomSheet;
import org.telegram.ui.ActionBar.SimpleTextView;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Adapters.FiltersView;
import org.telegram.ui.Cells.AudioPlayerCell;
import org.telegram.ui.ChatActivity;
import org.telegram.ui.DialogsActivity;
@ -595,14 +596,14 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
if (parentActivity.getActionBarLayout().getLastFragment() instanceof DialogsActivity) {
DialogsActivity dialogsActivity = (DialogsActivity) parentActivity.getActionBarLayout().getLastFragment();
if (!dialogsActivity.onlyDialogsAdapter()) {
dialogsActivity.setShowSearch(query, 4);
dialogsActivity.setShowSearch(query, FiltersView.FILTER_INDEX_MUSIC);
dismiss();
return;
}
}
DialogsActivity fragment = new DialogsActivity(null);
fragment.setSearchString(query);
fragment.setInitialSearchType(4);
fragment.setInitialSearchType(FiltersView.FILTER_INDEX_MUSIC);
parentActivity.presentFragment(fragment, false, false);
dismiss();
});

View File

@ -18,6 +18,9 @@ import android.os.Build;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.Log;
import android.util.LruCache;
import android.util.Pair;
import androidx.core.graphics.ColorUtils;
@ -28,6 +31,8 @@ import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import java.util.Objects;
public class AvatarDrawable extends Drawable {
private TextPaint namePaint;

View File

@ -60,8 +60,25 @@ public class AvatarsDarawable {
private float overrideAlpha = 1f;
public long transitionDuration = 220;
public Interpolator transitionInterpolator = CubicBezierInterpolator.DEFAULT;
private boolean transitionInProgress;
public void commitTransition(boolean animated) {
commitTransition(animated, true);
}
public void setTransitionProgress(float transitionProgress) {
if (transitionInProgress) {
if (this.transitionProgress != transitionProgress) {
this.transitionProgress = transitionProgress;
if (transitionProgress == 1f) {
swapStates();
transitionInProgress = false;
}
}
}
}
public void commitTransition(boolean animated, boolean createAnimator) {
if (!wasDraw || !animated) {
transitionProgress = 1f;
swapStates();
@ -112,33 +129,41 @@ public class AvatarsDarawable {
}
if (transitionProgressAnimator != null) {
transitionProgressAnimator.cancel();
if (transitionInProgress) {
swapStates();
transitionInProgress = false;
}
}
transitionProgress = 0;
transitionProgressAnimator = ValueAnimator.ofFloat(0, 1f);
transitionProgressAnimator.addUpdateListener(valueAnimator -> {
transitionProgress = (float) valueAnimator.getAnimatedValue();
invalidate();
});
transitionProgressAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (transitionProgressAnimator != null) {
transitionProgress = 1f;
swapStates();
if (updateAfterTransition) {
updateAfterTransition = false;
if (updateDelegate != null) {
updateDelegate.run();
if (createAnimator) {
transitionProgressAnimator = ValueAnimator.ofFloat(0, 1f);
transitionProgressAnimator.addUpdateListener(valueAnimator -> {
transitionProgress = (float) valueAnimator.getAnimatedValue();
invalidate();
});
transitionProgressAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (transitionProgressAnimator != null) {
transitionProgress = 1f;
swapStates();
if (updateAfterTransition) {
updateAfterTransition = false;
if (updateDelegate != null) {
updateDelegate.run();
}
}
invalidate();
}
invalidate();
transitionProgressAnimator = null;
}
transitionProgressAnimator = null;
}
});
transitionProgressAnimator.setDuration(transitionDuration);
transitionProgressAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT);
transitionProgressAnimator.start();
});
transitionProgressAnimator.setDuration(transitionDuration);
transitionProgressAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT);
transitionProgressAnimator.start();
} else {
transitionInProgress = true;
}
invalidate();
}
@ -173,9 +198,13 @@ public class AvatarsDarawable {
overrideSize = size;
}
public void animateFromState(AvatarsDarawable avatarsDarawable, int currentAccount) {
public void animateFromState(AvatarsDarawable avatarsDarawable, int currentAccount, boolean createAnimator) {
if (avatarsDarawable.transitionProgressAnimator != null) {
avatarsDarawable.transitionProgressAnimator.cancel();
if (transitionInProgress) {
transitionInProgress = false;
swapStates();
}
}
TLObject[] objects = new TLObject[3];
for (int i = 0; i < 3; i++) {
@ -187,7 +216,7 @@ public class AvatarsDarawable {
setObject(i, currentAccount, objects[i]);
}
wasDraw = true;
commitTransition(true);
commitTransition(true, createAnimator);
}
public void setAlpha(float alpha) {
@ -221,13 +250,13 @@ public class AvatarsDarawable {
this.parent = parent;
for (int a = 0; a < 3; a++) {
currentStates[a] = new DrawingState();
currentStates[a].imageReceiver = new ImageReceiver();
currentStates[a].imageReceiver = new ImageReceiver(parent);
currentStates[a].imageReceiver.setRoundRadius(AndroidUtilities.dp(12));
currentStates[a].avatarDrawable = new AvatarDrawable();
currentStates[a].avatarDrawable.setTextSize(AndroidUtilities.dp(12));
animatingStates[a] = new DrawingState();
animatingStates[a].imageReceiver = new ImageReceiver();
animatingStates[a].imageReceiver = new ImageReceiver(parent);
animatingStates[a].imageReceiver.setRoundRadius(AndroidUtilities.dp(12));
animatingStates[a].avatarDrawable = new AvatarDrawable();
animatingStates[a].avatarDrawable.setTextSize(AndroidUtilities.dp(12));

View File

@ -41,7 +41,7 @@ public class BlurredFrameLayout extends FrameLayout {
y += view.getY();
view = (View) view.getParent();
}
sizeNotifierFrameLayout.drawBlur(canvas, y, AndroidUtilities.rectTmp2, backgroundPaint, isTopView);
sizeNotifierFrameLayout.drawBlurRect(canvas, y, AndroidUtilities.rectTmp2, backgroundPaint, isTopView);
}
super.dispatchDraw(canvas);
}

View File

@ -43,7 +43,7 @@ public class BlurredLinearLayout extends LinearLayout {
y += view.getY();
view = (View) view.getParent();
}
sizeNotifierFrameLayout.drawBlur(canvas, y, AndroidUtilities.rectTmp2, backgroundPaint, isTopView);
sizeNotifierFrameLayout.drawBlurRect(canvas, y, AndroidUtilities.rectTmp2, backgroundPaint, isTopView);
}
super.dispatchDraw(canvas);
}

View File

@ -2549,6 +2549,9 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
AndroidUtilities.runOnUIThread(()->{
if (senderSelectPopupWindow == null) {
return;
}
Dialog d = new Dialog(getContext(), R.style.TransparentDialogNoAnimation);
FrameLayout aFrame = new FrameLayout(getContext());
aFrame.addView(avatar, LayoutHelper.createFrame(SenderSelectPopup.AVATAR_SIZE_DP, SenderSelectPopup.AVATAR_SIZE_DP, Gravity.LEFT));
@ -3108,9 +3111,13 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
cancelBotButton = new ImageView(context);
cancelBotButton.setVisibility(INVISIBLE);
cancelBotButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
cancelBotButton.setImageDrawable(progressDrawable = new CloseProgressDrawable2());
cancelBotButton.setImageDrawable(progressDrawable = new CloseProgressDrawable2() {
@Override
protected int getCurrentColor() {
return Theme.getColor(Theme.key_chat_messagePanelCancelInlineBot);
}
});
cancelBotButton.setContentDescription(LocaleController.getString("Cancel", R.string.Cancel));
progressDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_messagePanelCancelInlineBot), PorterDuff.Mode.MULTIPLY));
cancelBotButton.setSoundEffectsEnabled(false);
cancelBotButton.setScaleX(0.1f);
cancelBotButton.setScaleY(0.1f);
@ -3441,7 +3448,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
backgroundPaint.setColor(getThemedColor(Theme.key_chat_messagePanelBackground));
if (SharedConfig.chatBlurEnabled() && sizeNotifierLayout != null) {
AndroidUtilities.rectTmp2.set(0, bottom, getWidth(), getHeight());
sizeNotifierLayout.drawBlur(canvas, getTop(), AndroidUtilities.rectTmp2, backgroundPaint, false);
sizeNotifierLayout.drawBlurRect(canvas, getTop(), AndroidUtilities.rectTmp2, backgroundPaint, false);
} else {
canvas.drawRect(0, bottom, getWidth(), getHeight(), backgroundPaint);
}
@ -6651,7 +6658,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
}
boolean wasVisible = senderSelectView.getVisibility() == View.VISIBLE;
boolean isVisible = delegate.getSendAsPeers() != null && defPeer != null && delegate.getSendAsPeers().peers.size() > 1 &&
boolean isVisible = defPeer != null && (delegate.getSendAsPeers() == null || delegate.getSendAsPeers().peers.size() > 1) &&
!isEditingMessage() && !isRecordingAudioVideo() && recordedAudioPanel.getVisibility() != View.VISIBLE;
int pad = AndroidUtilities.dp(2);
MarginLayoutParams params = (MarginLayoutParams) senderSelectView.getLayoutParams();

View File

@ -16,6 +16,7 @@ import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Canvas;
@ -56,7 +57,9 @@ import android.widget.TextView;
import androidx.annotation.Keep;
import androidx.core.graphics.ColorUtils;
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.FloatValueHolder;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -64,7 +67,6 @@ import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaController;
import org.telegram.messenger.MediaDataController;
@ -137,17 +139,10 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
if (nextAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview) {
currentAttachLayout.setTranslationX(value * -width);
nextAttachLayout.setTranslationX((1f - value) * width);
if (currentAttachLayout instanceof ChatAttachAlertPhotoLayout) {
((ChatAttachAlertPhotoLayout) currentAttachLayout).checkCameraViewPosition();
}
} else {
currentAttachLayout.setTranslationX(value * width);
nextAttachLayout.setTranslationX(-width * (1f - value));
if (nextAttachLayout instanceof ChatAttachAlertPhotoLayout) {
((ChatAttachAlertPhotoLayout) nextAttachLayout).checkCameraViewPosition();
}
}
updateLayout(currentAttachLayout, false, 0);
} else {
if (value > 0.7f) {
float alpha = 1.0f - (1.0f - value) / 0.3f;
@ -824,11 +819,11 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
}
int keyboardSize = measureKeyboardHeight();
int paddingBottom;
int paddingBottom = getPaddingBottom();
if (SharedConfig.smoothKeyboard && keyboardVisible) {
paddingBottom = 0;
paddingBottom += 0;
} else {
paddingBottom = keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? commentTextView.getEmojiPadding() : 0;
paddingBottom += keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? commentTextView.getEmojiPadding() : 0;
}
setBottomClip(paddingBottom);
@ -1061,7 +1056,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
}
}
boolean clip = !drawBackground && (headerView != null && headerView.getAlpha() > .9f) && (currentAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview || nextAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview) && (viewChangeAnimator instanceof Animator && ((Animator) viewChangeAnimator).isRunning());
boolean clip = !drawBackground && (headerView != null && headerView.getAlpha() > .9f) && (currentAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview || nextAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview) && (viewChangeAnimator instanceof SpringAnimation && ((SpringAnimation) viewChangeAnimator).isRunning());
if (clip) {
canvas.save();
int finalMove;
@ -1137,7 +1132,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
@Override
protected void dispatchDraw(Canvas canvas) {
canvas.save();
canvas.clipRect(0, getPaddingTop() + currentPanTranslationY, getMeasuredWidth(), getMeasuredHeight() + currentPanTranslationY);
canvas.clipRect(0, getPaddingTop() + currentPanTranslationY, getMeasuredWidth(), getMeasuredHeight() + currentPanTranslationY - getPaddingBottom());
if (currentAttachLayout == photoPreviewLayout || nextAttachLayout == photoPreviewLayout || (currentAttachLayout == photoLayout && nextAttachLayout == null)) {
drawChildBackground(canvas, currentAttachLayout);
}
@ -1394,8 +1389,8 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
@Override
public void setAlpha(float alpha) {
selectedView.setAlpha(1f - alpha);
selectedView.setTranslationX(alpha * -AndroidUtilities.dp(8));
mediaPreviewView.setTranslationX((1f - alpha) * AndroidUtilities.dp(8));
selectedView.setTranslationX(alpha * -AndroidUtilities.dp(16));
mediaPreviewView.setTranslationX((1f - alpha) * AndroidUtilities.dp(16));
super.setAlpha(alpha);
}
};
@ -1818,6 +1813,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
sendPressed(notify, scheduleDate);
} else {
currentAttachLayout.sendSelectedItems(notify, scheduleDate);
allowPassConfirmationAlert = true;
dismiss();
}
}, resourcesProvider);
@ -1826,6 +1822,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
sendPressed(true, 0);
} else {
currentAttachLayout.sendSelectedItems(true, 0);
allowPassConfirmationAlert = true;
dismiss();
}
}
@ -1845,7 +1842,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
sendPopupLayout.setAnimationEnabled(false);
sendPopupLayout.setOnTouchListener(new View.OnTouchListener() {
private android.graphics.Rect popupRect = new android.graphics.Rect();
private Rect popupRect = new Rect();
@Override
public boolean onTouch(View v, MotionEvent event) {
@ -1983,9 +1980,8 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
openTransitionFinished = false;
if (Build.VERSION.SDK_INT >= 30) {
int color = getThemedColor(Theme.key_windowBackgroundGray);
if (AndroidUtilities.computePerceivedBrightness(color) < 0.721) {
getWindow().setNavigationBarColor(color);
}
getWindow().setNavigationBarColor(color);
AndroidUtilities.setLightNavigationBar(getWindow(), AndroidUtilities.computePerceivedBrightness(color) > 0.721);
}
}
@ -2072,6 +2068,9 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
actionBar.closeSearchField();
}
currentAttachLayout.onHide();
if (nextAttachLayout == photoLayout) {
photoLayout.setCheckCameraWhenShown(true);
}
nextAttachLayout.onShow(currentAttachLayout);
nextAttachLayout.setVisibility(View.VISIBLE);
@ -2083,38 +2082,6 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
containerView.addView(nextAttachLayout, nextAttachLayout == locationLayout ? index : index + 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
}
AnimatorSet animator = new AnimatorSet();
if (!(currentAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview || nextAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview)) {
nextAttachLayout.setAlpha(0.0f);
nextAttachLayout.setTranslationY(AndroidUtilities.dp(78));
animator.playTogether(
ObjectAnimator.ofFloat(currentAttachLayout, View.TRANSLATION_Y, AndroidUtilities.dp(78) + t)
);
animator.setInterpolator(CubicBezierInterpolator.DEFAULT);
} else {
int width = Math.max(nextAttachLayout.getWidth(), currentAttachLayout.getWidth());
if (nextAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview) {
// nextAttachLayout.bringToFront();
nextAttachLayout.setTranslationX(width);
if (currentAttachLayout instanceof ChatAttachAlertPhotoLayout) {
((ChatAttachAlertPhotoLayout) currentAttachLayout).checkCameraViewPosition();
}
} else {
currentAttachLayout.setTranslationX(-width);
if (nextAttachLayout instanceof ChatAttachAlertPhotoLayout) {
((ChatAttachAlertPhotoLayout) nextAttachLayout).checkCameraViewPosition();
}
}
nextAttachLayout.setAlpha(1);
currentAttachLayout.setAlpha(1);
ATTACH_ALERT_LAYOUT_TRANSLATION.set(currentAttachLayout, 0.0f);
animator.setInterpolator(CubicBezierInterpolator.EASE_BOTH);
}
animator.playTogether(
ObjectAnimator.ofFloat(currentAttachLayout, ATTACH_ALERT_LAYOUT_TRANSLATION, 0.0f, 1.0f)
);
animator.setDuration(180);
animator.setStartDelay(20);
Runnable onEnd = () -> {
if (Build.VERSION.SDK_INT >= 20) {
container.setLayerType(View.LAYER_TYPE_NONE, null);
@ -2130,10 +2097,21 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
nextAttachLayout = null;
scrollOffsetY[0] = scrollOffsetY[1];
};
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (!(nextAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview || currentAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview)) {
if (!(currentAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview || nextAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview)) {
AnimatorSet animator = new AnimatorSet();
nextAttachLayout.setAlpha(0.0f);
nextAttachLayout.setTranslationY(AndroidUtilities.dp(78));
animator.playTogether(
ObjectAnimator.ofFloat(currentAttachLayout, View.TRANSLATION_Y, AndroidUtilities.dp(78) + t),
ObjectAnimator.ofFloat(currentAttachLayout, ATTACH_ALERT_LAYOUT_TRANSLATION, 0.0f, 1.0f)
);
animator.setDuration(180);
animator.setStartDelay(20);
animator.setInterpolator(CubicBezierInterpolator.DEFAULT);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
currentAttachLayout.setAlpha(0.0f);
SpringAnimation springAnimation = new SpringAnimation(nextAttachLayout, DynamicAnimation.TRANSLATION_Y, 0);
springAnimation.getSpring().setDampingRatio(0.75f);
@ -2150,18 +2128,57 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
});
viewChangeAnimator = springAnimation;
springAnimation.start();
} else {
currentAttachLayout.onHideShowProgress(1f);
nextAttachLayout.onHideShowProgress(1f);
currentAttachLayout.onContainerTranslationUpdated(currentPanTranslationY);
nextAttachLayout.onContainerTranslationUpdated(currentPanTranslationY);
containerView.invalidate();
onEnd.run();
}
});
viewChangeAnimator = animator;
animator.start();
} else {
int width = Math.max(nextAttachLayout.getWidth(), currentAttachLayout.getWidth());
if (nextAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview) {
nextAttachLayout.setTranslationX(width);
if (currentAttachLayout instanceof ChatAttachAlertPhotoLayout) {
ChatAttachAlertPhotoLayout photoLayout = (ChatAttachAlertPhotoLayout) currentAttachLayout;
if (photoLayout.cameraView != null) {
photoLayout.cameraView.setVisibility(View.INVISIBLE);
photoLayout.cameraIcon.setVisibility(View.INVISIBLE);
photoLayout.cameraCell.setVisibility(View.VISIBLE);
}
}
} else {
currentAttachLayout.setTranslationX(-width);
if (nextAttachLayout == photoLayout) {
ChatAttachAlertPhotoLayout photoLayout = (ChatAttachAlertPhotoLayout) nextAttachLayout;
if (photoLayout.cameraView != null) {
photoLayout.cameraView.setVisibility(View.VISIBLE);
photoLayout.cameraIcon.setVisibility(View.VISIBLE);
}
}
}
});
viewChangeAnimator = animator;
animator.start();
nextAttachLayout.setAlpha(1);
currentAttachLayout.setAlpha(1);
ATTACH_ALERT_LAYOUT_TRANSLATION.set(currentAttachLayout, 0.0f);
SpringAnimation springAnimation = new SpringAnimation(new FloatValueHolder(0));
springAnimation.addUpdateListener((animation, value, velocity) -> {
float f = value / 500f;
ATTACH_ALERT_LAYOUT_TRANSLATION.set(currentAttachLayout, f);
mediaPreviewView.setAlpha(nextAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview ? f : 1f - f);
});
springAnimation.addEndListener((animation, canceled, value, velocity) -> {
currentAttachLayout.onHideShowProgress(1f);
nextAttachLayout.onHideShowProgress(1f);
currentAttachLayout.onContainerTranslationUpdated(currentPanTranslationY);
nextAttachLayout.onContainerTranslationUpdated(currentPanTranslationY);
containerView.invalidate();
onEnd.run();
});
springAnimation.setSpring(new SpringForce(500f));
springAnimation.getSpring().setDampingRatio(1f);
springAnimation.getSpring().setStiffness(1000.0f);
springAnimation.start();
viewChangeAnimator = springAnimation;
}
}
public void updatePhotoPreview(boolean show) {
@ -2173,10 +2190,8 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
photoPreviewLayout = new ChatAttachAlertPhotoLayoutPreview(this, getContext(), parentThemeDelegate);
photoPreviewLayout.bringToFront();
}
updateMediaPreview(currentAttachLayout != photoPreviewLayout, true);
showLayout(currentAttachLayout == photoPreviewLayout ? photoLayout : photoPreviewLayout);
} else {
updateMediaPreview(false, true);
showLayout(photoLayout);
}
}
@ -2439,7 +2454,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
@Override
protected boolean onCustomOpenAnimation() {
photoLayout.setTranslationX(0);
updateMediaPreview(false, false);
mediaPreviewView.setAlpha(0);
int fromTranslationY = super.containerView.getMeasuredHeight();
super.containerView.setTranslationY(fromTranslationY);
@ -2451,6 +2466,9 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
ATTACH_ALERT_PROGRESS.set(this, 0.0f);
buttonsAnimation.start();
if (appearSpringAnimation != null) {
appearSpringAnimation.cancel();
}
appearSpringAnimation = new SpringAnimation(super.containerView, DynamicAnimation.TRANSLATION_Y, 0);
appearSpringAnimation.getSpring().setDampingRatio(0.75f);
appearSpringAnimation.getSpring().setStiffness(350.0f);
@ -2733,20 +2751,8 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
}
}
@SuppressLint("NewApi")
protected void updateLayout(AttachAlertLayout layout, boolean animated, int dy) {
if (layout == null) {
return;
}
int newOffset = layout.getCurrentItemTop();
if (newOffset == Integer.MAX_VALUE) {
return;
}
boolean show = layout == currentAttachLayout && newOffset <= layout.getButtonsHideOffset();
if (currentAttachLayout != photoPreviewLayout && keyboardVisible && animated) {
animated = false;
}
if (layout == currentAttachLayout && (show && actionBar.getTag() == null || !show && actionBar.getTag() != null)) {
private void updateActionBarVisibility(boolean show, boolean animated) {
if (show && actionBar.getTag() == null || !show && actionBar.getTag() != null) {
actionBar.setTag(show ? 1 : null);
if (actionBarAnimation != null) {
actionBarAnimation.cancel();
@ -2822,10 +2828,28 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
}
}
}
}
@SuppressLint("NewApi")
protected void updateLayout(AttachAlertLayout layout, boolean animated, int dy) {
if (layout == null) {
return;
}
int newOffset = layout.getCurrentItemTop();
if (newOffset == Integer.MAX_VALUE) {
return;
}
boolean show = layout == currentAttachLayout && newOffset <= layout.getButtonsHideOffset();
if (currentAttachLayout != photoPreviewLayout && keyboardVisible && animated) {
animated = false;
}
if (layout == currentAttachLayout) {
updateActionBarVisibility(show, animated);
}
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) layout.getLayoutParams();
newOffset += (layoutParams == null ? 0 : layoutParams.topMargin) - AndroidUtilities.dp(11);
int idx = currentAttachLayout == layout ? 0 : 1;
boolean previewAnimationIsRunning = (currentAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview || nextAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview) && (viewChangeAnimator instanceof Animator && ((Animator) viewChangeAnimator).isRunning());
boolean previewAnimationIsRunning = (currentAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview || nextAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview) && (viewChangeAnimator instanceof SpringAnimation && ((SpringAnimation) viewChangeAnimator).isRunning());
if (scrollOffsetY[idx] != newOffset || previewAnimationIsRunning) {
previousScrollOffsetY = scrollOffsetY[idx];
scrollOffsetY[idx] = newOffset;
@ -2841,26 +2865,6 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
return false;
}
private AnimatorSet mediaPreviewAnimator;
public void updateMediaPreview(boolean enabled, boolean animated) {
if (mediaPreviewAnimator != null) {
mediaPreviewAnimator.cancel();
mediaPreviewAnimator = null;
}
if (!animated) {
mediaPreviewView.setAlpha(enabled ? 1f : 0f);
} else {
mediaPreviewAnimator = new AnimatorSet();
mediaPreviewAnimator.playTogether(
ObjectAnimator.ofFloat(mediaPreviewView, View.ALPHA, enabled ? 1f : 0f)
);
mediaPreviewAnimator.setDuration(200);
mediaPreviewAnimator.setInterpolator(CubicBezierInterpolator.EASE_BOTH);
mediaPreviewAnimator.start();
}
}
public void updateCountButton(int animated) {
if (viewChangeAnimator != null) {
return;
@ -3270,6 +3274,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
containerView.removeView(layouts[a]);
layouts[a] = null;
}
updateActionBarVisibility(false, false);
super.dismissInternal();
}
@ -3300,20 +3305,65 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
return currentAttachLayout.canDismissWithTouchOutside();
}
private boolean confirmationAlertShown = false;
protected boolean allowPassConfirmationAlert = false;
public void dismiss(boolean passConfirmationAlert) {
if (passConfirmationAlert) {
this.allowPassConfirmationAlert = passConfirmationAlert;
}
this.dismiss();
}
@Override
public void dismiss() {
if (currentAttachLayout.onDismiss()) {
return;
}
if (commentTextView != null) {
AndroidUtilities.hideKeyboard(commentTextView.getEditText());
}
if (!allowPassConfirmationAlert && baseFragment != null && currentAttachLayout.getSelectedItemsCount() > 0) {
if (confirmationAlertShown) {
return;
}
confirmationAlertShown = true;
AlertDialog dialog =
new AlertDialog.Builder(baseFragment.getParentActivity(), parentThemeDelegate)
.setTitle(LocaleController.getString("DiscardSelectionAlertTitle", R.string.DiscardSelectionAlertTitle))
.setMessage(LocaleController.getString("DiscardSelectionAlertMessage", R.string.DiscardSelectionAlertMessage))
.setPositiveButton(LocaleController.getString("PassportDiscard", R.string.PassportDiscard), (dialogInterface, i) -> {
allowPassConfirmationAlert = true;
dismiss();
})
.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null)
.setOnCancelListener(di -> {
if (appearSpringAnimation != null) {
appearSpringAnimation.cancel();
}
appearSpringAnimation = new SpringAnimation(super.containerView, DynamicAnimation.TRANSLATION_Y, 0);
appearSpringAnimation.getSpring().setDampingRatio(1.5f);
appearSpringAnimation.getSpring().setStiffness(1500.0f);
appearSpringAnimation.start();
})
.setOnPreDismissListener(di -> {
confirmationAlertShown = false;
})
.create();
dialog.show();
TextView button = (TextView) dialog.getButton(DialogInterface.BUTTON_POSITIVE);
if (button != null) {
button.setTextColor(getThemedColor(Theme.key_dialogTextRed2));
}
return;
}
for (int a = 0; a < layouts.length; a++) {
if (layouts[a] != null && currentAttachLayout != layouts[a]) {
layouts[a].onDismiss();
}
}
if (commentTextView != null) {
AndroidUtilities.hideKeyboard(commentTextView.getEditText());
}
super.dismiss();
allowPassConfirmationAlert = false;
}
@Override

View File

@ -49,7 +49,7 @@ public class ChatAttachAlertContactsLayout extends ChatAttachAlert.AttachAlertLa
private FrameLayout frameLayout;
private RecyclerListView listView;
private LinearLayoutManager layoutManager;
private FillLastLinearLayoutManager layoutManager;
private ShareAdapter listAdapter;
private ShareSearchAdapter searchAdapter;
private EmptyTextProgressView emptyView;
@ -78,6 +78,8 @@ public class ChatAttachAlertContactsLayout extends ChatAttachAlert.AttachAlertLa
private CharSequence currentName;
private CharSequence currentStatus;
private TLRPC.User formattedPhoneNumberUser;
private CharSequence formattedPhoneNumber;
private String lastName;
private int lastStatus;
@ -132,9 +134,48 @@ public class ChatAttachAlertContactsLayout extends ChatAttachAlert.AttachAlertLa
update(0);
}
public interface CharSequenceCallback {
CharSequence run();
}
public void setData(TLRPC.User user, CharSequence name, CharSequenceCallback status, boolean divider) {
setData(user, name, (CharSequence) null, divider);
Utilities.globalQueue.postRunnable(() -> {
final CharSequence newCurrentStatus = status.run();
AndroidUtilities.runOnUIThread(() -> {
setStatus(newCurrentStatus);
});
});
}
public void setStatus(CharSequence status) {
currentStatus = status;
if (currentStatus != null) {
statusTextView.setText(currentStatus);
} else if (currentUser != null) {
if (TextUtils.isEmpty(currentUser.phone)) {
statusTextView.setText(LocaleController.getString("NumberUnknown", R.string.NumberUnknown));
} else {
if (formattedPhoneNumberUser != currentUser && formattedPhoneNumber != null) {
statusTextView.setText(formattedPhoneNumber);
} else {
statusTextView.setText("");
Utilities.globalQueue.postRunnable(() -> {
formattedPhoneNumber = PhoneFormat.getInstance().format("+" + currentUser.phone);
formattedPhoneNumberUser = currentUser;
AndroidUtilities.runOnUIThread(() -> statusTextView.setText(formattedPhoneNumber));
});
}
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(64) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY));
super.onMeasure(
MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(64) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY)
);
}
public void update(int mask) {
@ -197,15 +238,8 @@ public class ChatAttachAlertContactsLayout extends ChatAttachAlert.AttachAlertLa
}
nameTextView.setText(lastName);
}
if (currentStatus != null) {
statusTextView.setText(currentStatus);
} else if (currentUser != null) {
if (TextUtils.isEmpty(currentUser.phone)) {
statusTextView.setText(LocaleController.getString("NumberUnknown", R.string.NumberUnknown));
} else {
statusTextView.setText(PhoneFormat.getInstance().format("+" + currentUser.phone));
}
}
setStatus(currentStatus);
lastAvatar = photo;
if (currentUser != null) {
@ -319,6 +353,7 @@ public class ChatAttachAlertContactsLayout extends ChatAttachAlert.AttachAlertLa
startSmoothScroll(linearSmoothScroller);
}
});
layoutManager.setBind(false);
listView.setHorizontalScrollBarEnabled(false);
listView.setVerticalScrollBarEnabled(false);
addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0));
@ -645,13 +680,14 @@ public class ChatAttachAlertContactsLayout extends ChatAttachAlert.AttachAlertLa
user = contact.user;
} else {
userCell.setCurrentId(contact.contact_id);
userCell.setData(null, ContactsController.formatName(contact.first_name, contact.last_name), contact.phones.isEmpty() ? "" : PhoneFormat.getInstance().format(contact.phones.get(0)), divider);
userCell.setData(null, ContactsController.formatName(contact.first_name, contact.last_name), () -> contact.phones.isEmpty() ? "" : PhoneFormat.getInstance().format(contact.phones.get(0)), divider);
}
} else {
user = (TLRPC.User) object;
}
if (user != null) {
userCell.setData(user, null, PhoneFormat.getInstance().format("+" + user.phone), divider);
final TLRPC.User finalUser = user;
userCell.setData(user, null, () -> PhoneFormat.getInstance().format("+" + finalUser.phone), divider);
}
}
}
@ -877,13 +913,14 @@ public class ChatAttachAlertContactsLayout extends ChatAttachAlert.AttachAlertLa
user = contact.user;
} else {
userCell.setCurrentId(contact.contact_id);
userCell.setData(null, searchResultNames.get(position - 1), contact.phones.isEmpty() ? "" : PhoneFormat.getInstance().format(contact.phones.get(0)), divider);
userCell.setData(null, searchResultNames.get(position - 1), () -> contact.phones.isEmpty() ? "" : PhoneFormat.getInstance().format(contact.phones.get(0)), divider);
}
} else {
user = (TLRPC.User) object;
}
if (user != null) {
userCell.setData(user, searchResultNames.get(position - 1), PhoneFormat.getInstance().format("+" + user.phone), divider);
final TLRPC.User finalUser = user;
userCell.setData(user, searchResultNames.get(position - 1), () -> PhoneFormat.getInstance().format("+" + finalUser.phone), divider);
}
}
}

View File

@ -58,6 +58,7 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSmoothScroller;
import androidx.recyclerview.widget.RecyclerView;
import org.checkerframework.checker.units.qual.A;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.BuildVars;
@ -83,6 +84,8 @@ import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.ActionBarMenu;
import org.telegram.ui.ActionBar.ActionBarMenuItem;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.BasePermissionsActivity;
import org.telegram.ui.Cells.PhotoAttachCameraCell;
@ -126,8 +129,9 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
private int animateToPadding;
private AnimatorSet cameraInitAnimation;
private CameraView cameraView;
private FrameLayout cameraIcon;
protected CameraView cameraView;
protected FrameLayout cameraIcon;
protected PhotoAttachCameraCell cameraCell;
private TextView recordTime;
private ImageView[] flashModeButton = new ImageView[2];
private boolean flashAnimationInProgress;
@ -1683,6 +1687,10 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
cameraExpanded = true;
cameraView.setFpsLimit(-1);
AndroidUtilities.hideKeyboard(this);
AndroidUtilities.setLightNavigationBar(parentAlert.getWindow(), false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
parentAlert.getWindow().setNavigationBarColor(0xff000000);
}
if (animated) {
setCameraOpenProgress(0);
cameraAnimationInProgress = true;
@ -2855,10 +2863,12 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
gridView.post(setScrollY);
}
checkCameraViewPosition();
try {
if (cameraView != null) {
CameraSession cameraSession = cameraView.getCameraSession();
if (cameraSession != null && !CameraController.getInstance().isPreviewRunning(cameraSession)) {
if (cameraSession != null) {
CameraController.getInstance().startPreview(cameraSession);
}
}
@ -2935,7 +2945,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
try {
if (cameraView != null) {
CameraSession cameraSession = cameraView.getCameraSession();
if (cameraSession != null && CameraController.getInstance().isPreviewRunning(cameraSession)) {
if (cameraSession != null) {
CameraController.getInstance().stopPreview(cameraSession);
}
}
@ -3346,7 +3356,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
break;
}
case 1: {
PhotoAttachCameraCell cameraCell = (PhotoAttachCameraCell) holder.itemView;
cameraCell = (PhotoAttachCameraCell) holder.itemView;
if (cameraView != null && cameraView.isInited() && !isHidden) {
cameraCell.setVisibility(View.INVISIBLE);
} else {
@ -3382,7 +3392,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
}
break;
case 1:
PhotoAttachCameraCell cameraCell = new PhotoAttachCameraCell(mContext, resourcesProvider);
cameraCell = new PhotoAttachCameraCell(mContext, resourcesProvider);
if (Build.VERSION.SDK_INT >= 21) {
cameraCell.setOutlineProvider(new ViewOutlineProvider() {
@Override

View File

@ -13,10 +13,11 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.media.MediaMetadataRetriever;
import android.os.Build;
import android.os.SystemClock;
import android.text.TextPaint;
import android.text.TextUtils;
@ -32,6 +33,7 @@ import android.view.animation.Interpolator;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.exifinterface.media.ExifInterface;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -58,7 +60,7 @@ import java.util.Map;
public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAlertLayout {
private final long durationMultiplier = 1; // 10; // 10 times slower for animation debugging
private final long durationMultiplier = 1;
public float getPreviewScale() {
// preview is 80% of real message size
@ -67,7 +69,6 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
private ChatActivity.ThemeDelegate themeDelegate;
// public ScrollView scrollView;
public RecyclerListView listView;
private LinearLayoutManager layoutManager;
public PaddingBox paddingView;
@ -75,22 +76,13 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
private UndoView undoView;
private TextView header;
int scrollY = 0;
private float draggingCellTouchX = 0, draggingCellTouchY = 0;
private float draggingCellTop = 0, draggingCellLeft = 0;
private float draggingCellFromWidth = 0, draggingCellFromHeight = 0;
private float draggingT = 0, fromDraggingT = 0;
private float draggingOutX = 0, draggingOutY = 0;
private boolean scrolling = false;
private boolean currentlyScrolling = false, currentlyTouching = false;
private PreviewGroupsView.PreviewGroupCell.MediaCell draggingToCell = null;
private PreviewGroupsView.PreviewGroupCell.MediaCell draggingCell = null;
private boolean draggingCellHiding = false;
private ValueAnimator draggingAnimator;
private PreviewGroupsView.PreviewGroupCell draggingFromGroupCell;
private float draggingCellGroupY = 0;
private Drawable videoPlayImage;
@ -279,6 +271,9 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
@Override
void onHidden() {
draggingCell = null;
if (undoView != null) {
undoView.hide(false, 0);
}
}
@Override
@ -298,7 +293,9 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
}
}
private static HashMap<MediaController.PhotoEntry, Boolean> photoRotate = new HashMap<>();
private class GroupCalculator {
public ArrayList<MessageObject.GroupedMessagePosition> posArray = new ArrayList<>();
public HashMap<MediaController.PhotoEntry, MessageObject.GroupedMessagePosition> positions = new HashMap<>();
@ -351,6 +348,8 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
int firstSpanAdditionalSize = 200;
int count = photos.size();
posArray.clear();
positions.clear();
if (count == 0) {
width = 0;
height = 0;
@ -358,9 +357,7 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
maxY = 0;
return;
}
posArray.clear();
posArray.ensureCapacity(count);
positions.clear();
final float maxSizeHeight = 814.0f;
char[] proportionsArray = new char[count];
@ -371,7 +368,43 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
MediaController.PhotoEntry photo = photos.get(a);
MessageObject.GroupedMessagePosition position = new MessageObject.GroupedMessagePosition();
position.last = a == count - 1;
position.aspectRatio = photo.width / (float) photo.height; // that's the only endpoint where messages/photos get used, everything else can be reused
int w = photo.width, h = photo.height;
boolean rotate;
if (photoRotate.containsKey(photo)) {
rotate = photoRotate.get(photo);
} else {
rotate = false;
try {
if (photo.isVideo) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
MediaMetadataRetriever m = new MediaMetadataRetriever();
m.setDataSource(photo.path);
String rotation = m.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
rotate = rotation != null && (rotation.equals("90") || rotation.equals("270"));
}
} else {
ExifInterface exif = new ExifInterface(photo.path);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = true;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
default:
break;
}
}
} catch (Exception ignore) {}
photoRotate.put(photo, rotate);
}
if (rotate) {
int wasW = w;
w = h;
h = wasW;
}
position.aspectRatio = w / (float) h;
proportionsArray[a] = (
position.aspectRatio > 1.2f ? 'w' : (
@ -399,13 +432,13 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
float minH = AndroidUtilities.dp(100) / maxSizeHeight;
if (!forceCalc && (count == 2 || count == 3 || count == 4) || count == 1) {
if (count == 1) {
MessageObject.GroupedMessagePosition position1 = posArray.get(0);
int widthPx = AndroidUtilities.displaySize.x - parentAlert.getBackgroundPaddingLeft() * 2;
float maxHeight = Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * .5f;
position1.set(0, 0, 0, 0, 800, (widthPx * .8f) / position1.aspectRatio / maxHeight, POSITION_FLAG_LEFT | POSITION_FLAG_RIGHT | POSITION_FLAG_TOP | POSITION_FLAG_BOTTOM);
} else if (count == 2) {
if (count == 1) {
MessageObject.GroupedMessagePosition position1 = posArray.get(0);
int widthPx = AndroidUtilities.displaySize.x - parentAlert.getBackgroundPaddingLeft() * 2;
float maxHeight = Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * .5f;
position1.set(0, 0, 0, 0, 800, (widthPx * .8f) / position1.aspectRatio / maxHeight, POSITION_FLAG_LEFT | POSITION_FLAG_RIGHT | POSITION_FLAG_TOP | POSITION_FLAG_BOTTOM);
} else if (!forceCalc && (count == 2 || count == 3 || count == 4)) {
if (count == 2) {
MessageObject.GroupedMessagePosition position1 = posArray.get(0);
MessageObject.GroupedMessagePosition position2 = posArray.get(1);
if (proportions.equals("ww") && averageAspectRatio > 1.4 * maxAspectRatio && position1.aspectRatio - position2.aspectRatio < 0.2) {
@ -835,7 +868,7 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
paddingTop = Math.max(0, paddingTop);
canvas.save();
canvas.clipRect(0, paddingTop, getWidth(), getHeight());
chatBackgroundDrawable.setBounds(0, 0, getWidth(), AndroidUtilities.displaySize.y);
chatBackgroundDrawable.setBounds(0, paddingTop, getWidth(), AndroidUtilities.displaySize.y);
chatBackgroundDrawable.draw(canvas);
restore = true;
}
@ -863,6 +896,15 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
}
}
@Override
void onSelectedItemsCountChanged(int count) {
if (count > 1) {
parentAlert.selectedMenuItem.showSubItem(ChatAttachAlertPhotoLayout.group);
} else {
parentAlert.selectedMenuItem.hideSubItem(ChatAttachAlertPhotoLayout.group);
}
}
private class PreviewGroupsView extends ViewGroup {
private ChatActionCell hintView;
@ -871,7 +913,7 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
super(context);
setWillNotDraw(false);
hintView = new ChatActionCell(context, false, themeDelegate);
hintView = new ChatActionCell(context, true, themeDelegate);
hintView.setCustomText(LocaleController.getString("AttachMediaDragHint", R.string.AttachMediaDragHint));
addView(hintView);
}
@ -1013,7 +1055,8 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
private int paddingTop = AndroidUtilities.dp(8 + 8);
private int paddingBottom = AndroidUtilities.dp(32 + 32);
private int lastMeasuredHeight = 0;
private int measureHeight() {
private int measurePureHeight() {
int height = paddingTop + paddingBottom;
final int groupCellsCount = groupCells.size();
for (int i = 0; i < groupCellsCount; ++i) {
@ -1026,7 +1069,10 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
);
}
height += hintView.getMeasuredHeight();
return Math.max(AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(8 + 46 - 9), height);
return height;
}
private int measureHeight() {
return Math.max(measurePureHeight(), AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(8 + 46 - 9));
}
@Override
@ -1133,25 +1179,17 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
y += height;
i += groupCell.group.photos.size();
}
hintView.setVisiblePart(y, hintView.getMeasuredHeight());
if (hintView.hasGradientService()) {
hintView.drawBackground(canvas, true);
}
hintView.draw(canvas);
canvas.restore();
if (draggingCell != null) {
canvas.save();
RectF drawingRect = draggingCell.rect();
RectF finalDrawingRect = draggingCell.rect(1f);
canvas.translate(
AndroidUtilities.lerp(
finalDrawingRect.left + drawingRect.width() / 2f,
draggingCellTouchX - (draggingCellLeft - .5f) * draggingCellFromWidth,
draggingT
),
AndroidUtilities.lerp(
draggingCell.groupCell.y + finalDrawingRect.top + drawingRect.height() / 2f,
draggingCellGroupY + draggingCellTouchY - (draggingCellTop - .5f) * draggingCellFromHeight,
draggingT
)
);
Point point = dragTranslate();
canvas.translate(point.x, point.y);
if (draggingCell.draw(canvas, true)) {
invalidate();
}
@ -1165,12 +1203,59 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
PreviewGroupCell tapGroupCell = null;
PreviewGroupCell.MediaCell tapMediaCell = null;
private float draggingT = 0;
private float savedDragFromX, savedDragFromY, savedDraggingT;
private final Point tmpPoint = new Point();
Point dragTranslate() {
if (draggingCell == null) {
tmpPoint.x = 0;
tmpPoint.y = 0;
return tmpPoint;
}
if (!draggingCellHiding) {
RectF drawingRect = draggingCell.rect();
RectF finalDrawingRect = draggingCell.rect(1f);
tmpPoint.x = AndroidUtilities.lerp(
finalDrawingRect.left + drawingRect.width() / 2f,
draggingCellTouchX - (draggingCellLeft - .5f) * draggingCellFromWidth,
draggingT
);
tmpPoint.y = AndroidUtilities.lerp(
draggingCell.groupCell.y + finalDrawingRect.top + drawingRect.height() / 2f,
draggingCellTouchY - (draggingCellTop - .5f) * draggingCellFromHeight + draggingCellGroupY,
draggingT
);
} else {
RectF drawingRect = draggingCell.rect();
RectF finalDrawingRect = draggingCell.rect(1f);
tmpPoint.x = AndroidUtilities.lerp(
finalDrawingRect.left + drawingRect.width() / 2f,
savedDragFromX,
draggingT / savedDraggingT
);
tmpPoint.y = AndroidUtilities.lerp(
draggingCell.groupCell.y + finalDrawingRect.top + drawingRect.height() / 2f,
savedDragFromY,
draggingT / savedDraggingT
);
}
return tmpPoint;
}
void stopDragging() {
if (draggingAnimator != null) {
draggingAnimator.cancel();
}
Point dragTranslate = dragTranslate();
savedDraggingT = draggingT;
savedDragFromX = dragTranslate.x;
savedDragFromY = dragTranslate.y;
draggingCellHiding = true;
draggingAnimator = ValueAnimator.ofFloat(draggingT, 0f);
draggingAnimator = ValueAnimator.ofFloat(savedDraggingT, 0f);
draggingAnimator.addUpdateListener(a -> {
draggingT = (float) a.getAnimatedValue();
invalidate();
@ -1179,21 +1264,20 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
@Override
public void onAnimationEnd(Animator animation) {
draggingCell = null;
draggingFromGroupCell = null;
draggingCellHiding = false;
invalidate();
}
});
draggingAnimator.setDuration((long) (180 * durationMultiplier * Math.abs(draggingT)));
draggingAnimator.setDuration((long) (200 * durationMultiplier));
draggingAnimator.start();
invalidate();
}
void startDragging(PreviewGroupCell.MediaCell cell) {
draggingCell = cell;
draggingFromGroupCell = draggingCell.groupCell;
draggingCellGroupY = draggingCell.groupCell.y;
draggingCellHiding = false;
draggingT = 0;
invalidate();
if (draggingAnimator != null) {
draggingAnimator.cancel();
@ -1203,7 +1287,7 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
draggingT = (float) a.getAnimatedValue();
invalidate();
});
draggingAnimator.setDuration((long) (180 * durationMultiplier * Math.abs(1f - draggingT)));
draggingAnimator.setDuration((long) (200 * durationMultiplier));
draggingAnimator.start();
}
@ -1216,6 +1300,9 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
}
int scrollY = listView.computeVerticalScrollOffset();
boolean atBottom = scrollY + listView.computeVerticalScrollExtent() >= (measurePureHeight() - paddingBottom + paddingTop);
float top = Math.max(0, draggingCellTouchY - Math.max(0, scrollY - getListTopPadding()) - AndroidUtilities.dp(52));
float bottom = Math.max(0, (listView.getMeasuredHeight() - (draggingCellTouchY - scrollY) - getListTopPadding()) - AndroidUtilities.dp(52 + 32));
@ -1227,7 +1314,7 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
dy = (1f - bottom / r) * (float) AndroidUtilities.dp(6);
}
if (Math.abs((int) dy) > 0 && listView.canScrollVertically((int) dy)) {
if (Math.abs((int) dy) > 0 && listView.canScrollVertically((int) dy) && !(dy > 0 && atBottom)) {
draggingCellTouchY += dy;
listView.scrollBy(0, (int) dy);
invalidate();
@ -1276,18 +1363,9 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
if (draggingCell != null) {
groupY = 0;
RectF drawingRect = draggingCell.rect();
RectF finalDrawingRect = draggingCell.rect(1f);
Point dragPoint = dragTranslate();
RectF draggingCellXY = new RectF();
float cx = AndroidUtilities.lerp(
finalDrawingRect.left + drawingRect.width() / 2f,
draggingCellTouchX - (draggingCellLeft - .5f) * draggingCellFromWidth,
draggingT
),
cy = AndroidUtilities.lerp(
draggingCell.groupCell.y + finalDrawingRect.top + drawingRect.height() / 2f,
draggingCellGroupY + draggingCellTouchY - (draggingCellTop - .5f) * draggingCellFromHeight,
draggingT
);
float cx = dragPoint.x, cy = dragPoint.y;
draggingCellXY.set(
cx - drawingRect.width() / 2,
cy - drawingRect.height() / 2,
@ -1313,14 +1391,26 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
final int mediaCount = draggingOverGroupCell.media.size();
for (int i = 0; i < mediaCount; ++i) {
PreviewGroupCell.MediaCell mediaCell = draggingOverGroupCell.media.get(i);
if (mediaCell != null && mediaCell != draggingCell) {
if (mediaCell != null && mediaCell != draggingCell && draggingOverGroupCell.group.photos.contains(mediaCell.photoEntry)) {
RectF mediaCellRect = mediaCell.drawingRect();
if ((mediaCell.positionFlags & POSITION_FLAG_TOP) > 0) {
mediaCellRect.top = 0;
}
if ((mediaCell.positionFlags & POSITION_FLAG_LEFT) > 0) {
mediaCellRect.left = 0;
}
if ((mediaCell.positionFlags & POSITION_FLAG_RIGHT) > 0) {
mediaCellRect.right = getWidth();
}
if ((mediaCell.positionFlags & POSITION_FLAG_BOTTOM) > 0) {
mediaCellRect.bottom = draggingOverGroupCell.height;
}
if (RectF.intersects(draggingCellXY, mediaCellRect)) {
float area = (
(Math.min(mediaCellRect.right, draggingCellXY.right) - Math.max(mediaCellRect.left, draggingCellXY.left)) *
(Math.min(mediaCellRect.bottom, draggingCellXY.bottom) - Math.max(mediaCellRect.top, draggingCellXY.top))
) / (mediaCellRect.width() * mediaCellRect.height());
if (area > maxArea) {
) / (draggingCellXY.width() * draggingCellXY.height());
if (area > 0.15f && area > maxArea) {
draggingOverMediaCell = mediaCell;
maxArea = area;
}
@ -1331,13 +1421,12 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
}
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN && draggingCell == null && !listView.scrollingByUser && (draggingAnimator == null || !draggingAnimator.isRunning()) && touchGroupCell != null && touchMediaCell != null) {
if (action == MotionEvent.ACTION_DOWN && draggingCell == null && !listView.scrollingByUser && (draggingAnimator == null || !draggingAnimator.isRunning()) && touchGroupCell != null && touchMediaCell != null && touchGroupCell.group != null && touchGroupCell.group.photos.contains(touchMediaCell.photoEntry)) {
tapGroupCell = touchGroupCell;
tapMediaCell = touchMediaCell;
draggingCellTouchX = touchX;
draggingCellTouchY = touchY;
draggingCell = null;
draggingFromGroupCell = null;
final long wasTapTime = tapTime = SystemClock.elapsedRealtime();
final PreviewGroupCell.MediaCell wasTapMediaCell = tapMediaCell;
@ -1348,7 +1437,7 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
startDragging(tapMediaCell);
RectF draggingCellRect = draggingCell.rect();
RectF draggingCellDrawingRect = draggingCell.drawingRect();
draggingCellLeft = (draggingCellTouchX - draggingCellRect.left) / (float) draggingCellRect.width();
draggingCellLeft = (.5f + (draggingCellTouchX - draggingCellRect.left) / (float) draggingCellRect.width()) / 2;
draggingCellTop = (draggingCellTouchY - draggingCellRect.top) / (float) draggingCellRect.height();
draggingCellFromWidth = draggingCellDrawingRect.width();
draggingCellFromHeight = draggingCellDrawingRect.height();
@ -1373,15 +1462,14 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
} else if (action == MotionEvent.ACTION_UP && draggingCell != null) {
PreviewGroupCell replaceGroupCell = null;
PreviewGroupCell.MediaCell replaceMediaCell = null;
// if (touchGroupCell != null && touchMediaCell != null && touchMediaCell != draggingCell) {
// replaceGroupCell = touchGroupCell;
// replaceMediaCell = touchMediaCell;
// } else
if (draggingOverGroupCell != null && draggingOverMediaCell != null && draggingOverMediaCell != draggingCell) {
if (touchGroupCell != null && touchMediaCell != null && touchMediaCell != draggingCell) {
replaceGroupCell = touchGroupCell;
replaceMediaCell = touchMediaCell;
} else if (draggingOverGroupCell != null && draggingOverMediaCell != null && draggingOverMediaCell != draggingCell && draggingOverMediaCell.photoEntry != draggingCell.photoEntry) {
replaceGroupCell = draggingOverGroupCell;
replaceMediaCell = draggingOverMediaCell;
}
if (replaceGroupCell != null && replaceMediaCell != null) {
if (replaceGroupCell != null && replaceMediaCell != null && replaceMediaCell != draggingCell) {
int draggingIndex = draggingCell.groupCell.group.photos.indexOf(draggingCell.photoEntry);
int tapIndex = replaceGroupCell.group.photos.indexOf(replaceMediaCell.photoEntry);
if (draggingIndex >= 0) {
@ -1410,7 +1498,7 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
remeasure();
newDraggingCell.layoutFrom(draggingCell);
draggingCell = newDraggingCell;
newDraggingCell.groupCell = draggingFromGroupCell = replaceGroupCell;
newDraggingCell.groupCell = replaceGroupCell;
newDraggingCell.scale = draggingCell.fromScale = 1f;
remeasure();
}
@ -1484,7 +1572,7 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
}
private void pushToGroup(PreviewGroupCell groupCell, MediaController.PhotoEntry photoEntry, int index) {
groupCell.group.photos.add(index, photoEntry);
groupCell.group.photos.add(Math.min(groupCell.group.photos.size(), index), photoEntry);
if (groupCell.group.photos.size() == 11) {
MediaController.PhotoEntry jumpPhoto = groupCell.group.photos.get(10);
groupCell.group.photos.remove(10);
@ -1619,15 +1707,13 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
this.lastUpdate = SystemClock.elapsedRealtime();
}
private boolean firstLayout = true;
private void layout(GroupCalculator group, MessageObject.GroupedMessagePosition pos, boolean animated) {
if (group == null || pos == null) {
if (animated) {
final long now = SystemClock.elapsedRealtime();
final float t = interpolator.getInterpolation(Math.min(1, (now - lastUpdate) / (float) updateDuration));
fromScale = AndroidUtilities.lerp(fromScale, scale, t);
fromScale = AndroidUtilities.lerp(fromScale, scale, getT());
if (fromRect != null) {
AndroidUtilities.lerp(fromRect, rect, t, fromRect);
AndroidUtilities.lerp(fromRect, rect, getT(), fromRect);
}
scale = 0f;
lastUpdate = now;
@ -1638,8 +1724,7 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
}
positionFlags = pos.flags;
if (animated) {
final long now = SystemClock.elapsedRealtime();
final float t = interpolator.getInterpolation(Math.min(1, (now - lastUpdate) / (float) updateDuration));
final float t = getT();
if (fromRect != null) {
AndroidUtilities.lerp(fromRect, rect, t, fromRect);
}
@ -1647,7 +1732,7 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
AndroidUtilities.lerp(fromRoundRadiuses, roundRadiuses, t, fromRoundRadiuses);
}
fromScale = AndroidUtilities.lerp(fromScale, scale, t);
lastUpdate = now;
lastUpdate = SystemClock.elapsedRealtime();
}
float x = pos.left / group.width,
y = pos.top / group.height,
@ -1697,9 +1782,9 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
return tempRect;
}
float x = left + rect.left * width,
y = top + rect.top * height,
w = rect.width() * width,
h = rect.height() * height;
y = top + rect.top * height,
w = rect.width() * width,
h = rect.height() * height;
if (t < 1f && fromRect != null) {
x = AndroidUtilities.lerp(left + fromRect.left * width, x, t);
y = AndroidUtilities.lerp(top + fromRect.top * height, y, t);
@ -1867,9 +1952,6 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
return false;
}
RectF drawingRect = this.drawingRect();
// if (!ignoreBounds && !isSeen(drawingRect.top, drawingRect.bottom)) {
// return false;
// }
float R = AndroidUtilities.dp(SharedConfig.bubbleRadius - 1);
float tl = roundRadiuses.left, tr = roundRadiuses.top, br = roundRadiuses.right, bl = roundRadiuses.bottom;
if (t < 1f && fromRoundRadiuses != null) {
@ -1886,13 +1968,10 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
canvas.save();
canvas.translate(-drawingRect.centerX(), -drawingRect.centerY());
}
// canvas.save();
// canvas.clipPath(roundedRect(drawingRect, tl, tr, br, bl));
image.setRoundRadius((int) tl, (int) tr, (int) br, (int) bl);
image.setImageCoords(drawingRect.left, drawingRect.top, drawingRect.width(), drawingRect.height());
image.setAlpha(scale);
image.draw(canvas);
// canvas.restore();
int index = indexStart + group.photos.indexOf(photoEntry);
String indexText = index >= 0 ? (index + 1) + "" : null;
@ -1910,12 +1989,11 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
private Interpolator interpolator = CubicBezierInterpolator.EASE_BOTH;
private GroupCalculator group;
private void setGroup(GroupCalculator group, boolean animated) {
group.calculate();
this.group = group;
if (group == null) {
return;
}
group.calculate();
final long now = SystemClock.elapsedRealtime();
if (now - lastMediaUpdate < updateDuration) {
final float t = (now - lastMediaUpdate) / (float) updateDuration;
@ -2046,18 +2124,6 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle
}
return update;
}
private float[] tempRadii = new float[8];
private Path tempPath = new Path();
Path roundedRect(RectF rect, float topleft, float topright, float bottomright, float bottomleft) {
tempPath.reset();
tempRadii[0] = tempRadii[1] = topleft;
tempRadii[2] = tempRadii[3] = topright;
tempRadii[4] = tempRadii[5] = bottomright;
tempRadii[6] = tempRadii[7] = bottomleft;
tempPath.addRoundRect(rect, tempRadii, Path.Direction.CW);
return tempPath;
}
}
}

View File

@ -2,6 +2,7 @@ package org.telegram.ui.Components;
import android.content.Context;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import org.telegram.messenger.AndroidUtilities;
@ -9,8 +10,9 @@ import org.telegram.ui.ActionBar.ActionBarPopupWindow;
public class ChatScrimPopupContainerLayout extends LinearLayout {
public ReactionsContainerLayout reactionsLayout;
public ActionBarPopupWindow.ActionBarPopupWindowLayout popupWindowLayout;
private ReactionsContainerLayout reactionsLayout;
private ActionBarPopupWindow.ActionBarPopupWindowLayout popupWindowLayout;
private View bottomView;
public ChatScrimPopupContainerLayout(Context context) {
super(context);
@ -38,10 +40,47 @@ public class ChatScrimPopupContainerLayout extends LinearLayout {
if (popupWindowLayout.getSwipeBack() != null) {
widthDiff = popupWindowLayout.getSwipeBack().getMeasuredWidth() - popupWindowLayout.getSwipeBack().getChildAt(0).getMeasuredWidth();
}
((LayoutParams)reactionsLayout.getLayoutParams()).rightMargin = widthDiff;
((LayoutParams) reactionsLayout.getLayoutParams()).rightMargin = widthDiff;
if (bottomView != null) {
if (popupWindowLayout.getSwipeBack() != null) {
((LayoutParams) bottomView.getLayoutParams()).rightMargin = widthDiff + AndroidUtilities.dp(36);
} else {
((LayoutParams) bottomView.getLayoutParams()).rightMargin = AndroidUtilities.dp(36);
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void applyViewBottom(FrameLayout bottomView) {
this.bottomView = bottomView;
}
public void setReactionsLayout(ReactionsContainerLayout reactionsLayout) {
this.reactionsLayout = reactionsLayout;
}
public void setPopupWindowLayout(ActionBarPopupWindow.ActionBarPopupWindowLayout popupWindowLayout) {
this.popupWindowLayout = popupWindowLayout;
popupWindowLayout.setOnSizeChangedListener(new ActionBarPopupWindow.onSizeChangedListener() {
@Override
public void onSizeChanged() {
if (bottomView != null) {
bottomView.setTranslationY(popupWindowLayout.getVisibleHeight() - popupWindowLayout.getMeasuredHeight());
}
}
});
if (popupWindowLayout.getSwipeBack() != null) {
popupWindowLayout.getSwipeBack().addOnSwipeBackProgressListener(new PopupSwipeBackLayout.OnSwipeBackProgressListener() {
@Override
public void onSwipeBackProgress(PopupSwipeBackLayout layout, float toProgress, float progress) {
if (bottomView != null) {
bottomView.setAlpha(1f - progress);
}
}
});
}
}
}

View File

@ -5,12 +5,12 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
@ -117,11 +117,12 @@ public class ChatThemeBottomSheet extends BottomSheet implements NotificationCen
int drawableColor = getThemedColor(Theme.key_featuredStickers_addButton);
int drawableSize = AndroidUtilities.dp(28);
darkThemeDrawable = new RLottieDrawable(R.raw.sun_outline, "" + R.raw.sun_outline, drawableSize, drawableSize, true, null);
darkThemeDrawable = new RLottieDrawable(R.raw.sun_outline, "" + R.raw.sun_outline, drawableSize, drawableSize, false, null);
forceDark = !Theme.getActiveTheme().isDark();
setForceDark(Theme.getActiveTheme().isDark(), false);
darkThemeDrawable.setAllowDecodeSingleFrame(true);
darkThemeDrawable.setPlayInDirectionOfCustomEndFrame(true);
darkThemeDrawable.beginApplyLayerColors();
setDarkButtonColor(drawableColor);
darkThemeDrawable.commitApplyLayerColors();
darkThemeDrawable.setColorFilter(new PorterDuffColorFilter(drawableColor, PorterDuff.Mode.MULTIPLY));
darkThemeView = new RLottieImageView(getContext());
darkThemeView.setAnimation(darkThemeDrawable);
@ -133,8 +134,6 @@ public class ChatThemeBottomSheet extends BottomSheet implements NotificationCen
setupLightDarkTheme(!forceDark);
});
rootLayout.addView(darkThemeView, LayoutHelper.createFrame(44, 44, Gravity.TOP | Gravity.END, 0, -2, 7, 0));
forceDark = !Theme.getActiveTheme().isDark();
setForceDark(Theme.getActiveTheme().isDark(), false);
scroller = new LinearSmoothScroller(getContext()) {
@Override
@ -333,7 +332,7 @@ public class ChatThemeBottomSheet extends BottomSheet implements NotificationCen
onAnimationStart();
isAnimationStarted = true;
}
setDarkButtonColor(getThemedColor(Theme.key_featuredStickers_addButton));
darkThemeDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_featuredStickers_addButton), PorterDuff.Mode.MULTIPLY));
setOverlayNavBarColor(getThemedColor(Theme.key_dialogBackground));
if (isLightDarkChangeAnimation) {
setItemsAnimationProgress(progress);
@ -572,10 +571,16 @@ public class ChatThemeBottomSheet extends BottomSheet implements NotificationCen
forceDark = isDark;
if (playAnimation) {
darkThemeDrawable.setCustomEndFrame(isDark ? darkThemeDrawable.getFramesCount() : 0);
darkThemeView.playAnimation();
if (darkThemeView != null) {
darkThemeView.playAnimation();
}
} else {
darkThemeDrawable.setCurrentFrame(isDark ? darkThemeDrawable.getFramesCount() - 1 : 0, false, true);
darkThemeView.invalidate();
int frame = isDark ? darkThemeDrawable.getFramesCount() - 1 : 0;
darkThemeDrawable.setCurrentFrame(frame, false, true);
darkThemeDrawable.setCustomEndFrame(frame);
if (darkThemeView != null) {
darkThemeView.invalidate();
}
}
}

View File

@ -9,6 +9,7 @@
package org.telegram.ui.Components;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
@ -16,6 +17,8 @@ import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.view.animation.DecelerateInterpolator;
import androidx.core.graphics.ColorUtils;
import org.telegram.messenger.AndroidUtilities;
public class CloseProgressDrawable2 extends Drawable {
@ -27,6 +30,8 @@ public class CloseProgressDrawable2 extends Drawable {
private float angle;
private boolean animating;
private int side;
private int globalColorAlpha = 255;
private int currentColor;
public CloseProgressDrawable2() {
super();
@ -51,8 +56,12 @@ public class CloseProgressDrawable2 extends Drawable {
return animating;
}
public void setColor(int value) {
paint.setColor(value);
private void setColor(int value) {
if (currentColor != value) {
globalColorAlpha = Color.alpha(value);
value = ColorUtils.setAlphaComponent(value, 255);
paint.setColor(value);
}
}
public void setSide(int value) {
@ -62,7 +71,7 @@ public class CloseProgressDrawable2 extends Drawable {
@Override
public void draw(Canvas canvas) {
long newTime = System.currentTimeMillis();
boolean invalidate = false;
setColor(getCurrentColor());
if (lastFrameTime != 0) {
long dt = (newTime - lastFrameTime);
if (animating || angle != 0) {
@ -76,7 +85,11 @@ public class CloseProgressDrawable2 extends Drawable {
}
}
canvas.save();
if (globalColorAlpha == 255 || getBounds() == null || getBounds().isEmpty()) {
canvas.save();
} else {
canvas.saveLayerAlpha(getBounds().left, getBounds().top, getBounds().right, getBounds().bottom, globalColorAlpha, Canvas.ALL_SAVE_FLAG);
}
canvas.translate(getIntrinsicWidth() / 2, getIntrinsicHeight() / 2);
canvas.rotate(-45);
float progress1 = 1.0f;
@ -137,7 +150,7 @@ public class CloseProgressDrawable2 extends Drawable {
@Override
public void setColorFilter(ColorFilter cf) {
paint.setColorFilter(cf);
}
@Override
@ -154,4 +167,8 @@ public class CloseProgressDrawable2 extends Drawable {
public int getIntrinsicHeight() {
return AndroidUtilities.dp(24);
}
protected int getCurrentColor() {
return Color.WHITE;
}
}

View File

@ -489,12 +489,16 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
clearSearchImageView = new ImageView(context);
clearSearchImageView.setScaleType(ImageView.ScaleType.CENTER);
clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2());
clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2() {
@Override
protected int getCurrentColor() {
return getThemedColor(Theme.key_chat_emojiSearchIcon);
}
});
progressDrawable.setSide(AndroidUtilities.dp(7));
clearSearchImageView.setScaleX(0.1f);
clearSearchImageView.setScaleY(0.1f);
clearSearchImageView.setAlpha(0.0f);
clearSearchImageView.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_emojiSearchIcon), PorterDuff.Mode.MULTIPLY));
addView(clearSearchImageView, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP, 14, 14, 14, 0));
clearSearchImageView.setOnClickListener(v -> {
searchEditText.setText("");

View File

@ -219,6 +219,10 @@ public class FilterShaders {
return shaderString.toString();
}
public void drawBoxBlur() {
}
private static class BlurProgram {
private String vertexShaderCode;
@ -1005,9 +1009,9 @@ public class FilterShaders {
private int renderBufferWidth;
private int renderBufferHeight;
private FloatBuffer vertexBuffer;
private FloatBuffer textureBuffer;
private FloatBuffer vertexInvertBuffer;
public FloatBuffer vertexBuffer;
public FloatBuffer textureBuffer;
public FloatBuffer vertexInvertBuffer;
private ByteBuffer hsvBuffer;
private ByteBuffer cdtBuffer;

View File

@ -47,6 +47,7 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.IntDef;
import androidx.annotation.Keep;
import org.telegram.messenger.AccountInstance;
@ -73,15 +74,37 @@ import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ChatActivity;
import org.telegram.ui.Components.voip.CellFlickerDrawable;
import org.telegram.ui.Components.voip.VoIPHelper;
import org.telegram.ui.DialogsActivity;
import org.telegram.ui.GroupCallActivity;
import org.telegram.ui.LaunchActivity;
import org.telegram.ui.LocationActivity;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
public class FragmentContextView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate, VoIPService.StateListener {
public final static int STYLE_NOT_SET = -1,
STYLE_AUDIO_PLAYER = 0,
STYLE_CONNECTING_GROUP_CALL = 1,
STYLE_LIVE_LOCATION = 2,
STYLE_ACTIVE_GROUP_CALL = 3,
STYLE_INACTIVE_GROUP_CALL = 4,
STYLE_IMPORTING_MESSAGES = 5;
@Retention(RetentionPolicy.SOURCE)
@IntDef({
STYLE_NOT_SET,
STYLE_AUDIO_PLAYER,
STYLE_CONNECTING_GROUP_CALL,
STYLE_LIVE_LOCATION,
STYLE_ACTIVE_GROUP_CALL,
STYLE_INACTIVE_GROUP_CALL,
STYLE_IMPORTING_MESSAGES
})
public @interface Style {}
private ImageView playButton;
private PlayPauseDrawable playPauseDrawable;
@ -102,6 +125,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
private ActionBarMenuSubItem[] speedItems = new ActionBarMenuSubItem[4];
private FragmentContextView additionalContextView;
private TextView joinButton;
private CellFlickerDrawable joinButtonFlicker;
private boolean isMuted;
@ -110,7 +134,8 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
private MessageObject lastMessageObject;
private float topPadding;
private boolean visible;
private int currentStyle = -1;
@Style
private int currentStyle = STYLE_NOT_SET;
private String lastString;
private boolean isMusic;
private boolean supportsCalls = true;
@ -196,7 +221,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
public boolean drawOverlayed() {
return currentStyle == 3;
return currentStyle == STYLE_ACTIVE_GROUP_CALL;
}
public interface FragmentContextViewDelegate {
@ -241,7 +266,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (currentStyle == 4 && timeLayout != null) {
if (currentStyle == STYLE_INACTIVE_GROUP_CALL && timeLayout != null) {
int width = (int) Math.ceil(timeLayout.getLineWidth(0)) + AndroidUtilities.dp(24);
if (width != gradientWidth) {
linearGradient = new LinearGradient(0, 0, width * 1.7f, 0, new int[]{0xff648CF4, 0xff8C69CF, 0xffD45979, 0xffD45979}, new float[]{0.0f, 0.294f, 0.588f, 1.0f}, Shader.TileMode.CLAMP);
@ -289,12 +314,12 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
playButton.setScaleType(ImageView.ScaleType.CENTER);
playButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_inappPlayerPlayPause), PorterDuff.Mode.MULTIPLY));
playButton.setImageDrawable(playPauseDrawable = new PlayPauseDrawable(14));
if (Build.VERSION.SDK_INT >= 21) {
playButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_inappPlayerPlayPause) & 0x19ffffff, 1, AndroidUtilities.dp(14)));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
playButton.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_inappPlayerPlayPause) & 0x19ffffff, 1, AndroidUtilities.dp(14)));
}
addView(playButton, LayoutHelper.createFrame(36, 36, Gravity.TOP | Gravity.LEFT));
playButton.setOnClickListener(v -> {
if (currentStyle == 0) {
if (currentStyle == STYLE_AUDIO_PLAYER) {
if (MediaController.getInstance().isMessagePaused()) {
MediaController.getInstance().playMessage(MediaController.getInstance().getPlayingMessageObject());
} else {
@ -320,16 +345,16 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
textView.setEllipsize(TextUtils.TruncateAt.END);
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
if (currentStyle == 0 || currentStyle == 2) {
if (currentStyle == STYLE_AUDIO_PLAYER || currentStyle == STYLE_LIVE_LOCATION) {
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
textView.setTypeface(Typeface.DEFAULT);
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
} else if (currentStyle == 4) {
} else if (currentStyle == STYLE_INACTIVE_GROUP_CALL) {
textView.setGravity(Gravity.TOP | Gravity.LEFT);
textView.setTextColor(getThemedColor(Theme.key_inappPlayerPerformer));
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
} else if (currentStyle == 1 || currentStyle == 3) {
} else if (currentStyle == STYLE_CONNECTING_GROUP_CALL || currentStyle == STYLE_ACTIVE_GROUP_CALL) {
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
textView.setTextColor(getThemedColor(Theme.key_returnToCallText));
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
@ -356,7 +381,26 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
};
addView(subtitleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 35, 10, 36, 0));
joinButton = new TextView(context);
joinButtonFlicker = new CellFlickerDrawable();
joinButtonFlicker.setProgress(2f);
joinButtonFlicker.repeatEnabled = false;
joinButton = new TextView(context) {
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
AndroidUtilities.rectTmp.set(0, 0, getWidth(), getHeight());
joinButtonFlicker.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(4));
invalidate();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
joinButtonFlicker.setParentWidth(getWidth());
}
};
joinButton.setText(LocaleController.getString("VoipChatJoin", R.string.VoipChatJoin));
joinButton.setTextColor(getThemedColor(Theme.key_featuredStickers_buttonText));
joinButton.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), getThemedColor(Theme.key_featuredStickers_addButton), getThemedColor(Theme.key_featuredStickers_addButtonPressed)));
@ -459,7 +503,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
@Override
public boolean onTouchEvent(MotionEvent event) {
if (currentStyle == 3 || currentStyle == 1) {
if (currentStyle == STYLE_ACTIVE_GROUP_CALL || currentStyle == STYLE_CONNECTING_GROUP_CALL) {
VoIPService service = VoIPService.getSharedInstance();
if (service == null) {
AndroidUtilities.cancelRunOnUIThread(pressRunnable);
@ -512,8 +556,8 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
};
muteButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_returnToCallText), PorterDuff.Mode.MULTIPLY));
if (Build.VERSION.SDK_INT >= 21) {
muteButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_inappPlayerClose) & 0x19ffffff, 1, AndroidUtilities.dp(14)));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
muteButton.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_inappPlayerClose) & 0x19ffffff, 1, AndroidUtilities.dp(14)));
}
muteButton.setAnimation(muteDrawable);
muteButton.setScaleType(ImageView.ScaleType.CENTER);
@ -551,13 +595,13 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
closeButton = new ImageView(context);
closeButton.setImageResource(R.drawable.miniplayer_close);
closeButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_inappPlayerClose), PorterDuff.Mode.MULTIPLY));
if (Build.VERSION.SDK_INT >= 21) {
closeButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_inappPlayerClose) & 0x19ffffff, 1, AndroidUtilities.dp(14)));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
closeButton.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_inappPlayerClose) & 0x19ffffff, 1, AndroidUtilities.dp(14)));
}
closeButton.setScaleType(ImageView.ScaleType.CENTER);
addView(closeButton, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP, 0, 0, 2, 0));
closeButton.setOnClickListener(v -> {
if (currentStyle == 2) {
if (currentStyle == STYLE_LIVE_LOCATION) {
AlertDialog.Builder builder = new AlertDialog.Builder(fragment.getParentActivity(), resourcesProvider);
builder.setTitle(LocaleController.getString("StopLiveLocationAlertToTitle", R.string.StopLiveLocationAlertToTitle));
if (fragment instanceof DialogsActivity) {
@ -596,7 +640,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
});
setOnClickListener(v -> {
if (currentStyle == 0) {
if (currentStyle == STYLE_AUDIO_PLAYER) {
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
if (fragment != null && messageObject != null) {
if (messageObject.isMusic()) {
@ -625,10 +669,10 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
}
}
} else if (currentStyle == 1) {
} else if (currentStyle == STYLE_CONNECTING_GROUP_CALL) {
Intent intent = new Intent(getContext(), LaunchActivity.class).setAction("voip");
getContext().startActivity(intent);
} else if (currentStyle == 2) {
} else if (currentStyle == STYLE_LIVE_LOCATION) {
long did = 0;
int account = UserConfig.selectedAccount;
if (fragment instanceof ChatActivity) {
@ -650,11 +694,11 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
} else {
fragment.showDialog(new SharingLocationsAlert(getContext(), this::openSharingLocation, resourcesProvider));
}
} else if (currentStyle == 3) {
} else if (currentStyle == STYLE_ACTIVE_GROUP_CALL) {
if (VoIPService.getSharedInstance() != null && getContext() instanceof LaunchActivity) {
GroupCallActivity.create((LaunchActivity) getContext(), AccountInstance.getInstance(VoIPService.getSharedInstance().getAccount()), null, null, false, null);
}
} else if (currentStyle == 4) {
} else if (currentStyle == STYLE_INACTIVE_GROUP_CALL) {
if (fragment.getParentActivity() == null) {
return;
}
@ -664,7 +708,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
return;
}
VoIPHelper.startCall(chatActivity.getMessagesController().getChat(call.chatId), null, null, false, call.call != null && !call.call.rtmp_stream, fragment.getParentActivity(), fragment, fragment.getAccountInstance());
} else if (currentStyle == 5) {
} else if (currentStyle == STYLE_IMPORTING_MESSAGES) {
SendMessagesHelper.ImportingHistory importingHistory = parentFragment.getSendMessagesHelper().getImportingHistory(((ChatActivity) parentFragment).getDialogId());
if (importingHistory == null) {
return;
@ -762,10 +806,12 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
} else {
if (VoIPService.getSharedInstance() != null && !VoIPService.getSharedInstance().isHangingUp() && VoIPService.getSharedInstance().getCallState() != VoIPService.STATE_WAITING_INCOMING) {
show = true;
startJoinFlickerAnimation();
} else if (fragment instanceof ChatActivity && fragment.getSendMessagesHelper().getImportingHistory(((ChatActivity) fragment).getDialogId()) != null && !isPlayingVoice()) {
show = true;
} else if (fragment instanceof ChatActivity && ((ChatActivity) fragment).getGroupCall() != null && ((ChatActivity) fragment).getGroupCall().shouldShowPanel() && !GroupCallPip.isShowing() && !isPlayingVoice()) {
show = true;
startJoinFlickerAnimation();
} else {
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
if (messageObject != null && messageObject.getId() != 0) {
@ -795,19 +841,19 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
private void updateStyle(int style) {
private void updateStyle(@Style int style) {
if (currentStyle == style) {
return;
}
if (currentStyle == 3 || currentStyle == 1) {
if (currentStyle == STYLE_ACTIVE_GROUP_CALL || currentStyle == STYLE_CONNECTING_GROUP_CALL) {
Theme.getFragmentContextViewWavesDrawable().removeParent(this);
if (VoIPService.getSharedInstance() != null) {
VoIPService.getSharedInstance().unregisterStateListener(this);
}
}
currentStyle = style;
frameLayout.setWillNotDraw(currentStyle != 4);
if (style != 4) {
frameLayout.setWillNotDraw(currentStyle != STYLE_INACTIVE_GROUP_CALL);
if (style != STYLE_INACTIVE_GROUP_CALL) {
timeLayout = null;
}
@ -822,7 +868,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
updatePaddings();
setTopPadding(AndroidUtilities.dp2(getStyleHeight()));
}
if (style == 5) {
if (style == STYLE_IMPORTING_MESSAGES) {
selector.setBackground(Theme.getSelectorDrawable(false));
frameLayout.setBackgroundColor(getThemedColor(Theme.key_inappPlayerBackground));
frameLayout.setTag(Theme.key_inappPlayerBackground);
@ -851,7 +897,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
playbackSpeedButton.setVisibility(GONE);
}
titleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 35, 0, 36, 0));
} else if (style == 0 || style == 2) {
} else if (style == STYLE_AUDIO_PLAYER || style == STYLE_LIVE_LOCATION) {
selector.setBackground(Theme.getSelectorDrawable(false));
frameLayout.setBackgroundColor(getThemedColor(Theme.key_inappPlayerBackground));
frameLayout.setTag(Theme.key_inappPlayerBackground);
@ -875,7 +921,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
}
titleTextView.setTag(Theme.key_inappPlayerTitle);
if (style == 0) {
if (style == STYLE_AUDIO_PLAYER) {
playButton.setLayoutParams(LayoutHelper.createFrame(36, 36, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0));
titleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 35, 0, 36, 0));
if (playbackSpeedButton != null) {
@ -887,7 +933,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
titleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 35 + 16, 0, 36, 0));
closeButton.setContentDescription(LocaleController.getString("AccDescrStopLiveLocation", R.string.AccDescrStopLiveLocation));
}
} else if (style == 4) {
} else if (style == STYLE_INACTIVE_GROUP_CALL) {
selector.setBackground(Theme.getSelectorDrawable(false));
frameLayout.setBackgroundColor(getThemedColor(Theme.key_inappPlayerBackground));
frameLayout.setTag(Theme.key_inappPlayerBackground);
@ -929,18 +975,13 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
if (playbackSpeedButton != null) {
playbackSpeedButton.setVisibility(GONE);
}
} else if (style == 1 || style == 3) {
} else if (style == STYLE_CONNECTING_GROUP_CALL || style == STYLE_ACTIVE_GROUP_CALL) {
selector.setBackground(null);
updateCallTitle();
boolean isRtmpStream = false;
if (fragment instanceof ChatActivity) {
ChatActivity chatActivity = (ChatActivity) fragment;
isRtmpStream = chatActivity.getGroupCall() != null && chatActivity.getGroupCall().call != null && chatActivity.getGroupCall().call.rtmp_stream;
}
boolean isRtmpStream = VoIPService.hasRtmpStream();
avatars.setVisibility(!isRtmpStream ? VISIBLE : GONE);
if (style == 3) {
if (style == STYLE_ACTIVE_GROUP_CALL) {
if (VoIPService.getSharedInstance() != null) {
VoIPService.getSharedInstance().registerStateListener(this);
}
@ -1022,7 +1063,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.groupCallVisibilityChanged);
}
if (currentStyle == 3 || currentStyle == 1) {
if (currentStyle == STYLE_ACTIVE_GROUP_CALL || currentStyle == STYLE_CONNECTING_GROUP_CALL) {
Theme.getFragmentContextViewWavesDrawable().removeParent(this);
}
if (VoIPService.getSharedInstance() != null) {
@ -1073,7 +1114,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
}
if (currentStyle == 3 || currentStyle == 1) {
if (currentStyle == STYLE_ACTIVE_GROUP_CALL || currentStyle == STYLE_CONNECTING_GROUP_CALL) {
Theme.getFragmentContextViewWavesDrawable().addParent(this);
if (VoIPService.getSharedInstance() != null) {
VoIPService.getSharedInstance().registerStateListener(this);
@ -1085,7 +1126,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
muteDrawable.setCurrentFrame(muteDrawable.getCustomEndFrame() - 1, false, true);
muteButton.invalidate();
}
} else if (currentStyle == 4) {
} else if (currentStyle == STYLE_INACTIVE_GROUP_CALL) {
if (!scheduleRunnableScheduled) {
scheduleRunnableScheduled = true;
updateScheduleTimeRunnable.run();
@ -1118,13 +1159,13 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
}
} else if (id == NotificationCenter.messagePlayingDidStart || id == NotificationCenter.messagePlayingPlayStateChanged || id == NotificationCenter.messagePlayingDidReset || id == NotificationCenter.didEndCall) {
if (currentStyle == 1 || currentStyle == 3 || currentStyle == 4) {
if (currentStyle == STYLE_CONNECTING_GROUP_CALL || currentStyle == STYLE_ACTIVE_GROUP_CALL || currentStyle == STYLE_INACTIVE_GROUP_CALL) {
checkCall(false);
}
checkPlayer(false);
} else if (id == NotificationCenter.didStartedCall || id == NotificationCenter.groupCallUpdated || id == NotificationCenter.groupCallVisibilityChanged) {
checkCall(false);
if (currentStyle == 3) {
if (currentStyle == STYLE_ACTIVE_GROUP_CALL) {
VoIPService sharedInstance = VoIPService.getSharedInstance();
if (sharedInstance != null && sharedInstance.groupCall != null) {
if (id == NotificationCenter.didStartedCall) {
@ -1145,7 +1186,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
}
} else if (id == NotificationCenter.groupCallTypingsUpdated) {
if (visible && currentStyle == 4) {
if (visible && currentStyle == STYLE_INACTIVE_GROUP_CALL) {
ChatObject.Call call = ((ChatActivity) fragment).getGroupCall();
if (call != null) {
if (call.isScheduled()) {
@ -1159,7 +1200,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
updateAvatars(true);
}
} else if (id == NotificationCenter.historyImportProgressChanged) {
if (currentStyle == 1 || currentStyle == 3 || currentStyle == 4) {
if (currentStyle == STYLE_CONNECTING_GROUP_CALL || currentStyle == STYLE_ACTIVE_GROUP_CALL || currentStyle == STYLE_INACTIVE_GROUP_CALL) {
checkCall(false);
}
checkImport(false);
@ -1191,11 +1232,11 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
float micAmplitude;
public int getStyleHeight() {
return currentStyle == 4 ? 48 : 36;
return currentStyle == STYLE_INACTIVE_GROUP_CALL ? 48 : 36;
}
public boolean isCallTypeVisible() {
return (currentStyle == 1 || currentStyle == 3) && visible;
return (currentStyle == STYLE_CONNECTING_GROUP_CALL || currentStyle == STYLE_ACTIVE_GROUP_CALL) && visible;
}
private void checkLiveLocation(boolean create) {
@ -1242,7 +1283,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
}
} else {
updateStyle(2);
updateStyle(STYLE_LIVE_LOCATION);
playButton.setImageDrawable(new ShareLocationDrawable(getContext(), 1));
if (create && topPadding == 0) {
setTopPadding(AndroidUtilities.dp2(getStyleHeight()));
@ -1401,7 +1442,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
private void checkPlayer(boolean create) {
if (visible && (currentStyle == 1 || currentStyle == 3 || (currentStyle == 4 || currentStyle == 5) && !isPlayingVoice())) {
if (visible && (currentStyle == STYLE_CONNECTING_GROUP_CALL || currentStyle == STYLE_ACTIVE_GROUP_CALL || (currentStyle == STYLE_INACTIVE_GROUP_CALL || currentStyle == STYLE_IMPORTING_MESSAGES) && !isPlayingVoice())) {
return;
}
MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
@ -1474,12 +1515,12 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
setVisibility(View.GONE);
}
} else {
if (currentStyle != 0 && animatorSet != null && !create) {
if (currentStyle != STYLE_AUDIO_PLAYER && animatorSet != null && !create) {
checkPlayerAfterAnimation = true;
return;
}
int prevStyle = currentStyle;
updateStyle(0);
updateStyle(STYLE_AUDIO_PLAYER);
if (create && topPadding == 0) {
updatePaddings();
setTopPadding(AndroidUtilities.dp2(getStyleHeight()));
@ -1540,7 +1581,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
playPauseDrawable.setPause(true, !create);
playButton.setContentDescription(LocaleController.getString("AccActionPause", R.string.AccActionPause));
}
if (lastMessageObject != messageObject || prevStyle != 0) {
if (lastMessageObject != messageObject || prevStyle != STYLE_AUDIO_PLAYER) {
lastMessageObject = messageObject;
SpannableStringBuilder stringBuilder;
if (lastMessageObject.isVoice() || lastMessageObject.isRoundVideo()) {
@ -1594,7 +1635,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
public void checkImport(boolean create) {
if (!(fragment instanceof ChatActivity) || visible && (currentStyle == 1 || currentStyle == 3)) {
if (!(fragment instanceof ChatActivity) || visible && (currentStyle == STYLE_CONNECTING_GROUP_CALL || currentStyle == STYLE_ACTIVE_GROUP_CALL)) {
return;
}
ChatActivity chatActivity = (ChatActivity) fragment;
@ -1612,7 +1653,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
if (importingHistory == null) {
if (visible && (create && currentStyle == -1 || currentStyle == 5)) {
if (visible && (create && currentStyle == STYLE_NOT_SET || currentStyle == STYLE_IMPORTING_MESSAGES)) {
visible = false;
if (create) {
if (getVisibility() != GONE) {
@ -1652,17 +1693,16 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
});
animatorSet.start();
}
} else if (currentStyle == -1 || currentStyle == 5) {
} else if (currentStyle == STYLE_NOT_SET || currentStyle == STYLE_IMPORTING_MESSAGES) {
visible = false;
setVisibility(GONE);
}
} else {
if (currentStyle != 5 && animatorSet != null && !create) {
if (currentStyle != STYLE_IMPORTING_MESSAGES && animatorSet != null && !create) {
checkImportAfterAnimation = true;
return;
}
int prevStyle = currentStyle;
updateStyle(5);
updateStyle(STYLE_IMPORTING_MESSAGES);
if (create && topPadding == 0) {
updatePaddings();
setTopPadding(AndroidUtilities.dp2(getStyleHeight()));
@ -1730,7 +1770,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
public void checkCall(boolean create) {
VoIPService voIPService = VoIPService.getSharedInstance();
if (visible && currentStyle == 5 && (voIPService == null || voIPService.isHangingUp())) {
if (visible && currentStyle == STYLE_IMPORTING_MESSAGES && (voIPService == null || voIPService.isHangingUp())) {
return;
}
View fragmentView = fragment.getFragmentView();
@ -1760,7 +1800,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
if (!callAvailable) {
if (visible && (create && currentStyle == -1 || currentStyle == 4 || currentStyle == 3 || currentStyle == 1)) {
if (visible && (create && currentStyle == STYLE_NOT_SET || currentStyle == STYLE_INACTIVE_GROUP_CALL || currentStyle == STYLE_ACTIVE_GROUP_CALL || currentStyle == STYLE_CONNECTING_GROUP_CALL)) {
visible = false;
if (create) {
if (getVisibility() != GONE) {
@ -1800,7 +1840,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
});
animatorSet.start();
}
} else if (visible && (currentStyle == -1 || currentStyle == 4 || currentStyle == 3 || currentStyle == 1)) {
} else if (visible && (currentStyle == STYLE_NOT_SET || currentStyle == STYLE_INACTIVE_GROUP_CALL || currentStyle == STYLE_ACTIVE_GROUP_CALL || currentStyle == STYLE_CONNECTING_GROUP_CALL)) {
visible = false;
setVisibility(GONE);
}
@ -1811,11 +1851,11 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
} else {
int newStyle;
if (groupActive) {
newStyle = 4;
newStyle = STYLE_INACTIVE_GROUP_CALL;
} else if (voIPService.groupCall != null) {
newStyle = 3;
newStyle = STYLE_ACTIVE_GROUP_CALL;
} else {
newStyle = 1;
newStyle = STYLE_CONNECTING_GROUP_CALL;
}
if (newStyle != currentStyle && animatorSet != null && !create) {
checkCallAfterAnimation = true;
@ -1847,8 +1887,8 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
return;
}
if (groupActive) {
boolean updateAnimated = currentStyle == 4 && visible;
updateStyle(4);
boolean updateAnimated = currentStyle == STYLE_INACTIVE_GROUP_CALL && visible;
updateStyle(STYLE_INACTIVE_GROUP_CALL);
ChatObject.Call call = ((ChatActivity) fragment).getGroupCall();
TLRPC.Chat chat = ((ChatActivity) fragment).getCurrentChat();
@ -1882,7 +1922,9 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
} else {
timeLayout = null;
joinButton.setVisibility(VISIBLE);
if (ChatObject.isChannelOrGiga(chat)) {
if (call.call.rtmp_stream) {
titleTextView.setText(LocaleController.getString(R.string.VoipChannelVoiceChat), false);
} else if (ChatObject.isChannelOrGiga(chat)) {
titleTextView.setText(LocaleController.getString("VoipChannelVoiceChat", R.string.VoipChannelVoiceChat), false);
} else {
titleTextView.setText(LocaleController.getString("VoipGroupVoiceChat", R.string.VoipGroupVoiceChat), false);
@ -1898,11 +1940,11 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
updateAvatars(avatars.avatarsDarawable.wasDraw && updateAnimated);
} else {
if (voIPService != null && voIPService.groupCall != null) {
updateAvatars(currentStyle == 3);
updateStyle(3);
updateAvatars(currentStyle == STYLE_ACTIVE_GROUP_CALL);
updateStyle(STYLE_ACTIVE_GROUP_CALL);
} else {
updateAvatars(currentStyle == 1);
updateStyle(1);
updateAvatars(currentStyle == STYLE_CONNECTING_GROUP_CALL);
updateStyle(STYLE_CONNECTING_GROUP_CALL);
}
}
if (!visible) {
@ -1939,12 +1981,15 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
checkCallAfterAnimation = false;
checkPlayerAfterAnimation = false;
checkImportAfterAnimation = false;
startJoinFlickerAnimation();
}
});
animatorSet.start();
} else {
updatePaddings();
setTopPadding(AndroidUtilities.dp2(getStyleHeight()));
startJoinFlickerAnimation();
}
visible = true;
setVisibility(VISIBLE);
@ -1952,6 +1997,12 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
}
private void startJoinFlickerAnimation() {
if (joinButtonFlicker.getProgress() > 1) {
AndroidUtilities.runOnUIThread(()-> joinButtonFlicker.setProgress(0), 150);
}
}
private void updateAvatars(boolean animated) {
if (!animated) {
if (avatars.avatarsDarawable.transitionProgressAnimator != null) {
@ -1963,7 +2014,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
TLRPC.User userCall;
if (avatars.avatarsDarawable.transitionProgressAnimator == null) {
int currentAccount;
if (currentStyle == 4) {
if (currentStyle == STYLE_INACTIVE_GROUP_CALL) {
if (fragment instanceof ChatActivity) {
ChatActivity chatActivity = (ChatActivity) fragment;
call = chatActivity.getGroupCall();
@ -2004,7 +2055,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
avatars.commitTransition(animated);
if (currentStyle == 4 && call != null) {
if (currentStyle == STYLE_INACTIVE_GROUP_CALL && call != null) {
int N = call.call.rtmp_stream ? 0 : Math.min(3, call.sortedParticipants.size());
int x = N == 0 ? 10 : (10 + 24 * (N - 1) + 32 + 10);
if (animated) {
@ -2048,7 +2099,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
return;
}
boolean clipped = false;
if ((currentStyle == 3 || currentStyle == 1) && drawOverlay) {
if ((currentStyle == STYLE_ACTIVE_GROUP_CALL || currentStyle == STYLE_CONNECTING_GROUP_CALL) && drawOverlay) {
boolean mutedByAdmin = GroupCallActivity.groupCallInstance == null && Theme.getFragmentContextViewWavesDrawable().getState() == FragmentContextViewWavesDrawable.MUTE_BUTTON_STATE_MUTED_BY_ADMIN;
Theme.getFragmentContextViewWavesDrawable().updateState(wasDraw);
@ -2087,7 +2138,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
@Override
public void invalidate() {
super.invalidate();
if (currentStyle == 3 || currentStyle == 1) {
if (currentStyle == STYLE_ACTIVE_GROUP_CALL || currentStyle == STYLE_CONNECTING_GROUP_CALL) {
if (getParent() != null) {
((View) getParent()).invalidate();
}
@ -2095,7 +2146,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
public boolean isCallStyle() {
return currentStyle == 3 || currentStyle == 1;
return currentStyle == STYLE_ACTIVE_GROUP_CALL || currentStyle == STYLE_CONNECTING_GROUP_CALL;
}
@Override
@ -2129,7 +2180,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
private void updateCallTitle() {
VoIPService service = VoIPService.getSharedInstance();
if (service != null && (currentStyle == 1 || currentStyle == 3)) {
if (service != null && (currentStyle == STYLE_CONNECTING_GROUP_CALL || currentStyle == STYLE_ACTIVE_GROUP_CALL)) {
int currentCallState = service.getCallState();
if (!service.isSwitchingStream() && (currentCallState == VoIPService.STATE_WAIT_INIT || currentCallState == VoIPService.STATE_WAIT_INIT_ACK || currentCallState == VoIPService.STATE_CREATING || currentCallState == VoIPService.STATE_RECONNECTING)) {
titleTextView.setText(LocaleController.getString("VoipGroupConnecting", R.string. VoipGroupConnecting), false);
@ -2139,10 +2190,14 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
} else {
if (fragment instanceof ChatActivity && ((ChatActivity) fragment).getCurrentChat() != null && ((ChatActivity) fragment).getCurrentChat().id == service.getChat().id) {
TLRPC.Chat chat = ((ChatActivity) fragment).getCurrentChat();
if (ChatObject.isChannelOrGiga(chat)) {
titleTextView.setText(LocaleController.getString("VoipChannelViewVoiceChat", R.string.VoipChannelViewVoiceChat), false);
if (VoIPService.hasRtmpStream()) {
titleTextView.setText(LocaleController.getString(R.string.VoipChannelViewVoiceChat), false);
} else {
titleTextView.setText(LocaleController.getString("VoipGroupViewVoiceChat", R.string.VoipGroupViewVoiceChat), false);
if (ChatObject.isChannelOrGiga(chat)) {
titleTextView.setText(LocaleController.getString("VoipChannelViewVoiceChat", R.string.VoipChannelViewVoiceChat), false);
} else {
titleTextView.setText(LocaleController.getString("VoipGroupViewVoiceChat", R.string.VoipGroupViewVoiceChat), false);
}
}
} else {
titleTextView.setText(service.getChat().title, false);
@ -2160,9 +2215,9 @@ public class FragmentContextView extends FrameLayout implements NotificationCent
}
private int getTitleTextColor() {
if (currentStyle == 4) {
if (currentStyle == STYLE_INACTIVE_GROUP_CALL) {
return getThemedColor(Theme.key_inappPlayerPerformer);
} else if (currentStyle == 1 || currentStyle == 3) {
} else if (currentStyle == STYLE_CONNECTING_GROUP_CALL || currentStyle == STYLE_ACTIVE_GROUP_CALL) {
return getThemedColor(Theme.key_returnToCallText);
}
return getThemedColor(Theme.key_inappPlayerTitle);

View File

@ -22,6 +22,10 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.core.graphics.ColorUtils;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.LocaleController;
@ -31,10 +35,6 @@ import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.BottomSheet;
import org.telegram.ui.ActionBar.Theme;
import androidx.core.graphics.ColorUtils;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
public class GroupCallRecordAlert extends BottomSheet {
private ViewPager viewPager;
@ -275,7 +275,7 @@ public class GroupCallRecordAlert extends BottomSheet {
positiveButton.invalidate();
}
protected void onStartRecord(int type) {
public void onStartRecord(@ChatObject.Call.RecordType int type) {
}

View File

@ -398,7 +398,7 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega
didSelectPhotos(media);
if (button != 8) {
chatAttachAlert.dismiss();
chatAttachAlert.dismiss(true);
}
return;
} else {
@ -562,11 +562,13 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega
}
public void onRequestPermissionsResultFragment(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == 17 && chatAttachAlert != null) {
chatAttachAlert.getPhotoLayout().checkCamera(false);
chatAttachAlert.getPhotoLayout().checkStorage();
} else if (requestCode == BasePermissionsActivity.REQUEST_CODE_EXTERNAL_STORAGE) {
chatAttachAlert.getPhotoLayout().checkStorage();
if (chatAttachAlert != null) {
if (requestCode == 17) {
chatAttachAlert.getPhotoLayout().checkCamera(false);
chatAttachAlert.getPhotoLayout().checkStorage();
} else if (requestCode == BasePermissionsActivity.REQUEST_CODE_EXTERNAL_STORAGE) {
chatAttachAlert.getPhotoLayout().checkStorage();
}
}
}

View File

@ -16,6 +16,7 @@ import android.view.View;
import android.view.animation.DecelerateInterpolator;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.ui.Components.voip.CellFlickerDrawable;
public class LineProgressView extends View {
@ -34,6 +35,8 @@ public class LineProgressView extends View {
private RectF rect = new RectF();
CellFlickerDrawable cellFlickerDrawable;
public LineProgressView(Context context) {
super(context);
@ -108,13 +111,26 @@ public class LineProgressView extends View {
progressPaint.setAlpha((int) (255 * animatedAlphaValue));
int start = (int) (getWidth() * animatedProgressValue);
rect.set(0, 0, getWidth(), getHeight());
canvas.drawRoundRect(rect, getHeight() / 2, getHeight() / 2, progressPaint);
canvas.drawRoundRect(rect, getHeight() / 2f, getHeight() / 2f, progressPaint);
}
progressPaint.setColor(progressColor);
progressPaint.setAlpha((int) (255 * animatedAlphaValue));
rect.set(0, 0, getWidth() * animatedProgressValue, getHeight());
canvas.drawRoundRect(rect, getHeight() / 2, getHeight() / 2, progressPaint);
canvas.drawRoundRect(rect, getHeight() / 2f, getHeight() / 2f, progressPaint);
if (animatedAlphaValue > 0) {
if (cellFlickerDrawable == null) {
cellFlickerDrawable = new CellFlickerDrawable(160, 0);
cellFlickerDrawable.drawFrame = false;
cellFlickerDrawable.animationSpeedScale = 0.8f;
cellFlickerDrawable.repeatProgress = 1.2f;
}
cellFlickerDrawable.setParentWidth(getMeasuredWidth());
cellFlickerDrawable.draw(canvas, rect, getHeight() / 2f);
invalidate();
}
updateAnimation();
}
}

View File

@ -222,7 +222,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
@Override
protected void drawBackgroundWithBlur(Canvas canvas, float y, Rect rectTmp2, Paint backgroundPaint) {
fragmentView.drawBlur(canvas, getY() + y, rectTmp2, backgroundPaint, true);
fragmentView.drawBlurRect(canvas, getY() + y, rectTmp2, backgroundPaint, true);
}
@Override
@ -237,7 +237,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
fragmentView.addView(sharedMediaLayout);
fragmentView.addView(actionBar);
fragmentView.addView(avatarContainer);
fragmentView.blurBehindViews.add(sharedMediaLayout.scrollSlidingTextTabStrip);
fragmentView.blurBehindViews.add(sharedMediaLayout);
TLObject avatarObject = null;
if (DialogObject.isEncryptedDialog(dialogId)) {

View File

@ -324,6 +324,9 @@ public class MotionBackgroundDrawable extends Drawable {
} else {
gradientDrawable = null;
}
if (colors[0] == c1 || colors[1] == c2 || colors[2] == c3 || colors[3] == c4) {
return;
}
colors[0] = c1;
colors[1] = c2;
colors[2] = c3;

View File

@ -742,7 +742,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica
return emojiView != null && emojiView.getVisibility() == VISIBLE;
}
public boolean isPopupAnimatig() {
public boolean isPopupAnimating() {
return popupAnimating;
}

View File

@ -27,6 +27,8 @@ import org.telegram.messenger.UserConfig;
import org.telegram.ui.ActionBar.ActionBarPopupWindow;
import org.telegram.ui.ActionBar.Theme;
import java.util.ArrayList;
public class PopupSwipeBackLayout extends FrameLayout {
private final static int DURATION = 300;
@ -43,7 +45,7 @@ public class PopupSwipeBackLayout extends FrameLayout {
private Path mPath = new Path();
private RectF mRect = new RectF();
private OnSwipeBackProgressListener onSwipeBackProgressListener;
private ArrayList<OnSwipeBackProgressListener> onSwipeBackProgressListeners = new ArrayList<>();
private boolean isSwipeBackDisallowed;
private float overrideForegroundHeight;
@ -113,12 +115,12 @@ public class PopupSwipeBackLayout extends FrameLayout {
}
/**
* Sets new swipeback listener
* add new swipeback listener
*
* @param onSwipeBackProgressListener New progress listener
*/
public void setOnSwipeBackProgressListener(OnSwipeBackProgressListener onSwipeBackProgressListener) {
this.onSwipeBackProgressListener = onSwipeBackProgressListener;
public void addOnSwipeBackProgressListener(OnSwipeBackProgressListener onSwipeBackProgressListener) {
onSwipeBackProgressListeners.add(onSwipeBackProgressListener);
}
@Override
@ -143,8 +145,10 @@ public class PopupSwipeBackLayout extends FrameLayout {
*/
private void invalidateTransforms() {
if (onSwipeBackProgressListener != null) {
onSwipeBackProgressListener.onSwipeBackProgress(this, toProgress, transitionProgress);
if (!onSwipeBackProgressListeners.isEmpty()) {
for (int i = 0; i < onSwipeBackProgressListeners.size(); i++) {
onSwipeBackProgressListeners.get(i).onSwipeBackProgress(this, toProgress, transitionProgress);
}
}
View bg = getChildAt(0);

View File

@ -182,9 +182,11 @@ public class ReactedHeaderView extends FrameLayout {
private void loadReactions() {
MessagesController ctrl = MessagesController.getInstance(currentAccount);
TLRPC.TL_messages_getMessageReactionsList getList = new TLRPC.TL_messages_getMessageReactionsList();
getList.peer = ctrl.getInputPeer(dialogId);
getList.peer = ctrl.getInputPeer(message.getDialogId());
getList.id = message.getId();
getList.limit = 3;
getList.reaction = null;
getList.offset = null;
ConnectionsManager.getInstance(currentAccount).sendRequest(getList, (response, error) -> {
if (response instanceof TLRPC.TL_messages_messageReactionsList) {
TLRPC.TL_messages_messageReactionsList list = (TLRPC.TL_messages_messageReactionsList) response;

View File

@ -52,7 +52,7 @@ public class ReactedUsersListView extends FrameLayout {
private FlickerLoadingView loadingView;
private List<TLRPC.TL_messagePeerReaction> userReactions = new ArrayList<>();
private LongSparseArray<TLRPC.User> users = new LongSparseArray<>();
private LongSparseArray<TLRPC.TL_messagePeerReaction> peerReactionMap = new LongSparseArray<>();
private String offset;
private boolean isLoading, isLoaded, canLoadMore = true;
private boolean onlySeenNow;
@ -127,16 +127,19 @@ public class ReactedUsersListView extends FrameLayout {
public ReactedUsersListView setSeenUsers(List<TLRPC.User> users) {
List<TLRPC.TL_messagePeerReaction> nr = new ArrayList<>(users.size());
for (TLRPC.User u : users) {
if (this.users.get(u.id) != null) continue;
this.users.put(u.id, u);
if (peerReactionMap.get(u.id) != null) {
continue;
}
TLRPC.TL_messagePeerReaction r = new TLRPC.TL_messagePeerReaction();
r.reaction = null;
r.peer_id = new TLRPC.TL_peerUser();
r.peer_id.user_id = u.id;
peerReactionMap.put(MessageObject.getPeerId(r.peer_id), r);
nr.add(r);
}
if (userReactions.isEmpty())
if (userReactions.isEmpty()) {
onlySeenNow = true;
}
userReactions.addAll(nr);
adapter.notifyDataSetChanged();
updateHeight();
@ -167,30 +170,34 @@ public class ReactedUsersListView extends FrameLayout {
if (offset != null)
getList.flags |= 2;
ConnectionsManager.getInstance(currentAccount).sendRequest(getList, (response, error) -> {
if (response instanceof TLRPC.TL_messages_messageReactionsList) {
TLRPC.TL_messages_messageReactionsList l = (TLRPC.TL_messages_messageReactionsList) response;
AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).doOnIdle(() -> {
if (response instanceof TLRPC.TL_messages_messageReactionsList) {
TLRPC.TL_messages_messageReactionsList res = (TLRPC.TL_messages_messageReactionsList) response;
for (TLRPC.User u : l.users) {
MessagesController.getInstance(currentAccount).putUser(u, false);
users.put(u.id, u);
}
for (TLRPC.User u : res.users) {
MessagesController.getInstance(currentAccount).putUser(u, false);
}
// It's safer to create a new list to prevent inconsistency
int prev = userReactions.size();
List<TLRPC.TL_messagePeerReaction> newReactions = new ArrayList<>(userReactions.size() + l.reactions.size());
newReactions.addAll(userReactions);
newReactions.addAll(l.reactions);
for (int i = 0; i < res.reactions.size(); i++) {
userReactions.add(res.reactions.get(i));
long peerId = MessageObject.getPeerId(res.reactions.get(i).peer_id);
TLRPC.TL_messagePeerReaction reaction = peerReactionMap.get(peerId);
if (reaction != null) {
userReactions.remove(reaction);
}
peerReactionMap.put(peerId, res.reactions.get(i));
if (onlySeenNow) {
Collections.sort(newReactions, (o1, o2) -> Integer.compare(o1.reaction != null ? 1 : 0, o2.reaction != null ? 1 : 0));
}
}
if (onlySeenNow) {
Collections.sort(userReactions, (o1, o2) -> Integer.compare(o1.reaction != null ? 1 : 0, o2.reaction != null ? 1 : 0));
}
AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).doOnIdle(() -> {
userReactions = newReactions;
if (onlySeenNow) {
onlySeenNow = false;
adapter.notifyDataSetChanged();
} else adapter.notifyItemRangeInserted(prev, l.reactions.size());
}
adapter.notifyDataSetChanged();
if (!isLoaded) {
ValueAnimator anim = ValueAnimator.ofFloat(0, 1).setDuration(150);
@ -212,12 +219,14 @@ public class ReactedUsersListView extends FrameLayout {
isLoaded = true;
}
offset = l.next_offset;
offset = res.next_offset;
if (offset == null)
canLoadMore = false;
isLoading = false;
}));
} else isLoading = false;
} else {
isLoading = false;
}
}));
}, ConnectionsManager.RequestFlagInvokeAfter);
}
@ -272,7 +281,10 @@ public class ReactedUsersListView extends FrameLayout {
}
void setUserReaction(TLRPC.TL_messagePeerReaction reaction) {
TLRPC.User u = users.get(MessageObject.getPeerId(reaction.peer_id));
TLRPC.User u = MessagesController.getInstance(currentAccount).getUser(MessageObject.getPeerId(reaction.peer_id));
if (u == null) {
return;
}
avatarDrawable.setInfo(u);
titleView.setText(UserObject.getUserName(u));
avatarView.setImage(ImageLocation.getForUser(u, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, u);

View File

@ -158,7 +158,7 @@ public class ReactionsLayoutInBubble {
isEmpty = reactionButtons.isEmpty();
}
public void measure(int availableWidth) {
public void measure(int availableWidth, int gravity) {
height = 0;
width = 0;
positionOffsetY = 0;
@ -199,10 +199,33 @@ public class ReactionsLayoutInBubble {
if (currentX > maxWidth) {
maxWidth = currentX;
}
}
if (gravity == Gravity.RIGHT && !reactionButtons.isEmpty()) {
int fromP = 0;
int startY = reactionButtons.get(0).y;
for (int i = 0; i < reactionButtons.size(); i++) {
if (reactionButtons.get(i).y != startY) {
int lineOffset = availableWidth - reactionButtons.get(i - 1).x + reactionButtons.get(i - 1).width;
for (int k = fromP; k < i; k++) {
reactionButtons.get(k).x += lineOffset;
}
fromP = i;
}
}
int last = reactionButtons.size() - 1;
if (fromP != last) {
int lineOffset = availableWidth - (reactionButtons.get(last).x + reactionButtons.get(last).width);
for (int k = fromP; k <= last; k++) {
reactionButtons.get(k).x += lineOffset;
}
}
}
lastLineX = currentX;
width = maxWidth;
if (gravity == Gravity.RIGHT) {
width = availableWidth;
} else {
width = maxWidth;
}
height = currentY + (reactionButtons.size() == 0 ? 0 : AndroidUtilities.dp(26));
drawServiceShaderBackground = false;
}
@ -304,7 +327,7 @@ public class ReactionsLayoutInBubble {
if (lastButton.avatarsDarawable == null) {
lastButton.setUsers(new ArrayList<>());
}
button.avatarsDarawable.animateFromState(lastButton.avatarsDarawable, currentAccount);
button.avatarsDarawable.animateFromState(lastButton.avatarsDarawable, currentAccount, false);
}
changed = true;
} else {
@ -437,9 +460,8 @@ public class ReactionsLayoutInBubble {
TLRPC.TL_availableReaction r = MediaDataController.getInstance(currentAccount).getReactionsMap().get(reaction);
if (r != null) {
SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(r.static_icon, Theme.key_windowBackgroundGray, 1.0f);
imageReceiver.setImage(ImageLocation.getForDocument(r.static_icon), "40_40", svgThumb, "webp", r, 1);
//TODO uncomment when fixed ImageLoader
//imageReceiver.setImage(ImageLocation.getForDocument(r.center_icon), "40_40_firstframe", svgThumb, "webp", r, 1);
//imageReceiver.setImage(ImageLocation.getForDocument(r.static_icon), "40_40", svgThumb, "webp", r, 1);
imageReceiver.setImage(ImageLocation.getForDocument(r.center_icon), "40_40_lastframe", svgThumb, "webp", r, 1);
}
}
@ -510,6 +532,7 @@ public class ReactionsLayoutInBubble {
canvas.save();
canvas.translate(AndroidUtilities.dp(10) + AndroidUtilities.dp(20) + AndroidUtilities.dp(2), 0);
avatarsDarawable.setAlpha(alpha);
avatarsDarawable.setTransitionProgress(progress);
avatarsDarawable.onDraw(canvas);
canvas.restore();
}

View File

@ -44,6 +44,7 @@ import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.SvgHelper;
import org.telegram.messenger.Utilities;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
@ -323,11 +324,13 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
super.dispatchDraw(canvas);
if (leftShadowPaint != null) {
leftShadowPaint.setAlpha((int) (leftAlpha * transitionProgress * 0xFF));
float p = Utilities.clamp(leftAlpha * transitionProgress, 1f, 0f);
leftShadowPaint.setAlpha((int) (p * 0xFF));
canvas.drawRect(rect, leftShadowPaint);
}
if (rightShadowPaint != null) {
rightShadowPaint.setAlpha((int) (rightAlpha * transitionProgress * 0xFF));
float p = Utilities.clamp(rightAlpha * transitionProgress, 1f, 0f);
rightShadowPaint.setAlpha((int) (p * 0xFF));
canvas.drawRect(rect, rightShadowPaint);
}
canvas.restoreToCount(s);

View File

@ -22,11 +22,11 @@ import androidx.recyclerview.widget.RecyclerView;
import org.telegram.messenger.AccountInstance;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.DownloadController;
import org.telegram.messenger.FileLoader;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.MessagesStorage;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
@ -37,6 +37,7 @@ import org.telegram.ui.ActionBar.BottomSheet;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.CacheControlActivity;
import org.telegram.ui.Cells.GraySectionCell;
import org.telegram.ui.Cells.SharedAudioCell;
import org.telegram.ui.Cells.SharedDocumentCell;
import org.telegram.ui.FilteredSearchView;
import org.telegram.ui.PhotoViewer;
@ -86,7 +87,7 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio
recyclerListView.setLayoutManager(new LinearLayoutManager(fragment.getParentActivity()) {
@Override
public boolean supportsPredictiveItemAnimations() {
return false;
return true;
}
});
recyclerListView.setAdapter(adapter);
@ -104,16 +105,21 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio
recyclerListView.setItemAnimator(defaultItemAnimator);
recyclerListView.setOnItemClickListener((view, position) -> {
MessageObject messageObject = adapter.getMessage(position);
if (messageObject == null) {
return;
}
if (uiCallback.actionModeShowing()) {
uiCallback.toggleItemSelection(messageObject, view, 0);
messageHashIdTmp.set(messageObject.getId(), messageObject.getDialogId());
adapter.notifyItemChanged(position);
return;
}
if (view instanceof Cell) {
SharedDocumentCell cell = ((Cell) view).sharedDocumentCell;
MessageObject message = cell.getMessage();
TLRPC.Document document = message.getDocument();
if (uiCallback.actionModeShowing()) {
uiCallback.toggleItemSelection(cell.getMessage(), view, 0);
messageHashIdTmp.set(cell.getMessage().getId(), cell.getMessage().getDialogId());
cell.setChecked(uiCallback.isSelected(messageHashIdTmp), true);
return;
};
if (cell.isLoaded()) {
if (message.isRoundVideo() || message.isVoice()) {
MediaController.getInstance().playMessage(message);
@ -126,13 +132,10 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio
documents.add(message);
PhotoViewer.getInstance().setParentActivity(parentActivity);
PhotoViewer.getInstance().openPhoto(documents, 0, 0, 0, new PhotoViewer.EmptyPhotoViewerProvider());
// photoViewerClassGuid = PhotoViewer.getInstance().getClassGuid();
return;
}
AndroidUtilities.openDocument(message, parentActivity, parentFragment);
} else if (!cell.isLoading()) {
MessageObject messageObject = cell.getMessage();
messageObject.putInDownloadsStore = true;
AccountInstance.getInstance(UserConfig.selectedAccount).getFileLoader().loadFile(document, messageObject, 0, 0);
cell.updateFileExistIcon(true);
@ -142,17 +145,21 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio
}
update(true);
}
if (view instanceof SharedAudioCell) {
SharedAudioCell cell = (SharedAudioCell) view;
cell.didPressedButton();
}
});
recyclerListView.setOnItemLongClickListener((view, position) -> {
if (view instanceof Cell) {
SharedDocumentCell cell = ((Cell) view).sharedDocumentCell;
MessageObject messageObject = adapter.getMessage(position);
if (messageObject != null) {
if (!uiCallback.actionModeShowing()) {
uiCallback.showActionMode();
}
if (uiCallback.actionModeShowing()) {
uiCallback.toggleItemSelection(cell.getMessage(), view, 0);
messageHashIdTmp.set(cell.getMessage().getId(), cell.getMessage().getDialogId());
cell.setChecked(uiCallback.isSelected(messageHashIdTmp), true);
uiCallback.toggleItemSelection(messageObject, view, 0);
messageHashIdTmp.set(messageObject.getId(), messageObject.getDialogId());
adapter.notifyItemChanged(position);
}
return true;
}
@ -257,7 +264,7 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio
}
private boolean isEmptyDownloads() {
return MessagesStorage.getInstance(currentAccount).downloadingFiles.isEmpty() && MessagesStorage.getInstance(currentAccount).recentDownloadingFiles.isEmpty();
return DownloadController.getInstance(currentAccount).downloadingFiles.isEmpty() && DownloadController.getInstance(currentAccount).recentDownloadingFiles.isEmpty();
}
private void updateListInternal(boolean animated, ArrayList<MessageObject> currentLoadingFilesTmp, ArrayList<MessageObject> recentLoadingFilesTmp) {
@ -397,9 +404,17 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio
View view;
if (viewType == 0) {
view = new GraySectionCell(parent.getContext());
} else {
} else if (viewType == 1){
Cell sharedDocumentCell = new Cell(parent.getContext());
view = sharedDocumentCell;
} else {
SharedAudioCell sharedAudioCell = new SharedAudioCell(parent.getContext()) {
@Override
public boolean needPlayMessage(MessageObject messageObject) {
return MediaController.getInstance().playMessage(messageObject);
}
};
view = sharedAudioCell;
}
view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
return new RecyclerListView.Holder(view);
@ -435,18 +450,22 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio
});
}
} else {
Cell view = (Cell) holder.itemView;
view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
if (position >= downloadingFilesStartRow && position < downloadingFilesEndRow) {
// currentLoadingFiles.get(position - downloadingFilesStartRow).checkMediaExistance();
view.sharedDocumentCell.setDocument(currentLoadingFiles.get(position - downloadingFilesStartRow), true);
} else if (position >= recentFilesStartRow && position < recentFilesEndRow) {
// recentLoadingFiles.get(position - recentFilesStartRow).checkMediaExistance();
view.sharedDocumentCell.setDocument(recentLoadingFiles.get(position - recentFilesStartRow), true);
MessageObject messageObject = getMessage(position);
if (messageObject != null) {
if (type == 1) {
Cell view = (Cell) holder.itemView;
view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
int oldId = view.sharedDocumentCell.getMessage() == null ? 0 : view.sharedDocumentCell.getMessage().getId();
view.sharedDocumentCell.setDocument(messageObject, true);
messageHashIdTmp.set(view.sharedDocumentCell.getMessage().getId(), view.sharedDocumentCell.getMessage().getDialogId());
view.sharedDocumentCell.setChecked(uiCallback.isSelected(messageHashIdTmp), oldId == messageObject.getId());
} else if (type == 2) {
SharedAudioCell sharedAudioCell = (SharedAudioCell) holder.itemView;
sharedAudioCell.setMessageObject(messageObject, true);
int oldId = sharedAudioCell.getMessage() == null ? 0 : sharedAudioCell.getMessage().getId();
sharedAudioCell.setChecked(uiCallback.isSelected(messageHashIdTmp), oldId == messageObject.getId());
}
}
messageHashIdTmp.set(view.sharedDocumentCell.getMessage().getId(), view.sharedDocumentCell.getMessage().getDialogId());
view.sharedDocumentCell.setChecked(uiCallback.isSelected(messageHashIdTmp), false);
}
}
@ -455,9 +474,25 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio
if (position == downloadingFilesHeader || position == recentFilesHeader) {
return 0;
}
MessageObject messageObject = getMessage(position);
if (messageObject == null) {
return 1;
}
if (messageObject.isMusic()) {
return 2;
}
return 1;
}
private MessageObject getMessage(int position) {
if (position >= downloadingFilesStartRow && position < downloadingFilesEndRow) {;
return currentLoadingFiles.get(position - downloadingFilesStartRow);
} else if (position >= recentFilesStartRow && position < recentFilesEndRow) {
return recentLoadingFiles.get(position - recentFilesStartRow);
}
return null;
}
@Override
public int getItemCount() {
return rowCount;
@ -465,7 +500,7 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio
@Override
public boolean isEnabled(RecyclerView.ViewHolder holder) {
return holder.getItemViewType() == 1;
return holder.getItemViewType() == 1 || holder.getItemViewType() == 2;
}
}
@ -536,7 +571,7 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio
});
buttonTextView2.setOnClickListener(view -> {
bottomSheet.dismiss();
MessagesStorage.getInstance(currentAccount).clearRecentDownloadedFiles();
DownloadController.getInstance(currentAccount).clearRecentDownloadedFiles();
});
//parentFragment.showDialog(bottomSheet);
}
@ -546,7 +581,7 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio
super.onAttachedToWindow();
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.onDownloadingFilesChanged);
if (getVisibility() == View.VISIBLE) {
MessagesStorage.getInstance(currentAccount).clearUnviewedDownloads();
DownloadController.getInstance(currentAccount).clearUnviewedDownloads();
}
}
@ -561,7 +596,7 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio
public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.onDownloadingFilesChanged) {
if (getVisibility() == View.VISIBLE) {
MessagesStorage.getInstance(currentAccount).clearUnviewedDownloads();
DownloadController.getInstance(currentAccount).clearUnviewedDownloads();
}
update(true);
}

View File

@ -59,12 +59,16 @@ public class SearchField extends FrameLayout {
clearSearchImageView = new ImageView(context);
clearSearchImageView.setScaleType(ImageView.ScaleType.CENTER);
clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2());
clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2() {
@Override
protected int getCurrentColor() {
return getThemedColor(Theme.key_dialogSearchIcon);
}
});
progressDrawable.setSide(AndroidUtilities.dp(7));
clearSearchImageView.setScaleX(0.1f);
clearSearchImageView.setScaleY(0.1f);
clearSearchImageView.setAlpha(0.0f);
clearSearchImageView.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogSearchIcon), PorterDuff.Mode.MULTIPLY));
if (supportRtl) {
lp = LayoutHelper.createFrameRelatively(36, 36, Gravity.END | Gravity.TOP, 14, 11, 14, 0);
} else {

View File

@ -364,13 +364,13 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie
spannableStringBuilder
.append(AndroidUtilities.replaceTags(LocaleController.formatPluralString("RemoveDocumentsMessage", selectedFiles.size())))
.append("\n\n")
.append( LocaleController.getString("RemoveDocumentsMessage", R.string.RemoveDocumentsMessage));
.append(LocaleController.getString("RemoveDocumentsAlertMessage", R.string.RemoveDocumentsAlertMessage));
builder.setMessage(spannableStringBuilder);
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), (dialogInterface, i) -> dialogInterface.dismiss());
builder.setPositiveButton(LocaleController.getString("Delete", R.string.Delete), (dialogInterface, i) -> {
dialogInterface.dismiss();
parent.getMessagesStorage().deleteRecentFiles(messageObjects);
parent.getDownloadController().deleteRecentFiles(messageObjects);
hideActionMode();
});
AlertDialog alertDialog = builder.show();
@ -618,6 +618,9 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie
}
public void setPosition(int position) {
if (position < 0) {
return;
}
super.setPosition(position);
viewsByType.clear();
if (tabsView != null) {
@ -662,28 +665,30 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie
noMediaFiltersSearchView.messagesDeleted(channelId, markAsDeletedMessages);
if (!selectedFiles.isEmpty()) {
ArrayList<FilteredSearchView.MessageHashId> toRemove = null;
Iterator<FilteredSearchView.MessageHashId> iterator = selectedFiles.keySet().iterator();
while (iterator.hasNext()) {
FilteredSearchView.MessageHashId hashId = iterator.next();
ArrayList<FilteredSearchView.MessageHashId> arrayList = new ArrayList<>(selectedFiles.keySet());
for (int k = 0; k < arrayList.size(); k++) {
FilteredSearchView.MessageHashId hashId = arrayList.get(k);
MessageObject messageObject = selectedFiles.get(hashId);
long dialogId = messageObject.getDialogId();
int currentChannelId = dialogId < 0 && ChatObject.isChannel((int) -dialogId, currentAccount) ? (int) -dialogId : 0;
if (currentChannelId == channelId) {
for (int i = 0; i < markAsDeletedMessages.size(); i++) {
if (messageObject.getId() == markAsDeletedMessages.get(i)) {
toRemove = new ArrayList<>();
toRemove.add(hashId);
if (messageObject != null) {
long dialogId = messageObject.getDialogId();
int currentChannelId = dialogId < 0 && ChatObject.isChannel((int) -dialogId, currentAccount) ? (int) -dialogId : 0;
if (currentChannelId == channelId) {
for (int i = 0; i < markAsDeletedMessages.size(); i++) {
if (messageObject.getId() == markAsDeletedMessages.get(i)) {
toRemove = new ArrayList<>();
toRemove.add(hashId);
}
}
}
}
if (toRemove != null) {
for (int a = 0, N = toRemove.size(); a < N; a++) {
selectedFiles.remove(toRemove.get(a));
}
selectedMessagesCountTextView.setNumber(selectedFiles.size(), true);
if (gotoItem != null) {
gotoItem.setVisibility(selectedFiles.size() == 1 ? View.VISIBLE : View.GONE);
}
}
if (toRemove != null) {
for (int a = 0, N = toRemove.size(); a < N; a++) {
selectedFiles.remove(toRemove.get(a));
}
selectedMessagesCountTextView.setNumber(selectedFiles.size(), true);
if (gotoItem != null) {
gotoItem.setVisibility(selectedFiles.size() == 1 ? View.VISIBLE : View.GONE);
}
}
}
@ -726,6 +731,15 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie
setPosition(2);
}
public int getPositionForType(int initialSearchType) {
for (int i = 0; i < viewPagerAdapter.items.size(); i++) {
if (viewPagerAdapter.items.get(i).type == ViewPagerAdapter.FILTER_TYPE && viewPagerAdapter.items.get(i).filterIndex == initialSearchType) {
return i;
}
}
return -1;
}
private class ViewPagerAdapter extends ViewPagerFixed.Adapter {
ArrayList<Item> items = new ArrayList<>();

View File

@ -320,12 +320,16 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi
clearSearchImageView = new ImageView(context);
clearSearchImageView.setScaleType(ImageView.ScaleType.CENTER);
clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2());
clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2() {
@Override
protected int getCurrentColor() {
return getThemedColor(darkTheme ? Theme.key_voipgroup_searchPlaceholder : Theme.key_dialogSearchIcon);
}
});
progressDrawable.setSide(AndroidUtilities.dp(7));
clearSearchImageView.setScaleX(0.1f);
clearSearchImageView.setScaleY(0.1f);
clearSearchImageView.setAlpha(0.0f);
clearSearchImageView.setColorFilter(new PorterDuffColorFilter(getThemedColor(darkTheme ? Theme.key_voipgroup_searchPlaceholder : Theme.key_dialogSearchIcon), PorterDuff.Mode.MULTIPLY));
addView(clearSearchImageView, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP, 14, 11, 14, 0));
clearSearchImageView.setOnClickListener(v -> {
updateSearchAdapter = true;

View File

@ -464,7 +464,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
private ArrayList<SharedPhotoVideoCell> cache = new ArrayList<>(10);
private ArrayList<SharedAudioCell> audioCellCache = new ArrayList<>(10);
private ArrayList<SharedAudioCell> audioCache = new ArrayList<>(10);
public ScrollSlidingTextTabStrip scrollSlidingTextTabStrip;
private ScrollSlidingTextTabStripInner scrollSlidingTextTabStrip;
private View shadowLine;
private ChatActionCell floatingDateView;
private AnimatorSet floatingDateAnimation;
@ -2624,6 +2624,12 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
@Override
protected void dispatchDraw(Canvas canvas) {
if (scrollSlidingTextTabStrip != null) {
canvas.save();
canvas.translate(scrollSlidingTextTabStrip.getX(), scrollSlidingTextTabStrip.getY());
scrollSlidingTextTabStrip.drawBackground(canvas);
canvas.restore();
}
super.dispatchDraw(canvas);
if (fragmentContextView != null && fragmentContextView.isCallStyle()) {
canvas.save();
@ -2635,31 +2641,8 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
}
}
private ScrollSlidingTextTabStrip createScrollingTextTabStrip(Context context) {
ScrollSlidingTextTabStrip scrollSlidingTextTabStrip = new ScrollSlidingTextTabStrip(context) {
protected Paint backgroundPaint;
public int backgroundColor = Color.TRANSPARENT;
@Override
protected void dispatchDraw(Canvas canvas) {
if (SharedConfig.chatBlurEnabled() && backgroundColor != Color.TRANSPARENT) {
if (backgroundPaint == null) {
backgroundPaint = new Paint();
}
backgroundPaint.setColor(backgroundColor);
AndroidUtilities.rectTmp2.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
drawBackgroundWithBlur(canvas, getY(), AndroidUtilities.rectTmp2, backgroundPaint);
}
super.dispatchDraw(canvas);
}
@Override
public void setBackgroundColor(int color) {
backgroundColor = color;
invalidate();
}
};
private ScrollSlidingTextTabStripInner createScrollingTextTabStrip(Context context) {
ScrollSlidingTextTabStripInner scrollSlidingTextTabStrip = new ScrollSlidingTextTabStripInner(context);
if (initialTab != -1) {
scrollSlidingTextTabStrip.setInitialTabId(initialTab);
initialTab = -1;
@ -6592,6 +6575,34 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
return newColumnsCount;
}
private class ScrollSlidingTextTabStripInner extends ScrollSlidingTextTabStrip {
protected Paint backgroundPaint;
public int backgroundColor = Color.TRANSPARENT;
public ScrollSlidingTextTabStripInner(Context context) {
super(context);
}
protected void drawBackground(Canvas canvas) {
if (SharedConfig.chatBlurEnabled() && backgroundColor != Color.TRANSPARENT) {
if (backgroundPaint == null) {
backgroundPaint = new Paint();
}
backgroundPaint.setColor(backgroundColor);
AndroidUtilities.rectTmp2.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
drawBackgroundWithBlur(canvas, getY(), AndroidUtilities.rectTmp2, backgroundPaint);
}
}
@Override
public void setBackgroundColor(int color) {
backgroundColor = color;
invalidate();
}
}
public interface Delegate {
void scrollToSharedMedia();

View File

@ -83,6 +83,8 @@ public class SizeNotifierFrameLayout extends FrameLayout {
public Paint blurPaintTop2 = new Paint();
public Paint blurPaintBottom = new Paint();
public Paint blurPaintBottom2 = new Paint();
private Paint selectedBlurPaint;
private Paint selectedBlurPaint2;
float saturation;
public float blurCrossfadeProgress;
@ -682,60 +684,92 @@ public class SizeNotifierFrameLayout extends FrameLayout {
blurIsRunning = false;
}
public void drawBlur(Canvas canvas, float y, Rect rectTmp, Paint blurScrimPaint, boolean top) {
public void drawBlurRect(Canvas canvas, float y, Rect rectTmp, Paint blurScrimPaint, boolean top) {
int blurAlpha = Color.alpha(Theme.getColor(Theme.key_chat_BlurAlpha));
if (currentBitmap == null || !SharedConfig.chatBlurEnabled()) {
canvas.drawRect(rectTmp, blurScrimPaint);
return;
}
Paint blurPaint = top ? blurPaintTop : blurPaintBottom;
Paint blurPaint2 = top ? blurPaintTop2 : blurPaintBottom2;
if (blurPaint.getShader() != null) {
matrix.reset();
matrix2.reset();
if (!top) {
float y1 = -y + currentBitmap.bottomOffset - currentBitmap.pixelFixOffset - TOP_CLIP_OFFSET - (currentBitmap.drawnLisetTranslationY - (getBottomOffset() + getListTranslationY()));
matrix.setTranslate(0, y1);
matrix.preScale(currentBitmap.bottomScaleX, currentBitmap.bottomScaleY);
if (prevBitmap != null) {
y1 = -y + prevBitmap.bottomOffset - prevBitmap.pixelFixOffset - TOP_CLIP_OFFSET - (prevBitmap.drawnLisetTranslationY - (getBottomOffset() + getListTranslationY()));
matrix2.setTranslate(0, y1);
matrix2.preScale(prevBitmap.bottomScaleX, prevBitmap.bottomScaleY);
}
} else {
matrix.setTranslate(0, -y - currentBitmap.pixelFixOffset - TOP_CLIP_OFFSET);
matrix.preScale(currentBitmap.topScaleX, currentBitmap.topScaleY);
if (prevBitmap != null) {
matrix2.setTranslate(0, -y - prevBitmap.pixelFixOffset - TOP_CLIP_OFFSET);
matrix2.preScale(prevBitmap.topScaleX, prevBitmap.topScaleY);
}
}
blurPaint.getShader().setLocalMatrix(matrix);
if (blurPaint2.getShader() != null) {
blurPaint2.getShader().setLocalMatrix(matrix);
}
}
updateBlurShaderPosition(y, top);
blurScrimPaint.setAlpha(255);
if (blurCrossfadeProgress != 1f && blurPaint2.getShader() != null) {
if (blurCrossfadeProgress != 1f && selectedBlurPaint2.getShader() != null) {
canvas.drawRect(rectTmp, blurScrimPaint);
canvas.drawRect(rectTmp, blurPaint2);
canvas.drawRect(rectTmp, selectedBlurPaint2);
canvas.saveLayerAlpha(rectTmp.left, rectTmp.top, rectTmp.right, rectTmp.bottom, (int) (blurCrossfadeProgress * 255), Canvas.ALL_SAVE_FLAG);
canvas.drawRect(rectTmp, blurScrimPaint);
canvas.drawRect(rectTmp, blurPaint);
canvas.drawRect(rectTmp, selectedBlurPaint);
canvas.restore();
} else {
canvas.drawRect(rectTmp, blurScrimPaint);
canvas.drawRect(rectTmp, blurPaint);
canvas.drawRect(rectTmp, selectedBlurPaint);
}
blurScrimPaint.setAlpha(blurAlpha);
canvas.drawRect(rectTmp, blurScrimPaint);
}
public void drawBlurCircle(Canvas canvas, float viewY, float cx, float cy, float radius, Paint blurScrimPaint, boolean top) {
int blurAlpha = Color.alpha(Theme.getColor(Theme.key_chat_BlurAlpha));
if (currentBitmap == null || !SharedConfig.chatBlurEnabled()) {
canvas.drawCircle(cx, cy, radius, blurScrimPaint);
return;
}
updateBlurShaderPosition(viewY, top);
blurScrimPaint.setAlpha(255);
if (blurCrossfadeProgress != 1f && selectedBlurPaint2.getShader() != null) {
canvas.drawCircle(cx, cy, radius, blurScrimPaint);
canvas.drawCircle(cx, cy, radius, selectedBlurPaint2);
canvas.saveLayerAlpha(cx - radius, cy - radius, cx + radius, cy + radius, (int) (blurCrossfadeProgress * 255), Canvas.ALL_SAVE_FLAG);
canvas.drawCircle(cx, cy, radius, blurScrimPaint);
canvas.drawCircle(cx, cy, radius, selectedBlurPaint);
canvas.restore();
} else {
canvas.drawCircle(cx, cy, radius, blurScrimPaint);
canvas.drawCircle(cx, cy, radius, selectedBlurPaint);
}
blurScrimPaint.setAlpha(blurAlpha);
canvas.drawCircle(cx, cy, radius, blurScrimPaint);
}
private void updateBlurShaderPosition(float viewY, boolean top) {
selectedBlurPaint = top ? blurPaintTop : blurPaintBottom;
selectedBlurPaint2 = top ? blurPaintTop2 : blurPaintBottom2;
if (top) {
viewY += getTranslationY();
}
if (selectedBlurPaint.getShader() != null) {
matrix.reset();
matrix2.reset();
if (!top) {
float y1 = -viewY + currentBitmap.bottomOffset - currentBitmap.pixelFixOffset - TOP_CLIP_OFFSET - (currentBitmap.drawnLisetTranslationY - (getBottomOffset() + getListTranslationY()));
matrix.setTranslate(0, y1);
matrix.preScale(currentBitmap.bottomScaleX, currentBitmap.bottomScaleY);
if (prevBitmap != null) {
y1 = -viewY + prevBitmap.bottomOffset - prevBitmap.pixelFixOffset - TOP_CLIP_OFFSET - (prevBitmap.drawnLisetTranslationY - (getBottomOffset() + getListTranslationY()));
matrix2.setTranslate(0, y1);
matrix2.preScale(prevBitmap.bottomScaleX, prevBitmap.bottomScaleY);
}
} else {
matrix.setTranslate(0, -viewY - currentBitmap.pixelFixOffset - TOP_CLIP_OFFSET);
matrix.preScale(currentBitmap.topScaleX, currentBitmap.topScaleY);
if (prevBitmap != null) {
matrix2.setTranslate(0, -viewY - prevBitmap.pixelFixOffset - TOP_CLIP_OFFSET);
matrix2.preScale(prevBitmap.topScaleX, prevBitmap.topScaleY);
}
}
selectedBlurPaint.getShader().setLocalMatrix(matrix);
if (selectedBlurPaint2.getShader() != null) {
selectedBlurPaint2.getShader().setLocalMatrix(matrix);
}
}
}
protected float getBottomTranslation() {
return 0;
}

View File

@ -228,7 +228,7 @@ public class StickerEmptyView extends FrameLayout implements NotificationCenter.
if (set == null) {
set = MediaDataController.getInstance(currentAccount).getStickerSetByEmojiOrName(AndroidUtilities.STICKERS_PLACEHOLDER_PACK_NAME);
}
if (set != null && set.documents.size() >= 2) {
if (set != null && stickerType >= 0 && stickerType < set.documents.size() ) {
document = set.documents.get(stickerType);
}
imageFilter = "130_130";

View File

@ -31,15 +31,17 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearSmoothScroller;
import androidx.recyclerview.widget.RecyclerView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.DocumentObject;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.FileLoader;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaDataController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.SvgHelper;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLObject;
@ -55,10 +57,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearSmoothScroller;
import androidx.recyclerview.widget.RecyclerView;
@SuppressWarnings("unchecked")
public class StickerMasksAlert extends BottomSheet implements NotificationCenter.NotificationCenterDelegate {
@ -180,12 +178,16 @@ public class StickerMasksAlert extends BottomSheet implements NotificationCenter
clearSearchImageView = new ImageView(context);
clearSearchImageView.setScaleType(ImageView.ScaleType.CENTER);
clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2());
clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2() {
@Override
public int getCurrentColor() {
return 0xff777777;
}
});
progressDrawable.setSide(AndroidUtilities.dp(7));
clearSearchImageView.setScaleX(0.1f);
clearSearchImageView.setScaleY(0.1f);
clearSearchImageView.setAlpha(0.0f);
clearSearchImageView.setColorFilter(new PorterDuffColorFilter(0xff777777, PorterDuff.Mode.MULTIPLY));
addView(clearSearchImageView, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP, 14, 14, 14, 0));
clearSearchImageView.setOnClickListener(v -> {
searchEditText.setText("");

View File

@ -28,12 +28,15 @@ import android.graphics.drawable.RippleDrawable;
import android.os.Build;
import androidx.annotation.Keep;
import android.util.StateSet;
import android.view.HapticFeedbackConstants;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.ui.ActionBar.Theme;
import java.lang.reflect.Method;
public class Switch extends View {
private RectF rectF;
@ -219,7 +222,7 @@ public class Switch extends View {
private void animateToCheckedState(boolean newCheckedState) {
checkAnimator = ObjectAnimator.ofFloat(this, "progress", newCheckedState ? 1 : 0);
checkAnimator.setDuration(250);
checkAnimator.setDuration(semHaptics ? 150 : 250);
checkAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@ -231,7 +234,7 @@ public class Switch extends View {
private void animateIcon(boolean newCheckedState) {
iconAnimator = ObjectAnimator.ofFloat(this, "iconProgress", newCheckedState ? 1 : 0);
iconAnimator.setDuration(250);
iconAnimator.setDuration(semHaptics ? 150 : 250);
iconAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@ -265,6 +268,7 @@ public class Switch extends View {
if (checked != isChecked) {
isChecked = checked;
if (attachedToWindow && animated) {
vibrateChecked();
animateToCheckedState(checked);
} else {
cancelCheckAnimator();
@ -525,4 +529,26 @@ public class Switch extends View {
info.setChecked(isChecked);
//info.setContentDescription(isChecked ? LocaleController.getString("NotificationsOn", R.string.NotificationsOn) : LocaleController.getString("NotificationsOff", R.string.NotificationsOff));
}
private boolean semHaptics = false;
private void vibrateChecked() {
try {
Integer hapticIndex = null;
Method method = null;
if (Build.VERSION.SDK_INT >= 29) {
method = HapticFeedbackConstants.class.getDeclaredMethod("hidden_semGetVibrationIndex", Integer.TYPE);
} else if (Build.VERSION.SDK_INT >= 28) {
method = HapticFeedbackConstants.class.getMethod("semGetVibrationIndex", Integer.TYPE);
}
if (method != null) {
method.setAccessible(true);
hapticIndex = (Integer) method.invoke(null, 27);
}
if (hapticIndex != null) {
performHapticFeedback(hapticIndex);
semHaptics = true;
}
} catch (Exception ignore) {}
}
}

View File

@ -178,12 +178,16 @@ public class ThemeEditorView {
clearSearchImageView = new ImageView(context);
clearSearchImageView.setScaleType(ImageView.ScaleType.CENTER);
CloseProgressDrawable2 progressDrawable;
clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2());
clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2() {
@Override
public int getCurrentColor() {
return 0xffa1a8af;
}
});
progressDrawable.setSide(AndroidUtilities.dp(7));
clearSearchImageView.setScaleX(0.1f);
clearSearchImageView.setScaleY(0.1f);
clearSearchImageView.setAlpha(0.0f);
clearSearchImageView.setColorFilter(new PorterDuffColorFilter(0xffa1a8af, PorterDuff.Mode.MULTIPLY));
addView(clearSearchImageView, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP, 14, 11, 14, 0));
clearSearchImageView.setOnClickListener(v -> {
searchEditText.setText("");

View File

@ -227,12 +227,16 @@ public class UsersAlertBase extends BottomSheet {
clearSearchImageView = new ImageView(context);
clearSearchImageView.setScaleType(ImageView.ScaleType.CENTER);
clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2());
clearSearchImageView.setImageDrawable(progressDrawable = new CloseProgressDrawable2() {
@Override
protected int getCurrentColor() {
return Theme.getColor(keySearchPlaceholder);
}
});
progressDrawable.setSide(AndroidUtilities.dp(7));
clearSearchImageView.setScaleX(0.1f);
clearSearchImageView.setScaleY(0.1f);
clearSearchImageView.setAlpha(0.0f);
clearSearchImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(keySearchPlaceholder), PorterDuff.Mode.MULTIPLY));
addView(clearSearchImageView, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP, 14, 11, 14, 0));
clearSearchImageView.setOnClickListener(v -> {
searchEditText.setText("");

View File

@ -27,8 +27,10 @@ public class CellFlickerDrawable {
Matrix matrix = new Matrix();
public boolean repeatEnabled = true;
public boolean drawFrame = true;
public float repeatProgress = 1.2f;
public float animationSpeedScale = 1f;
public CellFlickerDrawable() {
this(64, 204);
@ -43,12 +45,23 @@ public class CellFlickerDrawable {
paintOutline.setStrokeWidth(AndroidUtilities.dp(2));
}
public float getProgress() {
return progress;
}
public void setProgress(float progress) {
this.progress = progress;
}
public void draw(Canvas canvas, RectF rectF, float rad) {
if (progress > 1f && !repeatEnabled) {
return;
}
long currentTime = System.currentTimeMillis();
if (lastUpdateTime != 0) {
long dt = currentTime - lastUpdateTime;
if (dt > 10) {
progress += dt / 1200f;
progress += (dt / 1200f) * animationSpeedScale;
if (progress > repeatProgress) {
progress = 0;
}

View File

@ -74,6 +74,8 @@ public class GroupCallRenderersContainer extends FrameLayout {
ValueAnimator fullscreenAnimator;
public boolean inLayout;
public ImageView pipView;
private LongSparseIntArray attachedPeerIds = new LongSparseIntArray();
int animationIndex;
@ -111,7 +113,6 @@ public class GroupCallRenderersContainer extends FrameLayout {
TextView pinTextView;
TextView unpinTextView;
View pinContainer;
ImageView pipView;
boolean hideUiRunnableIsScheduled;
Runnable hideUiRunnable = new Runnable() {

View File

@ -147,7 +147,8 @@ public class VoIPHelper {
if (Build.VERSION.SDK_INT >= 23) {
ArrayList<String> permissions = new ArrayList<>();
if (activity.checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
ChatObject.Call call = accountInstance.getMessagesController().getGroupCall(chat.id, false);
if (activity.checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED && !(call != null && call.call.rtmp_stream)) {
permissions.add(Manifest.permission.RECORD_AUDIO);
}
if (permissions.isEmpty()) {

View File

@ -243,7 +243,6 @@ public class ChatActivityMemberRequestsDelegate {
}
public interface Callback {
void onEnterOffsetChanged();
}
}

View File

@ -74,6 +74,7 @@ import android.widget.ScrollView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
@ -97,7 +98,6 @@ import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaDataController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.MessagesStorage;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.NotificationsController;
import org.telegram.messenger.R;
@ -612,7 +612,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
}
}
AndroidUtilities.rectTmp2.set(0, top, getMeasuredWidth(), top + actionBarHeight);
drawBlur(canvas, 0, AndroidUtilities.rectTmp2, searchAnimationProgress == 1f ? actionBarSearchPaint : actionBarDefaultPaint, true);
drawBlurRect(canvas, 0, AndroidUtilities.rectTmp2, searchAnimationProgress == 1f ? actionBarSearchPaint : actionBarDefaultPaint, true);
if (searchAnimationProgress > 0 && searchAnimationProgress < 1f) {
actionBarSearchPaint.setColor(ColorUtils.blendARGB(Theme.getColor(folderId == 0 ? Theme.key_actionBarDefault : Theme.key_actionBarDefaultArchived), Theme.getColor(Theme.key_windowBackgroundWhite), searchAnimationProgress));
if (searchIsShowed || !searchWasFullyShowed) {
@ -621,12 +621,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
float cX = getMeasuredWidth() - AndroidUtilities.dp(24);
int statusBarH = actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0;
float cY = statusBarH + (actionBar.getMeasuredHeight() - statusBarH) / 2f;
canvas.drawCircle(cX, cY, getMeasuredWidth() * 1.3f * searchAnimationProgress, actionBarSearchPaint);
drawBlurCircle(canvas, 0, cX, cY, getMeasuredWidth() * 1.3f * searchAnimationProgress, actionBarSearchPaint, true);
canvas.restore();
} else {
// canvas.drawRect(0, top, getMeasuredWidth(), top + actionBarHeight, actionBarSearchPaint);
AndroidUtilities.rectTmp2.set(0, top, getMeasuredWidth(), top + actionBarHeight);
drawBlur(canvas, 0, AndroidUtilities.rectTmp2, actionBarSearchPaint, true);
drawBlurRect(canvas, 0, AndroidUtilities.rectTmp2, actionBarSearchPaint, true);
}
if (filterTabsView != null && filterTabsView.getVisibility() == View.VISIBLE) {
filterTabsView.setTranslationY(actionBarHeight - (actionBar.getHeight() + filterTabsView.getMeasuredHeight()));
@ -651,13 +650,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
} else if (!inPreviewMode) {
if (progressToActionMode > 0) {
actionBarSearchPaint.setColor(ColorUtils.blendARGB(Theme.getColor(folderId == 0 ? Theme.key_actionBarDefault : Theme.key_actionBarDefaultArchived), Theme.getColor(Theme.key_windowBackgroundWhite), progressToActionMode));
// canvas.drawRect(0, top, getMeasuredWidth(), top + actionBarHeight, actionBarSearchPaint);
AndroidUtilities.rectTmp2.set(0, top, getMeasuredWidth(), top + actionBarHeight);
drawBlur(canvas, 0, AndroidUtilities.rectTmp2, actionBarSearchPaint, true);
drawBlurRect(canvas, 0, AndroidUtilities.rectTmp2, actionBarSearchPaint, true);
} else {
AndroidUtilities.rectTmp2.set(0, top, getMeasuredWidth(), top + actionBarHeight);
drawBlur(canvas, 0, AndroidUtilities.rectTmp2, actionBarDefaultPaint, true);
// canvas.drawRect(, actionBarDefaultPaint);
drawBlurRect(canvas, 0, AndroidUtilities.rectTmp2, actionBarDefaultPaint, true);
}
}
tabsYOffset = 0;
@ -1919,7 +1916,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
accountInstance.getMediaDataController().loadRecents(MediaDataController.TYPE_GREETINGS, false, true, false);
accountInstance.getMediaDataController().checkFeaturedStickers();
accountInstance.getMediaDataController().checkReactions();
AndroidUtilities.runOnUIThread(() -> accountInstance.getMessagesStorage().loadDownloadingFiles(), 200);
AndroidUtilities.runOnUIThread(() -> accountInstance.getDownloadController().loadDownloadingFiles(), 200);
for (String emoji : messagesController.diceEmojies) {
accountInstance.getMediaDataController().loadStickersByEmojiOrName(emoji, true, true);
}
@ -2081,6 +2078,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
updateProxyButton(false, false);
actionBar.setBackButtonContentDescription(LocaleController.getString("AccDescrGoBack", R.string.AccDescrGoBack));
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needCheckSystemBarColors);
((SizeNotifierFrameLayout) fragmentView).invalidateBlur();
}
@Override
@ -2123,6 +2121,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
actionBar.setBackButtonContentDescription(LocaleController.getString("AccDescrOpenMenu", R.string.AccDescrOpenMenu));
}
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needCheckSystemBarColors);
((SizeNotifierFrameLayout) fragmentView).invalidateBlur();
}
@Override
@ -3267,7 +3266,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
combinedDrawable.setIconSize(AndroidUtilities.dp(56), AndroidUtilities.dp(56));
drawable = combinedDrawable;
}
floatingButtonContainer.setBackground(drawable);
updateFloatingButtonColor();
floatingButtonContainer.addView(floatingButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
floatingProgressView = new RadialProgressView(context);
@ -4757,7 +4756,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
}
}
if (initialSearchType >= 0) {
searchViewPager.setPosition(initialSearchType);
searchViewPager.setPosition(searchViewPager.getPositionForType(initialSearchType));
}
if (!show) {
initialSearchType = -1;
@ -5058,6 +5057,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
return;
}
if (!selectedDialogs.isEmpty() || (initialDialogsType == 3 && selectAlertString != null)) {
if (!selectedDialogs.contains(dialogId) && !checkCanWrite(dialogId)) {
return;
}
boolean checked = addOrRemoveSelectedDialog(dialogId, view);
if (adapter == searchViewPager.dialogsSearchAdapter) {
actionBar.closeSearchField();
@ -6366,13 +6368,13 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
return;
}
boolean showDownloads = false;
for (int i = 0; i < getMessagesStorage().downloadingFiles.size(); i++){
if (getFileLoader().isLoadingFile(getMessagesStorage().downloadingFiles.get(i).getFileName())) {
for (int i = 0; i < getDownloadController().downloadingFiles.size(); i++){
if (getFileLoader().isLoadingFile(getDownloadController().downloadingFiles.get(i).getFileName())) {
showDownloads = true;
break;
}
}
if (!searching && (MessagesStorage.getInstance(currentAccount).hasUnviewedDownloads() || showDownloads || (downloadsItem.getVisibility() == View.VISIBLE && downloadsItem.getAlpha() == 1 && !force))) {
if (!searching && (getDownloadController().hasUnviewedDownloads() || showDownloads || (downloadsItem.getVisibility() == View.VISIBLE && downloadsItem.getAlpha() == 1 && !force))) {
downloadsItemVisible = true;
downloadsItem.setVisibility(View.VISIBLE);
} else {
@ -7336,7 +7338,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
this.initialSearchType = type;
}
private void didSelectResult(final long dialogId, boolean useAlert, final boolean param) {
private boolean checkCanWrite(final long dialogId) {
if (addToGroupAlertString == null && checkCanWrite) {
if (DialogObject.isChatDialog(dialogId)) {
TLRPC.Chat chat = getMessagesController().getChat(-dialogId);
@ -7350,7 +7352,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
}
builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), null);
showDialog(builder.create());
return;
return false;
}
} else if (DialogObject.isEncryptedDialog(dialogId) && (hasPoll != 0 || hasInvoice)) {
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
@ -7362,9 +7364,16 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
}
builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), null);
showDialog(builder.create());
return;
return false;
}
}
return true;
}
private void didSelectResult(final long dialogId, boolean useAlert, final boolean param) {
if (!checkCanWrite(dialogId)) {
return;
}
if (initialDialogsType == 11 || initialDialogsType == 12 || initialDialogsType == 13) {
if (checkingImportDialog) {
return;
@ -7670,6 +7679,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
}
searchItem.updateColor();
}
updateFloatingButtonColor();
setSearchAnimationProgress(searchAnimationProgress);
};
@ -8075,6 +8085,21 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
return arrayList;
}
private void updateFloatingButtonColor() {
if (getParentActivity() == null || floatingButtonContainer == null) {
return;
}
Drawable drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), Theme.getColor(Theme.key_chats_actionBackground), Theme.getColor(Theme.key_chats_actionPressedBackground));
if (Build.VERSION.SDK_INT < 21) {
Drawable shadowDrawable = ContextCompat.getDrawable(getParentActivity(), R.drawable.floating_shadow).mutate();
shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY));
CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0);
combinedDrawable.setIconSize(AndroidUtilities.dp(56), AndroidUtilities.dp(56));
drawable = combinedDrawable;
}
floatingButtonContainer.setBackground(drawable);
}
float slideFragmentProgress = 1f;
boolean isSlideBackTransition;
boolean isDrawerTransition;
@ -8218,8 +8243,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
if (!searchItem.getSearchField().getText().toString().equals(query)) {
searchItem.getSearchField().setText(query);
}
if (searchViewPager.getTabsView().getCurrentTabId() != i) {
searchViewPager.getTabsView().scrollToTab(i, i);
int p = searchViewPager.getPositionForType(i);
if (p >= 0) {
if (searchViewPager.getTabsView().getCurrentTabId() != p) {
searchViewPager.getTabsView().scrollToTab(p, p);
}
}
}
}

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