update to 9.7.2 (3705)

This commit is contained in:
xaxtix 2023-07-22 05:33:39 +04:00
parent 65f01a70e7
commit f10844350d
106 changed files with 2383 additions and 871 deletions

View file

@ -1,6 +1,9 @@
package org.telegram;
import org.telegram.messenger.FileLog;
import java.util.Comparator;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@ -21,8 +24,21 @@ public class DispatchQueuePriority {
}
return priority2 - priority1;
}
}));
})) {
@Override
protected void beforeExecute(Thread t, Runnable r) {
CountDownLatch latch = pauseLatch;
if (latch != null) {
try {
latch.await();
} catch (InterruptedException e) {
FileLog.e(e);
}
}
}
};
private volatile CountDownLatch pauseLatch;
public DispatchQueuePriority(String threadName) {
@ -41,15 +57,11 @@ public class DispatchQueuePriority {
}
public Runnable postRunnable(Runnable runnable, int priority) {
if (priority == 1) {
postRunnable(runnable);
return runnable;
} else {
PriorityRunnable priorityRunnable = new PriorityRunnable(priority, runnable);
threadPoolExecutor.execute(priorityRunnable);
return priorityRunnable;
if (priority != 1) {
runnable = new PriorityRunnable(priority, runnable);
}
postRunnable(runnable);
return runnable;
}
public void cancelRunnable(Runnable runnable) {
@ -57,7 +69,20 @@ public class DispatchQueuePriority {
return;
}
threadPoolExecutor.remove(runnable);
}
public void pause() {
if (pauseLatch == null) {
pauseLatch = new CountDownLatch(1);
}
}
public void resume() {
CountDownLatch latch = pauseLatch;
if (latch != null) {
latch.countDown();
pauseLatch = null;
}
}
private static class PriorityRunnable implements Runnable {

View file

@ -99,7 +99,6 @@ import android.view.inputmethod.InputMethodSubtype;
import android.view.inspector.WindowInspector;
import android.webkit.MimeTypeMap;
import android.widget.EdgeEffect;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
@ -123,7 +122,6 @@ import androidx.viewpager.widget.ViewPager;
import com.android.internal.telephony.ITelephony;
import com.google.android.exoplayer2.util.Consumer;
import com.google.android.exoplayer2.util.Log;
import com.google.android.gms.auth.api.phone.SmsRetriever;
import com.google.android.gms.auth.api.phone.SmsRetrieverClient;
import com.google.android.gms.tasks.Task;
@ -155,7 +153,6 @@ import org.telegram.ui.Components.MotionBackgroundDrawable;
import org.telegram.ui.Components.PickerBottomLayout;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.ShareAlert;
import org.telegram.ui.Components.SizeNotifierFrameLayout;
import org.telegram.ui.Components.TypefaceSpan;
import org.telegram.ui.Components.URLSpanReplacement;
import org.telegram.ui.Components.UndoView;
@ -177,7 +174,6 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.IDN;
@ -196,7 +192,6 @@ import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
@ -590,7 +585,7 @@ public class AndroidUtilities {
}
public static void removeFromParent(View child) {
if (child.getParent() != null) {
if (child != null && child.getParent() != null) {
((ViewGroup) child.getParent()).removeView(child);
}
}
@ -2750,6 +2745,39 @@ public class AndroidUtilities {
return new SpannableStringBuilder(str);
}
private static Pattern linksPattern;
public static SpannableStringBuilder replaceLinks(String str, Theme.ResourcesProvider resourcesProvider) {
if (linksPattern == null) {
linksPattern = Pattern.compile("\\[(.+?)\\]\\((.+?)\\)");
}
SpannableStringBuilder spannable = new SpannableStringBuilder();
Matcher matcher = linksPattern.matcher(str);
int lastMatchEnd = 0;
while (matcher.find()) {
spannable.append(str, lastMatchEnd, matcher.start());
String linkText = matcher.group(1);
String url = matcher.group(2);
spannable.append(linkText);
int start = spannable.length() - linkText.length();
int end = spannable.length();
spannable.setSpan(new ClickableSpan() {
@Override
public void onClick(@NonNull View widget) {
Browser.openUrl(ApplicationLoader.applicationContext, url);
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
ds.setColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider));
ds.setUnderlineText(false);
}
}, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
lastMatchEnd = matcher.end();
}
spannable.append(str, lastMatchEnd, str.length());
return spannable;
}
public static class LinkMovementMethodMy extends LinkMovementMethod {
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
@ -5324,4 +5352,12 @@ public class AndroidUtilities {
} catch (Exception ignore) {}
return "";
}
public static void quietSleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException ignored) {
}
}
}

View file

@ -24,8 +24,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 = 3687;
public static String BUILD_VERSION_STRING = "9.7.0";
public static int BUILD_VERSION = 3705;
public static String BUILD_VERSION_STRING = "9.7.2";
public static int APP_ID = 4;
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";

View file

@ -11,17 +11,21 @@ package org.telegram.messenger;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.SystemClock;
import java.util.concurrent.CountDownLatch;
public class DispatchQueue extends Thread {
private static final int THREAD_PRIORITY_DEFAULT = -1000;
private volatile Handler handler = null;
private CountDownLatch syncLatch = new CountDownLatch(1);
private long lastTaskTime;
private static int indexPointer = 0;
public final int index = indexPointer++;
private int priority = THREAD_PRIORITY_DEFAULT;
public DispatchQueue(final String threadName) {
this(threadName, true);
@ -34,6 +38,14 @@ public class DispatchQueue extends Thread {
}
}
public DispatchQueue(final String threadName, boolean start, int priority) {
this.priority = priority;
setName(threadName);
if (start) {
start();
}
}
public void sendMessage(Message msg, int delay) {
try {
syncLatch.await();
@ -114,6 +126,9 @@ public class DispatchQueue extends Thread {
return true;
});
syncLatch.countDown();
if (priority != THREAD_PRIORITY_DEFAULT) {
Process.setThreadPriority(priority);
}
Looper.loop();
}

View file

@ -5,6 +5,8 @@ import android.util.SparseIntArray;
import androidx.annotation.UiThread;
import org.telegram.ui.Components.Reactions.HwEmojis;
import java.util.LinkedList;
public class DispatchQueuePool {
@ -68,6 +70,11 @@ public class DispatchQueuePool {
busyQueues.add(queue);
int count = busyQueuesMap.get(queue.index, 0);
busyQueuesMap.put(queue.index, count + 1);
if (HwEmojis.isHwEnabled()) {
queue.setPriority(Thread.MIN_PRIORITY);
} else if (queue.getPriority() != Thread.MAX_PRIORITY) {
queue.setPriority(Thread.MAX_PRIORITY);
}
queue.postRunnable(() -> {
runnable.run();
AndroidUtilities.runOnUIThread(() -> {

View file

@ -5,6 +5,8 @@ import android.util.SparseIntArray;
import androidx.annotation.UiThread;
import org.telegram.ui.Components.Reactions.HwEmojis;
import java.util.ArrayList;
public class DispatchQueuePoolBackground {
@ -77,6 +79,11 @@ public class DispatchQueuePoolBackground {
busyQueues.add(queue);
int count = busyQueuesMap.get(queue.index, 0);
busyQueuesMap.put(queue.index, count + 1);
if(HwEmojis.isHwEnabled()) {
queue.setPriority(Thread.MIN_PRIORITY);
} else if (queue.getPriority() != Thread.MAX_PRIORITY) {
queue.setPriority(Thread.MAX_PRIORITY);
}
queue.postRunnable(() -> {
runnable.run();
Utilities.globalQueue.postRunnable(() -> {

View file

@ -638,7 +638,7 @@ public class FileLoadOperation {
final CountDownLatch countDownLatch = new CountDownLatch(1);
final File[] result = new File[1];
Utilities.stageQueue.postRunnable(() -> {
if (state == stateFinished) {
if (state == stateFinished && !preloadFinished) {
result[0] = cacheFileFinal;
} else {
result[0] = cacheFileTemp;
@ -654,7 +654,7 @@ public class FileLoadOperation {
}
protected File getCurrentFileFast() {
if (state == stateFinished) {
if (state == stateFinished && !preloadFinished) {
return cacheFileFinal;
} else {
return cacheFileTemp;

View file

@ -938,7 +938,7 @@ public class FileLoader extends BaseController {
}
loaderQueue.add(operation);
loaderQueue.checkLoadingOperations();
loaderQueue.checkLoadingOperations(operation.isStory && priority >= PRIORITY_HIGH);
if (BuildVars.LOGS_ENABLED) {
FileLog.d("create load operation fileName=" + finalFileName + " documentName=" + getDocumentFileName(document) + "size=" + AndroidUtilities.formatFileSize(operation.totalBytesCount) + " position in queue " + operation.getPositionInQueue() + " account=" + currentAccount);

View file

@ -69,6 +69,15 @@ public class FileLoaderPriorityQueue {
}
public void checkLoadingOperations() {
checkLoadingOperations(false);
}
public void checkLoadingOperations(boolean immediate) {
if (immediate) {
workerQueue.cancelRunnable(checkOperationsRunnable);
checkOperationsRunnable.run();
return;
}
if (checkOperationsScheduled) {
return;
}

View file

@ -21,6 +21,7 @@ import org.telegram.messenger.time.FastDateFormat;
import org.telegram.messenger.video.MediaCodecVideoConvertor;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.Components.AnimatedFileDrawable;
import org.telegram.ui.LaunchActivity;
import java.io.File;
@ -170,7 +171,7 @@ public class FileLog {
excludeRequests.add("TL_upload_getFile");
excludeRequests.add("TL_upload_a");
gson = new GsonBuilder().addSerializationExclusionStrategy(new ExclusionStrategy() {
ExclusionStrategy strategy = new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
@ -182,12 +183,10 @@ public class FileLog {
@Override
public boolean shouldSkipClass(Class<?> clazz) {
if (clazz.isInstance(ColorStateList.class) || clazz.isInstance(Context.class)) {
return true;
}
return false;
return clazz.isInstance(AnimatedFileDrawable.class) || clazz.isInstance(ColorStateList.class) || clazz.isInstance(Context.class);
}
}).registerTypeAdapterFactory(RuntimeClassNameTypeAdapterFactory.of(TLObject.class, "type_")).create();
};
gson = new GsonBuilder().addSerializationExclusionStrategy(strategy).registerTypeAdapterFactory(RuntimeClassNameTypeAdapterFactory.of(TLObject.class, "type_", strategy)).create();
}
}

View file

@ -1059,19 +1059,21 @@ public class FileRefController extends BaseController {
Object arg = requester.args[1];
if (arg instanceof FileLoadOperation) {
FileLoadOperation operation = (FileLoadOperation) requester.args[1];
TLRPC.StoryItem storyItem = (TLRPC.StoryItem) operation.parentObject;
if (newStoryItem == null) {
TLRPC.TL_updateStory story = new TLRPC.TL_updateStory();
story.user_id = storyItem.dialogId;
story.story = new TLRPC.TL_storyItemDeleted();
story.story.id = storyItem.id;
ArrayList<TLRPC.Update> updates = new ArrayList<>();
updates.add(story);
getMessagesController().processUpdateArray(updates, null, null, false, 0);
} else {
TLRPC.User user = getMessagesController().getUser(storyItem.dialogId);
if (user != null && user.contact) {
MessagesController.getInstance(currentAccount).getStoriesController().getStoriesStorage().updateStoryItem(storyItem.dialogId, newStoryItem);
if (operation.parentObject instanceof TLRPC.StoryItem) {
TLRPC.StoryItem storyItem = (TLRPC.StoryItem) operation.parentObject;
if (newStoryItem == null) {
TLRPC.TL_updateStory story = new TLRPC.TL_updateStory();
story.user_id = storyItem.dialogId;
story.story = new TLRPC.TL_storyItemDeleted();
story.story.id = storyItem.id;
ArrayList<TLRPC.Update> updates = new ArrayList<>();
updates.add(story);
getMessagesController().processUpdateArray(updates, null, null, false, 0);
} else {
TLRPC.User user = getMessagesController().getUser(storyItem.dialogId);
if (user != null && user.contact) {
MessagesController.getInstance(currentAccount).getStoriesController().getStoriesStorage().updateStoryItem(storyItem.dialogId, newStoryItem);
}
}
}
}

View file

@ -24,6 +24,7 @@ import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
@ -141,8 +142,16 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO
countDownLatch = null;
}
}
if (file == null) {
currentFile = loadOperation.getCurrentFile();
File currentFileFast = loadOperation.getCurrentFileFast();
if (file == null || !Objects.equals(currentFile, currentFileFast)) {
if (file != null) {
try {
file.close();
} catch (Exception ignore) {
}
}
currentFile = currentFileFast;
if (currentFile != null) {
try {
file = new RandomAccessFile(currentFile, "r");

View file

@ -52,6 +52,7 @@ import org.telegram.ui.Components.BackgroundGradientDrawable;
import org.telegram.ui.Components.MotionBackgroundDrawable;
import org.telegram.ui.Components.Point;
import org.telegram.ui.Components.RLottieDrawable;
import org.telegram.ui.Components.Reactions.HwEmojis;
import org.telegram.ui.Components.SlotsDrawable;
import org.telegram.ui.Components.ThemePreviewDrawable;
@ -171,6 +172,10 @@ public class ImageLoader {
return null;
}
public static boolean isSdCardPath(File videoFile) {
return !TextUtils.isEmpty(SharedConfig.storageCacheDir) && videoFile.getAbsolutePath().startsWith(SharedConfig.storageCacheDir);
}
public void moveToFront(String key) {
if (key == null) {
return;
@ -3291,6 +3296,9 @@ public class ImageLoader {
}
public void loadImageForImageReceiver(ImageReceiver imageReceiver) {
loadImageForImageReceiver(imageReceiver, null);
}
public void loadImageForImageReceiver(ImageReceiver imageReceiver, List<ImageReceiver> preloadReceiver) {
if (imageReceiver == null) {
return;
}
@ -3300,24 +3308,26 @@ public class ImageLoader {
int guid = imageReceiver.getNewGuid();
if (mediaKey != null) {
ImageLocation mediaLocation = imageReceiver.getMediaLocation();
Drawable drawable;
if (useLottieMemCache(mediaLocation, mediaKey)) {
drawable = getFromLottieCache(mediaKey);
} else {
drawable = memCache.get(mediaKey);
if (drawable != null) {
memCache.moveToFront(mediaKey);
}
if (drawable == null) {
drawable = smallImagesMemCache.get(mediaKey);
Drawable drawable = findInPreloadImageReceivers(mediaKey, preloadReceiver);
if (drawable == null) {
if (useLottieMemCache(mediaLocation, mediaKey)) {
drawable = getFromLottieCache(mediaKey);
} else {
drawable = memCache.get(mediaKey);
if (drawable != null) {
smallImagesMemCache.moveToFront(mediaKey);
memCache.moveToFront(mediaKey);
}
}
if (drawable == null) {
drawable = wallpaperMemCache.get(mediaKey);
if (drawable != null) {
wallpaperMemCache.moveToFront(mediaKey);
if (drawable == null) {
drawable = smallImagesMemCache.get(mediaKey);
if (drawable != null) {
smallImagesMemCache.moveToFront(mediaKey);
}
}
if (drawable == null) {
drawable = wallpaperMemCache.get(mediaKey);
if (drawable != null) {
wallpaperMemCache.moveToFront(mediaKey);
}
}
}
}
@ -3342,8 +3352,8 @@ public class ImageLoader {
String imageKey = imageReceiver.getImageKey();
if (!imageSet && imageKey != null) {
ImageLocation imageLocation = imageReceiver.getImageLocation();
Drawable drawable = null;
if (useLottieMemCache(imageLocation, imageKey)) {
Drawable drawable = findInPreloadImageReceivers(imageKey, preloadReceiver);
if (drawable == null && useLottieMemCache(imageLocation, imageKey)) {
drawable = getFromLottieCache(imageKey);
}
if (drawable == null) {
@ -3599,6 +3609,22 @@ public class ImageLoader {
}
}
private Drawable findInPreloadImageReceivers(String imageKey, List<ImageReceiver> receivers) {
if (receivers == null) {
return null;
}
for (int i = 0; i < receivers.size(); i++) {
ImageReceiver receiver = receivers.get(i);
if (imageKey.equals(receiver.getImageKey())) {
return receiver.getImageDrawable();
}
if (imageKey.equals(receiver.getMediaKey())) {
return receiver.getMediaDrawable();
}
}
return null;
}
private BitmapDrawable getFromLottieCache(String imageKey) {
BitmapDrawable drawable = lottieMemCache.get(imageKey);
if (drawable instanceof AnimatedFileDrawable) {

View file

@ -43,9 +43,12 @@ import org.telegram.ui.Components.RecyclableDrawable;
import org.telegram.ui.Components.VectorAvatarThumbDrawable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ImageReceiver implements NotificationCenter.NotificationCenterDelegate {
List<ImageReceiver> preloadReceivers;
public boolean updateThumbShaderMatrix() {
if (currentThumbDrawable != null && thumbShader != null) {
drawDrawable(null, currentThumbDrawable, 255, thumbShader, 0, 0, 0, null);
@ -58,6 +61,18 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
return false;
}
public void setPreloadingReceivers(List<ImageReceiver> preloadReceivers) {
this.preloadReceivers = preloadReceivers;
}
public Drawable getImageDrawable() {
return currentImageDrawable;
}
public Drawable getMediaDrawable() {
return currentMediaDrawable;
}
public interface ImageReceiverDelegate {
void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb, boolean memCache);
@ -706,7 +721,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
}
private void loadImage() {
ImageLoader.getInstance().loadImageForImageReceiver(this);
ImageLoader.getInstance().loadImageForImageReceiver(this, preloadReceivers);
invalidate();
}
@ -1047,6 +1062,12 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
if (setImageBackup != null && setImageBackup.isSet()) {
SetImageBackup temp = setImageBackup;
setImageBackup = null;
if (temp.thumb instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) temp.thumb;
if (!(bitmapDrawable instanceof RLottieDrawable) && !(bitmapDrawable instanceof AnimatedFileDrawable) && bitmapDrawable.getBitmap() != null && bitmapDrawable.getBitmap().isRecycled()) {
temp.thumb = null;
}
}
setImage(temp.mediaLocation, temp.mediaFilter, temp.imageLocation, temp.imageFilter, temp.thumbLocation, temp.thumbFilter, temp.thumb, temp.size, temp.ext, temp.parentObject, temp.cacheType);
temp.clear();
setImageBackup = temp;

View file

@ -17508,7 +17508,10 @@ public class MessagesController extends BaseController implements NotificationCe
reason = getRestrictionReason(user.restriction_reason);
if (type != 3 && user.bot) {
type = 1;
closeLast = true;
BaseFragment lastFragment = LaunchActivity.getLastFragment();
if (!(lastFragment.storyViewer != null && lastFragment.storyViewer.isShown())) {
closeLast = true;
}
}
}
if (reason != null) {

View file

@ -22,8 +22,6 @@ import android.util.SparseIntArray;
import androidx.annotation.UiThread;
import androidx.collection.LongSparseArray;
import com.google.android.exoplayer2.util.Log;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.SQLite.SQLiteCursor;
import org.telegram.SQLite.SQLiteDatabase;

View file

@ -3708,7 +3708,11 @@ public class NotificationsController extends BaseController {
} else if (names.isEmpty()) {
msg.message = "";
} else if (names.size() == 1) {
msg.message = LocaleController.formatPluralString("StoryNotification1", storiesCount, names.get(0));
if (storiesCount == 1) {
msg.message = LocaleController.getString("StoryNotificationSingle");
} else {
msg.message = LocaleController.formatPluralString("StoryNotification1", storiesCount, names.get(0));
}
} else if (names.size() == 2) {
msg.message = LocaleController.formatString(R.string.StoryNotification2, names.get(0), names.get(1));
} else if (names.size() == 3 && storyPushMessages.size() == 3) {
@ -4682,7 +4686,11 @@ public class NotificationsController extends BaseController {
} else if (names.isEmpty()) {
continue;
} else if (names.size() == 1) {
text.append(LocaleController.formatPluralString("StoryNotification1", storiesCount, names.get(0)));
if (storiesCount == 1) {
text.append(LocaleController.getString("StoryNotificationSingle"));
} else {
text.append(LocaleController.formatPluralString("StoryNotification1", storiesCount, names.get(0)));
}
} else if (names.size() == 2) {
text.append(LocaleController.formatString(R.string.StoryNotification2, names.get(0), names.get(1)));
} else if (names.size() == 3 && storyPushMessages.size() == 3) {

View file

@ -459,7 +459,7 @@ public class PushListenerController {
} else {
switch (loc_key) {
case "STORY_NOTEXT": {
messageText = LocaleController.formatPluralString("StoryNotification1", 1, args[0]);
messageText = LocaleController.getString("StoryNotificationSingle");
message1 = null;
msg_id = story_id;
break;

View file

@ -1,5 +1,6 @@
package org.telegram.messenger;
import com.google.gson.ExclusionStrategy;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@ -114,21 +115,23 @@ public final class RuntimeClassNameTypeAdapterFactory<T> implements TypeAdapterF
private final String typeFieldName;
private final Map<String, Class<?>> labelToSubtype = new LinkedHashMap<String, Class<?>>();
private final Map<Class<?>, String> subtypeToLabel = new LinkedHashMap<Class<?>, String>();
private final ExclusionStrategy exclusionStrategy;
private RuntimeClassNameTypeAdapterFactory(Class<?> baseType, String typeFieldName) {
private RuntimeClassNameTypeAdapterFactory(Class<?> baseType, String typeFieldName, ExclusionStrategy exclusionStrategy) {
if (typeFieldName == null || baseType == null) {
throw new NullPointerException();
}
this.baseType = baseType;
this.typeFieldName = typeFieldName;
this.exclusionStrategy = exclusionStrategy;
}
/**
* Creates a new runtime type adapter using for {@code baseType} using {@code
* typeFieldName} as the type field name. Type field names are case sensitive.
*/
public static <T> RuntimeClassNameTypeAdapterFactory<T> of(Class<T> baseType, String typeFieldName) {
return new RuntimeClassNameTypeAdapterFactory<T>(baseType, typeFieldName);
public static <T> RuntimeClassNameTypeAdapterFactory<T> of(Class<T> baseType, String typeFieldName, ExclusionStrategy exclusionStrategy) {
return new RuntimeClassNameTypeAdapterFactory<T>(baseType, typeFieldName, exclusionStrategy);
}
/**
@ -136,7 +139,7 @@ public final class RuntimeClassNameTypeAdapterFactory<T> implements TypeAdapterF
* the type field name.
*/
public static <T> RuntimeClassNameTypeAdapterFactory<T> of(Class<T> baseType) {
return new RuntimeClassNameTypeAdapterFactory<T>(baseType, "class");
return new RuntimeClassNameTypeAdapterFactory<T>(baseType, "class", null);
}
/**
@ -171,6 +174,9 @@ public final class RuntimeClassNameTypeAdapterFactory<T> implements TypeAdapterF
public <R> TypeAdapter<R> create(Gson gson, TypeToken<R> type) {
if (exclusionStrategy.shouldSkipClass(type.getRawType().getClass())) {
return null;
}
final Map<String, TypeAdapter<?>> labelToDelegate
= new LinkedHashMap<String, TypeAdapter<?>>();
final Map<Class<?>, TypeAdapter<?>> subtypeToDelegate

View file

@ -436,6 +436,7 @@ public class CameraController implements MediaRecorder.OnInfoListener {
if (!ignoreOrientation && orientation != -1) {
matrix.setRotate(orientation);
}
orientation = 0;
matrix.postScale(-1, 1);
Bitmap scaled = Bitmaps.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
if (scaled != bitmap) {

View file

@ -60,9 +60,11 @@ import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
import com.google.zxing.common.detector.MathUtils;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.BuildVars;
import org.telegram.messenger.DispatchQueue;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.ImageLoader;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.R;
import org.telegram.messenger.SharedConfig;
@ -77,6 +79,7 @@ import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.RLottieDrawable;
import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@ -96,6 +99,8 @@ import javax.microedition.khronos.opengles.GL;
@SuppressLint("NewApi")
public class CameraView extends FrameLayout implements TextureView.SurfaceTextureListener, CameraController.ICameraView {
public boolean WRITE_TO_FILE_IN_BACKGROUND = true;
public boolean isStory;
private Size[] previewSize = new Size[2];
private Size[] pictureSize = new Size[2];
@ -272,7 +277,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
addToDualWait(400L);
return;
}
if (!isFrontface && "samsung".equalsIgnoreCase(Build.MANUFACTURER) && !toggledDualAsSave) {
if (!isFrontface && "samsung".equalsIgnoreCase(Build.MANUFACTURER) && !toggledDualAsSave && cameraSession[0] != null) {
final Handler handler = cameraThread.getHandler();
if (handler != null) {
cameraThread.sendMessage(handler.obtainMessage(cameraThread.BLUR_CAMERA1), 0);
@ -1042,7 +1047,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
private CameraSession currentSession[] = new CameraSession[2];
private SurfaceTexture[] cameraSurface = new SurfaceTexture[2];
private final SurfaceTexture[] cameraSurface = new SurfaceTexture[2];
private final int DO_RENDER_MESSAGE = 0;
private final int DO_SHUTDOWN_MESSAGE = 1;
@ -1329,11 +1334,13 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
}
public void finish() {
for (int i = 0; i < 2; ++i) {
if (cameraSurface[i] != null) {
cameraSurface[i].setOnFrameAvailableListener(null);
cameraSurface[i].release();
cameraSurface[i] = null;
if (cameraSurface != null) {
for (int i = 0; i < cameraSurface.length; ++i) {
if (cameraSurface[i] != null) {
cameraSurface[i].setOnFrameAvailableListener(null);
cameraSurface[i].release();
cameraSurface[i] = null;
}
}
}
if (eglSurface != null) {
@ -1464,7 +1471,10 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
continue;
}
final int i = a < 0 ? 1 : a;
if (cameraSurface[i] == null || i != 0 && (currentSession[i] == null || !currentSession[i].isInitied()) || i == 0 && cameraId1 < 0 && !dual || i == 1 && cameraId2 < 0) {
if (cameraSurface[i] == null) {
continue;
}
if (i != 0 && (currentSession[i] == null || !currentSession[i].isInitied()) || i == 0 && cameraId1 < 0 && !dual || i == 1 && cameraId2 < 0) {
continue;
}
@ -1489,7 +1499,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
GLES20.glUniformMatrix4fv(vertexMatrixHandle, 1, false, mMVPMatrix[i], 0);
if (i == 0) {
GLES20.glUniform2f(pixelHandle, pixelW, pixelH);
GLES20.glUniform1f(dualHandle, 0f);
GLES20.glUniform1f(dualHandle, dual ? 1 : 0);
} else {
GLES20.glUniform2f(pixelHandle, pixelDualW, pixelDualH);
GLES20.glUniform1f(dualHandle, 1f);
@ -1947,6 +1957,8 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
private static final int IFRAME_INTERVAL = 1;
private File videoFile;
private File fileToWrite;
private boolean writingToDifferentFile;
private int videoBitrate;
private boolean videoConvertFirstWrite = true;
private boolean blendEnabled;
@ -2348,7 +2360,8 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
GLES20.glEnable(GLES20.GL_BLEND);
blendEnabled = true;
}
if (dual) {
final boolean isDual = dual;
if (isDual) {
GLES20.glClearColor(0.f, 0.f, 0.f, 1.f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
}
@ -2379,7 +2392,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
GLES20.glUniform1f(blurHandle, 0);
if (i == 0) {
GLES20.glUniform2f(pixelHandle, pixelW, pixelH);
GLES20.glUniform1f(dualHandle, 0f);
GLES20.glUniform1f(dualHandle, isDual ? 1f : 0f);
} else {
GLES20.glUniform2f(pixelHandle, pixelDualW, pixelDualH);
GLES20.glUniform1f(dualHandle, 1f);
@ -2484,6 +2497,19 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
e.printStackTrace();
}
if (writingToDifferentFile) {
if (!fileToWrite.renameTo(videoFile)) {
FileLog.e("unable to rename file, try move file");
try {
AndroidUtilities.copyFile(fileToWrite, videoFile);
fileToWrite.delete();
} catch (IOException e) {
FileLog.e(e);
FileLog.e("unable to move file");
}
}
}
EGL14.eglDestroySurface(eglDisplay, eglSurface);
eglSurface = EGL14.EGL_NO_SURFACE;
if (surface != null) {
@ -2586,8 +2612,24 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
surface = videoEncoder.createInputSurface();
videoEncoder.start();
boolean isSdCard = ImageLoader.isSdCardPath(videoFile);
fileToWrite = videoFile;
if (isSdCard) {
try {
fileToWrite = new File(ApplicationLoader.getFilesDirFixed(), "camera_tmp.mp4");
if (fileToWrite.exists()) {
fileToWrite.delete();
}
writingToDifferentFile = true;
} catch (Throwable e) {
FileLog.e(e);
fileToWrite = videoFile;
writingToDifferentFile = false;
}
}
Mp4Movie movie = new Mp4Movie();
movie.setCacheFile(videoFile);
movie.setCacheFile(fileToWrite);
movie.setRotation(0);
movie.setSize(videoWidth, videoHeight);
mediaMuxer = new MP4Builder().createMovie(movie, false, false);
@ -2749,7 +2791,6 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
if (encodedData == null) {
throw new RuntimeException("encoderOutputBuffer " + encoderStatus + " was null");
}
boolean allowReleaseBuffer = true;
if (videoBufferInfo.size > 1) {
if ((videoBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
if (prependHeaderSize != 0 && (videoBufferInfo.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0) {
@ -2765,18 +2806,10 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
bufferInfo.offset = videoBufferInfo.offset;
bufferInfo.flags = videoBufferInfo.flags;
bufferInfo.presentationTimeUs = videoBufferInfo.presentationTimeUs;
allowReleaseBuffer = false;
ByteBuffer byteBuffer = encodedData.duplicate();
fileWriteQueue.postRunnable(() -> {
try {
mediaMuxer.writeSampleData(videoTrackIndex, encodedData, bufferInfo, true);
MediaCodec videoEncoder = VideoRecorder.this.videoEncoder;
if (videoEncoder != null) {
try {
videoEncoder.releaseOutputBuffer(encoderStatus, false);
} catch (Throwable e) {
//ignore IllegalStateException if codec released
}
}
mediaMuxer.writeSampleData(videoTrackIndex, byteBuffer, bufferInfo, true);
} catch (Exception e) {
FileLog.e(e);
}
@ -2813,9 +2846,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
videoTrackIndex = mediaMuxer.addTrack(newFormat, false);
}
}
if (allowReleaseBuffer) {
videoEncoder.releaseOutputBuffer(encoderStatus, false);
}
videoEncoder.releaseOutputBuffer(encoderStatus, false);
if ((videoBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
break;
}
@ -2860,24 +2891,16 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
bufferInfo.offset = audioBufferInfo.offset;
bufferInfo.flags = audioBufferInfo.flags;
bufferInfo.presentationTimeUs = audioBufferInfo.presentationTimeUs;
ByteBuffer byteBuffer = encodedData.duplicate();
fileWriteQueue.postRunnable(() -> {
try {
mediaMuxer.writeSampleData(audioTrackIndex, encodedData, bufferInfo, false);
MediaCodec audioEncoder = VideoRecorder.this.audioEncoder;
if (audioEncoder != null) {
try {
audioEncoder.releaseOutputBuffer(encoderStatus, false);
} catch (Throwable e) {
//ignore IllegalStateException if codec released
}
}
mediaMuxer.writeSampleData(audioTrackIndex, byteBuffer, bufferInfo, false);
} catch (Exception e) {
FileLog.e(e);
}
});
} else {
audioEncoder.releaseOutputBuffer(encoderStatus, false);
}
audioEncoder.releaseOutputBuffer(encoderStatus, false);
if ((audioBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
break;
}

View file

@ -760,6 +760,7 @@ public class ActionBarLayout extends FrameLayout implements INavigationLayout, F
parent.removeViewInLayout(lastFragment.actionBar);
}
}
lastFragment.detachStoryViewer();
}
layoutToIgnore = null;
}

View file

@ -16,6 +16,7 @@ import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
@ -166,6 +167,12 @@ public class ActionBarPopupWindow extends PopupWindow {
try {
scrollView = new ScrollView(context);
scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
invalidate();
}
});
scrollView.setVerticalScrollBarEnabled(false);
if (swipeBackLayout != null) {
swipeBackLayout.addView(scrollView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, shownFromBottom ? Gravity.BOTTOM : Gravity.TOP));
@ -416,6 +423,8 @@ public class ActionBarPopupWindow extends PopupWindow {
return super.dispatchKeyEvent(event);
}
Path path;
@Override
protected void dispatchDraw(Canvas canvas) {
if (swipeBackGravityRight) {
@ -487,9 +496,15 @@ public class ActionBarPopupWindow extends PopupWindow {
backgroundDrawable.draw(canvas);
if (hasGap) {
canvas.save();
AndroidUtilities.rectTmp2.set(backgroundDrawable.getBounds());
AndroidUtilities.rectTmp2.inset(AndroidUtilities.dp(8), AndroidUtilities.dp(8));
canvas.clipRect(AndroidUtilities.rectTmp2);
AndroidUtilities.rectTmp.set(backgroundDrawable.getBounds());
AndroidUtilities.rectTmp.inset(AndroidUtilities.dp(8), AndroidUtilities.dp(8));
if (path == null) {
path = new Path();
} else {
path.rewind();
}
path.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(8), AndroidUtilities.dp(8), Path.Direction.CW);
canvas.clipPath(path);
for (int i = 0; i < linearLayout.getChildCount(); i++) {
if (linearLayout.getChildAt(i) instanceof GapView && linearLayout.getChildAt(i).getVisibility() == View.VISIBLE) {
canvas.save();
@ -504,7 +519,7 @@ public class ActionBarPopupWindow extends PopupWindow {
break;
}
}
canvas.translate(x, y * scrollView.getScaleY());
canvas.translate(x, y * scrollView.getScaleY() - scrollView.getScrollY());
child.draw(canvas);
canvas.restore();
}

View file

@ -84,26 +84,13 @@ public class ContactsAdapter extends RecyclerListView.SectionsAdapter {
}
public void setStories(ArrayList<TLRPC.TL_userStories> stories, boolean animated) {
boolean hasStories = !stories.isEmpty();
userStories.clear();
userStories.addAll(stories);
if (this.hasStories != hasStories) {
this.hasStories = hasStories;
// if (!animated) {
// notifyDataSetChanged();
// } else {
// cleanupCache();
// notifyDataSetChanged();
// if (hasStories) {
// notifyItemInserted(0);
// } else {
// notifyItemRemoved(0);
// notifyItemRangeChanged(1, getItemCount());
// }
// }
}
update(true);
// notifyDataSetChanged();
// boolean hasStories = !stories.isEmpty();
// userStories.clear();
// userStories.addAll(stories);
// if (this.hasStories != hasStories) {
// this.hasStories = hasStories;
// }
// update(true);
}
public void setDisableSections(boolean value) {

View file

@ -74,6 +74,7 @@ import org.telegram.ui.Components.PullForegroundDrawable;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.DialogsActivity;
import org.telegram.ui.Stories.DialogStoriesCell;
import org.telegram.ui.Stories.StoriesController;
import org.telegram.ui.Stories.StoriesListPlaceProvider;
import org.telegram.ui.Stories.StoriesUtilities;
@ -92,8 +93,8 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements
VIEW_TYPE_USER = 6,
VIEW_TYPE_HEADER = 7,
VIEW_TYPE_SHADOW = 8,
// VIEW_TYPE_ARCHIVE = 9,
VIEW_TYPE_LAST_EMPTY = 10,
// VIEW_TYPE_ARCHIVE = 9,
VIEW_TYPE_LAST_EMPTY = 10,
VIEW_TYPE_NEW_CHAT_HINT = 11,
VIEW_TYPE_TEXT = 12,
VIEW_TYPE_CONTACTS_FLICKER = 13,
@ -487,7 +488,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements
if (view != null) {
float offset = view.getTop() - recyclerListView.getPaddingTop();
if (!hasStories) {
// offset += tabsTranslation;
// offset += tabsTranslation;
} else {
tabsTranslation = 0;
}
@ -660,8 +661,8 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements
case VIEW_TYPE_ARCHIVE_FULLSCREEN:
LastEmptyView lastEmptyView = new LastEmptyView(mContext);
lastEmptyView.addView(
new ArchiveHelp(mContext, currentAccount, null, DialogsAdapter.this::onArchiveSettingsClick,null),
LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER, 0, -(int) (DialogStoriesCell.HEIGHT_IN_DP * .5f), 0, 0)
new ArchiveHelp(mContext, currentAccount, null, DialogsAdapter.this::onArchiveSettingsClick, null),
LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER, 0, -(int) (DialogStoriesCell.HEIGHT_IN_DP * .5f), 0, 0)
);
view = lastEmptyView;
break;
@ -733,6 +734,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements
if (dialogsType == DialogsActivity.DIALOGS_TYPE_BOT_REQUEST_PEER) {
view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
}
break;
}
case VIEW_TYPE_STORIES: {
view = new View(mContext) {
@ -1091,6 +1093,23 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements
parentFragment.showChatPreview(cell);
}
@Override
public void openHiddenStories() {
StoriesController storiesController = MessagesController.getInstance(currentAccount).getStoriesController();
if (storiesController.getHiddenList().isEmpty()) {
return;
}
boolean unreadOnly = storiesController.getUnreadState(storiesController.getHiddenList().get(0).user_id) != StoriesController.STATE_READ;
ArrayList<Long> peerIds = new ArrayList<>();
for (int i = 0; i < storiesController.getHiddenList().size(); i++) {
if (!unreadOnly || storiesController.getUnreadState(storiesController.getHiddenList().get(i).user_id) != StoriesController.STATE_READ) {
peerIds.add(storiesController.getHiddenList().get(i).user_id);
}
}
parentFragment.getOrCreateStoryViewer().open(mContext, null, peerIds, 0, null, null, StoriesListPlaceProvider.of(recyclerListView, true), false);
}
public void setIsTransitionSupport() {
this.isTransitionSupport = true;
}

View file

@ -316,12 +316,12 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter {
items.add(new Item(15, LocaleController.getString("SetEmojiStatus", R.string.SetEmojiStatus), R.drawable.msg_status_set));
}
}
// if (MessagesController.getInstance(UserConfig.selectedAccount).storiesEnabled()) {
if (MessagesController.getInstance(UserConfig.selectedAccount).storiesEnabled()) {
items.add(new Item(16, LocaleController.getString("ProfileMyStories", R.string.ProfileMyStories), R.drawable.msg_menu_stories));
items.add(null); // divider
// } else if (me != null && me.isPremium()) {
// items.add(null); // divider
// }
} else if (me != null && me.isPremium()) {
items.add(null); // divider
}
items.add(new Item(2, LocaleController.getString("NewGroup", R.string.NewGroup), newGroupIcon));
//items.add(new Item(3, LocaleController.getString("NewSecretChat", R.string.NewSecretChat), newSecretIcon));
//items.add(new Item(4, LocaleController.getString("NewChannel", R.string.NewChannel), newChannelIcon));

View file

@ -112,7 +112,7 @@ public class AudioPlayerCell extends View implements DownloadController.FileDown
try {
CharSequence author = currentMessageObject.getMusicAuthor().replace('\n', ' ');
if (viewType == VIEW_TYPE_GLOBAL_SEARCH) {
author = new SpannableStringBuilder(author).append(' ').append(dotSpan).append(' ').append(FilteredSearchView.createFromInfoString(currentMessageObject));
author = new SpannableStringBuilder(author).append(' ').append(dotSpan).append(' ').append(FilteredSearchView.createFromInfoString(currentMessageObject, 2));
}
CharSequence authorFinal = TextUtils.ellipsize(author, Theme.chat_contextResult_descriptionTextPaint, maxWidth, TextUtils.TruncateAt.END);
descriptionLayout = new StaticLayout(authorFinal, Theme.chat_contextResult_descriptionTextPaint, maxWidth + AndroidUtilities.dp(4), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);

View file

@ -1063,7 +1063,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
private int getImageSize(MessageObject messageObject) {
int imageSize = stickerSize;
if (messageObject.type == MessageObject.TYPE_SUGGEST_PHOTO || isNewStyleButtonLayout()) {
imageSize = (int) (stickerSize * 0.7f);
imageSize = AndroidUtilities.dp(78);//Math.max(, (int) (stickerSize * 0.7f));
}
return imageSize;
}
@ -1178,7 +1178,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
} else {
giftPremiumTitleLayout = null;
}
if (currentMessageObject != null && (currentMessageObject.type == MessageObject.TYPE_SUGGEST_PHOTO || currentMessageObject.isStoryMention())) {
if (currentMessageObject != null && isNewStyleButtonLayout()) {
giftSubtitlePaint.setTextSize(AndroidUtilities.dp(13));
} else {
giftSubtitlePaint.setTextSize(AndroidUtilities.dp(15));

View file

@ -4894,6 +4894,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
type = webpage == null ? null : webpage.type;
duration = storyItem != null && storyItem.media != null && storyItem.media.document != null ? (int) MessageObject.getDocumentDuration(storyItem.media.document) : 0;
smallImage = false;
isSmallImage = false;
} else if (hasLinkPreview) {
TLRPC.TL_webPage webPage = (TLRPC.TL_webPage) webpage;
site_name = webPage.site_name;

View file

@ -161,16 +161,26 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
private TimerDrawable timerDrawable;
private Paint timerPaint;
private Paint timerPaint2;
public final StoriesUtilities.AvatarStoryParams params = new StoriesUtilities.AvatarStoryParams(false) {
public final StoriesUtilities.AvatarStoryParams storyParams = new StoriesUtilities.AvatarStoryParams(false) {
@Override
public void openStory(long dialogId, Runnable onDone) {
if (delegate != null) {
delegate.openStory(DialogCell.this, onDone);
if (delegate == null) {
return;
}
if (currentDialogFolderId != 0) {
delegate.openHiddenStories();
} else {
if (delegate != null) {
delegate.openStory(DialogCell.this, onDone);
}
}
}
@Override
public void onLongPress() {
if (delegate == null) {
return;
}
delegate.showChatPreview(DialogCell.this);
}
};
@ -522,7 +532,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
public DialogCell(DialogsActivity fragment, Context context, boolean needCheck, boolean forceThreeLines, int account, Theme.ResourcesProvider resourcesProvider) {
super(context);
params.allowLongress = true;
storyParams.allowLongress = true;
this.resourcesProvider = resourcesProvider;
parentFragment = fragment;
Theme.createDialogsResources(context);
@ -697,7 +707,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
AnimatedEmojiSpan.release(this, animatedEmojiStack2);
AnimatedEmojiSpan.release(this, animatedEmojiStack3);
AnimatedEmojiSpan.release(this, animatedEmojiStackName);
params.onDetachFromWindow();
storyParams.onDetachFromWindow();
}
@Override
@ -1888,7 +1898,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
avatarLeft = AndroidUtilities.dp(10);
thumbLeft = avatarLeft + AndroidUtilities.dp(56 + 13);
}
params.originalAvatarRect.set(avatarLeft, avatarTop, avatarLeft + AndroidUtilities.dp(56), avatarTop + AndroidUtilities.dp(56));
storyParams.originalAvatarRect.set(avatarLeft, avatarTop, avatarLeft + AndroidUtilities.dp(56), avatarTop + AndroidUtilities.dp(56));
for (int i = 0; i < thumbImage.length; ++i) {
thumbImage[i].setImageCoords(thumbLeft + (thumbSize + 2) * i, avatarTop + AndroidUtilities.dp(31) + (twoLinesForName ? AndroidUtilities.dp(20) : 0), AndroidUtilities.dp(18), AndroidUtilities.dp(18));
}
@ -1911,7 +1921,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
avatarLeft = AndroidUtilities.dp(10);
thumbLeft = avatarLeft + AndroidUtilities.dp(56 + 11);
}
params.originalAvatarRect.set(avatarLeft, avatarTop, avatarLeft + AndroidUtilities.dp(54), avatarTop + AndroidUtilities.dp(54));
storyParams.originalAvatarRect.set(avatarLeft, avatarTop, avatarLeft + AndroidUtilities.dp(54), avatarTop + AndroidUtilities.dp(54));
for (int i = 0; i < thumbImage.length; ++i) {
thumbImage[i].setImageCoords(thumbLeft + (thumbSize + 2) * i, avatarTop + AndroidUtilities.dp(30) + (twoLinesForName ? AndroidUtilities.dp(20) : 0), AndroidUtilities.dp(thumbSize), AndroidUtilities.dp(thumbSize));
}
@ -3793,8 +3803,9 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
canvas.scale(scale, scale, avatarImage.getCenterX(), avatarImage.getCenterY());
}
if (drawAvatar && (!(currentDialogFolderId != 0 || isTopic && forumTopic != null && forumTopic.id == 1) || archivedChatsDrawable == null || !archivedChatsDrawable.isDraw())) {
StoriesUtilities.drawAvatarWithStory(currentDialogId, canvas, avatarImage, params);
if (drawAvatar && (!(isTopic && forumTopic != null && forumTopic.id == 1) || archivedChatsDrawable == null || !archivedChatsDrawable.isDraw())) {
storyParams.drawHiddenStoriesAsSegments = currentDialogFolderId != 0;
StoriesUtilities.drawAvatarWithStory(currentDialogId, canvas, avatarImage, storyParams);
}
if (animatingArchiveAvatar) {
@ -3812,8 +3823,8 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
} else {
drawCounterMuted = chat != null && chat.forum && forumTopic == null ? !hasUnmutedTopics : dialogMuted;
}
int countLeftLocal = (int) (params.originalAvatarRect.left + avatarImage.getImageWidth() - countWidth - AndroidUtilities.dp(5f));
int countLeftOld = (int) (params.originalAvatarRect.left + avatarImage.getImageWidth() - countWidthOld - AndroidUtilities.dp(5f));
int countLeftLocal = (int) (storyParams.originalAvatarRect.left + avatarImage.getImageWidth() - countWidth - AndroidUtilities.dp(5f));
int countLeftOld = (int) (storyParams.originalAvatarRect.left + avatarImage.getImageWidth() - countWidthOld - AndroidUtilities.dp(5f));
int countTop = (int) (avatarImage.getImageY() + avatarImage.getImageHeight() - AndroidUtilities.dp(22));
drawCounter(canvas, drawCounterMuted, countTop, countLeftLocal, countLeftOld, rightFragmentOpenedProgress, true);
}
@ -3970,9 +3981,9 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
int top = (int) (avatarImage.getImageY2() - AndroidUtilities.dp(9));
int left;
if (LocaleController.isRTL) {
left = (int) (params.originalAvatarRect.left + AndroidUtilities.dp(9));
left = (int) (storyParams.originalAvatarRect.left + AndroidUtilities.dp(9));
} else {
left = (int) (params.originalAvatarRect.right - AndroidUtilities.dp(9));
left = (int) (storyParams.originalAvatarRect.right - AndroidUtilities.dp(9));
}
timerDrawable.setBounds(
0, 0, AndroidUtilities.dp(22), AndroidUtilities.dp(22)
@ -4011,12 +4022,12 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
if (user != null && !MessagesController.isSupportUser(user) && !user.bot) {
boolean isOnline = isOnline();
if (isOnline || onlineProgress != 0) {
int top = (int) (params.originalAvatarRect.bottom - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 6 : 8));
int top = (int) (storyParams.originalAvatarRect.bottom - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 6 : 8));
int left;
if (LocaleController.isRTL) {
left = (int) (params.originalAvatarRect.left + AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6));
left = (int) (storyParams.originalAvatarRect.left + AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6));
} else {
left = (int) (params.originalAvatarRect.right - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6));
left = (int) (storyParams.originalAvatarRect.right - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6));
}
Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider));
@ -4045,12 +4056,12 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
hasCall = chat.call_active && chat.call_not_empty;
if ((hasCall || chatCallProgress != 0) && rightFragmentOpenedProgress < 1f) {
float checkProgress = checkBox != null && checkBox.isChecked() ? 1.0f - checkBox.getProgress() : 1.0f;
int top = (int) (params.originalAvatarRect.bottom - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 6 : 8));
int top = (int) (storyParams.originalAvatarRect.bottom - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 6 : 8));
int left;
if (LocaleController.isRTL) {
left = (int) (params.originalAvatarRect.left + AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6));
left = (int) (storyParams.originalAvatarRect.left + AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6));
} else {
left = (int) (params.originalAvatarRect.right - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6));
left = (int) (storyParams.originalAvatarRect.right - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6));
}
if (rightFragmentOpenedProgress != 0) {
@ -4370,9 +4381,9 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
archivedChatsDrawable.outRadius = 0;
archivedChatsDrawable.outImageSize = 0;
} else {
archivedChatsDrawable.outCy = params.originalAvatarRect.centerY();
archivedChatsDrawable.outCx = params.originalAvatarRect.centerX();
archivedChatsDrawable.outRadius = params.originalAvatarRect.width() / 2.0f;
archivedChatsDrawable.outCy = storyParams.originalAvatarRect.centerY();
archivedChatsDrawable.outCx = storyParams.originalAvatarRect.centerX();
archivedChatsDrawable.outRadius = avatarImage.getImageWidth() / 2.0f;
archivedChatsDrawable.outImageSize = avatarImage.getBitmapWidth();
}
archivedChatsDrawable.startOutAnimation();
@ -4864,7 +4875,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (rightFragmentOpenedProgress == 0 && params.checkOnTouchEvent(ev, this)) {
if (rightFragmentOpenedProgress == 0 && storyParams.checkOnTouchEvent(ev, this)) {
return true;
}
return super.onInterceptTouchEvent(ev);
@ -4873,14 +4884,14 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) {
params.checkOnTouchEvent(ev, this);
storyParams.checkOnTouchEvent(ev, this);
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (rightFragmentOpenedProgress == 0 && params.checkOnTouchEvent(event, this)) {
if (rightFragmentOpenedProgress == 0 && storyParams.checkOnTouchEvent(event, this)) {
return true;
}
if (delegate == null || delegate.canClickButtonInside()) {
@ -4935,6 +4946,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava
boolean canClickButtonInside();
void openStory(DialogCell dialogCell, Runnable onDone);
void showChatPreview(DialogCell dialogCell);
void openHiddenStories();
}
private class DialogUpdateHelper {

View file

@ -31,7 +31,6 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
@ -65,6 +64,7 @@ import org.telegram.ui.Components.Premium.StarParticlesView;
import org.telegram.ui.Components.RLottieDrawable;
import org.telegram.ui.Components.RLottieImageView;
import org.telegram.ui.Components.Reactions.AnimatedEmojiEffect;
import org.telegram.ui.Components.Reactions.HwEmojis;
import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
import org.telegram.ui.Components.SnowflakesEffect;
import org.telegram.ui.ThemeActivity;
@ -125,6 +125,38 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
animatedStatus.translate(AndroidUtilities.rectTmp2.centerX(), AndroidUtilities.rectTmp2.centerY());
}
}
@Override
public void invalidate() {
if (HwEmojis.grab(this)) {
return;
}
super.invalidate();
}
@Override
public void invalidate(int l, int t, int r, int b) {
if (HwEmojis.grab(this)) {
return;
}
super.invalidate(l, t, r, b);
}
@Override
public void invalidateDrawable(Drawable who) {
if (HwEmojis.grab(this)) {
return;
}
super.invalidateDrawable(who);
}
@Override
public void invalidate(Rect dirty) {
if (HwEmojis.grab(this)) {
return;
}
super.invalidate(dirty);
}
};
nameTextView.setRightDrawableOnClick(e -> {
if (lastUser != null && lastUser.premium) {
@ -441,6 +473,7 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
status.attach();
updateColors();
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded);
for (int i = 0; i < UserConfig.MAX_ACCOUNT_COUNT; i++){
@ -451,6 +484,7 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
status.detach();
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded);
for (int i = 0; i < UserConfig.MAX_ACCOUNT_COUNT; i++){
NotificationCenter.getInstance(i).removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged);

View file

@ -88,6 +88,7 @@ public class DrawerUserCell extends FrameLayout implements NotificationCenter.No
protected void onAttachedToWindow() {
super.onAttachedToWindow();
textView.setTextColor(Theme.getColor(Theme.key_chats_menuItemText));
status.attach();
for (int i = 0; i < UserConfig.MAX_ACCOUNT_COUNT; i++){
NotificationCenter.getInstance(i).addObserver(this, NotificationCenter.currentUserPremiumStatusChanged);
NotificationCenter.getInstance(i).addObserver(this, NotificationCenter.updateInterfaces);
@ -98,6 +99,7 @@ public class DrawerUserCell extends FrameLayout implements NotificationCenter.No
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
status.detach();
for (int i = 0; i < UserConfig.MAX_ACCOUNT_COUNT; i++){
NotificationCenter.getInstance(i).removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged);
NotificationCenter.getInstance(i).removeObserver(this, NotificationCenter.updateInterfaces);

View file

@ -168,7 +168,7 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F
try {
CharSequence title;
if (viewType == VIEW_TYPE_GLOBAL_SEARCH && (currentMessageObject.isVoice() || currentMessageObject.isRoundVideo())) {
title = FilteredSearchView.createFromInfoString(currentMessageObject);
title = FilteredSearchView.createFromInfoString(currentMessageObject, 1);
} else {
title = currentMessageObject.getMusicTitle().replace('\n', ' ');
}
@ -210,7 +210,7 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F
author = authorH;
}
if (viewType == VIEW_TYPE_GLOBAL_SEARCH) {
author = new SpannableStringBuilder(author).append(' ').append(dotSpan).append(' ').append(FilteredSearchView.createFromInfoString(currentMessageObject));
author = new SpannableStringBuilder(author).append(' ').append(dotSpan).append(' ').append(FilteredSearchView.createFromInfoString(currentMessageObject, 1));
}
TextPaint paint = viewType == VIEW_TYPE_GLOBAL_SEARCH ? description2TextPaint : Theme.chat_contextResult_descriptionTextPaint;
author = TextUtils.ellipsize(author, paint, maxWidth, TextUtils.TruncateAt.END);

View file

@ -37,6 +37,7 @@ import org.telegram.messenger.ImageLocation;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
@ -220,6 +221,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
dateTextView.setSingleLine(true);
dateTextView.setEllipsize(TextUtils.TruncateAt.END);
dateTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
NotificationCenter.listenEmojiLoading(dateTextView);
if (viewType == VIEW_TYPE_PICKER) {
dateTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13);
addView(dateTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 8 : 72, 34, LocaleController.isRTL ? 72 : 8, 0));
@ -509,7 +511,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
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);
CharSequence fromName = FilteredSearchView.createFromInfoString(message, true, 2, dateTextView.getPaint());
dateTextView.setText(new SpannableStringBuilder().append(fileSize)
.append(' ').append(dotSpan).append(' ')

View file

@ -477,7 +477,7 @@ public class SharedLinkCell extends FrameLayout {
}
if (viewType == VIEW_TYPE_GLOBAL_SEARCH) {
fromInfoLayout = ChatMessageCell.generateStaticLayout(FilteredSearchView.createFromInfoString(message), description2TextPaint, maxWidth, maxWidth, 0, desctiptionLines);
fromInfoLayout = ChatMessageCell.generateStaticLayout(FilteredSearchView.createFromInfoString(message, true, 2, description2TextPaint), description2TextPaint, maxWidth, maxWidth, 0, desctiptionLines);
fromInfoLayoutEmojis = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, fromInfoLayoutEmojis, fromInfoLayout);
}

View file

@ -65,6 +65,7 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica
private Theme.ResourcesProvider resourcesProvider;
private AvatarDrawable avatarDrawable;
private boolean storiable;
private Object currentObject;
private TLRPC.EncryptedChat encryptedChat;
@ -142,8 +143,12 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica
avatarImageView = new BackupImageView(context) {
@Override
protected void onDraw(Canvas canvas) {
storyParams.originalAvatarRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
StoriesUtilities.drawAvatarWithStory(dialogId, canvas, imageReceiver, storyParams);
if (storiable) {
storyParams.originalAvatarRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
StoriesUtilities.drawAvatarWithStory(dialogId, canvas, imageReceiver, storyParams);
} else {
super.onDraw(canvas);
}
}
@Override
@ -257,6 +262,7 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica
if (object == null && name == null && status == null) {
currentStatus = null;
currentName = null;
storiable = false;
currentObject = null;
nameTextView.setText("");
statusTextView.setText("");
@ -271,6 +277,7 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica
}
} catch (Exception ignore) {}
currentName = name;
storiable = !(object instanceof String);
currentObject = object;
currentDrawable = resId;
needDivider = divider;

View file

@ -23126,7 +23126,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
primaryMessage = null;
message = null;
}
if (message == null || message.type == MessageObject.TYPE_STORY_MENTION) {
if (message == null) {
return false;
}
if (!single && message.messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium) {
@ -23231,7 +23231,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
} else {
allowPin = false;
}
allowPin = allowPin && message.getId() > 0 && (message.messageOwner.action == null || message.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) && !message.isExpiredStory();
allowPin = allowPin && message.getId() > 0 && (message.messageOwner.action == null || message.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) && !message.isExpiredStory() && message.type != MessageObject.TYPE_STORY_MENTION;
boolean noforwards = getMessagesController().isChatNoForwards(currentChat) || message.messageOwner.noforwards;
boolean allowUnpin = message.getDialogId() != mergeDialogId && allowPin && (pinnedMessageObjects.containsKey(message.getId()) || groupedMessages != null && !groupedMessages.messages.isEmpty() && pinnedMessageObjects.containsKey(groupedMessages.messages.get(0).getId())) && !message.isExpiredStory();
boolean allowEdit = message.canEditMessage(currentChat) && !chatActivityEnterView.hasAudioToSend() && message.getDialogId() != mergeDialogId && message.type != MessageObject.TYPE_STORY;
@ -23645,7 +23645,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
if (!selectedObject.isSponsored() && chatMode != MODE_SCHEDULED && (!selectedObject.needDrawBluredPreview() || selectedObject.hasExtendedMediaPreview()) &&
!selectedObject.isLiveLocation() && selectedObject.type != MessageObject.TYPE_PHONE_CALL && !noforwards &&
selectedObject.type != MessageObject.TYPE_GIFT_PREMIUM && selectedObject.type != MessageObject.TYPE_SUGGEST_PHOTO && !selectedObject.isWallpaperAction() && !message.isExpiredStory()) {
selectedObject.type != MessageObject.TYPE_GIFT_PREMIUM && selectedObject.type != MessageObject.TYPE_SUGGEST_PHOTO && !selectedObject.isWallpaperAction()
&& !message.isExpiredStory() && message.type != MessageObject.TYPE_STORY_MENTION) {
items.add(LocaleController.getString("Forward", R.string.Forward));
options.add(OPTION_FORWARD);
icons.add(R.drawable.msg_forward);

View file

@ -34,6 +34,7 @@ import org.telegram.messenger.ImageReceiver;
import org.telegram.messenger.LiteMode;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.MessagesStorage;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.SvgHelper;
import org.telegram.messenger.UserConfig;
@ -41,7 +42,7 @@ import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.NativeByteBuffer;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.Premium.PremiumLockIconView;
import org.telegram.ui.Components.Reactions.HwEmojis;
import org.telegram.ui.SelectAnimatedEmojiDialog;
import java.io.File;
@ -146,6 +147,7 @@ public class AnimatedEmojiDrawable extends Drawable {
}
private static HashMap<Integer, EmojiDocumentFetcher> fetchers;
public static EmojiDocumentFetcher getDocumentFetcher(int account) {
if (fetchers == null) {
fetchers = new HashMap<>();
@ -156,17 +158,23 @@ public class AnimatedEmojiDrawable extends Drawable {
}
return fetcher;
}
public static class EmojiDocumentFetcher {
private HashMap<Long, TLRPC.Document> emojiDocumentsCache;
private HashMap<Long, ArrayList<ReceivedDocument>> loadingDocuments;
private HashSet<Long> toFetchDocuments;
private Runnable fetchRunnable;
private Runnable uiDbCallback;
private final int currentAccount;
public EmojiDocumentFetcher(int account) {
currentAccount = account;
}
public void setUiDbCallback(Runnable uiDbCallback) {
this.uiDbCallback = uiDbCallback;
}
public void fetchDocument(long id, ReceivedDocument onDone) {
synchronized (this) {
if (emojiDocumentsCache != null) {
@ -204,7 +212,7 @@ public class AnimatedEmojiDrawable extends Drawable {
AndroidUtilities.runOnUIThread(fetchRunnable = () -> {
ArrayList<Long> emojiToLoad = new ArrayList<>(toFetchDocuments);
toFetchDocuments.clear();
loadFromDatabase(emojiToLoad);
loadFromDatabase(emojiToLoad, uiDbCallback == null);
fetchRunnable = null;
});
}
@ -219,51 +227,73 @@ public class AnimatedEmojiDrawable extends Drawable {
return true;
}
private void loadFromDatabase(ArrayList<Long> emojiToLoad, boolean async) {
if (async) {
MessagesStorage messagesStorage = MessagesStorage.getInstance(currentAccount);
messagesStorage.getStorageQueue().postRunnable(() -> loadFromDatabase(emojiToLoad));
} else {
loadFromDatabase(emojiToLoad);
}
}
private void loadFromDatabase(ArrayList<Long> emojiToLoad) {
MessagesStorage messagesStorage = MessagesStorage.getInstance(currentAccount);
messagesStorage.getStorageQueue().postRunnable(() -> {
SQLiteDatabase database = messagesStorage.getDatabase();
if (database == null) {
return;
}
try {
String idsStr = TextUtils.join(",", emojiToLoad);
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM animated_emoji WHERE document_id IN (%s)", idsStr));
ArrayList<Object> documents = new ArrayList<>();
HashSet<Long> loadFromServerIds = new HashSet<>(emojiToLoad);
while (cursor.next()) {
NativeByteBuffer byteBuffer = cursor.byteBufferValue(0);
try {
TLRPC.Document document = TLRPC.Document.TLdeserialize(byteBuffer, byteBuffer.readInt32(true), true);
if (document != null && document.id != 0) {
documents.add(document);
loadFromServerIds.remove(document.id);
}
} catch (Exception e) {
FileLog.e(e);
}
if (byteBuffer != null) {
byteBuffer.reuse();
SQLiteDatabase database = messagesStorage.getDatabase();
if (database == null) {
return;
}
try {
String idsStr = TextUtils.join(",", emojiToLoad);
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM animated_emoji WHERE document_id IN (%s)", idsStr));
ArrayList<Object> documents = new ArrayList<>();
HashSet<Long> loadFromServerIds = new HashSet<>(emojiToLoad);
while (cursor.next()) {
NativeByteBuffer byteBuffer = cursor.byteBufferValue(0);
try {
TLRPC.Document document = TLRPC.Document.TLdeserialize(byteBuffer, byteBuffer.readInt32(true), true);
if (document != null && document.id != 0) {
documents.add(document);
loadFromServerIds.remove(document.id);
}
} catch (Exception e) {
FileLog.e(e);
}
if (byteBuffer != null) {
byteBuffer.reuse();
}
AndroidUtilities.runOnUIThread(() -> {
processDocuments(documents);
if (!loadFromServerIds.isEmpty()) {
loadFromServer(new ArrayList<>(loadFromServerIds));
}
});
cursor.dispose();
} catch (SQLiteException e) {
messagesStorage.checkSQLException(e);
}
});
processDatabaseResult(documents, loadFromServerIds);
cursor.dispose();
if (uiDbCallback != null) {
uiDbCallback.run();
uiDbCallback = null;
}
} catch (SQLiteException e) {
messagesStorage.checkSQLException(e);
}
}
private void processDocumentsAndLoadMore(ArrayList<Object> documents, HashSet<Long> loadFromServerIds) {
processDocuments(documents);
if (!loadFromServerIds.isEmpty()) {
loadFromServer(new ArrayList<>(loadFromServerIds));
}
}
private void processDatabaseResult(ArrayList<Object> documents, HashSet<Long> loadFromServerIds) {
if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
processDocumentsAndLoadMore(documents, loadFromServerIds);
} else {
NotificationCenter.getInstance(currentAccount).doOnIdle(() -> AndroidUtilities.runOnUIThread(() -> processDocumentsAndLoadMore(documents, loadFromServerIds)));
}
}
private void loadFromServer(ArrayList<Long> loadFromServerIds) {
final TLRPC.TL_messages_getCustomEmojiDocuments req = new TLRPC.TL_messages_getCustomEmojiDocuments();
req.document_id = loadFromServerIds;
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> {
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> NotificationCenter.getInstance(currentAccount).doOnIdle(() -> AndroidUtilities.runOnUIThread(() -> {
HashSet<Long> loadedFromServer = new HashSet<>(loadFromServerIds);
if (res instanceof TLRPC.Vector) {
ArrayList<Object> objects = ((TLRPC.Vector) res).objects;
@ -280,7 +310,7 @@ public class AnimatedEmojiDrawable extends Drawable {
loadFromServer(new ArrayList<>(loadedFromServer));
}
}
}));
})));
}
private void putToStorage(ArrayList<Object> objects) {
@ -438,11 +468,13 @@ public class AnimatedEmojiDrawable extends Drawable {
sizedp = 34;
}
}
public long getDocumentId() {
return this.document != null ? this.document.id : this.documentId;
}
private static boolean liteModeKeyboard, liteModeReactions;
private static void updateLiteModeValues() {
liteModeKeyboard = LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_KEYBOARD);
liteModeReactions = LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_EMOJI_REACTIONS);
@ -472,6 +504,7 @@ public class AnimatedEmojiDrawable extends Drawable {
};
imageReceiver.setAllowLoadingOnAttachedOnly(true);
};
if (cacheType == CACHE_TYPE_RENDERING_VIDEO) {
imageReceiver.ignoreNotifications = true;
}
@ -541,7 +574,7 @@ public class AnimatedEmojiDrawable extends Drawable {
if (onlyStaticPreview || (!liteModeKeyboard && cacheType != CACHE_TYPE_AVATAR_CONSTRUCTOR_PREVIEW)) {
if ("video/webm".equals(document.mime_type)) {
imageReceiver.setImage(null, null, ImageLocation.getForDocument(thumb, document), sizedp + "_" + sizedp, null, null, thumbDrawable, document.size, null, document, 1);
} else if (MessageObject.isAnimatedStickerDocument(document, true)){
} else if (MessageObject.isAnimatedStickerDocument(document, true)) {
imageReceiver.setImage(mediaLocation, mediaFilter + "_firstframe", null, null, thumbDrawable, document.size, null, document, 1);
} else {
imageReceiver.setImage(ImageLocation.getForDocument(thumb, document), sizedp + "_" + sizedp, null, null, thumbDrawable, document.size, null, document, 1);
@ -612,6 +645,7 @@ public class AnimatedEmojiDrawable extends Drawable {
}
private static Paint placeholderPaint;
public static void updatePlaceholderPaintColor() {
if (placeholderPaint != null) {
placeholderPaint.setColor(Theme.isCurrentThemeDark() ? 0x0fffffff : 0x0f000000);
@ -706,6 +740,7 @@ public class AnimatedEmojiDrawable extends Drawable {
public static int attachedCount = 0;
public static ArrayList<AnimatedEmojiDrawable> attachedDrawable;
private void updateAttachState() {
if (imageReceiver == null) {
return;
@ -742,6 +777,7 @@ public class AnimatedEmojiDrawable extends Drawable {
}
private Boolean canOverrideColorCached = null;
public boolean canOverrideColor() {
if (canOverrideColorCached != null) {
return canOverrideColorCached;
@ -753,6 +789,7 @@ public class AnimatedEmojiDrawable extends Drawable {
}
private Boolean isDefaultStatusEmojiCached = null;
public boolean isDefaultStatusEmoji() {
if (isDefaultStatusEmojiCached != null) {
return isDefaultStatusEmojiCached;
@ -760,8 +797,8 @@ public class AnimatedEmojiDrawable extends Drawable {
if (document != null) {
TLRPC.InputStickerSet set = MessageObject.getInputStickerSet(document);
return isDefaultStatusEmojiCached = (
set instanceof TLRPC.TL_inputStickerSetEmojiDefaultStatuses ||
set instanceof TLRPC.TL_inputStickerSetID && (set.id == 773947703670341676L || set.id == 2964141614563343L)
set instanceof TLRPC.TL_inputStickerSetEmojiDefaultStatuses ||
set instanceof TLRPC.TL_inputStickerSetID && (set.id == 773947703670341676L || set.id == 2964141614563343L)
);
}
return false;
@ -812,6 +849,7 @@ public class AnimatedEmojiDrawable extends Drawable {
}
private static HashMap<Long, Integer> dominantColors;
public static int getDominantColor(AnimatedEmojiDrawable yourDrawable) {
if (yourDrawable == null) {
return 0;
@ -868,6 +906,7 @@ public class AnimatedEmojiDrawable extends Drawable {
}
private int alpha = 255;
@Override
public void setAlpha(int alpha) {
this.alpha = alpha;
@ -945,6 +984,7 @@ public class AnimatedEmojiDrawable extends Drawable {
private Integer lastColor;
private ColorFilter colorFilter;
public void setColor(Integer color) {
if (lastColor == null && color == null || lastColor != null && lastColor.equals(color)) {
return;
@ -967,17 +1007,17 @@ public class AnimatedEmojiDrawable extends Drawable {
drawables[1].setBounds(bounds);
} else if (center) {
drawables[1].setBounds(
bounds.centerX() - drawables[1].getIntrinsicWidth() / 2,
bounds.centerY() - drawables[1].getIntrinsicHeight() / 2,
bounds.centerX() + drawables[1].getIntrinsicWidth() / 2,
bounds.centerY() + drawables[1].getIntrinsicHeight() / 2
bounds.centerX() - drawables[1].getIntrinsicWidth() / 2,
bounds.centerY() - drawables[1].getIntrinsicHeight() / 2,
bounds.centerX() + drawables[1].getIntrinsicWidth() / 2,
bounds.centerY() + drawables[1].getIntrinsicHeight() / 2
);
} else { // left
drawables[1].setBounds(
bounds.left,
bounds.centerY() - drawables[1].getIntrinsicHeight() / 2,
bounds.left + drawables[1].getIntrinsicWidth(),
bounds.centerY() + drawables[1].getIntrinsicHeight() / 2
bounds.left,
bounds.centerY() - drawables[1].getIntrinsicHeight() / 2,
bounds.left + drawables[1].getIntrinsicWidth(),
bounds.centerY() + drawables[1].getIntrinsicHeight() / 2
);
}
drawables[1].setColorFilter(colorFilter);
@ -1001,10 +1041,10 @@ public class AnimatedEmojiDrawable extends Drawable {
canvas.scale(scale, scale, bounds.centerX(), bounds.centerY());
}
drawables[0].setBounds(
bounds.centerX() - drawables[0].getIntrinsicWidth() / 2,
bounds.centerY() - drawables[0].getIntrinsicHeight() / 2,
bounds.centerX() + drawables[0].getIntrinsicWidth() / 2,
bounds.centerY() + drawables[0].getIntrinsicHeight() / 2
bounds.centerX() - drawables[0].getIntrinsicWidth() / 2,
bounds.centerY() - drawables[0].getIntrinsicHeight() / 2,
bounds.centerX() + drawables[0].getIntrinsicWidth() / 2,
bounds.centerY() + drawables[0].getIntrinsicHeight() / 2
);
} else { // left
if (progress < 1) {
@ -1012,10 +1052,10 @@ public class AnimatedEmojiDrawable extends Drawable {
canvas.scale(scale, scale, bounds.left + drawables[0].getIntrinsicWidth() / 2f, bounds.centerY());
}
drawables[0].setBounds(
bounds.left,
bounds.centerY() - drawables[0].getIntrinsicHeight() / 2,
bounds.left + drawables[0].getIntrinsicWidth(),
bounds.centerY() + drawables[0].getIntrinsicHeight() / 2
bounds.left,
bounds.centerY() - drawables[0].getIntrinsicHeight() / 2,
bounds.left + drawables[0].getIntrinsicWidth(),
bounds.centerY() + drawables[0].getIntrinsicHeight() / 2
);
}
drawables[0].setAlpha(alpha);
@ -1185,8 +1225,10 @@ public class AnimatedEmojiDrawable extends Drawable {
public void setAlpha(int i) {
alpha = i;
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {}
@Override
public int getOpacity() {
return PixelFormat.TRANSPARENT;

View file

@ -23,6 +23,7 @@ import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.Pair;
import android.view.Gravity;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
@ -35,6 +36,8 @@ import org.telegram.ui.ActionBar.Theme;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.IntStream;
public class AnimatedTextView extends View {
@ -352,6 +355,7 @@ public class AnimatedTextView extends View {
CharSequence to = splitByWords ? new WordSequence(currentText) : currentText;
diff(from, to, onEqualRegion, onNewPart, onOldPart);
// betterDiff(from, to, onEqualRegion, onNewPart, onOldPart);
if (this.currentParts == null || this.currentParts.length != currentParts.size()) {
this.currentParts = new Part[currentParts.size()];
@ -597,6 +601,81 @@ public class AnimatedTextView extends View {
return (a == null && b == null || a != null && b != null && a.charAt(aIndex) == b.charAt(bIndex));
}
private void betterDiff(final CharSequence oldText, final CharSequence newText,
RegionCallback onEqualPart, RegionCallback onNewPart, RegionCallback onOldPart) {
int m = oldText.length();
int n = newText.length();
int[][] dp = new int[m+1][n+1];
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
if (i == 0 || j == 0)
dp[i][j] = 0;
else if (partEquals(oldText, newText, i - 1, j - 1))
dp[i][j] = dp[i - 1][j - 1] + 1;
else
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
List<Runnable> parts = new ArrayList<>();
int i = m, j = n;
while (i > 0 && j > 0) {
if (partEquals(oldText, newText, i - 1, j - 1)) {
int start = i-1;
while (i > 1 && j > 1 && partEquals(oldText, newText, i - 2, j - 2)) {
i--;
j--;
}
final int end = i - 1;
parts.add(() -> onEqualPart.run(oldText.subSequence(end, start + 1), end, start + 1));
i--;
j--;
} else if (dp[i - 1][j] > dp[i][j - 1]) {
int start = i-1;
while (i > 1 && dp[i - 2][j] > dp[i - 1][j - 1]) {
i--;
}
final int end = i - 1;
parts.add(() -> onOldPart.run(oldText.subSequence(end, start + 1), end, start + 1));
i--;
} else {
int start = j - 1;
while (j > 1 && dp[i][j - 2] > dp[i - 1][j - 1]) {
j--;
}
final int end = j - 1;
parts.add(() -> onNewPart.run(newText.subSequence(end, start + 1), end, start + 1));
j--;
}
}
while (i > 0) {
final int start = i - 1;
while (i > 1 && dp[i - 2][j] >= dp[i - 1][j]) {
i--;
}
final int end = i - 1;
parts.add(() -> onOldPart.run(oldText.subSequence(end, start + 1), end, start + 1));
i--;
}
while (j > 0) {
final int start = j - 1;
while (j > 1 && dp[i][j - 2] >= dp[i][j - 1]) {
j--;
}
final int end = j - 1;
parts.add(() -> onNewPart.run(newText.subSequence(end, start + 1), end, start + 1));
j--;
}
Collections.reverse(parts);
for (Runnable part : parts) {
part.run();
}
}
private void diff(final CharSequence oldText, final CharSequence newText, RegionCallback onEqualPart, RegionCallback onNewPart, RegionCallback onOldPart) {
if (updateAll) {
onOldPart.run(oldText, 0, oldText.length());

View file

@ -41,7 +41,7 @@ public class BackupImageView extends View {
public BackupImageView(Context context) {
super(context);
imageReceiver = new ImageReceiver(this);
imageReceiver = createImageReciever();
imageReceiver.setAllowLoadingOnAttachedOnly(true);
imageReceiver.setDelegate((imageReceiver1, set, thumb, memCache) -> {
if (set && !thumb) {
@ -50,6 +50,10 @@ public class BackupImageView extends View {
});
}
protected ImageReceiver createImageReciever() {
return new ImageReceiver(this);
}
public void setBlurAllowed(boolean blurAllowed) {
if (attached) {
throw new IllegalStateException("You should call setBlurAllowed(...) only when detached!");

View file

@ -947,6 +947,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa
private void checkDirectory(File rootDir) {
File[] files = rootDir.listFiles();
File storiesDir = FileLoader.checkDirectory(FileLoader.MEDIA_DIR_STORIES);
if (files != null) {
for (int a = 0; a < files.length; a++) {
File file = files[a];
@ -954,6 +955,9 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa
checkDirectory(file);
continue;
}
if (file.equals(storiesDir)) {
continue;
}
ListItem item = new ListItem();
item.title = file.getName();
item.file = file;
@ -1165,11 +1169,17 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa
}
currentDir = dir;
listAdapter.items.clear();
File storiesDir = FileLoader.checkDirectory(FileLoader.MEDIA_DIR_STORIES);
for (int a = 0; a < files.length; a++) {
File file = files[a];
if (file.getName().indexOf('.') == 0) {
continue;
}
if (file.equals(storiesDir)) {
continue;
}
ListItem item = new ListItem();
item.title = file.getName();
item.file = file;

View file

@ -164,10 +164,10 @@ public class ChatScrimPopupContainerLayout extends LinearLayout {
updateBottomViewPosition();
}
public void setPopupAlpha(float aplha) {
popupWindowLayout.setAlpha(aplha);
public void setPopupAlpha(float alpha) {
popupWindowLayout.setAlpha(alpha);
if (bottomView != null) {
bottomView.setAlpha(aplha);
bottomView.setAlpha(alpha);
}
}

View file

@ -94,7 +94,7 @@ public class ColoredImageSpan extends ReplacementSpan {
canvas.save();
int transY = bottom - (drawable != null ? drawable.getBounds().bottom : bottom);
if (verticalAlignment == ALIGN_BASELINE) {
transY -= paint.getFontMetricsInt().descent;
// transY -= paint.getFontMetricsInt().descent;
} else if (verticalAlignment == ALIGN_CENTER) {
transY = top + (bottom - top) / 2 - (drawable != null ? drawable.getBounds().height() / 2 : 0);
} else if (verticalAlignment == ALIGN_DEFAULT) {

View file

@ -451,6 +451,9 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen
}
public void updateMatrix(boolean force) {
if (state == null) {
return;
}
overlayMatrix.reset();
if (state.getBaseRotation() == 90 || state.getBaseRotation() == 270) {
overlayMatrix.postTranslate(-state.getHeight() / 2, -state.getWidth() / 2);

View file

@ -9,6 +9,8 @@ import android.text.TextPaint;
import android.text.style.CharacterStyle;
import android.view.View;
import org.telegram.ui.Components.Reactions.HwEmojis;
import java.util.ArrayList;
public class EllipsizeSpanAnimator {
@ -81,7 +83,9 @@ public class EllipsizeSpanAnimator {
a.addUpdateListener(valueAnimator -> {
target.setAlpha((int) valueAnimator.getAnimatedValue());
for (int i = 0; i < ellipsizedViews.size(); i++) {
ellipsizedViews.get(i).invalidate();
if (!HwEmojis.isHwEnabled()) {
ellipsizedViews.get(i).invalidate();
}
}
});
a.setDuration(duration);

View file

@ -37,6 +37,7 @@ import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.Premium.PremiumLockIconView;
import org.telegram.ui.Components.Reactions.HwEmojis;
import org.telegram.ui.SelectAnimatedEmojiDialog;
import java.util.ArrayList;
@ -127,7 +128,7 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView {
child.setScaleX(0);
child.setScaleY(0);
child.setAlpha(0);
child.animate().scaleX(1f).scaleY(1f).alpha(1f).setDuration(200).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start();
child.animate().scaleX(1f).scaleY(1f).alpha(1f).setDuration(HwEmojis.isHwEnabledOrPreparing() ? 0 : 200).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).start();
}
if (id != null) {
if (lastX.get(id) != null && lastX.get(id) != x) {
@ -313,6 +314,17 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView {
}
}
public void showRecentTabStub(boolean show) {
if (recentTab == null) {
return;
}
if (show) {
recentTab.setBackground(new StabDrawable(selectorColor()));
} else {
recentTab.setBackground(null);
}
}
public void showSelected(boolean show) {
this.showSelected = show;
this.contentView.invalidate();
@ -372,6 +384,37 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView {
return null;
}
private static class StabDrawable extends Drawable {
private final Paint paint = new Paint();
private final RectF rectF = new RectF();
public StabDrawable(int color){
paint.setAlpha(45);
paint.setColor(color);
}
@Override
public void draw(@NonNull Canvas canvas) {
rectF.set(0, 0, AndroidUtilities.dp(30), AndroidUtilities.dp(30));
canvas.drawRoundRect(rectF, AndroidUtilities.dpf2(8), AndroidUtilities.dpf2(8), paint);
}
@Override
public void setAlpha(int alpha) {
paint.setAlpha(alpha);
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
private static class DelayedAnimatedEmojiDrawable extends Drawable {
int account;
@ -678,7 +721,7 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView {
if (settingsTab != null) {
settingsTab.bringToFront();
if (settingsTab.getAlpha() < 1) {
settingsTab.animate().alpha(1f).setDuration(200).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
settingsTab.animate().alpha(1f).setDuration(HwEmojis.isHwEnabledOrPreparing() ? 0 : 200).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
}
}
// if (doAppearAnimation) {
@ -935,10 +978,21 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView {
imageView = new ImageView(context) {
@Override
public void invalidate() {
if (HwEmojis.grab(this)) {
return;
}
super.invalidate();
updateLockImageReceiver();
}
@Override
public void invalidate(int l, int t, int r, int b) {
if (HwEmojis.grab(this)) {
return;
}
super.invalidate(l, t, r, b);
}
@Override
protected void onDraw(Canvas canvas) {
@ -966,7 +1020,23 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView {
}
addView(imageView);
lockView = new PremiumLockIconView(context, PremiumLockIconView.TYPE_STICKERS_PREMIUM_LOCKED, resourcesProvider);
lockView = new PremiumLockIconView(context, PremiumLockIconView.TYPE_STICKERS_PREMIUM_LOCKED, resourcesProvider) {
@Override
public void invalidate() {
if (HwEmojis.grab(this)) {
return;
}
super.invalidate();
}
@Override
public void invalidate(int l, int t, int r, int b) {
if (HwEmojis.grab(this)) {
return;
}
super.invalidate(l, t, r, b);
}
};
lockView.setAlpha(0f);
lockView.setScaleX(0);
lockView.setScaleY(0);
@ -976,6 +1046,22 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView {
setColor(Theme.getColor(Theme.key_chat_emojiPanelIcon, resourcesProvider));
}
@Override
public void invalidate() {
if (HwEmojis.grab(this)) {
return;
}
super.invalidate();
}
@Override
public void invalidate(int l, int t, int r, int b) {
if (HwEmojis.grab(this)) {
return;
}
super.invalidate(l, t, r, b);
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
@ -1116,7 +1202,7 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView {
}
});
lockAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT);
lockAnimator.setDuration(200);
lockAnimator.setDuration(HwEmojis.isHwEnabledOrPreparing() ? 0 : 200);
lockAnimator.start();
}
@ -1175,7 +1261,7 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView {
if (animatedEmoji != null && attached && wasVisible) {
animatedEmoji.updateView(imageView);
}
if (wasVisible) {
if (wasVisible && animatedEmoji != null) {
animatedEmoji.load();
}
initLock();
@ -1250,7 +1336,7 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView {
}
}
});
selectAnimator.setDuration(350);
selectAnimator.setDuration(HwEmojis.isHwEnabledOrPreparing() ? 0 : 350);
selectAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT);
selectAnimator.start();
} else {

View file

@ -155,6 +155,8 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
private final static int TAB_GIFS = 1;
private final static int TAB_STICKERS = 2;
public int emojiCacheType = AnimatedEmojiDrawable.CACHE_TYPE_KEYBOARD;
private ArrayList<Tab> allTabs = new ArrayList<>();
private ArrayList<Tab> currentTabs = new ArrayList<>();
private boolean ignorePagerScroll;
@ -2838,7 +2840,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
}
public void updateEmojiDrawables() {
animatedEmojiDrawables = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_KEYBOARD, this, getAnimatedEmojiSpans(), animatedEmojiDrawables);
animatedEmojiDrawables = AnimatedEmojiSpan.update(emojiCacheType, this, getAnimatedEmojiSpans(), animatedEmojiDrawables);
}
@Override

View file

@ -79,6 +79,7 @@ import org.telegram.messenger.BuildVars;
import org.telegram.messenger.DispatchQueue;
import org.telegram.messenger.FileLoader;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.ImageLoader;
import org.telegram.messenger.ImageReceiver;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaController;
@ -103,6 +104,7 @@ import org.telegram.ui.Components.voip.CellFlickerDrawable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@ -123,6 +125,8 @@ import javax.microedition.khronos.egl.EGLSurface;
@TargetApi(18)
public class InstantCameraView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate {
public boolean WRITE_TO_FILE_IN_BACKGROUND = true;
private int currentAccount = UserConfig.selectedAccount;
private InstantViewCameraContainer cameraContainer;
private Delegate delegate;
@ -1730,6 +1734,8 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
private static final int IFRAME_INTERVAL = 1;
private File videoFile;
private File fileToWrite;
private boolean writingToDifferentFile;
private int videoWidth;
private int videoHeight;
private int videoBitrate;
@ -2302,6 +2308,18 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
} catch (InterruptedException e) {
e.printStackTrace();
}
if (writingToDifferentFile) {
if (!fileToWrite.renameTo(videoFile)) {
FileLog.e("unable to rename file, try move file");
try {
AndroidUtilities.copyFile(fileToWrite, videoFile);
fileToWrite.delete();
} catch (IOException e) {
FileLog.e(e);
FileLog.e("unable to move file");
}
}
}
}
if (generateKeyframeThumbsQueue != null) {
generateKeyframeThumbsQueue.cleanupQueue();
@ -2394,7 +2412,16 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
});
} else {
FileLoader.getInstance(currentAccount).cancelFileUpload(videoFile.getAbsolutePath(), false);
videoFile.delete();
try {
fileToWrite.delete();
} catch (Throwable ignore) {
}
try {
videoFile.delete();
} catch (Throwable ignore) {
}
}
EGL14.eglDestroySurface(eglDisplay, eglSurface);
eglSurface = EGL14.EGL_NO_SURFACE;
@ -2491,8 +2518,23 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
surface = videoEncoder.createInputSurface();
videoEncoder.start();
boolean isSdCard = ImageLoader.isSdCardPath(videoFile);
fileToWrite = videoFile;
if (isSdCard) {
try {
fileToWrite = new File(ApplicationLoader.getFilesDirFixed(), "camera_tmp.mp4");
if (fileToWrite.exists()) {
fileToWrite.delete();
}
writingToDifferentFile = true;
} catch (Throwable e) {
FileLog.e(e);
fileToWrite = videoFile;
writingToDifferentFile = false;
}
}
Mp4Movie movie = new Mp4Movie();
movie.setCacheFile(videoFile);
movie.setCacheFile(fileToWrite);
movie.setRotation(0);
movie.setSize(videoWidth, videoHeight);
mediaMuxer = new MP4Builder().createMovie(movie, isSecretChat, false);
@ -2684,31 +2726,30 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
}
firstEncode = false;
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
bufferInfo.size = videoBufferInfo.size;
bufferInfo.offset = videoBufferInfo.offset;
bufferInfo.flags = videoBufferInfo.flags;
bufferInfo.presentationTimeUs = videoBufferInfo.presentationTimeUs;
needReleaseBuffers = false;
fileWriteQueue.postRunnable(() -> {
long availableSize = 0;
try {
availableSize = mediaMuxer.writeSampleData(videoTrackIndex, encodedData, bufferInfo, true);
} catch (Exception e) {
e.printStackTrace();
}
MediaCodec videoEncoder = VideoRecorder.this.videoEncoder;
if (videoEncoder != null) {
if (WRITE_TO_FILE_IN_BACKGROUND) {
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
bufferInfo.size = videoBufferInfo.size;
bufferInfo.offset = videoBufferInfo.offset;
bufferInfo.flags = videoBufferInfo.flags;
bufferInfo.presentationTimeUs = videoBufferInfo.presentationTimeUs;
ByteBuffer byteBuffer = encodedData.duplicate();
fileWriteQueue.postRunnable(() -> {
long availableSize = 0;
try {
videoEncoder.releaseOutputBuffer(encoderStatus, false);
} catch (Throwable e) {
//ignore IllegalStateException if codec released
availableSize = mediaMuxer.writeSampleData(videoTrackIndex, byteBuffer, bufferInfo, true);
} catch (Exception e) {
e.printStackTrace();
}
}
if (availableSize != 0) {
if (availableSize != 0 && !writingToDifferentFile) {
didWriteData(videoFile, availableSize, false);
}
});
} else {
long availableSize = mediaMuxer.writeSampleData(videoTrackIndex, encodedData, videoBufferInfo, true);
if (availableSize != 0 && !writingToDifferentFile) {
didWriteData(videoFile, availableSize, false);
}
});
}
} else if (videoTrackIndex == -5) {
byte[] csd = new byte[videoBufferInfo.size];
encodedData.limit(videoBufferInfo.offset + videoBufferInfo.size);
@ -2780,31 +2821,33 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
audioBufferInfo.size = 0;
}
if (audioBufferInfo.size != 0) {
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
bufferInfo.size = audioBufferInfo.size;
bufferInfo.offset = audioBufferInfo.offset;
bufferInfo.flags = audioBufferInfo.flags;
bufferInfo.presentationTimeUs = audioBufferInfo.presentationTimeUs;
fileWriteQueue.postRunnable(() -> {
long availableSize = 0;
try {
availableSize = mediaMuxer.writeSampleData(audioTrackIndex, encodedData, bufferInfo, false);
} catch (Exception e) {
e.printStackTrace();
}
if (availableSize != 0) {
if (WRITE_TO_FILE_IN_BACKGROUND) {
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
bufferInfo.size = audioBufferInfo.size;
bufferInfo.offset = audioBufferInfo.offset;
bufferInfo.flags = audioBufferInfo.flags;
bufferInfo.presentationTimeUs = audioBufferInfo.presentationTimeUs;
ByteBuffer byteBuffer = encodedData.duplicate();
fileWriteQueue.postRunnable(() -> {
long availableSize = 0;
try {
availableSize = mediaMuxer.writeSampleData(audioTrackIndex, byteBuffer, bufferInfo, false);
} catch (Exception e) {
e.printStackTrace();
}
if (availableSize != 0 && !writingToDifferentFile) {
didWriteData(videoFile, availableSize, false);
}
});
audioEncoder.releaseOutputBuffer(encoderStatus, false);
} else {
long availableSize = mediaMuxer.writeSampleData(audioTrackIndex, encodedData, audioBufferInfo, false);
if (availableSize != 0 && !writingToDifferentFile) {
didWriteData(videoFile, availableSize, false);
}
MediaCodec audioEncoder = VideoRecorder.this.audioEncoder;
if (audioEncoder != null) {
try {
audioEncoder.releaseOutputBuffer(encoderStatus, false);
} catch (Throwable e) {
//ignore IllegalStateException if codec released
}
}
});
} else {
audioEncoder.releaseOutputBuffer(encoderStatus, false);
}
} else if (audioEncoder != null) {
audioEncoder.releaseOutputBuffer(encoderStatus, false);
}
if ((audioBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {

View file

@ -28,6 +28,7 @@ import androidx.core.graphics.ColorUtils;
import com.google.android.exoplayer2.util.Consumer;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.R;
import org.telegram.ui.ActionBar.ActionBarMenuSubItem;
import org.telegram.ui.ActionBar.ActionBarPopupWindow;
@ -153,7 +154,7 @@ public class ItemOptions {
}
ActionBarMenuSubItem subItem = new ActionBarMenuSubItem(context, false, false, resourcesProvider);
subItem.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18 + 8), 0);
subItem.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18 + (LocaleController.isRTL ? 0 : 8)), 0);
subItem.setTextAndIcon(text, iconResId);
subItem.setColors(Theme.getColor(textColorKey, resourcesProvider), Theme.getColor(iconColorKey, resourcesProvider));

View file

@ -129,7 +129,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
public boolean onFragmentCreate() {
type = getArguments().getInt("type", TYPE_MEDIA);
dialogId = getArguments().getLong("dialog_id");
initialTab = getArguments().getInt("start_from", SharedMediaLayout.TAB_STORIES);
initialTab = getArguments().getInt("start_from", type == TYPE_MEDIA ? SharedMediaLayout.TAB_PHOTOVIDEO : SharedMediaLayout.TAB_STORIES);
getNotificationCenter().addObserver(this, NotificationCenter.userInfoDidLoad);
getNotificationCenter().addObserver(this, NotificationCenter.currentUserPremiumStatusChanged);
getNotificationCenter().addObserver(this, NotificationCenter.storiesEnabledUpdate);
@ -612,6 +612,11 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
return type == TYPE_STORIES;
}
@Override
protected boolean includeStories() {
return type == TYPE_STORIES;
}
@Override
protected int getInitialTab() {
return initialTab;

View file

@ -141,7 +141,12 @@ public class PersistColorPalette {
public int getColor(int index) {
checkIndex(index);
if (index < 0 || index >= colors.size()) {
if (index >= 0 && index < DEFAULT_COLORS.size()) {
return DEFAULT_COLORS.get(index);
}
return DEFAULT_COLORS.get(0);
}
return colors.get(index);
}
@ -155,12 +160,18 @@ public class PersistColorPalette {
pendingChange.clear();
pendingChange.add(color);
pendingChange.addAll(from);
pendingChange.remove(pendingChange.size() - 1);
if (pendingChange.size() < DEFAULT_COLORS.size()) {
for (int j = pendingChange.size(); j < DEFAULT_COLORS.size(); ++j) {
pendingChange.add(DEFAULT_COLORS.get(j));
}
} else if (pendingChange.size() > DEFAULT_COLORS.size()) {
pendingChange = pendingChange.subList(0, DEFAULT_COLORS.size());
}
}
}
public void selectColorIndex(int index) {
int color = colors.get(index);
int color = index < 0 || index >= colors.size() ? DEFAULT_COLORS.get(index) : colors.get(index);
List<Integer> from = new ArrayList<>(pendingChange.isEmpty() ? colors : pendingChange);
pendingChange.clear();
pendingChange.add(color);
@ -171,6 +182,13 @@ public class PersistColorPalette {
pendingChange.add(from.get(i));
}
}
if (pendingChange.size() < DEFAULT_COLORS.size()) {
for (int j = pendingChange.size(); j < DEFAULT_COLORS.size(); ++j) {
pendingChange.add(DEFAULT_COLORS.get(j));
}
} else if (pendingChange.size() > DEFAULT_COLORS.size()) {
pendingChange = pendingChange.subList(0, DEFAULT_COLORS.size());
}
}
private void loadColors() {

View file

@ -228,8 +228,11 @@ public class EditTextOutline extends EditTextBoldCursor {
}
if (traceback) {
for (int j = i; j >= 1; --j) {
above = lines[i - 1];
above = lines[j - 1];
line = lines[j];
if (above.width() < dp(1) || line.width() < dp(1)) {
continue;
}
if (Math.abs(above.left - line.left) < mr) {
line.left = above.left = Math.min(line.left, above.left);
}

View file

@ -27,6 +27,7 @@ import org.telegram.messenger.ImageReceiver;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.VideoEditedInfo;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.Paint.Views.EditTextOutline;
import org.telegram.ui.Components.Paint.Views.PaintTextOptionsView;
@ -252,22 +253,22 @@ public class PaintingOverlay extends FrameLayout {
if (Build.VERSION.SDK_INT >= 23) {
editText.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE);
}
if ((entity.subType & 1) != 0) {
editText.setTextColor(0xffffffff);
editText.setStrokeColor(entity.color);
editText.setFrameColor(0);
editText.setShadowLayer(0, 0, 0, 0);
} else if ((entity.subType & 4) != 0) {
editText.setTextColor(0xff000000);
editText.setStrokeColor(0);
editText.setShadowLayer(0, 0, 0, 0);
int textColor = entity.color;
if (entity.subType == 0) {
editText.setFrameColor(entity.color);
editText.setShadowLayer(0, 0, 0, 0);
textColor = AndroidUtilities.computePerceivedBrightness(entity.color) >= .721f ? Color.BLACK : Color.WHITE;
} else if (entity.subType == 1) {
editText.setFrameColor(AndroidUtilities.computePerceivedBrightness(entity.color) >= .25f ? 0x99000000 : 0x99ffffff);
} else if (entity.subType == 2) {
editText.setFrameColor(AndroidUtilities.computePerceivedBrightness(entity.color) >= .25f ? Color.BLACK : Color.WHITE);
} else {
editText.setTextColor(entity.color);
editText.setStrokeColor(0);
editText.setFrameColor(0);
editText.setShadowLayer(5, 0, 1, 0x66000000);
}
editText.setTextColor(textColor);
editText.setCursorColor(textColor);
editText.setHandlesColor(textColor);
editText.setHighlightColor(Theme.multAlpha(textColor, .4f));
entity.view = child = editText;
}
if (child != null) {

View file

@ -623,6 +623,8 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica
return -10177041;
} else if (key == Theme.key_dialogFloatingIcon) {
return 0xffffffff;
} else if (key == Theme.key_chat_emojiPanelStickerSetName) {
return 0x73ffffff;
}
return 0;
}
@ -637,6 +639,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica
return;
}
emojiView = new EmojiView(null, true, false, false, getContext(), false, null, null, true, resourcesProvider);
emojiView.emojiCacheType = AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW;
emojiView.setDelegate(new EmojiView.EmojiViewDelegate() {
@Override
public boolean onBackspace() {
@ -712,6 +715,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica
}
if (!isRecent) {
span.fromEmojiKeyboard = true;
span.cacheType = AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW;
}
spannable.setSpan(span, 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
messageEditText.setText(messageEditText.getText().insert(i, spannable));

View file

@ -70,6 +70,7 @@ public class PremiumButtonView extends FrameLayout {
LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
buttonTextView = new AnimatedTextView(context);
buttonTextView.setAnimationProperties(.35f, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
buttonTextView.setGravity(Gravity.CENTER);
buttonTextView.setTextColor(Color.WHITE);
buttonTextView.setTextSize(AndroidUtilities.dp(14));

View file

@ -7,6 +7,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
@ -15,10 +16,12 @@ import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.view.WindowManager;
import android.view.animation.OvershootInterpolator;
import android.widget.FrameLayout;
@ -43,9 +46,11 @@ import org.telegram.ui.ChatActivity;
import org.telegram.ui.Components.Bulletin;
import org.telegram.ui.Components.BulletinFactory;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.EmojiTabsStrip;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet;
import org.telegram.ui.Components.ReactionsContainerLayout;
import org.telegram.ui.Components.StableAnimator;
import org.telegram.ui.LaunchActivity;
import org.telegram.ui.PremiumPreviewFragment;
import org.telegram.ui.SelectAnimatedEmojiDialog;
@ -70,7 +75,7 @@ public class CustomEmojiReactionsWindow {
SelectAnimatedEmojiDialog selectAnimatedEmojiDialog;
ReactionsContainerLayout reactionsContainerLayout;
Path pathToClip = new Path();
private final Path pathToClipApi20 = new Path();
private boolean invalidatePath;
List<ReactionsLayoutInBubble.VisibleReaction> reactions;
@ -199,6 +204,24 @@ public class CustomEmojiReactionsWindow {
containerView.invalidate();
}
};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
selectAnimatedEmojiDialog.setOutlineProvider(new ViewOutlineProvider() {
final Rect rect = new Rect();
final RectF rectTmp = new RectF();
final RectF rectF = new RectF();
@Override
public void getOutline(View view, Outline outline) {
float radius = AndroidUtilities.lerp(fromRadius, AndroidUtilities.dp(8), enterTransitionProgress);
rectTmp.set(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
AndroidUtilities.lerp(fromRect, rectTmp, enterTransitionProgress, rectF);
rectF.round(rect);
outline.setRoundRect(rect, radius);
}
});
selectAnimatedEmojiDialog.setClipToOutline(true);
}
selectAnimatedEmojiDialog.setOnLongPressedListener(new SelectAnimatedEmojiDialog.onLongPressedListener() {
@Override
public void onLongPressed(SelectAnimatedEmojiDialog.ImageViewEmoji view) {
@ -234,6 +257,7 @@ public class CustomEmojiReactionsWindow {
windowManager.addView(windowView, lp);
this.reactionsContainerLayout = reactionsContainerLayout;
reactionsContainerLayout.setOnSwitchedToLoopView(() -> containerView.invalidate()); //fixed emoji freeze
reactionsContainerLayout.prepareAnimation(true);
AndroidUtilities.runOnUIThread(() -> {
isShowing = true;
@ -333,50 +357,57 @@ public class CustomEmojiReactionsWindow {
cascadeAnimation = false;
}
if (cascadeAnimation) {
updateCascadeEnter(0);
updateCascadeEnter(0, true);
}
updateContainersAlpha();
selectAnimatedEmojiDialog.setEnterAnimationInProgress(true);
selectAnimatedEmojiDialog.emojiTabs.showRecentTabStub(enter && cascadeAnimation);
account = UserConfig.selectedAccount;
notificationsLocker.lock();
valueAnimator = ValueAnimator.ofFloat(enterTransitionProgress, enter ? 1f : 0);
valueAnimator = StableAnimator.ofFloat(enterTransitionProgress, enter ? 1f : 0);
valueAnimator.addUpdateListener(animation -> {
valueAnimator = null;
enterTransitionProgress = (float) animation.getAnimatedValue();
reactionsContainerLayout.setCustomEmojiEnterProgress(Utilities.clamp(enterTransitionProgress,1f, 0));
updateContainersAlpha();
updateContentPosition();
reactionsContainerLayout.setCustomEmojiEnterProgress(Utilities.clamp(enterTransitionProgress, 1f, 0));
invalidatePath = true;
containerView.invalidate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
selectAnimatedEmojiDialog.invalidateOutline();
}
if (cascadeAnimation) {
updateCascadeEnter(enterTransitionProgress);
updateCascadeEnter(enterTransitionProgress, enter);
}
});
if (!enter) {
syncReactionFrames(enter);
syncReactionFrames();
}
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
checkAnimationEnd();
updateContainersAlpha();
updateContentPosition();
checkAnimationEnd(enter);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
selectAnimatedEmojiDialog.invalidateOutline();
}
enterTransitionProgress = enter ? 1f : 0f;
if (enter) {
enterTransitionFinished = true;
selectAnimatedEmojiDialog.resetBackgroundBitmaps();
reactionsContainerLayout.onCustomEmojiWindowOpened();
containerView.invalidate();
}
reactionsContainerLayout.setCustomEmojiEnterProgress(Utilities.clamp(enterTransitionProgress, 1f, 0f));
if (enter) {
syncReactionFrames(enter);
}
if (!enter) {
reactionsContainerLayout.setSkipDraw(false);
}
if (!enter) {
removeView();
Runtime.getRuntime().gc(); //to prevent garbage collection when reopening
reactionsContainerLayout.setCustomEmojiReactionsBackground(true);
}
}
});
valueAnimator.setStartDelay(30);
if (cascadeAnimation) {
valueAnimator.setDuration(450);
valueAnimator.setInterpolator(new OvershootInterpolator(0.5f));
@ -384,15 +415,68 @@ public class CustomEmojiReactionsWindow {
valueAnimator.setDuration(350);
valueAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT);
}
valueAnimator.start();
containerView.invalidate();
switchLayerType(true);
if (!enter) {
reactionsContainerLayout.isHiddenNextReaction = true;
reactionsContainerLayout.invalidate();
valueAnimator.setStartDelay(30);
valueAnimator.start();
} else {
reactionsContainerLayout.setCustomEmojiReactionsBackground(false);
final ValueAnimator finalAnimator = valueAnimator;
HwEmojis.prepare(finalAnimator::start, cascadeAnimation);
}
HwEmojis.enableHw();
}
private void updateContainersAlpha() {
if (!cascadeAnimation) {
selectAnimatedEmojiDialog.searchBox.setAlpha(enterTransitionProgress);
selectAnimatedEmojiDialog.emojiGridView.setAlpha(enterTransitionProgress);
selectAnimatedEmojiDialog.emojiSearchGridView.setAlpha(enterTransitionProgress);
selectAnimatedEmojiDialog.emojiTabs.setAlpha(enterTransitionProgress);
selectAnimatedEmojiDialog.emojiTabsShadow.setAlpha(enterTransitionProgress);
}
}
private void updateContentPosition() {
selectAnimatedEmojiDialog.contentView.setTranslationX(cascadeAnimation ? 0 : containerView.enterTransitionOffsetX);
selectAnimatedEmojiDialog.contentView.setTranslationY(containerView.enterTransitionOffsetY);
selectAnimatedEmojiDialog.contentView.setPivotX(containerView.enterTransitionScalePx);
selectAnimatedEmojiDialog.contentView.setPivotY(containerView.enterTransitionScalePy);
selectAnimatedEmojiDialog.contentView.setScaleX(containerView.enterTransitionScale);
selectAnimatedEmojiDialog.contentView.setScaleY(containerView.enterTransitionScale);
}
private void switchLayerType(boolean hardware) {
int layerType = hardware ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE;
selectAnimatedEmojiDialog.emojiGridView.setLayerType(layerType, null);
selectAnimatedEmojiDialog.searchBox.setLayerType(layerType, null);
if (cascadeAnimation) {
for (int i = 0; i < Math.min(selectAnimatedEmojiDialog.emojiTabs.contentView.getChildCount(), 16); i++) {
View child = selectAnimatedEmojiDialog.emojiTabs.contentView.getChildAt(i);
child.setLayerType(layerType, null);
}
} else {
selectAnimatedEmojiDialog.emojiTabsShadow.setLayerType(layerType, null);
selectAnimatedEmojiDialog.emojiTabs.setLayerType(layerType, null);
}
}
HashSet<View> animatingEnterChild = new HashSet<>();
ArrayList<ValueAnimator> animators = new ArrayList<>();
private void updateCascadeEnter(float progress) {
int fullHeight = selectAnimatedEmojiDialog.contentView.getHeight();
private void setScaleForChild(View child, float value) {
if (child instanceof SelectAnimatedEmojiDialog.ImageViewEmoji) {
((SelectAnimatedEmojiDialog.ImageViewEmoji) child).setAnimatedScale(value);
} else if (child instanceof EmojiTabsStrip.EmojiTabButton) {
child.setScaleX(value);
child.setScaleY(value);
}
}
private void updateCascadeEnter(float progress, boolean enter) {
int parentTop = (int) (selectAnimatedEmojiDialog.getY() + selectAnimatedEmojiDialog.contentView.getY() + selectAnimatedEmojiDialog.emojiGridView.getY());
ArrayList<View> animatedViews = null;
boolean updated = false;
@ -409,8 +493,7 @@ public class CustomEmojiReactionsWindow {
animatedViews.add(child);
animatingEnterChild.add(child);
} else {
child.setScaleX(0f);
child.setScaleY(0f);
setScaleForChild(child, 0f);
updated = true;
}
}
@ -428,15 +511,12 @@ public class CustomEmojiReactionsWindow {
animatedViews.add(child);
animatingEnterChild.add(child);
} else {
child.setScaleX(0f);
child.setScaleY(0f);
setScaleForChild(child, 0f);
updated = true;
}
}
if (updated) {
selectAnimatedEmojiDialog.emojiGridView.invalidate();
selectAnimatedEmojiDialog.contentView.invalidate();
selectAnimatedEmojiDialog.emojiTabs.contentView.invalidate();
selectAnimatedEmojiDialog.emojiGridViewContainer.invalidate();
}
if (animatedViews != null) {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1f);
@ -444,12 +524,10 @@ public class CustomEmojiReactionsWindow {
valueAnimator.addUpdateListener(animation -> {
float s = (float) animation.getAnimatedValue();
for (int i = 0; i < finalAnimatedViews.size(); i++) {
finalAnimatedViews.get(i).setScaleX(s);
finalAnimatedViews.get(i).setScaleY(s);
View v = finalAnimatedViews.get(i);
setScaleForChild(v, s);
}
selectAnimatedEmojiDialog.emojiGridView.invalidate();
selectAnimatedEmojiDialog.contentView.invalidate();
selectAnimatedEmojiDialog.emojiTabs.contentView.invalidate();
selectAnimatedEmojiDialog.emojiGridViewContainer.invalidate();
});
animators.add(valueAnimator);
valueAnimator.addListener(new AnimatorListenerAdapter() {
@ -457,7 +535,7 @@ public class CustomEmojiReactionsWindow {
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
animators.remove(valueAnimator);
checkAnimationEnd();
checkAnimationEnd(enter);
}
});
valueAnimator.setDuration(350);
@ -466,16 +544,32 @@ public class CustomEmojiReactionsWindow {
}
}
private void checkAnimationEnd() {
private void checkAnimationEnd(boolean enter) {
if (animators.isEmpty()) {
switchLayerType(false);
HwEmojis.disableHw();
notificationsLocker.unlock();
selectAnimatedEmojiDialog.setEnterAnimationInProgress(false);
if (enter) {
selectAnimatedEmojiDialog.emojiTabs.showRecentTabStub(false);
selectAnimatedEmojiDialog.emojiGridView.invalidate();
selectAnimatedEmojiDialog.emojiGridView.invalidateViews();
selectAnimatedEmojiDialog.searchBox.checkInitialization();
if (reactionsContainerLayout.getPullingLeftProgress() > 0) {
reactionsContainerLayout.isHiddenNextReaction = false;
reactionsContainerLayout.onCustomEmojiWindowOpened();
} else {
reactionsContainerLayout.isHiddenNextReaction = true;
reactionsContainerLayout.onCustomEmojiWindowOpened();
}
selectAnimatedEmojiDialog.resetBackgroundBitmaps();
syncReactionFrames();
containerView.invalidate();
}
}
}
private void syncReactionFrames(boolean enter) {
HashMap<ReactionsLayoutInBubble.VisibleReaction, SelectAnimatedEmojiDialog.ImageViewEmoji> transitionReactions = new HashMap<>();
private void syncReactionFrames() {
for (int i = 0; i < selectAnimatedEmojiDialog.emojiGridView.getChildCount(); i++) {
if (selectAnimatedEmojiDialog.emojiGridView.getChildAt(i) instanceof SelectAnimatedEmojiDialog.ImageViewEmoji) {
SelectAnimatedEmojiDialog.ImageViewEmoji imageViewEmoji = (SelectAnimatedEmojiDialog.ImageViewEmoji) selectAnimatedEmojiDialog.emojiGridView.getChildAt(i);
@ -562,7 +656,7 @@ public class CustomEmojiReactionsWindow {
windowView.animate().alpha(0).setDuration(150).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
checkAnimationEnd();
checkAnimationEnd(false);
enterTransitionProgress = 0f;
reactionsContainerLayout.setCustomEmojiEnterProgress(Utilities.clamp(enterTransitionProgress, 1f, 0f));
reactionsContainerLayout.setSkipDraw(false);
@ -620,6 +714,12 @@ public class CustomEmojiReactionsWindow {
HashMap<ReactionsLayoutInBubble.VisibleReaction, SelectAnimatedEmojiDialog.ImageViewEmoji> transitionReactions = new HashMap<>();
float enterTransitionOffsetX = 0;
float enterTransitionOffsetY = 0;
float enterTransitionScale = 1f;
float enterTransitionScalePx = 0;
float enterTransitionScalePy = 0;
@Override
protected void dispatchDraw(Canvas canvas) {
if (!isShowing) {
@ -649,11 +749,11 @@ public class CustomEmojiReactionsWindow {
reactionsContainerLayout.drawBubbles(canvas);
canvas.restore();
}
float enterTransitionOffsetX = 0;
float enterTransitionOffsetY = 0;
float enterTransitionScale = 1f;
float enterTransitionScalePx = 0;
float enterTransitionScalePy = 0;
enterTransitionOffsetX = 0;
enterTransitionOffsetY = 0;
enterTransitionScale = 1f;
enterTransitionScalePx = 0;
enterTransitionScalePy = 0;
if (reactionsContainerLayout != null) {
for (int i = 0; i < selectAnimatedEmojiDialog.emojiGridView.getChildCount(); i++) {
@ -669,7 +769,8 @@ public class CustomEmojiReactionsWindow {
canvas.translate(drawingRect.left, drawingRect.top + reactionsContainerLayout.expandSize() * (1f - enterTransitionProgress));
float alpha = Math.max(selectAnimatedEmojiDialog.emojiGridView.getAlpha(), 1f - enterTransitionProgress);
float a = selectAnimatedEmojiDialog.emojiSearchGridView.getVisibility() == View.VISIBLE ? selectAnimatedEmojiDialog.emojiSearchGridView.getAlpha() : 0;
float alpha = Math.max(1f - a, 1f - enterTransitionProgress);
if (alpha != 1f) {
canvas.saveLayerAlpha(0, 0, drawingRect.width(), drawingRect.height(), (int) (255 * alpha), Canvas.ALL_SAVE_FLAG);
}
@ -678,9 +779,6 @@ public class CustomEmojiReactionsWindow {
canvas.clipRect(left, top + AndroidUtilities.dp(36) * enterTransitionProgress, left + selectAnimatedEmojiDialog.emojiGridView.getMeasuredHeight(), top + selectAnimatedEmojiDialog.emojiGridView.getMeasuredWidth());
for (int i = -1; i < reactionsContainerLayout.recyclerListView.getChildCount(); i++) {
View child;
if (enterTransitionProgress == 1 && i == -1) {
continue;
}
if (i == -1) {
child = reactionsContainerLayout.nextRecentReaction;
} else {
@ -802,6 +900,9 @@ public class CustomEmojiReactionsWindow {
imageReceiver.setAlpha(oldAlpha);
}
}
if (holderView.loopImageView.getVisibility() != View.VISIBLE) {
invalidate();
}
} else {
canvas.translate(child.getX() + drawingRect.width() - reactionsContainerLayout.rect.width(), child.getY() + fromRect.top - drawingRect.top);
canvas.saveLayerAlpha(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight(), (int) (255 * (1f - progressClpamped)), Canvas.ALL_SAVE_FLAG);
@ -814,20 +915,20 @@ public class CustomEmojiReactionsWindow {
canvas.restoreToCount(restoreCount);
}
if (invalidatePath) {
invalidatePath = false;
pathToClip.rewind();
pathToClip.addRoundRect(drawingRect, radius, radius, Path.Direction.CW);
boolean beforeLollipop = Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP;
if (beforeLollipop) {
if (invalidatePath) {
invalidatePath = false;
pathToClipApi20.rewind();
pathToClipApi20.addRoundRect(drawingRect, radius, radius, Path.Direction.CW);
}
canvas.save();
canvas.clipPath(pathToClipApi20);
super.dispatchDraw(canvas);
canvas.restore();
} else {
super.dispatchDraw(canvas);
}
canvas.save();
canvas.clipPath(pathToClip);
canvas.translate(cascadeAnimation ? 0 : enterTransitionOffsetX, enterTransitionOffsetY);
canvas.scale(enterTransitionScale, enterTransitionScale, enterTransitionScalePx, enterTransitionScalePy);
if (!cascadeAnimation) {
selectAnimatedEmojiDialog.setAlpha(enterTransitionProgress);
}
super.dispatchDraw(canvas);
canvas.restore();
if (frameDrawCount < 5) {
if (frameDrawCount == 3) {
@ -840,6 +941,7 @@ public class CustomEmojiReactionsWindow {
if (valueAnimator != null) {
invalidate();
}
HwEmojis.exec();
}
}

View file

@ -0,0 +1,106 @@
package org.telegram.ui.Components.Reactions;
import static org.telegram.messenger.SharedConfig.PERFORMANCE_CLASS_HIGH;
import static org.telegram.messenger.SharedConfig.getDevicePerformanceClass;
import android.view.View;
import org.telegram.messenger.ImageLoader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class HwEmojis {
private static final Set<View> hwViews = new HashSet<>();
private static volatile boolean hwEnabled = false;
private static Runnable task;
private static boolean firstOpen = true;
private static boolean isPreparing = false;
private static boolean isCascade = false;
private static boolean isBeforePreparing = false;
private static Boolean isWeakDevice;
public static void prepare(Runnable runnable, boolean cascade) {
isCascade = cascade;
isPreparing = true;
isBeforePreparing = false;
if (firstOpen) {
firstOpen = false;
}
task = runnable;
}
public static void beforePreparing() {
ImageLoader.getInstance().getCacheOutQueue().pause();
isBeforePreparing = true;
}
public static boolean isCascade() {
return isCascade;
}
public static boolean isPreparing() {
return isPreparing;
}
public static boolean isFirstOpen() {
return firstOpen;
}
public static boolean isHwEnabled() {
return hwEnabled;
}
public static boolean isHwEnabledOrPreparing() {
return hwEnabled || isPreparing || isBeforePreparing;
}
public static void exec() {
if (task != null) {
task.run();
task = null;
}
}
public static boolean grab(View view) {
if (hwEnabled) {
hwViews.add(view);
}
return hwEnabled;
}
public static boolean grabIfWeakDevice(View... views) {
if (isWeakDevice == null) {
isWeakDevice = getDevicePerformanceClass() != PERFORMANCE_CLASS_HIGH;
}
if (!isWeakDevice) {
return false;
}
if (hwEnabled) {
hwViews.addAll(Arrays.asList(views));
}
return hwEnabled;
}
public static void enableHw() {
ImageLoader.getInstance().getCacheOutQueue().pause();
hwEnabled = true;
isPreparing = false;
isBeforePreparing = false;
}
public static void disableHw() {
ImageLoader.getInstance().getCacheOutQueue().resume();
hwEnabled = false;
isPreparing = false;
isBeforePreparing = false;
task = null;
for (View view : hwViews) {
view.invalidate();
}
hwViews.clear();
}
}

View file

@ -61,10 +61,12 @@ import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.ReactedUserHolderView;
import org.telegram.ui.Components.ListView.AdapterWithDiffUtils;
import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet;
import org.telegram.ui.Components.Premium.PremiumLockIconView;
import org.telegram.ui.Components.Reactions.CustomEmojiReactionsWindow;
import org.telegram.ui.Components.Reactions.HwEmojis;
import org.telegram.ui.Components.Reactions.ReactionsEffectOverlay;
import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
import org.telegram.ui.Components.Reactions.ReactionsUtils;
@ -170,6 +172,8 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
final AnimationNotificationsLocker notificationsLocker = new AnimationNotificationsLocker();
private final int type;
public boolean skipEnterAnimation;
public boolean isHiddenNextReaction = true;
private Runnable onSwitchedToLoopView;
public ReactionsContainerLayout(int type, BaseFragment fragment, @NonNull Context context, int currentAccount, Theme.ResourcesProvider resourcesProvider) {
super(context);
@ -195,6 +199,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
shadow.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_messagePanelShadow), PorterDuff.Mode.MULTIPLY));
recyclerListView = new RecyclerListView(context) {
@Override
public boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (pressedReaction != null && (child instanceof ReactionHolderView) && ((ReactionHolderView) child).currentReaction.equals(pressedReaction)) {
@ -506,6 +511,10 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
}
}
public void setOnSwitchedToLoopView(Runnable onSwitchedToLoopView) {
this.onSwitchedToLoopView = onSwitchedToLoopView;
}
public void dismissWindow() {
reactionsWindow.dismiss();
}
@ -519,8 +528,10 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
return;
}
reactionsWindow = new CustomEmojiReactionsWindow(type, fragment, allReactionsList, selectedReactions, this, resourcesProvider);
invalidateLoopViews();
reactionsWindow.onDismissListener(() -> {
reactionsWindow = null;
invalidateLoopViews();
if (delegate != null) {
delegate.onEmojiWindowDismissed();
}
@ -528,6 +539,15 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
//animatePullingBack();
}
private void invalidateLoopViews() {
for (int i = 0; i < recyclerListView.getChildCount(); i++) {
View child = recyclerListView.getChildAt(i);
if (child instanceof ReactionHolderView) {
((ReactionHolderView) child).loopImageView.invalidate();
}
}
}
public boolean showCustomEmojiReaction() {
return !MessagesController.getInstance(currentAccount).premiumLocked && allReactionsAvailable;
}
@ -761,9 +781,10 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
}
if (pullingLeftOffsetProgress > 0) {
float progress = getPullingLeftProgress();
int left = lastReactionX + AndroidUtilities.dp(32);
float leftProgress = Utilities.clamp(left / (float) (getMeasuredWidth() - AndroidUtilities.dp(34)), 1f, 0f);
float pullingOffsetX = leftProgress * progress * AndroidUtilities.dp(32);
int reactionSize = nextRecentReaction.getMeasuredWidth() - AndroidUtilities.dp(2);
int left = lastReactionX + reactionSize;
float leftProgress = Utilities.clamp(left / (float) (getMeasuredWidth() - nextRecentReaction.getMeasuredWidth()), 1f, 0f);
float pullingOffsetX = leftProgress * progress * reactionSize;
if (nextRecentReaction.getTag() == null) {
nextRecentReaction.setTag(1f);
@ -773,10 +794,20 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
float scale = Utilities.clamp(progress, 1f, 0f);
nextRecentReaction.setScaleX(scale);
nextRecentReaction.setScaleY(scale);
nextRecentReaction.setTranslationX(recyclerListView.getX() + left - pullingOffsetX - AndroidUtilities.dp(20));
nextRecentReaction.setVisibility(View.VISIBLE);
float additionalOffset = 0;
if (type != TYPE_STORY) {
additionalOffset = - AndroidUtilities.dp(20);
} else {
additionalOffset = - AndroidUtilities.dp(8);
}
nextRecentReaction.setTranslationX(recyclerListView.getX() + left - pullingOffsetX + additionalOffset);
if (nextRecentReaction.getVisibility() != View.VISIBLE) {
nextRecentReaction.setVisibility(View.VISIBLE);
}
} else {
nextRecentReaction.setVisibility(View.GONE);
if (nextRecentReaction.getVisibility() != View.GONE && isHiddenNextReaction) {
nextRecentReaction.setVisibility(View.GONE);
}
if (nextRecentReaction.getTag() != null) {
nextRecentReaction.setTag(null);
}
@ -791,20 +822,25 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
return;
}
canvas.clipPath(mPath);
boolean showCustomEmojiReaction = showCustomEmojiReaction();
if (!showCustomEmojiReaction) {
canvas.clipPath(mPath);
}
canvas.translate((LocaleController.isRTL || mirrorX ? -1 : 1) * getWidth() * (1f - transitionProgress), 0);
recyclerListView.setTranslationX(-transitionLeftOffset);
super.dispatchDraw(canvas);
if (leftShadowPaint != null) {
float p = Utilities.clamp(leftAlpha * transitionProgress, 1f, 0f);
leftShadowPaint.setAlpha((int) (p * 0xFF));
canvas.drawRect(rect, leftShadowPaint);
}
if (rightShadowPaint != null) {
float p = Utilities.clamp(rightAlpha * transitionProgress, 1f, 0f);
rightShadowPaint.setAlpha((int) (p * 0xFF));
canvas.drawRect(rect, rightShadowPaint);
if (!showCustomEmojiReaction) {
if (leftShadowPaint != null) {
float p = Utilities.clamp(leftAlpha * transitionProgress, 1f, 0f);
leftShadowPaint.setAlpha((int) (p * 0xFF));
canvas.drawRect(rect, leftShadowPaint);
}
if (rightShadowPaint != null) {
float p = Utilities.clamp(rightAlpha * transitionProgress, 1f, 0f);
rightShadowPaint.setAlpha((int) (p * 0xFF));
canvas.drawRect(rect, rightShadowPaint);
}
}
canvas.restoreToCount(s);
@ -824,7 +860,6 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
return;
}
canvas.save();
float scale = transitionProgress;
canvas.clipRect(0, AndroidUtilities.lerp(rect.bottom, 0, CubicBezierInterpolator.DEFAULT.getInterpolation(flipVerticalProgress)) - (int) Math.ceil(rect.height() / 2f * (1f - transitionProgress)), getMeasuredWidth(), AndroidUtilities.lerp(getMeasuredHeight() + AndroidUtilities.dp(8), getPaddingTop() - expandSize(), CubicBezierInterpolator.DEFAULT.getInterpolation(flipVerticalProgress)));
float cx = LocaleController.isRTL || mirrorX ? bigCircleOffset : getWidth() - bigCircleOffset;
float cy = getHeight() - getPaddingBottom() + expandSize();
@ -937,7 +972,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
}
}
private float getPullingLeftProgress() {
public float getPullingLeftProgress() {
return Utilities.clamp(pullingLeftOffset / AndroidUtilities.dp(42), 2f, 0f);
}
@ -1160,6 +1195,14 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
invalidate();
}
public void setCustomEmojiReactionsBackground(boolean isNeed) {
if (isNeed) {
customEmojiReactionsIconView.setBackground(Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(28), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector), 40)));
} else {
customEmojiReactionsIconView.setBackground(null);
}
}
boolean skipDraw;
public void setSkipDraw(boolean b) {
@ -1185,7 +1228,11 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
}
public void onCustomEmojiWindowOpened() {
animatePullingBack();
pullingLeftOffset = 0f;
if (customReactionsContainer != null) {
customReactionsContainer.invalidate();
}
invalidate();
}
public void clearRecentReactions() {
@ -1337,6 +1384,20 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
this.recyclerReaction = recyclerReaction;
enterImageView = new BackupImageView(context) {
@Override
protected ImageReceiver createImageReciever() {
return new ImageReceiver(this) {
@Override
protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, boolean memCache, int guid) {
if (drawable instanceof RLottieDrawable) {
RLottieDrawable rLottieDrawable = (RLottieDrawable) drawable;
rLottieDrawable.setCurrentFrame(0, false, true);
}
return super.setImageBitmapByKey(drawable, key, type, memCache, guid);
}
};
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
@ -1347,6 +1408,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
switchedToLoopView = true;
loopImageView.imageReceiver.getLottieAnimation().setCurrentFrame(0, false, true);
loopImageView.setVisibility(View.VISIBLE);
if (onSwitchedToLoopView != null) {
onSwitchedToLoopView.run();
}
AndroidUtilities.runOnUIThread(() -> {
enterImageView.setVisibility(View.INVISIBLE);
});
@ -1356,21 +1420,97 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
@Override
public void invalidate() {
if (HwEmojis.grabIfWeakDevice(this, ReactionsContainerLayout.this)) {
return;
}
super.invalidate();
ReactionsContainerLayout.this.invalidate();
}
@Override
public void invalidate(Rect dirty) {
if (HwEmojis.grabIfWeakDevice(this, ReactionsContainerLayout.this)) {
return;
}
super.invalidate(dirty);
ReactionsContainerLayout.this.invalidate();
}
@Override
public void invalidate(int l, int t, int r, int b) {
if (HwEmojis.grabIfWeakDevice(this)) {
return;
}
super.invalidate(l, t, r, b);
}
};
loopImageView = new BackupImageView(context) {
@Override
protected void onDraw(Canvas canvas) {
ImageReceiver imageReceiver = animatedEmojiDrawable != null ? animatedEmojiDrawable.getImageReceiver() : this.imageReceiver;
if (imageReceiver != null && imageReceiver.getLottieAnimation() != null) {
if (reactionsWindow != null || pressed) {
imageReceiver.getLottieAnimation().start();
} else {
if (imageReceiver.getLottieAnimation().getCurrentFrame() <= 2) {
imageReceiver.getLottieAnimation().stop();
}
}
}
super.onDraw(canvas);
}
@Override
protected ImageReceiver createImageReciever() {
return new ImageReceiver(this) {
@Override
protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, boolean memCache, int guid) {
boolean rez = super.setImageBitmapByKey(drawable, key, type, memCache, guid);
if (rez) {
if (drawable instanceof RLottieDrawable) {
RLottieDrawable rLottieDrawable = (RLottieDrawable) drawable;
rLottieDrawable.setCurrentFrame(0, false, true);
rLottieDrawable.stop();
}
}
return rez;
}
};
}
@Override
public void invalidate() {
if (HwEmojis.grabIfWeakDevice(this)) {
return;
}
super.invalidate();
}
@Override
public void invalidate(int l, int t, int r, int b) {
if (HwEmojis.grabIfWeakDevice(this)) {
return;
}
super.invalidate(l, t, r, b);
}
};
loopImageView = new BackupImageView(context);
enterImageView.getImageReceiver().setAutoRepeat(0);
enterImageView.getImageReceiver().setAllowStartLottieAnimation(false);
pressedBackupImageView = new BackupImageView(context) {
@Override
protected void onDraw(Canvas canvas) {
ImageReceiver imageReceiver = animatedEmojiDrawable != null ? animatedEmojiDrawable.getImageReceiver() : this.imageReceiver;
if (imageReceiver != null && imageReceiver.getLottieAnimation() != null) {
imageReceiver.getLottieAnimation().start();
}
super.onDraw(canvas);
}
@Override
public void invalidate() {
super.invalidate();
@ -1382,6 +1522,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
addView(loopImageView, LayoutHelper.createFrame(34, 34, Gravity.CENTER));
enterImageView.setLayerNum(Integer.MAX_VALUE);
loopImageView.setLayerNum(Integer.MAX_VALUE);
loopImageView.imageReceiver.setAutoRepeat(0);
loopImageView.imageReceiver.setAllowStartAnimation(false);
loopImageView.imageReceiver.setAllowStartLottieAnimation(false);
pressedBackupImageView.setLayerNum(Integer.MAX_VALUE);
}
@ -1413,7 +1556,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
loopImageView.setAnimatedEmojiDrawable(loopDrawable);
}
setFocusable(true);
shouldSwitchToLoopView = hasEnterAnimation && showCustomEmojiReaction();
shouldSwitchToLoopView = hasEnterAnimation && !allReactionsIsDefault;
if (!hasEnterAnimation) {
enterImageView.setVisibility(View.GONE);
loopImageView.setVisibility(View.VISIBLE);
@ -1448,6 +1591,9 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
enterImageView.getImageReceiver().setImage(ImageLocation.getForDocument(defaultReaction.appear_animation), ReactionsUtils.APPEAR_ANIMATION_FILTER, null, null, svgThumb, 0, "tgs", react, 0);
loopImageView.getImageReceiver().setImage(ImageLocation.getForDocument(defaultReaction.select_animation), ReactionsUtils.SELECT_ANIMATION_FILTER, null, null, hasEnterAnimation ? null : svgThumb, 0, "tgs", currentReaction, 0);
}
if (enterImageView.getImageReceiver().getLottieAnimation() != null) {
enterImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(0, false, true);
}
pressedBackupImageView.getImageReceiver().setImage(ImageLocation.getForDocument(defaultReaction.select_animation), ReactionsUtils.SELECT_ANIMATION_FILTER, null, null, svgThumb, 0, "tgs", react, 0);
preloadImageReceiver.setAllowStartLottieAnimation(false);

View file

@ -1053,7 +1053,9 @@ public class RecyclerListView extends RecyclerView {
final View view = cv;
final int position = currentChildPosition;
if (instantClick && position != -1) {
view.playSoundEffect(SoundEffectConstants.CLICK);
try {
view.playSoundEffect(SoundEffectConstants.CLICK);
} catch (Exception ignore) {}
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
if (onItemClickListener != null) {
onItemClickListener.onItemClick(view, position);
@ -1070,7 +1072,9 @@ public class RecyclerListView extends RecyclerView {
if (view != null) {
onChildPressed(view, 0, 0, false);
if (!instantClick) {
view.playSoundEffect(SoundEffectConstants.CLICK);
try {
view.playSoundEffect(SoundEffectConstants.CLICK);
} catch (Exception ignore) {}
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
if (position != -1) {
if (onItemClickListener != null) {

View file

@ -1880,10 +1880,11 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
if (archivedHintLayout == null || archivedHintLayout.getWidth() != width) {
archivedHintLayout = new StaticLayout(LocaleController.getString("ProfileStoriesArchiveHint", R.string.ProfileStoriesArchiveHint), archivedHintPaint, width, Layout.Alignment.ALIGN_CENTER, 1f, 0f, false);
archivedHintLayoutWidth = 0;
archivedHintLayoutLeft = 0;
for (int i = 0; i < archivedHintLayout.getLineCount(); ++i) {
archivedHintLayoutWidth = Math.max(archivedHintLayoutWidth, archivedHintLayout.getLineWidth(i));
archivedHintLayoutLeft = Math.min(archivedHintLayoutLeft, archivedHintLayout.getLineLeft(i));
}
archivedHintLayoutLeft = archivedHintLayout.getLineCount() > 0 ? archivedHintLayout.getLineLeft(0) : 0;
}
canvas.save();
@ -2269,10 +2270,15 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
if (mediaPage.selectedType == TAB_GROUPUSERS) {
if (view instanceof UserCell) {
TLRPC.ChatParticipant participant;
final int i;
if (!chatUsersAdapter.sortedUsers.isEmpty()) {
participant = chatUsersAdapter.chatInfo.participants.participants.get(chatUsersAdapter.sortedUsers.get(position));
i = chatUsersAdapter.sortedUsers.get(position);
} else {
participant = chatUsersAdapter.chatInfo.participants.participants.get(position);
i = position;
}
participant = chatUsersAdapter.chatInfo.participants.participants.get(i);
if (i < 0 || i >= chatUsersAdapter.chatInfo.participants.participants.size()) {
return;
}
onMemberClick(participant, false, view);
} else if (mediaPage.listView.getAdapter() == groupUsersSearchAdapter) {
@ -2508,6 +2514,10 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
return false;
}
protected boolean includeStories() {
return true;
}
protected int getInitialTab() {
return 0;
}
@ -4822,7 +4832,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
if (changed > 3) {
idToView = null;
}
if (DialogObject.isUserDialog(dialog_id) && !DialogObject.isEncryptedDialog(dialog_id) && (userInfo != null && userInfo.stories_pinned_available || isStoriesView())) {
if (DialogObject.isUserDialog(dialog_id) && !DialogObject.isEncryptedDialog(dialog_id) && (userInfo != null && userInfo.stories_pinned_available || isStoriesView()) && includeStories()) {
if (!scrollSlidingTextTabStrip.hasTab(TAB_STORIES)) {
scrollSlidingTextTabStrip.addTextTab(TAB_STORIES, LocaleController.getString("ProfileStories", R.string.ProfileStories), idToView);
}

View file

@ -0,0 +1,68 @@
package org.telegram.ui.Components;
import android.animation.TimeAnimator;
import org.telegram.messenger.AndroidUtilities;
/**
* Good for animations with a jank at the beginning.
*/
public class StableAnimator extends TimeAnimator {
private int times = 0;
private int totalTimes = 0;
private AnimatorUpdateListener updateListener;
private Object animatedValue;
private float[] floatValues;
public static StableAnimator ofFloat(float... values) {
StableAnimator anim = new StableAnimator();
anim.setFloatValues(values);
return anim;
}
@Override
public void setFloatValues(float[] floatValues) {
super.setFloatValues(floatValues);
this.floatValues = floatValues;
}
@Override
public void addUpdateListener(AnimatorUpdateListener listener) {
updateListener = listener;
}
@Override
public Object getAnimatedValue() {
return animatedValue;
}
@Override
public void end() {
updateListener = null;
super.end();
}
@Override
public void start() {
setTimeListener((animation, totalTime, deltaTime) -> {
if (times > 0 && totalTimes > 0) {
times--;
if (updateListener != null) {
if (floatValues != null && floatValues.length == 2) {
float percent = (float) times / (float) totalTimes;
float fraction = getInterpolator().getInterpolation(1f - percent);
animatedValue = floatValues[0] + ((floatValues[1] - floatValues[0]) * fraction);
updateListener.onAnimationUpdate(this);
} else {
end();
}
}
} else {
end();
}
});
this.times = (int) (getDuration() / AndroidUtilities.screenRefreshTime);
this.totalTimes = this.times;
super.start();
}
}

View file

@ -18,6 +18,8 @@ import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.CharacterStyle;
import com.google.android.exoplayer2.util.Log;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.FileLog;
@ -133,6 +135,10 @@ public class StaticLayoutEx {
}*/
try {
if (maxLines == 1) {
int index = TextUtils.indexOf(source, "\n") - 1;
if (index > 0) {
source = SpannableStringBuilder.valueOf(source.subSequence(0, index)).append("");
}
CharSequence text = TextUtils.ellipsize(source, paint, ellipsisWidth, TextUtils.TruncateAt.END);
return new StaticLayout(text, 0, text.length(), paint, outerWidth, align, spacingMult, spacingAdd, includePad);
} else {

View file

@ -5,6 +5,7 @@ import static org.telegram.messenger.AndroidUtilities.dp;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
@ -32,6 +33,7 @@ import org.telegram.messenger.CacheFetcher;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.LiteMode;
import org.telegram.messenger.MessagesStorage;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
@ -114,6 +116,7 @@ public class StickerCategoriesListView extends RecyclerListView {
this(context, additionalCategories, categoriesType, null);
}
@SuppressLint("NotifyDataSetChanged")
public StickerCategoriesListView(Context context, EmojiCategory[] additionalCategories, @CategoriesType int categoriesType, Theme.ResourcesProvider resourcesProvider) {
super(context, resourcesProvider);
@ -136,19 +139,22 @@ public class StickerCategoriesListView extends RecyclerListView {
long start = System.currentTimeMillis();
fetcher.fetch(UserConfig.selectedAccount, categoriesType, (emojiGroups) -> {
if (emojiGroups != null) {
categories = new EmojiCategory[(additionalCategories == null ? 0 : additionalCategories.length) + emojiGroups.groups.size()];
int i = 0;
if (additionalCategories != null) {
for (; i < additionalCategories.length; ++i) {
categories[i] = additionalCategories[i];
Runnable action = () -> {
categories = new EmojiCategory[(additionalCategories == null ? 0 : additionalCategories.length) + emojiGroups.groups.size()];
int i = 0;
if (additionalCategories != null) {
for (; i < additionalCategories.length; ++i) {
categories[i] = additionalCategories[i];
}
}
}
for (int j = 0; j < emojiGroups.groups.size(); ++j) {
categories[i + j] = EmojiCategory.remote(emojiGroups.groups.get(j));
}
adapter.notifyDataSetChanged();
setCategoriesShownT(0);
updateCategoriesShown(categoriesShouldShow, System.currentTimeMillis() - start > 16);
for (int j = 0; j < emojiGroups.groups.size(); ++j) {
categories[i + j] = EmojiCategory.remote(emojiGroups.groups.get(j));
}
adapter.notifyDataSetChanged();
setCategoriesShownT(0);
updateCategoriesShown(categoriesShouldShow, System.currentTimeMillis() - start > 16);
};
NotificationCenter.getInstance(UserConfig.selectedAccount).doOnIdle(action);
}
});
}

View file

@ -160,7 +160,6 @@ public class VideoPlayer implements Player.Listener, VideoListener, AnalyticsLis
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.playerDidStartPlaying);
}
playerCounter++;
//Log.d("kek", "playerCounter " + playerCounter);
}
@Override
@ -343,7 +342,6 @@ public class VideoPlayer implements Player.Listener, VideoListener, AnalyticsLis
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.playerDidStartPlaying);
}
playerCounter--;
//Log.d("kek", "playerCounter " + playerCounter);
}
@Override

View file

@ -7,6 +7,7 @@ import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.os.Process;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.DispatchQueue;
@ -25,7 +26,7 @@ public class SpoilerEffectBitmapFactory {
return factory;
}
final DispatchQueue dispatchQueue = new DispatchQueue("SpoilerEffectBitmapFactory");
final DispatchQueue dispatchQueue = new DispatchQueue("SpoilerEffectBitmapFactory", true, 3 * Process.THREAD_PRIORITY_LESS_FAVORABLE);
private Bitmap shaderBitmap;
Bitmap bufferBitmap;
Bitmap backgroundBitmap;

View file

@ -2086,10 +2086,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
int currentPosition = layoutManager.findFirstVisibleItemPosition();
if (currentPosition == 0) {
int pTop = getPaddingTop();
View view = findArchiveDialogCell(parentPage);
int height = (int) (AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 78 : 72) * PullForegroundDrawable.SNAP_HEIGHT);
int diff = (view.getTop() - pTop) + view.getMeasuredHeight();
if (view instanceof DialogCell) {
DialogCell view = findArchiveDialogCell(parentPage);
if (view != null) {
int height = (int) (AndroidUtilities.dp(SharedConfig.useThreeLinesLayout ? 78 : 72) * PullForegroundDrawable.SNAP_HEIGHT);
int diff = (view.getTop() - pTop) + view.getMeasuredHeight();
long pullingTime = System.currentTimeMillis() - startArchivePullingTime;
if (diff < height || pullingTime < PullForegroundDrawable.minPullingTime) {
disableActionBarScrolling = true;
@ -2941,6 +2942,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
actionBar.setBackButtonContentDescription(LocaleController.getString("AccDescrGoBack", R.string.AccDescrGoBack));
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needCheckSystemBarColors);
((SizeNotifierFrameLayout) fragmentView).invalidateBlur();
if (optionsItem != null) {
optionsItem.setVisibility(View.GONE);
}
}
@Override
@ -2990,12 +2994,15 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
}
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needCheckSystemBarColors, true);
((SizeNotifierFrameLayout) fragmentView).invalidateBlur();
if (optionsItem != null) {
optionsItem.setVisibility(View.VISIBLE);
}
}
@Override
public void onTextChanged(EditText editText) {
String text = editText.getText().toString();
if (text.length() != 0 || (searchViewPager.dialogsSearchAdapter != null && searchViewPager.dialogsSearchAdapter.hasRecentSearch()) || searchFiltersWasShowed) {
if (text.length() != 0 || (searchViewPager.dialogsSearchAdapter != null && searchViewPager.dialogsSearchAdapter.hasRecentSearch()) || searchFiltersWasShowed || hasStories) {
searchWas = true;
if (!searchIsShowed) {
showSearch(true, false, true);
@ -3024,7 +3031,6 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
searchItem.setVisibility(View.GONE);
}
if (isArchive()) {
searchItem.searchRightMargin = -44;
optionsItem = menu.addItem(4, R.drawable.ic_ab_other);
optionsItem.addSubItem(5, R.drawable.msg_customize, LocaleController.getString("ArchiveSettings")).setColors(getThemedColor(Theme.key_actionBarDefaultSubmenuItem), getThemedColor(Theme.key_actionBarDefaultSubmenuItem));
optionsItem.addSubItem(6, R.drawable.msg_help, LocaleController.getString("HowDoesItWork")).setColors(getThemedColor(Theme.key_actionBarDefaultSubmenuItem), getThemedColor(Theme.key_actionBarDefaultSubmenuItem));
@ -3271,7 +3277,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
if (initialDialogsType != DIALOGS_TYPE_DEFAULT) {
return false;
}
if (actionBar.isActionModeShowed()) {
if (actionBar.isActionModeShowed() || storiesOverscroll != 0) {
return false;
}
if (filterOptions != null && filterOptions.isShown()) {
@ -4844,7 +4850,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
}, subItem -> {
subItem.setMultiline(false);
})
.addIf(!isArchive(), R.drawable.msg_archive, LocaleController.getString("ArchiveStories", R.string.ArchiveStories), () -> {
.addIf(!isArchive(), R.drawable.msg_archive, LocaleController.getString("ArchivePeerStories", R.string.ArchivePeerStories), () -> {
toggleArciveForStory(dialogId);
}, subItem -> {
subItem.setMultiline(false);
@ -6750,10 +6756,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
if (searchFiltersWasShowed) {
onlyDialogsAdapter = false;
} else {
onlyDialogsAdapter = onlyDialogsAdapter() && !hasStories;
onlyDialogsAdapter = onlyDialogsAdapter();
}
searchViewPager.showOnlyDialogsAdapter(onlyDialogsAdapter);
whiteActionBar = !onlyDialogsAdapter;
whiteActionBar = !onlyDialogsAdapter || hasStories;
if (whiteActionBar) {
searchFiltersWasShowed = true;
}
@ -7048,7 +7054,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
public boolean onlyDialogsAdapter() {
int dialogsCount = getMessagesController().getTotalDialogsCount();
return onlySelect || !searchViewPager.dialogsSearchAdapter.hasRecentSearch() || dialogsCount <= 10;
return onlySelect || !searchViewPager.dialogsSearchAdapter.hasRecentSearch() || dialogsCount <= 10 && !hasStories;
}
private void updateFilterTabsVisibility(boolean animated) {
@ -8053,6 +8059,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
this.storiesEnabled = storiesEnabled;
}
if (floatingButton == null || floatingButtonContainer == null) {
return;
}
if (initialDialogsType == DIALOGS_TYPE_WIDGET) {
floatingButton.setImageResource(R.drawable.floating_check);
floatingButtonContainer.setContentDescription(LocaleController.getString("Done", R.string.Done));
@ -11802,7 +11812,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
if (StoryRecorder.isVisible() || (storyViewer != null && storyViewer.isFullyVisible())) {
animated = false;
}
boolean onlySelfStories = getStoriesController().hasOnlySelfStories();
boolean onlySelfStories = !isArchive() && getStoriesController().hasOnlySelfStories();
boolean newVisibility;
if (isArchive()) {
newVisibility = !getStoriesController().getHiddenList().isEmpty();

View file

@ -12,6 +12,7 @@ import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.SpannableStringBuilder;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.SparseArray;
import android.view.Gravity;
@ -116,7 +117,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente
private String currentDataQuery;
private static SpannableStringBuilder arrowSpan;
private static SpannableStringBuilder[] arrowSpan = new SpannableStringBuilder[3];
private int photoViewerClassGuid;
@ -246,7 +247,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente
@Override
public CharSequence getTitleFor(int i) {
return createFromInfoString(messages.get(i));
return createFromInfoString(messages.get(i), 0);
}
@Override
@ -422,20 +423,37 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente
emptyView.setVisibility(View.GONE);
}
public static CharSequence createFromInfoString(MessageObject messageObject) {
return createFromInfoString(messageObject, true);
public static CharSequence createFromInfoString(MessageObject messageObject, int arrowType) {
return createFromInfoString(messageObject, true, arrowType);
}
public static CharSequence createFromInfoString(MessageObject messageObject, boolean includeChat) {
public static CharSequence createFromInfoString(MessageObject messageObject, boolean includeChat, int arrowType) {
return createFromInfoString(messageObject, includeChat, arrowType, null);
}
public static CharSequence createFromInfoString(MessageObject messageObject, boolean includeChat, int arrowType, TextPaint textPaint) {
if (messageObject == null) {
return "";
}
if (arrowSpan == null) {
arrowSpan = new SpannableStringBuilder(">");
Drawable arrowDrawable = ContextCompat.getDrawable(ApplicationLoader.applicationContext, R.drawable.attach_arrow_right).mutate();
ColoredImageSpan span = new ColoredImageSpan(arrowDrawable, ColoredImageSpan.ALIGN_CENTER);
arrowDrawable.setBounds(0, AndroidUtilities.dp(1), AndroidUtilities.dp(13), AndroidUtilities.dp(1 + 13));
arrowSpan.setSpan(span, 0, arrowSpan.length(), 0);
if (arrowSpan[arrowType] == null) {
arrowSpan[arrowType] = new SpannableStringBuilder(">");
int resId;
if (arrowType == 0) {
resId = R.drawable.attach_arrow_right;
} else if (arrowType == 1) {
resId = R.drawable.msg_mini_arrow_mediathin;
} else if (arrowType == 2) {
resId = R.drawable.msg_mini_arrow_mediabold;
} else {
return "";
}
Drawable arrowDrawable = ContextCompat.getDrawable(ApplicationLoader.applicationContext, resId).mutate();
ColoredImageSpan span = new ColoredImageSpan(arrowDrawable, arrowType == 0 ? ColoredImageSpan.ALIGN_CENTER : ColoredImageSpan.ALIGN_BASELINE);
// arrowDrawable.setBounds(0, 0, AndroidUtilities.dp(13), AndroidUtilities.dp(13));
if (arrowType == 1 || arrowType == 2) {
span.setScale(.85f);
}
arrowSpan[arrowType].setSpan(span, 0, arrowSpan[arrowType].length(), 0);
}
CharSequence fromName = null;
TLRPC.User user = messageObject.messageOwner.from_id.user_id != 0 ? MessagesController.getInstance(UserConfig.selectedAccount).getUser(messageObject.messageOwner.from_id.user_id) : null;
@ -459,17 +477,17 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente
chatTitle = ForumUtilities.getTopicSpannedName(topic, null);
}
}
chatTitle = Emoji.replaceEmoji(chatTitle, null, AndroidUtilities.dp(12), false);
chatTitle = Emoji.replaceEmoji(chatTitle, textPaint == null ? null : textPaint.getFontMetricsInt(), false);
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder
.append(Emoji.replaceEmoji(UserObject.getFirstName(user), null, AndroidUtilities.dp(12), false))
.append(Emoji.replaceEmoji(UserObject.getFirstName(user), textPaint == null ? null : textPaint.getFontMetricsInt(), false))
.append('')
.append(arrowSpan)
.append(arrowSpan[arrowType])
.append('')
.append(chatTitle);
fromName = spannableStringBuilder;
} else if (user != null) {
fromName = Emoji.replaceEmoji(UserObject.getUserName(user), null, AndroidUtilities.dp(12), false);
fromName = Emoji.replaceEmoji(UserObject.getUserName(user), textPaint == null ? null : textPaint.getFontMetricsInt(), false);
} else if (chatFrom != null) {
CharSequence chatTitle = chatFrom.title;
if (ChatObject.isForum(chatFrom)) {
@ -478,7 +496,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente
chatTitle = ForumUtilities.getTopicSpannedName(topic, null);
}
}
chatTitle = Emoji.replaceEmoji(chatTitle, null, AndroidUtilities.dp(12), false);
chatTitle = Emoji.replaceEmoji(chatTitle, textPaint == null ? null : textPaint.getFontMetricsInt(), false);
fromName = chatTitle;
}
return fromName == null ? "" : fromName;

View file

@ -3630,7 +3630,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
if (baseFragment != null) {
storyItem.dialogId = peerId;
StoryViewer storyViewer = baseFragment.getOrCreateStoryViewer();
if (storyViewer.isShown()) {
if (storyViewer.isShown() && storyViewer.attachedToParent()) {
StoryViewer overlayStoryViewer = baseFragment.getOrCreateOverlayStoryViewer();
final StoryViewer storyViewer1 = storyViewer;
overlayStoryViewer.setOnCloseListener(() -> storyViewer1.setOverlayVisible(false));
@ -5693,7 +5693,9 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
super.onDestroy();
onFinish();
FloatingDebugController.onDestroy();
flagSecureReason.detach();
if (flagSecureReason != null) {
flagSecureReason.detach();
}
}
@Override

View file

@ -12067,7 +12067,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
newMessageObject.updateTranslation();
isVideo = newMessageObject.isVideo();
title = FilteredSearchView.createFromInfoString(newMessageObject, opennedFromMedia && !openedFromProfile);
title = FilteredSearchView.createFromInfoString(newMessageObject, opennedFromMedia && !openedFromProfile, 0);
CharSequence subtitle = null;
if (newMessageObject.messageOwner != null) {
subtitle = LocaleController.formatDateAudio(newMessageObject.messageOwner.date, false);

View file

@ -191,6 +191,7 @@ import org.telegram.ui.Components.InstantCameraView;
import org.telegram.ui.Components.ItemOptions;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.LinkSpanDrawable;
import org.telegram.ui.Components.Paint.PersistColorPalette;
import org.telegram.ui.Components.Premium.GiftPremiumBottomSheet;
import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet;
import org.telegram.ui.Components.Premium.PremiumGradient;
@ -3453,6 +3454,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
ChatThemeController.getInstance(currentAccount).clearCache();
getNotificationCenter().postNotificationName(NotificationCenter.newSuggestionsAvailable);
RestrictedLanguagesSelectActivity.cleanup();
PersistColorPalette.getInstance(currentAccount).cleanup();
} else if (which == 7) {
VoIPHelper.showCallDebugSettings(getParentActivity());
} else if (which == 8) {

View file

@ -38,22 +38,20 @@ public class SponsoredMessageInfoView extends FrameLayout {
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
LinkSpanDrawable.LinksTextView description1 = new LinkSpanDrawable.LinksTextView(context, resourcesProvider);
description1.setText(AndroidUtilities.replaceSingleTag(LocaleController.getString("SponsoredMessageInfoDescriptionLink", R.string.SponsoredMessageInfoDescriptionLink), () -> {
Browser.openUrl(getContext(), "https://telegram.org/privacy#5-6-no-ads-based-on-user-data");
}));
description1.setText(AndroidUtilities.replaceLinks(LocaleController.getString("SponsoredMessageInfo2Description1"), resourcesProvider));
description1.setLinkTextColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider));
description1.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
description1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
description1.setLineSpacing(AndroidUtilities.dp(2), 1f);
TextView description2 = new TextView(context);
description2.setText(LocaleController.getString("SponsoredMessageInfoDescription2", R.string.SponsoredMessageInfoDescription2));
LinkSpanDrawable.LinksTextView description2 = new LinkSpanDrawable.LinksTextView(context);
description2.setText(AndroidUtilities.replaceLinks(LocaleController.getString("SponsoredMessageInfo2Description2"), resourcesProvider));
description2.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
description2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
description2.setLineSpacing(AndroidUtilities.dp(2), 1f);
TextView description3 = new TextView(context);
description3.setText(LocaleController.getString("SponsoredMessageInfoDescription3", R.string.SponsoredMessageInfoDescription3));
LinkSpanDrawable.LinksTextView description3 = new LinkSpanDrawable.LinksTextView(context);
description3.setText(AndroidUtilities.replaceLinks(LocaleController.getString("SponsoredMessageInfo2Description3"), resourcesProvider));
description3.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
description3.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
description3.setLineSpacing(AndroidUtilities.dp(2), 1f);
@ -86,22 +84,32 @@ public class SponsoredMessageInfoView extends FrameLayout {
button.setGravity(Gravity.CENTER_VERTICAL);
TextView description4 = new TextView(context);
description4.setText(LocaleController.getString("SponsoredMessageInfoDescription4", R.string.SponsoredMessageInfoDescription4));
LinkSpanDrawable.LinksTextView description4 = new LinkSpanDrawable.LinksTextView(context);
description4.setText(AndroidUtilities.replaceLinks(LocaleController.getString("SponsoredMessageInfo2Description4"), resourcesProvider));
description4.setLineSpacing(AndroidUtilities.dp(2), 1f);
description4.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
description4.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
textView.setPadding(AndroidUtilities.dp(22), 0, AndroidUtilities.dp(22), 0);
linearLayout.addView(textView);
description1.setPadding(AndroidUtilities.dp(22), 0, AndroidUtilities.dp(22), 0);
linearLayout.addView(description1, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 18, 0, 0));
description2.setPadding(AndroidUtilities.dp(22), 0, AndroidUtilities.dp(22), 0);
linearLayout.addView(description2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 24, 0, 0));
description3.setPadding(AndroidUtilities.dp(22), 0, AndroidUtilities.dp(22), 0);
linearLayout.addView(description3, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 24, 0, 0));
linearLayout.addView(button, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 34, Gravity.CENTER_HORIZONTAL, 0, 14, 0, 0));
linearLayout.addView(button, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 34, Gravity.CENTER_HORIZONTAL, 22, 14, 22, 0));
description4.setPadding(AndroidUtilities.dp(22), 0, AndroidUtilities.dp(22), 0);
linearLayout.addView(description4, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 14, 0, 0));
ScrollView scrollView = new ScrollView(getContext());
scrollView.addView(linearLayout);
addView(scrollView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 22, 12, 22, 22));
addView(scrollView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 12, 0, 22));
}
}

View file

@ -1594,13 +1594,15 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
.setBgColor(Theme.getColor(Theme.key_undo_background))
.setMultilineText(true)
.setTextAlign(Layout.Alignment.ALIGN_CENTER)
.setText(AndroidUtilities.replaceSingleTag(LocaleController.getString("StoriesPremiumHint"), Theme.key_undo_cancelColor, 0, () -> {
if (premiumHint != null) {
premiumHint.hide();
}
fragment.presentFragment(new PremiumPreviewFragment("stories"));
}))
.setJoint(0, 37 - 8);
CharSequence text = AndroidUtilities.replaceSingleTag(LocaleController.getString("StoriesPremiumHint").replace('\n', ' '), Theme.key_undo_cancelColor, 0, () -> {
if (premiumHint != null) {
premiumHint.hide();
}
fragment.presentFragment(new PremiumPreviewFragment("stories"));
});
premiumHint.setMaxWidthPx(HintView2.cutInFancyHalf(text, premiumHint.getTextPaint()));
premiumHint.setText(text);
premiumHint.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(24), AndroidUtilities.dp(8), 0);
if (getParent() instanceof FrameLayout) {
((FrameLayout) getParent()).addView(premiumHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 150, Gravity.LEFT | Gravity.TOP));
@ -1614,7 +1616,6 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
if (premiumHint.shown()) {
BotWebViewVibrationEffect.APP_ERROR.vibrate();
}
premiumHint.setMaxWidthPx(Math.min(AndroidUtilities.dp(450), (int) (AndroidUtilities.displaySize.x * .7f)));
premiumHint.show();
}
}

View file

@ -39,7 +39,6 @@ import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.OvershootInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
@ -59,7 +58,6 @@ import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.AnimationNotificationsLocker;
import org.telegram.messenger.BotWebViewVibrationEffect;
import org.telegram.messenger.BuildVars;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.FileLoader;
@ -96,7 +94,6 @@ import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.BottomSheet;
import org.telegram.ui.ActionBar.SimpleTextView;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.ChatMessageCell;
import org.telegram.ui.ChatActivity;
import org.telegram.ui.Components.AlertsCreator;
import org.telegram.ui.Components.AnimatedEmojiDrawable;
@ -132,12 +129,11 @@ import org.telegram.ui.Components.ScaleStateListAnimator;
import org.telegram.ui.Components.ShareAlert;
import org.telegram.ui.Components.SizeNotifierFrameLayout;
import org.telegram.ui.Components.TextStyleSpan;
import org.telegram.ui.Components.URLSpanMono;
import org.telegram.ui.Components.URLSpanNoUnderline;
import org.telegram.ui.Components.URLSpanReplacement;
import org.telegram.ui.Components.URLSpanUserMention;
import org.telegram.ui.Components.spoilers.SpoilersTextView;
import org.telegram.ui.Components.voip.CellFlickerDrawable;
import org.telegram.ui.DialogsActivity;
import org.telegram.ui.LaunchActivity;
import org.telegram.ui.NotificationsCustomSettingsActivity;
import org.telegram.ui.PinchToZoomHelper;
@ -174,7 +170,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
// private final CloseFriendsBadge closeFriendsBadge;
private final StoryPrivacyButton privacyButton;
private HintView2 privacyHint;
private HintView soundTooltip;
private HintView2 soundTooltip;
private int reactionsContainerIndex;
private final StoryViewer storyViewer;
private final StoryCaptionView storyCaptionView;
@ -271,8 +267,6 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
public boolean allowScreenshots;
public boolean forceUpdateOffsets;
private HintView mediaBanTooltip;
// private HintView closeFriendsTooltip;
ArrayList<HintView> createdTooltips = new ArrayList<>();
public PinchToZoomHelper pinchToZoomHelper = new PinchToZoomHelper();
private boolean imageChanged;
@ -308,6 +302,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
this.uploadingStories = new ArrayList<>();
this.imageReceiver = new ImageReceiver() {
@Override
protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, boolean memCache, int guid) {
boolean r = super.setImageBitmapByKey(drawable, key, type, memCache, guid);
@ -332,6 +327,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
this.rightPreloadImageReceiver.setAllowLoadingOnAttachedOnly(true);
this.rightPreloadImageReceiver.ignoreNotifications = true;
this.rightPreloadImageReceiver.setFileLoadingPriority(FileLoader.PRIORITY_LOW);
imageReceiver.setPreloadingReceivers(Arrays.asList(leftPreloadImageReceiver, rightPreloadImageReceiver));
this.avatarDrawable = new AvatarDrawable();
this.storyViewer = storyViewer;
@ -656,7 +652,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
storyCaptionView = new StoryCaptionView(getContext(), storyViewer.resourcesProvider) {
@Override
public void onLinkClick(ClickableSpan span, View spoilersTextView) {
public void onLinkClick(CharacterStyle span, View spoilersTextView) {
if (span instanceof URLSpanUserMention) {
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(Utilities.parseLong(((URLSpanUserMention) span).getURL()));
if (user != null) {
@ -678,8 +674,11 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
} else if (span instanceof URLSpan) {
String url = ((URLSpan) span).getURL();
processExternalUrl(2, url, span, span instanceof URLSpanReplacement);
} else {
span.onClick(spoilersTextView);
} else if (span instanceof URLSpanMono) {
((URLSpanMono) span).copyToClipboard();
BulletinFactory.of(storyContainer, resourcesProvider).createCopyBulletin(LocaleController.getString("TextCopied", R.string.TextCopied)).show();
} else if (span instanceof ClickableSpan) {
((ClickableSpan) span).onClick(spoilersTextView);
}
}
@ -959,7 +958,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
});
}
if (allowShare) {
if (allowShare || MessagesController.getInstance(currentAccount).storiesExportNopublicLink) {
ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_shareout, LocaleController.getString("BotShare", R.string.BotShare), false, resourcesProvider).setOnClickListener(v -> {
shareStory(false);
if (popupMenu != null) {
@ -1024,7 +1023,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
}
if (user.contact) {
if (!user.stories_hidden) {
ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_archive, LocaleController.getString("ArchiveStories", R.string.ArchiveStories), false, resourcesProvider).setOnClickListener(v -> {
ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_archive, LocaleController.getString("ArchivePeerStories", R.string.ArchivePeerStories), false, resourcesProvider).setOnClickListener(v -> {
toggleArciveForStory(dialogId);
if (popupMenu != null) {
popupMenu.dismiss();
@ -1042,16 +1041,16 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
}
if (!unsupported) {
//if (UserObject.isService(dialogId)) {
if (UserObject.isService(dialogId) || allowShare) {
ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_gallery, LocaleController.getString("SaveToGallery", R.string.SaveToGallery), false, resourcesProvider).setOnClickListener(v -> {
saveToGallery();
if (popupMenu != null) {
popupMenu.dismiss();
}
});
// }
}
}
if (allowShare) {
if (allowShare || MessagesController.getInstance(currentAccount).storiesExportNopublicLink) {
ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_link, LocaleController.getString("CopyLink", R.string.CopyLink), false, resourcesProvider).setOnClickListener(v -> {
AndroidUtilities.addToClipboard(currentStory.createLink());
onLickCopied();
@ -1163,16 +1162,18 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
firstName = firstName.substring(0, index);
}
CharSequence text;
boolean twoLines = true;
if (storyItem.close_friends) {
text = AndroidUtilities.replaceTags(LocaleController.formatString("StoryCloseFriendsHint", R.string.StoryCloseFriendsHint, firstName));
} else if (storyItem.contacts) {
text = AndroidUtilities.replaceTags(LocaleController.formatString("StoryContactsHint", R.string.StoryContactsHint, firstName));
twoLines = false;
} else if (storyItem.selected_contacts) {
text = AndroidUtilities.replaceTags(LocaleController.formatString("StorySelectedContactsHint", R.string.StorySelectedContactsHint, firstName));
} else {
return;
}
privacyHint.setMaxWidthPx(HintView2.cutInFancyHalf(text, privacyHint.getTextPaint()));
privacyHint.setMaxWidthPx(twoLines ? HintView2.cutInFancyHalf(text, privacyHint.getTextPaint()) : storyContainer.getMeasuredWidth());
privacyHint.setText(text);
privacyHint.setJoint(1, -(storyContainer.getWidth() - privacyButton.getCenterX()) / AndroidUtilities.density);
delegate.setIsHintVisible(true);
@ -1189,16 +1190,12 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
storyViewer.toggleSilentMode();
} else {
if (soundTooltip == null) {
soundTooltip = new HintView.Builder(context, resourcesProvider)
.setTopArrow(true)
.setBackgroundColor(ColorUtils.setAlphaComponent(Color.BLACK, (int) (0.5f * 255)))
.build();
soundTooltip.setExtraTranslationY(-dp(8));
soundTooltip = new HintView2(context, HintView2.DIRECTION_TOP).setJoint(1, -56);
soundTooltip.setText(LocaleController.getString(R.string.StoryNoSound));
addView(soundTooltip, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 10, 0, 10, 0));
createdTooltips.add(soundTooltip);
soundTooltip.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0);
storyContainer.addView(soundTooltip, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL_HORIZONTAL | Gravity.TOP, 0, 52, 0, 0));
}
soundTooltip.showForView(muteIconContainer, true);
soundTooltip.show();
}
});
@ -1906,6 +1903,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
this.dialogId = dialogId;
deletedPeer = false;
forceUpdateOffsets = true;
if (peerIdChanged) {
currentStory.clear();
}
if (dialogId >= 0) {
isSelf = dialogId == UserConfig.getInstance(currentAccount).getClientUserId();
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId);
@ -2274,7 +2274,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
@Override
public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.storiesUpdated) {
if (id == NotificationCenter.storiesUpdated || id == NotificationCenter.storiesListUpdated && storyViewer.storiesList == args[0]) {
if (delegate != null && delegate.isClosed()) {
return;
}
@ -2327,15 +2327,14 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
final boolean wasUploading = isUploading;
final boolean wasEditing = isEditing;
if (isActive) {
ImageLoader.getInstance().cancelLoadingForImageReceiver(leftPreloadImageReceiver, true);
ImageLoader.getInstance().cancelLoadingForImageReceiver(rightPreloadImageReceiver, true);
}
currentStory.editingSourceItem = null;
if (!uploadingStories.isEmpty() && position >= storyItems.size()) {
isUploading = true;
isEditing = false;
position -= storyItems.size();
if (position < 0 || position >= uploadingStories.size()) {
return;
}
StoriesController.UploadingStory uploadingStory = uploadingStories.get(position);
Drawable thumbDrawable = null;
imageReceiver.setCrossfadeWithOldImage(false);
@ -2355,6 +2354,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
} else {
isUploading = false;
isEditing = false;
if (position < 0 || position > storyItems.size() - 1) {
storyViewer.close(true);
}
TLRPC.StoryItem storyItem = storyItems.get(position);
StoriesController.UploadingStory editingStory = storiesController.findEditingStory(storyItem);
if (editingStory != null) {
@ -2385,7 +2387,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
if (storyItem.media != null) {
thumbDrawable = ImageLoader.createStripedBitmap(storyItem.media.document.thumbs);
}
if (ImageLoader.getInstance().isInMemCache(ImageLocation.getForPath(storyItem.firstFramePath).getKey(null, null, false) + "@" + filter, false)) {
if (storyItem.firstFramePath != null && ImageLoader.getInstance().isInMemCache(ImageLocation.getForPath(storyItem.firstFramePath).getKey(null, null, false) + "@" + filter, false)) {
imageReceiver.setImage(null, null, ImageLocation.getForPath(storyItem.firstFramePath), filter, null, null, thumbDrawable, 0, null, null, 0);
} else {
imageReceiver.setImage(null, null, ImageLocation.getForPath(storyItem.attachPath), filter + "_pframe", null, null, thumbDrawable, 0, null, null, 0);
@ -2436,7 +2438,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
allowShare = !unsupported && currentStory.storyItem != null && !(currentStory.storyItem instanceof TLRPC.TL_storyItemDeleted) && !(currentStory.storyItem instanceof TLRPC.TL_storyItemSkipped);
if (allowShare) {
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId);
allowShare = !currentStory.storyItem.noforwards && (currentStory.storyItem.isPublic || MessagesController.getInstance(currentAccount).storiesExportNopublicLink) && user != null && UserObject.getPublicUsername(user) != null;
allowShare = !currentStory.storyItem.noforwards && currentStory.storyItem.isPublic && user != null && UserObject.getPublicUsername(user) != null;
}
NotificationsController.getInstance(currentAccount).processReadStories(dialogId, storyItem.id);
}
@ -2501,12 +2503,12 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
headerView.setSubtitle(string, animateSubtitle);
}
}
for (int i = 0; i < createdTooltips.size(); i++) {
createdTooltips.get(i).hide(false);
}
if (privacyHint != null) {
privacyHint.hide(false);
}
if (soundTooltip != null) {
soundTooltip.hide(false);
}
}
CharSequence caption = null;
if (currentStory.uploadingStory != null) {
@ -2579,9 +2581,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
if (isActive) {
requestVideoPlayer(0);
updatePreloadImages();
imageReceiver.bumpPriority();
requestVideoPlayer(0);
}
if (storyViewer.storiesList != null && selectedPosition >= 0 && selectedPosition < storyViewer.storiesList.messageObjects.size()) {
@ -2987,11 +2989,8 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
if (privacyHint != null) {
privacyHint.hide();
}
for (int i = 0; i < createdTooltips.size(); i++) {
if (createdTooltips.get(i).getVisibility() == View.VISIBLE) {
createdTooltips.get(i).hide(true);
return true;
}
if (soundTooltip != null) {
soundTooltip.hide();
}
if (mediaBanTooltip != null) {
@ -3033,10 +3032,8 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
if (privacyHint != null && privacyHint.shown()) {
return true;
}
for (int i = 0; i < createdTooltips.size(); i++) {
if (createdTooltips.get(i).getVisibility() == View.VISIBLE) {
return true;
}
if (soundTooltip != null && soundTooltip.shown()) {
return true;
}
for (int i = 0; i < container.getChildCount(); i++) {
@ -3263,22 +3260,25 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
}
public void onActionDown(MotionEvent ev) {
for (int i = 0; i < createdTooltips.size(); i++) {
createdTooltips.get(i).hide();
}
if (privacyHint != null && privacyHint.shown() && privacyButton != null &&
!privacyHint.containsTouch(ev, getX() + storyContainer.getX() + privacyHint.getX(), getY() + storyContainer.getY() + privacyHint.getY()) &&
!hitPrivacyButton(ev)
!hitButton(privacyButton, ev)
) {
privacyHint.hide();
}
if (soundTooltip != null && soundTooltip.shown() && muteIconContainer != null &&
!soundTooltip.containsTouch(ev, getX() + storyContainer.getX() + soundTooltip.getX(), getY() + storyContainer.getY() + soundTooltip.getY()) &&
!hitButton(muteIconContainer, ev)
) {
soundTooltip.hide();
}
}
private boolean hitPrivacyButton(MotionEvent e) {
float ox = getX() + storyContainer.getX() + privacyButton.getX(), oy = getY() + storyContainer.getY() + privacyButton.getY();
private boolean hitButton(View v, MotionEvent e) {
float ox = getX() + storyContainer.getX() + v.getX(), oy = getY() + storyContainer.getY() + v.getY();
return (
e.getX() >= ox && e.getX() <= ox + privacyButton.getWidth() &&
e.getY() >= oy && e.getY() <= oy + privacyButton.getHeight()
e.getX() >= ox && e.getX() <= ox + v.getWidth() &&
e.getY() >= oy && e.getY() <= oy + v.getHeight()
);
}

View file

@ -165,8 +165,8 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif
final TLRPC.TL_userStories userStories;
if (userId == 0) {
userStories = null;
} else if (stateStories != null) {
userStories = stateStories;
// } else if (stateStories != null) {
// userStories = stateStories;
} else {
userStories = userFullStories;
}

View file

@ -210,13 +210,15 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente
if (id == NotificationCenter.storiesUpdated) {
if (storyItem.uploadingStory != null) {
TLRPC.TL_userStories stories = MessagesController.getInstance(currentAccount).storiesController.getStories(UserConfig.getInstance(currentAccount).clientUserId);
for (int i = 0; i < stories.stories.size(); i++) {
TLRPC.StoryItem storyItem = stories.stories.get(i);
if (storyItem.attachPath != null && storyItem.attachPath.equals(this.storyItem.uploadingStory.path)) {
this.storyItem.uploadingStory = null;
this.storyItem.storyItem = storyItem;
setStoryItem(this.storyItem);
break;
if (stories != null) {
for (int i = 0; i < stories.stories.size(); i++) {
TLRPC.StoryItem storyItem = stories.stories.get(i);
if (storyItem.attachPath != null && storyItem.attachPath.equals(this.storyItem.uploadingStory.path)) {
this.storyItem.uploadingStory = null;
this.storyItem.storyItem = storyItem;
setStoryItem(this.storyItem);
break;
}
}
}
}

View file

@ -10,7 +10,6 @@ import androidx.annotation.NonNull;
import androidx.collection.LongSparseArray;
import com.google.android.exoplayer2.util.Consumer;
import com.google.android.exoplayer2.util.Log;
import org.telegram.SQLite.SQLiteCursor;
import org.telegram.SQLite.SQLiteDatabase;
@ -157,13 +156,18 @@ public class StoriesController {
}
private void sortDialogStories(ArrayList<TLRPC.TL_userStories> list) {
fixDeletedStories(list);
fixDeletedAndNonContactsStories(list);
Collections.sort(list, userStoriesComparator);
}
private void fixDeletedStories(ArrayList<TLRPC.TL_userStories> list) {
private void fixDeletedAndNonContactsStories(ArrayList<TLRPC.TL_userStories> list) {
for (int k = 0; k < list.size(); k++) {
TLRPC.TL_userStories userStories = list.get(k);
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(userStories.user_id);
if (user != null && !user.contact) {
list.remove(k);
k--;
}
for (int i = 0; i < userStories.stories.size(); i++) {
if (userStories.stories.get(i) instanceof TLRPC.TL_storyItemDeleted) {
userStories.stories.remove(i);
@ -578,6 +582,7 @@ public class StoriesController {
AndroidUtilities.runOnUIThread(() -> {
TLRPC.TL_userStories currentUserStory = allStoriesMap.get(updateStory.user_id);
FileLog.d("StoriesController update stories for user " + updateStory.user_id);
updateStoriesInLists(updateStory.user_id, Collections.singletonList(updateStory.story));
ArrayList<TLRPC.StoryItem> newStoryItems = new ArrayList<>();
int oldStoriesCount = totalStoriesCount;
@ -645,7 +650,6 @@ public class StoriesController {
}
notify = true;
}
updateStoriesInLists(updateStory.user_id, newStoryItems);
} else {
if (updateStory.story instanceof TLRPC.TL_storyItemDeleted) {
FileLog.d("StoriesController can't add user " + updateStory.user_id + " with new story DELETED");
@ -671,8 +675,8 @@ public class StoriesController {
if (oldStoriesCount != totalStoriesCount) {
mainSettings.edit().putInt("total_stores", totalStoriesCount).apply();
}
fixDeletedStories(dialogListStories);
fixDeletedStories(hiddenListStories);
fixDeletedAndNonContactsStories(dialogListStories);
fixDeletedAndNonContactsStories(hiddenListStories);
if (notify) {
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesUpdated);
}
@ -789,14 +793,13 @@ public class StoriesController {
req.id.add(storyItem.id);
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> {
if (error == null) {
AndroidUtilities.runOnUIThread(() -> {
updateDeletedStoriesInLists(getSelfUserId(), Arrays.asList(storyItem));
});
}
});
storiesStorage.deleteStory(getSelfUserId(), storyItem.id);
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesUpdated);
MessagesController.getInstance(currentAccount).checkArchiveFolder();
updateDeletedStoriesInLists(getSelfUserId(), Arrays.asList(storyItem));
}
public void deleteStories(ArrayList<TLRPC.StoryItem> storyItems) {
@ -2126,6 +2129,9 @@ public class StoriesController {
}
boolean contains = loadedObjects.contains(storyItem.id) || cachedObjects.contains(storyItem.id);
boolean shouldContain = type == TYPE_ARCHIVE ? true : storyItem.pinned;
if (storyItem instanceof TLRPC.TL_storyItemDeleted) {
shouldContain = false;
}
if (contains != shouldContain) {
changed = true;
if (!shouldContain) {
@ -2249,4 +2255,9 @@ public class StoriesController {
public boolean hasOnlySelfStories() {
return hasSelfStories() && (getDialogListStories().isEmpty() || (getDialogListStories().size() == 1 && getDialogListStories().get(0).user_id == UserConfig.getInstance(currentAccount).clientUserId));
}
public void sortHiddenStories() {
sortDialogStories(hiddenListStories);
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesUpdated);
}
}

View file

@ -3,9 +3,10 @@ package org.telegram.ui.Stories;
import android.graphics.Canvas;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.Cells.ChatActionCell;
import org.telegram.ui.Cells.ChatMessageCell;
@ -20,12 +21,18 @@ public class StoriesListPlaceProvider implements StoryViewer.PlaceProvider {
private final RecyclerListView recyclerListView;
int[] clipPoint = new int[2];
private boolean isHiddenArchive;
public static StoriesListPlaceProvider of(RecyclerListView recyclerListView) {
return new StoriesListPlaceProvider(recyclerListView);
return of(recyclerListView, false);
}
public StoriesListPlaceProvider(RecyclerListView recyclerListView) {
public static StoriesListPlaceProvider of(RecyclerListView recyclerListView, boolean hiddenArchive) {
return new StoriesListPlaceProvider(recyclerListView, hiddenArchive);
}
public StoriesListPlaceProvider(RecyclerListView recyclerListView, boolean hiddenArchive) {
this.recyclerListView = recyclerListView;
this.isHiddenArchive = hiddenArchive;
}
@Override
@ -38,6 +45,9 @@ public class StoriesListPlaceProvider implements StoryViewer.PlaceProvider {
r.run();
}
} else {
if (isHiddenArchive) {
MessagesController.getInstance(UserConfig.selectedAccount).getStoriesController().sortHiddenStories();
}
r.run();
}
}
@ -48,6 +58,10 @@ public class StoriesListPlaceProvider implements StoryViewer.PlaceProvider {
holder.storyImage = null;
holder.drawAbove = null;
if (recyclerListView == null) {
return false;
}
DialogStoriesCell dialogStoriesCell = null;
if (recyclerListView.getParent() instanceof DialogStoriesCell) {
dialogStoriesCell = (DialogStoriesCell) recyclerListView.getParent();
@ -75,11 +89,14 @@ public class StoriesListPlaceProvider implements StoryViewer.PlaceProvider {
}
} else if (child instanceof DialogCell) {
DialogCell cell = (DialogCell) child;
if (cell.getDialogId() == dialogId) {
if (cell.getDialogId() == dialogId || (isHiddenArchive && cell.isDialogFolder())) {
holder.view = child;
holder.params = cell.params;
holder.params = cell.storyParams;
holder.avatarImage = cell.avatarImage;
holder.clipParent = (View) cell.getParent();
if (isHiddenArchive) {
holder.crossfadeToAvatarImage = cell.avatarImage;
}
updateClip(holder);
return true;
}

View file

@ -13,6 +13,8 @@ import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.TextView;
import androidx.core.graphics.ColorUtils;
@ -102,6 +104,10 @@ public class StoriesUtilities {
int unreadState = 0;
boolean showProgress = storiesController.isLoading(dialogId);
if (params.drawHiddenStoriesAsSegments) {
hasStories = storiesController.hasHiddenStories();
}
if (params.storyItem != null) {
unreadState = storiesController.getUnreadState(dialogId, params.storyId);
state = unreadState == StoriesController.STATE_READ ? STATE_READ : STATE_HAS_UNREAD;
@ -247,7 +253,13 @@ public class StoriesUtilities {
int globalState = storiesController.getUnreadState(dialogId);
params.globalState = globalState == StoriesController.STATE_READ ? STATE_READ : STATE_HAS_UNREAD;
TLRPC.TL_userStories userStories = storiesController.getStories(params.dialogId);
if (userStories == null || userStories.stories.size() == 1) {
int storiesCount;
if (params.drawHiddenStoriesAsSegments) {
storiesCount = storiesController.getHiddenList().size();
} else {
storiesCount = userStories == null || userStories.stories.size() == 1 ? 1 : userStories.stories.size();
}
if (storiesCount == 1) {
Paint localPaint = paint;
if (storiesController.hasUnreadStories(dialogId)) {
localPaint = unreadPaint;
@ -259,9 +271,9 @@ public class StoriesUtilities {
endAngle = 270;
drawSegment(canvas, rectTmp, localPaint, startAngle, endAngle, params);
// canvas.drawCircle(rectTmp.centerX(), rectTmp.centerY(), rectTmp.width() / 2f, localPaint);
} else if (userStories != null) {
float step = 360 / (float) userStories.stories.size();
int gap = userStories.stories.size() > 20 ? 3 : 5;
} else {
float step = 360 / (float) storiesCount;
int gap = storiesCount > 20 ? 3 : 5;
float gapLen = gap * params.progressToSegments;
if (gapLen > step) {
gapLen = 0;//step * 0.4f;
@ -277,15 +289,24 @@ public class StoriesUtilities {
globalPaint = params.isStoryCell ? storyCellGreyPaint[params.isArchive ? 1 : 0] : grayPaint;
}
int maxUnread = Math.max(userStories.max_read_id, storiesController.dialogIdToMaxReadId.get(dialogId, 0));
for (int i = 0; i < userStories.stories.size(); i++) {
int maxUnread = params.drawHiddenStoriesAsSegments ? 0 : Math.max(userStories.max_read_id, storiesController.dialogIdToMaxReadId.get(dialogId, 0));
for (int i = 0; i < storiesCount; i++) {
Paint segmentPaint = params.isStoryCell ? storyCellGreyPaint[params.isArchive ? 1 : 0] : grayPaint;
if (userStories.stories.get(i).justUploaded || userStories.stories.get(i).id > maxUnread) {
if (userStories.stories.get(i).close_friends) {
if (params.drawHiddenStoriesAsSegments) {
int userUnreadState = storiesController.getUnreadState(storiesController.getHiddenList().get(storiesCount - 1 - i).user_id);
if (userUnreadState == StoriesController.STATE_UNREAD_CLOSE_FRIEND) {
segmentPaint = closeFriendsPaint;
} else {
} else if (userUnreadState == StoriesController.STATE_UNREAD) {
segmentPaint = unreadPaint;
}
} else {
if (userStories.stories.get(i).justUploaded || userStories.stories.get(i).id > maxUnread) {
if (userStories.stories.get(i).close_friends) {
segmentPaint = closeFriendsPaint;
} else {
segmentPaint = unreadPaint;
}
}
}
float startAngle = step * i - 90;
float endAngle = startAngle + step;
@ -541,6 +562,9 @@ public class StoriesUtilities {
}
public static void setImage(ImageReceiver imageReceiver, TLRPC.StoryItem storyItem, String filter) {
if (storyItem == null) {
return;
}
if (storyItem.media != null && storyItem.media.document != null) {
TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(storyItem.media.document.thumbs, Integer.MAX_VALUE);
imageReceiver.setImage(ImageLocation.getForDocument(size, storyItem.media.document), filter, null, null, ImageLoader.createStripedBitmap(storyItem.media.document.thumbs), 0, null, storyItem, 0);
@ -683,6 +707,9 @@ public class StoriesUtilities {
}
public static void applyViewedUser(TLRPC.StoryItem storyItem, TLRPC.User currentUser) {
if (currentUser == null) {
return;
}
if (storyItem.dialogId == UserConfig.getInstance(UserConfig.selectedAccount).clientUserId && !hasExpiredViews(storyItem)) {
if (storyItem.views == null) {
storyItem.views = new TLRPC.TL_storyViews();
@ -743,6 +770,7 @@ public class StoriesUtilities {
public int prevUnreadState;
public int unreadState;
public int animateFromUnreadState;
public boolean drawHiddenStoriesAsSegments;
private long dialogId;
public int currentState;
@ -795,9 +823,16 @@ public class StoriesUtilities {
Runnable longPressRunnable;
public boolean checkOnTouchEvent(MotionEvent event, View view) {
StoriesController storiesController = MessagesController.getInstance(UserConfig.selectedAccount).getStoriesController();
if (event.getAction() == MotionEvent.ACTION_DOWN && originalAvatarRect.contains(event.getX(), event.getY())) {
TLRPC.User user = MessagesController.getInstance(UserConfig.selectedAccount).getUser(dialogId);
if (dialogId != UserConfig.getInstance(UserConfig.selectedAccount).clientUserId && (MessagesController.getInstance(UserConfig.selectedAccount).getStoriesController().hasStories(dialogId) || user != null && !user.stories_unavailable && user.stories_max_id > 0)) {
boolean hasStories;
if (drawHiddenStoriesAsSegments) {
hasStories = storiesController.hasHiddenStories();
} else {
hasStories = (MessagesController.getInstance(UserConfig.selectedAccount).getStoriesController().hasStories(dialogId) || user != null && !user.stories_unavailable && user.stories_max_id > 0);
}
if (dialogId != UserConfig.getInstance(UserConfig.selectedAccount).clientUserId && hasStories) {
if (buttonBounce == null) {
buttonBounce = new ButtonBounce(view, 1.5f);
} else {
@ -817,7 +852,10 @@ public class StoriesUtilities {
if (buttonBounce != null) {
buttonBounce.setPressed(false);
}
view.getParent().requestDisallowInterceptTouchEvent(false);
ViewParent parent = view.getParent();
if (parent instanceof ViewGroup) {
((ViewGroup) parent).requestDisallowInterceptTouchEvent(false);
}
pressed = false;
onLongPress();
}, ViewConfiguration.getLongPressTimeout());
@ -843,7 +881,10 @@ public class StoriesUtilities {
if (pressed && event.getAction() == MotionEvent.ACTION_UP) {
processOpenStory(view);
}
view.getParent().requestDisallowInterceptTouchEvent(false);
ViewParent parent = view.getParent();
if (parent instanceof ViewGroup) {
((ViewGroup) parent).requestDisallowInterceptTouchEvent(false);
}
pressed = false;
if (longPressRunnable != null) {
AndroidUtilities.cancelRunOnUIThread(longPressRunnable);
@ -860,6 +901,10 @@ public class StoriesUtilities {
int currentAccount = UserConfig.selectedAccount;
MessagesController messagesController = MessagesController.getInstance(UserConfig.selectedAccount);
StoriesController storiesController = messagesController.getStoriesController();
if (drawHiddenStoriesAsSegments) {
openStory(0, null);
return;
}
if (dialogId != UserConfig.getInstance(UserConfig.selectedAccount).getClientUserId()) {
if (storiesController.hasStories(dialogId)) {
openStory(dialogId, null);

View file

@ -82,6 +82,7 @@ public class StoriesViewPager extends ViewPager {
pageLayout.peerStoryView = view;
view.setAccount(currentAccount);
view.setDelegate(delegate);
view.setLongpressed(storyViewer.isLongpressed);
pageLayout.setTag(position);
pageLayout.dialogId = dialogs.get(position);
pageLayout.addView(view);

View file

@ -21,6 +21,7 @@ import android.text.Spannable;
import android.text.SpannableString;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.style.CharacterStyle;
import android.text.style.ClickableSpan;
import android.text.style.URLSpan;
import android.view.MotionEvent;
@ -55,6 +56,7 @@ import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.LinkPath;
import org.telegram.ui.Components.LinkSpanDrawable;
import org.telegram.ui.Components.StaticLayoutEx;
import org.telegram.ui.Components.URLSpanMono;
import org.telegram.ui.Components.spoilers.SpoilerEffect;
import org.telegram.ui.Components.spoilers.SpoilersClickDetector;
import org.telegram.ui.Components.spoilers.SpoilersTextView;
@ -151,7 +153,7 @@ public class StoryCaptionView extends NestedScrollView {
}
public void onLinkClick(ClickableSpan span, View spoilersTextView) {
public void onLinkClick(CharacterStyle span, View spoilersTextView) {
}
@ -540,7 +542,7 @@ public class StoryCaptionView extends NestedScrollView {
public class StoryCaptionTextView extends View {
private final PorterDuffColorFilter emojiColorFilter;
private LinkSpanDrawable<ClickableSpan> pressedLink;
private LinkSpanDrawable<CharacterStyle> pressedLink;
private AnimatedEmojiSpan pressedEmoji;
private LinkSpanDrawable.LinkCollector links = new LinkSpanDrawable.LinkCollector(this);
@ -783,7 +785,7 @@ public class StoryCaptionView extends NestedScrollView {
if (Build.VERSION.SDK_INT >= 24) {
return StaticLayout.Builder.obtain(string, 0, string.length(), textPaint, width).setBreakStrategy(StaticLayout.BREAK_STRATEGY_SIMPLE).setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE).setAlignment(LocaleController.isRTL ? StaticLayoutEx.ALIGN_RIGHT() : StaticLayoutEx.ALIGN_LEFT()).build();
} else {
return new StaticLayout(string, Theme.profile_aboutTextPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
return new StaticLayout(string, textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
}
}
@ -818,11 +820,14 @@ public class StoryCaptionView extends NestedScrollView {
final int off = fullLayout.getOffsetForHorizontal(line, x);
final float left = fullLayout.getLineLeft(line);
ClickableSpan touchLink = null;
CharacterStyle touchLink = null;
AnimatedEmojiSpan touchEmoji = null;
if (left <= x && left + fullLayout.getLineWidth(line) >= x && y >= 0 && y <= fullLayout.getHeight()) {
Spannable buffer = new SpannableString(text);
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
CharacterStyle[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link == null || link.length == 0) {
link = buffer.getSpans(off, off, URLSpanMono.class);
}
if (link != null && link.length != 0) {
touchLink = link[0];
if (event.getAction() == MotionEvent.ACTION_DOWN) {
@ -838,7 +843,7 @@ public class StoryCaptionView extends NestedScrollView {
path.setCurrentLayout(fullLayout, start, getPaddingTop());
fullLayout.getSelectionPath(start, end, path);
final LinkSpanDrawable<ClickableSpan> savedPressedLink = pressedLink;
final LinkSpanDrawable<CharacterStyle> savedPressedLink = pressedLink;
postDelayed(() -> {
if (savedPressedLink == pressedLink && pressedLink != null && pressedLink.getSpan() instanceof URLSpan) {
onLinkLongPress((URLSpan) pressedLink.getSpan(), this, () -> links.clear());

View file

@ -125,15 +125,16 @@ public class StoryContainsEmojiButton extends View {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final boolean exactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY;
final int height = getPaddingTop() + AndroidUtilities.lerp(dp(29), layout == null ? dp(29) : layout.getHeight(), loadT) + getPaddingBottom();
setMeasuredDimension(exactly ? MeasureSpec.getSize(widthMeasureSpec) : getMinimumWidth(), height);
final int contentWidth = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
if (exactly && (toSetText != null || layout != null && lastContentWidth != contentWidth)) {
setText(toSetText != null ? toSetText : layout.getText());
toSetText = null;
lastContentWidth = contentWidth;
}
final int height = getPaddingTop() + AndroidUtilities.lerp(dp(29), layout == null ? dp(29) : layout.getHeight(), loadT) + getPaddingBottom();
setMeasuredDimension(exactly ? MeasureSpec.getSize(widthMeasureSpec) : getMinimumWidth(), height);
}
@Override
@ -207,6 +208,9 @@ public class StoryContainsEmojiButton extends View {
req.media = inputStickeredMediaDocument;
}
final RequestDelegate requestDelegate = (response, error) -> AndroidUtilities.runOnUIThread(() -> {
if (response == null) {
return;
}
TLRPC.Vector vector = this.vector = (TLRPC.Vector) response;
lastRequestParentObject = parentObject;
lastResponse = vector;

View file

@ -118,6 +118,7 @@ public class StoryViewer {
float fromWidth;
float fromHeight;
RectF avatarRectTmp = new RectF();
float progressToOpen;
float progressToDismiss;
float swipeToDismissOffset;
@ -185,7 +186,7 @@ public class StoryViewer {
private static boolean runOpenAnimationAfterLayout;
private boolean isPopupVisible;
private boolean isLongpressed;
public boolean isLongpressed;
Runnable longPressRunnable = () -> setLongPressed(true);
@ -225,7 +226,12 @@ public class StoryViewer {
if (isLongpressed != b) {
isLongpressed = b;
updatePlayingMode();
storiesViewPager.getCurrentPeerView().setLongpressed(isLongpressed);
if (storiesViewPager != null) {
PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView();
if (peerStoriesView != null) {
peerStoriesView.setLongpressed(isLongpressed);
}
}
}
}
@ -474,6 +480,15 @@ public class StoryViewer {
final RectF outFromRectAvatar = new RectF();
final RectF outFromRectContainer = new RectF();
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (child == aspectRatioFrameLayout) {
return false;
}
return super.drawChild(canvas, child, drawingTime);
}
@Override
protected void dispatchDraw(Canvas canvas) {
float blackoutAlpha = getBlackoutAlpha();
@ -669,12 +684,36 @@ public class StoryViewer {
AndroidUtilities.lerp(rect1, rect2, progressToOpen, AndroidUtilities.rectTmp);
if (animateAvatar) {
headerView.backupImageView.getImageReceiver().setImageCoords(AndroidUtilities.rectTmp);
headerView.backupImageView.getImageReceiver().setRoundRadius((int) (AndroidUtilities.rectTmp.width() / 2f));
headerView.backupImageView.getImageReceiver().setVisible(true, false);
headerView.drawUploadingProgress(canvas, AndroidUtilities.rectTmp, !runOpenAnimationAfterLayout, progressToOpen);
headerView.backupImageView.getImageReceiver().draw(canvas);
headerView.backupImageView.getImageReceiver().setVisible(false, false);
boolean crossfade = transitionViewHolder != null && transitionViewHolder.crossfadeToAvatarImage != null;
if (!crossfade || progressToOpen != 0) {
headerView.backupImageView.getImageReceiver().setImageCoords(AndroidUtilities.rectTmp);
headerView.backupImageView.getImageReceiver().setRoundRadius((int) (AndroidUtilities.rectTmp.width() / 2f));
headerView.backupImageView.getImageReceiver().setVisible(true, false);
headerView.backupImageView.getImageReceiver().setAlpha(crossfade ? progressToOpen : 1f);
headerView.drawUploadingProgress(canvas, AndroidUtilities.rectTmp, !runOpenAnimationAfterLayout, progressToOpen);
headerView.backupImageView.getImageReceiver().draw(canvas);
headerView.backupImageView.getImageReceiver().setVisible(false, false);
}
if (progressToOpen != 1f && crossfade) {
avatarRectTmp.set(
transitionViewHolder.crossfadeToAvatarImage.getImageX(),
transitionViewHolder.crossfadeToAvatarImage.getImageY(),
transitionViewHolder.crossfadeToAvatarImage.getImageX2(),
transitionViewHolder.crossfadeToAvatarImage.getImageY2()
);
int oldRadius = transitionViewHolder.crossfadeToAvatarImage.getRoundRadius()[0];
boolean isVisible = transitionViewHolder.crossfadeToAvatarImage.getVisible();
transitionViewHolder.crossfadeToAvatarImage.setImageCoords(AndroidUtilities.rectTmp);
transitionViewHolder.crossfadeToAvatarImage.setRoundRadius((int) (AndroidUtilities.rectTmp.width() / 2f));
transitionViewHolder.crossfadeToAvatarImage.setVisible(true, false);
canvas.saveLayerAlpha(AndroidUtilities.rectTmp, (int) (255 * (1f - progressToOpen)), Canvas.ALL_SAVE_FLAG);
transitionViewHolder.crossfadeToAvatarImage.draw(canvas);
canvas.restore();
transitionViewHolder.crossfadeToAvatarImage.setVisible(isVisible, false);
transitionViewHolder.crossfadeToAvatarImage.setImageCoords(avatarRectTmp);
transitionViewHolder.crossfadeToAvatarImage.setRoundRadius(oldRadius);
// transitionViewHolder.crossfadeToAvatarImage.setVisible(false, false);
}
}
}
@ -759,7 +798,7 @@ public class StoryViewer {
boolean override = false;
boolean enableTouch = !keyboardVisible && !isClosed && !isRecording;
if (selfStoriesViewsOffset == 0 && !inSwipeToDissmissMode && storiesViewPager.currentState == ViewPager.SCROLL_STATE_DRAGGING && ev.getAction() == MotionEvent.ACTION_MOVE && enableTouch) {
float dx = lastX.get(ev.getPointerId(0)) - ev.getX(0);
float dx = lastX.get(ev.getPointerId(0), 0f) - ev.getX(0);
if (dx != 0 && !storiesViewPager.canScroll(dx) || swipeToDismissHorizontalOffset != 0) {
if (swipeToDismissHorizontalOffset == 0) {
swipeToDismissHorizontalDirection = -dx;
@ -968,14 +1007,6 @@ public class StoryViewer {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (child == aspectRatioFrameLayout) {
return true;
}
return super.drawChild(canvas, child, drawingTime);
}
@Override
protected void dispatchDraw(Canvas canvas) {
PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView();
@ -1175,6 +1206,7 @@ public class StoryViewer {
currentPlayerScope.textureView = textureView;
currentPlayerScope.surfaceView = surfaceView;
FileStreamLoadOperation.setPriorityForDocument(playerHolder.document, FileLoader.PRIORITY_HIGH);
FileLoader.getInstance(currentAccount).changePriority(FileLoader.PRIORITY_HIGH, playerHolder.document, null, null, null, null, null);
currentPlayerScope.player.start(isPaused(), uri, t, isInSilentMode);
currentPlayerScope.invalidate();
}
@ -1266,10 +1298,6 @@ public class StoryViewer {
uries.remove(j);
}
}
if (!found) {
preparedPlayers.remove(i).release(null);
i--;
}
}
for (int i = 0; i < uries.size(); i++) {
Uri uri = uries.get(i);
@ -1284,21 +1312,14 @@ public class StoryViewer {
player.release(null);
}
}
}
});
containerView.addView(storiesViewPager, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER_HORIZONTAL));
aspectRatioFrameLayout = new AspectRatioFrameLayout(context);
if (USE_SURFACE_VIEW) {
surfaceView = new SurfaceView(context) {
@Override
public void invalidate() {
super.invalidate();
if (currentPlayerScope != null) {
currentPlayerScope.invalidate();
}
}
};
surfaceView = new SurfaceView(context);
surfaceView.setZOrderMediaOverlay(false);
surfaceView.setZOrderOnTop(false);
//surfaceView.setZOrderMediaOverlay(true);
aspectRatioFrameLayout.addView(surfaceView);
} else {
@ -1315,12 +1336,14 @@ public class StoryViewer {
}
containerView.addView(aspectRatioFrameLayout);
volumeControl = new StoriesVolumeContorl(context);
containerView.addView(volumeControl, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 4, 0, 4, 0));
}
AndroidUtilities.removeFromParent(containerView);
windowView.addView(containerView);
AndroidUtilities.removeFromParent(aspectRatioFrameLayout);
windowView.addView(aspectRatioFrameLayout);
windowView.setClipChildren(false);
if (ATTACH_TO_FRAGMENT) {
@ -1480,11 +1503,13 @@ public class StoryViewer {
if (page == null || page.storyContainer == null) {
return false;
}
float x = windowView == null ? 0 : windowView.getX();
float y = windowView == null ? 0 : windowView.getY();
rectF.set(
windowView.getX() + swipeToDismissHorizontalOffset + containerView.getLeft() + page.getX() + page.storyContainer.getX(),
windowView.getY() + swipeToDismissOffset + containerView.getTop() + page.getY() + page.storyContainer.getY(),
windowView.getX() + swipeToDismissHorizontalOffset + containerView.getRight() - (containerView.getWidth() - page.getRight()) - (page.getWidth() - page.storyContainer.getRight()),
windowView.getY() + swipeToDismissOffset + containerView.getBottom() - (containerView.getHeight() - page.getBottom()) - (page.getHeight() - page.storyContainer.getBottom())
x + swipeToDismissHorizontalOffset + containerView.getLeft() + page.getX() + page.storyContainer.getX(),
y + swipeToDismissOffset + containerView.getTop() + page.getY() + page.storyContainer.getY(),
x + swipeToDismissHorizontalOffset + containerView.getRight() - (containerView.getWidth() - page.getRight()) - (page.getWidth() - page.storyContainer.getRight()),
y + swipeToDismissOffset + containerView.getBottom() - (containerView.getHeight() - page.getBottom()) - (page.getHeight() - page.storyContainer.getBottom())
);
return true;
}
@ -1524,10 +1549,10 @@ public class StoryViewer {
public void toggleSilentMode() {
isInSilentMode = !isInSilentMode;
if (playerHolder != null) {
playerHolder.setAudioEnabled(!isInSilentMode);
playerHolder.setAudioEnabled(!isInSilentMode, false);
}
for (int i = 0; i < preparedPlayers.size(); i++) {
preparedPlayers.get(i).setAudioEnabled(!isInSilentMode);
preparedPlayers.get(i).setAudioEnabled(!isInSilentMode, true);
}
PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView();
peerStoriesView.sharedResources.setIconMuted(!soundEnabled(), true);
@ -1758,7 +1783,10 @@ public class StoryViewer {
if (progressToDismiss != newProgress) {
progressToDismiss = newProgress;
checkNavBarColor();
storiesViewPager.getCurrentPeerView().progressToDismissUpdated();
PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView();
if (peerStoriesView != null) {
peerStoriesView.progressToDismissUpdated();
}
}
if (windowView != null) {
@ -2137,10 +2165,12 @@ public class StoryViewer {
surfaceView.setSecure(!allowScreenshots);
}
if (ATTACH_TO_FRAGMENT) {
if (allowScreenshots) {
fragment.getParentActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
} else {
fragment.getParentActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
if (fragment.getParentActivity() != null) {
if (allowScreenshots) {
fragment.getParentActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
} else {
fragment.getParentActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
}
} else {
if (allowScreenshots) {
@ -2160,6 +2190,9 @@ public class StoryViewer {
public void openFor(BaseFragment fragment, RecyclerListView recyclerListView, ChatActionCell cell) {
MessageObject messageObject = cell.getMessageObject();
if (fragment == null || fragment.getContext() == null) {
return;
}
if (messageObject.type == MessageObject.TYPE_STORY_MENTION) {
TLRPC.StoryItem storyItem = messageObject.messageOwner.media.storyItem;
storyItem.dialogId = messageObject.messageOwner.media.user_id;
@ -2196,6 +2229,7 @@ public class StoryViewer {
public View clipParent;
public float clipTop;
public float clipBottom;
public ImageReceiver crossfadeToAvatarImage;
StoriesUtilities.AvatarStoryParams params;
public void clear() {
@ -2207,6 +2241,7 @@ public class StoryViewer {
drawClip = null;
clipParent = null;
radialProgressUpload = null;
crossfadeToAvatarImage = null;
clipTop = 0;
clipBottom = 0;
}
@ -2474,7 +2509,7 @@ public class StoryViewer {
});
}
public void setAudioEnabled(boolean enabled) {
public void setAudioEnabled(boolean enabled, boolean prepared) {
boolean disabled = !enabled;
if (audioDisabled == disabled) {
return;
@ -2494,7 +2529,7 @@ public class StoryViewer {
ensurePlayerCreated(audioDisabled);
videoPlayer.preparePlayer(uri, "other");
videoPlayer.setWorkerQueue(dispatchQueue);
if (currentPlayerScope != null) {
if (!prepared) {
if (USE_SURFACE_VIEW) {
videoPlayer.setSurfaceView(surfaceView);
} else {
@ -2503,7 +2538,7 @@ public class StoryViewer {
}
// videoPlayer.setTextureView(textureView);
videoPlayer.seekTo(position + 50);
if (playing) {
if (playing && !prepared) {
videoPlayer.setPlayWhenReady(true);
videoPlayer.play();
} else {

View file

@ -19,6 +19,7 @@ import androidx.annotation.NonNull;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.R;
import org.telegram.ui.Components.AnimatedFloat;
import org.telegram.ui.Components.AnimatedTextView;
import org.telegram.ui.Components.CubicBezierInterpolator;

View file

@ -482,13 +482,29 @@ public class DualCameraView extends CameraView implements CameraController.Error
-862041025, // XIAOMI WILLOW
-1258375037, // XIAOMI INGRES
-1320049076, // XIAOMI GINKGO
-215749424, // XIAOMI LISA
1901578030, // XIAOMI LEMON
-215451421, // XIAOMI VIVA
1908491424, // XIAOMI STONE
-1321491332, // XIAOMI RAPHAEL
-1155551678, // XIAOMI MARBLE
1908524435, // XIAOMI SURYA
976847578, // XIAOMI LAUREL_SPROUT
-713271737, // OPPO OP4F2F
-2010722764, // SAMSUNG A52SXQ (A52s 5G)
1407170066, // SAMSUNG D2Q (Note10+)
-1394190055, // SAMSUNG B4Q
1407170066, // HUAWEI HWNAM
1407159934, // HUAWEI HWCOR
1407172057, // HUAWEI HWPCT
1231389747, // FAIRPHONE FP3
-2076538925, // MOTOROLA RSTAR
41497626, // MOTOROLA RHODEC
846150482, // MOTOROLA CHANNEL
-1198092731, // MOTOROLA CYPRUS64
-251277614, // MOTOROLA HANOIP
-2078385967, // MOTOROLA PSTAR
// -1426053134 // REALME REE2ADL1
};
private static final int[] dualWhitelistByModel = new int[] {

View file

@ -1917,7 +1917,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter.
if (emojiLayout != null) {
canvas.save();
canvas.translate(emojiRect.left + dp(12) + emojiLayoutLeft, emojiRect.top + (emojiRect.height() - emojiLayout.getHeight()) / 2f);
canvas.translate(emojiRect.left + dp(12) - emojiLayoutLeft, emojiRect.top + (emojiRect.height() - emojiLayout.getHeight()) / 2f);
textPaint.setColor(ColorUtils.blendARGB(0xFF838383, 0xFFFFFFFF, Utilities.clamp(1f - Math.abs(type - 0), 1, 0)));
emojiLayout.draw(canvas);
canvas.restore();
@ -1925,7 +1925,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter.
if (stickersLayout != null) {
canvas.save();
canvas.translate(stickersRect.left + dp(12) + stickersLayoutLeft, stickersRect.top + (stickersRect.height() - stickersLayout.getHeight()) / 2f);
canvas.translate(stickersRect.left + dp(12) - stickersLayoutLeft, stickersRect.top + (stickersRect.height() - stickersLayout.getHeight()) / 2f);
textPaint.setColor(ColorUtils.blendARGB(0xFF838383, 0xFFFFFFFF, Utilities.clamp(1f - Math.abs(type - 1), 1, 0)));
stickersLayout.draw(canvas);
canvas.restore();
@ -1933,7 +1933,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter.
if (masksLayout != null) {
canvas.save();
canvas.translate(masksRect.left + dp(12) + masksLayoutLeft, masksRect.top + (masksRect.height() - masksLayout.getHeight()) / 2f);
canvas.translate(masksRect.left + dp(12) - masksLayoutLeft, masksRect.top + (masksRect.height() - masksLayout.getHeight()) / 2f);
textPaint.setColor(ColorUtils.blendARGB(0xFF838383, 0xFFFFFFFF, Utilities.clamp(1f - Math.abs(type - 2), 1, 0)));
masksLayout.draw(canvas);
canvas.restore();

View file

@ -923,7 +923,7 @@ public class GalleryListView extends FrameLayout implements NotificationCenter.N
setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
setPadding(dp(16), dp(16), dp(21), dp(10));
setText(LocaleController.getString(onlyPhotos ? R.string.ChoosePhoto : R.string.ChoosePhotoOrVideo));
setText(LocaleController.getString(onlyPhotos ? R.string.AddImage : R.string.ChoosePhotoOrVideo));
}
}

View file

@ -26,6 +26,7 @@ public class HintTextView extends View {
textDrawable.getPaint().setShadowLayer(AndroidUtilities.dp(1.4f), 0, AndroidUtilities.dp(.4f), 0x4C000000);
textDrawable.setGravity(Gravity.CENTER_HORIZONTAL);
textDrawable.setCallback(this);
textDrawable.setOverrideFullWidth(AndroidUtilities.displaySize.x);
}
public void setText(CharSequence text, boolean animated) {
@ -45,4 +46,10 @@ public class HintTextView extends View {
protected boolean verifyDrawable(@NonNull Drawable who) {
return who == textDrawable || super.verifyDrawable(who);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
textDrawable.setOverrideFullWidth(getMeasuredWidth());
}
}

View file

@ -86,6 +86,7 @@ public class HintView2 extends View {
private float textX, textY;
private boolean hideByTouch = true;
private boolean repeatedBounce = true;
private boolean shown;
private AnimatedFloat show = new AnimatedFloat(this, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
@ -185,6 +186,18 @@ public class HintView2 extends View {
return this;
}
private static boolean contains(CharSequence text, char c) {
if (text == null) {
return false;
}
for (int i = 0; i < text.length(); ++i) {
if (text.charAt(i) == c) {
return true;
}
}
return false;
}
// returns max width
public static int cutInFancyHalf(CharSequence text, TextPaint paint) {
if (text == null) {
@ -257,6 +270,11 @@ public class HintView2 extends View {
return this;
}
public HintView2 setBounce(boolean enable) {
repeatedBounce = enable;
return this;
}
// works only for multiline=true
public HintView2 setTextAlign(Layout.Alignment alignment) {
textLayoutAlignment = alignment;
@ -318,6 +336,9 @@ public class HintView2 extends View {
private ValueAnimator bounceAnimator;
private float bounceT = 1;
private void bounceShow() {
if (!repeatedBounce) {
return;
}
if (bounceAnimator != null) {
bounceAnimator.cancel();
bounceAnimator = null;
@ -487,7 +508,7 @@ public class HintView2 extends View {
backgroundPaint.setAlpha(wasAlpha);
if (multiline) {
canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), (int) (0xFF * alpha), Canvas.ALL_SAVE_FLAG);
canvas.saveLayerAlpha(0, 0, getWidth(), Math.max(getHeight(), height), (int) (0xFF * alpha), Canvas.ALL_SAVE_FLAG);
canvas.translate(textX = bounds.left + innerPadding.left - textLayoutLeft, textY = bounds.top + innerPadding.top);
if (links.draw(canvas)) {
invalidate();

View file

@ -2739,8 +2739,9 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai
deleteView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem));
deleteView.setBackground(Theme.getSelectorDrawable(false));
deleteView.setGravity(Gravity.CENTER_VERTICAL);
deleteView.setEllipsize(TextUtils.TruncateAt.END);
deleteView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(14), 0);
deleteView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
deleteView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
deleteView.setTag(0);
deleteView.setText(LocaleController.getString("PaintDelete", R.string.PaintDelete));
deleteView.setOnClickListener(v -> {
@ -2757,8 +2758,9 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai
editView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem));
editView.setBackground(Theme.getSelectorDrawable(false));
editView.setGravity(Gravity.CENTER_VERTICAL);
editView.setEllipsize(TextUtils.TruncateAt.END);
editView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0);
editView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
editView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
if ((keyboardNotifier.keyboardVisible() && !keyboardNotifier.ignoring) || emojiPadding > 0) {
editView.setTag(3);
editView.setText(LocaleController.getString("Paste", R.string.Paste));
@ -2791,9 +2793,10 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai
TextView flipView = new TextView(getContext());
flipView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem));
flipView.setBackground(Theme.getSelectorDrawable(false));
flipView.setEllipsize(TextUtils.TruncateAt.END);
flipView.setGravity(Gravity.CENTER_VERTICAL);
flipView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0);
flipView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
flipView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
flipView.setTag(4);
flipView.setText(LocaleController.getString(R.string.Flip));
flipView.setOnClickListener(v -> {
@ -2809,22 +2812,25 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai
parent.addView(flipView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 48));
}
TextView duplicateView = new TextView(getContext());
duplicateView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem));
duplicateView.setBackgroundDrawable(Theme.getSelectorDrawable(false));
duplicateView.setGravity(Gravity.CENTER_VERTICAL);
duplicateView.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(16), 0);
duplicateView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
duplicateView.setTag(2);
duplicateView.setText(LocaleController.getString("PaintDuplicate", R.string.PaintDuplicate));
duplicateView.setOnClickListener(v -> {
duplicateEntity(entityView);
if (!(entityView instanceof PhotoView)) {
TextView duplicateView = new TextView(getContext());
duplicateView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem));
duplicateView.setBackground(Theme.getSelectorDrawable(false));
duplicateView.setEllipsize(TextUtils.TruncateAt.END);
duplicateView.setGravity(Gravity.CENTER_VERTICAL);
duplicateView.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(16), 0);
duplicateView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
duplicateView.setTag(2);
duplicateView.setText(LocaleController.getString("PaintDuplicate", R.string.PaintDuplicate));
duplicateView.setOnClickListener(v -> {
duplicateEntity(entityView);
if (popupWindow != null && popupWindow.isShowing()) {
popupWindow.dismiss(true);
}
});
parent.addView(duplicateView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 48));
if (popupWindow != null && popupWindow.isShowing()) {
popupWindow.dismiss(true);
}
});
parent.addView(duplicateView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 48));
}
popupLayout.addView(parent);
@ -2855,6 +2861,8 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai
newTextPaintView.setMaxWidth(w - AndroidUtilities.dp(7 + 7 + 18));
entitiesView.addView(newTextPaintView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT));
entityView = newTextPaintView;
} else {
return;
}
registerRemovalUndo(entityView);
@ -3192,6 +3200,9 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai
}
private void registerRemovalUndo(final EntityView entityView) {
if (entityView == null) {
return;
}
undoStore.registerUndo(entityView.getUUID(), () -> removeEntity(entityView));
}

View file

@ -278,6 +278,10 @@ public class PreviewView extends FrameLayout {
}
}
}
if (imageId < 0 && entry.isVideo && entry.thumbPath == null) {
invalidate();
return;
}
if (bitmap == null) {
String path = entry.getOriginalFile().getPath();
BitmapFactory.Options options = new BitmapFactory.Options();
@ -286,7 +290,13 @@ public class PreviewView extends FrameLayout {
if (entry.thumbPath != null) {
BitmapFactory.decodeFile(entry.thumbPath, options);
} else {
MediaStore.Video.Thumbnails.getThumbnail(getContext().getContentResolver(), imageId, MediaStore.Video.Thumbnails.MINI_KIND, options);
try {
MediaStore.Video.Thumbnails.getThumbnail(getContext().getContentResolver(), imageId, MediaStore.Video.Thumbnails.MINI_KIND, options);
} catch (Throwable e) {
bitmap = null;
invalidate();
return;
}
}
} else {
BitmapFactory.decodeFile(path, options);
@ -298,7 +308,13 @@ public class PreviewView extends FrameLayout {
if (entry.thumbPath != null) {
BitmapFactory.decodeFile(entry.thumbPath, options);
} else {
bitmap = MediaStore.Video.Thumbnails.getThumbnail(getContext().getContentResolver(), imageId, MediaStore.Video.Thumbnails.MINI_KIND, options);
try {
bitmap = MediaStore.Video.Thumbnails.getThumbnail(getContext().getContentResolver(), imageId, MediaStore.Video.Thumbnails.MINI_KIND, options);
} catch (Throwable e) {
bitmap = null;
invalidate();
return;
}
}
} else {
bitmap = BitmapFactory.decodeFile(path, options);
@ -459,7 +475,9 @@ public class PreviewView extends FrameLayout {
addView(textureView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT));
entry.detectHDR((hdrInfo) -> {
textureView.setHDRInfo(hdrInfo);
if (textureView != null) {
textureView.setHDRInfo(hdrInfo);
}
});
Uri uri = Uri.fromFile(entry.getOriginalFile());

View file

@ -571,8 +571,8 @@ public class StoryEntry extends IStoryPart {
long usedMemory = runtime.totalMemory() - runtime.freeMemory();
long availableMemory = maxMemory - usedMemory;
final boolean enoughMemory = options.outWidth * options.outHeight * 4L * 2L <= availableMemory;
if (!enoughMemory) {
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
if (!enoughMemory || Math.max(options.outWidth, options.outHeight) > 4200 || SharedConfig.getDevicePerformanceClass() <= SharedConfig.PERFORMANCE_CLASS_LOW) {
// options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inScaled = true;
options.inDensity = options.outWidth;
options.inTargetDensity = reqWidth;

View file

@ -879,7 +879,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
selectedUsers.addAll(selectedContacts);
selectedUsersByGroup.putAll(selectedContactsByGroup);
}
layoutManager.setReverseLayout(pageType == PAGE_TYPE_SHARE);
layoutManager.setReverseLayout(adapter.reversedLayout = pageType == PAGE_TYPE_SHARE);
updateSpans(false);
searchField.setText("");
searchField.setVisibility(pageType == PAGE_TYPE_SHARE ? View.GONE : View.VISIBLE);
@ -912,7 +912,9 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
sectionCell.setVisibility(View.GONE);
// items.add(ItemInner.asPad(dp(84) + 4 * dp(56) + (sendAsMessageEnabled ? dp(120) : dp(64))));
items.add(ItemInner.asHeader2(
LocaleController.getString("StoryPrivacyAlertTitle", R.string.StoryPrivacyAlertTitle),
isEdit ?
LocaleController.getString("StoryPrivacyAlertEditTitle", R.string.StoryPrivacyAlertEditTitle) :
LocaleController.getString("StoryPrivacyAlertTitle", R.string.StoryPrivacyAlertTitle),
storyPeriod != Integer.MAX_VALUE ?
LocaleController.formatPluralString("StoryPrivacyAlertSubtitle", storyPeriod / 3600) :
LocaleController.getString("StoryPrivacyAlertSubtitleProfile", R.string.StoryPrivacyAlertSubtitleProfile)
@ -1300,7 +1302,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
} else if (pageType == PAGE_TYPE_SEND_AS_MESSAGE) {
button.setShowZero(true);
button.setEnabled(!selectedUsers.isEmpty());
button.setText(LocaleController.formatPluralString("StoryPrivacyButtonMessageChats", selectedUsers.size()), animated);
// button.setText(LocaleController.formatPluralString("StoryPrivacyButtonMessageChats", selectedUsers.size()), animated);
button.setCount(selectedUsers.size(), animated);
button2.setVisibility(View.GONE);
}
@ -1536,6 +1538,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
}
private RecyclerListView listView;
public boolean reversedLayout;
@Override
public boolean isEnabled(RecyclerView.ViewHolder holder) {
@ -1587,8 +1590,8 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
}
final ItemInner item = items.get(position);
final int viewType = holder.getItemViewType();
final ItemInner nextItem = position + 1 < items.size() ? items.get(position + 1) : null;
final boolean divider = nextItem != null && nextItem.viewType == viewType;
final ItemInner neighbour = reversedLayout ? (position > 0 ? items.get(position - 1) : null) : (position + 1 < items.size() ? items.get(position + 1) : null);
final boolean divider = neighbour != null && neighbour.viewType == viewType;
if (viewType == VIEW_TYPE_USER) {
UserCell userCell = (UserCell) holder.itemView;
if (item.type > 0) {
@ -2539,7 +2542,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
}
}
private static class HeaderCell2 extends FrameLayout {
private static class HeaderCell2 extends LinearLayout {
private final Theme.ResourcesProvider resourcesProvider;
private final TextView titleTextView;
@ -2547,27 +2550,19 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
public HeaderCell2(Context context, Theme.ResourcesProvider resourcesProvider) {
super(context);
setOrientation(VERTICAL);
this.resourcesProvider = resourcesProvider;
titleTextView = new TextView(context);
titleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider));
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL, 27, 16, 27, 0));
addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL, 27, 16, 27, 0));
subtitleTextView = new TextView(context);
subtitleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray2, resourcesProvider));
subtitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
NotificationCenter.listenEmojiLoading(subtitleTextView);
addView(subtitleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL, 27, 44, 27, 0));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(
MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(dp(72), MeasureSpec.EXACTLY)
);
addView(subtitleTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL, 27, 5, 27, 13));
}
public void setText(CharSequence title, CharSequence subtitle) {

View file

@ -106,6 +106,7 @@ import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.SimpleTextView;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.AlertsCreator;
import org.telegram.ui.Components.Bulletin;
@ -460,6 +461,9 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
}
if (outputEntry != null) {
if (wasSend && outputEntry.isEdit) {
outputEntry.editedMedia = false;
}
outputEntry.destroy(false);
outputEntry = null;
}
@ -561,6 +565,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
private void onOpenDone() {
isShown = true;
wasSend = false;
if (openType == 1) {
previewContainer.setAlpha(1f);
previewContainer.setTranslationX(0);
@ -1303,7 +1308,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
private FrameLayout navbarContainer;
private ImageView backButton;
private TextView titleTextView;
private SimpleTextView titleTextView;
private StoryPrivacyBottomSheet privacySheet;
/* PAGE_CAMERA */
@ -1609,16 +1614,18 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
});
actionBarContainer.addView(backButton, LayoutHelper.createFrame(56, 56, Gravity.TOP | Gravity.LEFT));
titleTextView = new TextView(context);
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
titleTextView = new SimpleTextView(context);
titleTextView.setTextSize(20);
titleTextView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
titleTextView.setTextColor(0xffffffff);
titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
titleTextView.setText(LocaleController.getString("RecorderNewStory", R.string.RecorderNewStory));
titleTextView.setShadowLayer(dpf2(1), 0, 1, 0x40000000);
titleTextView.getPaint().setShadowLayer(dpf2(1), 0, 1, 0x40000000);
titleTextView.setAlpha(0f);
titleTextView.setVisibility(View.GONE);
actionBarContainer.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 56, Gravity.TOP | Gravity.FILL_HORIZONTAL, 71, 0, 96, 0));
titleTextView.setEllipsizeByGradient(true);
titleTextView.setRightPadding(AndroidUtilities.dp(96));
actionBarContainer.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 56, Gravity.TOP | Gravity.FILL_HORIZONTAL, 71, 0, 0, 0));
downloadButton = new DownloadButton(context, () -> {
applyFilter();
@ -1626,7 +1633,11 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
}, currentAccount, windowView, resourcesProvider);
actionBarContainer.addView(downloadButton, LayoutHelper.createFrame(56, 56, Gravity.TOP | Gravity.RIGHT));
muteHint = new HintView2(activity, HintView2.DIRECTION_TOP).setJoint(1, -68).setDuration(2000);
muteHint = new HintView2(activity, HintView2.DIRECTION_TOP)
.setJoint(1, -68)
.setDuration(2000)
.setBounce(false)
.setAnimatedTextHacks(true, true, false);
muteHint.setPadding(dp(8), 0, dp(8), 0);
actionBarContainer.addView(muteHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP, 0, 52, 0, 0));
@ -1640,7 +1651,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
return;
}
outputEntry.muted = !outputEntry.muted;
muteHint.setText(outputEntry.muted ? LocaleController.getString("StorySoundMuted") : LocaleController.getString("StorySoundNotMuted"), true);
muteHint.setText(outputEntry.muted ? LocaleController.getString("StorySoundMuted") : LocaleController.getString("StorySoundNotMuted"), muteHint.shown());
muteHint.show();
setIconMuted(outputEntry.muted, true);
previewView.mute(outputEntry.muted);
@ -1703,8 +1714,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
savedDualHint = new HintView2(activity, HintView2.DIRECTION_RIGHT)
.setJoint(0, 56 / 2)
.setDuration(5000)
.setMultilineText(true)
.setMaxWidth(140);
.setMultilineText(true);
actionBarContainer.addView(savedDualHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP, 0, 0, 52, 0));
videoTimerView = new VideoTimerView(context);
@ -1756,7 +1766,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
navbarContainer.addView(modeSwitcherView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL));
hintTextView = new HintTextView(context);
navbarContainer.addView(hintTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 32, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 66, 0, 66, 8));
navbarContainer.addView(hintTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 32, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 8, 0, 8, 8));
previewButtons = new PreviewButtons(context);
previewButtons.setVisibility(View.GONE);
@ -1791,6 +1801,9 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
.isEdit(false)
.setWarnUsers(getUsersFrom(captionEdit.getText()))
.whenSelectedRules((privacy, allowScreenshots, keepInProfile, whenDone) -> {
if (outputEntry == null) {
return;
}
previewView.updatePauseReason(5, true);
if (whenDone != null) {
whenDone.run();
@ -1837,7 +1850,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
trash = new TrashView(context);
trash.setAlpha(0f);
trash.setVisibility(View.GONE);
previewContainer.addView(trash, LayoutHelper.createFrame(120, 120, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0, 0, 16));
previewContainer.addView(trash, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 120, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0, 0, 16));
previewHighlight = new PreviewHighlightView(context, currentAccount, resourcesProvider);
previewContainer.addView(previewHighlight, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL));
@ -2899,6 +2912,9 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
if (isVideo) {
muteButton.setVisibility(View.VISIBLE);
setIconMuted(outputEntry != null && outputEntry.muted, false);
titleTextView.setRightPadding(AndroidUtilities.dp(96));
} else {
titleTextView.setRightPadding(AndroidUtilities.dp(48));
}
downloadButton.setVisibility(View.VISIBLE);
// privacySelector.setVisibility(View.VISIBLE);
@ -3173,13 +3189,13 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
paintViewBitmap.recycle();
paintViewBitmap = null;
}
if (outputEntry.isDraft && outputEntry.paintFile != null) {
if (outputEntry != null && outputEntry.isDraft && outputEntry.paintFile != null) {
paintViewBitmap = BitmapFactory.decodeFile(outputEntry.paintFile.getPath());
}
if (paintViewBitmap == null) {
paintViewBitmap = Bitmap.createBitmap(size.first, size.second, Bitmap.Config.ARGB_8888);
}
paintView = new PaintView(activity, windowView, activity, currentAccount, paintViewBitmap, null, previewView.getOrientation(), outputEntry.mediaEntities, previewContainer.getMeasuredWidth(), previewContainer.getMeasuredHeight(), new MediaController.CropState(), null, resourcesProvider) {
paintView = new PaintView(activity, windowView, activity, currentAccount, paintViewBitmap, null, previewView.getOrientation(), outputEntry == null ? null : outputEntry.mediaEntities, previewContainer.getMeasuredWidth(), previewContainer.getMeasuredHeight(), new MediaController.CropState(), null, resourcesProvider) {
@Override
public void onEntityDraggedTop(boolean value) {
previewHighlight.show(true, value, actionBarContainer);
@ -3673,7 +3689,9 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
return;
}
if (savedDualHint != null) {
savedDualHint.setText(isFrontface() ? LocaleController.getString(R.string.StoryCameraSavedDualBackHint) : LocaleController.getString(R.string.StoryCameraSavedDualFrontHint));
CharSequence text = isFrontface() ? LocaleController.getString(R.string.StoryCameraSavedDualBackHint) : LocaleController.getString(R.string.StoryCameraSavedDualFrontHint);
savedDualHint.setMaxWidthPx(HintView2.cutInFancyHalf(text, savedDualHint.getTextPaint()));
savedDualHint.setText(text);
savedDualHint.show();
MessagesController.getGlobalMainSettings().edit().putInt("storysvddualhint", MessagesController.getGlobalMainSettings().getInt("storysvddualhint", 0) + 1).apply();
}

View file

@ -60,7 +60,7 @@ public class TrashView extends View {
textDrawable = new AnimatedTextView.AnimatedTextDrawable(true, true, false);
textDrawable.setAnimationProperties(.3f, 0, 250, CubicBezierInterpolator.EASE_OUT_QUINT);
textDrawable.setOverrideFullWidth(dp(120));
textDrawable.setOverrideFullWidth(AndroidUtilities.displaySize.x);
textDrawable.setTextSize(dp(14));
textDrawable.setTextColor(0xffffffff);
textDrawable.setShadowLayer(dpf2(1.33f), 0, dp(1), 0x40000000);
@ -95,7 +95,7 @@ public class TrashView extends View {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(dp(120), dp(120));
setMeasuredDimension(widthMeasureSpec, dp(120));
}
public void onDragInfo(boolean dragged, boolean deleted) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B

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