diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 47f59409274..0b0ef7a7ea7 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -26,11 +26,11 @@ dependencies { compileOnly 'org.checkerframework:checker-compat-qual:2.5.0' implementation 'com.google.firebase:firebase-messaging:22.0.0' implementation 'com.google.firebase:firebase-config:21.0.1' - implementation 'com.google.firebase:firebase-datatransport:18.0.1' + implementation 'com.google.firebase:firebase-datatransport:18.1.0' implementation 'com.google.firebase:firebase-appindexing:20.0.0' implementation 'com.google.android.gms:play-services-maps:17.0.1' implementation 'com.google.android.gms:play-services-auth:19.2.0' - implementation 'com.google.android.gms:play-services-vision:16.2.0' + implementation 'com.google.android.gms:play-services-vision:20.1.3' implementation 'com.google.android.gms:play-services-wearable:17.1.0' implementation 'com.google.android.gms:play-services-location:18.0.0' implementation 'com.google.android.gms:play-services-wallet:18.1.3' @@ -299,7 +299,7 @@ android { } } - defaultConfig.versionCode = 2432 + defaultConfig.versionCode = 2462 applicationVariants.all { variant -> variant.outputs.all { output -> @@ -317,8 +317,8 @@ android { defaultConfig { minSdkVersion 16 - targetSdkVersion 29 - versionName "8.1.2" + targetSdkVersion 30 + versionName "8.2.1" vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi'] diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChildHelper.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChildHelper.java index 99fc2e3f2e5..babaef7f5e7 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChildHelper.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChildHelper.java @@ -37,7 +37,7 @@ */ public class ChildHelper { - private static final boolean DEBUG = BuildVars.DEBUG_VERSION; + private static final boolean DEBUG = false;//BuildVars.DEBUG_VERSION; private static final String TAG = "ChildrenHelper"; diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java index b9a46832459..d17c50e41ea 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java @@ -46,7 +46,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements private static final String TAG = "LinearLayoutManager"; - static final boolean DEBUG = BuildVars.DEBUG_VERSION; + static final boolean DEBUG = false; public static final int HORIZONTAL = RecyclerView.HORIZONTAL; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AccountInstance.java b/TMessagesProj/src/main/java/org/telegram/messenger/AccountInstance.java index e12c03f806b..50cc574fa9d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AccountInstance.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AccountInstance.java @@ -89,6 +89,10 @@ public SharedPreferences getNotificationsSettings() { return MessagesController.getNotificationsSettings(currentAccount); } + public MemberRequestsController getMemberRequestsController() { + return MemberRequestsController.getInstance(currentAccount); + } + public int getCurrentAccount() { return currentAccount; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index 6dc291fd972..a847e6832a1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -529,10 +529,12 @@ public static void fillStatusBarHeight(Context context) { if (context == null || AndroidUtilities.statusBarHeight > 0) { return; } + AndroidUtilities.statusBarHeight = getStatusBarHeight(context); + } + + public static int getStatusBarHeight(Context context) { int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); - if (resourceId > 0) { - AndroidUtilities.statusBarHeight = context.getResources().getDimensionPixelSize(resourceId); - } + return resourceId > 0 ? context.getResources().getDimensionPixelSize(resourceId) : 0; } public static int getThumbForNameOrMime(String name, String mime, boolean media) { @@ -2282,8 +2284,8 @@ public static void addMediaToGallery(Uri uri) { } } - private static File getAlbumDir(boolean secretChat) { //TODO scoped storage - if (secretChat || Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + private static File getAlbumDir(boolean secretChat) { + if (secretChat || !BuildVars.NO_SCOPED_STORAGE || (Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) { return FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE); } File storageDir = null; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BaseController.java b/TMessagesProj/src/main/java/org/telegram/messenger/BaseController.java index 601a22cf248..82f1a66ff6b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BaseController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BaseController.java @@ -75,4 +75,8 @@ protected final FileLoader getFileLoader() { protected final FileRefController getFileRefController() { return parentAccountInstance.getFileRefController(); } + + protected final MemberRequestsController getMemberRequestsController() { + return parentAccountInstance.getMemberRequestsController(); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index a775a86dd34..f9d464a6883 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -10,17 +10,18 @@ import android.content.Context; import android.content.SharedPreferences; +import android.os.Build; public class BuildVars { public static boolean DEBUG_VERSION = false; - public static boolean DEBUG_PRIVATE_VERSION = false; public static boolean LOGS_ENABLED = false; + public static boolean DEBUG_PRIVATE_VERSION = false; public static boolean USE_CLOUD_STRINGS = true; public static boolean CHECK_UPDATES = true; - public static boolean NO_SCOPED_STORAGE = true/* || Build.VERSION.SDK_INT <= 28*/; - public static int BUILD_VERSION = 2432; - public static String BUILD_VERSION_STRING = "8.1.2"; + public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29; + public static int BUILD_VERSION = 2462; + public static String BUILD_VERSION_STRING = "8.2.1"; public static int APP_ID = 4; public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103"; public static String SMS_HASH = isStandaloneApp() ? "w0lkcmTZkKh" : (DEBUG_VERSION ? "O2P2z+/jBpJ" : "oLeq9AcOZkT"); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java index 4372a5dfa9c..8455dc42b0a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java @@ -1490,6 +1490,10 @@ public static boolean isMegagroup(TLRPC.Chat chat) { return (chat instanceof TLRPC.TL_channel || chat instanceof TLRPC.TL_channelForbidden) && chat.megagroup; } + public static boolean isChannelAndNotMegaGroup(TLRPC.Chat chat) { + return isChannel(chat) && !isMegagroup(chat); + } + public static boolean isMegagroup(int currentAccount, long chatId) { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(chatId); return ChatObject.isChannel(chat) && chat.megagroup; @@ -1569,6 +1573,11 @@ public static boolean isChannel(long chatId, int currentAccount) { return chat instanceof TLRPC.TL_channel || chat instanceof TLRPC.TL_channelForbidden; } + public static boolean isChannelAndNotMegaGroup(long chatId, int currentAccount) { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(chatId); + return isChannelAndNotMegaGroup(chat); + } + public static boolean isCanWriteToChannel(long chatId, int currentAccount) { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(chatId); return ChatObject.canSendMessages(chat) || chat.megagroup; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatThemeController.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatThemeController.java index 0e82ae93a18..42a2f774bb8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatThemeController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatThemeController.java @@ -3,62 +3,63 @@ import android.content.Context; import android.content.SharedPreferences; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.text.TextUtils; import android.util.LongSparseArray; -import com.google.android.exoplayer2.util.Log; - import org.telegram.tgnet.ConnectionsManager; -import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.ResultCallback; import org.telegram.tgnet.SerializedData; -import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; -import org.telegram.ui.ActionBar.ChatTheme; +import org.telegram.ui.ActionBar.EmojiThemes; +import java.io.File; +import java.io.FileOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Locale; public class ChatThemeController extends BaseController { private static final long reloadTimeoutMs = 2 * 60 * 60 * 1000; - private static volatile DispatchQueue chatThemeQueue = new DispatchQueue("stageQueue"); + public static volatile DispatchQueue chatThemeQueue = new DispatchQueue("chatThemeQueue"); - private static final HashMap themeIdWallpaperMap = new HashMap<>(); + //private static final HashMap themeIdWallpaperMap = new HashMap<>(); private static final HashMap themeIdWallpaperThumbMap = new HashMap<>(); - private static List allChatThemes; - private static volatile int themesHash; + private static List allChatThemes; + private static volatile long themesHash; private static volatile long lastReloadTimeMs; public static void init() { SharedPreferences preferences = getSharedPreferences(); themesHash = 0; lastReloadTimeMs = 0; - if (!BuildVars.DEBUG_VERSION) { - preferences.getInt("hash", 0); + try { + themesHash = preferences.getLong("hash", 0); lastReloadTimeMs = preferences.getLong("lastReload", 0); + } catch (Exception e) { + FileLog.e(e); } allChatThemes = getAllChatThemesFromPrefs(); - Emoji.preloadEmoji("❌"); + + preloadSticker("❌"); if (!allChatThemes.isEmpty()) { - for (ChatTheme chatTheme : allChatThemes) { - Emoji.preloadEmoji(chatTheme.getEmoticon()); + for (EmojiThemes chatTheme : allChatThemes) { + preloadSticker(chatTheme.getEmoticon()); } - } else { - Emoji.preloadEmoji("\uD83E\uDD81"); - Emoji.preloadEmoji("⛄"); - Emoji.preloadEmoji("\uD83D\uDC8E"); - Emoji.preloadEmoji("\uD83D\uDC68\u200D\uD83C\uDFEB"); - Emoji.preloadEmoji("\uD83C\uDF37"); - Emoji.preloadEmoji("\uD83D\uDD2E"); - Emoji.preloadEmoji("\uD83C\uDF84"); - Emoji.preloadEmoji("\uD83C\uDFAE"); } } - public static void requestAllChatThemes(final ResultCallback> callback, boolean withDefault) { + private static void preloadSticker(String emojicon) { + ImageReceiver imageReceiver = new ImageReceiver(); + TLRPC.Document document = MediaDataController.getInstance(UserConfig.selectedAccount).getEmojiAnimatedSticker(emojicon); + imageReceiver.setImage(ImageLocation.getForDocument(document), "50_50", null, null, null, 0); + Emoji.preloadEmoji(emojicon); + } + + public static void requestAllChatThemes(final ResultCallback> callback, boolean withDefault) { if (themesHash == 0 || lastReloadTimeMs == 0) { init(); } @@ -69,30 +70,30 @@ public static void requestAllChatThemes(final ResultCallback> ca request.hash = themesHash; ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(request, (response, error) -> chatThemeQueue.postRunnable(() -> { boolean isError = false; - final List chatThemes; - if (response instanceof TLRPC.TL_account_chatThemes) { - TLRPC.TL_account_chatThemes resp = (TLRPC.TL_account_chatThemes) response; + final List chatThemes; + if (response instanceof TLRPC.TL_account_themes) { + TLRPC.TL_account_themes resp = (TLRPC.TL_account_themes) response; themesHash = resp.hash; lastReloadTimeMs = System.currentTimeMillis(); SharedPreferences.Editor editor = getSharedPreferences().edit(); editor.clear(); - editor.putInt("hash", themesHash); + editor.putLong("hash", themesHash); editor.putLong("lastReload", lastReloadTimeMs); editor.putInt("count", resp.themes.size()); chatThemes = new ArrayList<>(resp.themes.size()); for (int i = 0; i < resp.themes.size(); ++i) { - TLRPC.TL_chatTheme tlChatTheme = resp.themes.get(i); + TLRPC.TL_theme tlChatTheme = resp.themes.get(i); Emoji.preloadEmoji(tlChatTheme.emoticon); SerializedData data = new SerializedData(tlChatTheme.getObjectSize()); tlChatTheme.serializeToStream(data); editor.putString("theme_" + i, Utilities.bytesToHex(data.toByteArray())); - ChatTheme chatTheme = new ChatTheme(tlChatTheme, false); + EmojiThemes chatTheme = new EmojiThemes(tlChatTheme, false); chatTheme.preloadWallpaper(); chatThemes.add(chatTheme); } editor.apply(); - } else if (response instanceof TLRPC.TL_account_chatThemesNotModified) { + } else if (response instanceof TLRPC.TL_account_themesNotModified) { chatThemes = getAllChatThemesFromPrefs(); } else { chatThemes = null; @@ -100,10 +101,10 @@ public static void requestAllChatThemes(final ResultCallback> ca AndroidUtilities.runOnUIThread(() -> callback.onError(error)); } if (!isError) { - if (withDefault && !chatThemes.get(0).isDefault) { - chatThemes.add(0, ChatTheme.getDefault()); + if (withDefault && !chatThemes.get(0).showAsDefaultStub) { + chatThemes.add(0, EmojiThemes.createChatThemesDefault()); } - for (ChatTheme theme : chatThemes) { + for (EmojiThemes theme : chatThemes) { theme.initColors(); } AndroidUtilities.runOnUIThread(() -> { @@ -113,11 +114,11 @@ public static void requestAllChatThemes(final ResultCallback> ca } })); } else { - List chatThemes = new ArrayList<>(allChatThemes); - if (withDefault && !chatThemes.get(0).isDefault) { - chatThemes.add(0, ChatTheme.getDefault()); + List chatThemes = new ArrayList<>(allChatThemes); + if (withDefault && !chatThemes.get(0).showAsDefaultStub) { + chatThemes.add(0, EmojiThemes.createChatThemesDefault()); } - for (ChatTheme theme : chatThemes) { + for (EmojiThemes theme : chatThemes) { theme.initColors(); } callback.onComplete(chatThemes); @@ -131,17 +132,17 @@ private static SharedPreferences getEmojiSharedPreferences() { return ApplicationLoader.applicationContext.getSharedPreferences("chatthemeconfig_emoji", Context.MODE_PRIVATE); } - private static List getAllChatThemesFromPrefs() { + private static List getAllChatThemesFromPrefs() { SharedPreferences preferences = getSharedPreferences(); int count = preferences.getInt("count", 0); - List themes = new ArrayList<>(count); + List themes = new ArrayList<>(count); for (int i = 0; i < count; ++i) { String value = preferences.getString("theme_" + i, ""); SerializedData serializedData = new SerializedData(Utilities.hexToBytes(value)); try { - TLRPC.TL_chatTheme chatTheme = TLRPC.TL_chatTheme.TLdeserialize(serializedData, serializedData.readInt32(true), true); + TLRPC.TL_theme chatTheme = TLRPC.Theme.TLdeserialize(serializedData, serializedData.readInt32(true), true); if (chatTheme != null) { - themes.add(new ChatTheme(chatTheme, false)); + themes.add(new EmojiThemes(chatTheme, false)); } } catch (Throwable e) { FileLog.e(e); @@ -150,15 +151,15 @@ private static List getAllChatThemesFromPrefs() { return themes; } - public static void requestChatTheme(final String emoticon, final ResultCallback callback) { + public static void requestChatTheme(final String emoticon, final ResultCallback callback) { if (TextUtils.isEmpty(emoticon)) { callback.onComplete(null); return; } - requestAllChatThemes(new ResultCallback>() { + requestAllChatThemes(new ResultCallback>() { @Override - public void onComplete(List result) { - for (ChatTheme theme : result) { + public void onComplete(List result) { + for (EmojiThemes theme : result) { if (emoticon.equals(theme.getEmoticon())) { theme.initColors(); callback.onComplete(theme); @@ -221,14 +222,14 @@ public void setDialogTheme(long dialogId, String emoticon, boolean sendRequest) } } - public ChatTheme getDialogTheme(long dialogId) { + public EmojiThemes getDialogTheme(long dialogId) { String emoticon = dialogEmoticonsMap.get(dialogId); if (emoticon == null) { emoticon = getEmojiSharedPreferences().getString("chatTheme_" + currentAccount + "_" + dialogId, null); dialogEmoticonsMap.put(dialogId, emoticon); } if (emoticon != null) { - for (ChatTheme theme : allChatThemes) { + for (EmojiThemes theme : allChatThemes) { if (emoticon.equals(theme.getEmoticon())) { return theme; } @@ -238,26 +239,30 @@ public ChatTheme getDialogTheme(long dialogId) { } public static void preloadAllWallpaperImages(boolean isDark) { - for (ChatTheme chatTheme : allChatThemes) { - long themeId = chatTheme.getTlTheme(isDark).id; - if (themeIdWallpaperMap.containsKey(themeId)) { + for (EmojiThemes chatTheme : allChatThemes) { + TLRPC.TL_theme theme = chatTheme.getTlTheme(isDark ? 1 : 0); + if (theme == null) { continue; } - chatTheme.loadWallpaper(isDark, result -> { - if (result != null) { - themeIdWallpaperMap.put(result.first, result.second); - } - }); + long themeId = theme.id; + if (getPatternFile(themeId).exists()) { + continue; + } + chatTheme.loadWallpaper(isDark ? 1 : 0, null); } } public static void preloadAllWallpaperThumbs(boolean isDark) { - for (ChatTheme chatTheme : allChatThemes) { - long themeId = chatTheme.getTlTheme(isDark).id; + for (EmojiThemes chatTheme : allChatThemes) { + TLRPC.TL_theme theme = chatTheme.getTlTheme(isDark ? 1 : 0); + if (theme == null) { + continue; + } + long themeId = theme.id; if (themeIdWallpaperThumbMap.containsKey(themeId)) { continue; } - chatTheme.loadWallpaperThumb(isDark, result -> { + chatTheme.loadWallpaperThumb(isDark ? 1 : 0, result -> { if (result != null) { themeIdWallpaperThumbMap.put(result.first, result.second); } @@ -266,15 +271,52 @@ public static void preloadAllWallpaperThumbs(boolean isDark) { } public static void clearWallpaperImages() { - themeIdWallpaperMap.clear(); + } public static void clearWallpaperThumbImages() { themeIdWallpaperThumbMap.clear(); } - public static Bitmap getWallpaperBitmap(long themeId) { - return themeIdWallpaperMap.get(themeId); + public static void getWallpaperBitmap(long themeId, ResultCallback callback) { + if (themesHash == 0) { + callback.onComplete(null); + return; + } + File file = getPatternFile(themeId); + chatThemeQueue.postRunnable(() -> { + Bitmap bitmap = null; + try { + if (file.exists()) { + bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); + } + } catch (Exception e) { + FileLog.e(e); + } + if (callback != null) { + Bitmap finalBitmap = bitmap; + AndroidUtilities.runOnUIThread(() -> { + callback.onComplete(finalBitmap); + }); + } + }); + } + + private static File getPatternFile(long themeId) { + return new File(ApplicationLoader.getFilesDirFixed(), String.format(Locale.US, "%d_%d.jpg", themeId, themesHash)); + } + + public static void saveWallpaperBitmap(Bitmap bitmap, long themeId) { + File file = getPatternFile(themeId); + chatThemeQueue.postRunnable(() -> { + try { + FileOutputStream stream = new FileOutputStream(file); + bitmap.compress(Bitmap.CompressFormat.PNG, 87, stream); + stream.close(); + } catch (Exception e) { + FileLog.e(e); + } + }); } public static Bitmap getWallpaperThumbBitmap(long themeId) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java index d425534264d..439548bfb32 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java @@ -742,7 +742,7 @@ private boolean onRequestComplete(String locationKey, String parentKey, TLObject } else if (response instanceof TLRPC.TL_account_wallPapers) { TLRPC.TL_account_wallPapers accountWallPapers = (TLRPC.TL_account_wallPapers) response; for (int i = 0, size10 = accountWallPapers.wallpapers.size(); i < size10; i++) { - result = getFileReference(((TLRPC.TL_wallPaper) accountWallPapers.wallpapers.get(i)).document, requester.location, needReplacement, locationReplacement); + result = getFileReference(((TLRPC.WallPaper) accountWallPapers.wallpapers.get(i)).document, requester.location, needReplacement, locationReplacement); if (result != null) { break; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java b/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java index 0ea1d929aa6..73b55a1a5d4 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/GcmPushListenerService.java @@ -743,6 +743,10 @@ public void onMessageReceived(RemoteMessage message) { messageText = LocaleController.formatString("NotificationGroupAddSelfMega", R.string.NotificationGroupAddSelfMega, args[0], args[1]); break; } + case "CHAT_REQ_JOINED": { + messageText = LocaleController.formatString("UserAcceptedToGroupPushWithGroup", R.string.UserAcceptedToGroupPushWithGroup, args[0], args[1]); + break; + } case "CHAT_MESSAGE_FWDS": { messageText = LocaleController.formatString("NotificationGroupForwardedFew", R.string.NotificationGroupForwardedFew, args[0], args[1], LocaleController.formatPluralString("messages", Utilities.parseInt(args[2]))); localMessage = true; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java index 8d2291bbe15..95cf9d0d536 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -14,6 +14,8 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; @@ -30,6 +32,8 @@ import android.text.TextUtils; import android.util.SparseArray; +import com.google.android.exoplayer2.util.Log; + import org.json.JSONArray; import org.json.JSONObject; import org.telegram.messenger.secretmedia.EncryptedFileInputStream; @@ -73,9 +77,18 @@ import java.util.stream.Stream; import java.util.zip.GZIPInputStream; +/** + * image filter types + * suffixes: + * f - image is wallpaper + * isc - ignore cache for small images + * b - need blur image + * g - autoplay + */ public class ImageLoader { private HashMap bitmapUseCounts = new HashMap<>(); + private LruCache smallImagesMemCache; private LruCache memCache; private LruCache wallpaperMemCache; private LruCache lottieMemCache; @@ -118,9 +131,23 @@ public class ImageLoader { public static final String AUTOPLAY_FILTER = "g"; + public void moveToFront(String key) { + if (key == null) { + return; + } + BitmapDrawable drawable = memCache.get(key); + if (drawable != null) { + memCache.moveToFront(key); + } + drawable = smallImagesMemCache.get(key); + if (drawable != null) { + smallImagesMemCache.moveToFront(key); + } + } + public void putThumbsToCache(ArrayList updateMessageThumbs) { for (int i = 0; i < updateMessageThumbs.size(); i++) { - putImageToCache(updateMessageThumbs.get(i).drawable, updateMessageThumbs.get(i).key); + putImageToCache(updateMessageThumbs.get(i).drawable, updateMessageThumbs.get(i).key, true); } } @@ -1433,6 +1460,8 @@ private void onPostExecute(final Drawable drawable) { if (cacheImage.key.endsWith("_f")) { wallpaperMemCache.put(cacheImage.key, bitmapDrawable); incrementUseCount = false; + } else if (!cacheImage.key.endsWith("_isc") && bitmapDrawable.getBitmap().getWidth() <= 80 * AndroidUtilities.density && bitmapDrawable.getBitmap().getHeight() <= 80 * AndroidUtilities.density) { + smallImagesMemCache.put(cacheImage.key, bitmapDrawable); } else { memCache.put(cacheImage.key, bitmapDrawable); } @@ -1469,7 +1498,10 @@ public void cancel() { private BitmapDrawable getFromMemCache(String key) { BitmapDrawable drawable = memCache.get(key); if (drawable == null) { - return wallpaperMemCache.get(key); + drawable = smallImagesMemCache.get(key); + } + if (drawable == null) { + drawable = wallpaperMemCache.get(key); } return drawable; } @@ -1698,7 +1730,30 @@ public ImageLoader() { } int cacheSize = Math.min(maxSize, memoryClass / 7) * 1024 * 1024; - memCache = new LruCache(cacheSize) { + int commonCacheSize = (int) (cacheSize * 0.8f); + int smallImagesCacheSize = (int) (cacheSize * 0.2f); + + memCache = new LruCache(commonCacheSize) { + @Override + protected int sizeOf(String key, BitmapDrawable value) { + return value.getBitmap().getByteCount(); + } + + @Override + protected void entryRemoved(boolean evicted, String key, final BitmapDrawable oldValue, BitmapDrawable newValue) { + if (ignoreRemoval != null && ignoreRemoval.equals(key)) { + return; + } + final Integer count = bitmapUseCounts.get(key); + if (count == null || count == 0) { + Bitmap b = oldValue.getBitmap(); + if (!b.isRecycled()) { + b.recycle(); + } + } + } + }; + smallImagesMemCache = new LruCache(smallImagesCacheSize) { @Override protected int sizeOf(String key, BitmapDrawable value) { return value.getBitmap().getByteCount(); @@ -2104,10 +2159,15 @@ public String getReplacedKey(String oldKey) { } private void performReplace(String oldKey, String newKey) { - BitmapDrawable b = memCache.get(oldKey); + LruCache currentCache = memCache; + BitmapDrawable b = currentCache.get(oldKey); + if (b == null) { + currentCache = smallImagesMemCache; + b = currentCache.get(oldKey); + } replacedBitmaps.put(oldKey, newKey); if (b != null) { - BitmapDrawable oldBitmap = memCache.get(newKey); + BitmapDrawable oldBitmap = currentCache.get(newKey); boolean dontChange = false; if (oldBitmap != null && oldBitmap.getBitmap() != null && b.getBitmap() != null) { Bitmap oldBitmapObject = oldBitmap.getBitmap(); @@ -2118,11 +2178,11 @@ private void performReplace(String oldKey, String newKey) { } if (!dontChange) { ignoreRemoval = oldKey; - memCache.remove(oldKey); - memCache.put(newKey, b); + currentCache.remove(oldKey); + currentCache.put(newKey, b); ignoreRemoval = null; } else { - memCache.remove(oldKey); + currentCache.remove(oldKey); } } Integer val = bitmapUseCounts.get(oldKey); @@ -2158,6 +2218,7 @@ public boolean decrementUseCount(String key) { public void removeImage(String key) { bitmapUseCounts.remove(key); memCache.remove(key); + smallImagesMemCache.remove(key); } public boolean isInMemCache(String key, boolean animated) { @@ -2169,6 +2230,7 @@ public boolean isInMemCache(String key, boolean animated) { } public void clearMemory() { + smallImagesMemCache.evictAll(); memCache.evictAll(); lottieMemCache.evictAll(); } @@ -2195,6 +2257,14 @@ public void cancelLoadingForImageReceiver(final ImageReceiver imageReceiver, fin if (imageReceiver == null) { return; } + ArrayList runnables = imageReceiver.getLoadingOperations(); + if (!runnables.isEmpty()) { + for (int i = 0; i < runnables.size(); i++) { + imageLoadQueue.cancelRunnable(runnables.get(i)); + } + runnables.clear(); + } + imageReceiver.addLoadingImageRunnable(null); imageLoadQueue.postRunnable(() -> { for (int a = 0; a < 3; a++) { int type; @@ -2222,17 +2292,6 @@ public void cancelLoadingForImageReceiver(final ImageReceiver imageReceiver, fin }); } - public BitmapDrawable getAnyImageFromMemory(String key) { - BitmapDrawable drawable = memCache.get(key); - if (drawable == null) { - ArrayList filters = memCache.getFilterKeys(key); - if (filters != null && !filters.isEmpty()) { - return memCache.get(key + "@" + filters.get(0)); - } - } - return drawable; - } - public BitmapDrawable getImageFromMemory(TLObject fileLocation, String httpUrl, String filter) { if (fileLocation == null && httpUrl == null) { return null; @@ -2262,18 +2321,25 @@ public BitmapDrawable getImageFromMemory(TLObject fileLocation, String httpUrl, } private void replaceImageInCacheInternal(final String oldKey, final String newKey, final ImageLocation newLocation) { - ArrayList arr = memCache.getFilterKeys(oldKey); - if (arr != null) { - for (int a = 0; a < arr.size(); a++) { - String filter = arr.get(a); - String oldK = oldKey + "@" + filter; - String newK = newKey + "@" + filter; - performReplace(oldK, newK); - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didReplacedPhotoInMemCache, oldK, newK, newLocation); + for (int i = 0; i < 2; i++) { + ArrayList arr; + if (i == 0) { + arr = memCache.getFilterKeys(oldKey); + } else { + arr = smallImagesMemCache.getFilterKeys(oldKey); + } + if (arr != null) { + for (int a = 0; a < arr.size(); a++) { + String filter = arr.get(a); + String oldK = oldKey + "@" + filter; + String newK = newKey + "@" + filter; + performReplace(oldK, newK); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didReplacedPhotoInMemCache, oldK, newK, newLocation); + } + } else { + performReplace(oldKey, newKey); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didReplacedPhotoInMemCache, oldKey, newKey, newLocation); } - } else { - performReplace(oldKey, newKey); - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didReplacedPhotoInMemCache, oldKey, newKey, newLocation); } } @@ -2285,8 +2351,12 @@ public void replaceImageInCache(final String oldKey, final String newKey, final } } - public void putImageToCache(BitmapDrawable bitmap, String key) { - memCache.put(key, bitmap); + public void putImageToCache(BitmapDrawable bitmap, String key, boolean smallImage) { + if (smallImage) { + smallImagesMemCache.put(key, bitmap); + } else { + memCache.put(key, bitmap); + } } private void generateThumb(int mediaType, File originalPath, ThumbGenerateInfo info) { @@ -2332,7 +2402,7 @@ private void createLoadOperationForImageReceiver(final ImageReceiver imageReceiv final boolean shouldGenerateQualityThumb = imageReceiver.isShouldGenerateQualityThumb(); final int currentAccount = imageReceiver.getCurrentAccount(); final boolean currentKeyQuality = type == ImageReceiver.TYPE_IMAGE && imageReceiver.isCurrentKeyQuality(); - imageLoadQueue.postRunnable(() -> { + final Runnable loadOperationRunnable = () -> { boolean added = false; if (thumb != 2) { CacheImage alreadyLoadingUrl = imageLoadingByUrl.get(url); @@ -2633,7 +2703,9 @@ private void createLoadOperationForImageReceiver(final ImageReceiver imageReceiv } } } - }); + }; + imageLoadQueue.postRunnable(loadOperationRunnable); + imageReceiver.addLoadingImageRunnable(loadOperationRunnable); } public void preloadArtwork(String athumbUrl) { @@ -2684,7 +2756,14 @@ public void loadImageForImageReceiver(ImageReceiver imageReceiver) { drawable = memCache.get(mediaKey); if (drawable != null) { memCache.moveToFront(mediaKey); - } else { + } + 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); @@ -2710,7 +2789,14 @@ public void loadImageForImageReceiver(ImageReceiver imageReceiver) { drawable = memCache.get(imageKey); if (drawable != null) { memCache.moveToFront(imageKey); - } else { + } + if (drawable == null) { + drawable = smallImagesMemCache.get(imageKey); + if (drawable != null) { + smallImagesMemCache.moveToFront(imageKey); + } + } + if (drawable == null) { drawable = wallpaperMemCache.get(imageKey); if (drawable != null) { wallpaperMemCache.moveToFront(imageKey); @@ -2737,7 +2823,14 @@ public void loadImageForImageReceiver(ImageReceiver imageReceiver) { drawable = memCache.get(thumbKey); if (drawable != null) { memCache.moveToFront(thumbKey); - } else { + } + if (drawable == null) { + drawable = smallImagesMemCache.get(thumbKey); + if (drawable != null) { + smallImagesMemCache.moveToFront(thumbKey); + } + } + if (drawable == null) { drawable = wallpaperMemCache.get(thumbKey); if (drawable != null) { wallpaperMemCache.moveToFront(thumbKey); @@ -3657,7 +3750,7 @@ public static MessageThumb generateMessageThumb(TLRPC.Message message) { Point point = ChatMessageCell.getMessageSize(w, h); String key = String.format(Locale.US, "%s_false@%d_%d_b", ImageLocation.getStippedKey(message, message, size), (int) (point.x / AndroidUtilities.density), (int) (point.y / AndroidUtilities.density)); - if (!getInstance().memCache.contains(key)) { + if (!getInstance().isInMemCache(key, false)) { Bitmap b = getStrippedPhotoBitmap(size.bytes, null); if (b != null) { Utilities.blurBitmap(b, 3, 1, b.getWidth(), b.getHeight(), b.getRowBytes()); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index 3b9bf101d7d..4a05d3b8250 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java @@ -36,6 +36,8 @@ import androidx.annotation.Keep; +import java.util.ArrayList; + public class ImageReceiver implements NotificationCenter.NotificationCenterDelegate { public interface ImageReceiverDelegate { @@ -248,7 +250,7 @@ private void clear() { private boolean forcePreview; private boolean forceCrossfade; private int[] roundRadius = new int[4]; - private boolean isRoundRect; + private boolean isRoundRect = true; private Paint roundPaint; private RectF roundRect = new RectF(); @@ -273,6 +275,7 @@ private void clear() { private float pressedProgress; private int animateFromIsPressed; private String uniqKeyPrefix; + private ArrayList loadingOperations = new ArrayList<>(); public ImageReceiver() { this(null); @@ -1016,7 +1019,11 @@ private void drawDrawable(Canvas canvas, Drawable drawable, int alpha, BitmapSha if (isRoundRect) { try { - canvas.drawRoundRect(roundRect, roundRadius[0], roundRadius[0], roundPaint); + if (roundRadius[0] == 0) { + canvas.drawRect(roundRect, roundPaint); + } else { + canvas.drawRoundRect(roundRect, roundRadius[0], roundRadius[0], roundPaint); + } } catch (Exception e) { onBitmapException(bitmapDrawable); FileLog.e(e); @@ -1111,7 +1118,11 @@ private void drawDrawable(Canvas canvas, Drawable drawable, int alpha, BitmapSha if (isRoundRect) { try { - canvas.drawRoundRect(roundRect, roundRadius[0], roundRadius[0], roundPaint); + if (roundRadius[0] == 0) { + canvas.drawRect(roundRect, roundPaint); + } else { + canvas.drawRoundRect(roundRect, roundRadius[0], roundRadius[0], roundPaint); + } } catch (Exception e) { onBitmapException(bitmapDrawable); FileLog.e(e); @@ -2059,7 +2070,7 @@ protected boolean setImageBitmapByKey(Drawable drawable, String key, int type, b } updateDrawableRadius(drawable); - if (isVisible && (!memCache && !forcePreview || forceCrossfade)) { + if (isVisible && (!memCache && !forcePreview || forceCrossfade) && crossfadeDuration != 0) { boolean allowCorssfade = true; if (currentMediaDrawable instanceof AnimatedFileDrawable && ((AnimatedFileDrawable) currentMediaDrawable).hasBitmap()) { allowCorssfade = false; @@ -2319,4 +2330,17 @@ public void setUniqKeyPrefix(String prefix) { public String getUniqKeyPrefix() { return uniqKeyPrefix; } + + public void addLoadingImageRunnable(Runnable loadOperationRunnable) { + loadingOperations.add(loadOperationRunnable); + } + + public ArrayList getLoadingOperations() { + return loadingOperations; + } + + public void moveImageToFront() { + ImageLoader.getInstance().moveToFront(currentImageKey); + ImageLoader.getInstance().moveToFront(currentThumbKey); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java index 105f755fcb7..8915fcbe146 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java @@ -1711,6 +1711,11 @@ public static String formatStartsTime(long date, int type, boolean needToday) { } public static String formatSectionDate(long date) { + return formatYearMont(date, false); + } + + + public static String formatYearMont(long date, boolean alwaysShowYear) { try { date *= 1000; Calendar rightNow = Calendar.getInstance(); @@ -1733,7 +1738,7 @@ public static String formatSectionDate(long date) { LocaleController.getString("November", R.string.November), LocaleController.getString("December", R.string.December) }; - if (year == dateYear) { + if (year == dateYear && !alwaysShowYear) { return months[month]; } else { return months[month] + " " + dateYear; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java index b1ff19b9cb4..d54f9108147 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java @@ -2091,10 +2091,10 @@ public void loadMoreMusic() { } if (!playlistEndReached[0]) { loadingPlaylist = true; - AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playingMessageObject.getDialogId(), 50, playlistMaxId[0], MediaDataController.MEDIA_MUSIC, 1, playlistClassGuid); + AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playingMessageObject.getDialogId(), 50, playlistMaxId[0], 0, MediaDataController.MEDIA_MUSIC, 1, playlistClassGuid, 0); } else if (playlistMergeDialogId != 0 && !playlistEndReached[1]) { loadingPlaylist = true; - AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playlistMergeDialogId, 50, playlistMaxId[0], MediaDataController.MEDIA_MUSIC, 1, playlistClassGuid); + AccountInstance.getInstance(playingMessageObject.currentAccount).getMediaDataController().loadMedia(playlistMergeDialogId, 50, playlistMaxId[0], 0, MediaDataController.MEDIA_MUSIC, 1, playlistClassGuid, 0); } } @@ -4030,7 +4030,18 @@ public static void saveFile(String fullPath, Context context, final int type, fi public static String getStickerExt(Uri uri) { InputStream inputStream = null; try { - inputStream = ApplicationLoader.applicationContext.getContentResolver().openInputStream(uri); + try { + inputStream = ApplicationLoader.applicationContext.getContentResolver().openInputStream(uri); + } catch (Exception e) { + inputStream = null; + } + if (inputStream == null) { + File file = new File(uri.getPath()); + if (file.exists()) { + inputStream = new FileInputStream(file); + } + } + byte[] header = new byte[12]; if (inputStream.read(header, 0, 12) == 12) { if (header[0] == (byte) 0x89 && header[1] == (byte) 0x50 && header[2] == (byte) 0x4E && header[3] == (byte) 0x47 && header[4] == (byte) 0x0D && header[5] == (byte) 0x0A && header[6] == (byte) 0x1A && header[7] == (byte) 0x0A) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java index 41719c34856..043f319f0e5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java @@ -32,6 +32,7 @@ import android.text.SpannedString; import android.text.TextUtils; import android.text.style.CharacterStyle; +import android.util.Log; import android.util.SparseArray; import org.telegram.SQLite.SQLiteCursor; @@ -47,6 +48,7 @@ import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.Bulletin; +import org.telegram.ui.Components.SharedMediaLayout; import org.telegram.ui.Components.StickerSetBulletinLayout; import org.telegram.ui.Components.StickersArchiveAlert; import org.telegram.ui.Components.TextStyleSpan; @@ -73,14 +75,13 @@ import androidx.core.content.pm.ShortcutManagerCompat; import androidx.core.graphics.drawable.IconCompat; -import com.google.android.exoplayer2.util.Log; - @SuppressWarnings("unchecked") public class MediaDataController extends BaseController { public static String SHORTCUT_CATEGORY = "org.telegram.messenger.SHORTCUT_SHARE"; private static volatile MediaDataController[] Instance = new MediaDataController[UserConfig.MAX_ACCOUNT_COUNT]; + public static MediaDataController getInstance(int num) { MediaDataController localInstance = Instance[num]; if (localInstance == null) { @@ -1866,7 +1867,9 @@ private void loadStickerSetThumbInternal(TLRPC.PhotoSize thumb, Object parentObj } } - /** @param toggle 0 - remove, 1 - archive, 2 - add */ + /** + * @param toggle 0 - remove, 1 - archive, 2 - add + */ public void toggleStickerSet(Context context, TLObject stickerSetObject, int toggle, BaseFragment baseFragment, boolean showSettings, boolean showTooltip) { TLRPC.StickerSet stickerSet; TLRPC.TL_messages_stickerSet messages_stickerSet; @@ -1970,7 +1973,9 @@ private void toggleStickerSetInternal(Context context, int toggle, BaseFragment } } - /** @param toggle 0 - uninstall, 1 - archive, 2 - unarchive */ + /** + * @param toggle 0 - uninstall, 1 - archive, 2 - unarchive + */ public void toggleStickerSets(ArrayList stickerSetList, int type, int toggle, BaseFragment baseFragment, boolean showSettings) { int stickerSetListSize = stickerSetList.size(); ArrayList inputStickerSets = new ArrayList<>(stickerSetListSize); @@ -2325,22 +2330,35 @@ public String getLastSearchQuery() { public final static int MEDIA_URL = 3; public final static int MEDIA_MUSIC = 4; public final static int MEDIA_GIF = 5; - public final static int MEDIA_TYPES_COUNT = 6; + public final static int MEDIA_PHOTOS_ONLY = 6; + public final static int MEDIA_VIDEOS_ONLY = 7; + public final static int MEDIA_TYPES_COUNT = 8; + - public void loadMedia(long dialogId, int count, int max_id, int type, int fromCache, int classGuid) { + public void loadMedia(long dialogId, int count, int max_id, int min_id, int type, int fromCache, int classGuid, int requestIndex) { boolean isChannel = DialogObject.isChatDialog(dialogId) && ChatObject.isChannel(-dialogId, currentAccount); if (BuildVars.LOGS_ENABLED) { FileLog.d("load media did " + dialogId + " count = " + count + " max_id " + max_id + " type = " + type + " cache = " + fromCache + " classGuid = " + classGuid); } - if (fromCache != 0 || DialogObject.isEncryptedDialog(dialogId)) { - loadMediaDatabase(dialogId, count, max_id, type, classGuid, isChannel, fromCache); + if ((fromCache != 0 || DialogObject.isEncryptedDialog(dialogId))) { + loadMediaDatabase(dialogId, count, max_id, min_id, type, classGuid, isChannel, fromCache, requestIndex); } else { TLRPC.TL_messages_search req = new TLRPC.TL_messages_search(); req.limit = count; - req.offset_id = max_id; + if (min_id != 0) { + req.offset_id = min_id; + req.add_offset = -count; + } else { + req.offset_id = max_id; + } + if (type == MEDIA_PHOTOVIDEO) { req.filter = new TLRPC.TL_inputMessagesFilterPhotoVideo(); + } else if (type == MEDIA_PHOTOS_ONLY) { + req.filter = new TLRPC.TL_inputMessagesFilterPhotos(); + } else if (type == MEDIA_VIDEOS_ONLY) { + req.filter = new TLRPC.TL_inputMessagesFilterVideo(); } else if (type == MEDIA_FILE) { req.filter = new TLRPC.TL_inputMessagesFilterDocument(); } else if (type == MEDIA_AUDIO) { @@ -2361,7 +2379,14 @@ public void loadMedia(long dialogId, int count, int max_id, int type, int fromCa if (error == null) { TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; getMessagesController().removeDeletedMessagesFromArray(dialogId, res.messages); - processLoadedMedia(res, dialogId, count, max_id, type, 0, classGuid, isChannel, res.messages.size() == 0); + boolean topReached; + if (min_id != 0) { + topReached = res.messages.size() <= 1; + } else { + topReached = res.messages.size() == 0; + } + + processLoadedMedia(res, dialogId, count, max_id, min_id, type, 0, classGuid, isChannel, topReached, requestIndex); } }); getConnectionsManager().bindRequestToGuid(reqId, classGuid); @@ -2371,9 +2396,9 @@ public void loadMedia(long dialogId, int count, int max_id, int type, int fromCa public void getMediaCounts(long dialogId, int classGuid) { getMessagesStorage().getStorageQueue().postRunnable(() -> { try { - int[] counts = new int[]{-1, -1, -1, -1, -1, -1}; - int[] countsFinal = new int[]{-1, -1, -1, -1, -1, -1}; - int[] old = new int[]{0, 0, 0, 0, 0, 0}; + int[] counts = new int[]{-1, -1, -1, -1, -1, -1, -1, -1}; + int[] countsFinal = new int[]{-1, -1, -1, -1, -1, -1, -1, -1}; + int[] old = new int[]{0, 0, 0, 0, 0, 0, 0, 0}; SQLiteCursor cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT type, count, old FROM media_counts_v2 WHERE uid = %d", dialogId)); while (cursor.next()) { int type = cursor.intValue(0); @@ -2386,7 +2411,7 @@ public void getMediaCounts(long dialogId, int classGuid) { if (DialogObject.isEncryptedDialog(dialogId)) { for (int a = 0; a < counts.length; a++) { if (counts[a] == -1) { - cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT COUNT(mid) FROM media_v3 WHERE uid = %d AND type = %d LIMIT 1", dialogId, a)); + cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT COUNT(mid) FROM media_v4 WHERE uid = %d AND type = %d LIMIT 1", dialogId, a)); if (cursor.next()) { counts[a] = cursor.intValue(0); } else { @@ -2417,6 +2442,10 @@ public void getMediaCounts(long dialogId, int classGuid) { req.filters.add(new TLRPC.TL_inputMessagesFilterUrl()); } else if (a == MEDIA_MUSIC) { req.filters.add(new TLRPC.TL_inputMessagesFilterMusic()); + } else if (a == MEDIA_PHOTOS_ONLY) { + req.filters.add(new TLRPC.TL_inputMessagesFilterPhotos()); + } else if (a == MEDIA_VIDEOS_ONLY) { + req.filters.add(new TLRPC.TL_inputMessagesFilterVideo()); } else { req.filters.add(new TLRPC.TL_inputMessagesFilterGif()); } @@ -2429,7 +2458,11 @@ public void getMediaCounts(long dialogId, int classGuid) { } if (!req.filters.isEmpty()) { int reqId = getConnectionsManager().sendRequest(req, (response, error) -> { - Arrays.fill(counts, 0); + for (int i = 0; i < counts.length; i++) { + if (counts[i] < 0) { + counts[i] = 0; + } + } if (response != null) { TLRPC.Vector res = (TLRPC.Vector) response; for (int a = 0, N = res.objects.size(); a < N; a++) { @@ -2447,6 +2480,10 @@ public void getMediaCounts(long dialogId, int classGuid) { type = MEDIA_MUSIC; } else if (searchCounter.filter instanceof TLRPC.TL_inputMessagesFilterGif) { type = MEDIA_GIF; + } else if (searchCounter.filter instanceof TLRPC.TL_inputMessagesFilterPhotos) { + type = MEDIA_PHOTOS_ONLY; + } else if (searchCounter.filter instanceof TLRPC.TL_inputMessagesFilterVideo) { + type = MEDIA_VIDEOS_ONLY; } else { continue; } @@ -2568,20 +2605,20 @@ public static boolean canAddMessageToMedia(TLRPC.Message message) { } } - private void processLoadedMedia(TLRPC.messages_Messages res, long dialogId, int count, int max_id, int type, int fromCache, int classGuid, boolean isChannel, boolean topReached) { + private void processLoadedMedia(TLRPC.messages_Messages res, long dialogId, int count, int max_id, int min_id, int type, int fromCache, int classGuid, boolean isChannel, boolean topReached, int requestIndex) { if (BuildVars.LOGS_ENABLED) { - FileLog.d("process load media did " + dialogId + " count = " + count + " max_id " + max_id + " type = " + type + " cache = " + fromCache + " classGuid = " + classGuid); + FileLog.d("process load media did " + dialogId + " count = " + count + " max_id=" + max_id + " min_id=" + min_id + " type = " + type + " cache = " + fromCache + " classGuid = " + classGuid); } - if (fromCache != 0 && res.messages.isEmpty() && !DialogObject.isEncryptedDialog(dialogId)) { + if (fromCache != 0 && ((res.messages.isEmpty() && min_id == 0) || (res.messages.size() <= 1 && min_id != 0)) && !DialogObject.isEncryptedDialog(dialogId)) { if (fromCache == 2) { return; } - loadMedia(dialogId, count, max_id, type, 0, classGuid); + loadMedia(dialogId, count, max_id, min_id, type, 0, classGuid, requestIndex); } else { if (fromCache == 0) { ImageLoader.saveMessagesThumbs(res.messages); getMessagesStorage().putUsersAndChats(res.users, res.chats, true, true); - putMediaDatabase(dialogId, type, res.messages, max_id, topReached); + putMediaDatabase(dialogId, type, res.messages, max_id, min_id, topReached); } Utilities.searchQueue.postRunnable(() -> { @@ -2602,7 +2639,7 @@ private void processLoadedMedia(TLRPC.messages_Messages res, long dialogId, int int totalCount = res.count; getMessagesController().putUsers(res.users, fromCache != 0); getMessagesController().putChats(res.chats, fromCache != 0); - getNotificationCenter().postNotificationName(NotificationCenter.mediaDidLoad, dialogId, totalCount, objects, classGuid, type, topReached); + getNotificationCenter().postNotificationName(NotificationCenter.mediaDidLoad, dialogId, totalCount, objects, classGuid, type, topReached, min_id != 0, requestIndex); }); }); } @@ -2653,7 +2690,7 @@ private void getMediaCountDatabase(long dialogId, int type, int classGuid) { } cursor.dispose(); if (count == -1 && DialogObject.isEncryptedDialog(dialogId)) { - cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT COUNT(mid) FROM media_v3 WHERE uid = %d AND type = %d LIMIT 1", dialogId, type)); + cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT COUNT(mid) FROM media_v4 WHERE uid = %d AND type = %d LIMIT 1", dialogId, type)); if (cursor.next()) { count = cursor.intValue(0); } @@ -2670,7 +2707,7 @@ private void getMediaCountDatabase(long dialogId, int type, int classGuid) { }); } - private void loadMediaDatabase(long uid, int count, int max_id, int type, int classGuid, boolean isChannel, int fromCache) { + private void loadMediaDatabase(long uid, int count, int max_id, int min_id, int type, int classGuid, boolean isChannel, int fromCache, int requestIndex) { Runnable runnable = new Runnable() { @Override public void run() { @@ -2684,40 +2721,62 @@ public void run() { SQLiteCursor cursor; SQLiteDatabase database = getMessagesStorage().getDatabase(); boolean isEnd = false; + boolean reverseMessages = false; if (!DialogObject.isEncryptedDialog(uid)) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT start FROM media_holes_v2 WHERE uid = %d AND type = %d AND start IN (0, 1)", uid, type)); - if (cursor.next()) { - isEnd = cursor.intValue(0) == 1; - } else { - cursor.dispose(); - cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM media_v3 WHERE uid = %d AND type = %d AND mid > 0", uid, type)); + if (min_id == 0) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT start FROM media_holes_v2 WHERE uid = %d AND type = %d AND start IN (0, 1)", uid, type)); if (cursor.next()) { - int mid = cursor.intValue(0); - if (mid != 0) { - SQLitePreparedStatement state = database.executeFast("REPLACE INTO media_holes_v2 VALUES(?, ?, ?, ?)"); - state.requery(); - state.bindLong(1, uid); - state.bindInteger(2, type); - state.bindInteger(3, 0); - state.bindInteger(4, mid); - state.step(); - state.dispose(); + isEnd = cursor.intValue(0) == 1; + } else { + cursor.dispose(); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT min(mid) FROM media_v4 WHERE uid = %d AND type = %d AND mid > 0", uid, type)); + if (cursor.next()) { + int mid = cursor.intValue(0); + if (mid != 0) { + SQLitePreparedStatement state = database.executeFast("REPLACE INTO media_holes_v2 VALUES(?, ?, ?, ?)"); + state.requery(); + state.bindLong(1, uid); + state.bindInteger(2, type); + state.bindInteger(3, 0); + state.bindInteger(4, mid); + state.step(); + state.dispose(); + } } } + cursor.dispose(); } - cursor.dispose(); int holeMessageId = 0; if (max_id != 0) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT end FROM media_holes_v2 WHERE uid = %d AND type = %d AND end <= %d ORDER BY end DESC LIMIT 1", uid, type, max_id)); + int startHole = 0; + cursor = database.queryFinalized(String.format(Locale.US, "SELECT start, end FROM media_holes_v2 WHERE uid = %d AND type = %d AND start <= %d ORDER BY end DESC LIMIT 1", uid, type, max_id)); if (cursor.next()) { - holeMessageId = cursor.intValue(0); + startHole = cursor.intValue(0); + holeMessageId = cursor.intValue(1); } cursor.dispose(); + if (holeMessageId > 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v3 WHERE uid = %d AND mid > 0 AND mid < %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, max_id, holeMessageId, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid < %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, max_id, holeMessageId, type, countToLoad)); + isEnd = false; + } else { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, max_id, type, countToLoad)); + } + } else if (min_id != 0) { + int startHole = 0; + cursor = database.queryFinalized(String.format(Locale.US, "SELECT start, end FROM media_holes_v2 WHERE uid = %d AND type = %d AND end >= %d ORDER BY end ASC LIMIT 1", uid, type, min_id)); + if (cursor.next()) { + startHole = cursor.intValue(0); + holeMessageId = cursor.intValue(1); + } + cursor.dispose(); + reverseMessages = true; + if (startHole > 1) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid >= %d AND mid <= %d AND type = %d ORDER BY date ASC, mid ASC LIMIT %d", uid, min_id, startHole, type, countToLoad)); } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v3 WHERE uid = %d AND mid > 0 AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, max_id, type, countToLoad)); + isEnd = true; + cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND mid >= %d AND type = %d ORDER BY date ASC, mid ASC LIMIT %d", uid, min_id, type, countToLoad)); } } else { cursor = database.queryFinalized(String.format(Locale.US, "SELECT max(end) FROM media_holes_v2 WHERE uid = %d AND type = %d", uid, type)); @@ -2726,17 +2785,19 @@ public void run() { } cursor.dispose(); if (holeMessageId > 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v3 WHERE uid = %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, holeMessageId, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, holeMessageId, type, countToLoad)); } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v3 WHERE uid = %d AND mid > 0 AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > 0 AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, type, countToLoad)); } } } else { isEnd = true; if (max_id != 0) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_v3 as m LEFT JOIN randoms_v2 as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d AND type = %d ORDER BY m.mid ASC LIMIT %d", uid, max_id, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_v4 as m LEFT JOIN randoms_v2 as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d AND type = %d ORDER BY m.mid ASC LIMIT %d", uid, max_id, type, countToLoad)); + } else if (min_id != 0) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_v4 as m LEFT JOIN randoms_v2 as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid < %d AND type = %d ORDER BY m.mid DESC LIMIT %d", uid, min_id, type, countToLoad)); } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_v3 as m LEFT JOIN randoms_v2 as r ON r.mid = m.mid WHERE m.uid = %d AND type = %d ORDER BY m.mid ASC LIMIT %d", uid, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_v4 as m LEFT JOIN randoms_v2 as r ON r.mid = m.mid WHERE m.uid = %d AND type = %d ORDER BY m.mid ASC LIMIT %d", uid, type, countToLoad)); } } @@ -2751,7 +2812,12 @@ public void run() { if (DialogObject.isEncryptedDialog(uid)) { message.random_id = cursor.longValue(2); } - res.messages.add(message); + if (reverseMessages) { + res.messages.add(0, message); + } else { + res.messages.add(message); + } + MessagesStorage.addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad); } } @@ -2763,10 +2829,14 @@ public void run() { if (!chatsToLoad.isEmpty()) { getMessagesStorage().getChatsInternal(TextUtils.join(",", chatsToLoad), res.chats); } - if (res.messages.size() > count) { + if (res.messages.size() > count && min_id == 0) { res.messages.remove(res.messages.size() - 1); } else { - topReached = isEnd; + if (min_id != 0) { + topReached = false; + } else { + topReached = isEnd; + } } } catch (Exception e) { res.messages.clear(); @@ -2776,7 +2846,7 @@ public void run() { } finally { Runnable task = this; AndroidUtilities.runOnUIThread(() -> getMessagesStorage().completeTaskForGuid(task, classGuid)); - processLoadedMedia(res, uid, count, max_id, type, fromCache, classGuid, isChannel, topReached); + processLoadedMedia(res, uid, count, max_id, min_id, type, fromCache, classGuid, isChannel, topReached, requestIndex); } } }; @@ -2785,17 +2855,17 @@ public void run() { messagesStorage.bindTaskToGuid(runnable, classGuid); } - private void putMediaDatabase(long uid, int type, ArrayList messages, int max_id, boolean topReached) { + private void putMediaDatabase(long uid, int type, ArrayList messages, int max_id, int min_id, boolean topReached) { getMessagesStorage().getStorageQueue().postRunnable(() -> { try { - if (messages.isEmpty() || topReached) { + if (min_id == 0 && (messages.isEmpty() || topReached)) { getMessagesStorage().doneHolesInMedia(uid, max_id, type); if (messages.isEmpty()) { return; } } getMessagesStorage().getDatabase().beginTransaction(); - SQLitePreparedStatement state2 = getMessagesStorage().getDatabase().executeFast("REPLACE INTO media_v3 VALUES(?, ?, ?, ?, ?)"); + SQLitePreparedStatement state2 = getMessagesStorage().getDatabase().executeFast("REPLACE INTO media_v4 VALUES(?, ?, ?, ?, ?)"); for (TLRPC.Message message : messages) { if (canAddMessageToMedia(message)) { state2.requery(); @@ -2811,9 +2881,11 @@ private void putMediaDatabase(long uid, int type, ArrayList messa } } state2.dispose(); - if (!topReached || max_id != 0) { - int minId = topReached ? 1 : messages.get(messages.size() - 1).id; - if (max_id != 0) { + if (!topReached || max_id != 0 || min_id != 0) { + int minId = (topReached && min_id == 0) ? 1 : messages.get(messages.size() - 1).id; + if (min_id != 0) { + getMessagesStorage().closeHolesInMedia(uid, minId, messages.get(0).id, type); + } else if (max_id != 0) { getMessagesStorage().closeHolesInMedia(uid, minId, max_id, type); } else { getMessagesStorage().closeHolesInMedia(uid, minId, Integer.MAX_VALUE, type); @@ -2836,15 +2908,15 @@ public void loadMusic(long dialogId, long maxId, long minId) { SQLiteCursor cursor; if (a == 0) { if (!DialogObject.isEncryptedDialog(dialogId)) { - cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v3 WHERE uid = %d AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT 1000", dialogId, maxId, MEDIA_MUSIC)); + cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT 1000", dialogId, maxId, MEDIA_MUSIC)); } else { - cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v3 WHERE uid = %d AND mid > %d AND type = %d ORDER BY date DESC, mid DESC LIMIT 1000", dialogId, maxId, MEDIA_MUSIC)); + cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > %d AND type = %d ORDER BY date DESC, mid DESC LIMIT 1000", dialogId, maxId, MEDIA_MUSIC)); } } else { if (!DialogObject.isEncryptedDialog(dialogId)) { - cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v3 WHERE uid = %d AND mid > %d AND type = %d ORDER BY date DESC, mid DESC LIMIT 1000", dialogId, minId, MEDIA_MUSIC)); + cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid > %d AND type = %d ORDER BY date DESC, mid DESC LIMIT 1000", dialogId, minId, MEDIA_MUSIC)); } else { - cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v3 WHERE uid = %d AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT 1000", dialogId, minId, MEDIA_MUSIC)); + cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v4 WHERE uid = %d AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT 1000", dialogId, minId, MEDIA_MUSIC)); } } @@ -3804,7 +3876,7 @@ private ArrayList loadPinnedMessageInternal(long dialogId, long c } } if (!ok) { - getMessagesStorage().updatePinnedMessages(dialogId, req.id, false, -1, 0, false, null); + getMessagesStorage().updatePinnedMessages(dialogId, req.id, false, -1, 0, false, null); } }); } @@ -4006,8 +4078,7 @@ public void loadReplyMessagesForMessages(ArrayList messages, long if (messageObject.messageOwner.reply_to.reply_to_peer_id.channel_id != 0) { channelId = messageObject.messageOwner.reply_to.reply_to_peer_id.channel_id; } - } else - if (messageObject.messageOwner.peer_id.channel_id != 0) { + } else if (messageObject.messageOwner.peer_id.channel_id != 0) { channelId = messageObject.messageOwner.peer_id.channel_id; } @@ -4164,9 +4235,9 @@ private void saveReplyMessages(LongSparseArray firstImportersCache = new LongSparseArray<>(); + + public MemberRequestsController(int accountNum) { + super(accountNum); + } + + @Nullable + public TLRPC.TL_messages_chatInviteImporters getCachedImporters(long chatId) { + return firstImportersCache.get(chatId); + } + + public int getImporters(final long chatId, final String query, TLRPC.TL_chatInviteImporter lastImporter, LongSparseArray users, RequestDelegate onComplete) { + boolean isEmptyQuery = TextUtils.isEmpty(query); + TLRPC.TL_messages_getChatInviteImporters req = new TLRPC.TL_messages_getChatInviteImporters(); + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(-chatId); + req.requested = true; + req.limit = 30; + if (!isEmptyQuery) { + req.q = query; + req.flags |= 4; + } + if (lastImporter == null) { + req.offset_user = new TLRPC.TL_inputUserEmpty(); + } else { + req.offset_user = getMessagesController().getInputUser(users.get(lastImporter.user_id)); + req.offset_date = lastImporter.date; + } + return getConnectionsManager().sendRequest(req, (response, error) -> { + AndroidUtilities.runOnUIThread(() -> { + if (error == null) { + TLRPC.TL_messages_chatInviteImporters importers = (TLRPC.TL_messages_chatInviteImporters) response; + firstImportersCache.put(chatId, importers); + } + onComplete.run(response, error); + }); + }); + } + + public void onPendingRequestsUpdated(TLRPC.TL_updatePendingJoinRequests update) { + long peerId = MessageObject.getPeerId(update.peer); + firstImportersCache.put(-peerId, null); + TLRPC.ChatFull chatFull = getMessagesController().getChatFull(-peerId); + if (chatFull != null) { + chatFull.requests_pending = update.requests_pending; + chatFull.recent_requesters = update.recent_requesters; + chatFull.flags |= 131072; + getMessagesStorage().updateChatInfo(chatFull, false); + getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, chatFull, 0, false, false); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index 25e5e2ad63e..4c8361665dd 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -124,6 +124,7 @@ public class MessageObject { public long loadedFileSize; public byte[] sponsoredId; + public int sponsoredChannelPost; public String botStartParam; public boolean animateComments; @@ -186,6 +187,9 @@ public class MessageObject { public String messageTrimmedToHighlight; public int parentWidth; + public ImageLocation mediaThumb; + public ImageLocation mediaSmallThumb; + static final String[] excludeWords = new String[] { " vs. ", " vs ", @@ -1832,6 +1836,11 @@ public MessageObject(int accountNum, TLRPC.TL_channelAdminLogEvent event, ArrayL } messageText = replaceWithLink(LocaleController.formatString("ActionTTLChanged", R.string.ActionTTLChanged, time), "un1", fromUser); } + } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionParticipantJoinByRequest) { + TLRPC.TL_channelAdminLogEventActionParticipantJoinByRequest action = (TLRPC.TL_channelAdminLogEventActionParticipantJoinByRequest) event.action; + messageText = replaceWithLink(LocaleController.getString("JoinedViaInviteLinkApproved", R.string.JoinedViaInviteLinkApproved), "un1", fromUser); + messageText = replaceWithLink(messageText, "un2", action.invite); + messageText = replaceWithLink(messageText, "un3", MessagesController.getInstance(currentAccount).getUser(action.approved_by)); } else { messageText = "unsupported " + event.action; } @@ -2961,6 +2970,15 @@ private void updateMessageText(AbstractMap users, AbstractMap< ? LocaleController.formatString("ChatThemeChangedYou", R.string.ChatThemeChangedYou, emoticon) : LocaleController.formatString("ChatThemeChangedTo", R.string.ChatThemeChangedTo, userName, emoticon); } + } else if (messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest) { + if (UserObject.isUserSelf(fromUser)) { + boolean isChannel = ChatObject.isChannelAndNotMegaGroup(messageOwner.peer_id.channel_id, currentAccount); + messageText = isChannel + ? LocaleController.getString("RequestToJoinChannelApproved", R.string.RequestToJoinChannelApproved) + : LocaleController.getString("RequestToJoinGroupApproved", R.string.RequestToJoinGroupApproved); + } else { + messageText = replaceWithLink(LocaleController.getString("UserAcceptedToGroupAction", R.string.UserAcceptedToGroupAction), "un1", fromObject); + } } } } else { @@ -4280,13 +4298,13 @@ public void generateLayout(TLRPC.User fromUser) { if (useManualParse) { addLinks(isOutOwner(), messageText, true, true); } else { - if (messageText instanceof Spannable && messageText.length() < 1000) { - try { - AndroidUtilities.addLinks((Spannable) messageText, Linkify.PHONE_NUMBERS); - } catch (Throwable e) { - FileLog.e(e); - } - } +// if (messageText instanceof Spannable && messageText.length() < 1000) { +// try { +// AndroidUtilities.addLinks((Spannable) messageText, Linkify.PHONE_NUMBERS); +// } catch (Throwable e) { +// FileLog.e(e); +// } +// } } if (isYouTubeVideo() || replyMessageObject != null && replyMessageObject.isYouTubeVideo()) { addUrlsByPattern(isOutOwner(), messageText, false, 3, Integer.MAX_VALUE, false); @@ -5776,6 +5794,9 @@ public static boolean canDeleteMessage(int currentAccount, boolean inScheduleMod if (message == null) { return false; } + if (ChatObject.isChannelAndNotMegaGroup(chat) && message.action instanceof TLRPC.TL_messageActionChatJoinedByRequest) { + return false; + } if (message.id < 0) { return true; } @@ -6119,6 +6140,21 @@ private void handleFoundWords(ArrayList foundWords, String[] queryWord) } } + public void createMediaThumbs() { + if (isVideo()) { + TLRPC.Document document = getDocument(); + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 50); + TLRPC.PhotoSize qualityThumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 320); + mediaThumb = ImageLocation.getForDocument(qualityThumb, document); + mediaSmallThumb = ImageLocation.getForDocument(thumb, document); + } else if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && messageOwner.media.photo != null && !photoThumbs.isEmpty()) { + TLRPC.PhotoSize currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(photoThumbs, 50); + TLRPC.PhotoSize currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(photoThumbs, 320, false, currentPhotoObjectThumb, false); + mediaThumb = ImageLocation.getForObject(currentPhotoObject, photoThumbsObject); + mediaSmallThumb = ImageLocation.getForObject(currentPhotoObjectThumb, photoThumbsObject); + } + } + public boolean hasHighlightedWords() { return highlightedWords != null && !highlightedWords.isEmpty(); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index d23f0541711..382b5a36b4f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -2703,6 +2703,9 @@ public void cleanup() { } public TLRPC.User getUser(Long id) { + if (id == 0) { + return UserConfig.getInstance(currentAccount).getCurrentUser(); + } return users.get(id); } @@ -10875,62 +10878,69 @@ public void checkChatInviter(long chatId, boolean createMessage) { req.participant = getInputPeer(getUserConfig().getClientUserId()); getConnectionsManager().sendRequest(req, (response, error) -> { TLRPC.TL_channels_channelParticipant res = (TLRPC.TL_channels_channelParticipant) response; - if (res != null && res.participant instanceof TLRPC.TL_channelParticipantSelf && res.participant.inviter_id != getUserConfig().getClientUserId()) { - if (chat.megagroup && getMessagesStorage().isMigratedChat(chat.id)) { - return; - } - AndroidUtilities.runOnUIThread(() -> { - putUsers(res.users, false); - putChats(res.chats, false); - }); - getMessagesStorage().putUsersAndChats(res.users, res.chats, true, true); + if (res != null && res.participant instanceof TLRPC.TL_channelParticipantSelf) { + TLRPC.TL_channelParticipantSelf selfParticipant = (TLRPC.TL_channelParticipantSelf) res.participant; + if (selfParticipant.inviter_id != getUserConfig().getClientUserId() || selfParticipant.via_invite) { + if (chat.megagroup && getMessagesStorage().isMigratedChat(chat.id)) { + return; + } + AndroidUtilities.runOnUIThread(() -> { + putUsers(res.users, false); + putChats(res.chats, false); + }); + getMessagesStorage().putUsersAndChats(res.users, res.chats, true, true); - ArrayList pushMessages; - if (createMessage && Math.abs(getConnectionsManager().getCurrentTime() - res.participant.date) < 24 * 60 * 60 && !getMessagesStorage().hasInviteMeMessage(chatId)) { - TLRPC.TL_messageService message = new TLRPC.TL_messageService(); - message.media_unread = true; - message.unread = true; - message.flags = TLRPC.MESSAGE_FLAG_HAS_FROM_ID; - message.post = true; - message.local_id = message.id = getUserConfig().getNewMessageId(); - message.date = res.participant.date; - message.action = new TLRPC.TL_messageActionChatAddUser(); - message.from_id = new TLRPC.TL_peerUser(); - message.from_id.user_id = res.participant.inviter_id; - message.action.users.add(getUserConfig().getClientUserId()); - message.peer_id = new TLRPC.TL_peerChannel(); - message.peer_id.channel_id = chatId; - message.dialog_id = -chatId; - getUserConfig().saveConfig(false); + ArrayList pushMessages; + if (createMessage && Math.abs(getConnectionsManager().getCurrentTime() - res.participant.date) < 24 * 60 * 60 && !getMessagesStorage().hasInviteMeMessage(chatId)) { + TLRPC.TL_messageService message = new TLRPC.TL_messageService(); + message.media_unread = true; + message.unread = true; + message.flags = TLRPC.MESSAGE_FLAG_HAS_FROM_ID; + message.post = true; + message.local_id = message.id = getUserConfig().getNewMessageId(); + message.date = res.participant.date; + if (selfParticipant.inviter_id != getUserConfig().getClientUserId()) { + message.action = new TLRPC.TL_messageActionChatAddUser(); + } else if (selfParticipant.via_invite) { + message.action = new TLRPC.TL_messageActionChatJoinedByRequest(); + } + message.from_id = new TLRPC.TL_peerUser(); + message.from_id.user_id = res.participant.inviter_id; + message.action.users.add(getUserConfig().getClientUserId()); + message.peer_id = new TLRPC.TL_peerChannel(); + message.peer_id.channel_id = chatId; + message.dialog_id = -chatId; + getUserConfig().saveConfig(false); - pushMessages = new ArrayList<>(); - ArrayList messagesArr = new ArrayList<>(); + pushMessages = new ArrayList<>(); + ArrayList messagesArr = new ArrayList<>(); - ConcurrentHashMap usersDict = new ConcurrentHashMap<>(); - for (int a = 0; a < res.users.size(); a++) { - TLRPC.User user = res.users.get(a); - usersDict.put(user.id, user); - } + ConcurrentHashMap usersDict = new ConcurrentHashMap<>(); + for (int a = 0; a < res.users.size(); a++) { + TLRPC.User user = res.users.get(a); + usersDict.put(user.id, user); + } - messagesArr.add(message); - MessageObject obj = new MessageObject(currentAccount, message, usersDict, true, false); - pushMessages.add(obj); - getMessagesStorage().getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> getNotificationsController().processNewMessages(pushMessages, true, false, null))); - getMessagesStorage().putMessages(messagesArr, true, true, false, 0, false); - } else { - pushMessages = null; - } + messagesArr.add(message); + MessageObject obj = new MessageObject(currentAccount, message, usersDict, true, false); + pushMessages.add(obj); + getMessagesStorage().getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> getNotificationsController().processNewMessages(pushMessages, true, false, null))); + getMessagesStorage().putMessages(messagesArr, true, true, false, 0, false); + } else { + pushMessages = null; + } - getMessagesStorage().saveChatInviter(chatId, res.participant.inviter_id); + getMessagesStorage().saveChatInviter(chatId, res.participant.inviter_id); - AndroidUtilities.runOnUIThread(() -> { - gettingChatInviters.delete(chatId); - if (pushMessages != null) { - updateInterfaceWithMessages(-chatId, pushMessages, false); - getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); - } - getNotificationCenter().postNotificationName(NotificationCenter.didLoadChatInviter, chatId, res.participant.inviter_id); - }); + AndroidUtilities.runOnUIThread(() -> { + gettingChatInviters.delete(chatId); + if (pushMessages != null) { + updateInterfaceWithMessages(-chatId, pushMessages, false); + getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); + } + getNotificationCenter().postNotificationName(NotificationCenter.didLoadChatInviter, chatId, res.participant.inviter_id); + }); + } } }); } @@ -12728,6 +12738,11 @@ public boolean processUpdateArray(ArrayList updates, ArrayList(); } updatesOnMainThread.add(baseUpdate); + } else if (baseUpdate instanceof TLRPC.TL_updatePendingJoinRequests) { + if (updatesOnMainThread == null) { + updatesOnMainThread = new ArrayList<>(); + } + updatesOnMainThread.add(baseUpdate); } } if (messages != null) { @@ -13387,6 +13402,9 @@ public boolean processUpdateArray(ArrayList updates, ArrayList getSponsoredMessages(long dialogId) { MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, true, true); messageObject.sponsoredId = sponsoredMessage.random_id; messageObject.botStartParam = sponsoredMessage.start_param; + messageObject.sponsoredChannelPost = sponsoredMessage.channel_post; result.add(messageObject); } } @@ -14577,6 +14596,16 @@ public void didReceivedNotification(int id, int account, Object... args) { } } + public int getChatPendingRequestsOnClosed(long chatId) { + return mainPreferences.getInt("chatPendingRequests" + chatId, 0); + } + + public void setChatPendingRequestsOnClose(long chatId, int count) { + mainPreferences.edit() + .putInt("chatPendingRequests" + chatId, count) + .apply(); + } + public interface MessagesLoadedCallback { void onMessagesLoaded(boolean fromCache); void onError(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index c341af62cce..0e8fbda6538 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -48,8 +48,6 @@ import androidx.annotation.UiThread; import androidx.collection.LongSparseArray; -import com.google.android.exoplayer2.util.Log; - public class MessagesStorage extends BaseController { public interface IntCallback { @@ -100,7 +98,7 @@ public interface BooleanCallback { private CountDownLatch openSync = new CountDownLatch(1); private static volatile MessagesStorage[] Instance = new MessagesStorage[UserConfig.MAX_ACCOUNT_COUNT]; - private final static int LAST_DB_VERSION = 84; + private final static int LAST_DB_VERSION = 86; private boolean databaseMigrationInProgress; public static MessagesStorage getInstance(int num) { @@ -296,11 +294,12 @@ public void openDatabase(int openTries) { database.executeFast("CREATE TABLE media_holes_v2(uid INTEGER, type INTEGER, start INTEGER, end INTEGER, PRIMARY KEY(uid, type, start));").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS uid_end_media_holes_v2 ON media_holes_v2(uid, type, end);").stepThis().dispose(); - database.executeFast("CREATE TABLE scheduled_messages_v2(mid INTEGER, uid INTEGER, send_state INTEGER, date INTEGER, data BLOB, ttl INTEGER, replydata BLOB, PRIMARY KEY(mid, uid))").stepThis().dispose(); + database.executeFast("CREATE TABLE scheduled_messages_v2(mid INTEGER, uid INTEGER, send_state INTEGER, date INTEGER, data BLOB, ttl INTEGER, replydata BLOB, reply_to_message_id INTEGER, PRIMARY KEY(mid, uid))").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS send_state_idx_scheduled_messages_v2 ON scheduled_messages_v2(mid, send_state, date);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS uid_date_idx_scheduled_messages_v2 ON scheduled_messages_v2(uid, date);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS reply_to_idx_scheduled_messages_v2 ON scheduled_messages_v2(mid, reply_to_message_id);").stepThis().dispose(); - database.executeFast("CREATE TABLE messages_v2(mid INTEGER, uid INTEGER, read_state INTEGER, send_state INTEGER, date INTEGER, data BLOB, out INTEGER, ttl INTEGER, media INTEGER, replydata BLOB, imp INTEGER, mention INTEGER, forwards INTEGER, replies_data BLOB, thread_reply_id INTEGER, is_channel INTEGER, PRIMARY KEY(mid, uid))").stepThis().dispose(); + database.executeFast("CREATE TABLE messages_v2(mid INTEGER, uid INTEGER, read_state INTEGER, send_state INTEGER, date INTEGER, data BLOB, out INTEGER, ttl INTEGER, media INTEGER, replydata BLOB, imp INTEGER, mention INTEGER, forwards INTEGER, replies_data BLOB, thread_reply_id INTEGER, is_channel INTEGER, reply_to_message_id INTEGER, PRIMARY KEY(mid, uid))").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS uid_mid_read_out_idx_messages_v2 ON messages_v2(uid, mid, read_state, out);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS uid_date_mid_idx_messages_v2 ON messages_v2(uid, date, mid);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS mid_out_idx_messages_v2 ON messages_v2(mid, out);").stepThis().dispose(); @@ -308,6 +307,7 @@ public void openDatabase(int openTries) { database.executeFast("CREATE INDEX IF NOT EXISTS send_state_idx_messages_v2 ON messages_v2(mid, send_state, date);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS uid_mention_idx_messages_v2 ON messages_v2(uid, mention, read_state);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS is_channel_idx_messages_v2 ON messages_v2(mid, is_channel);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS reply_to_idx_messages_v2 ON messages_v2(mid, reply_to_message_id);").stepThis().dispose(); database.executeFast("CREATE TABLE download_queue(uid INTEGER, type INTEGER, date INTEGER, data BLOB, parent TEXT, PRIMARY KEY (uid, type));").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS type_date_idx_download_queue ON download_queue(type, date);").stepThis().dispose(); @@ -341,8 +341,8 @@ public void openDatabase(int openTries) { database.executeFast("CREATE TABLE params(id INTEGER PRIMARY KEY, seq INTEGER, pts INTEGER, date INTEGER, qts INTEGER, lsv INTEGER, sg INTEGER, pbytes BLOB)").stepThis().dispose(); database.executeFast("INSERT INTO params VALUES(1, 0, 0, 0, 0, 0, 0, NULL)").stepThis().dispose(); - database.executeFast("CREATE TABLE media_v3(mid INTEGER, uid INTEGER, date INTEGER, type INTEGER, data BLOB, PRIMARY KEY(mid, uid))").stepThis().dispose(); - database.executeFast("CREATE INDEX IF NOT EXISTS uid_mid_type_date_idx_media_v3 ON media_v3(uid, mid, type, date);").stepThis().dispose(); + database.executeFast("CREATE TABLE media_v4(mid INTEGER, uid INTEGER, date INTEGER, type INTEGER, data BLOB, PRIMARY KEY(mid, uid, type))").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS uid_mid_type_date_idx_media_v3 ON media_v4(uid, mid, type, date);").stepThis().dispose(); database.executeFast("CREATE TABLE bot_keyboard(uid INTEGER PRIMARY KEY, mid INTEGER, info BLOB)").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS bot_keyboard_idx_mid_v2 ON bot_keyboard(mid, uid);").stepThis().dispose(); @@ -445,6 +445,9 @@ public void openDatabase(int openTries) { try { updateDbToLastVersion(version); } catch (Exception e) { + if (BuildVars.DEBUG_PRIVATE_VERSION) { + throw e; + } FileLog.e(e); throw new RuntimeException("malformed"); } @@ -452,7 +455,9 @@ public void openDatabase(int openTries) { } } catch (Exception e) { FileLog.e(e); - + if (BuildVars.DEBUG_PRIVATE_VERSION) { + throw new RuntimeException(e); + } if (openTries < 3 && e.getMessage() != null && e.getMessage().contains("malformed")) { if (openTries == 2) { cleanupInternal(true); @@ -1465,9 +1470,62 @@ private void updateDbToLastVersion(int currentVersion) throws Exception { version = 84; } if (version == 84) { + database.executeFast("CREATE TABLE IF NOT EXISTS media_v4(mid INTEGER, uid INTEGER, date INTEGER, type INTEGER, data BLOB, PRIMARY KEY(mid, uid, type))").stepThis().dispose(); + database.beginTransaction(); + SQLiteCursor cursor; + try { + cursor = database.queryFinalized("SELECT mid, uid, date, type, data FROM media_v3 WHERE 1"); + } catch (Exception e) { + cursor = null; + FileLog.e(e); + } + if (cursor != null) { + SQLitePreparedStatement statement = database.executeFast("REPLACE INTO media_v4 VALUES(?, ?, ?, ?, ?)"); + while (cursor.next()) { + NativeByteBuffer data = cursor.byteBufferValue(4); + if (data == null) { + continue; + } + int mid = cursor.intValue(0); + long uid = cursor.longValue(1); + int lowerId = (int) uid; + if (lowerId == 0) { + int highId = (int) (uid >> 32); + uid = DialogObject.makeEncryptedDialogId(highId); + } + int date = cursor.intValue(2); + int type = cursor.intValue(3); + + statement.requery(); + statement.bindInteger(1, mid); + statement.bindLong(2, uid); + statement.bindInteger(3, date); + statement.bindInteger(4, type); + statement.bindByteBuffer(5, data); + statement.step(); + data.reuse(); + } + cursor.dispose(); + statement.dispose(); + } + database.commitTransaction(); + database.executeFast("DROP TABLE IF EXISTS media_v3;").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 85").stepThis().dispose(); + version = 85; } + if (version == 85) { + executeNoException("ALTER TABLE messages_v2 ADD COLUMN reply_to_message_id INTEGER default 0"); + executeNoException("ALTER TABLE scheduled_messages_v2 ADD COLUMN reply_to_message_id INTEGER default 0"); + database.executeFast("CREATE INDEX IF NOT EXISTS reply_to_idx_messages_v2 ON messages_v2(mid, reply_to_message_id);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS reply_to_idx_scheduled_messages_v2 ON scheduled_messages_v2(mid, reply_to_message_id);").stepThis().dispose(); + + executeNoException("UPDATE messages_v2 SET replydata = NULL"); + executeNoException("UPDATE scheduled_messages_v2 SET replydata = NULL"); + database.executeFast("PRAGMA user_version = 86").stepThis().dispose(); + version = 86; + } FileLog.d("MessagesStorage db migration finished"); AndroidUtilities.runOnUIThread(() -> { @@ -3697,7 +3755,7 @@ public void deleteDialog(long did, int messagesOnly) { database.executeFast("DELETE FROM messages_holes WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM bot_keyboard WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM media_counts_v2 WHERE uid = " + did).stepThis().dispose(); - database.executeFast("DELETE FROM media_v3 WHERE uid = " + did).stepThis().dispose(); + database.executeFast("DELETE FROM media_v4 WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM media_holes_v2 WHERE uid = " + did).stepThis().dispose(); getMediaDataController().clearBotKeyboard(did, null); @@ -3718,7 +3776,7 @@ public void deleteDialog(long did, int messagesOnly) { database.executeFast("DELETE FROM messages_v2 WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM bot_keyboard WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM media_counts_v2 WHERE uid = " + did).stepThis().dispose(); - database.executeFast("DELETE FROM media_v3 WHERE uid = " + did).stepThis().dispose(); + database.executeFast("DELETE FROM media_v4 WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM messages_holes WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM media_holes_v2 WHERE uid = " + did).stepThis().dispose(); getMediaDataController().clearBotKeyboard(did, null); @@ -3850,7 +3908,7 @@ public void resetDialogs(TLRPC.messages_Dialogs dialogsRes, int messagesCount, i database.executeFast("DELETE FROM messages_v2 WHERE uid IN " + ids).stepThis().dispose(); database.executeFast("DELETE FROM polls_v2 WHERE 1").stepThis().dispose(); database.executeFast("DELETE FROM bot_keyboard WHERE uid IN " + ids).stepThis().dispose(); - database.executeFast("DELETE FROM media_v3 WHERE uid IN " + ids).stepThis().dispose(); + database.executeFast("DELETE FROM media_v4 WHERE uid IN " + ids).stepThis().dispose(); database.executeFast("DELETE FROM messages_holes WHERE uid IN " + ids).stepThis().dispose(); database.executeFast("DELETE FROM media_holes_v2 WHERE uid IN " + ids).stepThis().dispose(); database.commitTransaction(); @@ -4019,7 +4077,7 @@ public void emptyMessagesMedia(long dialogId, ArrayList mids) { cursor.dispose(); deleteFromDownloadQueue(idsToDelete, true); if (!messages.isEmpty()) { - SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?)"); + SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 0)"); for (int a = 0; a < messages.size(); a++) { TLRPC.Message message = messages.get(a); @@ -8423,7 +8481,7 @@ public void putWebPages(LongSparseArray webPages) { database.beginTransaction(); SQLitePreparedStatement state = database.executeFast("UPDATE messages_v2 SET data = ? WHERE mid = ? AND uid = ?"); - SQLitePreparedStatement state2 = database.executeFast("UPDATE media_v3 SET data = ? WHERE mid = ? AND uid = ?"); + SQLitePreparedStatement state2 = database.executeFast("UPDATE media_v4 SET data = ? WHERE mid = ? AND uid = ?"); for (int a = 0; a < messages.size(); a++) { TLRPC.Message message = messages.get(a); NativeByteBuffer data = new NativeByteBuffer(message.getObjectSize()); @@ -8477,7 +8535,7 @@ public void overwriteChannel(long channelId, TLRPC.TL_updates_channelDifferenceT database.executeFast("DELETE FROM messages_v2 WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM bot_keyboard WHERE uid = " + did).stepThis().dispose(); database.executeFast("UPDATE media_counts_v2 SET old = 1 WHERE uid = " + did).stepThis().dispose(); - database.executeFast("DELETE FROM media_v3 WHERE uid = " + did).stepThis().dispose(); + database.executeFast("DELETE FROM media_v4 WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM messages_holes WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM media_holes_v2 WHERE uid = " + did).stepThis().dispose(); getMediaDataController().clearBotKeyboard(did, null); @@ -8747,7 +8805,7 @@ private void putMessagesInternal(ArrayList messages, boolean with database.beginTransaction(); } - SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO scheduled_messages_v2 VALUES(?, ?, ?, ?, ?, ?, NULL)"); + SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO scheduled_messages_v2 VALUES(?, ?, ?, ?, ?, ?, NULL, 0)"); SQLitePreparedStatement state_randoms = database.executeFast("REPLACE INTO randoms_v2 VALUES(?, ?, ?)"); ArrayList dialogsToUpdate = new ArrayList<>(); @@ -8835,7 +8893,7 @@ private void putMessagesInternal(ArrayList messages, boolean with LongSparseArray> dialogMessagesIdsMap = new LongSparseArray<>(); LongSparseArray> dialogMentionsIdsMap = new LongSparseArray<>(); - SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?)"); + SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 0)"); SQLitePreparedStatement state_media = null; SQLitePreparedStatement state_randoms = database.executeFast("REPLACE INTO randoms_v2 VALUES(?, ?, ?)"); SQLitePreparedStatement state_download = database.executeFast("REPLACE INTO download_queue VALUES(?, ?, ?, ?, ?)"); @@ -8938,7 +8996,7 @@ private void putMessagesInternal(ArrayList messages, boolean with SparseIntArray mediaTypes = dialogMediaTypes.get(dialogId); ArrayList messagesMediaIdsMap = dialogMessagesMediaIdsMap.get(dialogId); SparseIntArray mediaTypesChange = null; - SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT mid, type FROM media_v3 WHERE mid IN(%s) AND uid = %d", messageMediaIds.toString(), dialogId)); + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT mid, type FROM media_v4 WHERE mid IN(%s) AND uid = %d", messageMediaIds.toString(), dialogId)); while (cursor.next()) { int mid = cursor.intValue(0); int type = cursor.intValue(1); @@ -9120,7 +9178,7 @@ private void putMessagesInternal(ArrayList messages, boolean with if (MediaDataController.canAddMessageToMedia(message)) { if (state_media == null) { - state_media = database.executeFast("REPLACE INTO media_v3 VALUES(?, ?, ?, ?, ?)"); + state_media = database.executeFast("REPLACE INTO media_v4 VALUES(?, ?, ?, ?, ?)"); } state_media.requery(); state_media.bindInteger(1, messageId); @@ -9561,14 +9619,14 @@ private long[] updateMessageStateAndIdInternal(long randomId, long dialogId, Int } try { - state = database.executeFast("UPDATE media_v3 SET mid = ? WHERE mid = ? AND uid = ?"); + state = database.executeFast("UPDATE media_v4 SET mid = ? WHERE mid = ? AND uid = ?"); state.bindInteger(1, newId); state.bindInteger(2, oldMessageId); state.bindLong(3, did); state.step(); } catch (Exception e) { try { - database.executeFast(String.format(Locale.US, "DELETE FROM media_v3 WHERE mid = %d AND uid = %d", oldMessageId, did)).stepThis().dispose(); + database.executeFast(String.format(Locale.US, "DELETE FROM media_v4 WHERE mid = %d AND uid = %d", oldMessageId, did)).stepThis().dispose(); } catch (Exception e2) { FileLog.e(e2); } @@ -9947,6 +10005,38 @@ private ArrayList markMessagesAsDeletedInternal(long dialogId, ArrayList getFileLoader().cancelLoadFiles(namesToDelete)); getFileLoader().deleteFiles(filesToDelete, 0); @@ -9965,7 +10055,7 @@ private ArrayList markMessagesAsDeletedInternal(long dialogId, ArrayList markMessagesAsDeletedInternal(long dialogId, ArrayList markMessagesAsDeletedInternal(long dialogId, ArrayList> mediaCounts = null; while (cursor.next()) { long uid = cursor.longValue(0); @@ -10034,7 +10124,7 @@ private ArrayList markMessagesAsDeletedInternal(long dialogId, ArrayList value = mediaCounts.valueAt(c); @@ -10062,7 +10152,7 @@ private ArrayList markMessagesAsDeletedInternal(long dialogId, ArrayList markMessagesAsDeletedInternal(long channelId, int mid, b } database.executeFast(String.format(Locale.US, "DELETE FROM messages_v2 WHERE uid = %d AND mid <= %d", -channelId, mid)).stepThis().dispose(); - database.executeFast(String.format(Locale.US, "DELETE FROM media_v3 WHERE uid = %d AND mid <= %d", -channelId, mid)).stepThis().dispose(); + database.executeFast(String.format(Locale.US, "DELETE FROM media_v4 WHERE uid = %d AND mid <= %d", -channelId, mid)).stepThis().dispose(); database.executeFast(String.format(Locale.US, "UPDATE media_counts_v2 SET old = 1 WHERE uid = %d", -channelId)).stepThis().dispose(); updateWidgets(dialogsIds); return dialogsIds; @@ -10600,8 +10690,8 @@ public void replaceMessageIfExists(TLRPC.Message message, ArrayList database.beginTransaction(); - SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?)"); - SQLitePreparedStatement state2 = database.executeFast("REPLACE INTO media_v3 VALUES(?, ?, ?, ?, ?)"); + SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 0)"); + SQLitePreparedStatement state2 = database.executeFast("REPLACE INTO media_v4 VALUES(?, ?, ?, ?, ?)"); if (message.dialog_id == 0) { MessageObject.getDialogId(message); } @@ -10693,7 +10783,7 @@ public void putMessages(TLRPC.messages_Messages messages, long dialogId, int loa try { if (scheduled) { database.executeFast(String.format(Locale.US, "DELETE FROM scheduled_messages_v2 WHERE uid = %d AND mid > 0", dialogId)).stepThis().dispose(); - SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO scheduled_messages_v2 VALUES(?, ?, ?, ?, ?, ?, NULL)"); + SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO scheduled_messages_v2 VALUES(?, ?, ?, ?, ?, ?, NULL, 0)"); int count = messages.messages.size(); for (int a = 0; a < count; a++) { TLRPC.Message message = messages.messages.get(a); @@ -10758,8 +10848,8 @@ public void putMessages(TLRPC.messages_Messages messages, long dialogId, int loa ArrayList namesToDelete = new ArrayList<>(); ArrayList> idsToDelete = new ArrayList<>(); - SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?)"); - SQLitePreparedStatement state_media = database.executeFast("REPLACE INTO media_v3 VALUES(?, ?, ?, ?, ?)"); + SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 0)"); + SQLitePreparedStatement state_media = database.executeFast("REPLACE INTO media_v4 VALUES(?, ?, ?, ?, ?)"); SQLitePreparedStatement state_polls = null; SQLitePreparedStatement state_webpage = null; SQLitePreparedStatement state_tasks = null; @@ -10923,7 +11013,7 @@ public void putMessages(TLRPC.messages_Messages messages, long dialogId, int loa state_media.step(); } else if (message instanceof TLRPC.TL_messageService && message.action instanceof TLRPC.TL_messageActionHistoryClear) { try { - database.executeFast(String.format(Locale.US, "DELETE FROM media_v3 WHERE mid = %d AND uid = %d", message.id, dialogId)).stepThis().dispose(); + database.executeFast(String.format(Locale.US, "DELETE FROM media_v4 WHERE mid = %d AND uid = %d", message.id, dialogId)).stepThis().dispose(); database.executeFast("DELETE FROM media_counts_v2 WHERE uid = " + dialogId).stepThis().dispose(); } catch (Exception e2) { FileLog.e(e2); @@ -11413,9 +11503,9 @@ private void putDialogsInternal(TLRPC.messages_Dialogs dialogs, int check) { } if (!dialogs.dialogs.isEmpty()) { - SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?)"); + SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 0)"); SQLitePreparedStatement state_dialogs = database.executeFast("REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); - SQLitePreparedStatement state_media = database.executeFast("REPLACE INTO media_v3 VALUES(?, ?, ?, ?, ?)"); + SQLitePreparedStatement state_media = database.executeFast("REPLACE INTO media_v4 VALUES(?, ?, ?, ?, ?)"); SQLitePreparedStatement state_settings = database.executeFast("REPLACE INTO dialog_settings VALUES(?, ?)"); SQLitePreparedStatement state_holes = database.executeFast("REPLACE INTO messages_holes VALUES(?, ?, ?)"); SQLitePreparedStatement state_media_holes = database.executeFast("REPLACE INTO media_holes_v2 VALUES(?, ?, ?, ?)"); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MusicBrowserService.java b/TMessagesProj/src/main/java/org/telegram/messenger/MusicBrowserService.java index 0f746636e1a..f1c54e889c0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MusicBrowserService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MusicBrowserService.java @@ -158,7 +158,7 @@ public void onLoadChildren(String parentMediaId, Result usersToLoad = new ArrayList<>(); ArrayList chatsToLoad = new ArrayList<>(); - SQLiteCursor cursor = messagesStorage.getDatabase().queryFinalized(String.format(Locale.US, "SELECT DISTINCT uid FROM media_v3 WHERE uid != 0 AND mid > 0 AND type = %d", MediaDataController.MEDIA_MUSIC)); + SQLiteCursor cursor = messagesStorage.getDatabase().queryFinalized(String.format(Locale.US, "SELECT DISTINCT uid FROM media_v4 WHERE uid != 0 AND mid > 0 AND type = %d", MediaDataController.MEDIA_MUSIC)); while (cursor.next()) { long dialogId = cursor.longValue(0); if (DialogObject.isEncryptedDialog(dialogId)) { @@ -174,7 +174,7 @@ public void onLoadChildren(String parentMediaId, Result 0 AND type = %d ORDER BY date DESC, mid DESC", ids, MediaDataController.MEDIA_MUSIC)); + cursor = messagesStorage.getDatabase().queryFinalized(String.format(Locale.US, "SELECT uid, data, mid FROM media_v4 WHERE uid IN (%s) AND mid > 0 AND type = %d ORDER BY date DESC, mid DESC", ids, MediaDataController.MEDIA_MUSIC)); while (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(1); if (data != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java index d6f1d40c43b..31491f40ab8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java @@ -223,6 +223,7 @@ public class NotificationCenter { public static final int appUpdateAvailable = totalEvents++; public static final int onDatabaseMigration = totalEvents++; public static final int onEmojiInteractionsReceived = totalEvents++; + public static final int emojiPreviewThemesChanged = totalEvents++; private SparseArray> observers = new SparseArray<>(); private SparseArray> removeAfterBroadcast = new SparseArray<>(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java index 9bec22ab3f7..94d5c394b24 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java @@ -1760,6 +1760,8 @@ private String getShortStringForMessage(MessageObject messageObject, String[] us : LocaleController.formatString("ChangedChatThemeTo", R.string.ChatThemeChangedTo, name, emoticon); } return msg; + } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest) { + return messageObject.messageText.toString(); } } else { if (messageObject.isMediaEmpty()) { @@ -2334,6 +2336,8 @@ private String getStringForMessage(MessageObject messageObject, boolean shortMes ? LocaleController.formatString("ChangedChatThemeYou", R.string.ChatThemeChangedYou, emoticon) : LocaleController.formatString("ChangedChatThemeTo", R.string.ChatThemeChangedTo, name, emoticon); } + } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest) { + msg = messageObject.messageText.toString(); } } else if (ChatObject.isChannel(chat) && !chat.megagroup) { if (messageObject.isMediaEmpty()) { @@ -4125,8 +4129,9 @@ void call() { } } + boolean needAddPerson = !(lastMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest); NotificationCompat.MessagingStyle messagingStyle; - if (selfPerson != null) { + if (selfPerson != null && needAddPerson) { messagingStyle = new NotificationCompat.MessagingStyle(selfPerson); } else { messagingStyle = new NotificationCompat.MessagingStyle(""); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index b004f806c8d..9d06b00ab66 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -1614,7 +1614,7 @@ public void sendSticker(TLRPC.Document document, String query, long peer, Messag AndroidUtilities.runOnUIThread(() -> { if (bitmapFinal[0] != null && keyFinal[0] != null) { - ImageLoader.getInstance().putImageToCache(new BitmapDrawable(bitmapFinal[0]), keyFinal[0]); + ImageLoader.getInstance().putImageToCache(new BitmapDrawable(bitmapFinal[0]), keyFinal[0], false); } sendMessage((TLRPC.TL_document) finalDocument, null, null, peer, replyToMsg, replyToTopMsg, null, null, null, null, notify, scheduleDate, 0, parentObject, sendAnimationData); }); @@ -6717,7 +6717,7 @@ public static void prepareSendingBotContextResult(AccountInstance accountInstanc AndroidUtilities.runOnUIThread(() -> { if (finalDocument != null) { if (precahcedThumb[0] != null && precachedKey[0] != null) { - ImageLoader.getInstance().putImageToCache(new BitmapDrawable(precahcedThumb[0]), precachedKey[0]); + ImageLoader.getInstance().putImageToCache(new BitmapDrawable(precahcedThumb[0]), precachedKey[0], false); } accountInstance.getSendMessagesHelper().sendMessage(finalDocument, null, finalPathFinal, dialogId, replyToMsg, replyToTopMsg, result.send_message.message, result.send_message.entities, result.send_message.reply_markup, params, notify, scheduleDate, 0, result, null); } else if (finalPhoto != null) { @@ -7395,7 +7395,7 @@ public static void prepareSendingMedia(AccountInstance accountInstance, ArrayLis } AndroidUtilities.runOnUIThread(() -> { if (thumbFinal != null && thumbKeyFinal != null) { - ImageLoader.getInstance().putImageToCache(new BitmapDrawable(thumbFinal), thumbKeyFinal); + ImageLoader.getInstance().putImageToCache(new BitmapDrawable(thumbFinal), thumbKeyFinal, false); } if (editingMessageObject != null) { accountInstance.getSendMessagesHelper().editMessage(editingMessageObject, null, videoEditedInfo, videoFinal, finalPath, params, false, parentFinal); @@ -7592,7 +7592,7 @@ public static void prepareSendingMedia(AccountInstance accountInstance, ArrayLis } AndroidUtilities.runOnUIThread(() -> { if (bitmapFinal[0] != null && keyFinal[0] != null) { - ImageLoader.getInstance().putImageToCache(new BitmapDrawable(bitmapFinal[0]), keyFinal[0]); + ImageLoader.getInstance().putImageToCache(new BitmapDrawable(bitmapFinal[0]), keyFinal[0], false); } if (editingMessageObject != null) { accountInstance.getSendMessagesHelper().editMessage(editingMessageObject, photoFinal, null, null, null, params, false, parentFinal); @@ -8035,7 +8035,7 @@ public static void prepareSendingVideo(AccountInstance accountInstance, String v } AndroidUtilities.runOnUIThread(() -> { if (thumbFinal != null && thumbKeyFinal != null) { - ImageLoader.getInstance().putImageToCache(new BitmapDrawable(thumbFinal), thumbKeyFinal); + ImageLoader.getInstance().putImageToCache(new BitmapDrawable(thumbFinal), thumbKeyFinal, false); } if (editingMessageObject != null) { accountInstance.getSendMessagesHelper().editMessage(editingMessageObject, null, videoEditedInfo, videoFinal, finalPath, params, false, parentFinal); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index 2e6d7065719..323f9933f1f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -23,6 +23,7 @@ import org.json.JSONObject; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.SerializedData; +import org.telegram.ui.Components.SharedMediaLayout; import org.telegram.ui.Components.SwipeGestureSettingsView; import org.telegram.tgnet.TLRPC; @@ -133,6 +134,8 @@ public class SharedConfig { private static int chatSwipeAction; public static int distanceSystemType; + public static int mediaColumnsCount = 3; + public static int fastScrollHintCount = 3; static { loadConfig(); @@ -370,6 +373,9 @@ public static void loadConfig() { messageSeenHintCount = preferences.getInt("messageSeenCount", 3); emojiInteractionsHintCount = preferences.getInt("emojiInteractionsHintCount", 3); dayNightThemeSwitchHintCount = preferences.getInt("dayNightThemeSwitchHintCount", 3); + mediaColumnsCount = preferences.getInt("mediaColumnsCount", 3); + fastScrollHintCount = preferences.getInt("fastScrollHintCount", 3); + preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); showNotificationsForAllAccounts = preferences.getBoolean("AllAccounts", true); @@ -1141,4 +1147,18 @@ public static int getDevicePerformanceClass() { return devicePerformanceClass; } + + public static void setMediaColumnsCount(int count) { + if (mediaColumnsCount != count) { + mediaColumnsCount = count; + ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).edit().putInt("mediaColumnsCount", mediaColumnsCount).apply(); + } + } + + public static void setFastScrollHintCount(int count) { + if (fastScrollHintCount != count) { + fastScrollHintCount = count; + ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).edit().putInt("fastScrollHintCount", fastScrollHintCount).apply(); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java index 062e440ab3a..b522187e4e3 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java @@ -33,6 +33,7 @@ public class Utilities { public static volatile DispatchQueue cacheClearQueue = new DispatchQueue("cacheClearQueue"); public static volatile DispatchQueue searchQueue = new DispatchQueue("searchQueue"); public static volatile DispatchQueue phoneBookQueue = new DispatchQueue("phoneBookQueue"); + public static volatile DispatchQueue themeQueue = new DispatchQueue("themeQueue"); final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java index e79b8d3dc26..8a6fd796326 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java @@ -430,7 +430,7 @@ public boolean takePicture(final File path, final CameraSession session, final R outputStream.getFD().sync(); outputStream.close(); if (scaled != null) { - ImageLoader.getInstance().putImageToCache(new BitmapDrawable(scaled), key); + ImageLoader.getInstance().putImageToCache(new BitmapDrawable(scaled), key, false); } if (callback != null) { callback.run(); @@ -446,7 +446,7 @@ public boolean takePicture(final File path, final CameraSession session, final R outputStream.getFD().sync(); outputStream.close(); if (bitmap != null) { - ImageLoader.getInstance().putImageToCache(new BitmapDrawable(bitmap), key); + ImageLoader.getInstance().putImageToCache(new BitmapDrawable(bitmap), key, false); } } catch (Exception e) { FileLog.e(e); @@ -726,7 +726,7 @@ private void finishRecordingVideo() { if (onVideoTakeCallback != null) { String path = cacheFile.getAbsolutePath(); if (bitmapFinal != null) { - ImageLoader.getInstance().putImageToCache(new BitmapDrawable(bitmapFinal), Utilities.MD5(path)); + ImageLoader.getInstance().putImageToCache(new BitmapDrawable(bitmapFinal), Utilities.MD5(path), false); } onVideoTakeCallback.onFinishVideoRecording(path, durationFinal); onVideoTakeCallback = null; diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index a9398f35bab..bd8e360f001 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -12,6 +12,8 @@ import android.os.Build; import android.text.TextUtils; +import com.google.android.exoplayer2.util.Log; + import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.Utilities; @@ -64,7 +66,7 @@ public class TLRPC { public static final int MESSAGE_FLAG_HAS_BOT_ID = 0x00000800; public static final int MESSAGE_FLAG_EDITED = 0x00008000; - public static final int LAYER = 133; + public static final int LAYER = 134; public static class TL_stats_megagroupStats extends TLObject { public static int constructor = 0xef7ff916; @@ -5193,7 +5195,9 @@ public static abstract class ChatInvite extends TLObject { public boolean broadcast; public boolean isPublic; public boolean megagroup; + public boolean request_needed; public String title; + public String about; public Photo photo; public int participants_count; public ArrayList participants = new ArrayList<>(); @@ -5203,7 +5207,7 @@ public static abstract class ChatInvite extends TLObject { public static ChatInvite TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { ChatInvite result = null; switch (constructor) { - case 0xdfc2f58e: + case 0x300c44c1: result = new TL_chatInvite(); break; case 0x61695cb0: @@ -5224,8 +5228,7 @@ public static ChatInvite TLdeserialize(AbstractSerializedData stream, int constr } public static class TL_chatInvite extends ChatInvite { - public static int constructor = 0xdfc2f58e; - + public static int constructor = 0x300c44c1; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -5233,7 +5236,12 @@ public void readParams(AbstractSerializedData stream, boolean exception) { broadcast = (flags & 2) != 0; isPublic = (flags & 4) != 0; megagroup = (flags & 8) != 0; + request_needed = (flags & 64) != 0; title = stream.readString(exception); + boolean hasAbout = (flags & 32) != 0; + if (hasAbout) { + about = stream.readString(exception); + } photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); participants_count = stream.readInt32(exception); if ((flags & 16) != 0) { @@ -5261,8 +5269,13 @@ public void serializeToStream(AbstractSerializedData stream) { flags = broadcast ? (flags | 2) : (flags &~ 2); flags = isPublic ? (flags | 4) : (flags &~ 4); flags = megagroup ? (flags | 8) : (flags &~ 8); + flags = about != null ? (flags | 32) : (flags &~ 32); + flags = request_needed ? (flags | 64) : (flags &~ 64); stream.writeInt32(flags); stream.writeString(title); + if (about != null) { + stream.writeString(about); + } photo.serializeToStream(stream); stream.writeInt32(participants_count); if ((flags & 16) != 0) { @@ -5680,10 +5693,14 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_chatInviteImporter extends TLObject { - public static int constructor = 0xb5cd5f4; + public static int constructor = 0x8c5adfd9; + public int flags; + public boolean requested; public long user_id; public int date; + public String about; + public long approved_by; public static TL_chatInviteImporter TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { if (TL_chatInviteImporter.constructor != constructor) { @@ -5699,14 +5716,30 @@ public static TL_chatInviteImporter TLdeserialize(AbstractSerializedData stream, } public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + requested = (flags & 1) != 0; user_id = stream.readInt64(exception); date = stream.readInt32(exception); + if ((flags & 4) != 0) { + about = stream.readString(exception); + } + if ((flags & 2) != 0) { + approved_by = stream.readInt64(exception); + } } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + flags = requested ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); stream.writeInt64(user_id); stream.writeInt32(date); + if ((flags & 4) != 0) { + stream.writeString(about); + } + if ((flags & 2) != 0) { + stream.writeInt64(approved_by); + } } } @@ -8252,40 +8285,6 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class TL_chatTheme extends TLObject { - public static int constructor = 0xed0b5c33; - - public String emoticon; - public Theme theme; - public Theme dark_theme; - - public static TL_chatTheme TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_chatTheme.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_chatTheme", constructor)); - } else { - return null; - } - } - TL_chatTheme result = new TL_chatTheme(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - emoticon = stream.readString(exception); - theme = Theme.TLdeserialize(stream, stream.readInt32(exception), exception); - dark_theme = Theme.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeString(emoticon); - theme.serializeToStream(stream); - dark_theme.serializeToStream(stream); - } - } - public static abstract class messages_DhConfig extends TLObject { public byte[] random; public int g; @@ -10459,13 +10458,21 @@ public static abstract class ChatFull extends TLObject { public int ttl_period; public ArrayList pending_suggestions = new ArrayList<>(); public Peer groupcall_default_join_as; + public ArrayList recent_requesters = new ArrayList<>(); public String theme_emoticon; + public int requests_pending; public long inviterId; //custom public int invitesCount; //custom public static ChatFull TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { ChatFull result = null; switch (constructor) { + case 0x46a6ffb4: + result = new TL_chatFull(); + break; + case 0x59cff963: + result = new TL_channelFull(); + break; case 0x1c87a71a: result = new TL_channelFull_layer98(); break; @@ -10533,10 +10540,10 @@ public static ChatFull TLdeserialize(AbstractSerializedData stream, int construc result = new TL_channelFull_layer132(); break; case 0x4dbdc099: - result = new TL_chatFull(); + result = new TL_chatFull_layer133(); break; case 0xe9b27a17: - result = new TL_channelFull(); + result = new TL_channelFull_layer133(); break; case 0x1b7c9db3: result = new TL_chatFull_layer121(); @@ -11678,7 +11685,7 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class TL_chatFull extends ChatFull { + public static class TL_chatFull_layer133 extends ChatFull { public static int constructor = 0x4dbdc099; @@ -11777,223 +11784,133 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class TL_channelFull extends ChatFull { - public static int constructor = 0xe9b27a17; - + public static class TL_chatFull extends ChatFull { + public static int constructor = 0x46a6ffb4; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); - can_view_participants = (flags & 8) != 0; - can_set_username = (flags & 64) != 0; - can_set_stickers = (flags & 128) != 0; - hidden_prehistory = (flags & 1024) != 0; - can_set_location = (flags & 65536) != 0; - has_scheduled = (flags & 524288) != 0; - can_view_stats = (flags & 1048576) != 0; - blocked = (flags & 4194304) != 0; + can_set_username = (flags & 128) != 0; + has_scheduled = (flags & 256) != 0; id = stream.readInt64(exception); about = stream.readString(exception); - if ((flags & 1) != 0) { - participants_count = stream.readInt32(exception); - } - if ((flags & 2) != 0) { - admins_count = stream.readInt32(exception); - } - if ((flags & 4) != 0) { - kicked_count = stream.readInt32(exception); - } + participants = ChatParticipants.TLdeserialize(stream, stream.readInt32(exception), exception); if ((flags & 4) != 0) { - banned_count = stream.readInt32(exception); - } - if ((flags & 8192) != 0) { - online_count = stream.readInt32(exception); + chat_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); } - read_inbox_max_id = stream.readInt32(exception); - read_outbox_max_id = stream.readInt32(exception); - unread_count = stream.readInt32(exception); - chat_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); - if ((flags & 8388608) != 0) { - exported_invite = (TLRPC.TL_chatInviteExported) ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); - } - int magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; + if ((flags & 8192) != 0) { + exported_invite = ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); } - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - BotInfo object = BotInfo.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { + if ((flags & 8) != 0) { + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } return; } - bot_info.add(object); - } - if ((flags & 16) != 0) { - migrated_from_chat_id = stream.readInt64(exception); - } - if ((flags & 16) != 0) { - migrated_from_max_id = stream.readInt32(exception); + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + BotInfo object = BotInfo.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + bot_info.add(object); + } } - if ((flags & 32) != 0) { + if ((flags & 64) != 0) { pinned_msg_id = stream.readInt32(exception); } - if ((flags & 256) != 0) { - stickerset = StickerSet.TLdeserialize(stream, stream.readInt32(exception), exception); - } - if ((flags & 512) != 0) { - available_min_id = stream.readInt32(exception); - } if ((flags & 2048) != 0) { folder_id = stream.readInt32(exception); } + if ((flags & 4096) != 0) { + call = TL_inputGroupCall.TLdeserialize(stream, stream.readInt32(exception), exception); + } if ((flags & 16384) != 0) { - linked_chat_id = stream.readInt64(exception); + ttl_period = stream.readInt32(exception); } if ((flags & 32768) != 0) { - location = ChannelLocation.TLdeserialize(stream, stream.readInt32(exception), exception); - } - if ((flags & 131072) != 0) { - slowmode_seconds = stream.readInt32(exception); - } - if ((flags & 262144) != 0) { - slowmode_next_send_date = stream.readInt32(exception); - } - if ((flags & 4096) != 0) { - stats_dc = stream.readInt32(exception); + groupcall_default_join_as = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); } - pts = stream.readInt32(exception); - if ((flags & 2097152) != 0) { - call = TL_inputGroupCall.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 65536) != 0) { + theme_emoticon = stream.readString(exception); } - if ((flags & 16777216) != 0) { - ttl_period = stream.readInt32(exception); + if ((flags & 131072) != 0) { + requests_pending = stream.readInt32(exception); } - if ((flags & 33554432) != 0) { - magic = stream.readInt32(exception); + if ((flags & 131072) != 0) { + int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { if (exception) { throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); } return; } - count = stream.readInt32(exception); + int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - pending_suggestions.add(stream.readString(exception)); + recent_requesters.add(stream.readInt64(exception)); } } - if ((flags & 67108864) != 0) { - groupcall_default_join_as = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - } - if ((flags & 134217728) != 0) { - theme_emoticon = stream.readString(exception); - } } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - flags = can_view_participants ? (flags | 8) : (flags &~ 8); - flags = can_set_username ? (flags | 64) : (flags &~ 64); - flags = can_set_stickers ? (flags | 128) : (flags &~ 128); - flags = hidden_prehistory ? (flags | 1024) : (flags &~ 1024); - flags = can_set_location ? (flags | 65536) : (flags &~ 65536); - flags = has_scheduled ? (flags | 524288) : (flags &~ 524288); - flags = can_view_stats ? (flags | 1048576) : (flags &~ 1048576); - flags = blocked ? (flags | 4194304) : (flags &~ 4194304); + flags = can_set_username ? (flags | 128) : (flags &~ 128); + flags = has_scheduled ? (flags | 256) : (flags &~ 256); stream.writeInt32(flags); stream.writeInt64(id); stream.writeString(about); - if ((flags & 1) != 0) { - stream.writeInt32(participants_count); - } - if ((flags & 2) != 0) { - stream.writeInt32(admins_count); - } - if ((flags & 4) != 0) { - stream.writeInt32(kicked_count); - } + participants.serializeToStream(stream); if ((flags & 4) != 0) { - stream.writeInt32(banned_count); - } - if ((flags & 8192) != 0) { - stream.writeInt32(online_count); + chat_photo.serializeToStream(stream); } - stream.writeInt32(read_inbox_max_id); - stream.writeInt32(read_outbox_max_id); - stream.writeInt32(unread_count); - chat_photo.serializeToStream(stream); notify_settings.serializeToStream(stream); - if ((flags & 8388608) != 0) { + if ((flags & 8192) != 0) { exported_invite.serializeToStream(stream); } - stream.writeInt32(0x1cb5c415); - int count = bot_info.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - bot_info.get(a).serializeToStream(stream); - } - if ((flags & 16) != 0) { - stream.writeInt64(migrated_from_chat_id); - } - if ((flags & 16) != 0) { - stream.writeInt32(migrated_from_max_id); + if ((flags & 8) != 0) { + stream.writeInt32(0x1cb5c415); + int count = bot_info.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + bot_info.get(a).serializeToStream(stream); + } } - if ((flags & 32) != 0) { + if ((flags & 64) != 0) { stream.writeInt32(pinned_msg_id); } - if ((flags & 256) != 0) { - stickerset.serializeToStream(stream); - } - if ((flags & 512) != 0) { - stream.writeInt32(available_min_id); - } if ((flags & 2048) != 0) { stream.writeInt32(folder_id); } + if ((flags & 4096) != 0) { + call.serializeToStream(stream); + } if ((flags & 16384) != 0) { - stream.writeInt64(linked_chat_id); + stream.writeInt32(ttl_period); } if ((flags & 32768) != 0) { - location.serializeToStream(stream); - } - if ((flags & 131072) != 0) { - stream.writeInt32(slowmode_seconds); - } - if ((flags & 262144) != 0) { - stream.writeInt32(slowmode_next_send_date); - } - if ((flags & 4096) != 0) { - stream.writeInt32(stats_dc); + groupcall_default_join_as.serializeToStream(stream); } - stream.writeInt32(pts); - if ((flags & 2097152) != 0) { - call.serializeToStream(stream); + if ((flags & 65536) != 0) { + stream.writeString(theme_emoticon); } - if ((flags & 16777216) != 0) { - stream.writeInt32(ttl_period); + if ((flags & 131072) != 0) { + stream.writeInt32(requests_pending); } - if ((flags & 33554432) != 0) { + if ((flags & 131072) != 0) { stream.writeInt32(0x1cb5c415); - count = pending_suggestions.size(); + int count = recent_requesters.size(); stream.writeInt32(count); for (int a = 0; a < count; a++) { - stream.writeString(pending_suggestions.get(a)); + stream.writeInt64(recent_requesters.get(a)); } } - if ((flags & 67108864) != 0) { - groupcall_default_join_as.serializeToStream(stream); - } - if ((flags & 134217728) != 0) { - stream.writeString(theme_emoticon); - } } } - public static class TL_channelFull_layer131 extends TL_channelFull { - public static int constructor = 0x548c3f93; - + public static class TL_channelFull extends ChatFull { + public static int constructor = 0x59cff963; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -12028,7 +11945,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { chat_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); if ((flags & 8388608) != 0) { - exported_invite = (TL_chatInviteExported) ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); + exported_invite = ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); } int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -12101,6 +12018,25 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags & 67108864) != 0) { groupcall_default_join_as = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); } + if ((flags & 134217728) != 0) { + theme_emoticon = stream.readString(exception); + } + if ((flags & 268435456) != 0) { + requests_pending = stream.readInt32(exception); + } + if ((flags & 268435456) != 0) { + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + recent_requesters.add(stream.readInt64(exception)); + } + } } public void serializeToStream(AbstractSerializedData stream) { @@ -12196,11 +12132,25 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags & 67108864) != 0) { groupcall_default_join_as.serializeToStream(stream); } + if ((flags & 134217728) != 0) { + stream.writeString(theme_emoticon); + } + if ((flags & 268435456) != 0) { + stream.writeInt32(requests_pending); + } + if ((flags & 268435456) != 0) { + stream.writeInt32(0x1cb5c415); + count = recent_requesters.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt64(recent_requesters.get(a)); + } + } } } - public static class TL_channelFull_layer122 extends TL_channelFull { - public static int constructor = 0xef3a6acd; + public static class TL_channelFull_layer133 extends ChatFull { + public static int constructor = 0xe9b27a17; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -12213,7 +12163,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { has_scheduled = (flags & 524288) != 0; can_view_stats = (flags & 1048576) != 0; blocked = (flags & 4194304) != 0; - id = stream.readInt32(exception); + id = stream.readInt64(exception); about = stream.readString(exception); if ((flags & 1) != 0) { participants_count = stream.readInt32(exception); @@ -12235,9 +12185,8 @@ public void readParams(AbstractSerializedData stream, boolean exception) { unread_count = stream.readInt32(exception); chat_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); - ExportedChatInvite invite = ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); - if (invite instanceof TL_chatInviteExported) { - exported_invite = (TL_chatInviteExported) invite; + if ((flags & 8388608) != 0) { + exported_invite = (TLRPC.TL_chatInviteExported) ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); } int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -12255,7 +12204,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { bot_info.add(object); } if ((flags & 16) != 0) { - migrated_from_chat_id = stream.readInt32(exception); + migrated_from_chat_id = stream.readInt64(exception); } if ((flags & 16) != 0) { migrated_from_max_id = stream.readInt32(exception); @@ -12273,7 +12222,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { folder_id = stream.readInt32(exception); } if ((flags & 16384) != 0) { - linked_chat_id = stream.readInt32(exception); + linked_chat_id = stream.readInt64(exception); } if ((flags & 32768) != 0) { location = ChannelLocation.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -12291,6 +12240,28 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags & 2097152) != 0) { call = TL_inputGroupCall.TLdeserialize(stream, stream.readInt32(exception), exception); } + if ((flags & 16777216) != 0) { + ttl_period = stream.readInt32(exception); + } + if ((flags & 33554432) != 0) { + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + pending_suggestions.add(stream.readString(exception)); + } + } + if ((flags & 67108864) != 0) { + groupcall_default_join_as = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 134217728) != 0) { + theme_emoticon = stream.readString(exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -12304,7 +12275,7 @@ public void serializeToStream(AbstractSerializedData stream) { flags = can_view_stats ? (flags | 1048576) : (flags &~ 1048576); flags = blocked ? (flags | 4194304) : (flags &~ 4194304); stream.writeInt32(flags); - stream.writeInt32((int) id); + stream.writeInt64(id); stream.writeString(about); if ((flags & 1) != 0) { stream.writeInt32(participants_count); @@ -12326,10 +12297,8 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(unread_count); chat_photo.serializeToStream(stream); notify_settings.serializeToStream(stream); - if (exported_invite != null) { + if ((flags & 8388608) != 0) { exported_invite.serializeToStream(stream); - } else { - new TLRPC.TL_chatInviteEmpty_layer122().serializeToStream(stream); } stream.writeInt32(0x1cb5c415); int count = bot_info.size(); @@ -12338,7 +12307,7 @@ public void serializeToStream(AbstractSerializedData stream) { bot_info.get(a).serializeToStream(stream); } if ((flags & 16) != 0) { - stream.writeInt32((int) migrated_from_chat_id); + stream.writeInt64(migrated_from_chat_id); } if ((flags & 16) != 0) { stream.writeInt32(migrated_from_max_id); @@ -12356,7 +12325,7 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(folder_id); } if ((flags & 16384) != 0) { - stream.writeInt32((int) linked_chat_id); + stream.writeInt64(linked_chat_id); } if ((flags & 32768) != 0) { location.serializeToStream(stream); @@ -12374,11 +12343,28 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags & 2097152) != 0) { call.serializeToStream(stream); } + if ((flags & 16777216) != 0) { + stream.writeInt32(ttl_period); + } + if ((flags & 33554432) != 0) { + stream.writeInt32(0x1cb5c415); + count = pending_suggestions.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeString(pending_suggestions.get(a)); + } + } + if ((flags & 67108864) != 0) { + groupcall_default_join_as.serializeToStream(stream); + } + if ((flags & 134217728) != 0) { + stream.writeString(theme_emoticon); + } } } - public static class TL_channelFull_layer121 extends TL_channelFull { - public static int constructor = 0xf0e6672a; + public static class TL_channelFull_layer131 extends TL_channelFull { + public static int constructor = 0x548c3f93; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -12391,7 +12377,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { has_scheduled = (flags & 524288) != 0; can_view_stats = (flags & 1048576) != 0; blocked = (flags & 4194304) != 0; - id = stream.readInt32(exception); + id = stream.readInt64(exception); about = stream.readString(exception); if ((flags & 1) != 0) { participants_count = stream.readInt32(exception); @@ -12413,9 +12399,8 @@ public void readParams(AbstractSerializedData stream, boolean exception) { unread_count = stream.readInt32(exception); chat_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); - ExportedChatInvite invite = ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); - if (invite instanceof TL_chatInviteExported) { - exported_invite = (TL_chatInviteExported) invite; + if ((flags & 8388608) != 0) { + exported_invite = (TL_chatInviteExported) ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); } int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -12433,7 +12418,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { bot_info.add(object); } if ((flags & 16) != 0) { - migrated_from_chat_id = stream.readInt32(exception); + migrated_from_chat_id = stream.readInt64(exception); } if ((flags & 16) != 0) { migrated_from_max_id = stream.readInt32(exception); @@ -12451,7 +12436,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { folder_id = stream.readInt32(exception); } if ((flags & 16384) != 0) { - linked_chat_id = stream.readInt32(exception); + linked_chat_id = stream.readInt64(exception); } if ((flags & 32768) != 0) { location = ChannelLocation.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -12466,6 +12451,28 @@ public void readParams(AbstractSerializedData stream, boolean exception) { stats_dc = stream.readInt32(exception); } pts = stream.readInt32(exception); + if ((flags & 2097152) != 0) { + call = TL_inputGroupCall.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 16777216) != 0) { + ttl_period = stream.readInt32(exception); + } + if ((flags & 33554432) != 0) { + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + pending_suggestions.add(stream.readString(exception)); + } + } + if ((flags & 67108864) != 0) { + groupcall_default_join_as = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -12479,7 +12486,7 @@ public void serializeToStream(AbstractSerializedData stream) { flags = can_view_stats ? (flags | 1048576) : (flags &~ 1048576); flags = blocked ? (flags | 4194304) : (flags &~ 4194304); stream.writeInt32(flags); - stream.writeInt32((int) id); + stream.writeInt64(id); stream.writeString(about); if ((flags & 1) != 0) { stream.writeInt32(participants_count); @@ -12501,7 +12508,9 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(unread_count); chat_photo.serializeToStream(stream); notify_settings.serializeToStream(stream); - exported_invite.serializeToStream(stream); + if ((flags & 8388608) != 0) { + exported_invite.serializeToStream(stream); + } stream.writeInt32(0x1cb5c415); int count = bot_info.size(); stream.writeInt32(count); @@ -12509,7 +12518,7 @@ public void serializeToStream(AbstractSerializedData stream) { bot_info.get(a).serializeToStream(stream); } if ((flags & 16) != 0) { - stream.writeInt32((int) migrated_from_chat_id); + stream.writeInt64(migrated_from_chat_id); } if ((flags & 16) != 0) { stream.writeInt32(migrated_from_max_id); @@ -12527,7 +12536,7 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(folder_id); } if ((flags & 16384) != 0) { - stream.writeInt32((int) linked_chat_id); + stream.writeInt64(linked_chat_id); } if ((flags & 32768) != 0) { location.serializeToStream(stream); @@ -12542,11 +12551,28 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(stats_dc); } stream.writeInt32(pts); + if ((flags & 2097152) != 0) { + call.serializeToStream(stream); + } + if ((flags & 16777216) != 0) { + stream.writeInt32(ttl_period); + } + if ((flags & 33554432) != 0) { + stream.writeInt32(0x1cb5c415); + count = pending_suggestions.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeString(pending_suggestions.get(a)); + } + } + if ((flags & 67108864) != 0) { + groupcall_default_join_as.serializeToStream(stream); + } } } - public static class TL_channelFull_layer103 extends TL_channelFull { - public static int constructor = 0x10916653; + public static class TL_channelFull_layer122 extends TL_channelFull { + public static int constructor = 0xef3a6acd; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -12555,8 +12581,10 @@ public void readParams(AbstractSerializedData stream, boolean exception) { can_set_username = (flags & 64) != 0; can_set_stickers = (flags & 128) != 0; hidden_prehistory = (flags & 1024) != 0; - can_view_stats = (flags & 4096) != 0; can_set_location = (flags & 65536) != 0; + has_scheduled = (flags & 524288) != 0; + can_view_stats = (flags & 1048576) != 0; + blocked = (flags & 4194304) != 0; id = stream.readInt32(exception); about = stream.readString(exception); if ((flags & 1) != 0) { @@ -12622,7 +12650,19 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags & 32768) != 0) { location = ChannelLocation.TLdeserialize(stream, stream.readInt32(exception), exception); } + if ((flags & 131072) != 0) { + slowmode_seconds = stream.readInt32(exception); + } + if ((flags & 262144) != 0) { + slowmode_next_send_date = stream.readInt32(exception); + } + if ((flags & 4096) != 0) { + stats_dc = stream.readInt32(exception); + } pts = stream.readInt32(exception); + if ((flags & 2097152) != 0) { + call = TL_inputGroupCall.TLdeserialize(stream, stream.readInt32(exception), exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -12631,8 +12671,10 @@ public void serializeToStream(AbstractSerializedData stream) { flags = can_set_username ? (flags | 64) : (flags &~ 64); flags = can_set_stickers ? (flags | 128) : (flags &~ 128); flags = hidden_prehistory ? (flags | 1024) : (flags &~ 1024); - flags = can_view_stats ? (flags | 4096) : (flags &~ 4096); flags = can_set_location ? (flags | 65536) : (flags &~ 65536); + flags = has_scheduled ? (flags | 524288) : (flags &~ 524288); + flags = can_view_stats ? (flags | 1048576) : (flags &~ 1048576); + flags = blocked ? (flags | 4194304) : (flags &~ 4194304); stream.writeInt32(flags); stream.writeInt32((int) id); stream.writeString(about); @@ -12656,7 +12698,11 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(unread_count); chat_photo.serializeToStream(stream); notify_settings.serializeToStream(stream); - exported_invite.serializeToStream(stream); + if (exported_invite != null) { + exported_invite.serializeToStream(stream); + } else { + new TLRPC.TL_chatInviteEmpty_layer122().serializeToStream(stream); + } stream.writeInt32(0x1cb5c415); int count = bot_info.size(); stream.writeInt32(count); @@ -12687,12 +12733,24 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags & 32768) != 0) { location.serializeToStream(stream); } + if ((flags & 131072) != 0) { + stream.writeInt32(slowmode_seconds); + } + if ((flags & 262144) != 0) { + stream.writeInt32(slowmode_next_send_date); + } + if ((flags & 4096) != 0) { + stream.writeInt32(stats_dc); + } stream.writeInt32(pts); + if ((flags & 2097152) != 0) { + call.serializeToStream(stream); + } } } - public static class TL_channelFull_layer101 extends TL_channelFull { - public static int constructor = 0x9882e516; + public static class TL_channelFull_layer121 extends TL_channelFull { + public static int constructor = 0xf0e6672a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -12701,7 +12759,10 @@ public void readParams(AbstractSerializedData stream, boolean exception) { can_set_username = (flags & 64) != 0; can_set_stickers = (flags & 128) != 0; hidden_prehistory = (flags & 1024) != 0; - can_view_stats = (flags & 4096) != 0; + can_set_location = (flags & 65536) != 0; + has_scheduled = (flags & 524288) != 0; + can_view_stats = (flags & 1048576) != 0; + blocked = (flags & 4194304) != 0; id = stream.readInt32(exception); about = stream.readString(exception); if ((flags & 1) != 0) { @@ -12761,9 +12822,21 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags & 2048) != 0) { folder_id = stream.readInt32(exception); } - if ((flags & 8192) != 0) { + if ((flags & 16384) != 0) { linked_chat_id = stream.readInt32(exception); } + if ((flags & 32768) != 0) { + location = ChannelLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 131072) != 0) { + slowmode_seconds = stream.readInt32(exception); + } + if ((flags & 262144) != 0) { + slowmode_next_send_date = stream.readInt32(exception); + } + if ((flags & 4096) != 0) { + stats_dc = stream.readInt32(exception); + } pts = stream.readInt32(exception); } @@ -12773,7 +12846,10 @@ public void serializeToStream(AbstractSerializedData stream) { flags = can_set_username ? (flags | 64) : (flags &~ 64); flags = can_set_stickers ? (flags | 128) : (flags &~ 128); flags = hidden_prehistory ? (flags | 1024) : (flags &~ 1024); - flags = can_view_stats ? (flags | 4096) : (flags &~ 4096); + flags = can_set_location ? (flags | 65536) : (flags &~ 65536); + flags = has_scheduled ? (flags | 524288) : (flags &~ 524288); + flags = can_view_stats ? (flags | 1048576) : (flags &~ 1048576); + flags = blocked ? (flags | 4194304) : (flags &~ 4194304); stream.writeInt32(flags); stream.writeInt32((int) id); stream.writeString(about); @@ -12822,15 +12898,27 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags & 2048) != 0) { stream.writeInt32(folder_id); } - if ((flags & 8192) != 0) { + if ((flags & 16384) != 0) { stream.writeInt32((int) linked_chat_id); } + if ((flags & 32768) != 0) { + location.serializeToStream(stream); + } + if ((flags & 131072) != 0) { + stream.writeInt32(slowmode_seconds); + } + if ((flags & 262144) != 0) { + stream.writeInt32(slowmode_next_send_date); + } + if ((flags & 4096) != 0) { + stream.writeInt32(stats_dc); + } stream.writeInt32(pts); } } - public static class TL_channelFull_layer99 extends TL_channelFull { - public static int constructor = 0x3648977; + public static class TL_channelFull_layer103 extends TL_channelFull { + public static int constructor = 0x10916653; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -12840,6 +12928,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { can_set_stickers = (flags & 128) != 0; hidden_prehistory = (flags & 1024) != 0; can_view_stats = (flags & 4096) != 0; + can_set_location = (flags & 65536) != 0; id = stream.readInt32(exception); about = stream.readString(exception); if ((flags & 1) != 0) { @@ -12899,6 +12988,12 @@ public void readParams(AbstractSerializedData stream, boolean exception) { if ((flags & 2048) != 0) { folder_id = stream.readInt32(exception); } + if ((flags & 16384) != 0) { + linked_chat_id = stream.readInt32(exception); + } + if ((flags & 32768) != 0) { + location = ChannelLocation.TLdeserialize(stream, stream.readInt32(exception), exception); + } pts = stream.readInt32(exception); } @@ -12909,6 +13004,7 @@ public void serializeToStream(AbstractSerializedData stream) { flags = can_set_stickers ? (flags | 128) : (flags &~ 128); flags = hidden_prehistory ? (flags | 1024) : (flags &~ 1024); flags = can_view_stats ? (flags | 4096) : (flags &~ 4096); + flags = can_set_location ? (flags | 65536) : (flags &~ 65536); stream.writeInt32(flags); stream.writeInt32((int) id); stream.writeString(about); @@ -12957,12 +13053,288 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags & 2048) != 0) { stream.writeInt32(folder_id); } + if ((flags & 16384) != 0) { + stream.writeInt32((int) linked_chat_id); + } + if ((flags & 32768) != 0) { + location.serializeToStream(stream); + } stream.writeInt32(pts); } } - public static class TL_channelFull_layer98 extends TL_channelFull { - public static int constructor = 0x1c87a71a; + public static class TL_channelFull_layer101 extends TL_channelFull { + public static int constructor = 0x9882e516; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + can_view_participants = (flags & 8) != 0; + can_set_username = (flags & 64) != 0; + can_set_stickers = (flags & 128) != 0; + hidden_prehistory = (flags & 1024) != 0; + can_view_stats = (flags & 4096) != 0; + id = stream.readInt32(exception); + about = stream.readString(exception); + if ((flags & 1) != 0) { + participants_count = stream.readInt32(exception); + } + if ((flags & 2) != 0) { + admins_count = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + kicked_count = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + banned_count = stream.readInt32(exception); + } + if ((flags & 8192) != 0) { + online_count = stream.readInt32(exception); + } + read_inbox_max_id = stream.readInt32(exception); + read_outbox_max_id = stream.readInt32(exception); + unread_count = stream.readInt32(exception); + chat_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); + ExportedChatInvite invite = ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); + if (invite instanceof TL_chatInviteExported) { + exported_invite = (TL_chatInviteExported) invite; + } + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + BotInfo object = BotInfo.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + bot_info.add(object); + } + if ((flags & 16) != 0) { + migrated_from_chat_id = stream.readInt32(exception); + } + if ((flags & 16) != 0) { + migrated_from_max_id = stream.readInt32(exception); + } + if ((flags & 32) != 0) { + pinned_msg_id = stream.readInt32(exception); + } + if ((flags & 256) != 0) { + stickerset = StickerSet.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 512) != 0) { + available_min_id = stream.readInt32(exception); + } + if ((flags & 2048) != 0) { + folder_id = stream.readInt32(exception); + } + if ((flags & 8192) != 0) { + linked_chat_id = stream.readInt32(exception); + } + pts = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = can_view_participants ? (flags | 8) : (flags &~ 8); + flags = can_set_username ? (flags | 64) : (flags &~ 64); + flags = can_set_stickers ? (flags | 128) : (flags &~ 128); + flags = hidden_prehistory ? (flags | 1024) : (flags &~ 1024); + flags = can_view_stats ? (flags | 4096) : (flags &~ 4096); + stream.writeInt32(flags); + stream.writeInt32((int) id); + stream.writeString(about); + if ((flags & 1) != 0) { + stream.writeInt32(participants_count); + } + if ((flags & 2) != 0) { + stream.writeInt32(admins_count); + } + if ((flags & 4) != 0) { + stream.writeInt32(kicked_count); + } + if ((flags & 4) != 0) { + stream.writeInt32(banned_count); + } + if ((flags & 8192) != 0) { + stream.writeInt32(online_count); + } + stream.writeInt32(read_inbox_max_id); + stream.writeInt32(read_outbox_max_id); + stream.writeInt32(unread_count); + chat_photo.serializeToStream(stream); + notify_settings.serializeToStream(stream); + exported_invite.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = bot_info.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + bot_info.get(a).serializeToStream(stream); + } + if ((flags & 16) != 0) { + stream.writeInt32((int) migrated_from_chat_id); + } + if ((flags & 16) != 0) { + stream.writeInt32(migrated_from_max_id); + } + if ((flags & 32) != 0) { + stream.writeInt32(pinned_msg_id); + } + if ((flags & 256) != 0) { + stickerset.serializeToStream(stream); + } + if ((flags & 512) != 0) { + stream.writeInt32(available_min_id); + } + if ((flags & 2048) != 0) { + stream.writeInt32(folder_id); + } + if ((flags & 8192) != 0) { + stream.writeInt32((int) linked_chat_id); + } + stream.writeInt32(pts); + } + } + + public static class TL_channelFull_layer99 extends TL_channelFull { + public static int constructor = 0x3648977; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + can_view_participants = (flags & 8) != 0; + can_set_username = (flags & 64) != 0; + can_set_stickers = (flags & 128) != 0; + hidden_prehistory = (flags & 1024) != 0; + can_view_stats = (flags & 4096) != 0; + id = stream.readInt32(exception); + about = stream.readString(exception); + if ((flags & 1) != 0) { + participants_count = stream.readInt32(exception); + } + if ((flags & 2) != 0) { + admins_count = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + kicked_count = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + banned_count = stream.readInt32(exception); + } + if ((flags & 8192) != 0) { + online_count = stream.readInt32(exception); + } + read_inbox_max_id = stream.readInt32(exception); + read_outbox_max_id = stream.readInt32(exception); + unread_count = stream.readInt32(exception); + chat_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + notify_settings = PeerNotifySettings.TLdeserialize(stream, stream.readInt32(exception), exception); + ExportedChatInvite invite = ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); + if (invite instanceof TL_chatInviteExported) { + exported_invite = (TL_chatInviteExported) invite; + } + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + BotInfo object = BotInfo.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + bot_info.add(object); + } + if ((flags & 16) != 0) { + migrated_from_chat_id = stream.readInt32(exception); + } + if ((flags & 16) != 0) { + migrated_from_max_id = stream.readInt32(exception); + } + if ((flags & 32) != 0) { + pinned_msg_id = stream.readInt32(exception); + } + if ((flags & 256) != 0) { + stickerset = StickerSet.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 512) != 0) { + available_min_id = stream.readInt32(exception); + } + if ((flags & 2048) != 0) { + folder_id = stream.readInt32(exception); + } + pts = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = can_view_participants ? (flags | 8) : (flags &~ 8); + flags = can_set_username ? (flags | 64) : (flags &~ 64); + flags = can_set_stickers ? (flags | 128) : (flags &~ 128); + flags = hidden_prehistory ? (flags | 1024) : (flags &~ 1024); + flags = can_view_stats ? (flags | 4096) : (flags &~ 4096); + stream.writeInt32(flags); + stream.writeInt32((int) id); + stream.writeString(about); + if ((flags & 1) != 0) { + stream.writeInt32(participants_count); + } + if ((flags & 2) != 0) { + stream.writeInt32(admins_count); + } + if ((flags & 4) != 0) { + stream.writeInt32(kicked_count); + } + if ((flags & 4) != 0) { + stream.writeInt32(banned_count); + } + if ((flags & 8192) != 0) { + stream.writeInt32(online_count); + } + stream.writeInt32(read_inbox_max_id); + stream.writeInt32(read_outbox_max_id); + stream.writeInt32(unread_count); + chat_photo.serializeToStream(stream); + notify_settings.serializeToStream(stream); + exported_invite.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = bot_info.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + bot_info.get(a).serializeToStream(stream); + } + if ((flags & 16) != 0) { + stream.writeInt32((int) migrated_from_chat_id); + } + if ((flags & 16) != 0) { + stream.writeInt32(migrated_from_max_id); + } + if ((flags & 32) != 0) { + stream.writeInt32(pinned_msg_id); + } + if ((flags & 256) != 0) { + stickerset.serializeToStream(stream); + } + if ((flags & 512) != 0) { + stream.writeInt32(available_min_id); + } + if ((flags & 2048) != 0) { + stream.writeInt32(folder_id); + } + stream.writeInt32(pts); + } + } + + public static class TL_channelFull_layer98 extends TL_channelFull { + public static int constructor = 0x1c87a71a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -17628,74 +18000,6 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static abstract class account_ChatThemes extends TLObject { - - public static account_ChatThemes TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - account_ChatThemes result = null; - switch (constructor) { - case 0xe011e1c4: - result = new TL_account_chatThemesNotModified(); - break; - case 0xfe4cbebd: - result = new TL_account_chatThemes(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in account_ChatThemes", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_account_chatThemesNotModified extends account_ChatThemes { - public static int constructor = 0xe011e1c4; - - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_account_chatThemes extends account_ChatThemes { - public static int constructor = 0xfe4cbebd; - - public int hash; - public ArrayList themes = new ArrayList<>(); - - public void readParams(AbstractSerializedData stream, boolean exception) { - hash = stream.readInt32(exception); - int magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - TL_chatTheme object = TL_chatTheme.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - themes.add(object); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(hash); - stream.writeInt32(0x1cb5c415); - int count = themes.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - themes.get(a).serializeToStream(stream); - } - } - } - public static class TL_auth_passwordRecovery extends TLObject { public static int constructor = 0x137948a5; @@ -20163,6 +20467,12 @@ public static MessageAction TLdeserialize(AbstractSerializedData stream, int con case 0x4792929b: result = new TL_messageActionScreenshotTaken(); break; + case 0x1baa035: + result = new TL_messageActionPhoneNumberRequest(); + break; + case 0xebbca3cb: + result = new TL_messageActionChatJoinedByRequest(); + break; case 0x9fbab604: result = new TL_messageActionHistoryClear(); break; @@ -20556,6 +20866,24 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_messageActionPhoneNumberRequest extends MessageAction { + public static int constructor = 0x1baa035; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_messageActionChatJoinedByRequest extends MessageAction { + public static int constructor = 0xebbca3cb; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class TL_messageActionChatMigrateTo extends MessageAction { public static int constructor = 0xe1037f92; @@ -21418,7 +21746,7 @@ public static class TL_account_themes extends account_Themes { public static int constructor = 0x9a3d8c6d; public long hash; - public ArrayList themes = new ArrayList<>(); + public ArrayList themes = new ArrayList<>(); public void readParams(AbstractSerializedData stream, boolean exception) { hash = stream.readInt64(exception); @@ -21431,7 +21759,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - Theme object = Theme.TLdeserialize(stream, stream.readInt32(exception), exception); + TL_theme object = Theme.TLdeserialize(stream, stream.readInt32(exception), exception); if (object == null) { return; } @@ -26167,6 +26495,9 @@ public static Update TLdeserialize(AbstractSerializedData stream, int constructo case 0x3504914f: result = new TL_updateDialogFilters(); break; + case 0x7063c3db: + result = new TL_updatePendingJoinRequests(); + break; case 0x8e5e9873: result = new TL_updateDcOptions(); break; @@ -27895,6 +28226,42 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_updatePendingJoinRequests extends Update { + public static int constructor = 0x7063c3db; + + public Peer peer; + public int requests_pending; + public ArrayList recent_requesters = new ArrayList<>(); + + public void readParams(AbstractSerializedData stream, boolean exception) { + peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + requests_pending = stream.readInt32(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + recent_requesters.add(stream.readInt64(exception)); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(requests_pending); + stream.writeInt32(0x1cb5c415); + int count = recent_requesters.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt64(recent_requesters.get(a)); + } + } + } + public static class TL_updateDcOptions extends Update { public static int constructor = 0x8e5e9873; @@ -31787,8 +32154,8 @@ public void serializeToStream(AbstractSerializedData stream) { public static abstract class Theme extends TLObject { - public static Theme TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - Theme result = null; + public static TL_theme TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + TL_theme result = null; switch (constructor) { case 0x28f1114: result = new TL_theme_layer131(); @@ -31799,9 +32166,12 @@ public static Theme TLdeserialize(AbstractSerializedData stream, int constructor case 0x483d270c: result = new TL_themeDocumentNotModified_layer106(); break; - case 0xe802b8dc: + case 0xa00e67d6: result = new TL_theme(); break; + case 0xe802b8dc: + result = new TL_theme_layer133(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in Theme", constructor)); @@ -31813,9 +32183,55 @@ public static Theme TLdeserialize(AbstractSerializedData stream, int constructor } } - public static class TL_theme extends Theme { + public static class TL_theme_layer133 extends TL_theme { public static int constructor = 0xe802b8dc; + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + creator = (flags & 1) != 0; + isDefault = (flags & 2) != 0; + for_chat = (flags & 32) != 0; + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + slug = stream.readString(exception); + title = stream.readString(exception); + if ((flags & 4) != 0) { + document = Document.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 8) != 0) { + ThemeSettings settings = ThemeSettings.TLdeserialize(stream, stream.readInt32(exception), exception); + this.settings.add(settings); + } + if ((flags & 16) != 0) { + installs_count = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = creator ? (flags | 1) : (flags &~ 1); + flags = isDefault ? (flags | 2) : (flags &~ 2); + flags = for_chat ? (flags | 32) : (flags &~ 32); + stream.writeInt32(flags); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeString(slug); + stream.writeString(title); + if ((flags & 4) != 0) { + document.serializeToStream(stream); + } + if ((flags & 8) != 0) { + settings.get(0).serializeToStream(stream); + } + if ((flags & 16) != 0) { + stream.writeInt32(installs_count); + } + } + } + + public static class TL_theme extends Theme { + public static int constructor = 0xa00e67d6; + public int flags; public boolean creator; public boolean isDefault; @@ -31825,7 +32241,8 @@ public static class TL_theme extends Theme { public String slug; public String title; public Document document; - public ThemeSettings settings; + public ArrayList settings = new ArrayList<>(); + public String emoticon; public int installs_count; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -31841,7 +32258,24 @@ public void readParams(AbstractSerializedData stream, boolean exception) { document = Document.TLdeserialize(stream, stream.readInt32(exception), exception); } if ((flags & 8) != 0) { - settings = ThemeSettings.TLdeserialize(stream, stream.readInt32(exception), exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TL_themeSettings object = TL_themeSettings.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + settings.add(object); + } + } + if ((flags & 64) != 0) { + emoticon = stream.readString(exception); } if ((flags & 16) != 0) { installs_count = stream.readInt32(exception); @@ -31862,7 +32296,15 @@ public void serializeToStream(AbstractSerializedData stream) { document.serializeToStream(stream); } if ((flags & 8) != 0) { - settings.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = settings.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + settings.get(a).serializeToStream(stream); + } + } + if ((flags & 64) != 0) { + stream.writeString(emoticon); } if ((flags & 16) != 0) { stream.writeInt32(installs_count); @@ -31886,7 +32328,7 @@ public void readParams(AbstractSerializedData stream, boolean exception) { document = Document.TLdeserialize(stream, stream.readInt32(exception), exception); } if ((flags & 8) != 0) { - settings = ThemeSettings.TLdeserialize(stream, stream.readInt32(exception), exception); + settings.add(ThemeSettings.TLdeserialize(stream, stream.readInt32(exception), exception)); } installs_count = stream.readInt32(exception); } @@ -31904,7 +32346,7 @@ public void serializeToStream(AbstractSerializedData stream) { document.serializeToStream(stream); } if ((flags & 8) != 0) { - settings.serializeToStream(stream); + settings.get(0).serializeToStream(stream); } stream.writeInt32(installs_count); } @@ -31944,7 +32386,7 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class TL_themeDocumentNotModified_layer106 extends Theme { + public static class TL_themeDocumentNotModified_layer106 extends TL_theme { public static int constructor = 0x483d270c; @@ -32234,11 +32676,12 @@ public static ChannelMessagesFilter TLdeserialize(AbstractSerializedData stream, } public static class TL_sponsoredMessage extends TLObject { - public static int constructor = 0x2a3c381f; + public static int constructor = 0xd151e19a; public int flags; public byte[] random_id; public Peer from_id; + public int channel_post; public String start_param; public String message; public ArrayList entities = new ArrayList<>(); @@ -32260,6 +32703,9 @@ public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); random_id = stream.readByteArray(exception); from_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 4) != 0) { + channel_post = stream.readInt32(exception); + } if ((flags & 1) != 0) { start_param = stream.readString(exception); } @@ -32288,6 +32734,9 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(flags); stream.writeByteArray(random_id); from_id.serializeToStream(stream); + if ((flags & 4) != 0) { + stream.writeInt32(channel_post); + } if ((flags & 1) != 0) { stream.writeString(start_param); } @@ -32666,6 +33115,127 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_searchResultPosition extends TLObject { + public static int constructor = 0x7f648b67; + + public int msg_id; + public int date; + public int offset; + + public static TL_searchResultPosition TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_searchResultPosition.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_searchResultPosition", constructor)); + } else { + return null; + } + } + TL_searchResultPosition result = new TL_searchResultPosition(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + msg_id = stream.readInt32(exception); + date = stream.readInt32(exception); + offset = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(msg_id); + stream.writeInt32(date); + stream.writeInt32(offset); + } + } + + public static class TL_messages_searchResultsPositions extends TLObject { + public static int constructor = 0x53b22baf; + + public int count; + public ArrayList positions = new ArrayList<>(); + + public static TL_messages_searchResultsPositions TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_messages_searchResultsPositions.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_messages_searchResultsPositions", constructor)); + } else { + return null; + } + } + TL_messages_searchResultsPositions result = new TL_messages_searchResultsPositions(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + count = stream.readInt32(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TL_searchResultPosition object = TL_searchResultPosition.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + positions.add(object); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(count); + stream.writeInt32(0x1cb5c415); + int count = positions.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + positions.get(a).serializeToStream(stream); + } + } + } + + public static class TL_searchResultsCalendarPeriod extends TLObject { + public static int constructor = 0xc9b0539f; + + public int date; + public int min_msg_id; + public int max_msg_id; + public int count; + + public static TL_searchResultsCalendarPeriod TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_searchResultsCalendarPeriod.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_searchResultsCalendarPeriod", constructor)); + } else { + return null; + } + } + TL_searchResultsCalendarPeriod result = new TL_searchResultsCalendarPeriod(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + date = stream.readInt32(exception); + min_msg_id = stream.readInt32(exception); + max_msg_id = stream.readInt32(exception); + count = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(date); + stream.writeInt32(min_msg_id); + stream.writeInt32(max_msg_id); + stream.writeInt32(count); + } + } + public static class TL_inputSingleMedia extends TLObject { public static int constructor = 0x1cc6e91f; @@ -33047,6 +33617,8 @@ public static abstract class ChannelParticipant extends TLObject { public TL_chatAdminRights admin_rights; public TL_chatBannedRights banned_rights; public String rank; + public boolean via_invite; + public long user_id; public static ChannelParticipant TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { ChannelParticipant result = null; @@ -33087,9 +33659,12 @@ public static ChannelParticipant TLdeserialize(AbstractSerializedData stream, in case 0xa82fa898: result = new TL_channelParticipantAdmin_layer92(); break; - case 0x28a8bc67: + case 0x35a8bfa7: result = new TL_channelParticipantSelf(); break; + case 0x28a8bc67: + result = new TL_channelParticipantSelf_layer133(); + break; case 0x50a1dfd6: result = new TL_channelParticipantBanned_layer131(); break; @@ -33143,6 +33718,27 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_channelParticipantSelf extends ChannelParticipant { + public static int constructor = 0x35a8bfa7; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + via_invite = (flags & 1) != 0; + user_id = stream.readInt64(exception); + inviter_id = stream.readInt64(exception); + date = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = via_invite ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + stream.writeInt64(user_id); + stream.writeInt64(inviter_id); + stream.writeInt32(date); + } + } + + public static class TL_channelParticipantSelf_layer133 extends ChannelParticipant { public static int constructor = 0x28a8bc67; @@ -35280,6 +35876,9 @@ public static ChannelAdminLogEventAction TLdeserialize(AbstractSerializedData st case 0x5f5c95f1: result = new TL_channelAdminLogEventActionTogglePreHistoryHidden(); break; + case 0xafb6144a: + result = new TL_channelAdminLogEventActionParticipantJoinByRequest(); + break; case 0xe9e82c18: result = new TL_channelAdminLogEventActionUpdatePinned(); break; @@ -35675,6 +36274,24 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_channelAdminLogEventActionParticipantJoinByRequest extends ChannelAdminLogEventAction { + public static int constructor = 0xafb6144a; + + public ExportedChatInvite invite; + public long approved_by; + + public void readParams(AbstractSerializedData stream, boolean exception) { + invite = ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); + approved_by = stream.readInt64(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + invite.serializeToStream(stream); + stream.writeInt64(approved_by); + } + } + public static class TL_channelAdminLogEventActionUpdatePinned extends ChannelAdminLogEventAction { public static int constructor = 0xe9e82c18; @@ -39418,12 +40035,15 @@ public void serializeToStream(AbstractSerializedData stream) { public static abstract class ExportedChatInvite extends TLObject { - public static ExportedChatInvite TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - ExportedChatInvite result = null; + public static TL_chatInviteExported TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + TL_chatInviteExported result = null; switch (constructor) { - case 0xb18105e8: + case 0xab4a819: result = new TL_chatInviteExported(); break; + case 0xb18105e8: + result = new TL_chatInviteExported_layer133(); + break; case 0x69df3769: result = new TL_chatInviteEmpty_layer122(); break; @@ -39445,11 +40065,12 @@ public static ExportedChatInvite TLdeserialize(AbstractSerializedData stream, in } public static class TL_chatInviteExported extends ExportedChatInvite { - public static int constructor = 0xb18105e8; + public static int constructor = 0xab4a819; public int flags; public boolean revoked; public boolean permanent; + public boolean request_needed; public String link; public long admin_id; public int date; @@ -39457,9 +40078,72 @@ public static class TL_chatInviteExported extends ExportedChatInvite { public int expire_date; public int usage_limit; public int usage; + public int requested; + public String title; public ArrayList importers; //custom public boolean expired; //custom + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + revoked = (flags & 1) != 0; + permanent = (flags & 32) != 0; + request_needed = (flags & 64) != 0; + link = stream.readString(exception); + admin_id = stream.readInt64(exception); + date = stream.readInt32(exception); + if ((flags & 16) != 0) { + start_date = stream.readInt32(exception); + } + if ((flags & 2) != 0) { + expire_date = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + usage_limit = stream.readInt32(exception); + } + if ((flags & 8) != 0) { + usage = stream.readInt32(exception); + } + if ((flags & 128) != 0) { + requested = stream.readInt32(exception); + } + if ((flags & 256) != 0) { + title = stream.readString(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = revoked ? (flags | 1) : (flags &~ 1); + flags = permanent ? (flags | 32) : (flags &~ 32); + flags = request_needed ? (flags | 64) : (flags &~ 64); + stream.writeInt32(flags); + stream.writeString(link); + stream.writeInt64(admin_id); + stream.writeInt32(date); + if ((flags & 16) != 0) { + stream.writeInt32(start_date); + } + if ((flags & 2) != 0) { + stream.writeInt32(expire_date); + } + if ((flags & 4) != 0) { + stream.writeInt32(usage_limit); + } + if ((flags & 8) != 0) { + stream.writeInt32(usage); + } + if ((flags & 128) != 0) { + stream.writeInt32(requested); + } + if ((flags & 256) != 0) { + stream.writeString(title); + } + } + } + + public static class TL_chatInviteExported_layer133 extends TL_chatInviteExported { + public static int constructor = 0xb18105e8; + public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); revoked = (flags & 1) != 0; @@ -39504,7 +40188,7 @@ public void serializeToStream(AbstractSerializedData stream) { } } - public static class TL_chatInviteEmpty_layer122 extends ExportedChatInvite { + public static class TL_chatInviteEmpty_layer122 extends TL_chatInviteExported { public static int constructor = 0x69df3769; @@ -43034,17 +43718,17 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_account_getChatThemes extends TLObject { - public static int constructor = 0xd6d71d7b; + public static int constructor = 0xd638de89; - public int hash; + public long hash; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return account_ChatThemes.TLdeserialize(stream, constructor, exception); + return account_Themes.TLdeserialize(stream, constructor, exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - stream.writeInt32(hash); + stream.writeInt64(hash); } } @@ -43659,13 +44343,15 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_messages_deleteHistory extends TLObject { - public static int constructor = 0x1c015b09; + public static int constructor = 0xb08f922a; public int flags; public boolean just_clear; public boolean revoke; public InputPeer peer; public int max_id; + public int min_date; + public int max_date; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { return TL_messages_affectedHistory.TLdeserialize(stream, constructor, exception); @@ -43678,6 +44364,12 @@ public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(flags); peer.serializeToStream(stream); stream.writeInt32(max_id); + if ((flags & 4) != 0) { + stream.writeInt32(min_date); + } + if ((flags & 8) != 0) { + stream.writeInt32(max_date); + } } } @@ -44271,6 +44963,27 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_messages_getSearchResultsCalendar extends TLObject { + public static int constructor = 0x49f0bde9; + + public InputPeer peer; + public MessagesFilter filter; + public int offset_id; + public int offset_date; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_messages_searchResultsCalendar.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + filter.serializeToStream(stream); + stream.writeInt32(offset_id); + stream.writeInt32(offset_date); + } + } + public static class TL_updates_getState extends TLObject { public static int constructor = 0xedd4882a; @@ -45904,13 +46617,15 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_messages_exportChatInvite extends TLObject { - public static int constructor = 0x14b9bcd7; + public static int constructor = 0xa02ce5d5; public int flags; public boolean legacy_revoke_permanent; + public boolean request_needed; public InputPeer peer; public int expire_date; public int usage_limit; + public String title; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { return ExportedChatInvite.TLdeserialize(stream, constructor, exception); @@ -45919,6 +46634,7 @@ public TLObject deserializeResponse(AbstractSerializedData stream, int construct public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); flags = legacy_revoke_permanent ? (flags | 4) : (flags &~ 4); + flags = request_needed ? (flags | 8) : (flags &~ 8); stream.writeInt32(flags); peer.serializeToStream(stream); if ((flags & 1) != 0) { @@ -45927,6 +46643,9 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags & 2) != 0) { stream.writeInt32(usage_limit); } + if ((flags & 16) != 0) { + stream.writeString(title); + } } } @@ -47350,6 +48069,141 @@ public void serializeToStream(AbstractSerializedData stream) { } } + public static class TL_messages_searchResultsCalendar extends TLObject { + public static int constructor = 0x147ee23c; + + public int flags; + public boolean inexact; + public int count; + public int min_date; + public int min_msg_id; + public int offset_id_offset; + public ArrayList periods = new ArrayList<>(); + public ArrayList messages = new ArrayList<>(); + public ArrayList chats = new ArrayList<>(); + public ArrayList users = new ArrayList<>(); + + public static TL_messages_searchResultsCalendar TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_messages_searchResultsCalendar.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_messages_searchResultsCalendar", constructor)); + } else { + return null; + } + } + TL_messages_searchResultsCalendar result = new TL_messages_searchResultsCalendar(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + inexact = (flags & 1) != 0; + count = stream.readInt32(exception); + min_date = stream.readInt32(exception); + min_msg_id = stream.readInt32(exception); + if ((flags & 2) != 0) { + offset_id_offset = stream.readInt32(exception); + } + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TL_searchResultsCalendarPeriod object = TL_searchResultsCalendarPeriod.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + periods.add(object); + } + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + Message object = Message.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + messages.add(object); + } + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); + } + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + users.add(object); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = inexact ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + stream.writeInt32(count); + stream.writeInt32(min_date); + stream.writeInt32(min_msg_id); + if ((flags & 2) != 0) { + stream.writeInt32(offset_id_offset); + } + stream.writeInt32(0x1cb5c415); + int count = periods.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + periods.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = messages.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + messages.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = chats.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + chats.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); + } + } + } + public static class TL_messages_getMessageReactionsList extends TLObject { public static int constructor = 0x15b1376a; @@ -47643,7 +48497,7 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_messages_editExportedChatInvite extends TLObject { - public static int constructor = 0x2e4ffbe; + public static int constructor = 0xbdca2f75; public int flags; public boolean revoked; @@ -47651,6 +48505,8 @@ public static class TL_messages_editExportedChatInvite extends TLObject { public String link; public int expire_date; public int usage_limit; + public boolean request_needed; + public String title; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { return messages_ExportedChatInvite.TLdeserialize(stream, constructor, exception); @@ -47668,6 +48524,12 @@ public void serializeToStream(AbstractSerializedData stream) { if ((flags & 2) != 0) { stream.writeInt32(usage_limit); } + if ((flags & 8) != 0) { + stream.writeBool(request_needed); + } + if ((flags & 16) != 0) { + stream.writeString(title); + } } } @@ -47721,10 +48583,13 @@ public void serializeToStream(AbstractSerializedData stream) { } public static class TL_messages_getChatInviteImporters extends TLObject { - public static int constructor = 0x26fb7289; + public static int constructor = 0xdf04dd4e; + public int flags; + public boolean requested; public InputPeer peer; public String link; + public String q; public int offset_date; public InputUser offset_user; public int limit; @@ -47735,14 +48600,42 @@ public TLObject deserializeResponse(AbstractSerializedData stream, int construct public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + flags = requested ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); peer.serializeToStream(stream); - stream.writeString(link); + if ((flags & 2) != 0) { + stream.writeString(link); + } + if ((flags & 4) != 0) { + stream.writeString(q); + } stream.writeInt32(offset_date); offset_user.serializeToStream(stream); stream.writeInt32(limit); } } + public static class TL_messages_hideChatJoinRequest extends TLObject { + public static int constructor = 0x7fe7e815; + + public int flags; + public boolean approved; + public InputPeer peer; + public InputUser user_id; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = approved ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + peer.serializeToStream(stream); + user_id.serializeToStream(stream); + } + } + public static class TL_messages_setHistoryTTL extends TLObject { public static int constructor = 0xb80e5fe4; @@ -50850,7 +51743,6 @@ public void serializeToStream(AbstractSerializedData stream) { public static class TL_messageEmpty extends Message { public static int constructor = 0x90a6ca84; - public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); id = stream.readInt32(exception); @@ -54313,6 +55205,27 @@ public void freeResources() { } } + public static class TL_messages_getSearchResultsPositions extends TLObject { + public static int constructor = 0x6e9583a3; + + public InputPeer peer; + public MessagesFilter filter; + public int offset_id; + public int limit; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_messages_searchResultsPositions.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + filter.serializeToStream(stream); + stream.writeInt32(offset_id); + stream.writeInt32(limit); + } + } + //functions public static class Vector extends TLObject { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java index c153557e183..fefac3a2176 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java @@ -50,6 +50,7 @@ import android.widget.LinearLayout; import android.widget.TextView; +import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; import org.telegram.messenger.AndroidUtilities; @@ -165,6 +166,7 @@ public interface ActionBarMenuItemDelegate { private int notificationIndex = -1; private float transitionOffset; + private View showSubMenuFrom; private final Theme.ResourcesProvider resourcesProvider; public ActionBarMenuItem(Context context, ActionBarMenu menu, int backgroundColor, int iconColor) { @@ -584,7 +586,7 @@ public void setMenuYOffset(int offset) { yOffset = offset; } - public void toggleSubMenu() { + public void toggleSubMenu(View topView, View fromView) { if (popupLayout == null || parentMenu != null && parentMenu.isActionMode && parentMenu.parentActionBar != null && !parentMenu.parentActionBar.isActionModeShowed()) { return; } @@ -596,48 +598,76 @@ public void toggleSubMenu() { popupWindow.dismiss(); return; } + + showSubMenuFrom = fromView; + if (subMenuDelegate != null) { subMenuDelegate.onShowSubMenu(); } - if (popupWindow == null) { - popupWindow = new ActionBarPopupWindow(popupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); - if (animationEnabled && Build.VERSION.SDK_INT >= 19) { - popupWindow.setAnimationStyle(0); - } else { - popupWindow.setAnimationStyle(R.style.PopupAnimation); - } - if (!animationEnabled) { - popupWindow.setAnimationEnabled(animationEnabled); - } - popupWindow.setOutsideTouchable(true); - popupWindow.setClippingEnabled(true); - if (layoutInScreen) { - popupWindow.setLayoutInScreen(true); - } - popupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); - popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); - popupWindow.getContentView().setFocusableInTouchMode(true); - popupWindow.getContentView().setOnKeyListener((v, keyCode, event) -> { - if (keyCode == KeyEvent.KEYCODE_MENU && event.getRepeatCount() == 0 && event.getAction() == KeyEvent.ACTION_UP && popupWindow != null && popupWindow.isShowing()) { - popupWindow.dismiss(); - return true; - } - return false; - }); - popupWindow.setOnDismissListener(() -> { - onDismiss(); - if (subMenuDelegate != null) { - subMenuDelegate.onHideSubMenu(); + if (popupLayout.getParent() != null) { + ((ViewGroup) popupLayout.getParent()).removeView(popupLayout); + } + ViewGroup container = popupLayout; + if (topView != null) { + LinearLayout linearLayout = new LinearLayout(getContext()) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + popupLayout.measure(widthMeasureSpec, heightMeasureSpec); + topView.getLayoutParams().width = popupLayout.getMeasuredWidth() - AndroidUtilities.dp(16); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); } - }); + }; + linearLayout.setOrientation(LinearLayout.VERTICAL); + FrameLayout frameLayout = new FrameLayout(getContext()); + frameLayout.setAlpha(0f); + frameLayout.animate().alpha(1f).setDuration(100).start(); + Drawable drawable = ContextCompat.getDrawable(getContext(), R.drawable.popup_fixed_alert2).mutate(); + drawable.setColorFilter(new PorterDuffColorFilter(popupLayout.getBackgroundColor(), PorterDuff.Mode.MULTIPLY)); + + frameLayout.setBackground(drawable); + frameLayout.addView(topView); + linearLayout.addView(frameLayout, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + linearLayout.addView(popupLayout, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, 0, -AndroidUtilities.dp(4), 0, 0)); + container = linearLayout; + } + popupWindow = new ActionBarPopupWindow(container, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); + if (animationEnabled && Build.VERSION.SDK_INT >= 19) { + popupWindow.setAnimationStyle(0); + } else { + popupWindow.setAnimationStyle(R.style.PopupAnimation); } - if (measurePopup) { - popupLayout.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x - AndroidUtilities.dp(40), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.y, MeasureSpec.AT_MOST)); - measurePopup = false; + if (!animationEnabled) { + popupWindow.setAnimationEnabled(animationEnabled); + } + popupWindow.setOutsideTouchable(true); + popupWindow.setClippingEnabled(true); + if (layoutInScreen) { + popupWindow.setLayoutInScreen(true); } + popupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); + popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); + container.setFocusableInTouchMode(true); + container.setOnKeyListener((v, keyCode, event) -> { + if (keyCode == KeyEvent.KEYCODE_MENU && event.getRepeatCount() == 0 && event.getAction() == KeyEvent.ACTION_UP && popupWindow != null && popupWindow.isShowing()) { + popupWindow.dismiss(); + return true; + } + return false; + }); + popupWindow.setOnDismissListener(() -> { + onDismiss(); + if (subMenuDelegate != null) { + subMenuDelegate.onHideSubMenu(); + } + }); + + // if (measurePopup) { + container.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x - AndroidUtilities.dp(40), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.y, MeasureSpec.AT_MOST)); + measurePopup = false; + //} processedPopupClick = false; popupWindow.setFocusable(true); - if (popupLayout.getMeasuredWidth() == 0) { + if (container.getMeasuredWidth() == 0) { updateOrShowPopup(true, true); } else { updateOrShowPopup(true, false); @@ -645,6 +675,9 @@ public void toggleSubMenu() { popupLayout.updateRadialSelectors(); popupWindow.startAnimation(); } + public void toggleSubMenu() { + toggleSubMenu(null, null); + } public void openSearch(boolean openKeyboard) { if (searchContainer == null || searchContainer.getVisibility() == VISIBLE || parentMenu == null) { @@ -728,6 +761,8 @@ public void onAnimationEnd(Animator animation) { if (openKeyboard) { AndroidUtilities.hideKeyboard(searchField); } + parentMenu.requestLayout(); + requestLayout(); return false; } else { searchContainer.setVisibility(VISIBLE); @@ -1496,15 +1531,15 @@ private void updateOrShowPopup(boolean show, boolean update) { if (show) { popupLayout.scrollToTop(); } - + View fromView = showSubMenuFrom == null ? this : showSubMenuFrom; if (parentMenu != null) { View parent = parentMenu.parentActionBar; if (subMenuOpenSide == 0) { if (show) { - popupWindow.showAsDropDown(parent, getLeft() + parentMenu.getLeft() + getMeasuredWidth() - popupLayout.getMeasuredWidth() + (int) getTranslationX(), offsetY); + popupWindow.showAsDropDown(parent, fromView.getLeft() + parentMenu.getLeft() + fromView.getMeasuredWidth() - popupWindow.getContentView().getMeasuredWidth() + (int) getTranslationX(), offsetY); } if (update) { - popupWindow.update(parent, getLeft() + parentMenu.getLeft() + getMeasuredWidth() - popupLayout.getMeasuredWidth() + (int) getTranslationX(), offsetY, -1, -1); + popupWindow.update(parent, fromView.getLeft() + parentMenu.getLeft() + fromView.getMeasuredWidth() - popupWindow.getContentView().getMeasuredWidth() + (int) getTranslationX(), offsetY, -1, -1); } } else { if (show) { @@ -1523,10 +1558,10 @@ private void updateOrShowPopup(boolean show, boolean update) { if (getParent() != null) { View parent = (View) getParent(); if (show) { - popupWindow.showAsDropDown(parent, getLeft() + getMeasuredWidth() - popupLayout.getMeasuredWidth() + additionalXOffset, offsetY); + popupWindow.showAsDropDown(parent, getLeft() + getMeasuredWidth() - popupWindow.getContentView().getMeasuredWidth() + additionalXOffset, offsetY); } if (update) { - popupWindow.update(parent, getLeft() + getMeasuredWidth() - popupLayout.getMeasuredWidth() + additionalXOffset, offsetY, -1, -1); + popupWindow.update(parent, getLeft() + getMeasuredWidth() - popupWindow.getContentView().getMeasuredWidth() + additionalXOffset, offsetY, -1, -1); } } } else if (subMenuOpenSide == 1) { @@ -1538,10 +1573,10 @@ private void updateOrShowPopup(boolean show, boolean update) { } } else { if (show) { - popupWindow.showAsDropDown(this, getMeasuredWidth() - popupLayout.getMeasuredWidth() + additionalXOffset, offsetY); + popupWindow.showAsDropDown(this, getMeasuredWidth() - popupWindow.getContentView().getMeasuredWidth() + additionalXOffset, offsetY); } if (update) { - popupWindow.update(this, getMeasuredWidth() - popupLayout.getMeasuredWidth() + additionalXOffset, offsetY, -1, -1); + popupWindow.update(this, getMeasuredWidth() - popupWindow.getContentView().getMeasuredWidth() + additionalXOffset, offsetY, -1, -1); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java index 2d96863571b..de9e6979a37 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java @@ -234,4 +234,8 @@ private int getThemedColor(String key) { Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null; return color != null ? color : Theme.getColor(key); } + + public CheckBox2 getCheckView() { + return checkView; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java index d7ec53615a1..0aace7e0589 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java @@ -278,7 +278,7 @@ private void startChildAnimation(View child) { if (animationEnabled) { AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether( - ObjectAnimator.ofFloat(child, View.ALPHA, 0.0f, 1.0f), + ObjectAnimator.ofFloat(child, View.ALPHA, 0f, child.isEnabled() ? 1f : 0.5f), ObjectAnimator.ofFloat(child, View.TRANSLATION_Y, AndroidUtilities.dp(shownFromBotton ? 6 : -6), 0)); animatorSet.setDuration(180); animatorSet.addListener(new AnimatorListenerAdapter() { @@ -547,7 +547,18 @@ public void startAnimation() { if (windowAnimatorSet != null) { return; } - ActionBarPopupWindowLayout content = (ActionBarPopupWindowLayout) getContentView(); + + ViewGroup viewGroup = (ViewGroup) getContentView(); + ActionBarPopupWindowLayout content = null; + if (viewGroup instanceof ActionBarPopupWindowLayout) { + content = (ActionBarPopupWindowLayout) viewGroup; + } else { + for (int i = 0; i < viewGroup.getChildCount(); i++) { + if (viewGroup.getChildAt(i) instanceof ActionBarPopupWindowLayout) { + content = (ActionBarPopupWindowLayout) viewGroup.getChildAt(i); + } + } + } content.setTranslationY(0); content.setAlpha(1.0f); content.setPivotX(content.getMeasuredWidth()); @@ -578,11 +589,21 @@ public void startAnimation() { @Override public void onAnimationEnd(Animator animation) { windowAnimatorSet = null; - ActionBarPopupWindowLayout content = (ActionBarPopupWindowLayout) getContentView(); + ViewGroup viewGroup = (ViewGroup) getContentView(); + ActionBarPopupWindowLayout content = null; + if (viewGroup instanceof ActionBarPopupWindowLayout) { + content = (ActionBarPopupWindowLayout) viewGroup; + } else { + for (int i = 0; i < viewGroup.getChildCount(); i++) { + if (viewGroup.getChildAt(i) instanceof ActionBarPopupWindowLayout) { + content = (ActionBarPopupWindowLayout) viewGroup.getChildAt(i); + } + } + } int count = content.getItemsCount(); for (int a = 0; a < count; a++) { View child = content.getItemAt(a); - child.setAlpha(1.0f); + child.setAlpha(child.isEnabled() ? 1f : 0.5f); } } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java index 8302b031c5f..cca31bc255d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java @@ -713,5 +713,4 @@ private void setParentDialog(Dialog dialog) { public Theme.ResourcesProvider getResourceProvider() { return null; } - } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java index 47b27b635f4..c55136a4a28 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java @@ -1111,6 +1111,10 @@ public void setOnHideListener(OnDismissListener listener) { onHideListener = listener; } + protected int getTargetOpenTranslationY() { + return 0; + } + private void startOpenAnimation() { if (dismissed) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ChatTheme.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ChatTheme.java deleted file mode 100644 index e64a9105284..00000000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ChatTheme.java +++ /dev/null @@ -1,300 +0,0 @@ -package org.telegram.ui.ActionBar; - -import android.app.Activity; -import android.content.SharedPreferences; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.drawable.BitmapDrawable; -import android.util.Pair; - -import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.ApplicationLoader; -import org.telegram.messenger.ChatThemeController; -import org.telegram.messenger.FileLoader; -import org.telegram.messenger.FileLog; -import org.telegram.messenger.ImageLoader; -import org.telegram.messenger.ImageLocation; -import org.telegram.messenger.ImageReceiver; -import org.telegram.messenger.SharedConfig; -import org.telegram.messenger.Utilities; -import org.telegram.tgnet.ResultCallback; -import org.telegram.tgnet.TLRPC; - -import java.io.File; -import java.io.FileOutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -public class ChatTheme { - - public final boolean isDefault; - private final TLRPC.TL_chatTheme chatThemeObject; - private HashMap lightCurrentColors; - private HashMap darkCurrentColors; - private String darkWallpaperLink; - private String lightWallpaperLink; - - public ChatTheme(TLRPC.TL_chatTheme chatThemeObject, boolean isDefault) { - this.chatThemeObject = chatThemeObject; - this.isDefault = isDefault; - } - - public void initColors() { - getCurrentColors(0, false); - getCurrentColors(0, true); - } - - public String getEmoticon() { - return chatThemeObject.emoticon; - } - - public TLRPC.TL_theme getTlTheme(boolean isDark) { - return isDark ? ((TLRPC.TL_theme) chatThemeObject.dark_theme) : ((TLRPC.TL_theme) chatThemeObject.theme); - } - - public TLRPC.WallPaper getWallpaper(boolean isDark) { - return getTlTheme(isDark).settings.wallpaper; - } - - public String getWallpaperLink(boolean isDark) { - return isDark ? darkWallpaperLink : lightWallpaperLink; - } - - public HashMap getCurrentColors(int currentAccount, boolean isDark) { - HashMap currentColors = isDark ? darkCurrentColors : lightCurrentColors; - if (currentColors != null) { - return currentColors; - } - - TLRPC.TL_theme tlTheme = getTlTheme(isDark); - Theme.ThemeInfo baseTheme = Theme.getTheme(Theme.getBaseThemeKey(tlTheme.settings)); - Theme.ThemeInfo themeInfo = new Theme.ThemeInfo(baseTheme); - Theme.ThemeAccent accent = themeInfo.createNewAccent(tlTheme, currentAccount, true); - themeInfo.setCurrentAccentId(accent.id); - - HashMap currentColorsNoAccent = new HashMap<>(); - String[] wallpaperLink = new String[1]; - if (themeInfo.pathToFile != null) { - currentColorsNoAccent.putAll(Theme.getThemeFileValues(new File(themeInfo.pathToFile), null, wallpaperLink)); - } else if (themeInfo.assetName != null) { - currentColorsNoAccent.putAll(Theme.getThemeFileValues(null, themeInfo.assetName, wallpaperLink)); - } - if (isDark) { - darkWallpaperLink = wallpaperLink[0]; - } else { - lightWallpaperLink = wallpaperLink[0]; - } - currentColors = new HashMap<>(currentColorsNoAccent); - accent.fillAccentColors(currentColorsNoAccent, currentColors); - if (!isDark) { - currentColors.put(Theme.key_chat_messageTextOut, Theme.MSG_OUT_COLOR_BLACK); - } - HashMap fallbackKeys = Theme.getFallbackKeys(); - for (Map.Entry fallbackEntry : fallbackKeys.entrySet()) { - String colorKey = fallbackEntry.getKey(); - if (!currentColors.containsKey(colorKey)) { - Integer color = currentColors.get(fallbackEntry.getValue()); - currentColors.put(colorKey, color); - } - } - HashMap defaultColors = Theme.getDefaultColors(); - for (Map.Entry entry : defaultColors.entrySet()) { - if (!currentColors.containsKey(entry.getKey())) { - currentColors.put(entry.getKey(), entry.getValue()); - } - } - if (isDark) { - darkCurrentColors = currentColors; - } else { - lightCurrentColors = currentColors; - } - return currentColors; - } - - public void loadWallpaper(boolean isDark, ResultCallback> callback) { - final TLRPC.WallPaper wallPaper = getWallpaper(isDark); - if (wallPaper == null && callback != null) { - callback.onComplete(null); - return; - } - - long themeId = getTlTheme(isDark).id; - Bitmap cachedBitmap = ChatThemeController.getWallpaperBitmap(themeId); - if (cachedBitmap != null && callback != null) { - callback.onComplete(new Pair<>(themeId, cachedBitmap)); - return; - } - - ImageLocation imageLocation = ImageLocation.getForDocument(wallPaper.document); - ImageReceiver imageReceiver = new ImageReceiver(); - String imageFilter; - if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) { - int w = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); - int h = Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); - imageFilter = (int) (w / AndroidUtilities.density) + "_" + (int) (h / AndroidUtilities.density) + "_f"; - } else { - imageFilter = (int) (1080 / AndroidUtilities.density) + "_" + (int) (1920 / AndroidUtilities.density) + "_f"; - } - imageReceiver.setImage(imageLocation, imageFilter, null, ".jpg", wallPaper, 1); - imageReceiver.setDelegate((receiver, set, thumb, memCache) -> { - ImageReceiver.BitmapHolder holder = receiver.getBitmapSafe(); - if (!set || holder == null) { - return; - } - Bitmap bitmap = holder.bitmap; - if (bitmap == null && (holder.drawable instanceof BitmapDrawable)) { - bitmap = ((BitmapDrawable) holder.drawable).getBitmap(); - } - if (callback != null) { - callback.onComplete(new Pair<>(themeId, bitmap)); - } - }); - ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); - } - - public void loadWallpaperThumb(boolean isDark, ResultCallback> callback) { - final TLRPC.WallPaper wallpaper = getWallpaper(isDark); - if (wallpaper == null) { - if (callback != null) { - callback.onComplete(null); - } - return; - } - - long themeId = getTlTheme(isDark).id; - Bitmap bitmap = ChatThemeController.getWallpaperThumbBitmap(themeId); - File file = getWallpaperThumbFile(themeId); - if (bitmap == null && file.exists() && file.length() > 0) { - try { - bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); - } catch (Exception e) { - FileLog.e(e); - } - } - if (bitmap != null) { - if (callback != null) { - callback.onComplete(new Pair<>(themeId, bitmap)); - } - return; - } - - final TLRPC.PhotoSize thumbSize = FileLoader.getClosestPhotoSizeWithSize(wallpaper.document.thumbs, 120); - ImageLocation imageLocation = ImageLocation.getForDocument(thumbSize, wallpaper.document); - ImageReceiver imageReceiver = new ImageReceiver(); - imageReceiver.setImage(imageLocation, "120_80", null, null, null, 1); - imageReceiver.setDelegate((receiver, set, thumb, memCache) -> { - ImageReceiver.BitmapHolder holder = receiver.getBitmapSafe(); - if (!set || holder == null) { - return; - } - Bitmap resultBitmap = holder.bitmap; - if (resultBitmap == null && (holder.drawable instanceof BitmapDrawable)) { - resultBitmap = ((BitmapDrawable) holder.drawable).getBitmap(); - } - if (resultBitmap != null) { - if (callback != null) { - callback.onComplete(new Pair<>(themeId, resultBitmap)); - } - final Bitmap saveBitmap = resultBitmap; - Utilities.globalQueue.postRunnable(() -> { - try (FileOutputStream outputStream = new FileOutputStream(file)) { - saveBitmap.compress(Bitmap.CompressFormat.PNG, 87, outputStream); - } catch (Exception e) { - FileLog.e(e); - } - }); - } else { - if (callback != null) { - callback.onComplete(null); - } - } - }); - ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); - } - - public void preloadWallpaper() { - loadWallpaperThumb(false, null); - loadWallpaperThumb(true, null); - loadWallpaper(false, null); - loadWallpaper(true, null); - } - - private File getWallpaperThumbFile(long themeId) { - return new File(ApplicationLoader.getFilesDirFixed(), "wallpaper_thumb_" + themeId + ".png"); - } - - public static Theme.ThemeInfo getDefaultThemeInfo(boolean isDark) { - Theme.ThemeInfo themeInfo = isDark ? Theme.getCurrentNightTheme() : Theme.getCurrentTheme(); - if (isDark != themeInfo.isDark()) { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE); - String lastThemeName = isDark - ? preferences.getString("lastNightTheme", "Dark Blue") - : preferences.getString("lastDayTheme", "Blue"); - themeInfo = Theme.getTheme(lastThemeName); - if (themeInfo == null) { - themeInfo = Theme.getTheme(isDark ? "Dark Blue" : "Blue"); - } - } - return new Theme.ThemeInfo(themeInfo); - } - - public static ChatTheme getDefault() { - Theme.ThemeInfo darkThemeInfo = getDefaultThemeInfo(true); - fillTlTheme(darkThemeInfo); - Theme.ThemeInfo lightThemeInfo = getDefaultThemeInfo(false); - fillTlTheme(lightThemeInfo); - - TLRPC.TL_chatTheme tlChatTheme = new TLRPC.TL_chatTheme(); - tlChatTheme.emoticon = "❌"; - tlChatTheme.dark_theme = darkThemeInfo.info; - tlChatTheme.theme = lightThemeInfo.info; - - ChatTheme chatTheme = new ChatTheme(tlChatTheme, true); - chatTheme.darkCurrentColors = getCurrentColors(darkThemeInfo); - chatTheme.lightCurrentColors = getCurrentColors(lightThemeInfo); - return chatTheme; - } - - private static void fillTlTheme(Theme.ThemeInfo themeInfo) { - if (themeInfo.info == null) { - themeInfo.info = new TLRPC.TL_theme(); - } - if (themeInfo.info.settings == null) { - themeInfo.info.settings = new TLRPC.TL_themeSettings(); - } - ArrayList messageColors = new ArrayList<>(); - Theme.ThemeAccent accent = themeInfo.getAccent(false); - if (accent != null) { - if (accent.myMessagesAccentColor != 0) { - messageColors.add(accent.myMessagesAccentColor); - } - if (accent.myMessagesGradientAccentColor1 != 0) { - messageColors.add(accent.myMessagesGradientAccentColor1); - } - if (accent.myMessagesGradientAccentColor2 != 0) { - messageColors.add(accent.myMessagesGradientAccentColor2); - } - if (accent.myMessagesGradientAccentColor3 != 0) { - messageColors.add(accent.myMessagesGradientAccentColor3); - } - } - themeInfo.info.settings.message_colors = messageColors; - } - - private static HashMap getCurrentColors(Theme.ThemeInfo themeInfo) { - HashMap currentColorsNoAccent = new HashMap<>(); - if (themeInfo.pathToFile != null) { - currentColorsNoAccent.putAll(Theme.getThemeFileValues(new File(themeInfo.pathToFile), null, null)); - } else if (themeInfo.assetName != null) { - currentColorsNoAccent.putAll(Theme.getThemeFileValues(null, themeInfo.assetName, null)); - } - HashMap currentColors = new HashMap<>(currentColorsNoAccent); - Theme.ThemeAccent themeAccent = themeInfo.getAccent(false); - if (themeAccent != null) { - themeAccent.fillAccentColors(currentColorsNoAccent, currentColors); - } - return currentColors; - } - -} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java index c2d855d131a..8babd13fa9b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java @@ -25,10 +25,6 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.os.Build; -import androidx.annotation.Keep; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - import android.view.DisplayCutout; import android.view.Gravity; import android.view.MotionEvent; @@ -40,6 +36,10 @@ import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; +import androidx.annotation.Keep; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BuildVars; import org.telegram.messenger.FileLog; @@ -91,6 +91,8 @@ public class DrawerLayoutContainer extends FrameLayout { private PreviewForegroundDrawable previewForegroundDrawable; private boolean drawCurrentPreviewFragmentAbove; private float startY; + private boolean keyboardVisibility; + private int imeHeight; public DrawerLayoutContainer(Context context) { super(context); @@ -102,6 +104,15 @@ public DrawerLayoutContainer(Context context) { if (Build.VERSION.SDK_INT >= 21) { setFitsSystemWindows(true); setOnApplyWindowInsetsListener((v, insets) -> { + if (Build.VERSION.SDK_INT >= 30) { + boolean newKeyboardVisibility = insets.isVisible(WindowInsets.Type.ime()); + int imeHeight = insets.getInsets(WindowInsets.Type.ime()).bottom; + if (keyboardVisibility != newKeyboardVisibility || this.imeHeight != imeHeight) { + keyboardVisibility = newKeyboardVisibility; + this.imeHeight = imeHeight; + requestLayout(); + } + } final DrawerLayoutContainer drawerLayoutContainer = (DrawerLayoutContainer) v; if (AndroidUtilities.statusBarHeight != insets.getSystemWindowInsetTop()) { drawerLayoutContainer.requestLayout(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/EmojiThemes.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/EmojiThemes.java new file mode 100644 index 00000000000..3801ad080b9 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/EmojiThemes.java @@ -0,0 +1,510 @@ +package org.telegram.ui.ActionBar; + +import android.app.Activity; +import android.content.SharedPreferences; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.drawable.BitmapDrawable; +import android.util.Pair; + +import com.google.android.exoplayer2.util.Log; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.ChatThemeController; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.ImageLoader; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.Utilities; +import org.telegram.tgnet.ResultCallback; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.Components.ChatThemeBottomSheet; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class EmojiThemes { + + public boolean showAsDefaultStub; + String emoji; + int currentIndex = 0; + ArrayList items = new ArrayList<>(); + + private EmojiThemes() { + } + + public EmojiThemes(TLRPC.TL_theme chatThemeObject, boolean isDefault) { + this.showAsDefaultStub = isDefault; + this.emoji = chatThemeObject.emoticon; + if (!isDefault) { + ThemeItem lightTheme = new ThemeItem(); + lightTheme.tlTheme = chatThemeObject; + lightTheme.settingsIndex = 0; + items.add(lightTheme); + + ThemeItem darkTheme = new ThemeItem(); + darkTheme.tlTheme = chatThemeObject; + darkTheme.settingsIndex = 1; + items.add(darkTheme); + } + } + + public static EmojiThemes createPreviewFullTheme(TLRPC.TL_theme tl_theme) { + EmojiThemes chatTheme = new EmojiThemes(); + chatTheme.emoji = tl_theme.emoticon; + + for (int i = 0; i < tl_theme.settings.size(); i++) { + ThemeItem theme = new ThemeItem(); + theme.tlTheme = tl_theme; + theme.settingsIndex = i; + chatTheme.items.add(theme); + } + return chatTheme; + } + + + public static EmojiThemes createChatThemesDefault() { + + EmojiThemes themeItem = new EmojiThemes(); + themeItem.emoji = "❌"; + themeItem.showAsDefaultStub = true; + + ThemeItem lightTheme = new ThemeItem(); + lightTheme.themeInfo = getDefaultThemeInfo(true); + themeItem.items.add(lightTheme); + + ThemeItem darkTheme = new ThemeItem(); + darkTheme.themeInfo = getDefaultThemeInfo(false); + themeItem.items.add(darkTheme); + + return themeItem; + } + + public static EmojiThemes createPreviewCustom() { + EmojiThemes themeItem = new EmojiThemes(); + themeItem.emoji = "\uD83C\uDFA8"; + + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE); + String lastDayCustomTheme = preferences.getString("lastDayCustomTheme", null); + int dayAccentId = preferences.getInt("lastDayCustomThemeAccentId", -1); + if (lastDayCustomTheme == null || Theme.getTheme(lastDayCustomTheme) == null) { + lastDayCustomTheme = preferences.getString("lastDayTheme", "Blue"); + Theme.ThemeInfo themeInfo = Theme.getTheme(lastDayCustomTheme); + if (themeInfo == null) { + lastDayCustomTheme = "Blue"; + } + preferences.edit().putString("lastDayCustomTheme", lastDayCustomTheme).apply(); + } + + String lastDarkCustomTheme = preferences.getString("lastDarkCustomTheme", null); + int darkAccentId = preferences.getInt("lastDarkCustomThemeAccentId", -1); + if (lastDarkCustomTheme == null || Theme.getTheme(lastDarkCustomTheme) == null) { + lastDarkCustomTheme = preferences.getString("lastDarkTheme", "Dark Blue"); + Theme.ThemeInfo themeInfo = Theme.getTheme(lastDarkCustomTheme); + if (themeInfo == null) { + lastDarkCustomTheme = "Dark Blue"; + } + preferences.edit().putString("lastDarkCustomTheme", lastDarkCustomTheme).apply(); + } + + + ThemeItem lightTheme = new ThemeItem(); + lightTheme.themeInfo = Theme.getTheme(lastDayCustomTheme); + lightTheme.accentId = dayAccentId; + themeItem.items.add(lightTheme); + themeItem.items.add(null); + + ThemeItem darkTheme = new ThemeItem(); + darkTheme.themeInfo = Theme.getTheme(lastDarkCustomTheme); + darkTheme.accentId = darkAccentId; + themeItem.items.add(darkTheme); + themeItem.items.add(null); + + return themeItem; + } + + public static EmojiThemes createHomePreviewTheme() { + EmojiThemes themeItem = new EmojiThemes(); + themeItem.emoji = "\uD83C\uDFE0"; + + ThemeItem blue = new ThemeItem(); + blue.themeInfo = Theme.getTheme("Blue"); + blue.accentId = 99; + themeItem.items.add(blue); + + ThemeItem day = new ThemeItem(); + day.themeInfo = Theme.getTheme("Day"); + day.accentId = 9; + themeItem.items.add(day); + + ThemeItem night = new ThemeItem(); + night.themeInfo = Theme.getTheme("Night"); + night.accentId = 0; + themeItem.items.add(night); + + ThemeItem nightBlue = new ThemeItem(); + nightBlue.themeInfo = Theme.getTheme("Dark Blue"); + nightBlue.accentId = 0; + themeItem.items.add(nightBlue); + return themeItem; + } + + public void initColors() { + getCurrentColors(0, 0); + getCurrentColors(0, 1); + } + + public String getEmoticon() { + return emoji; + } + + public TLRPC.TL_theme getTlTheme(int index) { + return items.get(index).tlTheme; + } + + public TLRPC.WallPaper getWallpaper(int index) { + int settingsIndex = items.get(index).settingsIndex; + if (settingsIndex >= 0) { + return getTlTheme(index).settings.get(settingsIndex).wallpaper; + } + return null; + } + + public String getWallpaperLink(int index) { + return items.get(index).wallpaperLink; + } + + public int getSettingsIndex(int index) { + return items.get(index).settingsIndex; + } + + public HashMap getCurrentColors(int currentAccount, int index) { + HashMap currentColors = items.get(index).currentColors; + if (currentColors != null) { + return currentColors; + } + + Theme.ThemeInfo themeInfo = getThemeInfo(index); + Theme.ThemeAccent accent = null; + if (themeInfo == null) { + int settingsIndex = getSettingsIndex(index); + TLRPC.TL_theme tlTheme = getTlTheme(index); + Theme.ThemeInfo baseTheme = Theme.getTheme(Theme.getBaseThemeKey(tlTheme.settings.get(settingsIndex))); + themeInfo = new Theme.ThemeInfo(baseTheme); + accent = themeInfo.createNewAccent(tlTheme, currentAccount, true, settingsIndex); + themeInfo.setCurrentAccentId(accent.id); + } else { + if (themeInfo.themeAccentsMap != null) { + accent = themeInfo.themeAccentsMap.get(items.get(index).accentId); + } + } + + HashMap currentColorsNoAccent = new HashMap<>(); + String[] wallpaperLink = new String[1]; + if (themeInfo.pathToFile != null) { + currentColorsNoAccent.putAll(Theme.getThemeFileValues(new File(themeInfo.pathToFile), null, wallpaperLink)); + } else if (themeInfo.assetName != null) { + currentColorsNoAccent.putAll(Theme.getThemeFileValues(null, themeInfo.assetName, wallpaperLink)); + } + + items.get(index).wallpaperLink = wallpaperLink[0]; + + currentColors = new HashMap<>(currentColorsNoAccent); + if (accent != null) { + accent.fillAccentColors(currentColorsNoAccent, currentColors); + } + + HashMap fallbackKeys = Theme.getFallbackKeys(); + for (Map.Entry fallbackEntry : fallbackKeys.entrySet()) { + String colorKey = fallbackEntry.getKey(); + if (!currentColors.containsKey(colorKey)) { + Integer color = currentColors.get(fallbackEntry.getValue()); + currentColors.put(colorKey, color); + } + } + HashMap defaultColors = Theme.getDefaultColors(); + for (Map.Entry entry : defaultColors.entrySet()) { + if (!currentColors.containsKey(entry.getKey())) { + currentColors.put(entry.getKey(), entry.getValue()); + } + } + items.get(index).currentColors = currentColors; + return currentColors; + } + + public Theme.ThemeInfo getThemeInfo(int index) { + return items.get(index).themeInfo; + } + + public void loadWallpaper(int index, ResultCallback> callback) { + final TLRPC.WallPaper wallPaper = getWallpaper(index); + if (wallPaper == null) { + if (callback != null) { + callback.onComplete(null); + } + return; + } + + long themeId = getTlTheme(index).id; + ChatThemeController.getWallpaperBitmap(themeId, cachedBitmap -> { + if (cachedBitmap != null && callback != null) { + callback.onComplete(new Pair<>(themeId, cachedBitmap)); + return; + } + ImageLocation imageLocation = ImageLocation.getForDocument(wallPaper.document); + ImageReceiver imageReceiver = new ImageReceiver(); + String imageFilter; + if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) { + int w = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); + int h = Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); + imageFilter = (int) (w / AndroidUtilities.density) + "_" + (int) (h / AndroidUtilities.density) + "_f"; + } else { + imageFilter = (int) (1080 / AndroidUtilities.density) + "_" + (int) (1920 / AndroidUtilities.density) + "_f"; + } + + imageReceiver.setImage(imageLocation, imageFilter, null, ".jpg", wallPaper, 1); + imageReceiver.setDelegate((receiver, set, thumb, memCache) -> { + ImageReceiver.BitmapHolder holder = receiver.getBitmapSafe(); + if (!set || holder == null) { + return; + } + Bitmap bitmap = holder.bitmap; + if (bitmap == null && (holder.drawable instanceof BitmapDrawable)) { + bitmap = ((BitmapDrawable) holder.drawable).getBitmap(); + } + if (callback != null) { + callback.onComplete(new Pair<>(themeId, bitmap)); + } + ChatThemeController.saveWallpaperBitmap(bitmap, themeId); + }); + ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); + }); + } + + public void loadWallpaperThumb(int index, ResultCallback> callback) { + final TLRPC.WallPaper wallpaper = getWallpaper(index); + if (wallpaper == null) { + if (callback != null) { + callback.onComplete(null); + } + return; + } + + long themeId = getTlTheme(index).id; + Bitmap bitmap = ChatThemeController.getWallpaperThumbBitmap(themeId); + File file = getWallpaperThumbFile(themeId); + if (bitmap == null && file.exists() && file.length() > 0) { + try { + bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); + } catch (Exception e) { + FileLog.e(e); + } + } + if (bitmap != null) { + if (callback != null) { + callback.onComplete(new Pair<>(themeId, bitmap)); + } + return; + } + + final TLRPC.PhotoSize thumbSize = FileLoader.getClosestPhotoSizeWithSize(wallpaper.document.thumbs, 120); + ImageLocation imageLocation = ImageLocation.getForDocument(thumbSize, wallpaper.document); + ImageReceiver imageReceiver = new ImageReceiver(); + imageReceiver.setImage(imageLocation, "120_80", null, null, null, 1); + imageReceiver.setDelegate((receiver, set, thumb, memCache) -> { + ImageReceiver.BitmapHolder holder = receiver.getBitmapSafe(); + if (!set || holder == null) { + return; + } + Bitmap resultBitmap = holder.bitmap; + if (resultBitmap == null && (holder.drawable instanceof BitmapDrawable)) { + resultBitmap = ((BitmapDrawable) holder.drawable).getBitmap(); + } + if (resultBitmap != null) { + if (callback != null) { + callback.onComplete(new Pair<>(themeId, resultBitmap)); + } + final Bitmap saveBitmap = resultBitmap; + Utilities.globalQueue.postRunnable(() -> { + try (FileOutputStream outputStream = new FileOutputStream(file)) { + saveBitmap.compress(Bitmap.CompressFormat.PNG, 87, outputStream); + } catch (Exception e) { + FileLog.e(e); + } + }); + } else { + if (callback != null) { + callback.onComplete(null); + } + } + }); + ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); + } + + public void preloadWallpaper() { + loadWallpaperThumb(0, null); + loadWallpaperThumb(1, null); + loadWallpaper(0, null); + loadWallpaper(1, null); + } + + private File getWallpaperThumbFile(long themeId) { + return new File(ApplicationLoader.getFilesDirFixed(), "wallpaper_thumb_" + themeId + ".png"); + } + + public static Theme.ThemeInfo getDefaultThemeInfo(boolean isDark) { + Theme.ThemeInfo themeInfo = isDark ? Theme.getCurrentNightTheme() : Theme.getCurrentTheme(); + if (isDark != themeInfo.isDark()) { + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE); + String lastThemeName = isDark + ? preferences.getString("lastDarkTheme", "Dark Blue") + : preferences.getString("lastDayTheme", "Blue"); + themeInfo = Theme.getTheme(lastThemeName); + if (themeInfo == null) { + themeInfo = Theme.getTheme(isDark ? "Dark Blue" : "Blue"); + } + } + return new Theme.ThemeInfo(themeInfo); + } + + public static void fillTlTheme(Theme.ThemeInfo themeInfo) { + if (themeInfo.info == null) { + themeInfo.info = new TLRPC.TL_theme(); + } + } + + public static HashMap getCurrentColors(Theme.ThemeInfo themeInfo) { + HashMap currentColorsNoAccent = new HashMap<>(); + if (themeInfo.pathToFile != null) { + currentColorsNoAccent.putAll(Theme.getThemeFileValues(new File(themeInfo.pathToFile), null, null)); + } else if (themeInfo.assetName != null) { + currentColorsNoAccent.putAll(Theme.getThemeFileValues(null, themeInfo.assetName, null)); + } + HashMap currentColors = new HashMap<>(currentColorsNoAccent); + Theme.ThemeAccent themeAccent = themeInfo.getAccent(false); + if (themeAccent != null) { + themeAccent.fillAccentColors(currentColorsNoAccent, currentColors); + } + return currentColors; + } + + public int getAccentId(int themeIndex) { + return items.get(themeIndex).accentId; + } + + public void loadPreviewColors(int currentAccount) { + for (int i = 0; i < items.size(); i++) { + if (items.get(i) == null) { + continue; + } + HashMap colorsMap = getCurrentColors(currentAccount, i); + Integer color = colorsMap.get(Theme.key_chat_inBubble); + if (color == null) { + color = Theme.getDefaultColor(Theme.key_chat_inBubble); + } + items.get(i).inBubbleColor = color; + color = colorsMap.get(Theme.key_chat_outBubble); + if (color == null) { + color = Theme.getDefaultColor(Theme.key_chat_outBubble); + } + items.get(i).outBubbleColor = color; + color = colorsMap.get(Theme.key_featuredStickers_addButton); + if (color == null) { + color = Theme.getDefaultColor(Theme.key_featuredStickers_addButton); + } + items.get(i).outLineColor = color; + color = colorsMap.get(Theme.key_chat_wallpaper); + if (color == null) { + items.get(i).patternBgColor = 0; + } else { + items.get(i).patternBgColor = color; + } + color = colorsMap.get(Theme.key_chat_wallpaper_gradient_to1); + if (color == null) { + items.get(i).patternBgGradientColor1 = 0; + } else { + items.get(i).patternBgGradientColor1 = color; + } + color = colorsMap.get(Theme.key_chat_wallpaper_gradient_to2); + if (color == null) { + items.get(i).patternBgGradientColor2 = 0; + } else { + items.get(i).patternBgGradientColor2 = color; + } + color = colorsMap.get(Theme.key_chat_wallpaper_gradient_to3); + if (color == null) { + items.get(i).patternBgGradientColor3 = 0; + } else { + items.get(i).patternBgGradientColor3 = color; + } + if (items.get(i).themeInfo != null && items.get(i).themeInfo.getKey().equals("Blue")) { + int accentId = items.get(i).accentId >= 0 ? items.get(i).accentId : items.get(i).themeInfo.currentAccentId; + if (accentId == 99) { + items.get(i).patternBgColor = 0xffdbddbb; + items.get(i).patternBgGradientColor1 = 0xff6ba587; + items.get(i).patternBgGradientColor2 = 0xffd5d88d; + items.get(i).patternBgGradientColor3 = 0xff88b884; + } + } + } + } + + public ThemeItem getThemeItem(int index) { + return items.get(index); + } + + public static void saveCustomTheme(Theme.ThemeInfo themeInfo, int accentId) { + if (themeInfo == null) { + return; + } + if (accentId >= 0 && themeInfo.themeAccentsMap != null) { + Theme.ThemeAccent accent = themeInfo.themeAccentsMap.get(accentId); + if (accent == null || accent.isDefault) { + return; + } + } + if (themeInfo.getKey().equals("Blue") && accentId == 99) { + return; + } + if (themeInfo.getKey().equals("Day") && accentId == 9) { + return; + } + if (themeInfo.getKey().equals("Night") && accentId == 0) { + return; + } + if (themeInfo.getKey().equals("Dark Blue") && accentId == 0) { + return; + } + + boolean dark = themeInfo.isDark(); + String key = dark ? "lastDarkCustomTheme" : "lastDayCustomTheme"; + String accentKey = dark ? "lastDarkCustomThemeAccentId" : "lastDayCustomThemeAccentId"; + ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE).edit() + .putString(key, themeInfo.getKey()) + .putInt(accentKey, accentId) + .apply(); + } + public static class ThemeItem { + + public Theme.ThemeInfo themeInfo; + TLRPC.TL_theme tlTheme; + int settingsIndex; + public int accentId = -1; + public HashMap currentColors; + private String wallpaperLink; + + public int inBubbleColor; + public int outBubbleColor; + public int outLineColor; + public int patternBgColor; + public int patternBgGradientColor1; + public int patternBgGradientColor2; + public int patternBgGradientColor3; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java index e0a3a0f617d..750bd1ee080 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -66,6 +66,8 @@ import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.Bitmaps; import org.telegram.messenger.BuildVars; +import org.telegram.messenger.ChatThemeController; +import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLocation; @@ -85,6 +87,7 @@ import org.telegram.ui.Cells.ThemesHorizontalListCell; import org.telegram.ui.Components.AudioVisualizerDrawable; import org.telegram.ui.Components.BackgroundGradientDrawable; +import org.telegram.ui.Components.ChatThemeBottomSheet; import org.telegram.ui.Components.ChoosingStickerStatusDrawable; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.FragmentContextViewWavesDrawable; @@ -105,7 +108,6 @@ import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.lang.reflect.Field; @@ -118,6 +120,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.CountDownLatch; @@ -127,8 +130,6 @@ import androidx.annotation.UiThread; import androidx.core.graphics.ColorUtils; -import com.google.android.exoplayer2.util.Log; - public class Theme { public static final String DEFAULT_BACKGROUND_SLUG = "d"; @@ -205,6 +206,8 @@ public static class MessageDrawable extends Drawable { private Bitmap crosfadeFromBitmap; private Shader crosfadeFromBitmapShader; + PathDrawParams pathDrawCacheParams; + public MessageDrawable(int type, boolean out, boolean selected) { this(type, out, selected, null); } @@ -619,6 +622,17 @@ private static ByteBuffer getByteBuffer(int x1, int x2, int y1, int y2) { return buffer; } + public void drawCached(Canvas canvas, PathDrawParams patchDrawCacheParams) { + this.pathDrawCacheParams = patchDrawCacheParams; + if (crossfadeFromDrawable != null) { + crossfadeFromDrawable.pathDrawCacheParams = patchDrawCacheParams; + } + draw(canvas); + this.pathDrawCacheParams = null; + if (crossfadeFromDrawable != null) { + crossfadeFromDrawable.pathDrawCacheParams = null; + } + } @Override public void draw(Canvas canvas) { if (crossfadeFromDrawable != null) { @@ -663,119 +677,138 @@ public void draw(Canvas canvas, Paint paintToUse) { } int top = Math.max(bounds.top, 0); - path.reset(); - if (isOut) { - if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || topY + bounds.bottom - rad < currentBackgroundHeight) { - if (currentType == TYPE_MEDIA) { - path.moveTo(bounds.right - dp(8) - rad, bounds.bottom - padding); + boolean drawFullBottom, drawFullTop; + if (pathDrawCacheParams != null && bounds.height() < currentBackgroundHeight) { + drawFullBottom = true; + drawFullTop = true; + } else { + drawFullBottom = currentType == TYPE_MEDIA ? topY + bounds.bottom - smallRad * 2 < currentBackgroundHeight : topY + bounds.bottom - rad < currentBackgroundHeight; + drawFullTop = topY + rad * 2 >= 0; + } + Path path; + boolean invalidatePath; + if (pathDrawCacheParams != null) { + path = pathDrawCacheParams.path; + invalidatePath = pathDrawCacheParams.invalidatePath(bounds, drawFullBottom, drawFullTop); + } else { + path = this.path; + invalidatePath = true; + } + if (invalidatePath) { + path.reset(); + if (isOut) { + if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || drawFullBottom) { + if (currentType == TYPE_MEDIA) { + path.moveTo(bounds.right - dp(8) - rad, bounds.bottom - padding); + } else { + path.moveTo(bounds.right - dp(2.6f), bounds.bottom - padding); + } + path.lineTo(bounds.left + padding + rad, bounds.bottom - padding); + rect.set(bounds.left + padding, bounds.bottom - padding - rad * 2, bounds.left + padding + rad * 2, bounds.bottom - padding); + path.arcTo(rect, 90, 90, false); } else { - path.moveTo(bounds.right - dp(2.6f), bounds.bottom - padding); + path.moveTo(bounds.right - dp(8), top - topY + currentBackgroundHeight); + path.lineTo(bounds.left + padding, top - topY + currentBackgroundHeight); } - path.lineTo(bounds.left + padding + rad, bounds.bottom - padding); - rect.set(bounds.left + padding, bounds.bottom - padding - rad * 2, bounds.left + padding + rad * 2, bounds.bottom - padding); - path.arcTo(rect, 90, 90, false); - } else { - path.moveTo(bounds.right - dp(8), top - topY + currentBackgroundHeight); - path.lineTo(bounds.left + padding, top - topY + currentBackgroundHeight); - } - if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || topY + rad * 2 >= 0) { - path.lineTo(bounds.left + padding, bounds.top + padding + rad); - rect.set(bounds.left + padding, bounds.top + padding, bounds.left + padding + rad * 2, bounds.top + padding + rad * 2); - path.arcTo(rect, 180, 90, false); - - int radToUse = isTopNear ? nearRad : rad; - if (currentType == TYPE_MEDIA) { - path.lineTo(bounds.right - padding - radToUse, bounds.top + padding); - rect.set(bounds.right - padding - radToUse * 2, bounds.top + padding, bounds.right - padding, bounds.top + padding + radToUse * 2); + if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || drawFullTop) { + path.lineTo(bounds.left + padding, bounds.top + padding + rad); + rect.set(bounds.left + padding, bounds.top + padding, bounds.left + padding + rad * 2, bounds.top + padding + rad * 2); + path.arcTo(rect, 180, 90, false); + + int radToUse = isTopNear ? nearRad : rad; + if (currentType == TYPE_MEDIA) { + path.lineTo(bounds.right - padding - radToUse, bounds.top + padding); + rect.set(bounds.right - padding - radToUse * 2, bounds.top + padding, bounds.right - padding, bounds.top + padding + radToUse * 2); + } else { + path.lineTo(bounds.right - dp(8) - radToUse, bounds.top + padding); + rect.set(bounds.right - dp(8) - radToUse * 2, bounds.top + padding, bounds.right - dp(8), bounds.top + padding + radToUse * 2); + } + path.arcTo(rect, 270, 90, false); } else { - path.lineTo(bounds.right - dp(8) - radToUse, bounds.top + padding); - rect.set(bounds.right - dp(8) - radToUse * 2, bounds.top + padding, bounds.right - dp(8), bounds.top + padding + radToUse * 2); + path.lineTo(bounds.left + padding, top - topY - dp(2)); + if (currentType == TYPE_MEDIA) { + path.lineTo(bounds.right - padding, top - topY - dp(2)); + } else { + path.lineTo(bounds.right - dp(8), top - topY - dp(2)); + } } - path.arcTo(rect, 270, 90, false); - } else { - path.lineTo(bounds.left + padding, top - topY - dp(2)); if (currentType == TYPE_MEDIA) { - path.lineTo(bounds.right - padding, top - topY - dp(2)); - } else { - path.lineTo(bounds.right - dp(8), top - topY - dp(2)); - } - } - if (currentType == TYPE_MEDIA) { - if (paintToUse != null || topY + bounds.bottom - rad < currentBackgroundHeight) { - int radToUse = isBottomNear ? nearRad : rad; + if (paintToUse != null || drawFullBottom) { + int radToUse = isBottomNear ? nearRad : rad; - path.lineTo(bounds.right - padding, bounds.bottom - padding - radToUse); - rect.set(bounds.right - padding - radToUse * 2, bounds.bottom - padding - radToUse * 2, bounds.right - padding, bounds.bottom - padding); - path.arcTo(rect, 0, 90, false); + path.lineTo(bounds.right - padding, bounds.bottom - padding - radToUse); + rect.set(bounds.right - padding - radToUse * 2, bounds.bottom - padding - radToUse * 2, bounds.right - padding, bounds.bottom - padding); + path.arcTo(rect, 0, 90, false); + } else { + path.lineTo(bounds.right - padding, top - topY + currentBackgroundHeight); + } } else { - path.lineTo(bounds.right - padding, top - topY + currentBackgroundHeight); + if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || drawFullBottom) { + path.lineTo(bounds.right - dp(8), bounds.bottom - padding - smallRad - dp(3)); + rect.set(bounds.right - dp(8), bounds.bottom - padding - smallRad * 2 - dp(9), bounds.right - dp(7) + smallRad * 2, bounds.bottom - padding - dp(1)); + path.arcTo(rect, 180, -83, false); + } else { + path.lineTo(bounds.right - dp(8), top - topY + currentBackgroundHeight); + } } } else { - if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || topY + bounds.bottom - smallRad * 2 < currentBackgroundHeight) { - path.lineTo(bounds.right - dp(8), bounds.bottom - padding - smallRad - dp(3)); - rect.set(bounds.right - dp(8), bounds.bottom - padding - smallRad * 2 - dp(9), bounds.right - dp(7) + smallRad * 2, bounds.bottom - padding - dp(1)); - path.arcTo(rect, 180, -83, false); - } else { - path.lineTo(bounds.right - dp(8), top - topY + currentBackgroundHeight); - } - } - } else { - if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || topY + bounds.bottom - rad < currentBackgroundHeight) { - if (currentType == TYPE_MEDIA) { - path.moveTo(bounds.left + dp(8) + rad, bounds.bottom - padding); + if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || drawFullBottom) { + if (currentType == TYPE_MEDIA) { + path.moveTo(bounds.left + dp(8) + rad, bounds.bottom - padding); + } else { + path.moveTo(bounds.left + dp(2.6f), bounds.bottom - padding); + } + path.lineTo(bounds.right - padding - rad, bounds.bottom - padding); + rect.set(bounds.right - padding - rad * 2, bounds.bottom - padding - rad * 2, bounds.right - padding, bounds.bottom - padding); + path.arcTo(rect, 90, -90, false); } else { - path.moveTo(bounds.left + dp(2.6f), bounds.bottom - padding); + path.moveTo(bounds.left + dp(8), top - topY + currentBackgroundHeight); + path.lineTo(bounds.right - padding, top - topY + currentBackgroundHeight); } - path.lineTo(bounds.right - padding - rad, bounds.bottom - padding); - rect.set(bounds.right - padding - rad * 2, bounds.bottom - padding - rad * 2, bounds.right - padding, bounds.bottom - padding); - path.arcTo(rect, 90, -90, false); - } else { - path.moveTo(bounds.left + dp(8), top - topY + currentBackgroundHeight); - path.lineTo(bounds.right - padding, top - topY + currentBackgroundHeight); - } - if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || topY + rad * 2 >= 0) { - path.lineTo(bounds.right - padding, bounds.top + padding + rad); - rect.set(bounds.right - padding - rad * 2, bounds.top + padding, bounds.right - padding, bounds.top + padding + rad * 2); - path.arcTo(rect, 0, -90, false); - - int radToUse = isTopNear ? nearRad : rad; - if (currentType == TYPE_MEDIA) { - path.lineTo(bounds.left + padding + radToUse, bounds.top + padding); - rect.set(bounds.left + padding, bounds.top + padding, bounds.left + padding + radToUse * 2, bounds.top + padding + radToUse * 2); + if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || drawFullTop) { + path.lineTo(bounds.right - padding, bounds.top + padding + rad); + rect.set(bounds.right - padding - rad * 2, bounds.top + padding, bounds.right - padding, bounds.top + padding + rad * 2); + path.arcTo(rect, 0, -90, false); + + int radToUse = isTopNear ? nearRad : rad; + if (currentType == TYPE_MEDIA) { + path.lineTo(bounds.left + padding + radToUse, bounds.top + padding); + rect.set(bounds.left + padding, bounds.top + padding, bounds.left + padding + radToUse * 2, bounds.top + padding + radToUse * 2); + } else { + path.lineTo(bounds.left + dp(8) + radToUse, bounds.top + padding); + rect.set(bounds.left + dp(8), bounds.top + padding, bounds.left + dp(8) + radToUse * 2, bounds.top + padding + radToUse * 2); + } + path.arcTo(rect, 270, -90, false); } else { - path.lineTo(bounds.left + dp(8) + radToUse, bounds.top + padding); - rect.set(bounds.left + dp(8), bounds.top + padding, bounds.left + dp(8) + radToUse * 2, bounds.top + padding + radToUse * 2); + path.lineTo(bounds.right - padding, top - topY - dp(2)); + if (currentType == TYPE_MEDIA) { + path.lineTo(bounds.left + padding, top - topY - dp(2)); + } else { + path.lineTo(bounds.left + dp(8), top - topY - dp(2)); + } } - path.arcTo(rect, 270, -90, false); - } else { - path.lineTo(bounds.right - padding, top - topY - dp(2)); if (currentType == TYPE_MEDIA) { - path.lineTo(bounds.left + padding, top - topY - dp(2)); - } else { - path.lineTo(bounds.left + dp(8), top - topY - dp(2)); - } - } - if (currentType == TYPE_MEDIA) { - if (paintToUse != null || topY + bounds.bottom - rad < currentBackgroundHeight) { - int radToUse = isBottomNear ? nearRad : rad; + if (paintToUse != null || drawFullBottom) { + int radToUse = isBottomNear ? nearRad : rad; - path.lineTo(bounds.left + padding, bounds.bottom - padding - radToUse); - rect.set(bounds.left + padding, bounds.bottom - padding - radToUse * 2, bounds.left + padding + radToUse * 2, bounds.bottom - padding); - path.arcTo(rect, 180, -90, false); - } else { - path.lineTo(bounds.left + padding, top - topY + currentBackgroundHeight); - } - } else { - if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || topY + bounds.bottom - smallRad * 2 < currentBackgroundHeight) { - path.lineTo(bounds.left + dp(8), bounds.bottom - padding - smallRad - dp(3)); - rect.set(bounds.left + dp(7) - smallRad * 2, bounds.bottom - padding - smallRad * 2 - dp(9), bounds.left + dp(8), bounds.bottom - padding - dp(1)); - path.arcTo(rect, 0, 83, false); + path.lineTo(bounds.left + padding, bounds.bottom - padding - radToUse); + rect.set(bounds.left + padding, bounds.bottom - padding - radToUse * 2, bounds.left + padding + radToUse * 2, bounds.bottom - padding); + path.arcTo(rect, 180, -90, false); + } else { + path.lineTo(bounds.left + padding, top - topY + currentBackgroundHeight); + } } else { - path.lineTo(bounds.left + dp(8), top - topY + currentBackgroundHeight); + if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || drawFullBottom) { + path.lineTo(bounds.left + dp(8), bounds.bottom - padding - smallRad - dp(3)); + rect.set(bounds.left + dp(7) - smallRad * 2, bounds.bottom - padding - smallRad * 2 - dp(9), bounds.left + dp(8), bounds.bottom - padding - dp(1)); + path.arcTo(rect, 0, 83, false); + } else { + path.lineTo(bounds.left + dp(8), top - topY + currentBackgroundHeight); + } } } + path.close(); } - path.close(); canvas.drawPath(path, p); if (gradientShader != null && isSelected && paintToUse == null) { @@ -832,6 +865,21 @@ public void setBounds(int left, int top, int right, int bottom) { crossfadeFromDrawable.setBounds(left, top, right, bottom); } } + + public static class PathDrawParams { + Path path = new Path(); + Rect lastRect = new Rect(); + boolean lastDrawFullTop; + boolean lastDrawFullBottom; + + public boolean invalidatePath(Rect bounds, boolean drawFullBottom, boolean drawFullTop) { + boolean invalidate = lastRect.isEmpty() || lastRect.top != bounds.top || lastRect.bottom != bounds.bottom || lastRect.right != bounds.right || lastRect.left != bounds.left || lastDrawFullTop != drawFullTop || lastDrawFullBottom != drawFullBottom || !drawFullTop || !drawFullBottom; + lastDrawFullTop = drawFullTop; + lastDrawFullBottom = drawFullBottom; + lastRect.set(bounds); + return invalidate; + } + } } public static class PatternsLoader implements NotificationCenter.NotificationCenterDelegate { @@ -1007,7 +1055,7 @@ private Bitmap createWallpaperForAccent(Bitmap patternBitmap, boolean svg, File } ThemeInfo themeInfo = accent.parentTheme; HashMap values = getThemeFileValues(null, themeInfo.assetName, null); - + checkIsDark(values, themeInfo); int backgroundAccent = accent.accentColor; int backgroundColor = (int) accent.backgroundOverrideColor; @@ -1167,6 +1215,7 @@ public static class ThemeAccent { public TLRPC.InputFile uploadedFile; public OverrideWallpaperInfo overrideWallpaper; + public boolean isDefault; ThemeAccent() { @@ -1470,7 +1519,6 @@ public File getPathToWallpaper() { if (id < 100) { return !TextUtils.isEmpty(patternSlug) ? new File(ApplicationLoader.getFilesDirFixed(), String.format(Locale.US, "%s_%d_%s_v5.jpg", parentTheme.getKey(), id, patternSlug)) : null; } else { - // return !TextUtils.isEmpty(patternSlug) ? new File(ApplicationLoader.getFilesDirFixed(), String.format(Locale.US, "%s_%d_%s_v4.jpg", parentTheme.getKey(), id, patternSlug)) : null; return !TextUtils.isEmpty(patternSlug) ? new File(ApplicationLoader.getFilesDirFixed(), String.format(Locale.US, "%s_%d_%s_v8_dubug.jpg", parentTheme.getKey(), id, patternSlug)) : null; } } @@ -1743,6 +1791,11 @@ public static class ThemeInfo implements NotificationCenter.NotificationCenterDe private String newPathToWallpaper; public OverrideWallpaperInfo overrideWallpaper; + private int isDark = UNKNOWN; + + private final static int DARK= 1; + private final static int LIGHT = 0; + private final static int UNKNOWN = -1; ThemeInfo() { @@ -2004,7 +2057,20 @@ public boolean hasAccentColors() { } public boolean isDark() { - return "Dark Blue".equals(name) || "Night".equals(name); + if (isDark != UNKNOWN) { + return isDark == DARK; + } + if ("Dark Blue".equals(name) || "Night".equals(name)) { + isDark = DARK; + } else if ("Blue".equals(name) || "Arctic Blue".equals(name) || "Day".equals(name)) { + isDark = LIGHT; + } + if (isDark == UNKNOWN) { + String[] wallpaperLink = new String[1]; + HashMap colors = getThemeFileValues(new File(pathToFile), null, wallpaperLink); + checkIsDark(colors, this); + } + return isDark == DARK; } public boolean isLight() { @@ -2070,6 +2136,7 @@ private void setAccentColorOptions(int[] accent, int[] myMessages, int[] myMessa themeAccents = new ArrayList<>(); themeAccentsMap = new SparseArray<>(); accentsByThemeId = new LongSparseArray<>(); + for (int a = 0; a < accent.length; a++) { ThemeAccent themeAccent = new ThemeAccent(); themeAccent.id = ids != null ? ids[a] : a; @@ -2147,7 +2214,7 @@ private void onFinishLoadingRemoteTheme() { previewParsed = false; saveOtherThemes(true); if (this == currentTheme && previousTheme == null) { - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, this, this == currentNightTheme, null, -1); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, this, this == currentNightTheme, null, -1, fallbackKeys); } } @@ -2254,20 +2321,24 @@ public ThemeAccent createNewAccent(TLRPC.ThemeSettings settings) { } public ThemeAccent createNewAccent(TLRPC.TL_theme info, int account) { - return createNewAccent(info, account, false); + return createNewAccent(info, account, false, 0); } - public ThemeAccent createNewAccent(TLRPC.TL_theme info, int account, boolean ignoreThemeInfoId) { + public ThemeAccent createNewAccent(TLRPC.TL_theme info, int account, boolean ignoreThemeInfoId, int settingsIndex) { if (info == null) { return null; } + TLRPC.ThemeSettings settings = null; + if (settingsIndex < info.settings.size()) { + settings = info.settings.get(settingsIndex); + } if (ignoreThemeInfoId) { ThemeAccent themeAccent = chatAccentsByThemeId.get(info.id); if (themeAccent != null) { return themeAccent; } int id = ++lastChatThemeId; - themeAccent = createNewAccent(info.settings); + themeAccent = createNewAccent(settings); themeAccent.id = id; themeAccent.info = info; themeAccent.account = account; @@ -2279,7 +2350,7 @@ public ThemeAccent createNewAccent(TLRPC.TL_theme info, int account, boolean ign return themeAccent; } int id = ++lastAccentId; - themeAccent = createNewAccent(info.settings); + themeAccent = createNewAccent(settings); themeAccent.id = id; themeAccent.info = info; themeAccent.account = account; @@ -2524,6 +2595,7 @@ public void run() { private static long[] remoteThemesHash = new long[UserConfig.MAX_ACCOUNT_COUNT]; public static ArrayList themes; + public static final ArrayList defaultEmojiThemes = new ArrayList<>(); private static ArrayList otherThemes; private static HashMap themesDict; private static ThemeInfo currentTheme; @@ -3637,6 +3709,8 @@ public void run() { public static final String key_drawable_shareIcon = "drawableShareIcon"; public static final String key_drawable_muteIconDrawable = "drawableMuteIcon"; public static final String key_drawable_lockIconDrawable = "drawableLockIcon"; + public static final String key_drawable_chat_pollHintDrawableOut = "drawable_chat_pollHintDrawableOut"; + public static final String key_drawable_chat_pollHintDrawableIn = "drawable_chat_pollHintDrawableIn"; private static final HashMap defaultChatDrawables = new HashMap<>(); private static final HashMap defaultChatDrawableColorKeys = new HashMap<>(); @@ -5002,6 +5076,9 @@ public void run() { accent.info = (TLRPC.TL_theme) TLRPC.Theme.TLdeserialize(data, data.readInt32(true), true); } } + if (accent.info != null) { + accent.isDefault = accent.info.isDefault; + } info.themeAccentsMap.put(accent.id, accent); if (accent.info != null) { info.accentsByThemeId.put(accent.info.id, accent); @@ -5009,11 +5086,12 @@ public void run() { newAccents.add(accent); info.lastAccentId = Math.max(info.lastAccentId, accent.id); } catch (Throwable e) { - + throw new RuntimeException(e); } } } catch (Throwable e) { FileLog.e(e); + throw new RuntimeException(e); } } else { String key = "accent_for_" + info.assetName; @@ -5120,6 +5198,7 @@ public void run() { autoNightLastSunCheckDay = preferences.getInt("autoNightLastSunCheckDay", -1); } catch (Exception e) { FileLog.e(e); + throw new RuntimeException(e); } if (applyingTheme == null) { applyingTheme = defaultTheme; @@ -5163,6 +5242,35 @@ public void run() { } applyTheme(applyingTheme, false, false, switchToTheme == 2); AndroidUtilities.runOnUIThread(Theme::checkAutoNightThemeConditions); + + preferences = ApplicationLoader.applicationContext.getSharedPreferences("emojithemes_config", Context.MODE_PRIVATE); + int count = preferences.getInt("count", 0); + ArrayList previewItems = new ArrayList<>(); + previewItems.add(new ChatThemeBottomSheet.ChatThemeItem(EmojiThemes.createHomePreviewTheme())); + for (int i = 0; i < count; ++i) { + String value = preferences.getString("theme_" + i, ""); + SerializedData serializedData = new SerializedData(Utilities.hexToBytes(value)); + try { + TLRPC.TL_theme theme = TLRPC.Theme.TLdeserialize(serializedData, serializedData.readInt32(true), true); + previewItems.add(new ChatThemeBottomSheet.ChatThemeItem(EmojiThemes.createPreviewFullTheme(theme))); + + ChatThemeController.chatThemeQueue.postRunnable(new Runnable() { + @Override + public void run() { + for (int i = 0; i < previewItems.size(); i++) { + previewItems.get(i).chatTheme.loadPreviewColors(0); + } + AndroidUtilities.runOnUIThread(() -> { + defaultEmojiThemes.clear(); + defaultEmojiThemes.addAll(previewItems); + NotificationCenter.getInstance(0).postNotificationName(NotificationCenter.emojiPreviewThemesChanged); + }); + } + }); + } catch (Throwable e) { + FileLog.e(e); + } + } } private static Method StateListDrawable_getStateDrawableMethod; @@ -5890,7 +5998,8 @@ public static ThemeInfo fillThemeValues(File file, String themeName, TLRPC.TL_th themeInfo.account = UserConfig.selectedAccount; String[] wallpaperLink = new String[1]; - getThemeFileValues(new File(themeInfo.pathToFile), null, wallpaperLink); + HashMap colors = getThemeFileValues(new File(themeInfo.pathToFile), null, wallpaperLink); + checkIsDark(colors, themeInfo); if (!TextUtils.isEmpty(wallpaperLink[0])) { String link = wallpaperLink[0]; @@ -6964,13 +7073,17 @@ public static void checkCurrentRemoteTheme(boolean force) { boolean changed = false; if (response instanceof TLRPC.TL_theme) { TLRPC.TL_theme theme = (TLRPC.TL_theme) response; - if (accent != null && theme.settings != null) { - if (!ThemeInfo.accentEquals(accent, theme.settings)) { + TLRPC.ThemeSettings settings = null; + if (theme.settings.size() > 0) { + settings = theme.settings.get(0); + } + if (accent != null && settings != null) { + if (!ThemeInfo.accentEquals(accent, settings)) { File file = accent.getPathToWallpaper(); if (file != null) { file.delete(); } - ThemeInfo.fillAccentValues(accent, theme.settings); + ThemeInfo.fillAccentValues(accent, settings); if (currentTheme == themeInfo && currentTheme.currentAccentId == accent.id) { refreshThemeColors(); createChatResources(ApplicationLoader.applicationContext, false); @@ -6979,7 +7092,7 @@ public static void checkCurrentRemoteTheme(boolean force) { PatternsLoader.createLoader(true); changed = true; } - accent.patternMotion = theme.settings.wallpaper != null && theme.settings.wallpaper.settings != null && theme.settings.wallpaper.settings.motion; + accent.patternMotion = settings.wallpaper != null && settings.wallpaper.settings != null && settings.wallpaper.settings.motion; } else if (theme.document != null && theme.document.id != info.document.id) { if (accent != null) { accent.info = theme; @@ -6999,7 +7112,7 @@ public static void checkCurrentRemoteTheme(boolean force) { } public static void loadRemoteThemes(final int currentAccount, boolean force) { - if (loadingRemoteThemes[currentAccount] || !force && Math.abs(System.currentTimeMillis() / 1000 - lastLoadingThemesTime[currentAccount]) < 60 * 60 || !UserConfig.getInstance(currentAccount).isClientActivated()) { + if (loadingRemoteThemes[currentAccount]) { return; } loadingRemoteThemes[currentAccount] = true; @@ -7012,6 +7125,7 @@ public static void loadRemoteThemes(final int currentAccount, boolean force) { TLRPC.TL_account_themes res = (TLRPC.TL_account_themes) response; remoteThemesHash[currentAccount] = res.hash; lastLoadingThemesTime[currentAccount] = (int) (System.currentTimeMillis() / 1000); + ArrayList emojiPreviewThemes = new ArrayList<>(); ArrayList oldServerThemes = new ArrayList<>(); for (int a = 0, N = themes.size(); a < N; a++) { ThemeInfo info = themes.get(a); @@ -7034,36 +7148,47 @@ public static void loadRemoteThemes(final int currentAccount, boolean force) { continue; } TLRPC.TL_theme theme = (TLRPC.TL_theme) t; - if (theme.settings != null) { - String key = getBaseThemeKey(theme.settings); - if (key == null) { - continue; - } - ThemeInfo info = themesDict.get(key); - if (info == null || info.themeAccents == null) { - continue; - } - ThemeAccent accent = info.accentsByThemeId.get(theme.id); - if (accent != null) { - if (!ThemeInfo.accentEquals(accent, theme.settings)) { - File file = accent.getPathToWallpaper(); - if (file != null) { - file.delete(); + if (theme.isDefault) { + //TODO new emoji themes + continue; + //emojiPreviewThemes.add(theme); + } + if (theme.settings != null && theme.settings.size() > 0) { + for (int i = 0; i < theme.settings.size(); i++) { + TLRPC.ThemeSettings settings = theme.settings.get(i); + if (settings != null) { + String key = getBaseThemeKey(settings); + if (key == null) { + continue; } - ThemeInfo.fillAccentValues(accent, theme.settings); - loadPatterns = true; - added = true; - if (currentTheme == info && currentTheme.currentAccentId == accent.id) { - refreshThemeColors(); - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, currentTheme, currentNightTheme == currentTheme, null, -1); + ThemeInfo info = themesDict.get(key); + if (info == null || info.themeAccents == null) { + continue; } - } - accent.patternMotion = theme.settings.wallpaper != null && theme.settings.wallpaper.settings != null && theme.settings.wallpaper.settings.motion; - oldServerThemes.remove(accent); - } else { - accent = info.createNewAccent(theme, currentAccount); - if (!TextUtils.isEmpty(accent.patternSlug)) { - loadPatterns = true; + ThemeAccent accent = info.accentsByThemeId.get(theme.id); + if (accent != null) { + if (!ThemeInfo.accentEquals(accent, settings)) { + File file = accent.getPathToWallpaper(); + if (file != null) { + file.delete(); + } + ThemeInfo.fillAccentValues(accent, settings); + loadPatterns = true; + added = true; + if (currentTheme == info && currentTheme.currentAccentId == accent.id) { + refreshThemeColors(); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, currentTheme, currentNightTheme == currentTheme, null, -1); + } + } + accent.patternMotion = settings.wallpaper != null && settings.wallpaper.settings != null && settings.wallpaper.settings.motion; + oldServerThemes.remove(accent); + } else { + accent = info.createNewAccent(theme, currentAccount); + if (!TextUtils.isEmpty(accent.patternSlug)) { + loadPatterns = true; + } + } + accent.isDefault = theme.isDefault; } } } else { @@ -7123,10 +7248,52 @@ public static void loadRemoteThemes(final int currentAccount, boolean force) { if (loadPatterns) { PatternsLoader.createLoader(true); } + generateEmojiPreviewThemes(emojiPreviewThemes, currentAccount); } })); } + private static void generateEmojiPreviewThemes(final ArrayList emojiPreviewThemes, int currentAccount) { + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("emojithemes_config", Context.MODE_PRIVATE); + SharedPreferences.Editor editor = preferences.edit(); + editor.putInt("count", emojiPreviewThemes.size()); + for (int i = 0; i < emojiPreviewThemes.size(); ++i) { + TLRPC.TL_theme tlChatTheme = emojiPreviewThemes.get(i); + SerializedData data = new SerializedData(tlChatTheme.getObjectSize()); + tlChatTheme.serializeToStream(data); + editor.putString("theme_" + i, Utilities.bytesToHex(data.toByteArray())); + EmojiThemes chatTheme = new EmojiThemes(tlChatTheme, false); + } + editor.apply(); + + if (!emojiPreviewThemes.isEmpty()) { + final ArrayList previewItems = new ArrayList<>(); + previewItems.add(new ChatThemeBottomSheet.ChatThemeItem(EmojiThemes.createHomePreviewTheme())); + for (int i = 0; i < emojiPreviewThemes.size(); i++) { + TLRPC.TL_theme theme = emojiPreviewThemes.get(i); + EmojiThemes chatTheme = EmojiThemes.createPreviewFullTheme(theme); + ChatThemeBottomSheet.ChatThemeItem item = new ChatThemeBottomSheet.ChatThemeItem(chatTheme); + previewItems.add(item); + } + ChatThemeController.chatThemeQueue.postRunnable(new Runnable() { + @Override + public void run() { + for (int i = 0; i < previewItems.size(); i++) { + previewItems.get(i).chatTheme.loadPreviewColors(currentAccount); + } + AndroidUtilities.runOnUIThread(() -> { + defaultEmojiThemes.clear(); + defaultEmojiThemes.addAll(previewItems); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.emojiPreviewThemesChanged); + }); + } + }); + } else { + defaultEmojiThemes.clear(); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.emojiPreviewThemesChanged); + } + } + public static String getBaseThemeKey(TLRPC.ThemeSettings settings) { if (settings.base_theme instanceof TLRPC.TL_baseThemeClassic) { return "Blue"; @@ -7178,9 +7345,13 @@ public static void setThemeUploadInfo(ThemeInfo theme, ThemeAccent accent, TLRPC if (info == null) { return; } - if (info.settings != null) { + TLRPC.ThemeSettings settings = null; + if (info.settings.size() > 0) { + settings = info.settings.get(0); + } + if (settings != null) { if (theme == null) { - String key = getBaseThemeKey(info.settings); + String key = getBaseThemeKey(settings); if (key == null) { return; } @@ -7199,19 +7370,21 @@ public static void setThemeUploadInfo(ThemeInfo theme, ThemeAccent accent, TLRPC accent.info = info; accent.account = account; theme.accentsByThemeId.put(info.id, accent); - if (!ThemeInfo.accentEquals(accent, info.settings)) { + + + if (!ThemeInfo.accentEquals(accent, settings)) { File file = accent.getPathToWallpaper(); if (file != null) { file.delete(); } - ThemeInfo.fillAccentValues(accent, info.settings); + ThemeInfo.fillAccentValues(accent, settings); if (currentTheme == theme && currentTheme.currentAccentId == accent.id) { refreshThemeColors(); NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, currentTheme, currentNightTheme == currentTheme, null, -1); } PatternsLoader.createLoader(true); } - accent.patternMotion = info.settings.wallpaper != null && info.settings.wallpaper.settings != null && info.settings.wallpaper.settings.motion; + accent.patternMotion = settings.wallpaper != null && settings.wallpaper.settings != null && settings.wallpaper.settings.motion; theme.previewParsed = false; } else { String key; @@ -7278,6 +7451,7 @@ public static String createThemePreviewImage(String pathToFile, String wallpaper try { String[] wallpaperLink = new String[1]; HashMap colors = getThemeFileValues(new File(pathToFile), null, wallpaperLink); + checkIsDark(colors, accent.parentTheme); Integer wallpaperFileOffset = colors.get("wallpaperFileOffset"); Bitmap bitmap = Bitmaps.createBitmap(560, 678, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); @@ -7556,6 +7730,21 @@ protected Integer getCurrentColor(String key) { return null; } + private static void checkIsDark(HashMap colors, Theme.ThemeInfo info) { + if (info == null || colors == null) { + return; + } + if (info.isDark == ThemeInfo.UNKNOWN) { + int averageBackgroundColor = getPreviewColor(colors, key_windowBackgroundWhite); + averageBackgroundColor = ColorUtils.blendARGB(averageBackgroundColor, getPreviewColor(colors, key_windowBackgroundWhite), 0.5f); + if (ColorUtils.calculateLuminance(averageBackgroundColor) < 0.5f) { + info.isDark = ThemeInfo.DARK; + } else { + info.isDark = ThemeInfo.LIGHT; + } + } + } + public static HashMap getThemeFileValues(File file, String assetName, String[] wallpaperLink) { FileInputStream stream = null; HashMap stringMap = new HashMap<>(); @@ -8321,6 +8510,8 @@ public static void createChatResources(Context context, boolean fontsOnly) { addChatDrawable(key_drawable_shareIcon, chat_shareIconDrawable, key_chat_serviceIcon); addChatDrawable(key_drawable_muteIconDrawable, chat_muteIconDrawable, key_chat_muteIcon); addChatDrawable(key_drawable_lockIconDrawable, chat_lockIconDrawable, key_chat_lockIcon); + addChatDrawable(key_drawable_chat_pollHintDrawableOut, chat_pollHintDrawable[1], key_chat_outPreviewInstantText); + addChatDrawable(key_drawable_chat_pollHintDrawableIn, chat_pollHintDrawable[0], key_chat_inPreviewInstantText); applyChatTheme(fontsOnly, false); } @@ -8654,7 +8845,8 @@ public static void applyChatServiceMessageColor(int[] custom, Drawable wallpaper } Drawable drawable = wallpaperOverride != null ? wallpaperOverride : currentWallpaper; - if (drawable instanceof MotionBackgroundDrawable) { + boolean drawServiceGradient = drawable instanceof MotionBackgroundDrawable && SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW; + if (drawServiceGradient) { Bitmap newBitmap = ((MotionBackgroundDrawable) drawable).getBitmap(); if (serviceBitmap != newBitmap) { serviceBitmap = newBitmap; @@ -9140,8 +9332,12 @@ public static void loadWallpaper() { if (accent != null) { wallpaperFile = accent.getPathToWallpaper(); wallpaperMotion = accent.patternMotion; - if (accent.info != null && accent.info.settings != null && accent.info.settings.wallpaper != null) { - wallpaperDocument = accent.info.settings.wallpaper.document; + TLRPC.ThemeSettings settings = null; + if (accent.info != null && accent.info.settings.size() > 0) { + settings = accent.info.settings.get(0); + } + if (accent.info != null && settings != null && settings.wallpaper != null) { + wallpaperDocument = settings.wallpaper.document; } } else { wallpaperFile = null; @@ -9156,7 +9352,7 @@ public static void loadWallpaper() { } TLRPC.Document finalWallpaperDocument = wallpaperDocument; - Utilities.searchQueue.postRunnable(wallpaperLoadTask = () -> { + Utilities.themeQueue.postRunnable(wallpaperLoadTask = () -> { BackgroundDrawableSettings settings = createBackgroundDrawable( currentTheme, overrideWallpaper, @@ -9602,7 +9798,7 @@ public static Drawable getCachedWallpaper() { } if (drawable == null && wallpaperLoadTask != null) { CountDownLatch countDownLatch = new CountDownLatch(1); - Utilities.searchQueue.postRunnable(countDownLatch::countDown); + Utilities.themeQueue.postRunnable(countDownLatch::countDown); try { countDownLatch.await(); } catch (Exception e) { @@ -9773,9 +9969,7 @@ private static void addChatPaint(String key, Paint paint, String colorKey) { } } - public static void setColorToPaint(Paint paint, int color) { - if (paint.getColor() != color) { - paint.setColor(color); - } + public static boolean isCurrentThemeDay() { + return !getActiveTheme().isDark(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java index ac2d743b06e..4a920d86f30 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java @@ -547,7 +547,8 @@ public String getLetter(int position) { } @Override - public int getPositionForScrollProgress(float progress) { - return (int) (getItemCount() * progress); + public void getPositionForScrollProgress(RecyclerListView listView, float progress, int[] position) { + position[0] = (int) (getItemCount() * progress); + position[1] = 0; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java index a92ae3535eb..51775dff3d7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java @@ -104,9 +104,6 @@ public DialogsAdapter(DialogsActivity fragment, Context context, int type, int f SharedPreferences preferences = MessagesController.getGlobalMainSettings(); showArchiveHint = preferences.getBoolean("archivehint", true); preferences.edit().putBoolean("archivehint", false).commit(); - if (showArchiveHint) { - archiveHintCell = new ArchiveHintCell(context); - } } if (folder == 0) { this.preloader = new DialogsPreloader(); @@ -428,11 +425,8 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { break; } case 9: + archiveHintCell = new ArchiveHintCell(mContext); view = archiveHintCell; - if (archiveHintCell.getParent() != null) { - ViewGroup parent = (ViewGroup) archiveHintCell.getParent(); - parent.removeView(archiveHintCell); - } break; case 10: { view = new LastEmptyView(mContext); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java index e2200fc84a5..c0ddbdc7196 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java @@ -1149,7 +1149,7 @@ public void run() { if (searchResultUsernamesMap.indexOfKey(peerId) >= 0 || !isSearchingMentions && peerId == currentUserId) { continue; } - if (peerId > 0) { + if (peerId >= 0) { TLRPC.User user = messagesController.getUser(peerId); if (user == null) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java index 3f33b0c55a1..66d017cc9f3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java @@ -3664,7 +3664,7 @@ public void onTextCopied() { }); containerView.addView(textSelectionHelper.getOverlayView(activity)); - pinchToZoomHelper = new PinchToZoomHelper(containerView); + pinchToZoomHelper = new PinchToZoomHelper(containerView, windowView); pinchToZoomHelper.setClipBoundsListener(new PinchToZoomHelper.ClipBoundsListener() { @Override public void getClipTopBottom(float[] topBottom) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/AvatarPreviewPagerIndicator.java b/TMessagesProj/src/main/java/org/telegram/ui/AvatarPreviewPagerIndicator.java index 034bef7b7cc..41ed7ac92f6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/AvatarPreviewPagerIndicator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/AvatarPreviewPagerIndicator.java @@ -63,7 +63,7 @@ public class AvatarPreviewPagerIndicator extends View implements ProfileGalleryV private float currentLoadingAnimationProgress; private int currentLoadingAnimationDirection = 1; - ProfileGalleryView profileGalleryView; + protected ProfileGalleryView profileGalleryView; TextPaint textPaint; private float progressToCounter; @@ -378,4 +378,8 @@ public void onVideoSet() { public void setProfileGalleryView(ProfileGalleryView profileGalleryView) { this.profileGalleryView = profileGalleryView; } + + public ProfileGalleryView getProfileGalleryView() { + return profileGalleryView; + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java index a5e315c9bd2..4d5b90e1609 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java @@ -596,7 +596,7 @@ private void clearDatabase() { database.executeFast("DELETE FROM messages_holes WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM bot_keyboard WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM media_counts_v2 WHERE uid = " + did).stepThis().dispose(); - database.executeFast("DELETE FROM media_v3 WHERE uid = " + did).stepThis().dispose(); + database.executeFast("DELETE FROM media_v4 WHERE uid = " + did).stepThis().dispose(); database.executeFast("DELETE FROM media_holes_v2 WHERE uid = " + did).stepThis().dispose(); MediaDataController.getInstance(currentAccount).clearBotKeyboard(did, null); if (messageId != -1) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java index 3eeec95ba07..51c7bdc6785 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -11,11 +11,8 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; -import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.Path; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; import android.graphics.RectF; import android.text.Layout; import android.text.Spannable; @@ -28,8 +25,6 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; -import com.google.android.exoplayer2.util.Log; - import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DownloadController; import org.telegram.messenger.FileLoader; @@ -54,6 +49,8 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileDownloadProgressListener { + private boolean canDrawInParent; + public interface ChatActionCellDelegate { default void didClickImage(ChatActionCell cell) { } @@ -95,6 +92,8 @@ public interface ThemeDelegate extends Theme.ResourcesProvider { private int previousWidth; private boolean imagePressed; + TextPaint textPaint; + private float viewTop; private int backgroundHeight; private boolean visiblePartSet; @@ -128,11 +127,12 @@ public interface ThemeDelegate extends Theme.ResourcesProvider { private ThemeDelegate themeDelegate; public ChatActionCell(Context context) { - this(context, null); + this(context, false, null); } - public ChatActionCell(Context context, ThemeDelegate themeDelegate) { + public ChatActionCell(Context context, boolean canDrawInParent, ThemeDelegate themeDelegate) { super(context); + this.canDrawInParent = canDrawInParent; this.themeDelegate = themeDelegate; imageReceiver = new ImageReceiver(this); imageReceiver.setRoundRadius(AndroidUtilities.roundMessageSize / 2); @@ -257,9 +257,6 @@ public void setVisiblePart(float visibleTop, int parentH) { visiblePartSet = true; backgroundHeight = parentH; viewTop = visibleTop; - if (hasGradientService()) { - invalidate(); - } } @Override @@ -489,8 +486,30 @@ protected void onDraw(Canvas canvas) { return; } + drawBackground(canvas, false); + + if (textPaint != null) { + canvas.save(); + canvas.translate(textXLeft, textY); + if (textLayout.getPaint() != textPaint) { + buildLayout(); + } + textLayout.draw(canvas); + canvas.restore(); + } + } + + public void drawBackground(Canvas canvas, boolean fromParent) { + if (canDrawInParent) { + if (hasGradientService() && !fromParent) { + return; + } + if (!hasGradientService() && fromParent) { + return; + } + } Paint backgroundPaint = getThemedPaint(Theme.key_paint_chatActionBackground); - TextPaint textPaint = (TextPaint) getThemedPaint(Theme.key_paint_chatActionText); + textPaint = (TextPaint) getThemedPaint(Theme.key_paint_chatActionText); if (overrideBackground != null) { int color = getThemedColor(overrideBackground); if (overrideBackgroundPaint == null) { @@ -641,22 +660,28 @@ protected void onDraw(Canvas canvas) { } else { Theme.applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, 0, viewTop + AndroidUtilities.dp(4)); } + + int oldAlpha = -1; + int oldAlpha2 = -1; + if (fromParent && getAlpha() != 1f) { + oldAlpha = backgroundPaint.getAlpha(); + oldAlpha2 = Theme.chat_actionBackgroundGradientDarkenPaint.getAlpha(); + backgroundPaint.setAlpha((int) (oldAlpha * getAlpha())); + Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha((int) (oldAlpha2 * getAlpha())); + } canvas.drawPath(backgroundPath, backgroundPaint); if (hasGradientService()) { canvas.drawPath(backgroundPath, Theme.chat_actionBackgroundGradientDarkenPaint); } - canvas.save(); - canvas.translate(textXLeft, textY); - if (textLayout.getPaint() != textPaint) { - buildLayout(); + if (oldAlpha >= 0) { + backgroundPaint.setAlpha(oldAlpha); + Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha(oldAlpha2); } - textLayout.draw(canvas); - canvas.restore(); } - protected boolean hasGradientService() { - return themeDelegate != null ? themeDelegate.hasGradientService() : Theme.hasGradientService(); + public boolean hasGradientService() { + return overrideBackgroundPaint == null && (themeDelegate != null ? themeDelegate.hasGradientService() : Theme.hasGradientService()); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java index fdf9e0da143..6fec1e773c7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -68,6 +68,8 @@ import androidx.core.graphics.ColorUtils; +import com.google.android.exoplayer2.util.Log; + import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; @@ -825,18 +827,22 @@ public void run() { private int currentFocusedVirtualView = -1; public boolean drawFromPinchToZoom; + private Theme.MessageDrawable.PathDrawParams backgroundCacheParams = new Theme.MessageDrawable.PathDrawParams(); + VideoForwardDrawable videoForwardDrawable; VideoPlayerRewinder videoPlayerRewinder; private final Theme.ResourcesProvider resourcesProvider; + private final boolean canDrawBackgroundInParent; public ChatMessageCell(Context context) { - this(context, null); + this(context, false, null); } - public ChatMessageCell(Context context, Theme.ResourcesProvider resourcesProvider) { + public ChatMessageCell(Context context, boolean canDrawBackgroundInParent, Theme.ResourcesProvider resourcesProvider) { super(context); this.resourcesProvider = resourcesProvider; + this.canDrawBackgroundInParent = canDrawBackgroundInParent; backgroundDrawable = new MessageBackgroundDrawable(this); avatarImage = new ImageReceiver(); @@ -2584,7 +2590,7 @@ public void setVisiblePart(int position, int height, int parent, float parentOff this.parentViewTopOffset = parentOffset; parentHeight = parent; } - if (currentMessageObject != null && (hasGradientService() && currentMessageObject.shouldDrawWithoutBackground() || drawSideButton != 0 || !botButtons.isEmpty()) || currentBackgroundDrawable != null && currentBackgroundDrawable.getGradientShader() != null) { + if (currentMessageObject != null && (hasGradientService() && currentMessageObject.shouldDrawWithoutBackground() || drawSideButton != 0 || !botButtons.isEmpty()) ) { invalidate(); } @@ -5295,8 +5301,9 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe } else { availableTimeWidth = photoWidth - AndroidUtilities.dp(14); } + if (messageObject.type == MessageObject.TYPE_ROUND_VIDEO) { - availableTimeWidth -= Math.ceil(Theme.chat_audioTimePaint.measureText("00:00")) + AndroidUtilities.dp(26); + availableTimeWidth = (int) (AndroidUtilities.roundMessageSize - Math.ceil(Theme.chat_audioTimePaint.measureText("00:00")) + AndroidUtilities.dp(40)); } measureTime(messageObject); int timeWidthTotal = timeWidth + AndroidUtilities.dp((SharedConfig.bubbleRadius >= 10 ? 22 : 18) + (messageObject.isOutOwner() ? 20 : 0)); @@ -6882,6 +6889,9 @@ private void createInstantViewButton() { if (currentMessageObject.type == 12) { totalHeight += AndroidUtilities.dp(14); } + if (hasNewLineForTime) { + totalHeight += AndroidUtilities.dp(16); + } if (instantViewLayout != null && instantViewLayout.getLineCount() > 0) { instantTextX = (int) (instantWidth - Math.ceil(instantViewLayout.getLineWidth(0))) / 2 + (drawInstantViewType == 0 ? AndroidUtilities.dp(8) : 0); instantTextLeftX = (int) instantViewLayout.getLineLeft(0); @@ -7693,7 +7703,7 @@ private void drawContent(Canvas canvas) { if (audioVisualizerDrawable != null) { audioVisualizerDrawable.setParentView(this); - audioVisualizerDrawable.draw(canvas, buttonX + AndroidUtilities.dp(22), buttonY + AndroidUtilities.dp(22), currentMessageObject.isOutOwner()); + audioVisualizerDrawable.draw(canvas, buttonX + AndroidUtilities.dp(22), buttonY + AndroidUtilities.dp(22), currentMessageObject.isOutOwner(), resourcesProvider); } if (!enterTransitionInPorgress) { @@ -7922,6 +7932,9 @@ public void drawLinkPreview(Canvas canvas, float alpha) { linkX = unmovedTextX + AndroidUtilities.dp(1); } else if (currentMessageObject.isSponsored()) { startY = textY + currentMessageObject.textHeight - AndroidUtilities.dp(2); + if (hasNewLineForTime) { + startY += AndroidUtilities.dp(16); + } linkX = unmovedTextX + AndroidUtilities.dp(1); } else { startY = textY + currentMessageObject.textHeight + AndroidUtilities.dp(8); @@ -9586,7 +9599,7 @@ private boolean isOpenChatByShare(MessageObject messageObject) { } private boolean checkNeedDrawShareButton(MessageObject messageObject) { - if (currentMessageObject.deleted) { + if (currentMessageObject.deleted || currentMessageObject.isSponsored()) { return false; } if (currentPosition != null) { @@ -10213,14 +10226,14 @@ protected void onDraw(Canvas canvas) { } if (currentMessageObject.isOutOwner()) { - Theme.setColorToPaint(Theme.chat_msgTextPaint, getThemedColor(Theme.key_chat_messageTextOut)); - Theme.setColorToPaint(Theme.chat_msgGameTextPaint, getThemedColor(Theme.key_chat_messageTextOut)); + Theme.chat_msgTextPaint.setColor(getThemedColor(Theme.key_chat_messageTextOut)); + Theme.chat_msgGameTextPaint.setColor(getThemedColor(Theme.key_chat_messageTextOut)); Theme.chat_msgGameTextPaint.linkColor = getThemedColor(Theme.key_chat_messageLinkOut); Theme.chat_replyTextPaint.linkColor = getThemedColor(Theme.key_chat_messageLinkOut); Theme.chat_msgTextPaint.linkColor = getThemedColor(Theme.key_chat_messageLinkOut); } else { - Theme.setColorToPaint(Theme.chat_msgTextPaint, getThemedColor(Theme.key_chat_messageTextIn)); - Theme.setColorToPaint(Theme.chat_msgGameTextPaint, getThemedColor(Theme.key_chat_messageTextIn)); + Theme.chat_msgTextPaint.setColor(getThemedColor(Theme.key_chat_messageTextIn)); + Theme.chat_msgGameTextPaint.setColor(getThemedColor(Theme.key_chat_messageTextIn)); Theme.chat_msgGameTextPaint.linkColor = getThemedColor(Theme.key_chat_messageLinkIn); Theme.chat_replyTextPaint.linkColor = getThemedColor(Theme.key_chat_messageLinkIn); Theme.chat_msgTextPaint.linkColor = getThemedColor(Theme.key_chat_messageLinkIn); @@ -10244,23 +10257,234 @@ protected void onDraw(Canvas canvas) { } } if (currentMessageObject.type == MessageObject.TYPE_ROUND_VIDEO) { - Theme.setColorToPaint(Theme.chat_timePaint, getThemedColor(Theme.key_chat_serviceText)); + Theme.chat_timePaint.setColor(getThemedColor(Theme.key_chat_serviceText)); } else { if (mediaBackground) { if (currentMessageObject.shouldDrawWithoutBackground()) { - Theme.setColorToPaint(Theme.chat_timePaint, getThemedColor(Theme.key_chat_serviceText)); + Theme.chat_timePaint.setColor(getThemedColor(Theme.key_chat_serviceText)); } else { - Theme.setColorToPaint(Theme.chat_timePaint, getThemedColor(Theme.key_chat_mediaTimeText)); + Theme.chat_timePaint.setColor(getThemedColor(Theme.key_chat_mediaTimeText)); } } else { if (currentMessageObject.isOutOwner()) { - Theme.setColorToPaint(Theme.chat_timePaint, getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_outTimeSelectedText : Theme.key_chat_outTimeText)); + Theme.chat_timePaint.setColor(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_outTimeSelectedText : Theme.key_chat_outTimeText)); } else { - Theme.setColorToPaint(Theme.chat_timePaint, getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_inTimeSelectedText : Theme.key_chat_inTimeText)); + Theme.chat_timePaint.setColor(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_inTimeSelectedText : Theme.key_chat_inTimeText)); + } + } + } + + drawBackgroundInternal(canvas, false); + if (isHighlightedAnimated) { + long newTime = System.currentTimeMillis(); + long dt = Math.abs(newTime - lastHighlightProgressTime); + if (dt > 17) { + dt = 17; + } + highlightProgress -= dt; + lastHighlightProgressTime = newTime; + if (highlightProgress <= 0) { + highlightProgress = 0; + isHighlightedAnimated = false; + } + invalidate(); + if (getParent() != null) { + ((View) getParent()).invalidate(); + } + } + + int restore = Integer.MIN_VALUE; + if (alphaInternal != 1.0f) { + int top = 0; + int left = 0; + int bottom = getMeasuredHeight(); + int right = getMeasuredWidth(); + + if (currentBackgroundDrawable != null) { + top = currentBackgroundDrawable.getBounds().top; + bottom = currentBackgroundDrawable.getBounds().bottom; + left = currentBackgroundDrawable.getBounds().left; + right = currentBackgroundDrawable.getBounds().right; + } + + if (drawSideButton != 0) { + if (currentMessageObject.isOutOwner()) { + left -= AndroidUtilities.dp(8 + 32); + } else { + right += AndroidUtilities.dp(8 + 32); } } + if (getY() < 0) { + top = (int) -getY(); + } + if (getY() + getMeasuredHeight() > parentHeight) { + bottom = (int) (parentHeight - getY()); + } + rect.set(left, top, right, bottom); + restore = canvas.saveLayerAlpha(rect, (int) (255 * alphaInternal), Canvas.ALL_SAVE_FLAG); + } + boolean clipContent = false; + if (transitionParams.animateBackgroundBoundsInner && currentBackgroundDrawable != null && !isRoundVideo) { + Rect r = currentBackgroundDrawable.getBounds(); + canvas.save(); + canvas.clipRect( + r.left + AndroidUtilities.dp(4), r.top + AndroidUtilities.dp(4), + r.right - AndroidUtilities.dp(4), r.bottom - AndroidUtilities.dp(4) + ); + clipContent = true; + } + drawContent(canvas); + if (clipContent) { + canvas.restore(); } + if (!transitionParams.animateBackgroundBoundsInner) { + if (!transitionParams.transitionBotButtons.isEmpty()) { + drawBotButtons(canvas, transitionParams.transitionBotButtons, 1f - transitionParams.animateChangeProgress); + } + if (!botButtons.isEmpty()) { + drawBotButtons(canvas, botButtons, transitionParams.animateChangeProgress); + } + } + + if (drawSideButton != 0) { + if (currentMessageObject.isOutOwner()) { + sideStartX = getCurrentBackgroundLeft() - AndroidUtilities.dp(8 + 32); + if (currentMessagesGroup != null) { + sideStartX += currentMessagesGroup.transitionParams.offsetLeft - animationOffsetX; + } + } else { + sideStartX = currentBackgroundDrawable.getBounds().right + AndroidUtilities.dp(8); + if (currentMessagesGroup != null) { + sideStartX += currentMessagesGroup.transitionParams.offsetRight - animationOffsetX; + } + } + sideStartY = layoutHeight - AndroidUtilities.dp(41) + transitionParams.deltaBottom; + if (currentMessagesGroup != null) { + sideStartY += currentMessagesGroup.transitionParams.offsetBottom; + if (currentMessagesGroup.transitionParams.backgroundChangeBounds) { + sideStartY -= getTranslationY(); + } + } + if (!currentMessageObject.isOutOwner() && isRoundVideo && isAvatarVisible) { + float offsetSize = (AndroidUtilities.roundPlayingMessageSize - AndroidUtilities.roundMessageSize) * 0.7f; + float offsetX = isPlayingRound ? offsetSize : 0; + if (transitionParams.animatePlayingRound) { + offsetX = (isPlayingRound ? transitionParams.animateChangeProgress : (1f - transitionParams.animateChangeProgress)) * offsetSize; + } + sideStartX -= offsetX; + } + if (drawSideButton == 3) { + if (!(enterTransitionInPorgress && !currentMessageObject.isVoice())) { + drawCommentButton(canvas, 1f); + } + } else { + rect.set(sideStartX, sideStartY, sideStartX + AndroidUtilities.dp(32), sideStartY + AndroidUtilities.dp(32)); + applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, getX(), viewTop); + canvas.drawRoundRect(rect, AndroidUtilities.dp(16), AndroidUtilities.dp(16), getThemedPaint(sideButtonPressed ? Theme.key_paint_chatActionBackgroundSelected : Theme.key_paint_chatActionBackground)); + if (hasGradientService()) { + canvas.drawRoundRect(rect, AndroidUtilities.dp(16), AndroidUtilities.dp(16), Theme.chat_actionBackgroundGradientDarkenPaint); + } + + if (drawSideButton == 2) { + Drawable goIconDrawable = getThemedDrawable(Theme.key_drawable_goIcon); + if (currentMessageObject.isOutOwner()) { + setDrawableBounds(goIconDrawable, sideStartX + AndroidUtilities.dp(10), sideStartY + AndroidUtilities.dp(9)); + canvas.save(); + canvas.scale(-1, 1, goIconDrawable.getBounds().centerX(), goIconDrawable.getBounds().centerY()); + } else { + setDrawableBounds(goIconDrawable, sideStartX + AndroidUtilities.dp(12), sideStartY + AndroidUtilities.dp(9)); + } + goIconDrawable.draw(canvas); + if (currentMessageObject.isOutOwner()) { + canvas.restore(); + } + } else { + Drawable drawable = getThemedDrawable(Theme.key_drawable_shareIcon); + setDrawableBounds(drawable, sideStartX + AndroidUtilities.dp(8), sideStartY + AndroidUtilities.dp(9)); + drawable.draw(canvas); + } + } + } + + if (replyNameLayout != null) { + if (currentMessageObject.shouldDrawWithoutBackground()) { + if (currentMessageObject.isOutOwner()) { + replyStartX = AndroidUtilities.dp(23); + if (isPlayingRound) { + replyStartX -= (AndroidUtilities.roundPlayingMessageSize - AndroidUtilities.roundMessageSize); + } + } else if (currentMessageObject.type == MessageObject.TYPE_ROUND_VIDEO) { + replyStartX = backgroundDrawableLeft + backgroundDrawableRight + AndroidUtilities.dp(4); + } else { + replyStartX = backgroundDrawableLeft + backgroundDrawableRight + AndroidUtilities.dp(17); + } + replyStartY = AndroidUtilities.dp(12); + } else { + if (currentMessageObject.isOutOwner()) { + replyStartX = backgroundDrawableLeft + AndroidUtilities.dp(12) + getExtraTextX(); + } else { + if (mediaBackground) { + replyStartX = backgroundDrawableLeft + AndroidUtilities.dp(12) + getExtraTextX(); + } else { + replyStartX = backgroundDrawableLeft + AndroidUtilities.dp(drawPinnedBottom ? 12 : 18) + getExtraTextX(); + } + } + replyStartY = AndroidUtilities.dp(12 + (drawForwardedName && forwardedNameLayout[0] != null ? 36 : 0) + (drawNameLayout && nameLayout != null ? 20 : 0)); + } + } + if (currentPosition == null && !transitionParams.animateBackgroundBoundsInner && !(enterTransitionInPorgress && !currentMessageObject.isVoice())) { + drawNamesLayout(canvas, 1f); + } + + if ((!autoPlayingMedia || !MediaController.getInstance().isPlayingMessageAndReadyToDraw(currentMessageObject) || isRoundVideo) && !transitionParams.animateBackgroundBoundsInner) { + drawOverlays(canvas); + } + if ((drawTime || !mediaBackground) && !forceNotDrawTime && !transitionParams.animateBackgroundBoundsInner && !(enterTransitionInPorgress && !currentMessageObject.isVoice())) { + drawTime(canvas, 1f, false); + } + + if ((controlsAlpha != 1.0f || timeAlpha != 1.0f) && currentMessageObject.type != 5) { + long newTime = System.currentTimeMillis(); + long dt = Math.abs(lastControlsAlphaChangeTime - newTime); + if (dt > 17) { + dt = 17; + } + totalChangeTime += dt; + if (totalChangeTime > 100) { + totalChangeTime = 100; + } + lastControlsAlphaChangeTime = newTime; + if (controlsAlpha != 1.0f) { + controlsAlpha = AndroidUtilities.decelerateInterpolator.getInterpolation(totalChangeTime / 100.0f); + } + if (timeAlpha != 1.0f) { + timeAlpha = AndroidUtilities.decelerateInterpolator.getInterpolation(totalChangeTime / 100.0f); + } + invalidate(); + if (forceNotDrawTime && currentPosition != null && currentPosition.last && getParent() != null) { + View parent = (View) getParent(); + parent.invalidate(); + } + } + if (restore != Integer.MIN_VALUE) { + canvas.restoreToCount(restore); + } + updateSelectionTextPosition(); + } + + @SuppressLint("WrongCall") + public void drawBackgroundInternal(Canvas canvas, boolean fromParent) { + if (currentMessageObject == null) { + return; + } + if (!wasLayout && !animationRunning) { + forceLayout(); + return; + } + if (!wasLayout) { + onLayout(false, getLeft(), getTop(), getRight(), getBottom()); + } Drawable currentBackgroundShadowDrawable; int additionalTop = 0; int additionalBottom = 0; @@ -10473,27 +10697,36 @@ protected void onDraw(Canvas canvas) { } } + if (!fromParent && drawBackgroundInParent()) { + return; + } + boolean needRestore = false; if (transitionYOffsetForDrawables != 0) { needRestore = true; canvas.save(); canvas.translate(0, transitionYOffsetForDrawables); } + if (drawBackground && currentBackgroundDrawable != null && (currentPosition == null || isDrawSelectionBackground() && (currentMessageObject.isMusic() || currentMessageObject.isDocument())) && !(enterTransitionInPorgress && !currentMessageObject.isVoice())) { + float alphaInternal = this.alphaInternal; + if (fromParent) { + alphaInternal *= getAlpha(); + } if (isHighlightedAnimated) { currentBackgroundDrawable.setAlpha((int) (255 * alphaInternal)); - currentBackgroundDrawable.draw(canvas); + currentBackgroundDrawable.drawCached(canvas, backgroundCacheParams); float alpha = highlightProgress >= 300 ? 1.0f : highlightProgress / 300.0f; currentSelectedBackgroundAlpha = alpha; if (currentPosition == null) { currentBackgroundSelectedDrawable.setAlpha((int) (alphaInternal * alpha * 255)); - currentBackgroundSelectedDrawable.draw(canvas); + currentBackgroundSelectedDrawable.drawCached(canvas, backgroundCacheParams); } } else if (selectedBackgroundProgress != 0 && !(currentMessagesGroup != null && currentMessagesGroup.isDocuments)) { - currentBackgroundDrawable.draw(canvas); + currentBackgroundDrawable.drawCached(canvas, backgroundCacheParams); currentSelectedBackgroundAlpha = selectedBackgroundProgress; currentBackgroundSelectedDrawable.setAlpha((int) (selectedBackgroundProgress * alphaInternal * 255)); - currentBackgroundSelectedDrawable.draw(canvas); + currentBackgroundSelectedDrawable.drawCached(canvas, backgroundCacheParams); if (currentBackgroundDrawable.getGradientShader() == null) { currentBackgroundShadowDrawable = null; } @@ -10505,14 +10738,14 @@ protected void onDraw(Canvas canvas) { } currentSelectedBackgroundAlpha = 1f; currentBackgroundSelectedDrawable.setAlpha((int) (255 * alphaInternal)); - currentBackgroundSelectedDrawable.draw(canvas); + currentBackgroundSelectedDrawable.drawCached(canvas, backgroundCacheParams); if (currentPosition != null) { canvas.restore(); } } else { currentSelectedBackgroundAlpha = 0; currentBackgroundDrawable.setAlpha((int) (255 * alphaInternal)); - currentBackgroundDrawable.draw(canvas); + currentBackgroundDrawable.drawCached(canvas, backgroundCacheParams); } } if (currentBackgroundShadowDrawable != null && currentPosition == null) { @@ -10567,202 +10800,17 @@ protected void onDraw(Canvas canvas) { if (needRestore) { canvas.restore(); } - if (isHighlightedAnimated) { - long newTime = System.currentTimeMillis(); - long dt = Math.abs(newTime - lastHighlightProgressTime); - if (dt > 17) { - dt = 17; - } - highlightProgress -= dt; - lastHighlightProgressTime = newTime; - if (highlightProgress <= 0) { - highlightProgress = 0; - isHighlightedAnimated = false; - } - invalidate(); - if (getParent() != null) { - ((View) getParent()).invalidate(); - } - } - - int restore = Integer.MIN_VALUE; - if (alphaInternal != 1.0f) { - int top = 0; - int left = 0; - int bottom = getMeasuredHeight(); - int right = getMeasuredWidth(); - - if (currentBackgroundDrawable != null) { - top = currentBackgroundDrawable.getBounds().top; - bottom = currentBackgroundDrawable.getBounds().bottom; - left = currentBackgroundDrawable.getBounds().left; - right = currentBackgroundDrawable.getBounds().right; - } - - if (drawSideButton != 0) { - if (currentMessageObject.isOutOwner()) { - left -= AndroidUtilities.dp(8 + 32); - } else { - right += AndroidUtilities.dp(8 + 32); - } - } - if (getY() < 0) { - top = (int) -getY(); - } - if (getY() + getMeasuredHeight() > parentHeight) { - bottom = (int) (parentHeight - getY()); - } - rect.set(left, top, right, bottom); - restore = canvas.saveLayerAlpha(rect, (int) (255 * alphaInternal), Canvas.ALL_SAVE_FLAG); - } - boolean clipContent = false; - if (transitionParams.animateBackgroundBoundsInner && currentBackgroundDrawable != null && !isRoundVideo) { - Rect r = currentBackgroundDrawable.getBounds(); - canvas.save(); - canvas.clipRect( - r.left + AndroidUtilities.dp(4), r.top + AndroidUtilities.dp(4), - r.right - AndroidUtilities.dp(4), r.bottom - AndroidUtilities.dp(4) - ); - clipContent = true; - } - drawContent(canvas); - if (clipContent) { - canvas.restore(); - } - - if (!transitionParams.animateBackgroundBoundsInner) { - if (!transitionParams.transitionBotButtons.isEmpty()) { - drawBotButtons(canvas, transitionParams.transitionBotButtons, 1f - transitionParams.animateChangeProgress); - } - if (!botButtons.isEmpty()) { - drawBotButtons(canvas, botButtons, transitionParams.animateChangeProgress); - } - } - - if (drawSideButton != 0) { - if (currentMessageObject.isOutOwner()) { - sideStartX = getCurrentBackgroundLeft() - AndroidUtilities.dp(8 + 32); - if (currentMessagesGroup != null) { - sideStartX += currentMessagesGroup.transitionParams.offsetLeft - animationOffsetX; - } - } else { - sideStartX = currentBackgroundDrawable.getBounds().right + AndroidUtilities.dp(8); - if (currentMessagesGroup != null) { - sideStartX += currentMessagesGroup.transitionParams.offsetRight - animationOffsetX; - } - } - sideStartY = layoutHeight - AndroidUtilities.dp(41) + transitionParams.deltaBottom; - if (currentMessagesGroup != null) { - sideStartY += currentMessagesGroup.transitionParams.offsetBottom; - if (currentMessagesGroup.transitionParams.backgroundChangeBounds) { - sideStartY -= getTranslationY(); - } - } - if (!currentMessageObject.isOutOwner() && isRoundVideo && isAvatarVisible) { - float offsetSize = (AndroidUtilities.roundPlayingMessageSize - AndroidUtilities.roundMessageSize) * 0.7f; - float offsetX = isPlayingRound ? offsetSize : 0; - if (transitionParams.animatePlayingRound) { - offsetX = (isPlayingRound ? transitionParams.animateChangeProgress : (1f - transitionParams.animateChangeProgress)) * offsetSize; - } - sideStartX -= offsetX; - } - if (drawSideButton == 3) { - if (!(enterTransitionInPorgress && !currentMessageObject.isVoice())) { - drawCommentButton(canvas, 1f); - } - } else { - rect.set(sideStartX, sideStartY, sideStartX + AndroidUtilities.dp(32), sideStartY + AndroidUtilities.dp(32)); - applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, getX(), viewTop); - canvas.drawRoundRect(rect, AndroidUtilities.dp(16), AndroidUtilities.dp(16), getThemedPaint(sideButtonPressed ? Theme.key_paint_chatActionBackgroundSelected : Theme.key_paint_chatActionBackground)); - if (hasGradientService()) { - canvas.drawRoundRect(rect, AndroidUtilities.dp(16), AndroidUtilities.dp(16), Theme.chat_actionBackgroundGradientDarkenPaint); - } - - if (drawSideButton == 2) { - Drawable goIconDrawable = getThemedDrawable(Theme.key_drawable_goIcon); - if (currentMessageObject.isOutOwner()) { - setDrawableBounds(goIconDrawable, sideStartX + AndroidUtilities.dp(10), sideStartY + AndroidUtilities.dp(9)); - canvas.save(); - canvas.scale(-1, 1, goIconDrawable.getBounds().centerX(), goIconDrawable.getBounds().centerY()); - } else { - setDrawableBounds(goIconDrawable, sideStartX + AndroidUtilities.dp(12), sideStartY + AndroidUtilities.dp(9)); - } - goIconDrawable.draw(canvas); - if (currentMessageObject.isOutOwner()) { - canvas.restore(); - } - } else { - Drawable drawable = getThemedDrawable(Theme.key_drawable_shareIcon); - setDrawableBounds(drawable, sideStartX + AndroidUtilities.dp(8), sideStartY + AndroidUtilities.dp(9)); - drawable.draw(canvas); - } - } - } + } - if (replyNameLayout != null) { - if (currentMessageObject.shouldDrawWithoutBackground()) { - if (currentMessageObject.isOutOwner()) { - replyStartX = AndroidUtilities.dp(23); - if (isPlayingRound) { - replyStartX -= (AndroidUtilities.roundPlayingMessageSize - AndroidUtilities.roundMessageSize); - } - } else if (currentMessageObject.type == MessageObject.TYPE_ROUND_VIDEO) { - replyStartX = backgroundDrawableLeft + backgroundDrawableRight + AndroidUtilities.dp(4); - } else { - replyStartX = backgroundDrawableLeft + backgroundDrawableRight + AndroidUtilities.dp(17); - } - replyStartY = AndroidUtilities.dp(12); + public boolean drawBackgroundInParent() { + if (canDrawBackgroundInParent && currentMessageObject != null && currentMessageObject.isOutOwner()) { + if (resourcesProvider != null) { + return resourcesProvider.getCurrentColor(Theme.key_chat_outBubbleGradient1) != null; } else { - if (currentMessageObject.isOutOwner()) { - replyStartX = backgroundDrawableLeft + AndroidUtilities.dp(12) + getExtraTextX(); - } else { - if (mediaBackground) { - replyStartX = backgroundDrawableLeft + AndroidUtilities.dp(12) + getExtraTextX(); - } else { - replyStartX = backgroundDrawableLeft + AndroidUtilities.dp(drawPinnedBottom ? 12 : 18) + getExtraTextX(); - } - } - replyStartY = AndroidUtilities.dp(12 + (drawForwardedName && forwardedNameLayout[0] != null ? 36 : 0) + (drawNameLayout && nameLayout != null ? 20 : 0)); - } - } - if (currentPosition == null && !transitionParams.animateBackgroundBoundsInner && !(enterTransitionInPorgress && !currentMessageObject.isVoice())) { - drawNamesLayout(canvas, 1f); - } - - if ((!autoPlayingMedia || !MediaController.getInstance().isPlayingMessageAndReadyToDraw(currentMessageObject) || isRoundVideo) && !transitionParams.animateBackgroundBoundsInner) { - drawOverlays(canvas); - } - if ((drawTime || !mediaBackground) && !forceNotDrawTime && !transitionParams.animateBackgroundBoundsInner && !(enterTransitionInPorgress && !currentMessageObject.isVoice())) { - drawTime(canvas, 1f, false); - } - - if ((controlsAlpha != 1.0f || timeAlpha != 1.0f) && currentMessageObject.type != 5) { - long newTime = System.currentTimeMillis(); - long dt = Math.abs(lastControlsAlphaChangeTime - newTime); - if (dt > 17) { - dt = 17; - } - totalChangeTime += dt; - if (totalChangeTime > 100) { - totalChangeTime = 100; - } - lastControlsAlphaChangeTime = newTime; - if (controlsAlpha != 1.0f) { - controlsAlpha = AndroidUtilities.decelerateInterpolator.getInterpolation(totalChangeTime / 100.0f); - } - if (timeAlpha != 1.0f) { - timeAlpha = AndroidUtilities.decelerateInterpolator.getInterpolation(totalChangeTime / 100.0f); - } - invalidate(); - if (forceNotDrawTime && currentPosition != null && currentPosition.last && getParent() != null) { - View parent = (View) getParent(); - parent.invalidate(); + return Theme.getColorOrNull(Theme.key_chat_outBubbleGradient1) != null; } } - if (restore != Integer.MIN_VALUE) { - canvas.restoreToCount(restore); - } - updateSelectionTextPosition(); + return false; } public void drawCommentButton(Canvas canvas, float alpha) { @@ -10951,7 +10999,7 @@ public void drawBackground(Canvas canvas, int left, int top, int right, int bott } currentBackgroundDrawable.setAlpha((int) (getAlpha() * 255)); currentBackgroundDrawable.setBounds(left, top, right, bottom); - currentBackgroundDrawable.draw(canvas); + currentBackgroundDrawable.drawCached(canvas, backgroundCacheParams); currentBackgroundDrawable.setAlpha(255); } } @@ -11998,6 +12046,9 @@ private void drawTimeInternal(Canvas canvas, float alpha, boolean fromParent, fl } else { if (currentMessageObject.isSponsored()) { timeYOffset = -AndroidUtilities.dp(48); + if (hasNewLineForTime) { + timeYOffset -= AndroidUtilities.dp(16); + } } else { timeYOffset = -(drawCommentButton ? AndroidUtilities.dp(43) : 0); } @@ -13058,7 +13109,7 @@ public void drawOverlays(Canvas canvas) { TLRPC.TL_messageMediaPoll media = (TLRPC.TL_messageMediaPoll) currentMessageObject.messageOwner.media; if (lastPoll.quiz && (pollVoted || pollClosed) && !TextUtils.isEmpty(media.results.solution)) { - Drawable drawable = Theme.chat_pollHintDrawable[currentMessageObject.isOutOwner() ? 1 : 0]; + Drawable drawable = getThemedDrawable(currentMessageObject.isOutOwner() ? Theme.key_drawable_chat_pollHintDrawableOut : Theme.key_drawable_chat_pollHintDrawableIn); if (pollVoteInProgress) { drawable.setAlpha((int) (255 * pollAnimationProgress)); } else { @@ -14397,7 +14448,7 @@ public boolean performAction(int virtualViewId, int action, Bundle arguments) { private ClickableSpan getLinkById(int id, boolean caption) { if (caption) { id -= LINK_CAPTION_IDS_START; - if (!(currentMessageObject.caption instanceof Spannable)) { + if (!(currentMessageObject.caption instanceof Spannable) || id < 0) { return null; } Spannable buffer = (Spannable) currentMessageObject.caption; @@ -14408,7 +14459,7 @@ private ClickableSpan getLinkById(int id, boolean caption) { return links[id]; } else { id -= LINK_IDS_START; - if (!(currentMessageObject.messageText instanceof Spannable)) { + if (!(currentMessageObject.messageText instanceof Spannable) || id < 0) { return null; } Spannable buffer = (Spannable) currentMessageObject.messageText; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java index 19019686be2..9aecac10d9d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -988,7 +988,7 @@ public void buildLayout() { checkMessage = false; messageString = formatArchivedDialogNames(); } else if (message.messageOwner instanceof TLRPC.TL_messageService) { - if (ChatObject.isChannel(chat) && (message.messageOwner.action instanceof TLRPC.TL_messageActionHistoryClear || + if (ChatObject.isChannelAndNotMegaGroup(chat) && (message.messageOwner.action instanceof TLRPC.TL_messageActionHistoryClear || message.messageOwner.action instanceof TLRPC.TL_messageActionChannelMigrateFrom)) { messageString = ""; showChecks = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java index b852b8b4f7f..f73c420f38a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java @@ -109,7 +109,7 @@ public DrawerProfileCell(Context context) { setArrowState(false); sunDrawable = new RLottieDrawable(R.raw.sun, "" + R.raw.sun, AndroidUtilities.dp(28), AndroidUtilities.dp(28), true, null); - if (isCurrentThemeDay()) { + if (Theme.isCurrentThemeDay()) { sunDrawable.setCustomEndFrame(36); } else { sunDrawable.setCustomEndFrame(0); @@ -147,11 +147,11 @@ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { switchingTheme = true; SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE); String dayThemeName = preferences.getString("lastDayTheme", "Blue"); - if (Theme.getTheme(dayThemeName) == null) { + if (Theme.getTheme(dayThemeName) == null || Theme.getTheme(dayThemeName).isDark()) { dayThemeName = "Blue"; } String nightThemeName = preferences.getString("lastDarkTheme", "Dark Blue"); - if (Theme.getTheme(nightThemeName) == null) { + if (Theme.getTheme(nightThemeName) == null || !Theme.getTheme(nightThemeName).isDark()) { nightThemeName = "Dark Blue"; } Theme.ThemeInfo themeInfo = Theme.getActiveTheme(); @@ -196,23 +196,6 @@ private void switchTheme(Theme.ThemeInfo themeInfo, boolean toDark) { NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, themeInfo, false, pos, -1, toDark, darkThemeView); } - private boolean isCurrentThemeDay() { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE); - String dayThemeName = preferences.getString("lastDayTheme", "Blue"); - if (Theme.getTheme(dayThemeName) == null) { - dayThemeName = "Blue"; - } - String nightThemeName = preferences.getString("lastDarkTheme", "Dark Blue"); - if (Theme.getTheme(nightThemeName) == null) { - nightThemeName = "Dark Blue"; - } - Theme.ThemeInfo themeInfo = Theme.getActiveTheme(); - if (dayThemeName.equals(nightThemeName) && themeInfo.isDark()) { - dayThemeName = "Blue"; - } - return dayThemeName.equals(themeInfo.getKey()); - } - @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MemberRequestCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MemberRequestCell.java new file mode 100644 index 00000000000..36a869c94c0 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MemberRequestCell.java @@ -0,0 +1,147 @@ +package org.telegram.ui.Cells; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.util.LongSparseArray; +import android.view.Gravity; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.SimpleTextView; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.BackupImageView; +import org.telegram.ui.Components.LayoutHelper; + +public class MemberRequestCell extends FrameLayout { + + private final AvatarDrawable avatarDrawable = new AvatarDrawable(); + private final BackupImageView avatarImageView = new BackupImageView(getContext()); + private final SimpleTextView nameTextView = new SimpleTextView(getContext()); + private final SimpleTextView statusTextView = new SimpleTextView(getContext()); + + private TLRPC.TL_chatInviteImporter importer; + private boolean isNeedDivider; + + public MemberRequestCell(@NonNull Context context, OnClickListener clickListener, boolean isChannel) { + super(context); + + avatarImageView.setRoundRadius(AndroidUtilities.dp(23)); + addView(avatarImageView, LayoutHelper.createFrame(46, 46, Gravity.START, 12, 8, 12, 0)); + + nameTextView.setGravity(Gravity.START); + nameTextView.setMaxLines(1); + nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + nameTextView.setTextSize(17); + nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP, LocaleController.isRTL ? 12 : 74, 12, LocaleController.isRTL ? 74 : 12, 0)); + + statusTextView.setGravity(Gravity.START); + statusTextView.setMaxLines(1); + statusTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + statusTextView.setTextSize(14); + addView(statusTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP, LocaleController.isRTL ? 12 : 74, 36, LocaleController.isRTL ? 74 : 12, 0)); + + int btnPadding = AndroidUtilities.dp(17); + TextView addButton = new TextView(getContext()); + addButton.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + addButton.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + addButton.setMaxLines(1); + addButton.setPadding(btnPadding, 0, btnPadding, 0); + addButton.setText(isChannel ? LocaleController.getString("AddToChannel", R.string.AddToChannel) : LocaleController.getString("AddToGroup", R.string.AddToGroup)); + addButton.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); + addButton.setTextSize(14); + addButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + addButton.setOnClickListener(v -> { + if (clickListener != null && importer != null) { + clickListener.onAddClicked(importer); + } + }); + addView(addButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 32, Gravity.START, LocaleController.isRTL ? 0 : 73, 62, LocaleController.isRTL ? 73 : 0, 0)); + + float addButtonWidth = addButton.getPaint().measureText(addButton.getText().toString()) + btnPadding * 2; + TextView dismissButton = new TextView(getContext()); + dismissButton.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Color.TRANSPARENT, Theme.getColor(Theme.key_listSelector), 0xff000000)); + dismissButton.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + dismissButton.setMaxLines(1); + dismissButton.setPadding(btnPadding, 0, btnPadding, 0); + dismissButton.setText(LocaleController.getString("Dismiss", R.string.Dismiss)); + dismissButton.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText)); + dismissButton.setTextSize(14); + dismissButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + dismissButton.setOnClickListener(v -> { + if (clickListener != null && importer != null) { + clickListener.onDismissClicked(importer); + } + }); + FrameLayout.LayoutParams dismissLayoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, AndroidUtilities.dp(32)); + dismissLayoutParams.topMargin = AndroidUtilities.dp(62); + dismissLayoutParams.leftMargin = LocaleController.isRTL ? 0 : (int)(addButtonWidth + AndroidUtilities.dp(73 + 6)); + dismissLayoutParams.rightMargin = LocaleController.isRTL ? (int)(addButtonWidth + AndroidUtilities.dp(73 + 6)) : 0; + addView(dismissButton, dismissLayoutParams); + } + + public void setData(LongSparseArray users, TLRPC.TL_chatInviteImporter importer, boolean isNeedDivider) { + this.importer = importer; + this.isNeedDivider = isNeedDivider; + setWillNotDraw(!isNeedDivider); + + TLRPC.User user = users.get(importer.user_id); + avatarDrawable.setInfo(user); + avatarImageView.setForUserOrChat(user, avatarDrawable); + nameTextView.setText(UserObject.getUserName(user)); + String dateText = LocaleController.formatDateAudio(importer.date, false); + if (importer.approved_by == 0) { + statusTextView.setText(LocaleController.formatString("RequestedToJoinAt", R.string.RequestedToJoinAt, dateText)); + } else { + TLRPC.User approvedByUser = users.get(importer.approved_by); + if (approvedByUser != null) { + statusTextView.setText(LocaleController.formatString("AddedBy", R.string.AddedBy, UserObject.getFirstName(approvedByUser), dateText)); + } else { + statusTextView.setText(""); + } + } + } + + public TLRPC.TL_chatInviteImporter getImporter() { + return importer; + } + + public BackupImageView getAvatarImageView() { + return avatarImageView; + } + + public String getStatus() { + return statusTextView.getText().toString(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(107), MeasureSpec.EXACTLY)); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (isNeedDivider) { + canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(72), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(72) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); + } + } + + + public interface OnClickListener { + + void onAddClicked(TLRPC.TL_chatInviteImporter importer); + + void onDismissClicked(TLRPC.TL_chatInviteImporter importer); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PatternCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PatternCell.java index bdafa19d4e2..f15f61abcb2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PatternCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PatternCell.java @@ -174,7 +174,7 @@ private void updateButtonState(Object image, boolean ifSame, boolean animated) { @Override protected void onDraw(Canvas canvas) { float intensity = delegate.getIntensity(); - imageReceiver.setAlpha(Math.abs(intensity)); + //imageReceiver.setAlpha(Math.abs(intensity)); imageReceiver.setBlendMode(null); int backgroundColor = delegate.getBackgroundColor(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java index 479c77c9eb2..88b7df337c3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java @@ -32,6 +32,7 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.DotDividerSpan; +import org.telegram.ui.Components.FlickerLoadingView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.MediaActionDrawable; import org.telegram.ui.Components.RadialProgress2; @@ -381,48 +382,6 @@ public void didPressedButton() { } } - @Override - protected void onDraw(Canvas canvas) { - if (viewType == VIEW_TYPE_GLOBAL_SEARCH) { - description2TextPaint.setColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText3)); - } - if (dateLayout != null) { - canvas.save(); - canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline) + (LocaleController.isRTL ? 0 : dateLayoutX), titleY); - dateLayout.draw(canvas); - canvas.restore(); - } - - if (titleLayout != null) { - canvas.save(); - canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline) + (LocaleController.isRTL && dateLayout != null ? dateLayout.getWidth() + AndroidUtilities.dp(4) : 0), titleY); - titleLayout.draw(canvas); - canvas.restore(); - } - - if (captionLayout != null) { - captionTextPaint.setColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); - canvas.save(); - canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), captionY); - captionLayout.draw(canvas); - canvas.restore(); - } - - if (descriptionLayout != null) { - Theme.chat_contextResult_descriptionTextPaint.setColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText2)); - canvas.save(); - canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), descriptionY); - descriptionLayout.draw(canvas); - canvas.restore(); - } - - radialProgress.setProgressColor(getThemedColor(buttonPressed ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress)); - radialProgress.draw(canvas); - - if (needDivider) { - canvas.drawLine(AndroidUtilities.dp(72), getHeight() - 1, getWidth() - getPaddingRight(), getHeight() - 1, Theme.dividerPaint); - } - } private int getMiniIconForCurrentState() { if (miniButtonState < 0) { @@ -582,5 +541,80 @@ private int getThemedColor(String key) { Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null; return color != null ? color : Theme.getColor(key); } + + float enterAlpha = 1f; + FlickerLoadingView globalGradientView; + public void setGlobalGradientView(FlickerLoadingView globalGradientView) { + this.globalGradientView = globalGradientView; + } + + @Override + protected void dispatchDraw(Canvas canvas) { + if (enterAlpha != 1f && globalGradientView != null) { + canvas.saveLayerAlpha(0, 0, getMeasuredWidth(), getMeasuredHeight(), (int) ((1f - enterAlpha) * 255), Canvas.ALL_SAVE_FLAG); + globalGradientView.setViewType(FlickerLoadingView.AUDIO_TYPE); + globalGradientView.updateColors(); + globalGradientView.updateGradient(); + globalGradientView.draw(canvas); + canvas.restore(); + canvas.saveLayerAlpha(0, 0, getMeasuredWidth(), getMeasuredHeight(), (int) (enterAlpha * 255), Canvas.ALL_SAVE_FLAG); + drawInternal(canvas); + super.dispatchDraw(canvas); + canvas.restore(); + } else { + drawInternal(canvas); + super.dispatchDraw(canvas); + + } + } + + private void drawInternal(Canvas canvas) { + if (viewType == VIEW_TYPE_GLOBAL_SEARCH) { + description2TextPaint.setColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText3)); + } + if (dateLayout != null) { + canvas.save(); + canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline) + (LocaleController.isRTL ? 0 : dateLayoutX), titleY); + dateLayout.draw(canvas); + canvas.restore(); + } + + if (titleLayout != null) { + canvas.save(); + canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline) + (LocaleController.isRTL && dateLayout != null ? dateLayout.getWidth() + AndroidUtilities.dp(4) : 0), titleY); + titleLayout.draw(canvas); + canvas.restore(); + } + + if (captionLayout != null) { + captionTextPaint.setColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); + canvas.save(); + canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), captionY); + captionLayout.draw(canvas); + canvas.restore(); + } + + if (descriptionLayout != null) { + Theme.chat_contextResult_descriptionTextPaint.setColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText2)); + canvas.save(); + canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), descriptionY); + descriptionLayout.draw(canvas); + canvas.restore(); + } + + radialProgress.setProgressColor(getThemedColor(buttonPressed ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress)); + radialProgress.draw(canvas); + + if (needDivider) { + canvas.drawLine(AndroidUtilities.dp(72), getHeight() - 1, getWidth() - getPaddingRight(), getHeight() - 1, Theme.dividerPaint); + } + } + + public void setEnterAnimationAlpha(float alpha) { + if (enterAlpha != alpha) { + this.enterAlpha = alpha; + invalidate(); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java index 9e034a3f90f..3d00c145361 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java @@ -45,6 +45,7 @@ import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.DotDividerSpan; +import org.telegram.ui.Components.FlickerLoadingView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LineProgressView; import org.telegram.ui.Components.RLottieDrawable; @@ -89,6 +90,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle private CharSequence caption; private RLottieDrawable statusDrawable; private final Theme.ResourcesProvider resourcesProvider; + FlickerLoadingView globalGradientView; public SharedDocumentCell(Context context) { this(context, VIEW_TYPE_DEFAULT); @@ -190,7 +192,7 @@ protected void onDraw(Canvas canvas) { addView(captionTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 8 : 72, 30, LocaleController.isRTL ? 72 : 8, 0)); captionTextView.setVisibility(View.GONE); } else { - nameTextView.setMaxLines(2); + nameTextView.setMaxLines(1); addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 8 : 72, 5, LocaleController.isRTL ? 72 : 8, 0)); } @@ -563,9 +565,11 @@ public BackupImageView getImageView() { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (viewType == VIEW_TYPE_PICKER) { super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(64) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY)); + } else if (viewType == VIEW_TYPE_DEFAULT) { + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(56), MeasureSpec.EXACTLY)); } else { super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(56), MeasureSpec.EXACTLY)); - int h = AndroidUtilities.dp(5 + 29) + nameTextView.getMeasuredHeight() + (needDivider ? 1 : 0); + int h = AndroidUtilities.dp(5 + 29) + nameTextView.getMeasuredHeight() + (needDivider ? 1 : 0); if (caption != null && captionTextView != null && message.hasHighlightedWords()) { ignoreRequestLayout = true; captionTextView.setText(AndroidUtilities.ellipsizeCenterEnd(caption, message.highlightedWords.get(0), captionTextView.getMeasuredWidth(), captionTextView.getPaint(), 130)); @@ -601,12 +605,6 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto } } - @Override - protected void onDraw(Canvas canvas) { - if (needDivider) { - canvas.drawLine(AndroidUtilities.dp(72), getHeight() - 1, getWidth() - getPaddingRight(), getHeight() - 1, Theme.dividerPaint); - } - } @Override public void onFailedDownload(String name, boolean canceled) { @@ -650,4 +648,42 @@ private int getThemedColor(String key) { Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null; return color != null ? color : Theme.getColor(key); } + + float enterAlpha = 1f; + + public void setGlobalGradientView(FlickerLoadingView globalGradientView) { + this.globalGradientView = globalGradientView; + } + + @Override + protected void dispatchDraw(Canvas canvas) { + if (enterAlpha != 1f && globalGradientView != null) { + canvas.saveLayerAlpha(0, 0, getMeasuredWidth(), getMeasuredHeight(), (int) ((1f - enterAlpha) * 255), Canvas.ALL_SAVE_FLAG); + globalGradientView.setViewType(FlickerLoadingView.FILES_TYPE); + globalGradientView.updateColors(); + globalGradientView.updateGradient(); + globalGradientView.draw(canvas); + canvas.restore(); + canvas.saveLayerAlpha(0, 0, getMeasuredWidth(), getMeasuredHeight(), (int) (enterAlpha * 255), Canvas.ALL_SAVE_FLAG); + super.dispatchDraw(canvas); + drawDivider(canvas); + canvas.restore(); + } else { + super.dispatchDraw(canvas); + drawDivider(canvas); + } + } + + private void drawDivider(Canvas canvas) { + if (needDivider) { + canvas.drawLine(AndroidUtilities.dp(72), getHeight() - 1, getWidth() - getPaddingRight(), getHeight() - 1, Theme.dividerPaint); + } + } + + public void setEnterAnimationAlpha(float alpha) { + if (enterAlpha != alpha) { + this.enterAlpha = alpha; + invalidate(); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java new file mode 100644 index 00000000000..fdf67d6b4e5 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java @@ -0,0 +1,467 @@ +package org.telegram.ui.Cells; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.drawable.Drawable; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.text.TextUtils; +import android.util.SparseArray; +import android.view.Gravity; +import android.view.View; + +import androidx.core.content.ContextCompat; +import androidx.core.graphics.ColorUtils; + +import com.google.android.exoplayer2.util.Log; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.DownloadController; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.CheckBox2; +import org.telegram.ui.Components.CheckBoxBase; +import org.telegram.ui.Components.FlickerLoadingView; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.PhotoViewer; + +public class SharedPhotoVideoCell2 extends View { + + + public ImageReceiver imageReceiver = new ImageReceiver(); + int currentAccount; + MessageObject currentMessageObject; + int currentParentColumnsCount; + FlickerLoadingView globalGradientView; + SharedPhotoVideoCell2 crossfadeView; + float imageAlpha = 1f; + float imageScale = 1f; + boolean showVideoLayout; + StaticLayout videoInfoLayot; + String videoText; + CheckBoxBase checkBoxBase; + SharedResources sharedResources; + private boolean attached; + float crossfadeProgress; + float crossfadeToColumnsCount; + float highlightProgress; + + static long lastUpdateDownloadSettingsTime; + static boolean lastAutoDownload; + + public SharedPhotoVideoCell2(Context context, SharedResources sharedResources, int currentAccount) { + super(context); + this.sharedResources = sharedResources; + this.currentAccount = currentAccount; + + setChecked(false, false); + imageReceiver.setParentView(this); + } + + + public void setMessageObject(MessageObject messageObject, int parentColumnsCount) { + int oldParentColumsCount = currentParentColumnsCount; + currentParentColumnsCount = parentColumnsCount; + if (currentMessageObject == null && messageObject == null) { + return; + } + if (currentMessageObject != null && messageObject != null && currentMessageObject.getId() == messageObject.getId() && oldParentColumsCount == parentColumnsCount) { + return; + } + currentMessageObject = messageObject; + if (messageObject == null) { + imageReceiver.onDetachedFromWindow(); + videoText = null; + videoInfoLayot = null; + showVideoLayout = false; + return; + } else { + if (attached) { + imageReceiver.onAttachedToWindow(); + } + } + String restrictionReason = MessagesController.getRestrictionReason(messageObject.messageOwner.restriction_reason); + String imageFilter; + int stride; + int width = (int) (AndroidUtilities.displaySize.x / parentColumnsCount / AndroidUtilities.density); + imageFilter = sharedResources.getFilterString(width); + boolean showImageStub = false; + if (parentColumnsCount <= 2) { + stride = AndroidUtilities.getPhotoSize(); + } else if (parentColumnsCount == 3) { + stride = 320; + } else if (parentColumnsCount == 5) { + stride = 320; + } else { + stride = 320; + } + videoText = null; + videoInfoLayot = null; + showVideoLayout = false; + if (!TextUtils.isEmpty(restrictionReason)) { + showImageStub = true; + } else if (messageObject.isVideo()) { + showVideoLayout = true; + if (parentColumnsCount != 9) { + videoText = AndroidUtilities.formatShortDuration(messageObject.getDuration()); + } + if (messageObject.mediaThumb != null) { + if (messageObject.strippedThumb != null) { + imageReceiver.setImage(messageObject.mediaThumb, imageFilter, messageObject.strippedThumb, null, messageObject, 0); + } else { + imageReceiver.setImage(messageObject.mediaThumb, imageFilter, messageObject.mediaSmallThumb, imageFilter + "_b", null, 0, null, messageObject, 0); + } + } else { + TLRPC.Document document = messageObject.getDocument(); + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 50); + TLRPC.PhotoSize qualityThumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, stride); + if (thumb == qualityThumb) { + qualityThumb = null; + } + if (thumb != null) { + if (messageObject.strippedThumb != null) { + imageReceiver.setImage(ImageLocation.getForDocument(qualityThumb, document), imageFilter, messageObject.strippedThumb, null, messageObject, 0); + } else { + imageReceiver.setImage(ImageLocation.getForDocument(qualityThumb, document), imageFilter, ImageLocation.getForDocument(thumb, document), imageFilter + "_b", null, 0, null, messageObject, 0); + } + } else { + showImageStub = true; + } + } + } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && messageObject.messageOwner.media.photo != null && !messageObject.photoThumbs.isEmpty()) { + if (messageObject.mediaExists || canAutoDownload(messageObject)) { + if (messageObject.mediaThumb != null) { + if (messageObject.strippedThumb != null) { + imageReceiver.setImage(messageObject.mediaThumb, imageFilter, messageObject.strippedThumb, null, messageObject, 0); + } else { + imageReceiver.setImage(messageObject.mediaThumb, imageFilter, messageObject.mediaSmallThumb, imageFilter + "_b", null, 0, null, messageObject, 0); + } + } else { + TLRPC.PhotoSize currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 50); + TLRPC.PhotoSize currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, stride, false, currentPhotoObjectThumb, false); + if (currentPhotoObject == currentPhotoObjectThumb) { + currentPhotoObjectThumb = null; + } + if (messageObject.strippedThumb != null) { + imageReceiver.setImage(ImageLocation.getForObject(currentPhotoObject, messageObject.photoThumbsObject), imageFilter, null, null, messageObject.strippedThumb, currentPhotoObject != null ? currentPhotoObject.size : 0, null, messageObject, messageObject.shouldEncryptPhotoOrVideo() ? 2 : 1); + } else { + imageReceiver.setImage(ImageLocation.getForObject(currentPhotoObject, messageObject.photoThumbsObject), imageFilter, ImageLocation.getForObject(currentPhotoObjectThumb, messageObject.photoThumbsObject), imageFilter + "_b", currentPhotoObject != null ? currentPhotoObject.size : 0, null, messageObject, messageObject.shouldEncryptPhotoOrVideo() ? 2 : 1); + } + } + } else { + if (messageObject.strippedThumb != null) { + imageReceiver.setImage(null, null, null, null, messageObject.strippedThumb, 0, null, messageObject, 0); + } else { + imageReceiver.clearImage(); + } + } + } else { + showImageStub = true; + } + + if (showImageStub) { + imageReceiver.setImageBitmap(ContextCompat.getDrawable(getContext(), R.drawable.photo_placeholder_in)); + } + invalidate(); + } + + + private boolean canAutoDownload(MessageObject messageObject) { + if (System.currentTimeMillis() - lastUpdateDownloadSettingsTime > 5000) { + lastUpdateDownloadSettingsTime = System.currentTimeMillis(); + lastAutoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(messageObject); + } + return lastAutoDownload; + } + + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + float padding; + if (crossfadeProgress != 0 && (crossfadeToColumnsCount == 9 || currentParentColumnsCount == 9)) { + if (crossfadeToColumnsCount == 9) { + padding = AndroidUtilities.dp(0.5f) * crossfadeProgress + AndroidUtilities.dpf2(1) * (1f - crossfadeProgress); + } else { + padding = AndroidUtilities.dp(1f) * crossfadeProgress + AndroidUtilities.dpf2(0.5f) * (1f - crossfadeProgress); + } + } else { + padding = currentParentColumnsCount == 9 ? AndroidUtilities.dpf2(0.5f) : AndroidUtilities.dpf2(1); + } + + float imageWidth = (getMeasuredWidth() - padding * 2) * imageScale; + float imageHeight = (getMeasuredHeight() - padding * 2) * imageScale; + + if (crossfadeProgress > 0.5f && crossfadeToColumnsCount != 9 && currentParentColumnsCount != 9) { + imageWidth -= 2; + imageHeight -= 2; + } + + if (currentMessageObject == null || !imageReceiver.hasBitmapImage() || imageReceiver.getCurrentAlpha() != 1.0f || imageAlpha != 1f) { + if (SharedPhotoVideoCell2.this.getParent() != null) { + globalGradientView.setParentSize(((View) SharedPhotoVideoCell2.this.getParent()).getMeasuredWidth(), SharedPhotoVideoCell2.this.getMeasuredHeight(), -getX()); + globalGradientView.updateColors(); + globalGradientView.updateGradient(); + float localPadding = padding; + if (crossfadeProgress > 0.5f && crossfadeToColumnsCount != 9 && currentParentColumnsCount != 9) { + localPadding += 1; + } + canvas.drawRect(localPadding, localPadding, localPadding + imageWidth, localPadding + imageHeight, globalGradientView.getPaint()); + } + invalidate(); + } + if (currentMessageObject == null) { + return; + } + + if (imageAlpha != 1f) { + canvas.saveLayerAlpha(0,0, padding * 2 + imageWidth, padding * 2 + imageHeight, (int) (255 * imageAlpha), Canvas.ALL_SAVE_FLAG); + } else { + canvas.save(); + } + + if ((checkBoxBase != null && checkBoxBase.isChecked()) || PhotoViewer.isShowingImage(currentMessageObject)) { + canvas.drawRect(padding, padding, imageWidth, imageHeight, sharedResources.backgroundPaint); + } + if (currentMessageObject != null) { + if (checkBoxProgress > 0) { + float offset = AndroidUtilities.dp(10) * checkBoxProgress; + imageReceiver.setImageCoords(padding + offset, padding + offset, imageWidth - offset * 2, imageHeight - offset * 2); + } else { + float localPadding = padding; + if (crossfadeProgress > 0.5f && crossfadeToColumnsCount != 9 && currentParentColumnsCount != 9) { + localPadding += 1; + } + imageReceiver.setImageCoords(localPadding, localPadding, imageWidth, imageHeight); + } + if (!PhotoViewer.isShowingImage(currentMessageObject)) { + imageReceiver.draw(canvas); + if (highlightProgress > 0) { + sharedResources.highlightPaint.setColor(ColorUtils.setAlphaComponent(Color.BLACK, (int) (0.5f * highlightProgress * 255))); + canvas.drawRect(imageReceiver.getDrawRegion(), sharedResources.highlightPaint); + } + } + } + if (showVideoLayout) { + canvas.save(); + canvas.clipRect(padding, padding, padding + imageWidth, padding + imageHeight); + if (currentParentColumnsCount != 9 && videoInfoLayot == null && videoText != null) { + int textWidth = (int) Math.ceil(sharedResources.textPaint.measureText(videoText)); + videoInfoLayot = new StaticLayout(videoText, sharedResources.textPaint, textWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + } + int width; + if (videoInfoLayot == null) { + width = AndroidUtilities.dp(17); + } else { + width = AndroidUtilities.dp(14) + videoInfoLayot.getWidth() + AndroidUtilities.dp(4); + } + canvas.translate(AndroidUtilities.dp(5), AndroidUtilities.dp(1) + imageHeight - AndroidUtilities.dp(17) - AndroidUtilities.dp(4)); + AndroidUtilities.rectTmp.set(0, 0, width, AndroidUtilities.dp(17)); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(4), AndroidUtilities.dp(4), Theme.chat_timeBackgroundPaint); + canvas.save(); + canvas.translate(videoInfoLayot == null ? AndroidUtilities.dp(5) : AndroidUtilities.dp(4), (AndroidUtilities.dp(17) - sharedResources.playDrawable.getIntrinsicHeight()) / 2f); + sharedResources.playDrawable.setAlpha((int) (255 * imageAlpha)); + sharedResources.playDrawable.draw(canvas); + canvas.restore(); + if (videoInfoLayot != null) { + canvas.translate(AndroidUtilities.dp(14), (AndroidUtilities.dp(17) - videoInfoLayot.getHeight()) / 2f); + videoInfoLayot.draw(canvas); + } + canvas.restore(); + } + + if (checkBoxBase != null && checkBoxBase.getProgress() != 0) { + canvas.save(); + canvas.translate(imageWidth + AndroidUtilities.dp(2) - AndroidUtilities.dp(25), 0); + checkBoxBase.draw(canvas); + canvas.restore(); + } + canvas.restore(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + attached = true; + if (checkBoxBase != null) { + checkBoxBase.onAttachedToWindow(); + } + if (currentMessageObject != null) { + imageReceiver.onAttachedToWindow(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + attached = false; + if (checkBoxBase != null) { + checkBoxBase.onDetachedFromWindow(); + } + if (currentMessageObject != null) { + imageReceiver.onDetachedFromWindow(); + } + } + + public void setGradientView(FlickerLoadingView globalGradientView) { + this.globalGradientView = globalGradientView; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY)); + } + + public int getMessageId() { + return currentMessageObject != null ? currentMessageObject.getId() : 0; + } + + public MessageObject getMessageObject() { + return currentMessageObject; + } + + public void setImageAlpha(float alpha, boolean invalidate) { + if (this.imageAlpha != alpha) { + this.imageAlpha = alpha; + if (invalidate) { + invalidate(); + } + } + } + + public void setImageScale(float scale, boolean invalidate) { + if (this.imageScale != scale) { + this.imageScale = scale; + if (invalidate) { + invalidate(); + } + } + } + + public void setCrossfadeView(SharedPhotoVideoCell2 cell, float crossfadeProgress, int crossfadeToColumnsCount) { + crossfadeView = cell; + this.crossfadeProgress = crossfadeProgress; + this.crossfadeToColumnsCount = crossfadeToColumnsCount; + } + + public void drawCrossafadeImage(Canvas canvas) { + if (crossfadeView != null) { + canvas.save(); + canvas.translate(getX(), getY()); + float scale = ((getMeasuredWidth() - AndroidUtilities.dp(2)) * imageScale) / (float) (crossfadeView.getMeasuredWidth() - AndroidUtilities.dp(2)); + crossfadeView.setImageScale(scale, false); + crossfadeView.draw(canvas); + canvas.restore(); + } + } + + public View getCrossfadeView() { + return crossfadeView; + } + + ValueAnimator animator; + float checkBoxProgress; + + public void setChecked(final boolean checked, boolean animated) { + boolean currentIsChecked = checkBoxBase != null && checkBoxBase.isChecked(); + if (currentIsChecked == checked) { + return; + } + if (checkBoxBase == null) { + checkBoxBase = new CheckBoxBase(this,21, null); + checkBoxBase.setColor(null, Theme.key_sharedMedia_photoPlaceholder, Theme.key_checkboxCheck); + checkBoxBase.setDrawUnchecked(false); + checkBoxBase.setBackgroundType(1); + checkBoxBase.setBounds(0, 0, AndroidUtilities.dp(24), AndroidUtilities.dp(24)); + if (attached) { + checkBoxBase.onAttachedToWindow(); + } + } + checkBoxBase.setChecked(checked, animated); + if (animator != null) { + ValueAnimator animatorFinal = animator; + animator = null; + animatorFinal.cancel(); + } + if (animated) { + animator = ValueAnimator.ofFloat(checkBoxProgress, checked ? 1f : 0); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + checkBoxProgress = (float) valueAnimator.getAnimatedValue(); + invalidate(); + } + }); + animator.setDuration(200); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (animator != null && animator.equals(animation)) { + checkBoxProgress = checked ? 1f : 0; + animator = null; + } + } + }); + animator.start(); + } else { + checkBoxProgress = checked ? 1f : 0; + } + invalidate(); + } + + public void startHighlight() { + + } + + public void setHighlightProgress(float p) { + if (highlightProgress != p) { + highlightProgress = p; + invalidate(); + } + } + + public void moveImageToFront() { + imageReceiver.moveImageToFront(); + } + + public static class SharedResources { + TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + private Paint backgroundPaint = new Paint(); + Drawable playDrawable; + Paint highlightPaint = new Paint(); + SparseArray imageFilters = new SparseArray<>(); + + public SharedResources(Context context) { + textPaint.setTextSize(AndroidUtilities.dp(12)); + textPaint.setColor(Color.WHITE); + textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + playDrawable = ContextCompat.getDrawable(context, R.drawable.play_mini_video); + playDrawable.setBounds(0, 0, playDrawable.getIntrinsicWidth(), playDrawable.getIntrinsicHeight()); + backgroundPaint.setColor(Theme.getColor(Theme.key_sharedMedia_photoPlaceholder)); + } + + public String getFilterString(int width) { + String str = imageFilters.get(width); + if (str == null) { + str = width + "_" + width + "_isc"; + imageFilters.put(width, str); + } + return str; + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java index cd92fdb5afa..45bad59d66d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java @@ -23,6 +23,7 @@ import org.telegram.messenger.LocaleController; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; public class TextCell extends FrameLayout { @@ -34,7 +35,7 @@ public class TextCell extends FrameLayout { private int leftPadding; private boolean needDivider; private int offsetFromImage = 71; - private int imageLeft = 21; + public int imageLeft = 21; private boolean inDialogs; public TextCell(Context context) { @@ -80,7 +81,7 @@ public SimpleTextView getTextView() { return textView; } - public ImageView getImageView() { + public RLottieImageView getImageView() { return imageView; } @@ -179,7 +180,11 @@ public void setTextAndIcon(String text, Drawable drawable, boolean divider) { textView.setText(text); valueTextView.setText(null); imageView.setColorFilter(null); - imageView.setImageDrawable(drawable); + if (drawable instanceof RLottieDrawable) { + imageView.setAnimation((RLottieDrawable) drawable); + } else { + imageView.setImageDrawable(drawable); + } imageView.setVisibility(VISIBLE); valueTextView.setVisibility(GONE); valueImageView.setVisibility(GONE); @@ -246,4 +251,12 @@ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { } } } + + public void setNeedDivider(boolean needDivider) { + if (this.needDivider != needDivider) { + this.needDivider = needDivider; + setWillNotDraw(!needDivider); + invalidate(); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemesHorizontalListCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemesHorizontalListCell.java index 302603e8b1f..b6c9409aeab 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemesHorizontalListCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemesHorizontalListCell.java @@ -45,6 +45,7 @@ import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.EmojiThemes; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.MotionBackgroundDrawable; @@ -64,7 +65,7 @@ public class ThemesHorizontalListCell extends RecyclerListView implements NotificationCenter.NotificationCenterDelegate { - private static byte[] bytes = new byte[1024]; + public static byte[] bytes = new byte[1024]; private boolean drawDivider; private LinearLayoutManager horizontalLayoutManager; @@ -73,7 +74,7 @@ public class ThemesHorizontalListCell extends RecyclerListView implements Notifi private Theme.ThemeInfo prevThemeInfo; private ThemesListAdapter adapter; - private ArrayList darkThemes; + private ArrayList customThemes; private ArrayList defaultThemes; private int currentType; private int prevCount; @@ -104,7 +105,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (position < defaultThemes.size()) { arrayList = defaultThemes; } else { - arrayList = darkThemes; + arrayList = customThemes; p -= defaultThemes.size(); } view.setTheme(arrayList.get(p), position == getItemCount() - 1, position == 0); @@ -112,7 +113,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { @Override public int getItemCount() { - return prevCount = defaultThemes.size() + darkThemes.size(); + return prevCount = defaultThemes.size() + customThemes.size(); } } @@ -683,10 +684,10 @@ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { } } - public ThemesHorizontalListCell(Context context, int type, ArrayList def, ArrayList dark) { + public ThemesHorizontalListCell(Context context, int type, ArrayList def, ArrayList custom) { super(context); - darkThemes = dark; + customThemes = custom; defaultThemes = def; currentType = type; @@ -738,11 +739,11 @@ public void selectTheme(Theme.ThemeInfo themeInfo) { if (!TextUtils.isEmpty(themeInfo.assetName)) { Theme.PatternsLoader.createLoader(false); } - if (currentType != ThemeActivity.THEME_TYPE_OTHER) { - SharedPreferences.Editor editor = ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE).edit(); - editor.putString(currentType == ThemeActivity.THEME_TYPE_NIGHT || themeInfo.isDark() ? "lastDarkTheme" : "lastDayTheme", themeInfo.getKey()); - editor.commit(); - } + + SharedPreferences.Editor editor = ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE).edit(); + editor.putString(currentType == ThemeActivity.THEME_TYPE_NIGHT || themeInfo.isDark() ? "lastDarkTheme" : "lastDayTheme", themeInfo.getKey()); + editor.commit(); + if (currentType == ThemeActivity.THEME_TYPE_NIGHT) { if (themeInfo == Theme.getCurrentNightTheme()) { return; @@ -763,6 +764,7 @@ public void selectTheme(Theme.ThemeInfo themeInfo) { ((InnerThemeView) child).updateCurrentThemeCheck(); } } + EmojiThemes.saveCustomTheme(themeInfo, themeInfo.currentAccentId); } public void setDrawDivider(boolean draw) { @@ -922,7 +924,7 @@ public void scrollToCurrentTheme(int width, boolean animated) { prevThemeInfo = currentType == ThemeActivity.THEME_TYPE_NIGHT ? Theme.getCurrentNightTheme() : Theme.getCurrentTheme(); int index = defaultThemes.indexOf(prevThemeInfo); if (index < 0) { - index = darkThemes.indexOf(prevThemeInfo) + defaultThemes.size(); + index = customThemes.indexOf(prevThemeInfo) + defaultThemes.size(); if (index < 0) { return; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 5312ad5cc99..37652bd6fbe 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -149,7 +149,7 @@ import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; -import org.telegram.ui.ActionBar.ChatTheme; +import org.telegram.ui.ActionBar.EmojiThemes; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; @@ -235,6 +235,7 @@ import org.telegram.ui.Components.UndoView; import org.telegram.ui.Components.ViewHelper; import org.telegram.ui.Components.voip.VoIPHelper; +import org.telegram.ui.Delegates.ChatActivityMemberRequestsDelegate; import java.io.BufferedWriter; import java.io.File; @@ -749,6 +750,7 @@ public void run() { private boolean isPauseOnThemePreview; private ChatThemeBottomSheet chatThemeBottomSheet; private ThemeDelegate themeDelegate; + private ChatActivityMemberRequestsDelegate pendingRequestsDelegate; private final static int[] allowedNotificationsDuringChatListAnimations = new int[]{ NotificationCenter.messagesRead, @@ -1897,7 +1899,7 @@ protected Theme.ResourcesProvider getResourcesProvider() { if (chatMessageCellsCache.isEmpty()) { for (int a = 0; a < 15; a++) { - chatMessageCellsCache.add(new ChatMessageCell(context, themeDelegate)); + chatMessageCellsCache.add(new ChatMessageCell(context, true, themeDelegate)); } } for (int a = 1; a >= 0; a--) { @@ -2128,10 +2130,16 @@ public void onAutoDeleteHistory(int ttl, int action) { updatePinnedMessageView(true); updateVisibleRows(); } else if (id == chat_menu_attach) { - if (chatAttachAlert != null) { - chatAttachAlert.setEditingMessageObject(null); - } - openAttachMenu(); + ActionBarMenuSubItem attach = new ActionBarMenuSubItem(context, false, true, true, getResourceProvider()); + attach.setTextAndIcon(LocaleController.getString("AttachMenu", R.string.AttachMenu), R.drawable.input_attach); + attach.setOnClickListener(view -> { + headerItem.closeSubMenu(); + if (chatAttachAlert != null) { + chatAttachAlert.setEditingMessageObject(null); + } + openAttachMenu(); + }); + headerItem.toggleSubMenu(attach, attachItem); } else if (id == bot_help) { getSendMessagesHelper().sendMessage("/help", dialog_id, null, null, null, false, null, null, null, true, 0, null); } else if (id == bot_settings) { @@ -2910,7 +2918,6 @@ protected void dispatchDraw(Canvas canvas) { if (child != scrimView && (scrimGroup == null || scrimGroup != group) || child.getAlpha() == 0f) { continue; } - if (!groupedBackgroundWasDraw && cell != null && scrimGroup != null && scrimGroup.transitionParams.cell != null) { float x = scrimGroup.transitionParams.cell.getNonAnimationTranslationX(true); @@ -2970,6 +2977,9 @@ protected void dispatchDraw(Canvas canvas) { } canvas.clipRect(viewClipLeft, viewClipTop, viewClipRight, viewClipBottom); canvas.translate(chatListView.getLeft() + child.getX(), chatListView.getY() + child.getY()); + if (cell != null && scrimGroup == null && cell.drawBackgroundInParent()) { + cell.drawBackgroundInternal(canvas, true); + } child.draw(canvas); canvas.restore(); @@ -4020,7 +4030,6 @@ public void onDraw(Canvas c) { c.translate(0, getMeasuredHeight() - transitionOffset); if (pullingDownDrawable == null) { pullingDownDrawable = new ChatPullingDownDrawable(currentAccount, fragmentView, dialog_id, dialogFolderId, dialogFilterId, themeDelegate); - pullingDownDrawable.showBottomPanel(true); pullingDownDrawable.onAttach(); } pullingDownDrawable.setWidth(getMeasuredWidth()); @@ -4088,6 +4097,18 @@ private void drawChatBackgroundElements(Canvas canvas) { } else if (child instanceof ChatMessageCell) { ChatMessageCell cell = (ChatMessageCell) child; MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); + if (scrimView != cell && group == null && cell.drawBackgroundInParent()) { + canvas.save(); + canvas.translate(cell.getX(), cell.getY()); + if (cell.getScaleX() != 1f) { + canvas.scale( + cell.getScaleX(), cell.getScaleY(), + cell.getPivotX(), (cell.getHeight() >> 1) + ); + } + cell.drawBackgroundInternal(canvas, true); + canvas.restore(); + } if (group != null && group == lastDrawnGroup) { continue; } @@ -4146,6 +4167,15 @@ private void drawChatBackgroundElements(Canvas canvas) { canvas.restore(); } } + } else if (child instanceof ChatActionCell) { + ChatActionCell cell = (ChatActionCell) child; + if (cell.hasGradientService()) { + canvas.save(); + canvas.translate(cell.getX(), cell.getY()); + canvas.scale(cell.getScaleX(), cell.getScaleY(), cell.getMeasuredWidth() / 2f, cell.getMeasuredHeight() / 2f); + cell.drawBackground(canvas, true); + canvas.restore(); + } } } MessageObject.GroupedMessages scrimGroup = null; @@ -5034,8 +5064,8 @@ public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerVi } else { chatListView.setOverScrollMode(View.OVER_SCROLL_NEVER); } - if (pullingDownDrawable != null && chatListView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING) { - pullingDownDrawable.showBottomPanel(pullingDownOffset > 0); + if (pullingDownDrawable != null) { + pullingDownDrawable.showBottomPanel(pullingDownOffset > 0 && chatListView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING); } return scrolled; } @@ -5240,7 +5270,7 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { progressBar.setProgressColor(getThemedColor(Theme.key_chat_serviceText)); progressView.addView(progressBar, LayoutHelper.createFrame(32, 32, Gravity.CENTER)); - floatingDateView = new ChatActionCell(context, themeDelegate) { + floatingDateView = new ChatActionCell(context, false, themeDelegate) { @Override public void setTranslationY(float translationY) { @@ -5302,6 +5332,12 @@ protected void onDraw(Canvas canvas) { jumpToDate((int) (calendar.getTime().getTime() / 1000)); }); + if (currentChat != null) { + pendingRequestsDelegate = new ChatActivityMemberRequestsDelegate(this, currentChat, this::invalidateChatListViewTopPadding); + pendingRequestsDelegate.setChatInfo(chatInfo, false); + contentView.addView(pendingRequestsDelegate.getView(), ViewGroup.LayoutParams.MATCH_PARENT, pendingRequestsDelegate.getViewHeight()); + } + if (currentEncryptedChat == null) { pinnedMessageView = new FrameLayout(context) { @@ -6666,9 +6702,6 @@ public void onAnimationEnd(Animator animation) { } }); changeBoundAnimator.setDuration(ChatListItemAnimator.DEFAULT_DURATION); -// if (chatActivityEnterViewAnimateBeforeSending) { -// changeBoundAnimator.setStartDelay(20); -// } changeBoundAnimator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); if (!waitingForSendingMessageLoad) { changeBoundAnimator.start(); @@ -7730,7 +7763,7 @@ public void onTextCopied() { } else { decorView = contentView; } - pinchToZoomHelper = new PinchToZoomHelper(decorView) { + pinchToZoomHelper = new PinchToZoomHelper(decorView, contentView) { @Override protected void drawOverlays(Canvas canvas, float alpha, float parentOffsetX, float parentOffsetY, float clipTop, float clipBottom) { if (alpha > 0) { @@ -8001,7 +8034,7 @@ private void updateInfoTopView(boolean animated) { infoTopViewAnimator.cancel(); } if (infoTopView == null) { - infoTopView = new ChatActionCell(contentView.getContext(), themeDelegate); + infoTopView = new ChatActionCell(contentView.getContext(), false, themeDelegate); infoTopView.setCustomText(text); infoTopView.setInvalidateColors(true); infoTopView.setOnClickListener(onClickListener); @@ -8382,9 +8415,14 @@ private void updateChatListViewTopPadding() { if (pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { pinnedViewH = Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); } + float pendingViewH = 0; + View pendingRequestsView = pendingRequestsDelegate != null ? pendingRequestsDelegate.getView() : null; + if (pendingRequestsView != null && pendingRequestsView.getVisibility() == View.VISIBLE) { + pendingViewH = Math.max(0, pendingRequestsView.getHeight() + pendingRequestsDelegate.getViewEnterOffset()); + } float oldPadding = chatListViewPaddingTop; chatListViewPaddingTopOnlyTopViews = topPanelViewH + pinnedViewH; - chatListViewPaddingTop = AndroidUtilities.dp(4) + contentPaddingTop + topPanelViewH + pinnedViewH; + chatListViewPaddingTop = AndroidUtilities.dp(4) + contentPaddingTop + topPanelViewH + pinnedViewH + pendingViewH; chatListViewPaddingVisibleOffset = 0; chatListViewPaddingTop += contentPanTranslation + bottomPanelTranslationY; @@ -8485,10 +8523,17 @@ private void invalidateChatListViewTopPadding() { chatListView.invalidate(); } - float topPanelViewH = Math.max(0, AndroidUtilities.dp(48) + topChatPanelViewOffset); - + float translation = contentPanTranslation + contentPaddingTop + Math.max(0, AndroidUtilities.dp(48) + topChatPanelViewOffset); if (pinnedMessageView != null) { - pinnedMessageView.setTranslationY(contentPanTranslation + pinnedMessageEnterOffset + contentPaddingTop + topPanelViewH); + translation += pinnedMessageEnterOffset; + pinnedMessageView.setTranslationY(translation); + translation += AndroidUtilities.dp(48); + } + View pendingRequestsView = pendingRequestsDelegate != null ? pendingRequestsDelegate.getView() : null; + if (pendingRequestsView != null) { + translation += pendingRequestsDelegate.getViewEnterOffset(); + pendingRequestsView.setTranslationY(translation); + translation += pendingRequestsDelegate.getViewHeight(); } if (fragmentContextView != null) { float from = 0; @@ -8961,6 +9006,7 @@ public void didPressedButton(int button, boolean arg, boolean notify, int schedu fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, getThreadMessage(), null, button == 4 || forceDocument, arg, editingMessageObject, notify, scheduleDate); afterMessageSend(); + chatActivityEnterView.setFieldText(""); } if (scheduleDate != 0) { if (scheduledMessagesCount == -1) { @@ -9686,6 +9732,7 @@ private void openAttachMenu() { chatAttachAlert.setMaxSelectedPhotos(-1, true); } chatAttachAlert.init(); + chatAttachAlert.getCommentTextView().setText(chatActivityEnterView.getFieldText()); showDialog(chatAttachAlert); } @@ -11529,7 +11576,7 @@ private int getScrollOffsetForMessage(MessageObject object) { private int getHeightForMessage(MessageObject object) { if (dummyMessageCell == null) { - dummyMessageCell = new ChatMessageCell(getParentActivity(), themeDelegate); + dummyMessageCell = new ChatMessageCell(getParentActivity(), true, themeDelegate); } dummyMessageCell.isChat = currentChat != null || UserObject.isUserSelf(currentUser); dummyMessageCell.isBot = currentUser != null && currentUser.bot; @@ -12869,7 +12916,7 @@ private void sendUriAsDocument(Uri uri) { } String tempPath = AndroidUtilities.getPath(uri); String originalPath = tempPath; - if (tempPath == null) { + if (tempPath == null || !BuildVars.NO_SCOPED_STORAGE) { originalPath = uri.toString(); tempPath = MediaController.copyFileToCache(uri, "file"); } @@ -12939,6 +12986,9 @@ public void onActivityResultFragment(int requestCode, int resultCode, Intent dat } else { showAttachmentError(); } + if (chatAttachAlert != null) { + chatAttachAlert.dismiss(); + } afterMessageSend(); } } @@ -12986,7 +13036,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { doNotRemoveLoadIndex = false; } if (!doNotRemoveLoadIndex && !fragmentBeginToShow && !paused) { - int[] alowedNotifications = new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.groupCallUpdated, NotificationCenter.dialogsNeedReload, NotificationCenter.scheduledMessagesUpdated, + int[] alowedNotifications = new int[]{NotificationCenter.messagesDidLoad, NotificationCenter.chatInfoDidLoad, NotificationCenter.groupCallUpdated, NotificationCenter.dialogsNeedReload, NotificationCenter.scheduledMessagesUpdated, NotificationCenter.closeChats, NotificationCenter.botKeyboardDidLoad, NotificationCenter.userInfoDidLoad, NotificationCenter.pinnedInfoDidLoad, NotificationCenter.needDeleteDialog/*, NotificationCenter.botInfoDidLoad*/}; if (transitionAnimationIndex == 0) { transitionAnimationIndex = getNotificationCenter().setAnimationInProgress(transitionAnimationIndex, alowedNotifications); @@ -13709,6 +13759,7 @@ public void didReceivedNotification(int id, int account, final Object... args) { chatAdapter.notifyDataSetChanged(true); } if (scrollToMessage != null) { + addSponsoredMessages(!isFirstLoading); int yOffset; boolean bottom = true; if (startLoadFromMessageOffset != Integer.MAX_VALUE) { @@ -14584,6 +14635,9 @@ public void didReceivedNotification(int id, int account, final Object... args) { } checkGroupCallJoin((Boolean) args[3]); checkThemeEmoticon(); + if (pendingRequestsDelegate != null) { + pendingRequestsDelegate.setChatInfo(chatInfo, true); + } } } else if (id == NotificationCenter.chatInfoCantLoad) { long chatId = (Long) args[0]; @@ -15712,6 +15766,17 @@ private void addSponsoredMessages(boolean animated) { if (arrayList == null) { return; } + for (int i = 0; i < arrayList.size(); i++) { + MessageObject messageObject = arrayList.get(i); + messageObject.resetLayout(); + long dialogId = MessageObject.getPeerId(messageObject.messageOwner.from_id); + int messageId = 0 ; + if (messageObject.sponsoredChannelPost != 0) { + messageId = messageObject.sponsoredChannelPost; + } + getMessagesController().ensureMessagesLoaded(dialogId, messageId, null); + + } sponsoredMessagesAdded = true; processNewMessages(arrayList); } @@ -15997,7 +16062,9 @@ private void updateReplyMessageOwners(int id, MessageObject update) { } else { object.replyMessageObject = update; } - chatAdapter.updateRowWithMessageObject(object, true); + if (chatAdapter != null) { + chatAdapter.updateRowWithMessageObject(object, true); + } } } if (update == null) { @@ -17330,6 +17397,10 @@ public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { parentLayout.fragmentsStack.remove(backToPreviousFragment); } } + + if (pendingRequestsDelegate != null && backward) { + pendingRequestsDelegate.onBackToScreen(); + } } else { getNotificationCenter().onAnimationFinish(transitionAnimationIndex); } @@ -19956,7 +20027,7 @@ public boolean onTouch(View v, MotionEvent event) { } }); scrimPopupContainerLayout.setOrientation(LinearLayout.VERTICAL); - boolean showMessageSeen = currentChat != null && message.isOutOwner() && message.isSent() && !message.isEditing() && !message.isSending() && !message.isSendError() && !message.isContentUnread() && !message.isUnread() && (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - message.messageOwner.date < 7 * 86400) && (ChatObject.isMegagroup(currentChat) || !ChatObject.isChannel(currentChat)) && chatInfo != null && chatInfo.participants_count < 50; + boolean showMessageSeen = currentChat != null && message.isOutOwner() && message.isSent() && !message.isEditing() && !message.isSending() && !message.isSendError() && !message.isContentUnread() && !message.isUnread() && (ConnectionsManager.getInstance(currentAccount).getCurrentTime() - message.messageOwner.date < 7 * 86400) && (ChatObject.isMegagroup(currentChat) || !ChatObject.isChannel(currentChat)) && chatInfo != null && chatInfo.participants_count < 50 && !(message.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest); MessageSeenView messageSeenView = null; if (showMessageSeen) { messageSeenView = new MessageSeenView(contentView.getContext(), currentAccount, message, currentChat); @@ -22484,7 +22555,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType view = chatMessageCellsCache.get(0); chatMessageCellsCache.remove(0); } else { - view = new ChatMessageCell(mContext, themeDelegate); + view = new ChatMessageCell(mContext, true, themeDelegate); } ChatMessageCell chatMessageCell = (ChatMessageCell) view; chatMessageCell.setDelegate(new ChatMessageCell.ChatMessageCellDelegate() { @@ -23061,6 +23132,9 @@ public void didPressInstantButton(ChatMessageCell cell, int type) { } else { args.putLong("user_id", peerId); } + if (messageObject.sponsoredChannelPost != 0) { + args.putInt("message_id", messageObject.sponsoredChannelPost); + } if (messageObject.botStartParam != null) { args.putString("inline_query", messageObject.botStartParam); } @@ -23151,7 +23225,7 @@ public boolean isLandscape() { chatMessageCell.setAllowAssistant(true); } } else if (viewType == 1) { - view = new ChatActionCell(mContext, themeDelegate) { + view = new ChatActionCell(mContext, true, themeDelegate) { @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); @@ -24818,6 +24892,9 @@ public ArrayList getThemeDescriptions() { themeDescriptions.add(new ThemeDescription(chatActivityEnterView.botCommandsMenuContainer.listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{BotCommandsMenuView.BotCommandView.class}, new String[]{"description"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); themeDescriptions.add(new ThemeDescription(chatActivityEnterView.botCommandsMenuContainer.listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{BotCommandsMenuView.BotCommandView.class}, new String[]{"command"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText)); } + if (pendingRequestsDelegate != null) { + pendingRequestsDelegate.fillThemeDescriptions(themeDescriptions); + } for (ThemeDescription description : themeDescriptions) { description.resourcesProvider = themeDelegate; @@ -24830,7 +24907,6 @@ public ChatAvatarContainer getAvatarContainer() { return avatarContainer; } - @Override protected AnimatorSet onCustomTransitionAnimation(boolean isOpen, Runnable callback) { if (isOpen && fromPullingDownTransition && getParentLayout().fragmentsStack.size() > 1) { @@ -25019,7 +25095,7 @@ public class ThemeDelegate implements Theme.ResourcesProvider, ChatActionCell.Th private HashMap currentColors = new HashMap<>(); private HashMap animatingColors; - private ChatTheme chatTheme; + private EmojiThemes chatTheme; private Drawable backgroundDrawable; private ValueAnimator patternIntensityAnimator; private Bitmap serviceBitmap; @@ -25027,9 +25103,11 @@ public class ThemeDelegate implements Theme.ResourcesProvider, ChatActionCell.Th private Paint paint = new Paint(); private Canvas serviceCanvas; private BitmapShader serviceShader; + private BitmapShader serviceShaderSource; + private boolean useSourceShader; private int currentColor; private boolean isDark; - private List cachedThemes; + private List cachedThemes; private AnimatorSet patternAlphaAnimator; Theme.MessageDrawable animatingMessageDrawable; @@ -25046,15 +25124,15 @@ public class ThemeDelegate implements Theme.ResourcesProvider, ChatActionCell.Th } } if (!setup) { - Theme.refreshThemeColors(true, false); + Theme.refreshThemeColors(true, true); } } - public List getCachedThemes() { + public List getCachedThemes() { return cachedThemes; } - public void setCachedThemes(List cachedThemes) { + public void setCachedThemes(List cachedThemes) { this.cachedThemes = cachedThemes; } @@ -25126,7 +25204,11 @@ public void applyServiceShaderMatrix(int w, int h, float translationX, float tra if (chatTheme == null || serviceBitmap == null || serviceShader == null) { ChatActionCell.ThemeDelegate.super.applyServiceShaderMatrix(w, h, translationX, translationY); } else { - Theme.applyServiceShaderMatrix(serviceBitmap, serviceShader, actionMatrix, w, h, translationX, translationY); + if (useSourceShader) { + Theme.applyServiceShaderMatrix(serviceBitmapSource, serviceShaderSource, actionMatrix, w, h, translationX, translationY); + } else { + Theme.applyServiceShaderMatrix(serviceBitmap, serviceShader, actionMatrix, w, h, translationX, translationY); + } } } @@ -25154,7 +25236,7 @@ public boolean isThemeChangeAvailable() { return currentChat == null && currentEncryptedChat == null && !currentUser.bot && dialog_id >= 0; } - public ChatTheme getCurrentTheme() { + public EmojiThemes getCurrentTheme() { return chatTheme; } @@ -25168,11 +25250,11 @@ public boolean isWallpaperMotion() { return chatTheme != null ? false : Theme.isWallpaperMotion(); } - public void setCurrentTheme(final ChatTheme chatTheme, boolean animated, Boolean forceDark) { + public void setCurrentTheme(final EmojiThemes chatTheme, boolean animated, Boolean forceDark) { if (parentLayout == null) { return; } - final ChatTheme prevTheme = this.chatTheme; + final EmojiThemes prevTheme = this.chatTheme; boolean newIsDark = forceDark != null ? forceDark : Theme.getActiveTheme().isDark(); String newEmoticon = chatTheme != null ? chatTheme.getEmoticon() : null; String oldEmoticon = this.chatTheme != null ? this.chatTheme.getEmoticon() : null; @@ -25186,20 +25268,20 @@ public void setCurrentTheme(final ChatTheme chatTheme, boolean animated, Boolean if (this.chatTheme == null) { Drawable background = Theme.getCachedWallpaperNonBlocking(); - isBackgroundMotion = background instanceof MotionBackgroundDrawable; + drawServiceGradient = background instanceof MotionBackgroundDrawable; initServiceMessageColors(background); - startServiceTextColor = isBackgroundMotion ? 0xffffffff : Theme.getColor(Theme.key_chat_serviceText); - startServiceLinkColor = isBackgroundMotion ? 0xffffffff : Theme.getColor(Theme.key_chat_serviceLink); - startServiceButtonColor = isBackgroundMotion ? 0xffffffff : Theme.getColor(Theme.key_chat_serviceLink); - startServiceIconColor = isBackgroundMotion ? 0xffffffff : Theme.getColor(Theme.key_chat_serviceIcon); - } else if (isBackgroundMotion) { + startServiceTextColor = drawServiceGradient ? 0xffffffff : Theme.getColor(Theme.key_chat_serviceText); + startServiceLinkColor = drawServiceGradient ? 0xffffffff : Theme.getColor(Theme.key_chat_serviceLink); + startServiceButtonColor = drawServiceGradient ? 0xffffffff : Theme.getColor(Theme.key_chat_serviceLink); + startServiceIconColor = drawServiceGradient ? 0xffffffff : Theme.getColor(Theme.key_chat_serviceIcon); + } else if (drawServiceGradient) { startServiceBitmap = ((MotionBackgroundDrawable) backgroundDrawable).getBitmap(); } startServiceColor = currentServiceColor; - startServiceTextColor = isBackgroundMotion ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceText, true); - startServiceLinkColor = isBackgroundMotion ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceLink, true); - startServiceButtonColor = isBackgroundMotion ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceLink, true); - startServiceIconColor = isBackgroundMotion ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceIcon, true); + startServiceTextColor = drawServiceGradient ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceText, true); + startServiceLinkColor = drawServiceGradient ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceLink, true); + startServiceButtonColor = drawServiceGradient ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceLink, true); + startServiceIconColor = drawServiceGradient ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceIcon, true); if (chatTheme != null) { int[] colors = AndroidUtilities.calcDrawableColor(backgroundDrawable); @@ -25246,7 +25328,7 @@ public void setProgress(float p) { parentLayout.animateThemedValues(animationSettings); } - private void setupChatTheme(ChatTheme chatTheme, boolean withAnimation, boolean createNewResources) { + private void setupChatTheme(EmojiThemes chatTheme, boolean withAnimation, boolean createNewResources) { this.chatTheme = chatTheme; Drawable prevDrawable = null; @@ -25256,7 +25338,7 @@ private void setupChatTheme(ChatTheme chatTheme, boolean withAnimation, boolean final MotionBackgroundDrawable prevMotionDrawable = (prevDrawable instanceof MotionBackgroundDrawable) ? (MotionBackgroundDrawable) prevDrawable : null; final int prevPhase = prevMotionDrawable != null ? prevMotionDrawable.getPhase() : 0; - if (chatTheme == null || chatTheme.isDefault) { + if (chatTheme == null || chatTheme.showAsDefaultStub) { currentColor = Theme.getServiceMessageColor(); } if (chatTheme == null) { @@ -25275,11 +25357,11 @@ private void setupChatTheme(ChatTheme chatTheme, boolean withAnimation, boolean } else { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE); String dayThemeName = preferences.getString("lastDayTheme", "Blue"); - if (Theme.getTheme(dayThemeName) == null) { + if (Theme.getTheme(dayThemeName) == null || Theme.getTheme(dayThemeName).isDark()) { dayThemeName = "Blue"; } String nightThemeName = preferences.getString("lastDarkTheme", "Dark Blue"); - if (Theme.getTheme(nightThemeName) == null) { + if (Theme.getTheme(nightThemeName) == null || !Theme.getTheme(nightThemeName).isDark()) { nightThemeName = "Dark Blue"; } activeTheme = isDark ? Theme.getTheme(nightThemeName) : Theme.getTheme(dayThemeName); @@ -25287,7 +25369,7 @@ private void setupChatTheme(ChatTheme chatTheme, boolean withAnimation, boolean Theme.applyTheme(activeTheme, false, isDark); } else { - currentColors = chatTheme.getCurrentColors(currentAccount, isDark); + currentColors = chatTheme.getCurrentColors(currentAccount, isDark ? 1 : 0); backgroundDrawable = getBackgroundDrawableFromTheme(chatTheme, prevPhase); if (patternAlphaAnimator != null) { @@ -25428,7 +25510,7 @@ private void initPaints() { Bitmap startServiceBitmap; int currentServiceColor; - boolean isBackgroundMotion; + boolean drawServiceGradient; private void initServiceMessageColors(Drawable backgroundDrawable) { int[] result = AndroidUtilities.calcDrawableColor(backgroundDrawable); @@ -25441,14 +25523,16 @@ private void initServiceMessageColors(Drawable backgroundDrawable) { } currentServiceColor = serviceColor; - isBackgroundMotion = backgroundDrawable instanceof MotionBackgroundDrawable; + drawServiceGradient = backgroundDrawable instanceof MotionBackgroundDrawable && SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW; - if (isBackgroundMotion) { + if (drawServiceGradient) { serviceBitmap = Bitmap.createBitmap(60, 80, Bitmap.Config.ARGB_8888); serviceBitmapSource = ((MotionBackgroundDrawable) backgroundDrawable).getBitmap(); serviceCanvas = new Canvas(serviceBitmap); serviceCanvas.drawBitmap(serviceBitmapSource, 0, 0, null); serviceShader = new BitmapShader(serviceBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + serviceShaderSource = new BitmapShader(serviceBitmapSource, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + useSourceShader = true; } else { serviceBitmap = null; serviceShader = null; @@ -25458,15 +25542,15 @@ private void initServiceMessageColors(Drawable backgroundDrawable) { Paint actionBackgroundSelectedPaint = getPaint(Theme.key_paint_chatActionBackgroundSelected); if (actionBackgroundPaint != null) { - if (isBackgroundMotion) { + if (drawServiceGradient) { ColorMatrix colorMatrix = new ColorMatrix(); colorMatrix.setSaturation(((MotionBackgroundDrawable) backgroundDrawable).getIntensity() >= 0 ? 1.8f : 0.5f); actionBackgroundPaint.setAlpha(127); actionBackgroundPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix)); - actionBackgroundPaint.setShader(serviceShader); + actionBackgroundPaint.setShader(serviceShaderSource); actionBackgroundSelectedPaint.setAlpha(127); actionBackgroundSelectedPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix)); - actionBackgroundSelectedPaint.setShader(serviceShader); + actionBackgroundSelectedPaint.setShader(serviceShaderSource); } else { actionBackgroundPaint.setColorFilter(null); actionBackgroundPaint.setShader(null); @@ -25484,10 +25568,10 @@ private void updateServiceMessageColor(float progress) { Paint actionBackgroundSelectedPaint = getPaint(Theme.key_paint_chatActionBackgroundSelected); int serviceColor = currentServiceColor; - int serviceTextColor = isBackgroundMotion ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceText, true); - int serviceLinkColor = isBackgroundMotion ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceLink, true); - int serviceButtonColor = isBackgroundMotion ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceLink, true); - int serviceIconColor = isBackgroundMotion ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceIcon, true); + int serviceTextColor = drawServiceGradient ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceText, true); + int serviceLinkColor = drawServiceGradient ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceLink, true); + int serviceButtonColor = drawServiceGradient ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceLink, true); + int serviceIconColor = drawServiceGradient ? 0xffffffff : getCurrentColorOrDefault(Theme.key_chat_serviceIcon, true); if (progress != 1f) { serviceColor = ColorUtils.blendARGB(startServiceColor, serviceColor, progress); serviceTextColor = ColorUtils.blendARGB(startServiceTextColor, serviceTextColor, progress); @@ -25495,7 +25579,7 @@ private void updateServiceMessageColor(float progress) { serviceButtonColor = ColorUtils.blendARGB(startServiceButtonColor, serviceButtonColor, progress); serviceIconColor = ColorUtils.blendARGB(startServiceIconColor, serviceIconColor, progress); } - if (actionBackgroundPaint != null && !isBackgroundMotion) { + if (actionBackgroundPaint != null && !drawServiceGradient) { actionBackgroundPaint.setColor(serviceColor); actionBackgroundSelectedPaint.setColor(serviceColor); } @@ -25525,21 +25609,32 @@ private void updateServiceMessageColor(float progress) { if (serviceCanvas != null && serviceBitmapSource != null) { if (progress != 1f && startServiceBitmap != null) { + useSourceShader = false; serviceCanvas.drawBitmap(startServiceBitmap, 0, 0, null); paint.setAlpha((int) (255 * progress)); serviceCanvas.drawBitmap(serviceBitmapSource, 0, 0, paint); + if (actionBackgroundPaint != null) { + actionBackgroundPaint.setShader(serviceShader); + actionBackgroundSelectedPaint.setShader(serviceShader); + } } else { + useSourceShader = true; serviceCanvas.drawBitmap(serviceBitmapSource, 0, 0, null); + if (actionBackgroundPaint != null) { + actionBackgroundPaint.setShader(serviceShaderSource); + actionBackgroundSelectedPaint.setShader(serviceShaderSource); + } + } } } - private Drawable getBackgroundDrawableFromTheme(ChatTheme chatTheme, int prevPhase) { + private Drawable getBackgroundDrawableFromTheme(EmojiThemes chatTheme, int prevPhase) { Drawable drawable; - if (chatTheme.isDefault) { - Theme.ThemeInfo themeInfo = ChatTheme.getDefaultThemeInfo(isDark); - HashMap currentColors = chatTheme.getCurrentColors(currentAccount, isDark); - String wallpaperLink = chatTheme.getWallpaperLink(isDark); + if (chatTheme.showAsDefaultStub) { + Theme.ThemeInfo themeInfo = EmojiThemes.getDefaultThemeInfo(isDark); + HashMap currentColors = chatTheme.getCurrentColors(currentAccount, isDark ? 1 : 0); + String wallpaperLink = chatTheme.getWallpaperLink(isDark ? 1 : 0); Theme.BackgroundDrawableSettings settings = Theme.createBackgroundDrawable(themeInfo, currentColors, wallpaperLink, prevPhase); drawable = settings.wallpaper; } else { @@ -25552,22 +25647,22 @@ private Drawable getBackgroundDrawableFromTheme(ChatTheme chatTheme, int prevPha } MotionBackgroundDrawable motionDrawable = new MotionBackgroundDrawable(); - motionDrawable.setPatternBitmap(chatTheme.getWallpaper(isDark).settings.intensity); + motionDrawable.setPatternBitmap(chatTheme.getWallpaper(isDark ? 1 : 0).settings.intensity); motionDrawable.setColors(backgroundColor, gradientColor1, gradientColor2, gradientColor3, true); motionDrawable.setPhase(prevPhase); int patternColor = motionDrawable.getPatternColor(); final boolean isDarkTheme = isDark; - chatTheme.loadWallpaper(isDark, pair -> { + chatTheme.loadWallpaper(isDark ? 1 : 0, pair -> { if (pair == null) { return; } long themeId = pair.first; Bitmap bitmap = pair.second; - if (this.chatTheme != null && themeId == this.chatTheme.getTlTheme(isDark).id && bitmap != null) { + if (this.chatTheme != null && themeId == this.chatTheme.getTlTheme(isDark ? 1 : 0).id && bitmap != null) { if (patternIntensityAnimator != null) { patternIntensityAnimator.cancel(); } - int intensity = chatTheme.getWallpaper(isDarkTheme).settings.intensity; + int intensity = chatTheme.getWallpaper(isDarkTheme ? 1 : 0).settings.intensity; motionDrawable.setPatternBitmap(intensity, bitmap); motionDrawable.setPatternColorFilter(patternColor); patternIntensityAnimator = ValueAnimator.ofFloat(0, 1f); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java index a77832b1895..bd81171810b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java @@ -111,6 +111,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image private LinearLayout infoContainer; private TextCell membersCell; + private TextCell memberRequestsCell; private TextCell inviteLinksCell; private TextCell adminCell; private TextCell blockCell; @@ -831,6 +832,15 @@ public void afterTextChanged(Editable editable) { presentFragment(fragment); }); + if (!ChatObject.isChannelAndNotMegaGroup(currentChat)) { + memberRequestsCell = new TextCell(context); + memberRequestsCell.setBackground(Theme.getSelectorDrawable(false)); + memberRequestsCell.setOnClickListener(v -> { + MemberRequestsActivity activity = new MemberRequestsActivity(chatId); + presentFragment(activity); + }); + } + if (ChatObject.isChannel(currentChat) || currentChat.gigagroup) { logCell = new TextCell(context); logCell.setTextAndIcon(LocaleController.getString("EventLog", R.string.EventLog), R.drawable.group_log, false); @@ -846,6 +856,9 @@ public void afterTextChanged(Editable editable) { } infoContainer.addView(adminCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); infoContainer.addView(membersCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + if (memberRequestsCell != null && info != null && info.requests_pending > 0) { + infoContainer.addView(memberRequestsCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + } if (isChannel) { infoContainer.addView(inviteLinksCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } @@ -1358,14 +1371,21 @@ private void updateFields(boolean updateChat) { if (membersCell != null) { if (info != null) { + if (memberRequestsCell != null) { + if (memberRequestsCell.getParent() == null) { + int position = infoContainer.indexOfChild(membersCell) + 1; + infoContainer.addView(memberRequestsCell, position, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + } + memberRequestsCell.setVisibility(info.requests_pending > 0 ? View.VISIBLE : View.GONE); + } if (isChannel) { membersCell.setTextAndValueAndIcon(LocaleController.getString("ChannelSubscribers", R.string.ChannelSubscribers), String.format("%d", info.participants_count), R.drawable.actions_viewmembers, true); blockCell.setTextAndValueAndIcon(LocaleController.getString("ChannelBlacklist", R.string.ChannelBlacklist), String.format("%d", Math.max(info.banned_count, info.kicked_count)), R.drawable.actions_removed, logCell != null && logCell.getVisibility() == View.VISIBLE); } else { if (ChatObject.isChannel(currentChat)) { - membersCell.setTextAndValueAndIcon(LocaleController.getString("ChannelMembers", R.string.ChannelMembers), String.format("%d", info.participants_count), R.drawable.actions_viewmembers, logCell != null && logCell.getVisibility() == View.VISIBLE); + membersCell.setTextAndValueAndIcon(LocaleController.getString("ChannelMembers", R.string.ChannelMembers), String.format("%d", info.participants_count), R.drawable.actions_viewmembers, true); } else { - membersCell.setTextAndValueAndIcon(LocaleController.getString("ChannelMembers", R.string.ChannelMembers), String.format("%d", info.participants.participants.size()), R.drawable.actions_viewmembers, logCell != null && logCell.getVisibility() == View.VISIBLE); + membersCell.setTextAndValueAndIcon(LocaleController.getString("ChannelMembers", R.string.ChannelMembers), String.format("%d", info.participants.participants.size()), R.drawable.actions_viewmembers, memberRequestsCell.getVisibility() == View.VISIBLE); } if (currentChat.gigagroup) { blockCell.setTextAndValueAndIcon(LocaleController.getString("ChannelBlacklist", R.string.ChannelBlacklist), String.format("%d", Math.max(info.banned_count, info.kicked_count)), R.drawable.actions_removed, logCell != null && logCell.getVisibility() == View.VISIBLE); @@ -1401,6 +1421,9 @@ private void updateFields(boolean updateChat) { } blockCell.setTextAndValueAndIcon(LocaleController.getString("ChannelPermissions", R.string.ChannelPermissions), String.format("%d/%d", count, 8), R.drawable.actions_permissions, true); } + if (memberRequestsCell != null) { + memberRequestsCell.setTextAndValueAndIcon(LocaleController.getString("MemberRequests", R.string.MemberRequests), String.format("%d", info.requests_pending), R.drawable.actions_requests, logCell != null && logCell.getVisibility() == View.VISIBLE); + } } adminCell.setTextAndValueAndIcon(LocaleController.getString("ChannelAdministrators", R.string.ChannelAdministrators), String.format("%d", ChatObject.isChannel(currentChat) ? info.admins_count : getAdminCount()), R.drawable.actions_addadmin, true); } else { @@ -1466,6 +1489,11 @@ public ArrayList getThemeDescriptions() { themeDescriptions.add(new ThemeDescription(inviteLinksCell, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector)); themeDescriptions.add(new ThemeDescription(inviteLinksCell, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{TextCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); themeDescriptions.add(new ThemeDescription(inviteLinksCell, 0, new Class[]{TextCell.class}, new String[]{"imageView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayIcon)); + if (memberRequestsCell != null) { + themeDescriptions.add(new ThemeDescription(memberRequestsCell, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector)); + themeDescriptions.add(new ThemeDescription(memberRequestsCell, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{TextCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); + themeDescriptions.add(new ThemeDescription(memberRequestsCell, 0, new Class[]{TextCell.class}, new String[]{"imageView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayIcon)); + } themeDescriptions.add(new ThemeDescription(blockCell, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector)); themeDescriptions.add(new ThemeDescription(blockCell, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{TextCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java index 0c1324ad224..f62d949094e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java @@ -525,7 +525,10 @@ public static TLRPC.Dialog getNextUnreadDialog(long currentDialogId, int folderI TLRPC.Dialog dialog = dialogs.get(i); TLRPC.Chat chat = messagesController.getChat(-dialog.id); if (chat != null && dialog.id != currentDialogId && dialog.unread_count > 0 && DialogObject.isChannel(dialog) && !chat.megagroup && !messagesController.isPromoDialog(dialog.id, false)) { - return dialog; + String reason = MessagesController.getRestrictionReason(chat.restriction_reason); + if (reason == null) { + return dialog; + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java index dc166580caa..a3f1d21a06d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java @@ -2321,7 +2321,11 @@ private void loadChatParticipants(int offset, int count, boolean reset) { objects.addAll(res.participants); for (int a = 0, size = res.participants.size(); a < size; a++) { TLRPC.ChannelParticipant participant = res.participants.get(a); - map.put(MessageObject.getPeerId(participant.peer), participant); + if (participant.user_id == selfId) { + objects.remove(participant); + } else { + map.put(MessageObject.getPeerId(participant.peer), participant); + } } if (type == TYPE_USERS) { for (int a = 0, N = participants.size(); a < N; a++) { @@ -2830,7 +2834,9 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { peerObject = user; } else { TLRPC.Chat chat = getMessagesController().getChat(-peerId); - un = chat.username; + if (chat != null) { + un = chat.username; + } peerObject = chat; } } else if (object instanceof TLRPC.ChatParticipant) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java index 2b4448a8eab..3fc1b225dde 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java @@ -9,6 +9,7 @@ package org.telegram.ui.Components; import android.Manifest; +import android.annotation.SuppressLint; import android.app.Activity; import android.app.Dialog; import android.content.Context; @@ -20,6 +21,7 @@ import android.graphics.Outline; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; @@ -45,8 +47,10 @@ import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.KeyEvent; +import android.view.MotionEvent; import android.view.View; import android.view.ViewOutlineProvider; +import android.view.WindowManager; import android.view.inputmethod.EditorInfo; import android.widget.Button; import android.widget.EditText; @@ -82,6 +86,7 @@ import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBarMenuItem; +import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; @@ -123,7 +128,7 @@ public static Dialog processError(int currentAccount, TLRPC.TL_error error, Base TLRPC.InputPeer peer; if (request instanceof TLRPC.TL_messages_initHistoryImport) { peer = ((TLRPC.TL_messages_initHistoryImport) request).peer; - } else if (request instanceof TLRPC.TL_messages_startHistoryImport) { + } else if (request instanceof TLRPC.TL_messages_startHistoryImport) { peer = ((TLRPC.TL_messages_startHistoryImport) request).peer; } else { peer = null; @@ -865,7 +870,7 @@ public static void showCustomNotificationsDialog(BaseFragment parentFragment, lo setting = NotificationsController.SETTING_MUTE_HOUR; } else if (i == 2) { setting = NotificationsController.SETTING_MUTE_2_DAYS; - } else if (i == 4){ + } else if (i == 4) { setting = NotificationsController.SETTING_MUTE_FOREVER; } if (setting >= 0) { @@ -1588,7 +1593,7 @@ public CharSequence filter(CharSequence source, int start, int end, Spanned dest checkTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText4)); checkTextView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); dialogView.addView(checkTextView, LayoutHelper.createFrame(20, 20, LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT, 0, 14, 21, 0)); - editTextView.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(24) : 0, AndroidUtilities.dp(8), LocaleController.isRTL ? 0 : AndroidUtilities.dp(24), AndroidUtilities.dp(8)); + editTextView.setPadding(LocaleController.isRTL ? AndroidUtilities.dp(24) : 0, AndroidUtilities.dp(8), LocaleController.isRTL ? 0 : AndroidUtilities.dp(24), AndroidUtilities.dp(8)); editTextView.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { @@ -1602,7 +1607,7 @@ public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { @Override public void afterTextChanged(Editable s) { - int count = maxSymbolsCount - Character.codePointCount(s, 0, s.length()); + int count = maxSymbolsCount - Character.codePointCount(s, 0, s.length()); if (count < 30) { checkTextView.setNumber(count, checkTextView.getVisibility() == View.VISIBLE); AndroidUtilities.updateViewVisibilityAnimated(checkTextView, true); @@ -3525,7 +3530,7 @@ public void getOutline(View view, Outline outline) { background.setBackground(new BitmapDrawable(SvgHelper.getBitmap(svg, AndroidUtilities.dp(320), AndroidUtilities.dp(320 * aspectRatio), false))); frameLayout.addView(background, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, -1, -1, -1, -1)); - frameLayout.addView(button, LayoutHelper.createFrame(117,117)); + frameLayout.addView(button, LayoutHelper.createFrame(117, 117)); builder.setTopView(frameLayout); builder.setTitle(LocaleController.getString("PermissionDrawAboveOtherAppsGroupCallTitle", R.string.PermissionDrawAboveOtherAppsGroupCallTitle)); @@ -4782,4 +4787,51 @@ private static String generateThemeName(Theme.ThemeAccent accent) { } return result; } + + @SuppressLint("ClickableViewAccessibility") + public static ActionBarPopupWindow showPopupMenu(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout, View anchorView, int offsetX, int offsetY) { + Rect rect = new Rect(); + ActionBarPopupWindow popupWindow = new ActionBarPopupWindow(popupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); + if (Build.VERSION.SDK_INT >= 19) { + popupWindow.setAnimationStyle(0); + } else { + popupWindow.setAnimationStyle(R.style.PopupAnimation); + } + + popupWindow.setAnimationEnabled(true); + + popupWindow.setOutsideTouchable(true); + popupWindow.setClippingEnabled(true); + + popupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); + popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); + popupWindow.setFocusable(true); + popupLayout.setFocusableInTouchMode(true); + popupLayout.setOnKeyListener((v, keyCode, event) -> { + if (keyCode == KeyEvent.KEYCODE_MENU && event.getRepeatCount() == 0 && event.getAction() == KeyEvent.ACTION_UP && popupWindow.isShowing()) { + popupWindow.dismiss(); + return true; + } + return false; + }); + + popupLayout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x - AndroidUtilities.dp(40), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.y, View.MeasureSpec.AT_MOST)); + popupWindow.showAsDropDown(anchorView, offsetX, offsetY); + + popupLayout.updateRadialSelectors(); + popupWindow.startAnimation(); + + popupLayout.setOnTouchListener((v, event) -> { + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + if (popupWindow != null && popupWindow.isShowing()) { + v.getHitRect(rect); + if (!rect.contains((int) event.getX(), (int) event.getY())) { + popupWindow.dismiss(); + } + } + } + return false; + }); + return popupWindow; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioVisualizerDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioVisualizerDrawable.java index 5d8587cf41a..49e84a0095f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioVisualizerDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioVisualizerDrawable.java @@ -110,12 +110,12 @@ public void setWaveform(boolean playing, boolean animate, float[] waveform) { float rotation; - public void draw(Canvas canvas, float cx, float cy, boolean outOwner) { + public void draw(Canvas canvas, float cx, float cy, boolean outOwner, Theme.ResourcesProvider resourcesProvider) { if (outOwner) { - p1.setColor(Theme.getColor(Theme.key_chat_outLoader)); + p1.setColor(Theme.getColor(Theme.key_chat_outLoader, resourcesProvider)); p1.setAlpha(ALPHA); } else { - p1.setColor(Theme.getColor(Theme.key_chat_inLoader)); + p1.setColor(Theme.getColor(Theme.key_chat_inLoader, resourcesProvider)); p1.setAlpha(ALPHA); } this.draw(canvas, cx, cy); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarsImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarsImageView.java index db9b202b704..12ececc40de 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarsImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarsImageView.java @@ -33,7 +33,6 @@ public class AvatarsImageView extends FrameLayout { - public final static int STYLE_GROUP_CALL_TOOLTIP = 10; public final static int STYLE_MESSAGE_SEEN = 11; @@ -53,6 +52,7 @@ public class AvatarsImageView extends FrameLayout { boolean centered; private boolean isInCall; + protected int count; public void commitTransition(boolean animated) { if (!wasDraw || !animated) { @@ -472,4 +472,15 @@ protected void onAttachedToWindow() { public void setCentered(boolean centered) { this.centered = centered; } + + public void setCount(int count) { + this.count = count; + requestLayout(); + } + + public void reset() { + for (int i = 0; i < animatingStates.length; ++i) { + setObject(0, 0, null); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java index b366b97cafc..4c9111eb798 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java @@ -923,6 +923,25 @@ public SimpleLayout(@NonNull Context context, Theme.ResourcesProvider resourcesP } } + @SuppressLint("ViewConstructor") + public static class MultiLineLayout extends ButtonLayout { + + public final BackupImageView imageView = new BackupImageView(getContext()); + public final TextView textView = new TextView(getContext()); + + public MultiLineLayout(@NonNull Context context, Theme.ResourcesProvider resourcesProvider) { + super(context, resourcesProvider); + addView(imageView, LayoutHelper.createFrameRelatively(30, 30, Gravity.START | Gravity.CENTER_VERTICAL, 12, 8, 12, 8)); + + textView.setGravity(Gravity.START); + textView.setPadding(0, AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8)); + textView.setTextColor(getThemedColor(Theme.key_undo_infoColor)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + textView.setTypeface(Typeface.SANS_SERIF); + addView(textView, LayoutHelper.createFrameRelatively(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 56, 0, 16, 0)); + } + } + @SuppressLint("ViewConstructor") public static class TwoLineLayout extends ButtonLayout { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java index 8a0d7887c36..71b6628d9ae 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -2891,7 +2891,7 @@ public boolean onTouchEvent(MotionEvent event) { } sendButtonContainer.addView(sendButton, LayoutHelper.createFrame(48, 48)); sendButton.setOnClickListener(view -> { - if (sendPopupWindow != null && sendPopupWindow.isShowing() || (runningAnimationAudio != null && runningAnimationAudio.isRunning())) { + if ((sendPopupWindow != null && sendPopupWindow.isShowing()) || (runningAnimationAudio != null && runningAnimationAudio.isRunning()) || moveToSendStateRunnable != null) { return; } sendMessage(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java index ba859d37311..174d78a2bc1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java @@ -2906,4 +2906,8 @@ public void setAllowNestedScroll(boolean allowNestedScroll) { public BaseFragment getBaseFragment() { return baseFragment; } + + public EditTextEmoji getCommentTextView() { + return commentTextView; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertContactsLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertContactsLayout.java index a82af79c6d0..935180e404a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertContactsLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertContactsLayout.java @@ -25,7 +25,6 @@ import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; -import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; @@ -42,7 +41,6 @@ import java.util.ArrayList; import java.util.HashMap; -import androidx.collection.LongSparseArray; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearSmoothScroller; import androidx.recyclerview.widget.RecyclerView; @@ -674,8 +672,9 @@ public String getLetter(int position) { } @Override - public int getPositionForScrollProgress(float progress) { - return 0; + public void getPositionForScrollProgress(RecyclerListView listView, float progress, int[] position) { + position[0] = 0; + position[1] = 0; } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertDocumentLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertDocumentLayout.java index 521f6d5a438..ed2cf423414 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertDocumentLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertDocumentLayout.java @@ -1935,8 +1935,9 @@ public String getLetter(int position) { } @Override - public int getPositionForScrollProgress(float progress) { - return 0; + public void getPositionForScrollProgress(RecyclerListView listView, float progress, int[] position) { + position[0] = 0; + position[1] = 0; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java index 64ffd26c5fa..265594f774c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java @@ -375,6 +375,23 @@ public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolea addToSelectedPhotos(photoEntry, -1); } parentAlert.applyCaption(); + if (PhotoViewer.getInstance().hasCaptionForAllMedia) { + HashMap selectedPhotos = getSelectedPhotos(); + ArrayList selectedPhotosOrder = getSelectedPhotosOrder(); + if (!selectedPhotos.isEmpty()) { + for (int a = 0; a < selectedPhotosOrder.size(); a++) { + Object o = selectedPhotos.get(selectedPhotosOrder.get(a)); + if (o instanceof MediaController.PhotoEntry) { + MediaController.PhotoEntry photoEntry1 = (MediaController.PhotoEntry) o; + if (a == 0) { + photoEntry1.caption = PhotoViewer.getInstance().captionForAllMedia; + } else { + photoEntry1.caption = null; + } + } + } + } + } parentAlert.delegate.didPressedButton(7, true, notify, scheduleDate, forceDocument); } }; @@ -625,7 +642,9 @@ public int getSpanSize(int position) { AndroidUtilities.hideKeyboard(parentAlert.baseFragment.getFragmentView().findFocus()); AndroidUtilities.hideKeyboard(parentAlert.getContainer().findFocus()); } + ((MediaController.PhotoEntry) arrayList.get(position)).caption = parentAlert.getCommentTextView().getText(); PhotoViewer.getInstance().openPhotoForSelect(arrayList, position, type, false, photoViewerProvider, chatActivity); + PhotoViewer.getInstance().setCaption(parentAlert.getCommentTextView().getText()); } else { if (SharedConfig.inappCamera) { openCamera(true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java index b75a5858514..9a2b8804a35 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java @@ -13,7 +13,6 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; -import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; @@ -44,7 +43,6 @@ import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; -import org.telegram.ui.MediaActivity; import org.telegram.ui.ProfileActivity; public class ChatAvatarContainer extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { @@ -211,7 +209,7 @@ private void openProfile(boolean byAvatar) { if (key != null && !imageLoader.isInMemCache(key, false)) { Drawable drawable = imageReceiver.getDrawable(); if (drawable instanceof BitmapDrawable) { - imageLoader.putImageToCache((BitmapDrawable) drawable, key); + imageLoader.putImageToCache((BitmapDrawable) drawable, key, false); } } @@ -221,7 +219,7 @@ private void openProfile(boolean byAvatar) { args.putLong("dialog_id", parentFragment.getDialogId()); int[] media = new int[MediaDataController.MEDIA_TYPES_COUNT]; System.arraycopy(sharedMediaPreloader.getLastMediaCount(), 0, media, 0, media.length); - MediaActivity fragment = new MediaActivity(args, media, sharedMediaPreloader.getSharedMediaData(), -1); + MediaActivity fragment = new MediaActivity(args, sharedMediaPreloader); fragment.setChatInfo(parentFragment.getCurrentChatInfo()); parentFragment.presentFragment(fragment); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatThemeBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatThemeBottomSheet.java index e5955b0ce8c..d51ac2c462e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatThemeBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatThemeBottomSheet.java @@ -6,6 +6,7 @@ import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; @@ -16,8 +17,10 @@ import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.graphics.Shader; -import android.graphics.Typeface; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Bundle; import android.text.Layout; import android.text.StaticLayout; @@ -28,7 +31,6 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -40,24 +42,32 @@ import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ChatThemeController; +import org.telegram.messenger.DocumentObject; import org.telegram.messenger.Emoji; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; -import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.Utilities; +import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.ResultCallback; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BottomSheet; -import org.telegram.ui.ActionBar.ChatTheme; +import org.telegram.ui.ActionBar.EmojiThemes; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; +import org.telegram.ui.Cells.ThemesHorizontalListCell; import org.telegram.ui.ChatActivity; +import java.io.File; +import java.io.FileInputStream; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; @@ -68,7 +78,7 @@ public class ChatThemeBottomSheet extends BottomSheet implements NotificationCen private final Adapter adapter; private final ChatActivity.ThemeDelegate themeDelegate; - private final ChatTheme originalTheme; + private final EmojiThemes originalTheme; private final boolean originalIsDark; private final ChatActivity chatActivity; private final RecyclerListView recyclerView; @@ -97,7 +107,7 @@ public ChatThemeBottomSheet(final ChatActivity chatActivity, ChatActivity.ThemeD this.themeDelegate = themeDelegate; this.originalTheme = themeDelegate.getCurrentTheme(); this.originalIsDark = Theme.getActiveTheme().isDark(); - adapter = new Adapter(themeDelegate); + adapter = new Adapter(currentAccount, themeDelegate, Adapter.TYPE_DEFAULT); setDimBehind(false); setCanDismissWithSwipe(false); setApplyBottomPadding(false); @@ -158,14 +168,14 @@ protected int calculateTimeForScrolling(int dx) { } selectedItem = adapter.items.get(position); isLightDarkChangeAnimation = false; - if (selectedItem.chatTheme == null || selectedItem.chatTheme.isDefault) { + if (selectedItem.chatTheme == null || selectedItem.chatTheme.showAsDefaultStub) { applyTextView.animate().alpha(0f).setDuration(300).start(); resetTextView.animate().alpha(1f).setDuration(300).start(); } else { resetTextView.animate().alpha(0f).setDuration(300).start(); applyTextView.animate().alpha(1f).setDuration(300).start(); } - if (selectedItem.chatTheme.isDefault) { + if (selectedItem.chatTheme.showAsDefaultStub) { themeDelegate.setCurrentTheme(null, true, forceDark); } else { themeDelegate.setCurrentTheme(selectedItem.chatTheme, true, forceDark); @@ -191,7 +201,7 @@ public void run() { child.cancelAnimation(); } } - if (!adapter.items.get(position).chatTheme.isDefault) { + if (!adapter.items.get(position).chatTheme.showAsDefaultStub) { ((Adapter.ChatThemeView) view).playEmojiAnimation(); } }); @@ -245,11 +255,11 @@ protected void onCreate(Bundle savedInstanceState) { NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); isApplyClicked = false; - List cachedThemes = themeDelegate.getCachedThemes(); + List cachedThemes = themeDelegate.getCachedThemes(); if (cachedThemes == null || cachedThemes.isEmpty()) { - ChatThemeController.requestAllChatThemes(new ResultCallback>() { + ChatThemeController.requestAllChatThemes(new ResultCallback>() { @Override - public void onComplete(List result) { + public void onComplete(List result) { if (result != null && !result.isEmpty()) { themeDelegate.setCachedThemes(result); } @@ -266,7 +276,7 @@ public void onError(TLRPC.TL_error error) { } - if (chatActivity.getCurrentUser() != null && SharedConfig.dayNightThemeSwitchHintCount > 0) { + if (chatActivity.getCurrentUser() != null && SharedConfig.dayNightThemeSwitchHintCount > 0 && !chatActivity.getCurrentUser().self) { SharedConfig.updateDayNightThemeSwitchHintCount(SharedConfig.dayNightThemeSwitchHintCount - 1); hintView = new HintView(getContext(), 9, chatActivity.getResourceProvider()); hintView.setVisibility(View.INVISIBLE); @@ -287,6 +297,7 @@ public void onContainerTranslationYChanged(float y) { hintView.hide(); } } + @Override public void onBackPressed() { close(); @@ -446,7 +457,7 @@ public void onAnimationEnd(Animator animation) { setForceDark(isDark, true); if (selectedItem != null) { isLightDarkChangeAnimation = true; - if (selectedItem.chatTheme.isDefault) { + if (selectedItem.chatTheme.showAsDefaultStub) { themeDelegate.setCurrentTheme(null, false, isDark); } else { themeDelegate.setCurrentTheme(selectedItem.chatTheme, false, isDark); @@ -454,7 +465,7 @@ public void onAnimationEnd(Animator animation) { } if (adapter != null && adapter.items != null) { for (int i = 0; i < adapter.items.size(); i++) { - adapter.items.get(i).isDark = isDark; + adapter.items.get(i).themeIndex = isDark ? 1 : 0; } adapter.notifyDataSetChanged(); } @@ -479,51 +490,25 @@ protected boolean onContainerTouchEvent(MotionEvent event) { } } - private void onDataLoaded(List result) { + private void onDataLoaded(List result) { if (result == null || result.isEmpty()) { return; } ChatThemeItem noThemeItem = new ChatThemeItem(result.get(0)); List items = new ArrayList<>(result.size()); - ChatTheme currentTheme = themeDelegate.getCurrentTheme(); + EmojiThemes currentTheme = themeDelegate.getCurrentTheme(); items.add(0, noThemeItem); selectedItem = noThemeItem; for (int i = 1; i < result.size(); ++i) { - ChatTheme chatTheme = result.get(i); + EmojiThemes chatTheme = result.get(i); ChatThemeItem item = new ChatThemeItem(chatTheme); - HashMap colorsMap = chatTheme.getCurrentColors(chatActivity.getCurrentAccount(), true); - Integer color = colorsMap.get(Theme.key_chat_inBubble); - if (color == null) { - color = getThemedColor(Theme.key_chat_inBubble); - } - item.inBubbleColorDark = color; - color = colorsMap.get(Theme.key_chat_outBubble); - if (color == null) { - color = getThemedColor(Theme.key_chat_outBubble); - } - item.outBubbleColorDark = color; - color = colorsMap.get(Theme.key_featuredStickers_addButton); - item.strokeColorLight = color != null ? color : 0; - - colorsMap = chatTheme.getCurrentColors(chatActivity.getCurrentAccount(), false); - color = colorsMap.get(Theme.key_chat_inBubble); - if (color == null) { - color = getThemedColor(Theme.key_chat_inBubble); - } - item.inBubbleColorLight = color; - color = colorsMap.get(Theme.key_chat_outBubble); - if (color == null) { - color = getThemedColor(Theme.key_chat_outBubble); - } - item.outBubbleColorLight = color; - color = colorsMap.get(Theme.key_featuredStickers_addButton); - item.strokeColorDark = color != null ? color : 0; + chatTheme.loadPreviewColors(currentAccount); - item.isDark = forceDark; + item.themeIndex = forceDark ? 1 : 0; items.add(item); } adapter.setItems(items); @@ -549,6 +534,9 @@ private void onDataLoaded(List result) { if (selectedPosition != -1) { prevSelectedPosition = selectedPosition; adapter.setSelectedItem(selectedPosition); + if (selectedPosition > 0 && selectedPosition < items.size() / 2) { + selectedPosition -= 1; + } int finalSelectedPosition = Math.min(selectedPosition, adapter.items.size() - 1); layoutManager.scrollToPositionWithOffset(finalSelectedPosition, 0); } @@ -567,7 +555,7 @@ private void onDataLoaded(List result) { private void onAnimationStart() { if (adapter != null && adapter.items != null) { for (ChatThemeItem item : adapter.items) { - item.isDark = forceDark; + item.themeIndex = forceDark ? 1 : 0; } } if (!isLightDarkChangeAnimation) { @@ -610,15 +598,15 @@ private void setItemsAnimationProgress(float progress) { private void applySelectedTheme() { Bulletin bulletin = null; - ChatTheme newTheme = selectedItem.chatTheme; - if (newTheme.isDefault) { + EmojiThemes newTheme = selectedItem.chatTheme; + if (newTheme.showAsDefaultStub) { newTheme = null; } if (selectedItem != null && newTheme != originalTheme) { - ChatTheme chatTheme = selectedItem.chatTheme; - String emoticon = (chatTheme != null && !chatTheme.isDefault) ? chatTheme.getEmoticon() : null; + EmojiThemes chatTheme = selectedItem.chatTheme; + String emoticon = (chatTheme != null && !chatTheme.showAsDefaultStub) ? chatTheme.getEmoticon() : null; ChatThemeController.getInstance(currentAccount).setDialogTheme(chatActivity.getDialogId(), emoticon, true); - if (chatTheme != null && !chatTheme.isDefault) { + if (chatTheme != null && !chatTheme.showAsDefaultStub) { themeDelegate.setCurrentTheme(chatTheme, true, originalIsDark); } else { themeDelegate.setCurrentTheme(null, true, originalIsDark); @@ -667,27 +655,45 @@ private boolean hasChanges() { } @SuppressLint("NotifyDataSetChanged") - private class Adapter extends RecyclerView.Adapter { + public static class Adapter extends RecyclerView.Adapter { + public final static int TYPE_DEFAULT = 0; + public final static int TYPE_GRID = 1; private final Theme.ResourcesProvider resourcesProvider; - private List items; + public List items; private WeakReference selectedViewRef; private int selectedItemPosition = -1; + private final int currentAccount; + private final int currentType; - public Adapter(Theme.ResourcesProvider resourcesProvider) { + private HashMap loadingThemes = new HashMap<>(); + private HashMap loadingWallpapers = new HashMap<>(); + + public Adapter(int currentAccount, Theme.ResourcesProvider resourcesProvider, int type) { + this.currentType = type; this.resourcesProvider = resourcesProvider; + this.currentAccount = currentAccount; } @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new RecyclerListView.Holder(new ChatThemeView(parent.getContext(), resourcesProvider)); + return new RecyclerListView.Holder(new ChatThemeView(parent.getContext(), currentAccount, resourcesProvider, currentType)); } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { ChatThemeView view = (ChatThemeView) holder.itemView; + Theme.ThemeInfo themeInfo = items.get(position).chatTheme.getThemeInfo(items.get(position).themeIndex); + if (themeInfo != null && themeInfo.pathToFile != null && !themeInfo.previewParsed) { + File file = new File(themeInfo.pathToFile); + boolean fileExists = file.exists(); + if (fileExists) { + parseTheme(themeInfo); + } + } + view.setItem(items.get(position)); view.setSelected(position == selectedItemPosition); if (position == selectedItemPosition) { @@ -695,6 +701,163 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi } } + private boolean parseTheme(Theme.ThemeInfo themeInfo) { + if (themeInfo == null || themeInfo.pathToFile == null) { + return false; + } + boolean finished = false; + File file = new File(themeInfo.pathToFile); + try (FileInputStream stream = new FileInputStream(file)) { + int currentPosition = 0; + int idx; + int read; + int linesRead = 0; + while ((read = stream.read(ThemesHorizontalListCell.bytes)) != -1) { + int previousPosition = currentPosition; + int start = 0; + for (int a = 0; a < read; a++) { + if (ThemesHorizontalListCell.bytes[a] == '\n') { + linesRead++; + int len = a - start + 1; + String line = new String(ThemesHorizontalListCell.bytes, start, len - 1, "UTF-8"); + if (line.startsWith("WLS=")) { + String wallpaperLink = line.substring(4); + Uri uri = Uri.parse(wallpaperLink); + themeInfo.slug = uri.getQueryParameter("slug"); + themeInfo.pathToWallpaper = new File(ApplicationLoader.getFilesDirFixed(), Utilities.MD5(wallpaperLink) + ".wp").getAbsolutePath(); + + String mode = uri.getQueryParameter("mode"); + if (mode != null) { + mode = mode.toLowerCase(); + String[] modes = mode.split(" "); + if (modes != null && modes.length > 0) { + for (int b = 0; b < modes.length; b++) { + if ("blur".equals(modes[b])) { + themeInfo.isBlured = true; + break; + } + } + } + } + String pattern = uri.getQueryParameter("pattern"); + if (!TextUtils.isEmpty(pattern)) { + try { + String bgColor = uri.getQueryParameter("bg_color"); + if (!TextUtils.isEmpty(bgColor)) { + themeInfo.patternBgColor = Integer.parseInt(bgColor.substring(0, 6), 16) | 0xff000000; + if (bgColor.length() >= 13 && AndroidUtilities.isValidWallChar(bgColor.charAt(6))) { + themeInfo.patternBgGradientColor1 = Integer.parseInt(bgColor.substring(7, 13), 16) | 0xff000000; + } + if (bgColor.length() >= 20 && AndroidUtilities.isValidWallChar(bgColor.charAt(13))) { + themeInfo.patternBgGradientColor2 = Integer.parseInt(bgColor.substring(14, 20), 16) | 0xff000000; + } + if (bgColor.length() == 27 && AndroidUtilities.isValidWallChar(bgColor.charAt(20))) { + themeInfo.patternBgGradientColor3 = Integer.parseInt(bgColor.substring(21), 16) | 0xff000000; + } + } + } catch (Exception ignore) { + + } + try { + String rotation = uri.getQueryParameter("rotation"); + if (!TextUtils.isEmpty(rotation)) { + themeInfo.patternBgGradientRotation = Utilities.parseInt(rotation); + } + } catch (Exception ignore) { + + } + String intensity = uri.getQueryParameter("intensity"); + if (!TextUtils.isEmpty(intensity)) { + themeInfo.patternIntensity = Utilities.parseInt(intensity); + } + if (themeInfo.patternIntensity == 0) { + themeInfo.patternIntensity = 50; + } + } + } else if (line.startsWith("WPS")) { + themeInfo.previewWallpaperOffset = currentPosition + len; + finished = true; + break; + } else { + if ((idx = line.indexOf('=')) != -1) { + String key = line.substring(0, idx); + if (key.equals(Theme.key_chat_inBubble) || key.equals(Theme.key_chat_outBubble) || key.equals(Theme.key_chat_wallpaper) || key.equals(Theme.key_chat_wallpaper_gradient_to1) || key.equals(Theme.key_chat_wallpaper_gradient_to2) || key.equals(Theme.key_chat_wallpaper_gradient_to3)) { + String param = line.substring(idx + 1); + int value; + if (param.length() > 0 && param.charAt(0) == '#') { + try { + value = Color.parseColor(param); + } catch (Exception ignore) { + value = Utilities.parseInt(param); + } + } else { + value = Utilities.parseInt(param); + } + switch (key) { + case Theme.key_chat_inBubble: + themeInfo.setPreviewInColor(value); + break; + case Theme.key_chat_outBubble: + themeInfo.setPreviewOutColor(value); + break; + case Theme.key_chat_wallpaper: + themeInfo.setPreviewBackgroundColor(value); + break; + case Theme.key_chat_wallpaper_gradient_to1: + themeInfo.previewBackgroundGradientColor1 = value; + break; + case Theme.key_chat_wallpaper_gradient_to2: + themeInfo.previewBackgroundGradientColor2 = value; + break; + case Theme.key_chat_wallpaper_gradient_to3: + themeInfo.previewBackgroundGradientColor3 = value; + break; + } + } + } + } + start += len; + currentPosition += len; + } + } + if (finished || previousPosition == currentPosition) { + break; + } + stream.getChannel().position(currentPosition); + } + } catch (Throwable e) { + FileLog.e(e); + } + + if (themeInfo.pathToWallpaper != null && !themeInfo.badWallpaper) { + file = new File(themeInfo.pathToWallpaper); + if (!file.exists()) { + if (!loadingWallpapers.containsKey(themeInfo)) { + loadingWallpapers.put(themeInfo, themeInfo.slug); + TLRPC.TL_account_getWallPaper req = new TLRPC.TL_account_getWallPaper(); + TLRPC.TL_inputWallPaperSlug inputWallPaperSlug = new TLRPC.TL_inputWallPaperSlug(); + inputWallPaperSlug.slug = themeInfo.slug; + req.wallpaper = inputWallPaperSlug; + ConnectionsManager.getInstance(themeInfo.account).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (response instanceof TLRPC.TL_wallPaper) { + TLRPC.WallPaper wallPaper = (TLRPC.WallPaper) response; + String name = FileLoader.getAttachFileName(wallPaper.document); + if (!loadingThemes.containsKey(name)) { + loadingThemes.put(name, themeInfo); + FileLoader.getInstance(themeInfo.account).loadFile(wallPaper.document, wallPaper, 1, 1); + } + } else { + themeInfo.badWallpaper = true; + } + })); + } + return false; + } + } + themeInfo.previewParsed = true; + return true; + } + @Override public int getItemCount() { return items == null ? 0 : items.size(); @@ -711,7 +874,7 @@ public void setSelectedItem(int position) { } if (selectedItemPosition >= 0) { notifyItemChanged(selectedItemPosition); - ChatThemeView view = selectedViewRef.get(); + ChatThemeView view = selectedViewRef == null ? null : selectedViewRef.get(); if (view != null) { view.setSelected(false); } @@ -721,7 +884,7 @@ public void setSelectedItem(int position) { } - private class ChatThemeView extends FrameLayout implements Animator.AnimatorListener, ValueAnimator.AnimatorUpdateListener { + public static class ChatThemeView extends FrameLayout implements Animator.AnimatorListener, ValueAnimator.AnimatorUpdateListener { private final float STROKE_RADIUS = AndroidUtilities.dp(8); private final float INNER_RADIUS = AndroidUtilities.dp(6); @@ -743,12 +906,16 @@ private class ChatThemeView extends FrameLayout implements Animator.AnimatorList private StaticLayout textLayout; private ChatThemeItem chatThemeItem; private BackupImageView backupImageView; - private boolean isDark; private boolean hasAnimatedEmoji; + private final int currentAccount; Runnable animationCancelRunnable; + private int currentType; + int patternColor; - public ChatThemeView(Context context, Theme.ResourcesProvider resourcesProvider) { + public ChatThemeView(Context context, int currentAccount, Theme.ResourcesProvider resourcesProvider, int currentType) { super(context); + this.currentType = currentType; + this.currentAccount = currentAccount; this.resourcesProvider = resourcesProvider; strokePaint.setStyle(Paint.Style.STROKE); strokePaint.setStrokeWidth(AndroidUtilities.dp(2)); @@ -757,14 +924,28 @@ public ChatThemeView(Context context, Theme.ResourcesProvider resourcesProvider) backupImageView.getImageReceiver().setCrossfadeWithOldImage(true); backupImageView.getImageReceiver().setAllowStartLottieAnimation(false); backupImageView.getImageReceiver().setAutoRepeat(0); - addView(backupImageView, LayoutHelper.createFrame(28, 28, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 12)); + if (currentType == TYPE_DEFAULT) { + addView(backupImageView, LayoutHelper.createFrame(28, 28, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 12)); + } else { + addView(backupImageView, LayoutHelper.createFrame(36, 36, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 12)); + } + } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int height = MeasureSpec.getSize(heightMeasureSpec); - int width = AndroidUtilities.dp(77); - super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); + if (currentType == TYPE_GRID) { + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = (int) (width * 1.2f); + super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); + } else { + int height = MeasureSpec.getSize(heightMeasureSpec); + int width = AndroidUtilities.dp(77); + super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); + } + + backupImageView.setPivotY(backupImageView.getMeasuredHeight()); + backupImageView.setPivotX(backupImageView.getMeasuredWidth() / 2f); } @Override @@ -790,7 +971,7 @@ protected void dispatchDraw(Canvas canvas) { canvas.drawRoundRect(rectF, STROKE_RADIUS, STROKE_RADIUS, strokePaint); } rectF.set(INNER_RECT_SPACE, INNER_RECT_SPACE, getWidth() - INNER_RECT_SPACE, getHeight() - INNER_RECT_SPACE); - if (chatThemeItem.chatTheme == null || chatThemeItem.chatTheme.isDefault) { + if (chatThemeItem.chatTheme == null || chatThemeItem.chatTheme.showAsDefaultStub) { canvas.drawRoundRect(rectF, INNER_RADIUS, INNER_RADIUS, backgroundFillPaint); canvas.save(); StaticLayout textLayout = getNoThemeStaticLayout(); @@ -801,7 +982,21 @@ protected void dispatchDraw(Canvas canvas) { if (chatThemeItem.previewDrawable != null) { canvas.save(); canvas.clipPath(clipPath); - chatThemeItem.previewDrawable.setBounds(0, 0, getWidth(), getHeight()); + if (chatThemeItem.previewDrawable instanceof BitmapDrawable) { + int drawableW = chatThemeItem.previewDrawable.getIntrinsicWidth(); + int drawableH = chatThemeItem.previewDrawable.getIntrinsicHeight(); + if (drawableW / (float) drawableH > getWidth() / (float) getHeight()) { + int w = (int) (getWidth() * (float) drawableH / drawableW); + int padding = (w - getWidth()) / 2; + chatThemeItem.previewDrawable.setBounds(padding, 0, padding + w , getHeight()); + } else { + int h = (int) (getHeight() * (float) drawableH / drawableW); + int padding = (getHeight() - h) / 2; + chatThemeItem.previewDrawable.setBounds(0, padding, getWidth(), padding + h); + } + } else { + chatThemeItem.previewDrawable.setBounds(0, 0, getWidth(), getHeight()); + } chatThemeItem.previewDrawable.draw(canvas); canvas.restore(); } else { @@ -809,22 +1004,40 @@ protected void dispatchDraw(Canvas canvas) { } float bubbleTop = INNER_RECT_SPACE + AndroidUtilities.dp(8); float bubbleLeft = INNER_RECT_SPACE + AndroidUtilities.dp(22); - rectF.set(bubbleLeft, bubbleTop, bubbleLeft + BUBBLE_WIDTH, bubbleTop + BUBBLE_HEIGHT); + if (currentType == TYPE_DEFAULT) { + rectF.set(bubbleLeft, bubbleTop, bubbleLeft + BUBBLE_WIDTH, bubbleTop + BUBBLE_HEIGHT); + } else { + bubbleTop = getMeasuredHeight() * 0.12f; + bubbleLeft = getMeasuredWidth() - getMeasuredWidth() * 0.6f; + float bubbleRight = getMeasuredWidth() - getMeasuredWidth() * 0.1f; + float bubbleBottom = getMeasuredHeight() * 0.32f; + rectF.set(bubbleLeft, bubbleTop, bubbleRight, bubbleBottom); + } canvas.drawRoundRect(rectF, rectF.height() * 0.5f, rectF.height() * 0.5f, outBubblePaintFirst); canvas.drawRoundRect(rectF, rectF.height() * 0.5f, rectF.height() * 0.5f, outBubblePaintSecond); - bubbleLeft = INNER_RECT_SPACE + AndroidUtilities.dp(5); - bubbleTop += BUBBLE_HEIGHT + AndroidUtilities.dp(4); - rectF.set(bubbleLeft, bubbleTop, bubbleLeft + BUBBLE_WIDTH, bubbleTop + BUBBLE_HEIGHT); + + if (currentType == TYPE_DEFAULT) { + bubbleLeft = INNER_RECT_SPACE + AndroidUtilities.dp(5); + bubbleTop += BUBBLE_HEIGHT + AndroidUtilities.dp(4); + rectF.set(bubbleLeft, bubbleTop, bubbleLeft + BUBBLE_WIDTH, bubbleTop + BUBBLE_HEIGHT); + } else { + bubbleTop = getMeasuredHeight() * 0.35f; + bubbleLeft = getMeasuredWidth() * 0.1f; + float bubbleRight = getMeasuredWidth() * 0.6f; + float bubbleBottom = getMeasuredHeight() * 0.55f; + rectF.set(bubbleLeft, bubbleTop, bubbleRight, bubbleBottom); + } + canvas.drawRoundRect(rectF, rectF.height() * 0.5f, rectF.height() * 0.5f, inBubblePaint); } super.dispatchDraw(canvas); } - + int lastThemeIndex; public void setItem(ChatThemeItem item) { boolean itemChanged = chatThemeItem != item; - boolean darkModeChanged = isDark != item.isDark; - isDark = item.isDark; + boolean darkModeChanged = lastThemeIndex != item.themeIndex; + lastThemeIndex = item.themeIndex; this.chatThemeItem = item; hasAnimatedEmoji = false; TLRPC.Document document = null; @@ -840,27 +1053,39 @@ public void setItem(ChatThemeItem item) { backupImageView.setScaleX(1f); backupImageView.setScaleY(1f); } + if (itemChanged) { + Drawable thumb = null; + if (document != null) { + thumb = DocumentObject.getSvgThumb(document, Theme.key_emptyListPlaceholder, 0.2f); + } + if (thumb == null) { + thumb = Emoji.getEmojiDrawable(item.chatTheme.getEmoticon()); + } + backupImageView.setImage(ImageLocation.getForDocument(document), "50_50", thumb, null); + } - backupImageView.setImage(ImageLocation.getForDocument(document), "50_50", Emoji.getEmojiDrawable(item.chatTheme == null ? "❌" : item.chatTheme.getEmoticon()), null); - - if (item.chatTheme != null && !item.chatTheme.isDefault) { + if (itemChanged || darkModeChanged) { updatePreviewBackground(); - if (itemChanged || darkModeChanged) { - final long themeId = item.chatTheme.getTlTheme(isDark).id; - final int intensity = item.chatTheme.getWallpaper(isDark).settings.intensity; - item.chatTheme.loadWallpaperThumb(isDark, result -> { - if (result != null && result.first == themeId) { - MotionBackgroundDrawable drawable = getPreviewDrawable(); - if (drawable != null) { - drawable.setPatternBitmap(intensity >= 0 ? 100 : -100, result.second); - drawable.setPatternColorFilter(drawable.getPatternColor()); + TLRPC.TL_theme theme = item.chatTheme.getTlTheme(lastThemeIndex); + if (theme != null) { + final long themeId = theme.id; + TLRPC.WallPaper wallPaper = item.chatTheme.getWallpaper(lastThemeIndex); + if (wallPaper != null) { + final int intensity = wallPaper.settings.intensity; + int index = item.chatTheme.getSettingsIndex(lastThemeIndex); + item.chatTheme.loadWallpaperThumb(lastThemeIndex, result -> { + if (result != null && result.first == themeId) { + if (item.previewDrawable instanceof MotionBackgroundDrawable) { + MotionBackgroundDrawable motionBackgroundDrawable = (MotionBackgroundDrawable) item.previewDrawable; + motionBackgroundDrawable.setPatternBitmap(intensity >= 0 ? 100 : -100, result.second); + motionBackgroundDrawable.setPatternColorFilter(patternColor); + } + invalidate(); } - invalidate(); - } - }); + }); + } } } - setBackgroundColor(0); } @Override @@ -905,55 +1130,110 @@ private void fillOutBubblePaint(Paint paint, List messageColors) { } public void updatePreviewBackground() { - if (chatThemeItem == null || chatThemeItem.chatTheme == null || chatThemeItem.chatTheme.isDefault) { + if (chatThemeItem == null || chatThemeItem.chatTheme == null) { return; } - int color = chatThemeItem.isDark ? chatThemeItem.inBubbleColorDark : chatThemeItem.inBubbleColorLight; + EmojiThemes.ThemeItem themeItem = chatThemeItem.chatTheme.getThemeItem(chatThemeItem.themeIndex); + int color = themeItem.inBubbleColor; inBubblePaint.setColor(color); - color = chatThemeItem.isDark ? chatThemeItem.outBubbleColorDark : chatThemeItem.outBubbleColorLight; + color = themeItem.outBubbleColor; outBubblePaintSecond.setColor(color); - TLRPC.TL_theme firstTlTheme = chatThemeItem.chatTheme.getTlTheme(!chatThemeItem.isDark); - fillOutBubblePaint(outBubblePaintFirst, firstTlTheme.settings.message_colors); - TLRPC.TL_theme secondTlTheme = chatThemeItem.chatTheme.getTlTheme(chatThemeItem.isDark); - fillOutBubblePaint(outBubblePaintSecond, secondTlTheme.settings.message_colors); - outBubblePaintSecond.setAlpha(255); - - MotionBackgroundDrawable drawable = getPreviewDrawable(); - if (drawable != null) { - TLRPC.WallPaperSettings secondSettings = secondTlTheme.settings.wallpaper.settings; - int color1 = 0xff000000 | secondSettings.background_color; - if (color1 == 0xff000000) { - color1 = Color.TRANSPARENT; - } - int color2 = 0xff000000 | secondSettings.second_background_color; - if (color2 == 0xff000000) { - color2 = Color.TRANSPARENT; - } - int color3 = 0xff000000 | secondSettings.third_background_color; - if (color3 == 0xff000000) { - color3 = Color.TRANSPARENT; - } - int color4 = 0xff000000 | secondSettings.fourth_background_color; - if (color4 == 0xff000000) { - color4 = Color.TRANSPARENT; - } - drawable.setPatternBitmap(secondSettings.intensity >= 0 ? 100 : -100); - drawable.setColors(color1, color2, color3, color4, false); - drawable.setPatternColorFilter(drawable.getPatternColor()); + int strokeColor = chatThemeItem.chatTheme.showAsDefaultStub + ? getThemedColor(Theme.key_featuredStickers_addButton) + : themeItem.outLineColor; + int strokeAlpha = strokePaint.getAlpha(); + strokePaint.setColor(strokeColor); + strokePaint.setAlpha(strokeAlpha); + + + TLRPC.TL_theme tlTheme = chatThemeItem.chatTheme.getTlTheme(chatThemeItem.themeIndex); + + if (tlTheme != null) { + int index = chatThemeItem.chatTheme.getSettingsIndex(chatThemeItem.themeIndex); + TLRPC.ThemeSettings themeSettings = tlTheme.settings.get(index); + fillOutBubblePaint(outBubblePaintSecond, themeSettings.message_colors); + + outBubblePaintSecond.setAlpha(255); + getPreviewDrawable(tlTheme, index); + } else { + EmojiThemes.ThemeItem item = chatThemeItem.chatTheme.getThemeItem(chatThemeItem.themeIndex); + getPreviewDrawable(item); } + + invalidate(); } - private MotionBackgroundDrawable getPreviewDrawable() { + private Drawable getPreviewDrawable(TLRPC.TL_theme theme, int settingsIndex) { + if (chatThemeItem == null) { + return null; + } + + int color1 = 0; + int color2 = 0; + int color3 = 0; + int color4 = 0; + + Drawable drawable; + if (settingsIndex >= 0) { + TLRPC.ThemeSettings themeSettings = theme.settings.get(settingsIndex); + TLRPC.WallPaperSettings wallPaperSettings = themeSettings.wallpaper.settings; + color1 = wallPaperSettings.background_color; + color2 = wallPaperSettings.second_background_color; + color3 = wallPaperSettings.third_background_color; + color4 = wallPaperSettings.fourth_background_color; + } + if (color2 != 0) { + MotionBackgroundDrawable motionBackgroundDrawable = new MotionBackgroundDrawable(color1, color2, color3, color4, true); + patternColor = motionBackgroundDrawable.getPatternColor(); + drawable = motionBackgroundDrawable; + } else { + drawable = new MotionBackgroundDrawable(color1, color1, color1, color1, true); + patternColor = Color.BLACK; + } + chatThemeItem.previewDrawable = drawable; + + return drawable; + } + + private Drawable getPreviewDrawable(EmojiThemes.ThemeItem item) { if (chatThemeItem == null) { return null; } - MotionBackgroundDrawable drawable = chatThemeItem.previewDrawable; - if (drawable == null) { - drawable = new MotionBackgroundDrawable(); - chatThemeItem.previewDrawable = drawable; + Drawable drawable = null; + + int color1 = item.patternBgColor; + int color2 = item.patternBgGradientColor1; + int color3 = item.patternBgGradientColor2; + int color4 = item.patternBgGradientColor3; + + if (item.themeInfo.getAccent(false) != null) { + if (color2 != 0) { + MotionBackgroundDrawable motionBackgroundDrawable = new MotionBackgroundDrawable(color1, color2, color3, color4, true); + patternColor = motionBackgroundDrawable.getPatternColor(); + drawable = motionBackgroundDrawable; + } else { + drawable = new MotionBackgroundDrawable(color1, color1, color1, color1, true); + patternColor = Color.BLACK; + } + } else { + if (color1 != 0 && color2 != 0) { + drawable = new MotionBackgroundDrawable(color1, color2, color3, color4, true); + } else if (color1 != 0) { + drawable = new ColorDrawable(color1); + } else if (item.themeInfo != null && (item.themeInfo.previewWallpaperOffset > 0 || item.themeInfo.pathToWallpaper != null)) { + Bitmap wallpaper = getScaledBitmap(AndroidUtilities.dp(76), AndroidUtilities.dp(97), item.themeInfo.pathToWallpaper, item.themeInfo.pathToFile, item.themeInfo.previewWallpaperOffset); + if (wallpaper != null) { + drawable = new BitmapDrawable(wallpaper); + } + } else { + drawable = new MotionBackgroundDrawable(0xffdbddbb, 0xff6ba587, 0xffd5d88d, 0xff88b884, true); + } } + + chatThemeItem.previewDrawable = drawable; + return drawable; } @@ -983,9 +1263,10 @@ private int getThemedColor(String key) { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { - int strokeColor = chatThemeItem.chatTheme.isDefault + EmojiThemes.ThemeItem themeItem = chatThemeItem.chatTheme.getThemeItem(chatThemeItem.themeIndex); + int strokeColor = chatThemeItem.chatTheme.showAsDefaultStub ? getThemedColor(Theme.key_featuredStickers_addButton) - : chatThemeItem.isDark ? chatThemeItem.strokeColorDark : chatThemeItem.strokeColorLight; + : themeItem.outLineColor; strokePaint.setColor(strokeColor); strokePaint.setAlpha((int) valueAnimator.getAnimatedValue()); invalidate(); @@ -1017,8 +1298,6 @@ public void playEmojiAnimation() { backupImageView.setVisibility(View.VISIBLE); backupImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(0, false); backupImageView.getImageReceiver().getLottieAnimation().start(); - backupImageView.setPivotY(AndroidUtilities.dp(24)); - backupImageView.setPivotX(AndroidUtilities.dp(12)); backupImageView.animate().scaleX(2f).scaleY(2f).setDuration(300).setInterpolator(AndroidUtilities.overshootInterpolator).start(); AndroidUtilities.runOnUIThread(animationCancelRunnable = () -> { @@ -1037,21 +1316,15 @@ public void cancelAnimation() { } } - private static class ChatThemeItem { + public static class ChatThemeItem { - public final ChatTheme chatTheme; - public MotionBackgroundDrawable previewDrawable; - public boolean isDark; + public final EmojiThemes chatTheme; + public Drawable previewDrawable; + public int themeIndex; public boolean isSelected; public float animationProgress = 1f; - public int inBubbleColorLight; - public int inBubbleColorDark; - public int outBubbleColorLight; - public int outBubbleColorDark; - public int strokeColorDark; - public int strokeColorLight; - - public ChatThemeItem(ChatTheme chatTheme) { + + public ChatThemeItem(EmojiThemes chatTheme) { this.chatTheme = chatTheme; } } @@ -1061,4 +1334,54 @@ public void show() { super.show(); resetTextView.setText(themeDelegate.getCurrentTheme() == null ? LocaleController.getString("DoNoSetTheme", R.string.DoNoSetTheme) : LocaleController.getString("ChatResetTheme", R.string.ChatResetTheme)); } + + public static Bitmap getScaledBitmap(float w, float h, String path, String streamPath, int streamOffset) { + FileInputStream stream = null; + try { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + + if (path != null) { + BitmapFactory.decodeFile(path, options); + } else { + stream = new FileInputStream(streamPath); + stream.getChannel().position(streamOffset); + BitmapFactory.decodeStream(stream, null, options); + } + if (options.outWidth > 0 && options.outHeight > 0) { + if (w > h && options.outWidth < options.outHeight) { + float temp = w; + w = h; + h = temp; + } + float scale = Math.min(options.outWidth / w, options.outHeight / h); + options.inSampleSize = 1; + if (scale > 1.0f) { + do { + options.inSampleSize *= 2; + } while (options.inSampleSize < scale); + } + options.inJustDecodeBounds = false; + Bitmap wallpaper; + if (path != null) { + wallpaper = BitmapFactory.decodeFile(path, options); + } else { + stream.getChannel().position(streamOffset); + wallpaper = BitmapFactory.decodeStream(stream, null, options); + } + return wallpaper; + } + } catch (Throwable e) { + FileLog.e(e); + } finally { + try { + if (stream != null) { + stream.close(); + } + } catch (Exception e2) { + FileLog.e(e2); + } + } + return null; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java index cf11f36d300..4989d8740a5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java @@ -33,6 +33,7 @@ public class FlickerLoadingView extends View { public final static int SHARE_ALERT_TYPE = 12; public final static int MESSAGE_SEEN_TYPE = 13; public final static int CHAT_THEMES_TYPE = 14; + public final static int MEMBER_REQUESTS_TYPE = 15; private int gradientWidth; private LinearGradient gradient; @@ -62,6 +63,11 @@ public class FlickerLoadingView extends View { float[] randomParams; private Paint backgroundPaint; + private int parentWidth; + private int parentHeight; + private float parentXOffset; + + FlickerLoadingView globalGradientView; public void setViewType(int type) { this.viewType = type; @@ -119,19 +125,19 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { @Override protected void onDraw(Canvas canvas) { - int color0 = getThemedColor(colorKey1); - int color1 = getThemedColor(colorKey2); - if (this.color1 != color1 || this.color0 != color0) { - this.color0 = color0; - this.color1 = color1; - if (isSingleCell || viewType == MESSAGE_SEEN_TYPE || viewType == CHAT_THEMES_TYPE) { - gradient = new LinearGradient(0, 0, gradientWidth = AndroidUtilities.dp(200), 0, new int[]{color1, color0, color0, color1}, new float[]{0.0f, 0.4f, 0.6f, 1f}, Shader.TileMode.CLAMP); - } else { - gradient = new LinearGradient(0, 0, 0, gradientWidth = AndroidUtilities.dp(600), new int[]{color1, color0, color0, color1}, new float[]{0.0f, 0.4f, 0.6f, 1f}, Shader.TileMode.CLAMP); + + Paint paint = this.paint; + if (globalGradientView != null) { + if (getParent() != null) { + View parent = (View) getParent(); + globalGradientView.setParentSize(parent.getMeasuredWidth(), parent.getMeasuredHeight(), -getX()); } - paint.setShader(gradient); + paint = globalGradientView.paint; } + updateColors(); + updateGradient(); + int h = paddingTop; if (useHeaderOffset) { h += AndroidUtilities.dp(32); @@ -465,29 +471,86 @@ protected void onDraw(Canvas canvas) { canvas.drawCircle(x + itemWidth / 2, getMeasuredHeight() - AndroidUtilities.dp(20), AndroidUtilities.dp(8), backgroundPaint); x += itemWidth; } + } else if (getViewType() == MEMBER_REQUESTS_TYPE) { + int count = 0; + int radius = AndroidUtilities.dp(23); + int rectRadius = AndroidUtilities.dp(4); + while (h <= getMeasuredHeight()) { + canvas.drawCircle(checkRtl(paddingLeft + AndroidUtilities.dp(12)) + radius, h + AndroidUtilities.dp(8) + radius, radius, paint); + + rectF.set(paddingLeft + AndroidUtilities.dp(74), h + AndroidUtilities.dp(12), paddingLeft + AndroidUtilities.dp(260), h + AndroidUtilities.dp(20)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, rectRadius, rectRadius, paint); + + rectF.set(paddingLeft + AndroidUtilities.dp(74), h + AndroidUtilities.dp(36), paddingLeft + AndroidUtilities.dp(140), h + AndroidUtilities.dp(42)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, rectRadius, rectRadius, paint); + + h += getCellHeight(getMeasuredWidth()); + count++; + if (isSingleCell && count >= itemsCount) { + break; + } + } } + invalidate(); + } + public void updateGradient() { + if (globalGradientView != null) { + globalGradientView.updateGradient(); + return; + } long newUpdateTime = SystemClock.elapsedRealtime(); long dt = Math.abs(lastUpdateTime - newUpdateTime); if (dt > 17) { dt = 16; } + if (dt < 4) { + dt = 0; + } + int width = parentWidth; + if (width == 0) { + width = getMeasuredWidth(); + } + int height = parentHeight; + if (height == 0) { + height = getMeasuredHeight(); + } lastUpdateTime = newUpdateTime; if (isSingleCell || viewType == MESSAGE_SEEN_TYPE || getViewType() == CHAT_THEMES_TYPE) { - totalTranslation += dt * getMeasuredWidth() / 400.0f; - if (totalTranslation >= getMeasuredWidth() * 2) { + totalTranslation += dt * width / 400.0f; + if (totalTranslation >= width * 2) { totalTranslation = -gradientWidth * 2; } - matrix.setTranslate(totalTranslation, 0); + matrix.setTranslate(totalTranslation + parentXOffset, 0); } else { - totalTranslation += dt * getMeasuredHeight() / 400.0f; - if (totalTranslation >= getMeasuredHeight() * 2) { + totalTranslation += dt * height / 400.0f; + if (totalTranslation >= height * 2) { totalTranslation = -gradientWidth * 2; } - matrix.setTranslate(0, totalTranslation); + matrix.setTranslate(parentXOffset, totalTranslation); } gradient.setLocalMatrix(matrix); - invalidate(); + } + + public void updateColors() { + if (globalGradientView != null) { + globalGradientView.updateColors(); + return; + } + int color0 = getThemedColor(colorKey1); + int color1 = getThemedColor(colorKey2); + if (this.color1 != color1 || this.color0 != color0) { + this.color0 = color0; + this.color1 = color1; + if (isSingleCell || viewType == MESSAGE_SEEN_TYPE || viewType == CHAT_THEMES_TYPE) { + gradient = new LinearGradient(0, 0, gradientWidth = AndroidUtilities.dp(200), 0, new int[]{color1, color0, color0, color1}, new float[]{0.0f, 0.4f, 0.6f, 1f}, Shader.TileMode.CLAMP); + } else { + gradient = new LinearGradient(0, 0, 0, gradientWidth = AndroidUtilities.dp(600), new int[]{color1, color0, color0, color1}, new float[]{0.0f, 0.4f, 0.6f, 1f}, Shader.TileMode.CLAMP); + } + paint.setShader(gradient); + } } private float checkRtl(float x) { @@ -513,9 +576,9 @@ private int getCellHeight(int width) { int photoWidth = (width - (AndroidUtilities.dp(2) * (getColumnsCount() - 1))) / getColumnsCount(); return photoWidth + AndroidUtilities.dp(2); } else if (getViewType() == 3) { - return AndroidUtilities.dp(56) + 1; + return AndroidUtilities.dp(56); } else if (getViewType() == 4) { - return AndroidUtilities.dp(56) + 1; + return AndroidUtilities.dp(56); } else if (getViewType() == 5) { return AndroidUtilities.dp(80); } else if (getViewType() == USERS_TYPE) { @@ -530,6 +593,8 @@ private int getCellHeight(int width) { return AndroidUtilities.dp(36); } else if (getViewType() == SHARE_ALERT_TYPE) { return AndroidUtilities.dp(103); + } else if (getViewType() == MEMBER_REQUESTS_TYPE) { + return AndroidUtilities.dp(107); } return 0; } @@ -564,4 +629,18 @@ private int getThemedColor(String key) { Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null; return color != null ? color : Theme.getColor(key); } + + public void setGlobalGradientView(FlickerLoadingView globalGradientView) { + this.globalGradientView = globalGradientView; + } + + public void setParentSize(int parentWidth, int parentHeight, float parentXOffset) { + this.parentWidth = parentWidth; + this.parentHeight = parentHeight; + this.parentXOffset = parentXOffset; + } + + public Paint getPaint() { + return paint; + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardingPreviewView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardingPreviewView.java index 499caef1ef5..f5ee2d2fd60 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardingPreviewView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardingPreviewView.java @@ -122,6 +122,14 @@ protected Drawable getNewDrawable() { Drawable drawable = resourcesProvider.getWallpaperDrawable(); return drawable != null ? drawable : super.getNewDrawable(); } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (ev.getY() < currentTopOffset) { + return false; + } + return super.dispatchTouchEvent(ev); + } }; chatPreviewContainer.setBackgroundImage(resourcesProvider.getWallpaperDrawable(), resourcesProvider.isWallpaperMotion()); chatPreviewContainer.setOccupyStatusBar(false); @@ -326,6 +334,7 @@ private void drawChatBackgroundElements(Canvas canvas) { } } } + }; chatListView.setItemAnimator(itemAnimator = new ChatListItemAnimator(null, chatListView, resourcesProvider) { @@ -961,7 +970,7 @@ private class Adapter extends RecyclerView.Adapter { @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - ChatMessageCell chatMessageCell = new ChatMessageCell(parent.getContext(), resourcesProvider); + ChatMessageCell chatMessageCell = new ChatMessageCell(parent.getContext(), false, resourcesProvider); return new RecyclerListView.Holder(chatMessageCell); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java index b588a7dbb01..a581b424001 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java @@ -594,7 +594,9 @@ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); if (fragment != null && messageObject != null) { if (messageObject.isMusic()) { - fragment.showDialog(new AudioPlayerAlert(getContext(), resourcesProvider)); + if (getContext() instanceof LaunchActivity) { + fragment.showDialog(new AudioPlayerAlert(getContext(), resourcesProvider)); + } } else { long dialogId = 0; if (fragment instanceof ChatActivity) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java index fa5876edd3f..0fa1172eecb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java @@ -116,11 +116,17 @@ public void fillList() { int newCount = 0; Object currentObject = null; if (imagesArrLocations != null && !imagesArrLocations.isEmpty()) { + if (currentIndex >= imagesArrLocations.size()) { + currentIndex = imagesArrLocations.size() - 1; + } ImageLocation location = imagesArrLocations.get(currentIndex); newCount = imagesArrLocations.size(); currentObject = location; hasPhotos = true; } else if (imagesArr != null && !imagesArr.isEmpty()) { + if (currentIndex >= imagesArr.size()) { + currentIndex = imagesArr.size() - 1; + } MessageObject messageObject = imagesArr.get(currentIndex); currentObject = messageObject; long localGroupId = delegate.validGroupId(messageObject.getGroupIdForUse()) ? messageObject.getGroupIdForUse() : 0; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java index bd89f035932..1617c040ce0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java @@ -717,7 +717,7 @@ private void processBitmap(Bitmap bitmap, MessageObject avatarObject) { try { Bitmap b = BitmapFactory.decodeFile(FileLoader.getPathToAttach(smallPhoto, true).getAbsolutePath()); String key = smallPhoto.location.volume_id + "_" + smallPhoto.location.local_id + "@50_50"; - ImageLoader.getInstance().putImageToCache(new BitmapDrawable(b), key); + ImageLoader.getInstance().putImageToCache(new BitmapDrawable(b), key, true); } catch (Throwable ignore) { } @@ -869,7 +869,7 @@ public void didReceivedNotification(int id, int account, Object... args) { try { Bitmap b = BitmapFactory.decodeFile(FileLoader.getPathToAttach(smallPhoto, true).getAbsolutePath()); String key = smallPhoto.location.volume_id + "_" + smallPhoto.location.local_id + "@50_50"; - ImageLoader.getInstance().putImageToCache(new BitmapDrawable(b), key); + ImageLoader.getInstance().putImageToCache(new BitmapDrawable(b), key, true); } catch (Throwable ignore) { } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteLinkBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteLinkBottomSheet.java index f841433e225..945a0f197ae 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteLinkBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteLinkBottomSheet.java @@ -12,6 +12,7 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; +import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; @@ -26,6 +27,7 @@ import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; @@ -46,7 +48,9 @@ import org.telegram.ui.ProfileActivity; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Locale; public class InviteLinkBottomSheet extends BottomSheet { @@ -59,15 +63,20 @@ public class InviteLinkBottomSheet extends BottomSheet { int creatorRow; int dividerRow; int divider2Row; - int usersHeaderRow; - int usersStartRow; - int usersEndRow; + int divider3Row; + int joinedHeaderRow; + int joinedStartRow; + int joinedEndRow; int linkActionRow; int linkInfoRow; int loadingRow; int emptyView; int emptyView2; + int emptyView3; int emptyHintRow; + int requestedHeaderRow; + int requestedStartRow; + int requestedEndRow; boolean usersLoading; boolean hasMore; @@ -86,7 +95,8 @@ public class InviteLinkBottomSheet extends BottomSheet { private boolean permanent; private boolean titleVisible; - ArrayList invitedUsers = new ArrayList<>(); + ArrayList joinedUsers = new ArrayList<>(); + ArrayList requestedUsers = new ArrayList<>(); private long chatId; private boolean isChannel; @@ -95,6 +105,7 @@ public class InviteLinkBottomSheet extends BottomSheet { InviteDelegate inviteDelegate; private boolean canEdit = true; + public boolean isNeedReopen = false; public InviteLinkBottomSheet(Context context, TLRPC.TL_chatInviteExported invite, TLRPC.ChatFull info, HashMap users, BaseFragment fragment, long chatId, boolean permanent, boolean isChannel) { super(context, false); @@ -263,28 +274,30 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { } } }); - listView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { - @Override - public void onItemClick(View view, int position) { - if (position == creatorRow && invite.admin_id == UserConfig.getInstance(currentAccount).clientUserId) { - return; + listView.setOnItemClickListener((view, position) -> { + if (position == creatorRow && invite.admin_id == UserConfig.getInstance(currentAccount).clientUserId) { + return; + } + boolean isJoinedUserRow = position >= joinedStartRow && position < joinedEndRow; + boolean isRequestedUserRow = position >= requestedStartRow && position < requestedEndRow; + if ((position == creatorRow || isJoinedUserRow || isRequestedUserRow) && users != null) { + long userId = invite.admin_id; + if (isJoinedUserRow) { + userId = joinedUsers.get(position - joinedStartRow).user_id; + } else if (isRequestedUserRow) { + userId = requestedUsers.get(position - requestedStartRow).user_id; } - if (position == creatorRow || (position >= usersStartRow && position < usersEndRow)) { - TLRPC.User user; - if (position == creatorRow) { - user = users.get(invite.admin_id); - } else { - TLRPC.TL_chatInviteImporter invitedUser = invitedUsers.get(position - usersStartRow); - user = users.get(invitedUser.user_id); - } - if (user != null) { + TLRPC.User user = users.get(userId); + if (user != null) { + MessagesController.getInstance(UserConfig.selectedAccount).putUser(user, false); + AndroidUtilities.runOnUIThread(() -> { Bundle bundle = new Bundle(); bundle.putLong("user_id", user.id); - MessagesController.getInstance(UserConfig.selectedAccount).putUser(user, false); ProfileActivity profileActivity = new ProfileActivity(bundle); fragment.presentFragment(profileActivity); - dismiss(); - } + isNeedReopen = true; + }, 100); + dismiss(); } } }); @@ -305,7 +318,6 @@ public void onItemClick(View view, int position) { } else { titleTextView.setText(LocaleController.getString("InviteLink", R.string.InviteLink)); } - titleVisible = true; } else { titleTextView.setText(LocaleController.getString("InviteLink", R.string.InviteLink)); @@ -313,6 +325,11 @@ public void onItemClick(View view, int position) { titleTextView.setVisibility(View.INVISIBLE); titleTextView.setAlpha(0f); } + if (!TextUtils.isEmpty(invite.title)) { + SpannableStringBuilder builder = new SpannableStringBuilder(invite.title); + Emoji.replaceEmoji(builder, titleTextView.getPaint().getFontMetricsInt(), (int) titleTextView.getPaint().getTextSize(), false); + titleTextView.setText(builder); + } containerView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, !titleVisible ? 0 : 48, 0, 0)); containerView.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, !titleVisible ? 48 : 50, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); @@ -359,6 +376,12 @@ public void updateColors() { containerView.invalidate(); } + @Override + public void show() { + super.show(); + isNeedReopen = false; + } + private void updateColorForView(View view) { if (view instanceof HeaderCell) { ((HeaderCell) view).getTextView().setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader)); @@ -417,13 +440,19 @@ private void updateRows() { rowCount = 0; dividerRow = -1; divider2Row = -1; - usersHeaderRow = -1; - usersStartRow = -1; - usersEndRow = -1; + divider3Row = -1; + joinedHeaderRow = -1; + joinedStartRow = -1; + joinedEndRow = -1; emptyView2 = -1; + emptyView3 = -1; linkActionRow = -1; linkInfoRow = -1; emptyHintRow = -1; + requestedHeaderRow = -1; + requestedStartRow = -1; + requestedEndRow = -1; + loadingRow = -1; if (!permanent) { linkActionRow = rowCount++; @@ -433,23 +462,35 @@ private void updateRows() { creatorRow = rowCount++; emptyView = rowCount++; - if (!(invite.usage == 0 && invite.usage_limit == 0)) { + boolean needUsers = invite.usage > 0 || invite.usage_limit > 0 || invite.requested > 0; + boolean usersLoaded = false; + if (!joinedUsers.isEmpty()) { dividerRow = rowCount++; - usersHeaderRow = rowCount++; - if (!invitedUsers.isEmpty()) { - usersStartRow = rowCount; - rowCount += invitedUsers.size(); - usersEndRow = rowCount; - emptyView2 = rowCount++; - } else if (invite.usage > 0) { + joinedHeaderRow = rowCount++; + joinedStartRow = rowCount; + rowCount += joinedUsers.size(); + joinedEndRow = rowCount; + emptyView2 = rowCount++; + usersLoaded = true; + } + if (!requestedUsers.isEmpty()) { + divider2Row = rowCount++; + requestedHeaderRow = rowCount++; + requestedStartRow = rowCount; + rowCount += requestedUsers.size(); + requestedEndRow = rowCount; + emptyView3 = rowCount++; + usersLoaded = true; + } + if (needUsers) { + if (!usersLoaded) { + dividerRow = rowCount++; loadingRow = rowCount++; emptyView2 = rowCount++; - } else { - emptyHintRow = rowCount++; } } if (emptyHintRow == -1) { - divider2Row = rowCount++; + divider3Row = rowCount++; } adapter.notifyDataSetChanged(); @@ -459,11 +500,11 @@ private class Adapter extends RecyclerListView.SelectionAdapter { @Override public int getItemViewType(int position) { - if (position == creatorHeaderRow) { + if (position == creatorHeaderRow || position == requestedHeaderRow || position == joinedHeaderRow) { return 0; - } else if (position == creatorRow || position >= usersStartRow && position < usersEndRow) { + } else if (position == creatorRow || position >= requestedStartRow && position < requestedEndRow || position >= joinedStartRow && position < joinedEndRow) { return 1; - } else if (position == dividerRow) { + } else if (position == dividerRow || position == divider2Row) { return 2; } else if (position == linkActionRow) { return 3; @@ -471,9 +512,9 @@ public int getItemViewType(int position) { return 4; } else if (position == loadingRow) { return 5; - } else if (position == emptyView || position == emptyView2) { + } else if (position == emptyView || position == emptyView2 || position == emptyView3) { return 6; - } else if (position == divider2Row) { + } else if (position == divider3Row) { return 7; } else if (position == emptyHintRow) { return 8; @@ -609,6 +650,7 @@ public void removeLink() { flickerLoadingView.setIsSingleCell(true); flickerLoadingView.setViewType(FlickerLoadingView.USERS2_TYPE); flickerLoadingView.showDate(false); + flickerLoadingView.setPaddingLeft(AndroidUtilities.dp(10)); view = flickerLoadingView; break; case 6: @@ -643,7 +685,7 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi if (position == creatorHeaderRow) { headerCell.setText(LocaleController.getString("LinkCreatedeBy", R.string.LinkCreatedeBy)); headerCell.setText2(null); - } else if (position == usersHeaderRow) { + } else if (position == joinedHeaderRow) { if (invite.usage > 0) { headerCell.setText(LocaleController.formatPluralString("PeopleJoined", invite.usage)); } else { @@ -654,6 +696,8 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi } else { headerCell.setText2(null); } + } else if (position == requestedHeaderRow) { + headerCell.setText(LocaleController.formatPluralString("JoinRequests", invite.requested)); } break; case 1: @@ -701,7 +745,13 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int positi } } } else { - TLRPC.TL_chatInviteImporter invitedUser = invitedUsers.get(position - usersStartRow); + int startRow = joinedStartRow; + List usersList = joinedUsers; + if (requestedStartRow != -1 && position >= requestedStartRow) { + startRow = requestedStartRow; + usersList = requestedUsers; + } + TLRPC.TL_chatInviteImporter invitedUser = usersList.get(position - startRow); user = users.get(invitedUser.user_id); } userCell.setAdminRole(role); @@ -783,7 +833,7 @@ public boolean isEnabled(RecyclerView.ViewHolder holder) { return false; } return true; - } else if (position >= usersStartRow && position < usersEndRow) { + } else if (position >= joinedStartRow && position < joinedEndRow || position >= requestedStartRow && position < requestedEndRow) { return true; } return false; @@ -840,7 +890,6 @@ public void onAnimationEnd(Animator animation) { if (shadowAnimation != null && shadowAnimation.equals(animation)) { if (!show) { shadow.setVisibility(View.INVISIBLE); - titleTextView.setVisibility(View.INVISIBLE); } shadowAnimation = null; } @@ -858,32 +907,48 @@ public void onAnimationCancel(Animator animation) { } public void loadUsers() { - if (invite.usage <= 0 || usersLoading) { + if (usersLoading) { return; } + + boolean hasMoreJoinedUsers = invite.usage > joinedUsers.size(); + boolean hasMoreRequestedUsers = invite.request_needed && invite.requested > requestedUsers.size(); + boolean loadRequestedUsers; + if (hasMoreJoinedUsers) { + loadRequestedUsers = false; + } else if (hasMoreRequestedUsers) { + loadRequestedUsers = true; + } else { + return; + } + + final List importersList = loadRequestedUsers ? requestedUsers : joinedUsers; TLRPC.TL_messages_getChatInviteImporters req = new TLRPC.TL_messages_getChatInviteImporters(); + req.flags |= 2; req.link = invite.link; req.peer = MessagesController.getInstance(UserConfig.selectedAccount).getInputPeer(-chatId); - if (invitedUsers.isEmpty()) { + req.requested = loadRequestedUsers; + if (importersList.isEmpty()) { req.offset_user = new TLRPC.TL_inputUserEmpty(); } else { - TLRPC.TL_chatInviteImporter invitedUser = invitedUsers.get(invitedUsers.size() - 1); + TLRPC.TL_chatInviteImporter invitedUser = importersList.get(importersList.size() - 1); req.offset_user = MessagesController.getInstance(currentAccount).getInputUser(users.get(invitedUser.user_id)); req.offset_date = invitedUser.date; } + usersLoading = true; ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> { AndroidUtilities.runOnUIThread(() -> { if (error == null) { TLRPC.TL_messages_chatInviteImporters inviteImporters = (TLRPC.TL_messages_chatInviteImporters) response; - - invitedUsers.addAll(inviteImporters.importers); - + importersList.addAll(inviteImporters.importers); for (int i = 0; i < inviteImporters.users.size(); i++) { TLRPC.User user = inviteImporters.users.get(i); users.put(user.id, user); } - hasMore = invitedUsers.size() < inviteImporters.count; + hasMore = loadRequestedUsers + ? importersList.size() < inviteImporters.count + : importersList.size() < inviteImporters.count || hasMoreRequestedUsers; updateRows(); } usersLoading = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteMembersBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteMembersBottomSheet.java index 50d9467f322..5fec41402d5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteMembersBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteMembersBottomSheet.java @@ -124,8 +124,8 @@ public interface InviteMembersBottomSheetDelegate { void didSelectDialogs(ArrayList dids); } - public InviteMembersBottomSheet(Context context, int account, LongSparseArray ignoreUsers, long chatId, BaseFragment parentFragment, Theme.ResourcesProvider resourcesProvider) { - super(context, false, account, null); + public InviteMembersBottomSheet(Context context, int account, LongSparseArray ignoreUsers, long chatId, BaseFragment parentFragment, Theme.ResourcesProvider resourcesProvider) { + super(context, false, account, resourcesProvider); this.ignoreUsers = ignoreUsers; needSnapToTop = false; this.parentFragment = parentFragment; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java index 643d5b0e2e2..f9ff8fd718e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java @@ -15,6 +15,8 @@ import android.view.Gravity; import android.view.View; import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -33,6 +35,7 @@ import org.telegram.ui.Cells.JoinSheetUserCell; import org.telegram.ui.ChatActivity; +import androidx.core.widget.NestedScrollView; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -41,6 +44,8 @@ public class JoinGroupAlert extends BottomSheet { private TLRPC.ChatInvite chatInvite; private String hash; private BaseFragment fragment; + private TextView requestTextView; + private RadialProgressView requestProgressView; public JoinGroupAlert(final Context context, TLRPC.ChatInvite invite, String group, BaseFragment parentFragment) { super(context, false); @@ -54,7 +59,22 @@ public JoinGroupAlert(final Context context, TLRPC.ChatInvite invite, String gro LinearLayout linearLayout = new LinearLayout(context); linearLayout.setOrientation(LinearLayout.VERTICAL); linearLayout.setClickable(true); - setCustomView(linearLayout); + + FrameLayout frameLayout = new FrameLayout(context); + frameLayout.addView(linearLayout); + + NestedScrollView scrollView = new NestedScrollView(context); + scrollView.addView(frameLayout); + setCustomView(scrollView); + + ImageView closeView = new ImageView(context); + closeView.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_listSelector))); + closeView.setColorFilter(Theme.getColor(Theme.key_sheet_other)); + closeView.setImageResource(R.drawable.ic_layer_close); + closeView.setOnClickListener((view) -> dismiss()); + int closeViewPadding = AndroidUtilities.dp(8); + closeView.setPadding(closeViewPadding, closeViewPadding, closeViewPadding, closeViewPadding); + frameLayout.addView(closeView, LayoutHelper.createFrame(36, 36, Gravity.TOP | Gravity.END, 6, 8, 6, 0)); String title; AvatarDrawable avatarDrawable; @@ -87,86 +107,160 @@ public JoinGroupAlert(final Context context, TLRPC.ChatInvite invite, String gro textView.setEllipsize(TextUtils.TruncateAt.END); linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 10, 9, 10, participants_count > 0 ? 0 : 20)); + final boolean isChannel = invite.channel && !invite.megagroup || ChatObject.isChannelAndNotMegaGroup(invite.chat); + boolean hasAbout = !TextUtils.isEmpty(invite.about); if (participants_count > 0) { textView = new TextView(context); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setTextColor(Theme.getColor(Theme.key_dialogTextGray3)); textView.setSingleLine(true); textView.setEllipsize(TextUtils.TruncateAt.END); - if (invite.channel || ChatObject.isChannel(invite.chat) && !invite.chat.megagroup) { + if (isChannel) { textView.setText(LocaleController.formatPluralString("Subscribers", participants_count)); } else { textView.setText(LocaleController.formatPluralString("Members", participants_count)); } - linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 10, 3, 10, 20)); + linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 10, 3, 10, hasAbout ? 0 : 20)); } - if (!invite.participants.isEmpty()) { - RecyclerListView listView = new RecyclerListView(context); - listView.setPadding(0, 0, 0, AndroidUtilities.dp(8)); - listView.setNestedScrollingEnabled(false); - listView.setClipToPadding(false); - listView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false)); - listView.setHorizontalScrollBarEnabled(false); - listView.setVerticalScrollBarEnabled(false); - listView.setAdapter(new UsersAdapter(context)); - listView.setGlowColor(Theme.getColor(Theme.key_dialogScrollGlow)); - linearLayout.addView(listView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 90, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0, 0, 7)); + if (hasAbout) { + TextView aboutTextView = new TextView(context); + aboutTextView.setGravity(Gravity.CENTER); + aboutTextView.setText(invite.about); + aboutTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + aboutTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + linearLayout.addView(aboutTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP, 24, 10, 24, 20)); } - View shadow = new View(context); - shadow.setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine)); - linearLayout.addView(shadow, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.getShadowHeight())); - - PickerBottomLayout pickerBottomLayout = new PickerBottomLayout(context, false); - linearLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); - pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); - pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); - pickerBottomLayout.cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase()); - pickerBottomLayout.cancelButton.setOnClickListener(view -> dismiss()); - pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); - pickerBottomLayout.doneButton.setVisibility(View.VISIBLE); - pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE); - pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); - if (invite.channel && !invite.megagroup || ChatObject.isChannel(invite.chat) && !invite.chat.megagroup) { - pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("ProfileJoinChannel", R.string.ProfileJoinChannel).toUpperCase()); - } else { - pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("JoinGroup", R.string.JoinGroup)); - } - pickerBottomLayout.doneButton.setOnClickListener(v -> { - dismiss(); - final TLRPC.TL_messages_importChatInvite req = new TLRPC.TL_messages_importChatInvite(); - req.hash = hash; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - if (error == null) { - TLRPC.Updates updates = (TLRPC.Updates) response; - MessagesController.getInstance(currentAccount).processUpdates(updates, false); - } + if (invite.request_needed) { + FrameLayout requestFrameLayout = new FrameLayout(getContext()); + linearLayout.addView(requestFrameLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + requestProgressView = new RadialProgressView(getContext(), resourcesProvider); + requestProgressView.setProgressColor(getThemedColor(Theme.key_featuredStickers_addButton)); + requestProgressView.setSize(AndroidUtilities.dp(32)); + requestProgressView.setVisibility(View.INVISIBLE); + requestFrameLayout.addView(requestProgressView, LayoutHelper.createFrame(48, 48, Gravity.CENTER)); + + requestTextView = new TextView(getContext()); + requestTextView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(6), getThemedColor(Theme.key_featuredStickers_addButton), getThemedColor(Theme.key_featuredStickers_addButtonPressed))); + requestTextView.setEllipsize(TextUtils.TruncateAt.END); + requestTextView.setGravity(Gravity.CENTER); + requestTextView.setSingleLine(true); + requestTextView.setText(isChannel ? LocaleController.getString("RequestToJoinChannel", R.string.RequestToJoinChannel) : LocaleController.getString("RequestToJoinGroup", R.string.RequestToJoinGroup)); + requestTextView.setTextColor(getThemedColor(Theme.key_featuredStickers_buttonText)); + requestTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + requestTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + requestTextView.setOnClickListener((view) -> { AndroidUtilities.runOnUIThread(() -> { - if (fragment == null || fragment.getParentActivity() == null) { - return; + if (!isDismissed()) { + requestTextView.setVisibility(View.INVISIBLE); + requestProgressView.setVisibility(View.VISIBLE); } + }, 400); + final TLRPC.TL_messages_importChatInvite request = new TLRPC.TL_messages_importChatInvite(); + request.hash = hash; + ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> { + AndroidUtilities.runOnUIThread(() -> { + if (fragment == null || fragment.getParentActivity() == null) { + return; + } + if (error != null) { + if ("INVITE_REQUEST_SENT".equals(error.text)) { + setOnDismissListener(dialog -> { + Bulletin.TwoLineLottieLayout layout = new Bulletin.TwoLineLottieLayout(context, fragment.getResourceProvider()); + layout.imageView.setAnimation(R.raw.timer_3, 28, 28); + layout.titleTextView.setText(LocaleController.getString("RequestToJoinSent", R.string.RequestToJoinSent)); + String subTitle = isChannel + ? LocaleController.getString("RequestToJoinChannelSentDescription", R.string.RequestToJoinChannelSentDescription) + : LocaleController.getString("RequestToJoinSentDescription", R.string.RequestToJoinGroupSentDescription); + layout.subtitleTextView.setText(subTitle); + Bulletin.make(fragment, layout, Bulletin.DURATION_LONG).show(); + }); + } else { + AlertsCreator.processError(currentAccount, error, fragment, request); + } + } + dismiss(); + }); + }, ConnectionsManager.RequestFlagFailOnServerErrors); + }); + requestFrameLayout.addView(requestTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.START, 16, 0, 16, 0)); + + TextView descriptionTextView = new TextView(getContext()); + descriptionTextView.setGravity(Gravity.CENTER); + descriptionTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + descriptionTextView.setText(isChannel ? LocaleController.getString("RequestToJoinChannelDescription", R.string.RequestToJoinChannelDescription) : LocaleController.getString("RequestToJoinGroupDescription", R.string.RequestToJoinGroupDescription)); + descriptionTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray3)); + linearLayout.addView(descriptionTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP, 24, 17, 24, 15)); + } else { + if (!invite.participants.isEmpty()) { + RecyclerListView listView = new RecyclerListView(context); + listView.setPadding(0, 0, 0, AndroidUtilities.dp(8)); + listView.setNestedScrollingEnabled(false); + listView.setClipToPadding(false); + listView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false)); + listView.setHorizontalScrollBarEnabled(false); + listView.setVerticalScrollBarEnabled(false); + listView.setAdapter(new UsersAdapter(context)); + listView.setGlowColor(Theme.getColor(Theme.key_dialogScrollGlow)); + linearLayout.addView(listView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 90, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0, 0, 7)); + } + + View shadow = new View(context); + shadow.setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine)); + linearLayout.addView(shadow, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.getShadowHeight())); + + PickerBottomLayout pickerBottomLayout = new PickerBottomLayout(context, false); + linearLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); + pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); + pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); + pickerBottomLayout.cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase()); + pickerBottomLayout.cancelButton.setOnClickListener(view -> dismiss()); + pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); + pickerBottomLayout.doneButton.setVisibility(View.VISIBLE); + pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE); + pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); + if (invite.channel && !invite.megagroup || ChatObject.isChannel(invite.chat) && !invite.chat.megagroup) { + pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("ProfileJoinChannel", R.string.ProfileJoinChannel).toUpperCase()); + } else { + pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("JoinGroup", R.string.JoinGroup)); + } + pickerBottomLayout.doneButton.setOnClickListener(v -> { + dismiss(); + final TLRPC.TL_messages_importChatInvite req = new TLRPC.TL_messages_importChatInvite(); + req.hash = hash; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (error == null) { TLRPC.Updates updates = (TLRPC.Updates) response; - if (!updates.chats.isEmpty()) { - TLRPC.Chat chat = updates.chats.get(0); - chat.left = false; - chat.kicked = false; - MessagesController.getInstance(currentAccount).putUsers(updates.users, false); - MessagesController.getInstance(currentAccount).putChats(updates.chats, false); - Bundle args = new Bundle(); - args.putLong("chat_id", chat.id); - if (MessagesController.getInstance(currentAccount).checkCanOpenChat(args, fragment)) { - ChatActivity chatActivity = new ChatActivity(args); - fragment.presentFragment(chatActivity, fragment instanceof ChatActivity); + MessagesController.getInstance(currentAccount).processUpdates(updates, false); + } + AndroidUtilities.runOnUIThread(() -> { + if (fragment == null || fragment.getParentActivity() == null) { + return; + } + if (error == null) { + TLRPC.Updates updates = (TLRPC.Updates) response; + if (!updates.chats.isEmpty()) { + TLRPC.Chat chat = updates.chats.get(0); + chat.left = false; + chat.kicked = false; + MessagesController.getInstance(currentAccount).putUsers(updates.users, false); + MessagesController.getInstance(currentAccount).putChats(updates.chats, false); + Bundle args = new Bundle(); + args.putLong("chat_id", chat.id); + if (MessagesController.getInstance(currentAccount).checkCanOpenChat(args, fragment)) { + ChatActivity chatActivity = new ChatActivity(args); + fragment.presentFragment(chatActivity, fragment instanceof ChatActivity); + } } + } else { + AlertsCreator.processError(currentAccount, error, fragment, req); } - } else { - AlertsCreator.processError(currentAccount, error, fragment, req); - } - }); - }, ConnectionsManager.RequestFlagFailOnServerErrors); - }); + }); + }, ConnectionsManager.RequestFlagFailOnServerErrors); + }); + } } private class UsersAdapter extends RecyclerListView.SelectionAdapter { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java new file mode 100644 index 00000000000..e3daf838cf2 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java @@ -0,0 +1,345 @@ +package org.telegram.ui.Components; + +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.PorterDuff; +import android.os.Build; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; +import android.widget.FrameLayout; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ContactsController; +import org.telegram.messenger.DialogObject; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLoader; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.BackDrawable; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.SimpleTextView; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ActionBar.ThemeDescription; +import org.telegram.ui.Cells.UserCell; +import org.telegram.ui.ProfileActivity; + +import java.util.ArrayList; + +public class MediaActivity extends BaseFragment implements SharedMediaLayout.SharedMediaPreloaderDelegate { + + private SharedMediaLayout.SharedMediaPreloader sharedMediaPreloader; + private TLRPC.ChatFull currentChatInfo; + private long dialogId; + private SimpleTextView nameTextView; + ProfileActivity.AvatarImageView avatarImageView; + + SharedMediaLayout sharedMediaLayout; + AudioPlayerAlert.ClippingTextViewSwitcher mediaCounterTextView; + + public MediaActivity(Bundle args, SharedMediaLayout.SharedMediaPreloader sharedMediaPreloader) { + super(args); + this.sharedMediaPreloader = sharedMediaPreloader; + } + + @Override + public boolean onFragmentCreate() { + dialogId = getArguments().getLong("dialog_id"); + if (this.sharedMediaPreloader == null) { + this.sharedMediaPreloader = new SharedMediaLayout.SharedMediaPreloader(this); + this.sharedMediaPreloader.addDelegate(this); + } + return super.onFragmentCreate(); + } + + @Override + public View createView(Context context) { + actionBar.setBackButtonDrawable(new BackDrawable(false)); + actionBar.setCastShadows(false); + actionBar.setAddToContainer(false); + actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { + @Override + public void onItemClick(int id) { + if (id == -1) { + finishFragment(); + } + } + }); + FrameLayout avatarContainer = new FrameLayout(context); + FrameLayout fragmentView = new FrameLayout(context) { + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + FrameLayout.LayoutParams lp = (LayoutParams) sharedMediaLayout.getLayoutParams(); + lp.topMargin = ActionBar.getCurrentActionBarHeight() + (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0); + + lp = (LayoutParams) avatarContainer.getLayoutParams(); + lp.topMargin = actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0; + lp.height = ActionBar.getCurrentActionBarHeight(); + + int textTop = (ActionBar.getCurrentActionBarHeight() / 2 - AndroidUtilities.dp(22)) / 2 + AndroidUtilities.dp(!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ? 4 : 5); + lp = (LayoutParams) nameTextView.getLayoutParams(); + lp.topMargin = textTop; + + textTop = ActionBar.getCurrentActionBarHeight() / 2 + (ActionBar.getCurrentActionBarHeight() / 2 - AndroidUtilities.dp(19)) / 2 - AndroidUtilities.dp(3); + lp = (LayoutParams) mediaCounterTextView.getLayoutParams(); + lp.topMargin = textTop; + + lp = (LayoutParams) avatarImageView.getLayoutParams(); + lp.topMargin = (ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(42)) / 2; + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (sharedMediaLayout != null && sharedMediaLayout.isInFastScroll() && sharedMediaLayout.getY() == 0) { + return sharedMediaLayout.dispatchFastScrollEvent(ev); + } + if (sharedMediaLayout != null && sharedMediaLayout.checkPinchToZoom(ev)) { + return true; + } + return super.dispatchTouchEvent(ev); + } + }; + this.fragmentView = fragmentView; + + nameTextView = new SimpleTextView(context); + + nameTextView.setTextSize(18); + nameTextView.setGravity(Gravity.LEFT); + nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + nameTextView.setLeftDrawableTopPadding(-AndroidUtilities.dp(1.3f)); + nameTextView.setScrollNonFitText(true); + nameTextView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); + avatarContainer.addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 118, 0, 56, 0)); + + avatarImageView = new ProfileActivity.AvatarImageView(context) { + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (getImageReceiver().hasNotThumb()) { + info.setText(LocaleController.getString("AccDescrProfilePicture", R.string.AccDescrProfilePicture)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + info.addAction(new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK, LocaleController.getString("Open", R.string.Open))); + info.addAction(new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_LONG_CLICK, LocaleController.getString("AccDescrOpenInPhotoViewer", R.string.AccDescrOpenInPhotoViewer))); + } + } else { + info.setVisibleToUser(false); + } + } + }; + avatarImageView.getImageReceiver().setAllowDecodeSingleFrame(true); + avatarImageView.setRoundRadius(AndroidUtilities.dp(21)); + avatarImageView.setPivotX(0); + avatarImageView.setPivotY(0); + AvatarDrawable avatarDrawable = new AvatarDrawable(); + avatarDrawable.setProfile(true); + + avatarImageView.setImageDrawable(avatarDrawable); + avatarContainer.addView(avatarImageView, LayoutHelper.createFrame(42, 42, Gravity.TOP | Gravity.LEFT, 64, 0, 0, 0)); + + mediaCounterTextView = new AudioPlayerAlert.ClippingTextViewSwitcher(context) { + @Override + protected TextView createTextView() { + TextView textView = new TextView(context); + textView.setTextColor(Theme.getColor(Theme.key_player_actionBarSubtitle)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setSingleLine(true); + textView.setEllipsize(TextUtils.TruncateAt.END); + textView.setGravity(Gravity.LEFT); + return textView; + } + }; + avatarContainer.addView(mediaCounterTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 118, 0, 56, 0)); + sharedMediaLayout = new SharedMediaLayout(context, dialogId, sharedMediaPreloader, 0, null, currentChatInfo, false, this, new SharedMediaLayout.Delegate() { + @Override + public void scrollToSharedMedia() { + + } + + @Override + public boolean onMemberClick(TLRPC.ChatParticipant participant, boolean b, boolean resultOnly) { + return false; + } + + @Override + public TLRPC.Chat getCurrentChat() { + return null; + } + + @Override + public boolean isFragmentOpened() { + return true; + } + + @Override + public RecyclerListView getListView() { + return null; + } + + @Override + public boolean canSearchMembers() { + return false; + } + + @Override + public void updateSelectedMediaTabText() { + updateMediaCount(); + } + }, SharedMediaLayout.VIEW_TYPE_MEDIA_ACTIVITY) { + @Override + protected void onSelectedTabChanged() { + updateMediaCount(); + } + + @Override + protected void onSearchStateChanged(boolean expanded) { + if (SharedConfig.smoothKeyboard) { + AndroidUtilities.removeAdjustResize(getParentActivity(), classGuid); + } + AndroidUtilities.updateViewVisibilityAnimated(avatarContainer, !expanded, 0.95f, true); + } + + }; + + sharedMediaLayout.getSearchItem().setTranslationY(0); + sharedMediaLayout.photoVideoOptionsItem.setTranslationY(0); + + fragmentView.addView(sharedMediaLayout); + fragmentView.addView(actionBar); + fragmentView.addView(avatarContainer); + + TLObject avatarObject = null; + if (DialogObject.isEncryptedDialog(dialogId)) { + TLRPC.EncryptedChat encryptedChat = getMessagesController().getEncryptedChat(DialogObject.getEncryptedChatId(dialogId)); + if (encryptedChat != null) { + TLRPC.User user = getMessagesController().getUser(encryptedChat.user_id); + if (user != null) { + nameTextView.setText(ContactsController.formatName(user.first_name, user.last_name)); + avatarDrawable.setInfo(user); + avatarObject = user; + } + } + } else if (DialogObject.isUserDialog(dialogId)) { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); + if (user != null) { + if (user.self) { + nameTextView.setText(LocaleController.getString("SavedMessages", R.string.SavedMessages)); + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_SAVED); + avatarDrawable.setSmallSize(true); + } else { + nameTextView.setText(ContactsController.formatName(user.first_name, user.last_name)); + avatarDrawable.setInfo(user); + avatarObject = user; + } + } + + } else { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); + if (chat != null) { + nameTextView.setText(chat.title); + avatarDrawable.setInfo(chat); + avatarObject = chat; + } + } + + final ImageLocation thumbLocation = ImageLocation.getForUserOrChat(avatarObject, ImageLocation.TYPE_SMALL); + avatarImageView.setImage(thumbLocation, "50_50", avatarDrawable, avatarObject); + + + if (TextUtils.isEmpty(nameTextView.getText())) { + nameTextView.setText(LocaleController.getString("SharedContentTitle", R.string.SharedContentTitle)); + } + + if (sharedMediaLayout.isSearchItemVisible()) { + sharedMediaLayout.getSearchItem().setVisibility(View.VISIBLE); + } + if (sharedMediaLayout.isCalendarItemVisible()) { + sharedMediaLayout.photoVideoOptionsItem.setVisibility(View.VISIBLE); + } else { + sharedMediaLayout.photoVideoOptionsItem.setVisibility(View.INVISIBLE); + } + + AndroidUtilities.updateViewVisibilityAnimated(avatarContainer, true, 1, false); + updateMediaCount(); + updateColors(); + return fragmentView; + } + + private void updateMediaCount() { + int id = sharedMediaLayout.getClosestTab(); + int[] mediaCount = sharedMediaPreloader.getLastMediaCount(); + if (id < 0 || mediaCount[id] < 0) { + return; + } + if (id == 0) { + if (sharedMediaLayout.getPhotosVideosTypeFilter() == SharedMediaLayout.FILTER_PHOTOS_ONLY) { + mediaCounterTextView.setText(LocaleController.formatPluralString("Photos", mediaCount[MediaDataController.MEDIA_PHOTOS_ONLY])); + } else if (sharedMediaLayout.getPhotosVideosTypeFilter() == SharedMediaLayout.FILTER_VIDEOS_ONLY) { + mediaCounterTextView.setText(LocaleController.formatPluralString("Videos", mediaCount[MediaDataController.MEDIA_VIDEOS_ONLY])); + } else { + mediaCounterTextView.setText(LocaleController.formatPluralString("Media", mediaCount[MediaDataController.MEDIA_PHOTOVIDEO])); + } + } else if (id == 1) { + mediaCounterTextView.setText(LocaleController.formatPluralString("Files", mediaCount[MediaDataController.MEDIA_FILE])); + } else if (id == 2) { + mediaCounterTextView.setText(LocaleController.formatPluralString("Voice", mediaCount[MediaDataController.MEDIA_AUDIO])); + } else if (id == 3) { + mediaCounterTextView.setText(LocaleController.formatPluralString("Links", mediaCount[MediaDataController.MEDIA_URL])); + } else if (id == 4) { + mediaCounterTextView.setText(LocaleController.formatPluralString("MusicFiles", mediaCount[MediaDataController.MEDIA_MUSIC])); + } else if (id == 5) { + mediaCounterTextView.setText(LocaleController.formatPluralString("GIFs", mediaCount[MediaDataController.MEDIA_GIF])); + } + } + + public void setChatInfo(TLRPC.ChatFull currentChatInfo) { + this.currentChatInfo = currentChatInfo; + } + + public long getDialogId() { + return dialogId; + } + + @Override + public void mediaCountUpdated() { + if (sharedMediaLayout != null && sharedMediaPreloader != null) { + sharedMediaLayout.setNewMediaCounts(sharedMediaPreloader.getLastMediaCount()); + } + updateMediaCount(); + } + + + private void updateColors() { + actionBar.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + actionBar.setItemsColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), false); + actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), false); + actionBar.setTitleColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + } + + @Override + public ArrayList getThemeDescriptions() { + ThemeDescription.ThemeDescriptionDelegate themeDelegate = () -> { + updateColors(); + }; + ArrayList arrayList = new ArrayList<>(); + arrayList.add(new ThemeDescription(null, 0, null, null, null, themeDelegate, Theme.key_windowBackgroundWhite)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, themeDelegate, Theme.key_actionBarActionModeDefaultSelector)); + arrayList.add(new ThemeDescription(null, 0, null, null, null, themeDelegate, Theme.key_windowBackgroundWhiteBlackText)); + arrayList.addAll(sharedMediaLayout.getThemeDescriptions()); + return arrayList; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MemberRequestsBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MemberRequestsBottomSheet.java new file mode 100644 index 00000000000..361aaf8a542 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MemberRequestsBottomSheet.java @@ -0,0 +1,157 @@ +package org.telegram.ui.Components; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; + +import android.app.Activity; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ChatActivity; +import org.telegram.ui.Delegates.MemberRequestsDelegate; +import org.telegram.ui.LaunchActivity; + +public class MemberRequestsBottomSheet extends UsersAlertBase { + + private final int touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); + private final MemberRequestsDelegate delegate; + private final FlickerLoadingView currentLoadingView; + private final StickerEmptyView membersEmptyView; + private final StickerEmptyView membersSearchEmptyView; + + private float yOffset; + private boolean enterEventSent; + + public MemberRequestsBottomSheet(BaseFragment fragment, long chatId) { + super(fragment.getParentActivity(), false, fragment.getCurrentAccount(), fragment.getResourceProvider()); + this.needSnapToTop = false; + this.isEmptyViewVisible = false; + this.delegate = new MemberRequestsDelegate(fragment, container, chatId, false) { + @Override + protected void onImportersChanged(String query, boolean fromCache, boolean fromHide) { + if (!hasAllImporters()) { + if (membersEmptyView.getVisibility() != View.INVISIBLE) { + membersEmptyView.setVisibility(View.INVISIBLE); + } + dismiss(); + } else if (fromHide) { + searchView.searchEditText.setText(""); + } else { + super.onImportersChanged(query, fromCache, fromHide); + } + } + }; + this.delegate.setShowLastItemDivider(false); + setDimBehindAlpha(75); + + searchView.searchEditText.setHint(LocaleController.getString("SearchMemberRequests", R.string.SearchMemberRequests)); + + searchListViewAdapter = listViewAdapter = delegate.getAdapter(); + listView.setAdapter(listViewAdapter); + delegate.setRecyclerView(listView); + + int position = ((ViewGroup) listView.getParent()).indexOfChild(listView); + currentLoadingView = delegate.getLoadingView(); + containerView.addView(currentLoadingView, position, LayoutHelper.createFrame(MATCH_PARENT, MATCH_PARENT)); + + membersEmptyView = delegate.getEmptyView(); + containerView.addView(membersEmptyView, position, LayoutHelper.createFrame(MATCH_PARENT, MATCH_PARENT)); + + membersSearchEmptyView = delegate.getSearchEmptyView(); + containerView.addView(membersSearchEmptyView, position, LayoutHelper.createFrame(MATCH_PARENT, MATCH_PARENT)); + + delegate.loadMembers(); + } + + @Override + public void show() { + if (delegate.isNeedRestoreList && scrollOffsetY == 0) { + scrollOffsetY = AndroidUtilities.dp(8); + } + super.show(); + delegate.isNeedRestoreList = false; + } + + @Override + public void onBackPressed() { + if (delegate.onBackPressed()) { + super.onBackPressed(); + } + } + + public boolean isNeedRestoreDialog() { + return delegate.isNeedRestoreList; + } + + @Override + protected boolean isAllowSelectChildAtPosition(float x, float y) { + return y >= scrollOffsetY + frameLayout.getMeasuredHeight(); + } + + @Override + protected void setTranslationY(int newOffset) { + super.setTranslationY(newOffset); + currentLoadingView.setTranslationY(newOffset + frameLayout.getMeasuredHeight()); + membersEmptyView.setTranslationY(newOffset); + membersSearchEmptyView.setTranslationY(newOffset); + } + + @Override + protected void updateLayout() { + if (listView.getChildCount() <= 0) { + int newOffset = listView.getVisibility() == View.VISIBLE + ? listView.getPaddingTop() - AndroidUtilities.dp(8) + : 0; + if (scrollOffsetY != newOffset) { + scrollOffsetY = newOffset; + setTranslationY(newOffset); + } + } else { + super.updateLayout(); + } + } + + @Override + protected void search(String text) { + super.search(text); + delegate.setQuery(text); + } + + @Override + protected void onSearchViewTouched(MotionEvent ev, EditTextBoldCursor searchEditText) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + yOffset = scrollOffsetY; + delegate.setAdapterItemsEnabled(false); + } else if (ev.getAction() == MotionEvent.ACTION_UP && Math.abs(scrollOffsetY - yOffset) < touchSlop) { + if (!enterEventSent) { + Activity activity = AndroidUtilities.findActivity(getContext()); + BaseFragment fragment = null; + if (activity instanceof LaunchActivity) { + fragment = ((LaunchActivity) activity).getActionBarLayout().fragmentsStack.get(((LaunchActivity) activity).getActionBarLayout().fragmentsStack.size() - 1); + } + if (fragment instanceof ChatActivity) { + boolean keyboardVisible = ((ChatActivity) fragment).needEnterText(); + enterEventSent = true; + AndroidUtilities.runOnUIThread(() -> { + setFocusable(true); + searchEditText.requestFocus(); + AndroidUtilities.runOnUIThread(() -> AndroidUtilities.showKeyboard(searchEditText)); + }, keyboardVisible ? 200 : 0); + } else { + enterEventSent = true; + setFocusable(true); + searchEditText.requestFocus(); + AndroidUtilities.runOnUIThread(() -> AndroidUtilities.showKeyboard(searchEditText)); + } + } + } + if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) { + delegate.setAdapterItemsEnabled(true); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MotionBackgroundDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MotionBackgroundDrawable.java index 56bfefc96e4..38b79abfe6c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MotionBackgroundDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MotionBackgroundDrawable.java @@ -25,6 +25,7 @@ import androidx.core.graphics.ColorUtils; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.FileLog; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.Utilities; @@ -36,6 +37,8 @@ public class MotionBackgroundDrawable extends Drawable { private static final boolean useLegacyBitmap = Build.VERSION.SDK_INT < 28; private static final boolean useSoftLight = Build.VERSION.SDK_INT >= 29; + private static boolean errorWhileGenerateLegacyBitmap = false; + private static float legacyBitmapScale = 0.7f; private int[] colors = new int[]{ 0xff426D57, @@ -95,6 +98,9 @@ public class MotionBackgroundDrawable extends Drawable { private float patternAlpha = 1f; private int alpha = 255; + private ColorFilter legacyBitmapColorFilter; + private int legacyBitmapColor; + public MotionBackgroundDrawable() { super(); init(); @@ -240,18 +246,27 @@ public void switchToNextPosition(boolean fast) { private void generateNextGradient() { if (useLegacyBitmap && intensity < 0) { - if (legacyBitmap != null) { - if (legacyBitmap2 == null || legacyBitmap2.getHeight() != legacyBitmap.getHeight() || legacyBitmap2.getWidth() != legacyBitmap.getWidth()) { - if (legacyBitmap2 != null) { - legacyBitmap2.recycle(); + try { + if (legacyBitmap != null) { + if (legacyBitmap2 == null || legacyBitmap2.getHeight() != legacyBitmap.getHeight() || legacyBitmap2.getWidth() != legacyBitmap.getWidth()) { + if (legacyBitmap2 != null) { + legacyBitmap2.recycle(); + } + legacyBitmap2 = Bitmap.createBitmap(legacyBitmap.getWidth(), legacyBitmap.getHeight(), Bitmap.Config.ARGB_8888); + legacyCanvas2 = new Canvas(legacyBitmap2); + } else { + legacyBitmap2.eraseColor(Color.TRANSPARENT); } - legacyBitmap2 = Bitmap.createBitmap(legacyBitmap.getWidth(), legacyBitmap.getHeight(), Bitmap.Config.ARGB_8888); - legacyCanvas2 = new Canvas(legacyBitmap2); - } else { - legacyBitmap2.eraseColor(Color.TRANSPARENT); + legacyCanvas2.drawBitmap(legacyBitmap, 0, 0, null); + } + } catch (Exception e) { + FileLog.e(e); + if (legacyBitmap2 != null) { + legacyBitmap2.recycle(); + legacyBitmap2 = null; } - legacyCanvas2.drawBitmap(legacyBitmap,0 ,0, null); } + Utilities.generateGradient(currentBitmap, true, phase, 1f, currentBitmap.getWidth(), currentBitmap.getHeight(), currentBitmap.getRowBytes(), colors); invalidateLegacy = true; } @@ -316,7 +331,6 @@ private void invalidateParent() { AndroidUtilities.cancelRunOnUIThread(updateAnimationRunnable); AndroidUtilities.runOnUIThread(updateAnimationRunnable, 16); } - // invalidateLegacy = true; } public boolean hasPattern() { @@ -371,7 +385,11 @@ public void setPatternBitmap(int intensity, Bitmap bitmap) { matrix = new Matrix(); } else { createLegacyBitmap(); - paint2.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); + if (!errorWhileGenerateLegacyBitmap) { + paint2.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); + } else { + paint2.setXfermode(null); + } } } else { if (!useLegacyBitmap) { @@ -400,9 +418,9 @@ public void setBounds(int left, int top, int right, int bottom) { } private void createLegacyBitmap() { - if (useLegacyBitmap && intensity < 0) { - int w = patternBounds.width(); - int h = patternBounds.height(); + if (useLegacyBitmap && intensity < 0 && !errorWhileGenerateLegacyBitmap) { + int w = (int) (patternBounds.width() * legacyBitmapScale); + int h = (int) (patternBounds.height() * legacyBitmapScale); if (w > 0 && h > 0 && (legacyBitmap == null || legacyBitmap.getWidth() != w || legacyBitmap.getHeight() != h)) { if (legacyBitmap != null) { legacyBitmap.recycle(); @@ -411,9 +429,20 @@ private void createLegacyBitmap() { legacyBitmap2.recycle(); legacyBitmap2 = null; } - legacyBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); - legacyCanvas = new Canvas(legacyBitmap); - invalidateLegacy = true; + try { + + legacyBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + legacyCanvas = new Canvas(legacyBitmap); + invalidateLegacy = true; + } catch (Exception e) { + if (legacyBitmap != null) { + legacyBitmap.recycle(); + legacyBitmap = null; + } + FileLog.e(e); + errorWhileGenerateLegacyBitmap = true; + paint2.setXfermode(null); + } } } } @@ -441,7 +470,29 @@ public void draw(Canvas canvas) { canvas.drawColor(ColorUtils.setAlphaComponent(Color.BLACK, alpha)); if (patternBitmap != null) { if (useLegacyBitmap) { - if (legacyBitmap != null) { + if (errorWhileGenerateLegacyBitmap) { + bitmapWidth = patternBitmap.getWidth(); + bitmapHeight = patternBitmap.getHeight(); + maxScale = Math.max(w / bitmapWidth, h / bitmapHeight); + width = bitmapWidth * maxScale; + height = bitmapHeight * maxScale; + x = (w - width) / 2; + y = (h - height) / 2; + rect.set(x, y, x + width, y + height); + + int averageColor = AndroidUtilities.getAverageColor(colors[2], AndroidUtilities.getAverageColor(colors[0], colors[1])); + if (colors[3] != 0) { + averageColor = AndroidUtilities.getAverageColor(colors[3], averageColor); + } + if (legacyBitmapColorFilter == null || averageColor != legacyBitmapColor) { + legacyBitmapColor = averageColor; + legacyBitmapColorFilter = new PorterDuffColorFilter(averageColor, PorterDuff.Mode.SRC_IN); + } + paint2.setColorFilter(legacyBitmapColorFilter); + paint2.setAlpha((int) ((Math.abs(intensity) / 100f) * alpha * patternAlpha)); + canvas.translate(0, tr); + canvas.drawBitmap(patternBitmap, null, rect, paint2); + } else if (legacyBitmap != null) { if (invalidateLegacy) { rect.set(0, 0, legacyBitmap.getWidth(), legacyBitmap.getHeight()); int oldAlpha = paint.getAlpha(); @@ -460,7 +511,10 @@ public void draw(Canvas canvas) { paint2.setColorFilter(null); paint2.setAlpha((int) ((Math.abs(intensity) / 100f) * 255)); + legacyCanvas.save(); + legacyCanvas.scale(legacyBitmapScale, legacyBitmapScale); legacyCanvas.drawBitmap(patternBitmap, null, rect, paint2); + legacyCanvas.restore(); invalidateLegacy = false; } @@ -477,6 +531,9 @@ public void draw(Canvas canvas) { } } } else { + if (matrix == null) { + matrix = new Matrix(); + } matrix.reset(); matrix.setTranslate(x, y + tr); float scaleW = (currentBitmap.getWidth() / (float) bounds.width()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PollVotesAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PollVotesAlert.java index 93f5cc057d6..4c092527067 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PollVotesAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PollVotesAlert.java @@ -1188,8 +1188,9 @@ public String getLetter(int position) { } @Override - public int getPositionForScrollProgress(float progress) { - return 0; + public void getPositionForScrollProgress(RecyclerListView listView, float progress, int[] position) { + position[0] = 0; + position[1] = 0; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java index 7e91a06e7a7..07e5eb483e6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java @@ -738,6 +738,7 @@ public void didReceivedNotification(int id, int account, Object... args) { if (did == dialogId && parentClassGuid == guid && adapter != null) { boolean fromCache = (Boolean) args[2]; ArrayList arrayList = (ArrayList) args[4]; + thumbsFileNames.clear(); videoFileNames.clear(); imagesLocations.clear(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java index d6b1f6eeee1..34eb7dd1d43 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java @@ -17,6 +17,8 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.graphics.drawable.TransitionDrawable; @@ -25,7 +27,6 @@ import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; -import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.util.StateSet; import android.view.GestureDetector; @@ -43,6 +44,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.FileLog; +import org.telegram.messenger.R; import org.telegram.ui.ActionBar.Theme; import java.lang.reflect.Field; @@ -50,11 +52,11 @@ import java.util.ArrayList; import java.util.HashSet; +import androidx.core.content.ContextCompat; +import androidx.core.graphics.ColorUtils; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.google.android.exoplayer2.util.Log; - public class RecyclerListView extends RecyclerView { private OnItemClickListener onItemClickListener; @@ -102,7 +104,7 @@ public class RecyclerListView extends RecyclerView { private boolean selfOnLayout; - private boolean scrollingByUser; + public boolean scrollingByUser; private GestureDetector gestureDetector; private View currentChildView; @@ -145,6 +147,10 @@ public class RecyclerListView extends RecyclerView { protected final Theme.ResourcesProvider resourcesProvider; + public FastScroll getFastScroll() { + return fastScroll; + } + public interface OnItemClickListener { void onItemClick(View view, int position); } @@ -177,7 +183,28 @@ public int getSelectionBottomPadding(View view) { public abstract static class FastScrollAdapter extends SelectionAdapter { public abstract String getLetter(int position); - public abstract int getPositionForScrollProgress(float progress); + public abstract void getPositionForScrollProgress(RecyclerListView listView, float progress, int[] position); + public void onStartFastScroll() { + + } + public void onFinishFastScroll(RecyclerListView listView) { + + } + + public int getTotalItemsCount() { + return getItemCount(); + } + + public float getScrollProgress(RecyclerListView listView) { + return listView.computeVerticalScrollOffset() / ((float) getTotalItemsCount() * listView.getChildAt(0).getMeasuredHeight() - listView.getMeasuredHeight()); + } + + public boolean fastScrollIsVisible(RecyclerListView listView) { + return true; + } + public void onFastScrollSingleTap() { + + } } public interface IntReturnCallback { @@ -323,10 +350,14 @@ public Holder(View itemView) { } } - private class FastScroll extends View { + public class FastScroll extends View { + + public static final int LETTER_TYPE = 0; + public static final int DATE_TYPE = 1; private RectF rect = new RectF(); private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private Paint paint2 = new Paint(Paint.ANTI_ALIAS_FLAG); private float progress; private float lastY; private float startDy; @@ -341,85 +372,147 @@ private class FastScroll extends View { private float textY; private float bubbleProgress; private long lastUpdateTime; - private int[] colors = new int[6]; private int scrollX; + private int type; + private int inactiveColor; + private int activeColor; + private boolean floatingDateVisible; + private float floatingDateProgress; + private int[] positionWithOffset = new int[2]; + boolean isVisible; + float touchSlop; + + Drawable fastScrollBackgroundDrawable; + + Runnable hideFloatingDateRunnable = new Runnable() { + @Override + public void run() { + if (pressed) { + AndroidUtilities.cancelRunOnUIThread(hideFloatingDateRunnable); + AndroidUtilities.runOnUIThread(hideFloatingDateRunnable, 4000); + } else { + floatingDateVisible = false; + invalidate(); + } + } + }; - public FastScroll(Context context) { + public FastScroll(Context context, int type) { super(context); - - letterPaint.setTextSize(AndroidUtilities.dp(45)); + this.type = type; + if (type == LETTER_TYPE) { + letterPaint.setTextSize(AndroidUtilities.dp(45)); + } else { + letterPaint.setTextSize(AndroidUtilities.dp(13)); + letterPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + paint2.setColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + fastScrollBackgroundDrawable = ContextCompat.getDrawable(context, R.drawable.calendar_date).mutate(); + fastScrollBackgroundDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhite), PorterDuff.Mode.MULTIPLY)); + } for (int a = 0; a < 8; a++) { radii[a] = AndroidUtilities.dp(44); } - scrollX = LocaleController.isRTL ? AndroidUtilities.dp(10) : AndroidUtilities.dp(117); + scrollX = LocaleController.isRTL ? AndroidUtilities.dp(10) : AndroidUtilities.dp((type == LETTER_TYPE ? 132 : 240) - 15); updateColors(); + setFocusableInTouchMode(true); + ViewConfiguration vc = ViewConfiguration.get(context); + touchSlop = vc.getScaledTouchSlop(); } private void updateColors() { - int inactive = Theme.getColor(Theme.key_fastScrollInactive); - int active = Theme.getColor(Theme.key_fastScrollActive); - paint.setColor(inactive); - letterPaint.setColor(Theme.getColor(Theme.key_fastScrollText)); - colors[0] = Color.red(inactive); - colors[1] = Color.red(active); - colors[2] = Color.green(inactive); - colors[3] = Color.green(active); - colors[4] = Color.blue(inactive); - colors[5] = Color.blue(active); + inactiveColor = type == LETTER_TYPE ? Theme.getColor(Theme.key_fastScrollInactive) : ColorUtils.setAlphaComponent(Color.BLACK, (int) (255 * 0.4f)); + activeColor = Theme.getColor(Theme.key_fastScrollActive); + paint.setColor(inactiveColor); + + if (type == LETTER_TYPE) { + letterPaint.setColor(Theme.getColor(Theme.key_fastScrollText)); + } else { + letterPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + } invalidate(); } + float startY; + boolean isMoving; + long startTime; + @Override public boolean onTouchEvent(MotionEvent event) { + if (!isVisible) { + pressed = false; + return false; + } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: float x = event.getX(); - lastY = event.getY(); + startY = lastY = event.getY(); float currentY = (float) Math.ceil((getMeasuredHeight() - AndroidUtilities.dp(24 + 30)) * progress) + AndroidUtilities.dp(12); if (LocaleController.isRTL && x > AndroidUtilities.dp(25) || !LocaleController.isRTL && x < AndroidUtilities.dp(107) || lastY < currentY || lastY > currentY + AndroidUtilities.dp(30)) { return false; } startDy = lastY - currentY; + startTime = System.currentTimeMillis(); pressed = true; + isMoving = false; lastUpdateTime = System.currentTimeMillis(); - getCurrentLetter(); invalidate(); + Adapter adapter = getAdapter(); + showFloatingDate(); + if (adapter instanceof FastScrollAdapter) { + ((FastScrollAdapter) adapter).onStartFastScroll(); + } return true; case MotionEvent.ACTION_MOVE: if (!pressed) { return true; } - float newY = event.getY(); - float minY = AndroidUtilities.dp(12) + startDy; - float maxY = getMeasuredHeight() - AndroidUtilities.dp(12 + 30) + startDy; - if (newY < minY) { - newY = minY; - } else if (newY > maxY) { - newY = maxY; + if (Math.abs(event.getY() - startY) > touchSlop) { + isMoving = true; } - float dy = newY - lastY; - lastY = newY; - progress += dy / (getMeasuredHeight() - AndroidUtilities.dp(24 + 30)); - if (progress < 0) { - progress = 0; - } else if (progress > 1) { - progress = 1; + if (isMoving) { + float newY = event.getY(); + float minY = AndroidUtilities.dp(12) + startDy; + float maxY = getMeasuredHeight() - AndroidUtilities.dp(12 + 30) + startDy; + if (newY < minY) { + newY = minY; + } else if (newY > maxY) { + newY = maxY; + } + float dy = newY - lastY; + lastY = newY; + progress += dy / (getMeasuredHeight() - AndroidUtilities.dp(24 + 30)); + if (progress < 0) { + progress = 0; + } else if (progress > 1) { + progress = 1; + } + getCurrentLetter(true); + invalidate(); } - getCurrentLetter(); - invalidate(); return true; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: + adapter = getAdapter(); + if (pressed && !isMoving && System.currentTimeMillis() - startTime < 150) { + if (adapter instanceof FastScrollAdapter) { + ((FastScrollAdapter)adapter).onFastScrollSingleTap(); + } + } + isMoving = false; pressed = false; lastUpdateTime = System.currentTimeMillis(); invalidate(); + if (adapter instanceof FastScrollAdapter) { + ((FastScrollAdapter) adapter).onFinishFastScroll(RecyclerListView.this); + } + showFloatingDate(); return true; } - return super.onTouchEvent(event); + return pressed; } - private void getCurrentLetter() { + private void getCurrentLetter(boolean updatePosition) { LayoutManager layoutManager = getLayoutManager(); if (layoutManager instanceof LinearLayoutManager) { LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager; @@ -427,16 +520,24 @@ private void getCurrentLetter() { Adapter adapter = getAdapter(); if (adapter instanceof FastScrollAdapter) { FastScrollAdapter fastScrollAdapter = (FastScrollAdapter) adapter; - int position = fastScrollAdapter.getPositionForScrollProgress(progress); - linearLayoutManager.scrollToPositionWithOffset(position, sectionOffset); - String newLetter = fastScrollAdapter.getLetter(position); + fastScrollAdapter.getPositionForScrollProgress(RecyclerListView.this, progress, positionWithOffset); + if (updatePosition) { + linearLayoutManager.scrollToPositionWithOffset(positionWithOffset[0], -positionWithOffset[1] + sectionOffset); + } + + String newLetter = fastScrollAdapter.getLetter(positionWithOffset[0]); if (newLetter == null) { if (letterLayout != null) { oldLetterLayout = letterLayout; } letterLayout = null; } else if (!newLetter.equals(currentLetter)) { - letterLayout = new StaticLayout(newLetter, letterPaint, 1000, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + if (type == LETTER_TYPE) { + letterLayout = new StaticLayout(newLetter, letterPaint, 1000, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + } else { + int w = ((int) letterPaint.measureText(newLetter)) + 1; + letterLayout = new StaticLayout(newLetter, letterPaint, w, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + } oldLetterLayout = null; if (letterLayout.getLineCount() > 0) { float lWidth = letterLayout.getLineWidth(0); @@ -456,67 +557,96 @@ private void getCurrentLetter() { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(AndroidUtilities.dp(132), MeasureSpec.getSize(heightMeasureSpec)); + setMeasuredDimension(AndroidUtilities.dp(type == LETTER_TYPE ? 132 : 240), MeasureSpec.getSize(heightMeasureSpec)); } @Override protected void onDraw(Canvas canvas) { - paint.setColor(Color.argb(255, colors[0] + (int) ((colors[1] - colors[0]) * bubbleProgress), colors[2] + (int) ((colors[3] - colors[2]) * bubbleProgress), colors[4] + (int) ((colors[5] - colors[4]) * bubbleProgress))); + paint.setColor(ColorUtils.blendARGB(inactiveColor, activeColor, bubbleProgress)); int y = (int) Math.ceil((getMeasuredHeight() - AndroidUtilities.dp(24 + 30)) * progress); rect.set(scrollX, AndroidUtilities.dp(12) + y, scrollX + AndroidUtilities.dp(5), AndroidUtilities.dp(12 + 30) + y); canvas.drawRoundRect(rect, AndroidUtilities.dp(2), AndroidUtilities.dp(2), paint); - if ((pressed || bubbleProgress != 0)) { - paint.setAlpha((int) (255 * bubbleProgress)); - int progressY = y + AndroidUtilities.dp(30); - y -= AndroidUtilities.dp(46); - float diff = 0; - if (y <= AndroidUtilities.dp(12)) { - diff = AndroidUtilities.dp(12) - y; - y = AndroidUtilities.dp(12); - } - float raduisTop; - float raduisBottom; - canvas.translate(AndroidUtilities.dp(10), y); - if (diff <= AndroidUtilities.dp(29)) { - raduisTop = AndroidUtilities.dp(44); - raduisBottom = AndroidUtilities.dp(4) + (diff / AndroidUtilities.dp(29)) * AndroidUtilities.dp(40); - } else { - diff -= AndroidUtilities.dp(29); - raduisBottom = AndroidUtilities.dp(44); - raduisTop = AndroidUtilities.dp(4) + (1.0f - diff / AndroidUtilities.dp(29)) * AndroidUtilities.dp(40); - } - if (LocaleController.isRTL && (radii[0] != raduisTop || radii[6] != raduisBottom) || !LocaleController.isRTL && (radii[2] != raduisTop || radii[4] != raduisBottom)) { - if (LocaleController.isRTL) { - radii[0] = radii[1] = raduisTop; - radii[6] = radii[7] = raduisBottom; + if (type == LETTER_TYPE) { + if ((isMoving || bubbleProgress != 0)) { + paint.setAlpha((int) (255 * bubbleProgress)); + int progressY = y + AndroidUtilities.dp(30); + y -= AndroidUtilities.dp(46); + float diff = 0; + if (y <= AndroidUtilities.dp(12)) { + diff = AndroidUtilities.dp(12) - y; + y = AndroidUtilities.dp(12); + } + float raduisTop; + float raduisBottom; + canvas.translate(AndroidUtilities.dp(10), y); + if (diff <= AndroidUtilities.dp(29)) { + raduisTop = AndroidUtilities.dp(44); + raduisBottom = AndroidUtilities.dp(4) + (diff / AndroidUtilities.dp(29)) * AndroidUtilities.dp(40); } else { - radii[2] = radii[3] = raduisTop; - radii[4] = radii[5] = raduisBottom; + diff -= AndroidUtilities.dp(29); + raduisBottom = AndroidUtilities.dp(44); + raduisTop = AndroidUtilities.dp(4) + (1.0f - diff / AndroidUtilities.dp(29)) * AndroidUtilities.dp(40); + } + if (LocaleController.isRTL && (radii[0] != raduisTop || radii[6] != raduisBottom) || !LocaleController.isRTL && (radii[2] != raduisTop || radii[4] != raduisBottom)) { + if (LocaleController.isRTL) { + radii[0] = radii[1] = raduisTop; + radii[6] = radii[7] = raduisBottom; + } else { + radii[2] = radii[3] = raduisTop; + radii[4] = radii[5] = raduisBottom; + } + path.reset(); + rect.set(LocaleController.isRTL ? AndroidUtilities.dp(10) : 0, 0, AndroidUtilities.dp(LocaleController.isRTL ? 98 : 88), AndroidUtilities.dp(88)); + path.addRoundRect(rect, radii, Path.Direction.CW); + path.close(); + } + StaticLayout layoutToDraw = letterLayout != null ? letterLayout : oldLetterLayout; + if (layoutToDraw != null) { + canvas.save(); + canvas.scale(bubbleProgress, bubbleProgress, scrollX, progressY - y); + canvas.drawPath(path, paint); + canvas.translate(textX, textY); + layoutToDraw.draw(canvas); + canvas.restore(); } - path.reset(); - rect.set(LocaleController.isRTL ? AndroidUtilities.dp(10) : 0, 0, AndroidUtilities.dp(LocaleController.isRTL ? 98 : 88), AndroidUtilities.dp(88)); - path.addRoundRect(rect, radii, Path.Direction.CW); - path.close(); } - StaticLayout layoutToDraw = letterLayout != null ? letterLayout : oldLetterLayout; - if (layoutToDraw != null) { + } else if (type == DATE_TYPE) { + if (letterLayout != null && floatingDateProgress != 0) { canvas.save(); - canvas.scale(bubbleProgress, bubbleProgress, scrollX, progressY - y); - canvas.drawPath(path, paint); - canvas.translate(textX, textY); - layoutToDraw.draw(canvas); + float s = 0.7f + 0.3f * floatingDateProgress; + canvas.scale(s, s, rect.right - AndroidUtilities.dp(12), rect.centerY()); + + float cy = rect.centerY(); + float x = rect.left - AndroidUtilities.dp(30) * bubbleProgress; + float r = letterLayout.getHeight() / 2f + AndroidUtilities.dp(6); + rect.set(x - letterLayout.getWidth() - AndroidUtilities.dp(36), cy - letterLayout.getHeight() / 2f - AndroidUtilities.dp(8), x - AndroidUtilities.dp(12), cy + letterLayout.getHeight() / 2f + AndroidUtilities.dp(8)); + + int oldAlpha1 = paint2.getAlpha(); + int oldAlpha2 = letterPaint.getAlpha(); + paint2.setAlpha((int) (oldAlpha1 * floatingDateProgress)); + letterPaint.setAlpha((int) (oldAlpha2 * floatingDateProgress)); + fastScrollBackgroundDrawable.setBounds((int) rect.left, (int) rect.top, (int) rect.right, (int) rect.bottom); + fastScrollBackgroundDrawable.draw(canvas); + canvas.save(); + canvas.translate(x - letterLayout.getWidth() - AndroidUtilities.dp(24), cy - letterLayout.getHeight() / 2f); + letterLayout.draw(canvas); + canvas.restore(); + + paint2.setAlpha(oldAlpha1); + letterPaint.setAlpha(oldAlpha2); + canvas.restore(); } } - if ((pressed && letterLayout != null && bubbleProgress < 1.0f) || (!pressed || letterLayout == null) && bubbleProgress > 0.0f) { - long newTime = System.currentTimeMillis(); - long dt = (newTime - lastUpdateTime); - if (dt < 0 || dt > 17) { - dt = 17; - } + long newTime = System.currentTimeMillis(); + long dt = (newTime - lastUpdateTime); + if (dt < 0 || dt > 17) { + dt = 17; + } + if ((isMoving && letterLayout != null && bubbleProgress < 1.0f) || (!isMoving || letterLayout == null) && bubbleProgress > 0.0f) { lastUpdateTime = newTime; invalidate(); - if (pressed && letterLayout != null) { + if (isMoving && letterLayout != null) { bubbleProgress += dt / 120.0f; if (bubbleProgress > 1.0f) { bubbleProgress = 1.0f; @@ -528,6 +658,21 @@ protected void onDraw(Canvas canvas) { } } } + + + if (floatingDateVisible && floatingDateProgress != 1f) { + floatingDateProgress += dt / 120.0f; + if (floatingDateProgress > 1.0f) { + floatingDateProgress = 1.0f; + } + invalidate(); + } else if (!floatingDateVisible && floatingDateProgress != 0) { + floatingDateProgress -= dt / 120.0f; + if (floatingDateProgress < 0.0f) { + floatingDateProgress = 0.0f; + } + invalidate(); + } } @Override @@ -538,10 +683,40 @@ public void layout(int l, int t, int r, int b) { super.layout(l, t, r, b); } - private void setProgress(float value) { + public void setProgress(float value) { progress = value; invalidate(); } + + @Override + public boolean isPressed() { + return pressed; + } + + public void showFloatingDate() { + if (type != DATE_TYPE) { + return; + } + if (!floatingDateVisible) { + floatingDateVisible = true; + invalidate(); + } + AndroidUtilities.cancelRunOnUIThread(hideFloatingDateRunnable); + AndroidUtilities.runOnUIThread(hideFloatingDateRunnable, 4000); + } + + public void setIsVisible(boolean visible) { + this.isVisible = visible; + setAlpha(visible ? 1f : 0f); + } + + public int getScrollBarY() { + return (int) Math.ceil((getMeasuredHeight() - AndroidUtilities.dp(24 + 30)) * progress) + AndroidUtilities.dp(17); + } + + public float getProgress() { + return progress; + } } private class RecyclerListViewItemClickListener implements OnItemTouchListener { @@ -900,6 +1075,9 @@ public RecyclerListView(Context context, Theme.ResourcesProvider resourcesProvid try { if (!gotAttributes) { attributes = getResourceDeclareStyleableIntArray("com.android.internal", "View"); + if (attributes == null) { + attributes = new int[0]; + } gotAttributes = true; } TypedArray a = context.getTheme().obtainStyledAttributes(attributes); @@ -951,7 +1129,10 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { } else { selectorRect.setEmpty(); } - checkSection(); + checkSection(false); + if (dy != 0 && fastScroll != null) { + fastScroll.showFloatingDate(); + } } }); addOnItemTouchListener(new RecyclerListViewItemClickListener(context)); @@ -989,7 +1170,7 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { } selfOnLayout = false; } - checkSection(); + checkSection(false); if (pendingHighlightPosition != null) { highlightRowInternal(pendingHighlightPosition, false); } @@ -1027,8 +1208,8 @@ public void setSelectorDrawableColor(int color) { selectorDrawable.setCallback(this); } - public void checkSection() { - if (scrollingByUser && fastScroll != null || sectionsType != 0 && sectionsAdapter != null) { + public void checkSection(boolean force) { + if ((scrollingByUser || force) && fastScroll != null || sectionsType != 0 && sectionsAdapter != null) { LayoutManager layoutManager = getLayoutManager(); if (layoutManager instanceof LinearLayoutManager) { LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager; @@ -1072,10 +1253,10 @@ public void checkSection() { int lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition(); int visibleItemCount = Math.abs(lastVisibleItem - firstVisibleItem) + 1; - if (scrollingByUser && fastScroll != null) { + if ((scrollingByUser || force) && fastScroll != null && !fastScroll.isPressed()) { Adapter adapter = getAdapter(); if (adapter instanceof FastScrollAdapter) { - fastScroll.setProgress(Math.min(1.0f, firstVisibleItem / (float) (adapter.getItemCount() - visibleItemCount + 1))); + fastScroll.setProgress(Math.min(1.0f, firstVisibleItem / (float) (sectionsAdapter.getTotalItemsCount() - visibleItemCount + 1))); } } @@ -1217,13 +1398,20 @@ public void checkSection() { int firstVisibleItem = linearLayoutManager.findFirstVisibleItemPosition(); int lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition(); int visibleItemCount = Math.abs(lastVisibleItem - firstVisibleItem) + 1; + + if (firstVisibleItem == NO_POSITION) { return; } - if (scrollingByUser && fastScroll != null) { + if ((scrollingByUser || force) && fastScroll != null && !fastScroll.isPressed()) { Adapter adapter = getAdapter(); + if (adapter instanceof FastScrollAdapter) { - fastScroll.setProgress(Math.min(1.0f, firstVisibleItem / (float) (adapter.getItemCount() - visibleItemCount + 1))); + float p = ((FastScrollAdapter) adapter).getScrollProgress(RecyclerListView.this); + boolean visible = ((FastScrollAdapter) adapter).fastScrollIsVisible(RecyclerListView.this); + fastScroll.setIsVisible(visible); + fastScroll.setProgress(Math.min(1.0f, p)); + fastScroll.getCurrentLetter(false); } } } @@ -1505,8 +1693,8 @@ public void setDisallowInterceptTouchEvents(boolean value) { disallowInterceptTouchEvents = value; } - public void setFastScrollEnabled() { - fastScroll = new FastScroll(getContext()); + public void setFastScrollEnabled(int type) { + fastScroll = new FastScroll(getContext(), type); if (getParent() != null) { ((ViewGroup) getParent()).addView(fastScroll); } @@ -1951,6 +2139,9 @@ public void startMultiselect(int positionFrom, boolean useRelativePositions, onM @Override public boolean onTouchEvent(MotionEvent e) { + if (fastScroll != null && fastScroll.pressed) { + return false; + } if (multiSelectionGesture && e.getAction() != MotionEvent.ACTION_DOWN &&e.getAction() != MotionEvent.ACTION_UP && e.getAction() != MotionEvent.ACTION_CANCEL) { if (lastX == Float.MAX_VALUE && lastY == Float.MAX_VALUE) { lastX = e.getX(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchField.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchField.java index ad33e4a8a79..31ab8b64177 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchField.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchField.java @@ -29,7 +29,6 @@ public class SearchField extends FrameLayout { private ImageView clearSearchImageView; private CloseProgressDrawable2 progressDrawable; private EditTextBoldCursor searchEditText; - private View backgroundView; private final Theme.ResourcesProvider resourcesProvider; public SearchField(Context context, boolean supportRtl, Theme.ResourcesProvider resourcesProvider) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaFastScrollTooltip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaFastScrollTooltip.java new file mode 100644 index 00000000000..304c2668fa7 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaFastScrollTooltip.java @@ -0,0 +1,126 @@ +package org.telegram.ui.Components; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Shader; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.TextView; + +import androidx.core.graphics.ColorUtils; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.SimpleTextView; +import org.telegram.ui.ActionBar.Theme; + +import java.util.Random; + +public class SharedMediaFastScrollTooltip extends FrameLayout { + + public SharedMediaFastScrollTooltip(Context context) { + super(context); + TextView textView = new TextView(context); + textView.setText(LocaleController.getString("SharedMediaFastScrollHint", R.string.SharedMediaFastScrollHint)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setMaxLines(3); + textView.setTextColor(Theme.getColor(Theme.key_chat_gifSaveHintText)); + + setBackground(Theme.createRoundRectDrawable(AndroidUtilities.dp(6), Theme.getColor(Theme.key_chat_gifSaveHintBackground))); + addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 46, 8, 8, 8)); + + TooltipDrawableView hintView = new TooltipDrawableView(context); + addView(hintView, LayoutHelper.createFrame(29, 32, 0, 8, 8, 8, 8)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(MeasureSpec.makeMeasureSpec(Math.min(AndroidUtilities.dp(300), MeasureSpec.getSize(widthMeasureSpec) - AndroidUtilities.dp(32)), MeasureSpec.AT_MOST), heightMeasureSpec); + } + + private class TooltipDrawableView extends View { + + Random random = new Random(); + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + Paint paint2 = new Paint(Paint.ANTI_ALIAS_FLAG); + Paint fadePaint; + Paint fadePaintBack; + + public TooltipDrawableView(Context context) { + super(context); + paint.setColor(ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_chat_gifSaveHintText), (int) (255 * 0.3f))); + paint2.setColor(Theme.getColor(Theme.key_chat_gifSaveHintText)); + + fadePaint = new Paint(); + LinearGradient gradient = new LinearGradient(0, AndroidUtilities.dp(4), 0, 0, new int[]{0, 0xffffffff}, new float[]{0f, 1f}, Shader.TileMode.CLAMP); + fadePaint.setShader(gradient); + fadePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + + fadePaintBack = new Paint(); + gradient = new LinearGradient(0, 0, 0, AndroidUtilities.dp(4), new int[]{0, 0xffffffff}, new float[]{0f, 1f}, Shader.TileMode.CLAMP); + fadePaintBack.setShader(gradient); + fadePaintBack.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + } + + float progress = 1f; + float fromProgress = 0; + float toProgress; + + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.saveLayerAlpha(0, 0, getMeasuredWidth(), getMeasuredHeight(), 255, Canvas.ALL_SAVE_FLAG); + int rectSize = getMeasuredWidth() / 2 - AndroidUtilities.dp(3); + int totalHeight = (rectSize + AndroidUtilities.dp(1)) * 7 + AndroidUtilities.dp(1); + float progress = CubicBezierInterpolator.EASE_OUT.getInterpolation(this.progress > 0.4f ? (this.progress - 0.4f) / 0.6f : 0); + float p = fromProgress * (1f - progress) + toProgress * progress; + canvas.save(); + canvas.translate(0, -(totalHeight - (getMeasuredHeight() - AndroidUtilities.dp(4))) * p); + for (int i = 0; i < 7; i++) { + int y = AndroidUtilities.dp(3) + i * (rectSize + AndroidUtilities.dp(1)); + AndroidUtilities.rectTmp.set(0, y, rectSize, y + rectSize); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(2), AndroidUtilities.dp(2), paint); + AndroidUtilities.rectTmp.set(rectSize + AndroidUtilities.dp(1), y, rectSize + AndroidUtilities.dp(1) + rectSize, y + rectSize); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(2), AndroidUtilities.dp(2), paint); + } + canvas.restore(); + + canvas.drawRect(0, 0, getMeasuredWidth(), AndroidUtilities.dp(4), fadePaint); + canvas.translate(0, getMeasuredHeight() - AndroidUtilities.dp(4)); + canvas.drawRect(0, 0, getMeasuredWidth(), AndroidUtilities.dp(4), fadePaintBack); + + canvas.restore(); + + float y = AndroidUtilities.dp(3) + (getMeasuredHeight() - AndroidUtilities.dp(15 + 6)) * p; + AndroidUtilities.rectTmp.set(getMeasuredWidth() - AndroidUtilities.dp(3), y, getMeasuredWidth(), y + AndroidUtilities.dp(15)); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(1.5f), AndroidUtilities.dp(1.5f), paint2); + float cy = AndroidUtilities.rectTmp.centerY(); + float cx = rectSize + AndroidUtilities.dp(0.5f); + AndroidUtilities.rectTmp.set(cx - AndroidUtilities.dp(8), cy - AndroidUtilities.dp(3), cx + AndroidUtilities.dp(8), cy + AndroidUtilities.dp(3)); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(3), AndroidUtilities.dp(3), paint2); + + this.progress += 16 / 1000f; + if (this.progress > 1f) { + fromProgress = toProgress; + toProgress = Math.abs(random.nextInt() % 1001) / 1000f; + if (toProgress > fromProgress) { + toProgress += 0.3f; + } else { + toProgress -= 0.3f; + } + toProgress = Math.max(0, Math.min(1 ,toProgress)); + this.progress = 0; + } + invalidate(); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java index 818e4435b91..24c97940ec3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java @@ -1,16 +1,23 @@ package org.telegram.ui.Components; +import static org.telegram.messenger.MediaDataController.MEDIA_PHOTOVIDEO; +import static org.telegram.messenger.MediaDataController.getMediaType; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; import android.app.Activity; import android.content.Context; import android.content.res.Configuration; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; @@ -24,6 +31,7 @@ import android.transition.TransitionValues; import android.transition.Visibility; import android.util.SparseArray; +import android.util.SparseBooleanArray; import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; @@ -41,11 +49,15 @@ import android.widget.LinearLayout; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import com.google.android.exoplayer2.util.Log; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ChatObject; @@ -57,8 +69,10 @@ import org.telegram.messenger.MediaController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.messenger.browser.Browser; @@ -68,6 +82,8 @@ import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; +import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; @@ -77,6 +93,7 @@ import org.telegram.ui.ArticleViewer; import org.telegram.ui.Cells.ChatActionCell; import org.telegram.ui.Cells.ContextLinkCell; +import org.telegram.ui.Cells.DividerCell; import org.telegram.ui.Cells.GraySectionCell; import org.telegram.ui.Cells.LoadingCell; import org.telegram.ui.Cells.ManageChatUserCell; @@ -86,21 +103,218 @@ import org.telegram.ui.Cells.SharedLinkCell; import org.telegram.ui.Cells.SharedMediaSectionCell; import org.telegram.ui.Cells.SharedPhotoVideoCell; +import org.telegram.ui.Cells.SharedPhotoVideoCell2; import org.telegram.ui.Cells.UserCell; import org.telegram.ui.ChatActivity; import org.telegram.ui.DialogsActivity; +import org.telegram.ui.MediaCalendarActivity; import org.telegram.ui.PhotoViewer; import org.telegram.ui.ProfileActivity; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; @SuppressWarnings("unchecked") public class SharedMediaLayout extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { + public static final int FILTER_PHOTOS_AND_VIDEOS = 0; + public static final int FILTER_PHOTOS_ONLY = 1; + public static final int FILTER_VIDEOS_ONLY = 2; + + public static final int VIEW_TYPE_MEDIA_ACTIVITY = 0; + public static final int VIEW_TYPE_PROFILE_ACTIVITY = 1; + + private static final int[] supportedFastScrollTypes = new int[] { + MediaDataController.MEDIA_PHOTOVIDEO, + MediaDataController.MEDIA_FILE, + MediaDataController.MEDIA_AUDIO, + MediaDataController.MEDIA_MUSIC + }; + + public boolean isInFastScroll() { + return mediaPages[0] != null && mediaPages[0].listView.getFastScroll() != null && mediaPages[0].listView.getFastScroll().isPressed(); + } + + public boolean dispatchFastScrollEvent(MotionEvent ev) { + View view = (View) getParent(); + ev.offsetLocation(-view.getX() - getX() - mediaPages[0].listView.getFastScroll().getX(), -view.getY() - getY() - mediaPages[0].getY() - mediaPages[0].listView.getFastScroll().getY()); + return mediaPages[0].listView.getFastScroll().dispatchTouchEvent(ev); + } + + boolean isInPinchToZoomTouchMode; + boolean maybePinchToZoomTouchMode; + boolean maybePinchToZoomTouchMode2; + + private int pointerId1, pointerId2; + + float pinchStartDistance; + float pinchScale; + boolean pinchScaleUp; + int pinchCenterPosition; + int pinchCenterOffset; + int pinchCenterX; + int pinchCenterY; + Rect rect = new Rect(); + ActionBarPopupWindow optionsWindow; + FlickerLoadingView globalGradientView; + private final int viewType; + + public boolean checkPinchToZoom(MotionEvent ev) { + if (mediaPages[0].selectedType != 0 || getParent() == null) { + return false; + } + if (photoVideoChangeColumnsAnimation && !isInPinchToZoomTouchMode) { + return true; + } + + if (ev.getActionMasked() == MotionEvent.ACTION_DOWN || ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) { + if (maybePinchToZoomTouchMode && !isInPinchToZoomTouchMode && ev.getPointerCount() == 2 /*&& finishZoomTransition == null*/) { + pinchStartDistance = (float) Math.hypot(ev.getX(1) - ev.getX(0), ev.getY(1) - ev.getY(0)); + + pinchScale = 1f; + + pointerId1 = ev.getPointerId(0); + pointerId2 = ev.getPointerId(1); + + mediaPages[0].listView.cancelClickRunnables(false); + mediaPages[0].listView.cancelLongPress(); + mediaPages[0].listView.dispatchTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0)); + + View view = (View) getParent(); + pinchCenterX = (int) ((int) ((ev.getX(0) + ev.getX(1)) / 2.0f) - view.getX() - getX() - mediaPages[0].getX()); + pinchCenterY = (int) ((int) ((ev.getY(0) + ev.getY(1)) / 2.0f) - view.getY() - getY() - mediaPages[0].getY()); + + selectPinchPosition(pinchCenterX, pinchCenterY); + maybePinchToZoomTouchMode2 = true; + } + if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) { + View view = (View) getParent(); + // float x = ev.getX() - view.getX() - getX() - mediaPages[0].getX(); + float y = ev.getY() - view.getY() - getY() - mediaPages[0].getY(); + if (y > 0) { + maybePinchToZoomTouchMode = true; + } + } + + } else if (ev.getActionMasked() == MotionEvent.ACTION_MOVE && (isInPinchToZoomTouchMode || maybePinchToZoomTouchMode2)) { + int index1 = -1; + int index2 = -1; + for (int i = 0; i < ev.getPointerCount(); i++) { + if (pointerId1 == ev.getPointerId(i)) { + index1 = i; + } + if (pointerId2 == ev.getPointerId(i)) { + index2 = i; + } + } + if (index1 == -1 || index2 == -1) { + maybePinchToZoomTouchMode = false; + maybePinchToZoomTouchMode2 = false; + isInPinchToZoomTouchMode = false; + finishPinchToMediaColumnsCount(); + return false; + } + pinchScale = (float) Math.hypot(ev.getX(index2) - ev.getX(index1), ev.getY(index2) - ev.getY(index1)) / pinchStartDistance; + if (!isInPinchToZoomTouchMode && (pinchScale > 1.01f || pinchScale < 0.99f)) { + isInPinchToZoomTouchMode = true; + pinchScaleUp = pinchScale > 1f; + + startPinchToMediaColumnsCount(pinchScaleUp); + } + if (isInPinchToZoomTouchMode) { + if ((pinchScaleUp && pinchScale < 1f) || (!pinchScaleUp && pinchScale > 1f)) { + photoVideoChangeColumnsProgress = 0; + } else { + photoVideoChangeColumnsProgress = Math.max(0, Math.min(1, pinchScaleUp ? (1f - (2f - pinchScale) / 1f) : ((1f - pinchScale) / 0.5f))); + } + if (photoVideoChangeColumnsProgress == 1f || photoVideoChangeColumnsProgress == 0f) { + + if (photoVideoChangeColumnsProgress == 1f) { + int newRow = (int) Math.ceil(pinchCenterPosition / (float) animateToColumnsCount); + int columnWidth = (int) (mediaPages[0].listView.getMeasuredWidth() / (float) animateToColumnsCount); + int newColumn = (int) ((startedTrackingX / (float) (mediaPages[0].listView.getMeasuredWidth() - columnWidth)) * (animateToColumnsCount - 1)); + int newPosition = newRow * animateToColumnsCount + newColumn; + if (newPosition >= photoVideoAdapter.getItemCount()) { + newPosition = photoVideoAdapter.getItemCount() - 1; + } + pinchCenterPosition = newPosition; + } + + finishPinchToMediaColumnsCount(); + if (photoVideoChangeColumnsProgress == 0) { + pinchScaleUp = !pinchScaleUp; + } + + startPinchToMediaColumnsCount(pinchScaleUp); + pinchStartDistance = (float) Math.hypot(ev.getX(1) - ev.getX(0), ev.getY(1) - ev.getY(0)); + } + + mediaPages[0].listView.invalidate(); + if (mediaPages[0].fastScrollHintView != null) { + mediaPages[0].invalidate(); + } + } + } else if ((ev.getActionMasked() == MotionEvent.ACTION_UP || (ev.getActionMasked() == MotionEvent.ACTION_POINTER_UP && checkPointerIds(ev)) || ev.getActionMasked() == MotionEvent.ACTION_CANCEL) && isInPinchToZoomTouchMode) { + maybePinchToZoomTouchMode2 = false; + maybePinchToZoomTouchMode = false; + isInPinchToZoomTouchMode = false; + finishPinchToMediaColumnsCount(); + } + + return isInPinchToZoomTouchMode; + } + + private void selectPinchPosition(int pinchCenterX, int pinchCenterY) { + pinchCenterPosition = -1; + int y = pinchCenterY; + if (getY() != 0 && viewType == VIEW_TYPE_PROFILE_ACTIVITY) { + y = 0; + } + for (int i = 0; i < mediaPages[0].listView.getChildCount(); i++) { + View child = mediaPages[0].listView.getChildAt(i); + child.getHitRect(rect); + if (rect.contains(pinchCenterX, y)) { + pinchCenterPosition = mediaPages[0].listView.getChildLayoutPosition(child); + pinchCenterOffset = child.getTop(); + } + } + if (delegate.canSearchMembers()) { + if (pinchCenterPosition == -1) { + float x = Math.min(1, Math.max(pinchCenterX / (float) mediaPages[0].listView.getMeasuredWidth(), 0)); + pinchCenterPosition = (int) (mediaPages[0].layoutManager.findFirstVisibleItemPosition() + (mediaColumnsCount - 1) * x); + pinchCenterOffset = 0; + } + } + } + + private boolean checkPointerIds(MotionEvent ev) { + if (ev.getPointerCount() < 2) { + return false; + } + if (pointerId1 == ev.getPointerId(0) && pointerId2 == ev.getPointerId(1)) { + return true; + } + if (pointerId1 == ev.getPointerId(1) && pointerId2 == ev.getPointerId(0)) { + return true; + } + return false; + } + + public boolean isSwipeBackEnabled() { + return !photoVideoChangeColumnsAnimation && !tabsAnimationInProgress; + } + + public int getPhotosVideosTypeFilter() { + return sharedMediaData[0].filterType; + } + private static class MediaPage extends FrameLayout { + public long lastCheckScrollTime; private RecyclerListView listView; + private RecyclerListView animationSupportingListView; + private GridLayoutManager animationSupportingLayoutManager; private FlickerLoadingView progressView; private StickerEmptyView emptyView; private ExtendedGridLayoutManager layoutManager; @@ -108,14 +322,53 @@ private static class MediaPage extends FrameLayout { private RecyclerAnimationScrollHelper scrollHelper; private int selectedType; + public SharedMediaFastScrollTooltip fastScrollHintView; + public Runnable fastScrollHideHintRunnable; + public boolean fastScrollHinWasShown; + + public int highlightMessageId; + public boolean highlightAnimation; + public float highlightProgress; + + public MediaPage(Context context) { super(context); } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child == animationSupportingListView) { + return true; + } + return super.drawChild(canvas, child, drawingTime); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (fastScrollHintView != null && fastScrollHintView.getVisibility() == View.VISIBLE) { + boolean isVisible = false; + RecyclerListView.FastScroll fastScroll = listView.getFastScroll(); + if (fastScroll != null) { + float y = fastScroll.getScrollBarY() + AndroidUtilities.dp(36); + float x = (getMeasuredWidth() - fastScrollHintView.getMeasuredWidth() - AndroidUtilities.dp(16)); + fastScrollHintView.setPivotX(fastScrollHintView.getMeasuredWidth()); + fastScrollHintView.setPivotY(0); + fastScrollHintView.setTranslationX(x); + fastScrollHintView.setTranslationY(y); + } + + if (fastScroll.getProgress() > 0.85f) { + showFastScrollHint(this, null, false); + } + } + } } private ActionBar actionBar; private SharedPhotoVideoAdapter photoVideoAdapter; + private SharedPhotoVideoAdapter animationSupportingPhotoVideoAdapter; private SharedLinksAdapter linksAdapter; private SharedDocumentsAdapter documentsAdapter; private SharedDocumentsAdapter voiceAdapter; @@ -130,6 +383,7 @@ public MediaPage(Context context) { private MediaPage[] mediaPages = new MediaPage[2]; private ActionBarMenuItem deleteItem; private ActionBarMenuItem searchItem; + public ImageView photoVideoOptionsItem; private ActionBarMenuItem forwardItem; private ActionBarMenuItem gotoItem; private int searchItemState; @@ -176,7 +430,12 @@ public MediaPage(Context context) { private boolean backAnimation; private long dialog_id; - private int columnsCount = 3; + public boolean scrollingByUser; + private int mediaColumnsCount = 3; + private float photoVideoChangeColumnsProgress; + private boolean photoVideoChangeColumnsAnimation; + private ArrayList animationSupportingSortedCells = new ArrayList<>(); + private int animateToColumnsCount; private static final Interpolator interpolator = t -> { --t; @@ -189,10 +448,10 @@ public interface SharedMediaPreloaderDelegate { public static class SharedMediaPreloader implements NotificationCenter.NotificationCenterDelegate { - private int[] mediaCount = new int[]{-1, -1, -1, -1, -1, -1}; - private int[] mediaMergeCount = new int[]{-1, -1, -1, -1, -1, -1}; - private int[] lastMediaCount = new int[]{-1, -1, -1, -1, -1, -1}; - private int[] lastLoadMediaCount = new int[]{-1, -1, -1, -1, -1, -1}; + private int[] mediaCount = new int[]{-1, -1, -1, -1, -1, -1, -1, -1}; + private int[] mediaMergeCount = new int[]{-1, -1, -1, -1, -1, -1, -1, -1}; + private int[] lastMediaCount = new int[]{-1, -1, -1, -1, -1, -1, -1, -1}; + private int[] lastLoadMediaCount = new int[]{-1, -1, -1, -1, -1, -1, -1, -1}; private SharedMediaData[] sharedMediaData; private long dialogId; private long mergeDialogId; @@ -209,6 +468,9 @@ public SharedMediaPreloader(BaseFragment fragment) { } else if (fragment instanceof ProfileActivity) { ProfileActivity profileActivity = (ProfileActivity) fragment; dialogId = profileActivity.getDialogId(); + } else if (fragment instanceof MediaActivity) { + MediaActivity mediaActivity = (MediaActivity) fragment; + dialogId = mediaActivity.getDialogId(); } sharedMediaData = new SharedMediaData[6]; @@ -281,7 +543,15 @@ public void didReceivedNotification(int id, int account, Object... args) { lastMediaCount[a] = Math.max(mediaMergeCount[a], 0); } if (did == dialogId && lastMediaCount[a] != 0 && lastLoadMediaCount[a] != mediaCount[a]) { - parentFragment.getMediaDataController().loadMedia(did, lastLoadMediaCount[a] == -1 ? 30 : 20, 0, a, 2, parentFragment.getClassGuid()); + int type = a; + if (type == 0) { + if (sharedMediaData[0].filterType == FILTER_PHOTOS_ONLY) { + type = MediaDataController.MEDIA_PHOTOS_ONLY; + } else if (sharedMediaData[0].filterType == FILTER_VIDEOS_ONLY) { + type = MediaDataController.MEDIA_VIDEOS_ONLY; + } + } + parentFragment.getMediaDataController().loadMedia(did, lastLoadMediaCount[a] == -1 ? 30 : 20, 0, 0, type, 2, parentFragment.getClassGuid(), 0); lastLoadMediaCount[a] = mediaCount[a]; } } @@ -328,7 +598,19 @@ public void didReceivedNotification(int id, int account, Object... args) { if (type == -1) { continue; } - sharedMediaData[type].addMessage(obj, 0, true, enc); + if (type == 0 && sharedMediaData[0].filterType == FILTER_VIDEOS_ONLY && !obj.isVideo()) { + continue; + } + if (type == 0 && sharedMediaData[0].filterType == FILTER_PHOTOS_ONLY && obj.isVideo()) { + continue; + } + if (sharedMediaData[type].startReached) { + sharedMediaData[type].addMessage(obj, 0, true, enc); + } + sharedMediaData[type].totalCount++; + for (int i = 0; i < sharedMediaData[type].fastScrollPeriods.size(); i++) { + sharedMediaData[type].fastScrollPeriods.get(i).startOffset++; + } } loadMediaCounts(); } @@ -347,10 +629,18 @@ public void didReceivedNotification(int id, int account, Object... args) { int guid = (Integer) args[3]; if (guid == parentFragment.getClassGuid()) { int type = (Integer) args[4]; - sharedMediaData[type].setTotalCount((Integer) args[1]); + if (type != 0 && type != 6 && type != 7 && type != 1 && type != 2 && type != 4) { + sharedMediaData[type].setTotalCount((Integer) args[1]); + } ArrayList arr = (ArrayList) args[2]; boolean enc = DialogObject.isEncryptedDialog(did); int loadIndex = did == dialogId ? 0 : 1; + if (type == 0 || type == 6 || type == 7) { + if (type != sharedMediaData[0].filterType) { + return; + } + type = 0; + } if (!arr.isEmpty()) { sharedMediaData[type].setEndReached(loadIndex, (Boolean) args[5]); } @@ -380,6 +670,7 @@ public void didReceivedNotification(int id, int account, Object... args) { } boolean changed = false; + int type; ArrayList markAsDeletedMessages = (ArrayList) args[0]; for (int a = 0, N = markAsDeletedMessages.size(); a < N; a++) { for (int b = 0; b < sharedMediaData.length; b++) { @@ -509,18 +800,17 @@ public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObj } int[] coords = new int[2]; ImageReceiver imageReceiver = null; - if (view instanceof SharedPhotoVideoCell) { - SharedPhotoVideoCell cell = (SharedPhotoVideoCell) view; - for (int i = 0; i < 6; i++) { - MessageObject message = cell.getMessageObject(i); - if (message == null) { - break; - } - if (message.getId() == messageObject.getId()) { - BackupImageView imageView = cell.getImageView(i); - imageReceiver = imageView.getImageReceiver(); - imageView.getLocationInWindow(coords); - } + if (view instanceof SharedPhotoVideoCell2) { + SharedPhotoVideoCell2 cell = (SharedPhotoVideoCell2) view; + MessageObject message = cell.getMessageObject(); + if (message == null) { + continue; + } + if (message.getId() == messageObject.getId()) { + imageReceiver = cell.imageReceiver; + cell.getLocationInWindow(coords); + coords[0] += Math.round(cell.imageReceiver.getImageX()); + coords[1] += Math.round(cell.imageReceiver.getImageY()); } } else if (view instanceof SharedDocumentCell) { SharedDocumentCell cell = (SharedDocumentCell) view; @@ -559,6 +849,7 @@ public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObj object.thumb = object.imageReceiver.getBitmapSafe(); object.parentView.getLocationInWindow(coords); object.clipTopAddition = 0; + object.starOffset = sharedMediaData[0].startOffset; if (fragmentContextView != null && fragmentContextView.getVisibility() == View.VISIBLE) { object.clipTopAddition += AndroidUtilities.dp(36); } @@ -596,10 +887,10 @@ public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObj if (position <= firstVisiblePosition) { mediaPages[0].layoutManager.scrollToPositionWithOffset(position, 0); - profileActivity.scrollToSharedMedia(); + delegate.scrollToSharedMedia(); } else if (position >= lastVisiblePosition && lastVisiblePosition >= 0) { mediaPages[0].layoutManager.scrollToPositionWithOffset(position, 0, true); - profileActivity.scrollToSharedMedia(); + delegate.scrollToSharedMedia(); } } @@ -612,10 +903,28 @@ public static class SharedMediaData { public SparseArray[] messagesDict = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; public ArrayList sections = new ArrayList<>(); public HashMap> sectionArrays = new HashMap<>(); + public ArrayList fastScrollPeriods = new ArrayList<>(); public int totalCount; public boolean loading; + public boolean fastScrollDataLoaded; public boolean[] endReached = new boolean[]{false, true}; public int[] max_id = new int[]{0, 0}; + public int min_id; + public boolean startReached = true; + private int startOffset; + private int endLoadingStubs; + public boolean loadingAfterFastScroll; + public int requestIndex; + + public int filterType = FILTER_PHOTOS_AND_VIDEOS; + public boolean isFrozen; + public ArrayList frozenMessages = new ArrayList<>(); + public int frozenStartOffset; + public int frozenEndLoadingStubs; + private boolean hasVideos; + private boolean hasPhotos; + + RecyclerView.RecycledViewPool recycledViewPool = new RecyclerView.RecycledViewPool(); public void setTotalCount(int count) { totalCount = count; @@ -654,9 +963,17 @@ public boolean addMessage(MessageObject messageObject, int loadIndex, boolean is if (!enc) { if (messageObject.getId() > 0) { max_id[loadIndex] = Math.min(messageObject.getId(), max_id[loadIndex]); + min_id = Math.max(messageObject.getId(), min_id); } } else { max_id[loadIndex] = Math.max(messageObject.getId(), max_id[loadIndex]); + min_id = Math.min(messageObject.getId(), min_id); + } + if (!hasVideos && messageObject.isVideo()) { + hasVideos = true; + } + if (!hasPhotos && messageObject.isPhoto()) { + hasPhotos = true; } return true; } @@ -690,6 +1007,46 @@ public void replaceMid(int oldMid, int newMid) { max_id[0] = Math.min(newMid, max_id[0]); } } + + public ArrayList getMessages() { + return isFrozen ? frozenMessages : messages; + } + + public int getStartOffset() { + return isFrozen ? frozenStartOffset : startOffset; + } + + public void setListFrozen(boolean frozen) { + if (isFrozen == frozen) { + return; + } + isFrozen = frozen; + if (frozen) { + frozenStartOffset = startOffset; + frozenEndLoadingStubs = endLoadingStubs; + frozenMessages.clear(); + frozenMessages.addAll(messages); + } + } + + public int getEndLoadingStubs() { + return isFrozen ? frozenEndLoadingStubs : endLoadingStubs; + } + } + + public static class Period { + public String formatedDate; + public int startOffset; + int date; + //int messagesCount; + int maxId; + + public Period(TLRPC.TL_searchResultPosition calendarPeriod) { + this.date = calendarPeriod.date; + this.maxId = calendarPeriod.msg_id; + this.startOffset = calendarPeriod.offset; + formatedDate = LocaleController.formatYearMont(this.date, true); + } } private SharedMediaData[] sharedMediaData = new SharedMediaData[6]; @@ -699,7 +1056,7 @@ public void replaceMid(int oldMid, int newMid) { private final static int delete = 101; private final static int gotochat = 102; - private ProfileActivity profileActivity; + private BaseFragment profileActivity; private int startedTrackingPointerId; private boolean startedTracking; @@ -710,10 +1067,17 @@ public void replaceMid(int oldMid, int newMid) { private boolean isActionModeShowed; - public SharedMediaLayout(Context context, long did, SharedMediaPreloader preloader, int commonGroupsCount, ArrayList sortedUsers, TLRPC.ChatFull chatInfo, boolean membersFirst, ProfileActivity parent) { + final Delegate delegate; + + public SharedMediaLayout(Context context, long did, SharedMediaPreloader preloader, int commonGroupsCount, ArrayList sortedUsers, TLRPC.ChatFull chatInfo, boolean membersFirst, BaseFragment parent, Delegate delegate, int viewType) { super(context); + this.viewType = viewType; + + globalGradientView = new FlickerLoadingView(context); + globalGradientView.setIsSingleCell(true); sharedMediaPreloader = preloader; + this.delegate = delegate; int[] mediaCount = preloader.getLastMediaCount(); hasMedia = new int[]{mediaCount[0], mediaCount[1], mediaCount[2], mediaCount[3], mediaCount[4], mediaCount[5], commonGroupsCount}; if (membersFirst) { @@ -743,6 +1107,7 @@ public SharedMediaLayout(Context context, long did, SharedMediaPreloader preload profileActivity = parent; actionBar = profileActivity.getActionBar(); + mediaColumnsCount = SharedConfig.mediaColumnsCount; profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.mediaDidLoad); profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.messagesDeleted); @@ -753,7 +1118,7 @@ public SharedMediaLayout(Context context, long did, SharedMediaPreloader preload profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.messagePlayingDidStart); for (int a = 0; a < 10; a++) { - cellCache.add(new SharedPhotoVideoCell(context)); + //cellCache.add(new SharedPhotoVideoCell(context)); if (initialTab == MediaDataController.MEDIA_MUSIC) { SharedAudioCell cell = new SharedAudioCell(context) { @Override @@ -794,6 +1159,13 @@ public boolean needPlayMessage(MessageObject messageObject) { actionModeViews.clear(); final ActionBarMenu menu = actionBar.createMenu(); + menu.addOnLayoutChangeListener(new OnLayoutChangeListener() { + @Override + public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7) { + View parent = (View) searchItem.getParent(); + searchItem.setTranslationX(parent.getMeasuredWidth() - searchItem.getRight()); + } + }); searchItem = menu.addItem(0, R.drawable.ic_ab_search).setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { @Override public void onSearchExpand() { @@ -852,13 +1224,169 @@ public void onTextChanged(EditText editText) { @Override public void onLayout(int l, int t, int r, int b) { View parent = (View) searchItem.getParent(); - searchItem.setTranslationX(parent.getMeasuredWidth() - r); + searchItem.setTranslationX(parent.getMeasuredWidth() - searchItem.getRight()); } }); searchItem.setTranslationY(AndroidUtilities.dp(10)); searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); searchItem.setContentDescription(LocaleController.getString("Search", R.string.Search)); searchItem.setVisibility(View.INVISIBLE); + + photoVideoOptionsItem = new ImageView(context); + photoVideoOptionsItem.setTranslationY(AndroidUtilities.dp(10)); + photoVideoOptionsItem.setVisibility(View.INVISIBLE); + + Drawable calendarDrawable = ContextCompat.getDrawable(context, R.drawable.ic_ab_other).mutate(); + calendarDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), PorterDuff.Mode.MULTIPLY)); + photoVideoOptionsItem.setImageDrawable(calendarDrawable); + photoVideoOptionsItem.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + actionBar.addView(photoVideoOptionsItem, LayoutHelper.createFrame(48, 56, Gravity.RIGHT | Gravity.BOTTOM)); + photoVideoOptionsItem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + View dividerView = new DividerCell(context); + ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (dividerView.getParent() != null) { + dividerView.setVisibility(View.GONE); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + dividerView.getLayoutParams().width = getMeasuredWidth() - AndroidUtilities.dp(16); + dividerView.setVisibility(View.VISIBLE); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } else { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + } + }; + + ActionBarMenuSubItem mediaZoomInItem = new ActionBarMenuSubItem(context, true, false); + ActionBarMenuSubItem mediaZoomOutItem = new ActionBarMenuSubItem(context, false, false); + + mediaZoomInItem.setTextAndIcon(LocaleController.getString("MediaZoomIn", R.string.MediaZoomIn), R.drawable.msg_zoomin); + mediaZoomInItem.setOnClickListener(view1 -> { + if (photoVideoChangeColumnsAnimation) { + return; + } + int newColumnsCount = getNextMediaColumnsCount(mediaColumnsCount, true); + if (newColumnsCount == getNextMediaColumnsCount(newColumnsCount, true)) { + mediaZoomInItem.setEnabled(false); + mediaZoomInItem.animate().alpha(0.5f).start(); + } + if (mediaColumnsCount != newColumnsCount) { + if (!mediaZoomOutItem.isEnabled()) { + mediaZoomOutItem.setEnabled(true); + mediaZoomOutItem.animate().alpha(1f).start(); + } + SharedConfig.setMediaColumnsCount(newColumnsCount); + animateToMediaColumnsCount(newColumnsCount); + } + }); + popupLayout.addView(mediaZoomInItem); + + mediaZoomOutItem.setTextAndIcon(LocaleController.getString("MediaZoomOut", R.string.MediaZoomOut), R.drawable.msg_zoomout); + mediaZoomOutItem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + if (photoVideoChangeColumnsAnimation) { + return; + } + int newColumnsCount = getNextMediaColumnsCount(mediaColumnsCount, false); + if (newColumnsCount == getNextMediaColumnsCount(newColumnsCount, false)) { + mediaZoomOutItem.setEnabled(false); + mediaZoomOutItem.animate().alpha(0.5f).start(); + } + if (mediaColumnsCount != newColumnsCount) { + if (!mediaZoomInItem.isEnabled()) { + mediaZoomInItem.setEnabled(true); + mediaZoomInItem.animate().alpha(1f).start(); + } + SharedConfig.setMediaColumnsCount(newColumnsCount); + animateToMediaColumnsCount(newColumnsCount); + } + } + }); + + if (mediaColumnsCount == 2) { + mediaZoomInItem.setEnabled(false); + mediaZoomInItem.setAlpha(0.5f); + } else if (mediaColumnsCount == 9) { + mediaZoomOutItem.setEnabled(false); + mediaZoomOutItem.setAlpha(0.5f); + } + + popupLayout.addView(mediaZoomOutItem); + boolean hasDifferentTypes = (sharedMediaData[0].hasPhotos && sharedMediaData[0].hasVideos) || !sharedMediaData[0].endReached[0] || !sharedMediaData[0].endReached[1] || !sharedMediaData[0].startReached; + if (!DialogObject.isEncryptedDialog(dialog_id)) { + ActionBarMenuSubItem calendarItem = new ActionBarMenuSubItem(context, false, false); + calendarItem.setTextAndIcon(LocaleController.getString("Calendar", R.string.Calendar), R.drawable.msg_calendar2); + popupLayout.addView(calendarItem); + calendarItem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + showMediaCalendar(false); + if (optionsWindow != null) { + optionsWindow.dismiss(); + } + } + }); + + if (hasDifferentTypes) { + popupLayout.addView(dividerView); + ActionBarMenuSubItem showPhotosItem = new ActionBarMenuSubItem(context, true, false, false); + ActionBarMenuSubItem showVideosItem = new ActionBarMenuSubItem(context, true, false, true); + + showPhotosItem.setTextAndIcon(LocaleController.getString("MediaShowPhotos", R.string.MediaShowPhotos), 0); + showPhotosItem.setChecked(sharedMediaData[0].filterType == FILTER_PHOTOS_AND_VIDEOS || sharedMediaData[0].filterType == FILTER_PHOTOS_ONLY); + showPhotosItem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + if (changeTypeAnimation) { + return; + } + if (!showVideosItem.getCheckView().isChecked() && showPhotosItem.getCheckView().isChecked()) { + return; + } + showPhotosItem.setChecked(!showPhotosItem.getCheckView().isChecked()); + if (showPhotosItem.getCheckView().isChecked() && showVideosItem.getCheckView().isChecked()) { + sharedMediaData[0].filterType = FILTER_PHOTOS_AND_VIDEOS; + } else { + sharedMediaData[0].filterType = FILTER_VIDEOS_ONLY; + } + changeMediaFilterType(); + } + }); + popupLayout.addView(showPhotosItem); + + + showVideosItem.setTextAndIcon(LocaleController.getString("MediaShowVideos", R.string.MediaShowVideos), 0); + showVideosItem.setChecked(sharedMediaData[0].filterType == FILTER_PHOTOS_AND_VIDEOS || sharedMediaData[0].filterType == FILTER_VIDEOS_ONLY); + showVideosItem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + if (changeTypeAnimation) { + return; + } + if (!showPhotosItem.getCheckView().isChecked() && showVideosItem.getCheckView().isChecked()) { + return; + } + showVideosItem.setChecked(!showVideosItem.getCheckView().isChecked()); + if (showPhotosItem.getCheckView().isChecked() && showVideosItem.getCheckView().isChecked()) { + sharedMediaData[0].filterType = FILTER_PHOTOS_AND_VIDEOS; + } else { + sharedMediaData[0].filterType = FILTER_PHOTOS_ONLY; + } + changeMediaFilterType(); + } + }); + popupLayout.addView(showVideosItem); + } + } + + optionsWindow = AlertsCreator.showPopupMenu(popupLayout, photoVideoOptionsItem, 0, -AndroidUtilities.dp(56)); + } + }); + EditTextBoldCursor editText = searchItem.getSearchField(); editText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); editText.setHintTextColor(Theme.getColor(Theme.key_player_time)); @@ -913,7 +1441,17 @@ public void onLayout(int l, int t, int r, int b) { actionModeViews.add(deleteItem); deleteItem.setOnClickListener(v -> onActionBarItemClick(delete)); - photoVideoAdapter = new SharedPhotoVideoAdapter(context); + photoVideoAdapter = new SharedPhotoVideoAdapter(context) { + @Override + public void notifyDataSetChanged() { + super.notifyDataSetChanged(); + MediaPage mediaPage = getMediaPage(0); + if (mediaPage != null && mediaPage.animationSupportingListView.getVisibility() == View.VISIBLE) { + animationSupportingPhotoVideoAdapter.notifyDataSetChanged(); + } + } + }; + animationSupportingPhotoVideoAdapter = new SharedPhotoVideoAdapter(context); documentsAdapter = new SharedDocumentsAdapter(context, 1); voiceAdapter = new SharedDocumentsAdapter(context, 2); audioAdapter = new SharedDocumentsAdapter(context, 4); @@ -963,9 +1501,20 @@ public void setTranslationX(float translationX) { } else if (searchItemState == 1) { searchItem.setAlpha(scrollProgress); } + + float photoVideoOptionsAlpha = 0f; + if (mediaPages[1] != null && mediaPages[1].selectedType == 0) { + photoVideoOptionsAlpha = scrollProgress; + } + if (mediaPages[0].selectedType == 0) { + photoVideoOptionsAlpha = 1f - scrollProgress; + } + photoVideoOptionsItem.setAlpha(photoVideoOptionsAlpha); + photoVideoOptionsItem.setVisibility((photoVideoOptionsAlpha == 0 || !canShowSearchItem()) ? INVISIBLE : View.VISIBLE); } else { searchItem.setAlpha(0.0f); } + } } } @@ -986,7 +1535,7 @@ public boolean supportsPredictiveItemAnimations() { protected void calculateExtraLayoutSpace(RecyclerView.State state, int[] extraLayoutSpace) { super.calculateExtraLayoutSpace(state, extraLayoutSpace); if (mediaPage.selectedType == 0) { - extraLayoutSpace[1] = Math.max(extraLayoutSpace[1], SharedPhotoVideoCell.getItemSize(columnsCount) * 2); + extraLayoutSpace[1] = Math.max(extraLayoutSpace[1], SharedPhotoVideoCell.getItemSize(1) * 2); } else if (mediaPage.selectedType == 1) { extraLayoutSpace[1] = Math.max(extraLayoutSpace[1], AndroidUtilities.dp(56f) * 2); } @@ -1041,6 +1590,12 @@ public void onInitializeAccessibilityNodeInfoForItem(RecyclerView.Recycler recyc layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { + if (mediaPage.listView.getAdapter() == photoVideoAdapter) { + if (photoVideoAdapter.getItemViewType(position) == 2) { + return mediaColumnsCount; + } + return 1; + } if (mediaPage.listView.getAdapter() != gifAdapter) { return mediaPage.layoutManager.getSpanCount(); } @@ -1052,6 +1607,11 @@ public int getSpanSize(int position) { }); mediaPages[a].listView = new RecyclerListView(context) { + HashSet excludeDrawViews = new HashSet<>(); + ArrayList drawingViews = new ArrayList<>(); + ArrayList drawingViews2 = new ArrayList<>(); + ArrayList drawingViews3 = new ArrayList<>(); + @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); @@ -1064,23 +1624,259 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { @Override protected void dispatchDraw(Canvas canvas) { if (getAdapter() == photoVideoAdapter) { + int firstVisibleItemPosition = 0; + int firstVisibleItemPosition2 = 0; + int lastVisibleItemPosition = 0; + int lastVisibleItemPosition2 = 0; + + int rowsOffset = 0; + int columnsOffset = 0; + float minY = getMeasuredHeight(); + if (photoVideoChangeColumnsAnimation) { + firstVisibleItemPosition = mediaPage.layoutManager.findFirstVisibleItemPosition(); + firstVisibleItemPosition2 = mediaPage.animationSupportingLayoutManager.findFirstVisibleItemPosition(); + lastVisibleItemPosition = mediaPage.layoutManager.findLastVisibleItemPosition(); + lastVisibleItemPosition2 = mediaPage.animationSupportingLayoutManager.findLastVisibleItemPosition(); + + if (firstVisibleItemPosition >= 0 && firstVisibleItemPosition2 >= 0 && pinchCenterPosition >= 0) { + int rowsCount1 = (int) Math.ceil(photoVideoAdapter.getItemCount() / (float) mediaColumnsCount); + int rowsCount2 = (int) Math.ceil(photoVideoAdapter.getItemCount() / (float) animateToColumnsCount); + rowsOffset = (pinchCenterPosition / animateToColumnsCount - firstVisibleItemPosition2 / animateToColumnsCount) - (pinchCenterPosition / mediaColumnsCount - firstVisibleItemPosition / mediaColumnsCount); + if ((firstVisibleItemPosition / mediaColumnsCount - rowsOffset < 0 && animateToColumnsCount < mediaColumnsCount) || (firstVisibleItemPosition2 / animateToColumnsCount + rowsOffset < 0 && animateToColumnsCount > mediaColumnsCount)) { + rowsOffset = 0; + } + if ((lastVisibleItemPosition2 / mediaColumnsCount + rowsOffset >= rowsCount1 && animateToColumnsCount > mediaColumnsCount) || (lastVisibleItemPosition / animateToColumnsCount - rowsOffset >= rowsCount2 && animateToColumnsCount < mediaColumnsCount)) { + rowsOffset = 0; + } + + float k = (pinchCenterPosition % mediaColumnsCount) / (float) (mediaColumnsCount - 1); + columnsOffset = (int) ((animateToColumnsCount - mediaColumnsCount) * k); + } + animationSupportingSortedCells.clear(); + excludeDrawViews.clear(); + drawingViews.clear(); + drawingViews2.clear(); + drawingViews3.clear(); + for (int i = 0; i < mediaPage.animationSupportingListView.getChildCount(); i++) { + View child = mediaPage.animationSupportingListView.getChildAt(i); + if (child.getTop() > getMeasuredHeight() || child.getBottom() < 0) { + continue; + } + if (child instanceof SharedPhotoVideoCell2) { + animationSupportingSortedCells.add((SharedPhotoVideoCell2) child); + } + } + drawingViews.addAll(animationSupportingSortedCells); + FastScroll fastScroll = getFastScroll(); + if (fastScroll != null) { + float p1 = photoVideoAdapter.getScrollProgress(mediaPage.listView); + float p2 = animationSupportingPhotoVideoAdapter.getScrollProgress(mediaPage.animationSupportingListView); + float a1 = photoVideoAdapter.fastScrollIsVisible(mediaPage.listView) ? 1f : 0f; + float a2 = animationSupportingPhotoVideoAdapter.fastScrollIsVisible(mediaPage.animationSupportingListView) ? 1f : 0f; + fastScroll.setProgress(p1 * (1f - photoVideoChangeColumnsProgress) + p2 * photoVideoChangeColumnsProgress); + fastScroll.setAlpha(a1 * (1f - photoVideoChangeColumnsProgress) + a2 * photoVideoChangeColumnsProgress); + } + } + for (int i = 0; i < getChildCount(); i++) { - if (getChildViewHolder(getChildAt(i)).getItemViewType() == 1) { + View child = getChildAt(i); + if (child.getTop() > getMeasuredHeight() || child.getBottom() < 0) { + if (child instanceof SharedPhotoVideoCell2) { + SharedPhotoVideoCell2 cell = (SharedPhotoVideoCell2) getChildAt(i); + cell.setCrossfadeView(null, 0, 0); + cell.setTranslationX(0); + cell.setTranslationY(0); + cell.setImageScale(1f, !photoVideoChangeColumnsAnimation); + } + continue; + } + if (child instanceof SharedPhotoVideoCell2) { + SharedPhotoVideoCell2 cell = (SharedPhotoVideoCell2) getChildAt(i); + + if (cell.getMessageId() == mediaPage.highlightMessageId && cell.imageReceiver.hasBitmapImage()) { + if (!mediaPage.highlightAnimation) { + mediaPage.highlightProgress = 0; + mediaPage.highlightAnimation = true; + } + float p = 1f; + if (mediaPage.highlightProgress < 0.3f) { + p = mediaPage.highlightProgress / 0.3f; + } else if (mediaPage.highlightProgress > 0.7f) { + p = (1f - mediaPage.highlightProgress) / 0.3f; + } + cell.setHighlightProgress(p); + } else { + cell.setHighlightProgress(0); + } + + MessageObject messageObject = cell.getMessageObject(); + float alpha = 1f; + if (messageObject != null && messageAlphaEnter.get(messageObject.getId(), null) != null) { + alpha = messageAlphaEnter.get(messageObject.getId(), 1f); + } + cell.setImageAlpha(alpha, !photoVideoChangeColumnsAnimation); + + boolean inAnimation = false; + if (photoVideoChangeColumnsAnimation) { + float fromScale = 1f; + + int currentColumn = ((GridLayoutManager.LayoutParams) cell.getLayoutParams()).getViewAdapterPosition() % mediaColumnsCount + columnsOffset; + int currentRow = (((GridLayoutManager.LayoutParams) cell.getLayoutParams()).getViewAdapterPosition() - firstVisibleItemPosition) / mediaColumnsCount + rowsOffset; + int toIndex = currentRow * animateToColumnsCount + currentColumn; + if (currentColumn >= 0 && currentColumn < animateToColumnsCount && toIndex >= 0 && toIndex < animationSupportingSortedCells.size()) { + inAnimation = true; + float toScale = (animationSupportingSortedCells.get(toIndex).getMeasuredWidth() - AndroidUtilities.dpf2(2)) / (float) (cell.getMeasuredWidth() - AndroidUtilities.dpf2(2)); + float scale = fromScale * (1f - photoVideoChangeColumnsProgress) + toScale * photoVideoChangeColumnsProgress; + float fromX = cell.getLeft(); + float fromY = cell.getTop(); + float toX = animationSupportingSortedCells.get(toIndex).getLeft(); + float toY = animationSupportingSortedCells.get(toIndex).getTop(); + + cell.setPivotX(0); + cell.setPivotY(0); + cell.setImageScale(scale, !photoVideoChangeColumnsAnimation); + cell.setTranslationX((toX - fromX) * photoVideoChangeColumnsProgress); + cell.setTranslationY((toY - fromY) * photoVideoChangeColumnsProgress); + cell.setCrossfadeView(animationSupportingSortedCells.get(toIndex), photoVideoChangeColumnsProgress, animateToColumnsCount); + excludeDrawViews.add(animationSupportingSortedCells.get(toIndex)); + drawingViews3.add(cell); + canvas.save(); + canvas.translate(cell.getX(), cell.getY()); + cell.draw(canvas); + canvas.restore(); + + if (cell.getY() < minY) { + minY = cell.getY(); + } + } + } + + if (!inAnimation) { + if (photoVideoChangeColumnsAnimation) { + drawingViews2.add(cell); + } + cell.setCrossfadeView(null, 0, 0); + cell.setTranslationX(0); + cell.setTranslationY(0); + cell.setImageScale(1f, !photoVideoChangeColumnsAnimation); + } + } + } + + if (photoVideoChangeColumnsAnimation && !drawingViews.isEmpty()) { + float toScale = animateToColumnsCount / (float) mediaColumnsCount; + float scale = toScale * (1f - photoVideoChangeColumnsProgress) + photoVideoChangeColumnsProgress; + + float sizeToScale = ((getMeasuredWidth() / (float) mediaColumnsCount) - AndroidUtilities.dpf2(2)) / ((getMeasuredWidth() / (float) animateToColumnsCount) - AndroidUtilities.dpf2(2)); + float scaleSize = sizeToScale * (1f - photoVideoChangeColumnsProgress) + photoVideoChangeColumnsProgress; + + float fromSize = getMeasuredWidth() / (float) mediaColumnsCount; + float toSize = (getMeasuredWidth() / (float) animateToColumnsCount); + float size1 = (float) ((Math.ceil((getMeasuredWidth() / (float) animateToColumnsCount)) - AndroidUtilities.dpf2(2)) * scaleSize + AndroidUtilities.dpf2(2)); + + for (int i = 0; i < drawingViews.size(); i++) { + SharedPhotoVideoCell2 view = drawingViews.get(i); + if (excludeDrawViews.contains(view)) { + continue; + } + view.setCrossfadeView(null, 0, 0); + int fromColumn = ((GridLayoutManager.LayoutParams) view.getLayoutParams()).getViewAdapterPosition() % animateToColumnsCount; + int toColumn = fromColumn - columnsOffset; + int currentRow = (((GridLayoutManager.LayoutParams) view.getLayoutParams()).getViewAdapterPosition() - firstVisibleItemPosition2) / animateToColumnsCount; + currentRow -= rowsOffset; + canvas.save(); - canvas.translate(getChildAt(i).getX(), getChildAt(i).getY() - getChildAt(i).getMeasuredHeight() + AndroidUtilities.dp(2)); - getChildAt(i).draw(canvas); + canvas.translate(toColumn * fromSize * (1f - photoVideoChangeColumnsProgress) + toSize * fromColumn * photoVideoChangeColumnsProgress, minY + size1 * currentRow); + view.setImageScale(scaleSize, !photoVideoChangeColumnsAnimation); + if (toColumn < mediaColumnsCount) { + canvas.saveLayerAlpha(0, 0, view.getMeasuredWidth() * scale, view.getMeasuredWidth() * scale, (int) (photoVideoChangeColumnsProgress * 255), Canvas.ALL_SAVE_FLAG); + view.draw(canvas); + canvas.restore(); + } else { + view.draw(canvas); + } canvas.restore(); - invalidate(); } } + + super.dispatchDraw(canvas); + + if (photoVideoChangeColumnsAnimation) { + float toScale = mediaColumnsCount / (float) animateToColumnsCount; + float scale = toScale * photoVideoChangeColumnsProgress + (1f - photoVideoChangeColumnsProgress); + + float sizeToScale = ((getMeasuredWidth() / (float) animateToColumnsCount) - AndroidUtilities.dpf2(2)) / ((getMeasuredWidth() / (float) mediaColumnsCount) - AndroidUtilities.dpf2(2)); + float scaleSize = sizeToScale * photoVideoChangeColumnsProgress + (1f - photoVideoChangeColumnsProgress); + + float size1 = (float) ((Math.ceil((getMeasuredWidth() / (float) mediaColumnsCount)) - AndroidUtilities.dpf2(2)) * scaleSize + AndroidUtilities.dpf2(2)); + float fromSize = getMeasuredWidth() / (float) mediaColumnsCount; + float toSize = getMeasuredWidth() / (float) animateToColumnsCount; + + for (int i = 0; i < drawingViews2.size(); i++) { + SharedPhotoVideoCell2 view = drawingViews2.get(i); + int fromColumn = ((GridLayoutManager.LayoutParams) view.getLayoutParams()).getViewAdapterPosition() % mediaColumnsCount; + int currentRow = (((GridLayoutManager.LayoutParams) view.getLayoutParams()).getViewAdapterPosition() - firstVisibleItemPosition) / mediaColumnsCount; + + currentRow += rowsOffset; + int toColumn = fromColumn + columnsOffset; + + canvas.save(); + view.setImageScale(scaleSize, !photoVideoChangeColumnsAnimation); + canvas.translate(fromColumn * fromSize * (1f - photoVideoChangeColumnsProgress) + toSize * toColumn * photoVideoChangeColumnsProgress, minY + size1 * currentRow); + if (toColumn < animateToColumnsCount) { + canvas.saveLayerAlpha(0, 0, view.getMeasuredWidth() * scale, view.getMeasuredWidth() * scale, (int) ((1f - photoVideoChangeColumnsProgress) * 255), Canvas.ALL_SAVE_FLAG); + view.draw(canvas); + canvas.restore(); + } else { + view.draw(canvas); + } + canvas.restore(); + } + + if (!drawingViews3.isEmpty()) { + canvas.saveLayerAlpha(0, 0, getMeasuredWidth(), getMeasuredHeight(), (int) (255 * photoVideoChangeColumnsProgress), Canvas.ALL_SAVE_FLAG); + for (int i = 0; i < drawingViews3.size(); i++) { + drawingViews3.get(i).drawCrossafadeImage(canvas); + } + canvas.restore(); + } + } + } else { + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + int messageId = getMessageId(child); + float alpha = 1; + if (messageId != 0 && messageAlphaEnter.get(messageId, null) != null) { + alpha = messageAlphaEnter.get(messageId, 1f); + } + if (child instanceof SharedDocumentCell) { + SharedDocumentCell cell = (SharedDocumentCell) child; + cell.setEnterAnimationAlpha(alpha); + } else if (child instanceof SharedAudioCell) { + SharedAudioCell cell = (SharedAudioCell) child; + cell.setEnterAnimationAlpha(alpha); + } + } + super.dispatchDraw(canvas); + } + + + if (mediaPage.highlightAnimation) { + mediaPage.highlightProgress += 16f / 1500f; + if (mediaPage.highlightProgress >= 1) { + mediaPage.highlightProgress = 0; + mediaPage.highlightAnimation = false; + mediaPage.highlightMessageId = 0; + } + invalidate(); } - super.dispatchDraw(canvas); + } @Override public boolean drawChild(Canvas canvas, View child, long drawingTime) { if (getAdapter() == photoVideoAdapter) { - if (getChildViewHolder(child).getItemViewType() == 1) { + if (photoVideoChangeColumnsAnimation && child instanceof SharedPhotoVideoCell2) { return true; } } @@ -1088,6 +1884,8 @@ public boolean drawChild(Canvas canvas, View child, long drawingTime) { } }; + + mediaPages[a].listView.setFastScrollEnabled(RecyclerListView.FastScroll.DATE_TYPE); mediaPages[a].listView.setScrollingTouchSlop(RecyclerView.TOUCH_SLOP_PAGING); mediaPages[a].listView.setPinnedSectionOffsetY(-AndroidUtilities.dp(2)); mediaPages[a].listView.setPadding(0, AndroidUtilities.dp(2), 0, 0); @@ -1096,6 +1894,25 @@ public boolean drawChild(Canvas canvas, View child, long drawingTime) { mediaPages[a].listView.setSectionsType(2); mediaPages[a].listView.setLayoutManager(layoutManager); mediaPages[a].addView(mediaPages[a].listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + mediaPages[a].animationSupportingListView = new RecyclerListView(context); + mediaPages[a].animationSupportingListView.setLayoutManager(mediaPages[a].animationSupportingLayoutManager = new GridLayoutManager(context, 3) { + + @Override + public boolean supportsPredictiveItemAnimations() { + return false; + } + + @Override + public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) { + if (photoVideoChangeColumnsAnimation) { + dy = 0; + } + return super.scrollVerticallyBy(dy, recycler, state); + } + }); + mediaPages[a].addView(mediaPages[a].animationSupportingListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + mediaPages[a].animationSupportingListView.setVisibility(View.GONE); + mediaPages[a].listView.addItemDecoration(new RecyclerView.ItemDecoration() { @Override public void getItemOffsets(android.graphics.Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { @@ -1161,8 +1978,13 @@ public void getItemOffsets(android.graphics.Rect outRect, View view, RecyclerVie onItemClick(position, view, ((SharedLinkCell) view).getMessage(), 0, mediaPage.selectedType); } else if ((mediaPage.selectedType == 2 || mediaPage.selectedType == 4) && view instanceof SharedAudioCell) { onItemClick(position, view, ((SharedAudioCell) view).getMessage(), 0, mediaPage.selectedType); - } else if (mediaPage.selectedType == 5 && view instanceof ContextLinkCell) { + } else if (mediaPage.selectedType == 5 && view instanceof ContextLinkCell) { onItemClick(position, view, (MessageObject) ((ContextLinkCell) view).getParentObject(), 0, mediaPage.selectedType); + } else if (mediaPage.selectedType == 0 && view instanceof SharedPhotoVideoCell2) { + MessageObject messageObject = ((SharedPhotoVideoCell2) view).getMessageObject(); + if (messageObject != null) { + onItemClick(position, view, messageObject, 0, mediaPage.selectedType); + } } }); mediaPages[a].listView.setOnScrollListener(new RecyclerView.OnScrollListener() { @@ -1173,13 +1995,23 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - checkLoadMoreScroll(mediaPage, recyclerView, layoutManager); + checkLoadMoreScroll(mediaPage, (RecyclerListView) recyclerView, layoutManager); if (dy != 0 && (mediaPages[0].selectedType == 0 || mediaPages[0].selectedType == 5) && !sharedMediaData[0].messages.isEmpty()) { showFloatingDateView(); } + if (dy != 0 && mediaPage.selectedType == 0) { + showFastScrollHint(mediaPage, sharedMediaData, true); + } + mediaPage.listView.checkSection(true); + if (mediaPage.fastScrollHintView != null) { + mediaPage.invalidate(); + } } }); mediaPages[a].listView.setOnItemLongClickListener((view, position) -> { + if (photoVideoChangeColumnsAnimation) { + return false; + } if (isActionModeShowed) { mediaPage.listView.getOnItemClickListener().onItemClick(view, position); return true; @@ -1200,6 +2032,11 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { return onItemLongClick(((SharedAudioCell) view).getMessage(), view, 0); } else if (mediaPage.selectedType == 5 && view instanceof ContextLinkCell) { return onItemLongClick((MessageObject) ((ContextLinkCell) view).getParentObject(), view, 0); + } else if (mediaPage.selectedType == 0 && view instanceof SharedPhotoVideoCell2) { + MessageObject messageObject = ((SharedPhotoVideoCell2) view).getMessageObject(); + if (messageObject != null) { + return onItemLongClick(messageObject, view, 0); + } } return false; }); @@ -1223,7 +2060,7 @@ public void invalidate() { @Override public int getColumnsCount() { - return columnsCount; + return mediaColumnsCount; } @Override @@ -1301,6 +2138,344 @@ protected void onDraw(Canvas canvas) { updateTabs(false); switchToCurrentSelectedMode(false); + if (hasMedia[0] >= 0) { + loadFastScrollData(false); + } + } + + private int getMessageId(View child) { + if (child instanceof SharedPhotoVideoCell2) { + return ((SharedPhotoVideoCell2) child).getMessageId(); + } + if (child instanceof SharedDocumentCell) { + SharedDocumentCell cell = (SharedDocumentCell) child; + return cell.getMessage().getId(); + } + if (child instanceof SharedAudioCell) { + SharedAudioCell cell = (SharedAudioCell) child; + return cell.getMessage().getId(); + } + return 0; + } + + private boolean changeTypeAnimation; + + private void changeMediaFilterType() { + MediaPage mediaPage = getMediaPage(0); + if (mediaPage != null && mediaPage.getMeasuredHeight() > 0 && mediaPage.getMeasuredWidth() > 0) { + Bitmap bitmap = null; + try { + bitmap = Bitmap.createBitmap(mediaPage.getMeasuredWidth(), mediaPage.getMeasuredHeight(), Bitmap.Config.ARGB_8888); + } catch (Exception e) { + FileLog.e(e); + } + if (bitmap != null) { + changeTypeAnimation = true; + Canvas canvas = new Canvas(bitmap); + mediaPage.listView.draw(canvas); + View view = new View(mediaPage.getContext()); + view.setBackground(new BitmapDrawable(bitmap)); + mediaPage.addView(view); + Bitmap finalBitmap = bitmap; + view.animate().alpha(0f).setDuration(200).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + changeTypeAnimation = false; + if (view.getParent() != null) { + mediaPage.removeView(view); + finalBitmap.recycle(); + } + } + }).start(); + mediaPage.listView.setAlpha(0); + mediaPage.listView.animate().alpha(1f).setDuration(200).start(); + } + } + + int[] counts = sharedMediaPreloader.getLastMediaCount(); + ArrayList messages = sharedMediaPreloader.getSharedMediaData()[0].messages; + if (sharedMediaData[0].filterType == FILTER_PHOTOS_AND_VIDEOS) { + sharedMediaData[0].setTotalCount(counts[0]); + } else if (sharedMediaData[0].filterType == FILTER_PHOTOS_ONLY) { + sharedMediaData[0].setTotalCount(counts[6]); + } else { + sharedMediaData[0].setTotalCount(counts[7]); + } + sharedMediaData[0].fastScrollDataLoaded = false; + jumpToDate(0, DialogObject.isEncryptedDialog(dialog_id) ? Integer.MIN_VALUE : Integer.MAX_VALUE, 0, true); + loadFastScrollData(false); + delegate.updateSelectedMediaTabText(); + boolean enc = DialogObject.isEncryptedDialog(dialog_id); + for (int i = 0; i < messages.size(); i++) { + MessageObject messageObject = messages.get(i); + if (sharedMediaData[0].filterType == FILTER_PHOTOS_AND_VIDEOS) { + sharedMediaData[0].addMessage(messageObject, 0, false, enc); + } else if (sharedMediaData[0].filterType == FILTER_PHOTOS_ONLY) { + if (messageObject.isPhoto()) { + sharedMediaData[0].addMessage(messageObject, 0, false, enc); + } + } else { + if (!messageObject.isPhoto()) { + sharedMediaData[0].addMessage(messageObject, 0, false, enc); + } + } + } + } + + private MediaPage getMediaPage(int type) { + for (int i = 0; i < mediaPages.length; i++) { + if (mediaPages[i].selectedType == 0) { + return mediaPages[i]; + } + } + return null; + } + + private void showMediaCalendar(boolean fromFastScroll) { + if (fromFastScroll && SharedMediaLayout.this.getY() != 0 && viewType == VIEW_TYPE_PROFILE_ACTIVITY) { + return; + } + Bundle bundle = new Bundle(); + bundle.putLong("dialog_id", dialog_id); + int date = 0; + if (fromFastScroll) { + MediaPage mediaPage = getMediaPage(0); + if (mediaPage != null) { + ArrayList periods = sharedMediaData[0].fastScrollPeriods; + Period period = null; + int position = mediaPage.layoutManager.findFirstVisibleItemPosition(); + if (position >= 0) { + if (periods != null) { + for (int i = 0; i < periods.size(); i++) { + if (position <= periods.get(i).startOffset) { + period = periods.get(i); + break; + } + } + if (period == null) { + period = periods.get(periods.size() - 1); + } + } + if (period != null) { + date = period.date; + } + } + } + } + MediaCalendarActivity calendarActivity = new MediaCalendarActivity(bundle, sharedMediaData[0].filterType, date); + calendarActivity.setCallback(new MediaCalendarActivity.Callback() { + @Override + public void onDateSelected(int messageId, int startOffset) { + int index = -1; + for (int i = 0; i < sharedMediaData[0].messages.size(); i++) { + if (sharedMediaData[0].messages.get(i).getId() == messageId) { + index = i; + } + } + MediaPage mediaPage = getMediaPage(0); + if (index >= 0 && mediaPage != null) { + mediaPage.layoutManager.scrollToPositionWithOffset(index, 0); + } else { + jumpToDate(0, messageId, startOffset, true); + } + if (mediaPage != null) { + mediaPage.highlightMessageId = messageId; + mediaPage.highlightAnimation = false; + } + } + }); + profileActivity.presentFragment(calendarActivity); + } + + private void startPinchToMediaColumnsCount(boolean pinchScaleUp) { + if (photoVideoChangeColumnsAnimation) { + return; + } + MediaPage mediaPage = null; + for (int i = 0; i < mediaPages.length; i++) { + if (mediaPages[i].selectedType == 0) { + mediaPage = mediaPages[i]; + break; + } + } + if (mediaPage != null) { + int newColumnsCount = getNextMediaColumnsCount(mediaColumnsCount, pinchScaleUp); + animateToColumnsCount = newColumnsCount; + if (animateToColumnsCount == mediaColumnsCount) { + return; + } + mediaPage.animationSupportingListView.setVisibility(View.VISIBLE); + mediaPage.animationSupportingListView.setAdapter(animationSupportingPhotoVideoAdapter); + mediaPage.animationSupportingLayoutManager.setSpanCount(newColumnsCount); + AndroidUtilities.updateVisibleRows(mediaPage.listView); + + photoVideoChangeColumnsAnimation = true; + sharedMediaData[0].setListFrozen(true); + photoVideoChangeColumnsProgress = 0; + if (pinchCenterPosition >= 0) { + for (int k = 0; k < mediaPages.length; k++) { + if (mediaPages[k].selectedType == 0) { + mediaPages[k].animationSupportingLayoutManager.scrollToPositionWithOffset(pinchCenterPosition, pinchCenterOffset); + } + } + } else { + saveScrollPosition(); + } + } + } + + private void finishPinchToMediaColumnsCount() { + if (photoVideoChangeColumnsAnimation) { + MediaPage mediaPage = null; + for (int i = 0; i < mediaPages.length; i++) { + if (mediaPages[i].selectedType == 0) { + mediaPage = mediaPages[i]; + break; + } + } + if (mediaPage != null) { + if (photoVideoChangeColumnsProgress == 1f) { + int oldItemCount = photoVideoAdapter.getItemCount(); + photoVideoChangeColumnsAnimation = false; + sharedMediaData[0].setListFrozen(false); + mediaPage.animationSupportingListView.setVisibility(View.GONE); + mediaColumnsCount = animateToColumnsCount; + SharedConfig.setMediaColumnsCount(animateToColumnsCount); + mediaPage.layoutManager.setSpanCount(mediaColumnsCount); + mediaPage.listView.invalidate(); + if (photoVideoAdapter.getItemCount() == oldItemCount) { + AndroidUtilities.updateVisibleRows(mediaPage.listView); + } else { + updatePhotosAdapter(); + } + + if (pinchCenterPosition >= 0) { + for (int k = 0; k < mediaPages.length; k++) { + if (mediaPages[k].selectedType == 0) { + View view = mediaPages[k].animationSupportingLayoutManager.findViewByPosition(pinchCenterPosition); + if (view != null) { + pinchCenterOffset = view.getTop(); + } + mediaPages[k].layoutManager.scrollToPositionWithOffset(pinchCenterPosition, pinchCenterOffset); + } + } + } else { + saveScrollPosition(); + } + return; + } + if (photoVideoChangeColumnsProgress == 0) { + photoVideoChangeColumnsAnimation = false; + sharedMediaData[0].setListFrozen(false); + mediaPage.animationSupportingListView.setVisibility(View.GONE); + mediaPage.listView.invalidate(); + return; + } + boolean forward = photoVideoChangeColumnsProgress > 0.2f; + ValueAnimator animator = ValueAnimator.ofFloat(photoVideoChangeColumnsProgress, forward ? 1f : 0); + MediaPage finalMediaPage = mediaPage; + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + photoVideoChangeColumnsProgress = (float) valueAnimator.getAnimatedValue(); + finalMediaPage.listView.invalidate(); + } + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + int oldItemCount = photoVideoAdapter.getItemCount(); + photoVideoChangeColumnsAnimation = false; + sharedMediaData[0].setListFrozen(false); + if (forward) { + mediaColumnsCount = animateToColumnsCount; + SharedConfig.setMediaColumnsCount(animateToColumnsCount); + finalMediaPage.layoutManager.setSpanCount(mediaColumnsCount); + } + if (forward) { + if (photoVideoAdapter.getItemCount() == oldItemCount) { + AndroidUtilities.updateVisibleRows(finalMediaPage.listView); + } else { + updatePhotosAdapter(); + } + } + finalMediaPage.animationSupportingListView.setVisibility(View.GONE); + if (pinchCenterPosition >= 0) { + for (int k = 0; k < mediaPages.length; k++) { + if (mediaPages[k].selectedType == 0) { + if (forward) { + View view = mediaPages[k].animationSupportingLayoutManager.findViewByPosition(pinchCenterPosition); + if (view != null) { + pinchCenterOffset = view.getTop(); + } + } + mediaPages[k].layoutManager.scrollToPositionWithOffset(pinchCenterPosition, pinchCenterOffset); + } + } + } else { + saveScrollPosition(); + } + super.onAnimationEnd(animation); + } + }); + animator.setInterpolator(CubicBezierInterpolator.DEFAULT); + animator.setDuration(200); + animator.start(); + } + } + } + + int animationIndex; + + private void animateToMediaColumnsCount(int newColumnsCount) { + MediaPage mediaPage = getMediaPage(0); + pinchCenterPosition = -1; + + if (mediaPage != null) { + mediaPage.listView.stopScroll(); + animateToColumnsCount = newColumnsCount; + mediaPage.animationSupportingListView.setVisibility(View.VISIBLE); + mediaPage.animationSupportingListView.setAdapter(animationSupportingPhotoVideoAdapter); + mediaPage.animationSupportingLayoutManager.setSpanCount(newColumnsCount); + AndroidUtilities.updateVisibleRows(mediaPage.listView); + + photoVideoChangeColumnsAnimation = true; + sharedMediaData[0].setListFrozen(true); + photoVideoChangeColumnsProgress = 0; + saveScrollPosition(); + ValueAnimator animator = ValueAnimator.ofFloat(0, 1f); + MediaPage finalMediaPage = mediaPage; + animationIndex = NotificationCenter.getInstance(profileActivity.getCurrentAccount()).setAnimationInProgress(animationIndex, null); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + photoVideoChangeColumnsProgress = (float) valueAnimator.getAnimatedValue(); + finalMediaPage.listView.invalidate(); + } + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + NotificationCenter.getInstance(profileActivity.getCurrentAccount()).onAnimationFinish(animationIndex); + int oldItemCount = photoVideoAdapter.getItemCount(); + photoVideoChangeColumnsAnimation = false; + sharedMediaData[0].setListFrozen(false); + mediaColumnsCount = newColumnsCount; + finalMediaPage.layoutManager.setSpanCount(mediaColumnsCount); + if (photoVideoAdapter.getItemCount() == oldItemCount) { + AndroidUtilities.updateVisibleRows(finalMediaPage.listView); + } else { + updatePhotosAdapter(); + } + finalMediaPage.animationSupportingListView.setVisibility(View.GONE); + saveScrollPosition(); + } + }); + animator.setInterpolator(CubicBezierInterpolator.DEFAULT); + animator.setStartDelay(100); + animator.setDuration(350); + animator.start(); + } } @Override @@ -1355,6 +2530,16 @@ public void onPageScrolled(float progress) { mediaPages[0].setTranslationX(progress * mediaPages[0].getMeasuredWidth()); mediaPages[1].setTranslationX(progress * mediaPages[0].getMeasuredWidth() - mediaPages[0].getMeasuredWidth()); } + + float photoVideoOptionsAlpha = 0f; + if (mediaPages[0].selectedType == 0) { + photoVideoOptionsAlpha = 1f - progress; + } + if (mediaPages[1].selectedType == 0) { + photoVideoOptionsAlpha = progress; + } + photoVideoOptionsItem.setAlpha(photoVideoOptionsAlpha); + photoVideoOptionsItem.setVisibility((photoVideoOptionsAlpha == 0 || !canShowSearchItem()) ? INVISIBLE : View.VISIBLE); if (canShowSearchItem()) { if (searchItemState == 1) { searchItem.setAlpha(progress); @@ -1386,7 +2571,13 @@ private boolean fillMediaData(int type) { if (mediaData == null) { return false; } - sharedMediaData[type].totalCount = mediaData[type].totalCount; + if (type == 0) { + if (!sharedMediaData[type].fastScrollDataLoaded) { + sharedMediaData[type].totalCount = mediaData[type].totalCount; + } + } else { + sharedMediaData[type].totalCount = mediaData[type].totalCount; + } sharedMediaData[type].messages.addAll(mediaData[type].messages); sharedMediaData[type].sections.addAll(mediaData[type].sections); for (HashMap.Entry> entry : mediaData[type].sectionArrays.entrySet()) { @@ -1397,32 +2588,12 @@ private boolean fillMediaData(int type) { sharedMediaData[type].max_id[i] = mediaData[type].max_id[i]; sharedMediaData[type].endReached[i] = mediaData[type].endReached[i]; } + sharedMediaData[type].fastScrollPeriods.addAll(mediaData[type].fastScrollPeriods); return !mediaData[type].messages.isEmpty(); } private void showFloatingDateView() { - AndroidUtilities.cancelRunOnUIThread(hideFloatingDateRunnable); - AndroidUtilities.runOnUIThread(hideFloatingDateRunnable, 650); - if (floatingDateView.getTag() != null) { - return; - } - if (floatingDateAnimation != null) { - floatingDateAnimation.cancel(); - } - floatingDateView.setTag(1); - floatingDateAnimation = new AnimatorSet(); - floatingDateAnimation.setDuration(180); - floatingDateAnimation.playTogether( - ObjectAnimator.ofFloat(floatingDateView, View.ALPHA, 1.0f), - ObjectAnimator.ofFloat(floatingDateView, View.TRANSLATION_Y, additionalFloatingTranslation)); - floatingDateAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT); - floatingDateAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - floatingDateAnimation = null; - } - }); - floatingDateAnimation.start(); + } private void hideFloatingDateView(boolean animated) { @@ -1458,7 +2629,7 @@ private void scrollToTop() { int height; switch (mediaPages[0].selectedType) { case 0: - height = SharedPhotoVideoCell.getItemSize(columnsCount); + height = SharedPhotoVideoCell.getItemSize(1); break; case 1: case 2: @@ -1476,7 +2647,12 @@ private void scrollToTop() { height = AndroidUtilities.dp(58); break; } - int scrollDistance = mediaPages[0].layoutManager.findFirstVisibleItemPosition() * height; + int scrollDistance; + if (mediaPages[0].selectedType == 0) { + scrollDistance = mediaPages[0].layoutManager.findFirstVisibleItemPosition() / mediaColumnsCount * height; + } else { + scrollDistance = mediaPages[0].layoutManager.findFirstVisibleItemPosition() * height; + } if (scrollDistance >= mediaPages[0].listView.getMeasuredHeight() * 1.2f) { mediaPages[0].scrollHelper.setScrollDirection(RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP); mediaPages[0].scrollHelper.scrollToPosition(0, 0, false, true); @@ -1485,13 +2661,47 @@ private void scrollToTop() { } } - private void checkLoadMoreScroll(MediaPage mediaPage, RecyclerView recyclerView, LinearLayoutManager layoutManager) { + Runnable jumpToRunnable; + + private void checkLoadMoreScroll(MediaPage mediaPage, RecyclerListView recyclerView, LinearLayoutManager layoutManager) { + if (photoVideoChangeColumnsAnimation || jumpToRunnable != null) { + return; + } + long currentTime = System.currentTimeMillis(); + if ((recyclerView.getFastScroll() != null && recyclerView.getFastScroll().isPressed()) && (currentTime - mediaPage.lastCheckScrollTime) < 300) { + return; + } + mediaPage.lastCheckScrollTime = currentTime; if (searching && searchWas || mediaPage.selectedType == 7) { return; } int firstVisibleItem = layoutManager.findFirstVisibleItemPosition(); int visibleItemCount = firstVisibleItem == RecyclerView.NO_POSITION ? 0 : Math.abs(layoutManager.findLastVisibleItemPosition() - firstVisibleItem) + 1; int totalItemCount = recyclerView.getAdapter().getItemCount(); + if (mediaPage.selectedType == 0 || mediaPage.selectedType == 1 || mediaPage.selectedType == 2 || mediaPage.selectedType == 4) { + int type = mediaPage.selectedType; + totalItemCount = sharedMediaData[type].getStartOffset() + sharedMediaData[type].messages.size(); + if (sharedMediaData[type].fastScrollDataLoaded && sharedMediaData[type].fastScrollPeriods.size() > 2 && mediaPage.selectedType == 0 && sharedMediaData[type].messages.size() != 0) { + int columnsCount = 1; + if (type == 0) { + columnsCount = mediaColumnsCount; + } + int jumpToTreshold = (int) ((recyclerView.getMeasuredHeight() / ((float) (recyclerView.getMeasuredWidth() / (float) columnsCount))) * columnsCount * 1.5f); + if (jumpToTreshold < 100) { + jumpToTreshold = 100; + } + if (jumpToTreshold < sharedMediaData[type].fastScrollPeriods.get(1).startOffset) { + jumpToTreshold = sharedMediaData[type].fastScrollPeriods.get(1).startOffset; + } + if ((firstVisibleItem > totalItemCount && firstVisibleItem - totalItemCount > jumpToTreshold) || ((firstVisibleItem + visibleItemCount) < sharedMediaData[type].startOffset && sharedMediaData[0].startOffset - (firstVisibleItem + visibleItemCount) > jumpToTreshold)) { + AndroidUtilities.runOnUIThread(jumpToRunnable = () -> { + findPeriodAndJumpToDate(type, recyclerView, false); + jumpToRunnable = null; + }); + return; + } + } + } if (mediaPage.selectedType == 7) { @@ -1510,10 +2720,16 @@ private void checkLoadMoreScroll(MediaPage mediaPage, RecyclerView recyclerView, } else { threshold = 6; } - if (firstVisibleItem + visibleItemCount > totalItemCount - threshold && !sharedMediaData[mediaPage.selectedType].loading) { + + if ((firstVisibleItem + visibleItemCount > totalItemCount - threshold || sharedMediaData[mediaPage.selectedType].loadingAfterFastScroll) && !sharedMediaData[mediaPage.selectedType].loading) { int type; if (mediaPage.selectedType == 0) { - type = MediaDataController.MEDIA_PHOTOVIDEO; + type = MEDIA_PHOTOVIDEO; + if (sharedMediaData[0].filterType == FILTER_PHOTOS_ONLY) { + type = MediaDataController.MEDIA_PHOTOS_ONLY; + } else if (sharedMediaData[0].filterType == FILTER_VIDEOS_ONLY) { + type = MediaDataController.MEDIA_VIDEOS_ONLY; + } } else if (mediaPage.selectedType == 1) { type = MediaDataController.MEDIA_FILE; } else if (mediaPage.selectedType == 2) { @@ -1527,12 +2743,20 @@ private void checkLoadMoreScroll(MediaPage mediaPage, RecyclerView recyclerView, } if (!sharedMediaData[mediaPage.selectedType].endReached[0]) { sharedMediaData[mediaPage.selectedType].loading = true; - profileActivity.getMediaDataController().loadMedia(dialog_id, 50, sharedMediaData[mediaPage.selectedType].max_id[0], type, 1, profileActivity.getClassGuid()); + profileActivity.getMediaDataController().loadMedia(dialog_id, 50, sharedMediaData[mediaPage.selectedType].max_id[0], 0, type, 1, profileActivity.getClassGuid(), sharedMediaData[mediaPage.selectedType].requestIndex); } else if (mergeDialogId != 0 && !sharedMediaData[mediaPage.selectedType].endReached[1]) { sharedMediaData[mediaPage.selectedType].loading = true; - profileActivity.getMediaDataController().loadMedia(mergeDialogId, 50, sharedMediaData[mediaPage.selectedType].max_id[1], type, 1, profileActivity.getClassGuid()); + profileActivity.getMediaDataController().loadMedia(mergeDialogId, 50, sharedMediaData[mediaPage.selectedType].max_id[1], 0, type, 1, profileActivity.getClassGuid(), sharedMediaData[mediaPage.selectedType].requestIndex); } } + + int startOffset = sharedMediaData[mediaPage.selectedType].startOffset; + if (mediaPage.selectedType == 0) { + startOffset = photoVideoAdapter.getPositionForIndex(0); + } + if (firstVisibleItem - startOffset < threshold + 1 && !sharedMediaData[mediaPage.selectedType].loading && !sharedMediaData[mediaPage.selectedType].startReached && !sharedMediaData[mediaPage.selectedType].loadingAfterFastScroll) { + loadFromStart(mediaPage.selectedType); + } if (mediaPages[0].listView == recyclerView && (mediaPages[0].selectedType == 0 || mediaPages[0].selectedType == 5) && firstVisibleItem != RecyclerView.NO_POSITION) { RecyclerListView.ViewHolder holder = recyclerView.findViewHolderForAdapterPosition(firstVisibleItem); if (holder != null && holder.getItemViewType() == 0) { @@ -1551,17 +2775,45 @@ private void checkLoadMoreScroll(MediaPage mediaPage, RecyclerView recyclerView, } } + private void loadFromStart(int selectedType) { + int type; + if (selectedType == 0) { + type = MEDIA_PHOTOVIDEO; + if (sharedMediaData[0].filterType == FILTER_PHOTOS_ONLY) { + type = MediaDataController.MEDIA_PHOTOS_ONLY; + } else if (sharedMediaData[0].filterType == FILTER_VIDEOS_ONLY) { + type = MediaDataController.MEDIA_VIDEOS_ONLY; + } + } else if (selectedType == 1) { + type = MediaDataController.MEDIA_FILE; + } else if (selectedType == 2) { + type = MediaDataController.MEDIA_AUDIO; + } else if (selectedType == 4) { + type = MediaDataController.MEDIA_MUSIC; + } else if (selectedType == 5) { + type = MediaDataController.MEDIA_GIF; + } else { + type = MediaDataController.MEDIA_URL; + } + sharedMediaData[selectedType].loading = true; + profileActivity.getMediaDataController().loadMedia(dialog_id, 50, 0, sharedMediaData[selectedType].min_id, type, 1, profileActivity.getClassGuid(), sharedMediaData[selectedType].requestIndex); + } + public ActionBarMenuItem getSearchItem() { return searchItem; } public boolean isSearchItemVisible() { if (mediaPages[0].selectedType == 7) { - return profileActivity.canSearchMembers(); + return delegate.canSearchMembers(); } return mediaPages[0].selectedType != 0 && mediaPages[0].selectedType != 2 && mediaPages[0].selectedType != 5 && mediaPages[0].selectedType != 6; } + public boolean isCalendarItemVisible() { + return mediaPages[0].selectedType == 0; + } + public int getSelectedTab() { return scrollSlidingTextTabStrip.getCurrentTabId(); } @@ -1627,6 +2879,131 @@ public void setNewMediaCounts(int[] mediaCounts) { scrollSlidingTextTabStrip.resetTab(); } checkCurrentTabValid(); + if (hasMedia[0] >= 0) { + loadFastScrollData(false); + } + } + + private void loadFastScrollData(boolean force) { + for (int k = 0; k < supportedFastScrollTypes.length; k++) { + int type = supportedFastScrollTypes[k]; + if ((sharedMediaData[type].fastScrollDataLoaded && !force) || DialogObject.isEncryptedDialog(dialog_id)) { + return; + } + sharedMediaData[type].fastScrollDataLoaded = false; + TLRPC.TL_messages_getSearchResultsPositions req = new TLRPC.TL_messages_getSearchResultsPositions(); + if (type == 0) { + if (sharedMediaData[type].filterType == FILTER_PHOTOS_ONLY) { + req.filter = new TLRPC.TL_inputMessagesFilterPhotos(); + } else if (sharedMediaData[type].filterType == FILTER_VIDEOS_ONLY) { + req.filter = new TLRPC.TL_inputMessagesFilterVideo(); + } else { + req.filter = new TLRPC.TL_inputMessagesFilterPhotoVideo(); + } + } else if (type == MediaDataController.MEDIA_FILE) { + req.filter = new TLRPC.TL_inputMessagesFilterDocument(); + } else if (type == MediaDataController.MEDIA_AUDIO) { + req.filter = new TLRPC.TL_inputMessagesFilterRoundVoice(); + } else { + req.filter = new TLRPC.TL_inputMessagesFilterMusic(); + } + req.limit = 100; + req.peer = MessagesController.getInstance(profileActivity.getCurrentAccount()).getInputPeer(dialog_id); + int reqIndex = sharedMediaData[type].requestIndex; + int reqId = ConnectionsManager.getInstance(profileActivity.getCurrentAccount()).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (error != null) { + return; + } + if (reqIndex != sharedMediaData[type].requestIndex) { + return; + } + TLRPC.TL_messages_searchResultsPositions res = (TLRPC.TL_messages_searchResultsPositions) response; + sharedMediaData[type].fastScrollPeriods.clear(); + for (int i = 0, n = res.positions.size(); i < n; i++) { + TLRPC.TL_searchResultPosition serverPeriod = res.positions.get(i); + if (serverPeriod.date != 0) { + Period period = new Period(serverPeriod); + sharedMediaData[type].fastScrollPeriods.add(period); + } + } + Collections.sort(sharedMediaData[type].fastScrollPeriods, (period, period2) -> period2.date - period.date); + sharedMediaData[type].setTotalCount(res.count); + sharedMediaData[type].fastScrollDataLoaded = true; + if (!sharedMediaData[type].fastScrollPeriods.isEmpty()) { + for (int i = 0; i < mediaPages.length; i++) { + if (mediaPages[i].selectedType == type) { + mediaPages[i].listView.setFastScrollVisible(true); + mediaPages[i].listView.getFastScroll().setAlpha(0); + mediaPages[i].listView.getFastScroll().animate().alpha(1f).setDuration(100).start(); + mediaPages[i].listView.checkSection(true); + } + } + } + updatePhotosAdapter(); + })); + ConnectionsManager.getInstance(profileActivity.getCurrentAccount()).bindRequestToGuid(reqId, profileActivity.getClassGuid()); + } + } + + private void updatePhotosAdapter() { +// MediaPage mediaPage = getMediaPage(0); +// if (mediaPage != null) { +// for (int i = 0; i < mediaPage.listView.getChildCount(); i++) { +// View child = mediaPage.listView.getChildAt(i); +// if (child instanceof SharedPhotoVideoCell2) { +// ((SharedPhotoVideoCell2) child).moveImageToFront(); +// } +// } +// if (mediaPage.animationSupportingListView.getVisibility() == View.VISIBLE) { +// for (int i = 0; i < mediaPage.animationSupportingListView.getChildCount(); i++) { +// View child = mediaPage.animationSupportingListView.getChildAt(i); +// if (child instanceof SharedPhotoVideoCell2) { +// ((SharedPhotoVideoCell2) child).moveImageToFront(); +// } +// } +// } +// } + photoVideoAdapter.notifyDataSetChanged(); + } + + + private static void showFastScrollHint(MediaPage mediaPage, SharedMediaData[] sharedMediaData, boolean show) { + if (show) { + if (SharedConfig.fastScrollHintCount <= 0 || mediaPage.fastScrollHintView != null || mediaPage.fastScrollHinWasShown || mediaPage.listView.getFastScroll() == null || !mediaPage.listView.getFastScroll().isVisible || mediaPage.listView.getFastScroll().getVisibility() != View.VISIBLE || sharedMediaData[0].totalCount < 50) { + return; + } + SharedConfig.setFastScrollHintCount(SharedConfig.fastScrollHintCount - 1); + mediaPage.fastScrollHinWasShown = true; + SharedMediaFastScrollTooltip tooltip = new SharedMediaFastScrollTooltip(mediaPage.getContext()); + mediaPage.fastScrollHintView = tooltip; + mediaPage.addView(mediaPage.fastScrollHintView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + mediaPage.fastScrollHintView.setAlpha(0); + mediaPage.fastScrollHintView.setScaleX(0.8f); + mediaPage.fastScrollHintView.setScaleY(0.8f); + mediaPage.fastScrollHintView.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(150).start(); + mediaPage.invalidate(); + + AndroidUtilities.runOnUIThread(mediaPage.fastScrollHideHintRunnable = () -> { + mediaPage.fastScrollHintView = null; + mediaPage.fastScrollHideHintRunnable = null; + tooltip.animate().alpha(0f).scaleX(0.5f).scaleY(0.5f).setDuration(220).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (tooltip.getParent() != null) { + ((ViewGroup) tooltip.getParent()).removeView(tooltip); + } + } + }).start(); + }, 4000); + } else { + if (mediaPage.fastScrollHintView == null || mediaPage.fastScrollHideHintRunnable == null) { + return; + } + AndroidUtilities.cancelRunOnUIThread(mediaPage.fastScrollHideHintRunnable); + mediaPage.fastScrollHideHintRunnable.run(); + mediaPage.fastScrollHideHintRunnable = null; + mediaPage.fastScrollHintView = null; + } } public void setCommonGroupsCount(int count) { @@ -1682,7 +3059,7 @@ public void onActionBarItemClick(int id) { if (message != null) { profileActivity.getSendMessagesHelper().sendMessage(message.toString(), did, null, null, null, true, null, null, null, true, 0, null); } - profileActivity.getSendMessagesHelper().sendMessage(fmessages, did, false,false, true, 0); + profileActivity.getSendMessagesHelper().sendMessage(fmessages, did, false, false, true, 0); } fragment1.finishFragment(); } else { @@ -1754,6 +3131,7 @@ private boolean prepareForMoving(MotionEvent ev, boolean forward) { searchItem.setVisibility(INVISIBLE); searchItem.setAlpha(0.0f); } + getParent().requestDisallowInterceptTouchEvent(true); hideFloatingDateView(true); maybeStartTracking = false; @@ -1795,7 +3173,7 @@ public void setPadding(int left, int top, int right, int bottom) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSize = MeasureSpec.getSize(widthMeasureSpec); - int heightSize = profileActivity.getListView().getHeight(); + int heightSize = delegate.getListView() != null ? delegate.getListView().getHeight() : 0; if (heightSize == 0) { heightSize = MeasureSpec.getSize(heightMeasureSpec); } @@ -1810,7 +3188,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } if (child instanceof MediaPage) { measureChildWithMargins(child, widthMeasureSpec, 0, MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY), 0); - ((MediaPage) child).listView.setPadding(0, 0 ,0, topPadding); + ((MediaPage) child).listView.setPadding(0, 0, 0, topPadding); } else { measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); } @@ -1858,7 +3236,7 @@ public RecyclerListView getCurrentListView() { @Override public boolean onTouchEvent(MotionEvent ev) { - if (profileActivity.getParentLayout() != null && !profileActivity.getParentLayout().checkTransitionAnimation() && !checkTabsAnimationInProgress()) { + if (profileActivity.getParentLayout() != null && !profileActivity.getParentLayout().checkTransitionAnimation() && !checkTabsAnimationInProgress() && !isInPinchToZoomTouchMode) { if (ev != null) { if (velocityTracker == null) { velocityTracker = VelocityTracker.obtain(); @@ -1902,6 +3280,16 @@ public boolean onTouchEvent(MotionEvent ev) { } else if (searchItemState == 1) { searchItem.setAlpha(scrollProgress); } + + float photoVideoOptionsAlpha = 0f; + if (mediaPages[1] != null && mediaPages[1].selectedType == 0) { + photoVideoOptionsAlpha = scrollProgress; + } + if (mediaPages[0].selectedType == 0) { + photoVideoOptionsAlpha = 1f - scrollProgress; + } + photoVideoOptionsItem.setAlpha(photoVideoOptionsAlpha); + photoVideoOptionsItem.setVisibility((photoVideoOptionsAlpha == 0 || !canShowSearchItem()) ? INVISIBLE : View.VISIBLE); } else { searchItem.setAlpha(0.0f); } @@ -2055,6 +3443,7 @@ public void setVisibleHeight(int height) { } private AnimatorSet actionModeAnimation; + private void showActionMode(boolean show) { if (isActionModeShowed == show) { return; @@ -2094,10 +3483,20 @@ public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.mediaDidLoad) { long uid = (Long) args[0]; int guid = (Integer) args[3]; + int requestIndex = (Integer) args[7]; int type = (Integer) args[4]; - if (guid == profileActivity.getClassGuid()) { - sharedMediaData[type].totalCount = (Integer) args[1]; + boolean fromStart = (boolean) args[6]; + + if (type == 6 || type == 7) { + type = 0; + } + + if (guid == profileActivity.getClassGuid() && requestIndex == sharedMediaData[type].requestIndex) { + if (type != 0 && type != 1 && type != 2 && type != 4) { + sharedMediaData[type].totalCount = (Integer) args[1]; + } ArrayList arr = (ArrayList) args[2]; + boolean enc = DialogObject.isEncryptedDialog(dialog_id); int loadIndex = uid == dialog_id ? 0 : 1; @@ -2116,6 +3515,7 @@ public void didReceivedNotification(int id, int account, Object... args) { adapter = gifAdapter; } int oldItemCount; + int oldMessagesCount = sharedMediaData[type].messages.size(); if (adapter != null) { oldItemCount = adapter.getItemCount(); if (adapter instanceof RecyclerListView.SectionsAdapter) { @@ -2126,14 +3526,47 @@ public void didReceivedNotification(int id, int account, Object... args) { oldItemCount = 0; } sharedMediaData[type].loading = false; - for (int a = 0; a < arr.size(); a++) { - MessageObject message = arr.get(a); - sharedMediaData[type].addMessage(message, loadIndex, false, enc); + + SparseBooleanArray addedMesages = new SparseBooleanArray(); + + if (fromStart) { + for (int a = arr.size() - 1; a >= 0; a--) { + MessageObject message = arr.get(a); + boolean added = sharedMediaData[type].addMessage(message, loadIndex, true, enc); + if (added) { + addedMesages.put(message.getId(), true); + sharedMediaData[type].startOffset--; + if (sharedMediaData[type].startOffset < 0) { + sharedMediaData[type].startOffset = 0; + } + } + } + sharedMediaData[type].startReached = (Boolean) args[5]; + if (sharedMediaData[type].startReached) { + sharedMediaData[type].startOffset = 0; + } + } else { + for (int a = 0; a < arr.size(); a++) { + MessageObject message = arr.get(a); + if (sharedMediaData[type].addMessage(message, loadIndex, false, enc)) { + addedMesages.put(message.getId(), true); + sharedMediaData[type].endLoadingStubs--; + if (sharedMediaData[type].endLoadingStubs < 0) { + sharedMediaData[type].endLoadingStubs = 0; + } + } + } + if (sharedMediaData[type].loadingAfterFastScroll && sharedMediaData[type].messages.size() > 0) { + sharedMediaData[type].min_id = sharedMediaData[type].messages.get(0).getId(); + } + sharedMediaData[type].endReached[loadIndex] = (Boolean) args[5]; + if (sharedMediaData[type].endReached[loadIndex]) { + sharedMediaData[type].totalCount = sharedMediaData[type].messages.size() + sharedMediaData[type].startOffset; + } } - sharedMediaData[type].endReached[loadIndex] = (Boolean) args[5]; - if (loadIndex == 0 && sharedMediaData[type].endReached[loadIndex] && mergeDialogId != 0) { + if (!fromStart && loadIndex == 0 && sharedMediaData[type].endReached[loadIndex] && mergeDialogId != 0) { sharedMediaData[type].loading = true; - profileActivity.getMediaDataController().loadMedia(mergeDialogId, 50, sharedMediaData[type].max_id[1], type, 1, profileActivity.getClassGuid()); + profileActivity.getMediaDataController().loadMedia(mergeDialogId, 50, sharedMediaData[type].max_id[1], 0, type, 1, profileActivity.getClassGuid(), sharedMediaData[type].requestIndex); } if (adapter != null) { RecyclerListView listView = null; @@ -2144,20 +3577,46 @@ public void didReceivedNotification(int id, int account, Object... args) { } } int newItemCount = adapter.getItemCount(); - if (sharedMediaData[type].messages.isEmpty() && !sharedMediaData[type].loading) { + if (adapter == photoVideoAdapter) { + if (photoVideoAdapter.getItemCount() == oldItemCount) { + AndroidUtilities.updateVisibleRows(listView); + } else { + updatePhotosAdapter(); + } + } else { adapter.notifyDataSetChanged(); + } + if (sharedMediaData[type].messages.isEmpty() && !sharedMediaData[type].loading) { if (listView != null) { - animateItemsEnter(listView, oldItemCount); + animateItemsEnter(listView, oldItemCount, addedMesages); } } else { - adapter.notifyDataSetChanged(); - if (listView != null && newItemCount >= oldItemCount) { - animateItemsEnter(listView, oldItemCount); + if (listView != null && (adapter == photoVideoAdapter || newItemCount >= oldItemCount)) { + animateItemsEnter(listView, oldItemCount, addedMesages); + } + } + if (listView != null && !sharedMediaData[type].loadingAfterFastScroll) { + if (oldMessagesCount == 0) { + for (int k = 0; k < 2; k++) { + if (mediaPages[k].selectedType == 0) { + int position = photoVideoAdapter.getPositionForIndex(0); + ((LinearLayoutManager) listView.getLayoutManager()).scrollToPositionWithOffset(position, 0); + } + } + } else { + saveScrollPosition(); } } } + if (sharedMediaData[type].loadingAfterFastScroll) { + if (sharedMediaData[type].messages.size() == 0) { + loadFromStart(type); + } else { + sharedMediaData[type].loadingAfterFastScroll = false; + } + } scrolling = true; - } else if (sharedMediaPreloader != null && sharedMediaData[type].messages.isEmpty()) { + } else if (sharedMediaPreloader != null && sharedMediaData[type].messages.isEmpty() && !sharedMediaData[type].loadingAfterFastScroll) { if (fillMediaData(type)) { RecyclerListView.Adapter adapter = null; if (type == 0) { @@ -2208,9 +3667,11 @@ public void didReceivedNotification(int id, int account, Object... args) { } ArrayList markAsDeletedMessages = (ArrayList) args[0]; boolean updated = false; + int type = -1; for (int a = 0, N = markAsDeletedMessages.size(); a < N; a++) { for (int b = 0; b < sharedMediaData.length; b++) { if (sharedMediaData[b].deleteMessage(markAsDeletedMessages.get(a), loadIndex) != null) { + type = b; updated = true; } } @@ -2218,7 +3679,7 @@ public void didReceivedNotification(int id, int account, Object... args) { if (updated) { scrolling = true; if (photoVideoAdapter != null) { - photoVideoAdapter.notifyDataSetChanged(); + updatePhotosAdapter(); } if (documentsAdapter != null) { documentsAdapter.notifyDataSetChanged(); @@ -2235,7 +3696,12 @@ public void didReceivedNotification(int id, int account, Object... args) { if (gifAdapter != null) { gifAdapter.notifyDataSetChanged(); } + + if (type == 0 || type == 1 || type == 2 || type == 4) { + loadFastScrollData(true); + } } + MediaPage mediaPage = getMediaPage(type); } else if (id == NotificationCenter.didReceiveNewMessages) { boolean scheduled = (Boolean) args[2]; if (scheduled) { @@ -2255,7 +3721,7 @@ public void didReceivedNotification(int id, int account, Object... args) { if (type == -1) { return; } - if (sharedMediaData[type].addMessage(obj, obj.getDialogId() == dialog_id ? 0 : 1, true, enc)) { + if (sharedMediaData[type].startReached && sharedMediaData[type].addMessage(obj, obj.getDialogId() == dialog_id ? 0 : 1, true, enc)) { updated = true; hasMedia[type] = 1; } @@ -2279,7 +3745,7 @@ public void didReceivedNotification(int id, int account, Object... args) { } if (adapter != null) { int count = adapter.getItemCount(); - photoVideoAdapter.notifyDataSetChanged(); + updatePhotosAdapter(); documentsAdapter.notifyDataSetChanged(); voiceAdapter.notifyDataSetChanged(); linksAdapter.notifyDataSetChanged(); @@ -2337,7 +3803,55 @@ public void didReceivedNotification(int id, int account, Object... args) { } } - private void animateItemsEnter(final RecyclerListView finalListView, int oldItemCount) { + private void saveScrollPosition() { + for (int k = 0; k < mediaPages.length; k++) { + RecyclerListView listView = mediaPages[k].listView; + if (listView != null) { + int messageId = 0; + int offset = 0; + for (int i = 0; i < listView.getChildCount(); i++) { + View child = listView.getChildAt(i); + if (child instanceof SharedPhotoVideoCell2) { + SharedPhotoVideoCell2 cell = (SharedPhotoVideoCell2) child; + messageId = cell.getMessageId(); + offset = cell.getTop(); + } + if (child instanceof SharedDocumentCell) { + SharedDocumentCell cell = (SharedDocumentCell) child; + messageId = cell.getMessage().getId(); + } + if (child instanceof SharedAudioCell) { + SharedAudioCell cell = (SharedAudioCell) child; + messageId = cell.getMessage().getId(); + } + if (messageId != 0) { + break; + } + } + if (messageId != 0) { + int index = -1; + for (int i = 0; i < sharedMediaData[mediaPages[k].selectedType].messages.size(); i++) { + if (messageId == sharedMediaData[mediaPages[k].selectedType].messages.get(i).getId()) { + index = i; + break; + } + } + + int position = sharedMediaData[mediaPages[k].selectedType].startOffset + index; + if (index >= 0) { + ((LinearLayoutManager) listView.getLayoutManager()).scrollToPositionWithOffset(position, offset); + if (photoVideoChangeColumnsAnimation) { + mediaPages[k].animationSupportingLayoutManager.scrollToPositionWithOffset(position, offset); + } + } + } + } + } + } + + SparseArray messageAlphaEnter = new SparseArray<>(); + + private void animateItemsEnter(final RecyclerListView finalListView, int oldItemCount, SparseBooleanArray addedMesages) { int n = finalListView.getChildCount(); View progressView = null; for (int i = 0; i < n; i++) { @@ -2354,39 +3868,71 @@ private void animateItemsEnter(final RecyclerListView finalListView, int oldItem @Override public boolean onPreDraw() { getViewTreeObserver().removeOnPreDrawListener(this); - int n = finalListView.getChildCount(); - AnimatorSet animatorSet = new AnimatorSet(); - for (int i = 0; i < n; i++) { - View child = finalListView.getChildAt(i); - if (child != finalProgressView && finalListView.getChildAdapterPosition(child) >= oldItemCount - 1) { - child.setAlpha(0); - int s = Math.min(finalListView.getMeasuredHeight(), Math.max(0, child.getTop())); - int delay = (int) ((s / (float) finalListView.getMeasuredHeight()) * 100); - ObjectAnimator a = ObjectAnimator.ofFloat(child, View.ALPHA, 0, 1f); - a.setStartDelay(delay); - a.setDuration(200); - animatorSet.playTogether(a); - } - if (finalProgressView != null && finalProgressView.getParent() == null) { - finalListView.addView(finalProgressView); - RecyclerView.LayoutManager layoutManager = finalListView.getLayoutManager(); - if (layoutManager != null) { - layoutManager.ignoreView(finalProgressView); - Animator animator = ObjectAnimator.ofFloat(finalProgressView, ALPHA, finalProgressView.getAlpha(), 0); - animator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - finalProgressView.setAlpha(1f); - layoutManager.stopIgnoringView(finalProgressView); - finalListView.removeView(finalProgressView); - } - }); - animator.start(); + RecyclerView.Adapter adapter = finalListView.getAdapter(); + if (adapter == photoVideoAdapter || adapter == documentsAdapter || adapter == audioAdapter || adapter == voiceAdapter) { + if (addedMesages != null) { + int n = finalListView.getChildCount(); + for (int i = 0; i < n; i++) { + View child = finalListView.getChildAt(i); + int messageId = getMessageId(child); + if (messageId != 0 && addedMesages.get(messageId, false)) { + messageAlphaEnter.put(messageId, 0f); + ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f); + valueAnimator.addUpdateListener(valueAnimator1 -> { + messageAlphaEnter.put(messageId, (Float) valueAnimator1.getAnimatedValue()); + finalListView.invalidate(); + }); + valueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + messageAlphaEnter.remove(messageId); + finalListView.invalidate(); + } + }); + int s = Math.min(finalListView.getMeasuredHeight(), Math.max(0, child.getTop())); + int delay = (int) ((s / (float) finalListView.getMeasuredHeight()) * 100); + valueAnimator.setStartDelay(delay); + valueAnimator.setDuration(250); + valueAnimator.start(); + } } } + } else { + int n = finalListView.getChildCount(); + AnimatorSet animatorSet = new AnimatorSet(); + for (int i = 0; i < n; i++) { + View child = finalListView.getChildAt(i); + if (child != finalProgressView && finalListView.getChildAdapterPosition(child) >= oldItemCount - 1) { + child.setAlpha(0); + int s = Math.min(finalListView.getMeasuredHeight(), Math.max(0, child.getTop())); + int delay = (int) ((s / (float) finalListView.getMeasuredHeight()) * 100); + ObjectAnimator a = ObjectAnimator.ofFloat(child, View.ALPHA, 0, 1f); + a.setStartDelay(delay); + a.setDuration(200); + animatorSet.playTogether(a); + } + if (finalProgressView != null && finalProgressView.getParent() == null) { + finalListView.addView(finalProgressView); + RecyclerView.LayoutManager layoutManager = finalListView.getLayoutManager(); + if (layoutManager != null) { + layoutManager.ignoreView(finalProgressView); + Animator animator = ObjectAnimator.ofFloat(finalProgressView, ALPHA, finalProgressView.getAlpha(), 0); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + finalProgressView.setAlpha(1f); + layoutManager.stopIgnoringView(finalProgressView); + finalListView.removeView(finalProgressView); + } + }); + animator.start(); + } + } + } + animatorSet.start(); } - animatorSet.start(); + return true; } }); @@ -2395,7 +3941,7 @@ public void onAnimationEnd(Animator animation) { public void onResume() { scrolling = true; if (photoVideoAdapter != null) { - photoVideoAdapter.notifyDataSetChanged(); + updatePhotosAdapter(); } if (documentsAdapter != null) { documentsAdapter.notifyDataSetChanged(); @@ -2450,7 +3996,7 @@ public void setChatUsers(ArrayList sortedUsers, TLRPC.ChatFull chatInfo public void updateAdapters() { if (photoVideoAdapter != null) { - photoVideoAdapter.notifyDataSetChanged(); + updatePhotosAdapter(); } if (documentsAdapter != null) { documentsAdapter.notifyDataSetChanged(); @@ -2476,10 +4022,8 @@ private void updateRowsSelection() { View child = mediaPages[i].listView.getChildAt(a); if (child instanceof SharedDocumentCell) { ((SharedDocumentCell) child).setChecked(false, true); - } else if (child instanceof SharedPhotoVideoCell) { - for (int b = 0; b < 6; b++) { - ((SharedPhotoVideoCell) child).setChecked(b, false, true); - } + } else if (child instanceof SharedPhotoVideoCell2) { + ((SharedPhotoVideoCell2) child).setChecked(false, true); } else if (child instanceof SharedLinkCell) { ((SharedLinkCell) child).setChecked(false, true); } else if (child instanceof SharedAudioCell) { @@ -2499,7 +4043,7 @@ private void updateTabs(boolean animated) { if (scrollSlidingTextTabStrip == null) { return; } - if (!profileActivity.isFragmentOpened) { + if (!delegate.isFragmentOpened()) { animated = false; } int changed = 0; @@ -2550,6 +4094,7 @@ public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startV set.setInterpolator(CubicBezierInterpolator.DEFAULT); return set; } + @Override public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) { AnimatorSet set = new AnimatorSet(); @@ -2656,10 +4201,15 @@ private void switchToCurrentSelectedMode(boolean animated) { mediaPages[a].listView.stopScroll(); } int a = animated ? 1 : 0; + FrameLayout.LayoutParams layoutParams = (LayoutParams) mediaPages[a].getLayoutParams(); + // layoutParams.leftMargin = layoutParams.rightMargin = 0; + boolean fastScrollVisible = false; + int spanCount = 100; RecyclerView.Adapter currentAdapter = mediaPages[a].listView.getAdapter(); + RecyclerView.RecycledViewPool viewPool = null; if (searching && searchWas) { if (animated) { - if (mediaPages[a].selectedType == 0 || mediaPages[a].selectedType == 2 || mediaPages[a].selectedType == 5 || mediaPages[a].selectedType == 6 || mediaPages[a].selectedType == 7 && !profileActivity.canSearchMembers()) { + if (mediaPages[a].selectedType == 0 || mediaPages[a].selectedType == 2 || mediaPages[a].selectedType == 5 || mediaPages[a].selectedType == 6 || mediaPages[a].selectedType == 7 && !delegate.canSearchMembers()) { searching = false; searchWas = false; switchToCurrentSelectedMode(true); @@ -2731,18 +4281,34 @@ private void switchToCurrentSelectedMode(boolean animated) { } } else { mediaPages[a].listView.setPinnedHeaderShadowDrawable(null); + if (mediaPages[a].selectedType == 0) { if (currentAdapter != photoVideoAdapter) { recycleAdapter(currentAdapter); mediaPages[a].listView.setAdapter(photoVideoAdapter); } + layoutParams.leftMargin = layoutParams.rightMargin = -AndroidUtilities.dp(1); + if (sharedMediaData[0].fastScrollDataLoaded && !sharedMediaData[0].fastScrollPeriods.isEmpty()) { + fastScrollVisible = true; + } + spanCount = mediaColumnsCount; mediaPages[a].listView.setPinnedHeaderShadowDrawable(pinnedHeaderShadowDrawable); + if (sharedMediaData[0].recycledViewPool == null) { + sharedMediaData[0].recycledViewPool = new RecyclerView.RecycledViewPool(); + } + viewPool = sharedMediaData[0].recycledViewPool; } else if (mediaPages[a].selectedType == 1) { + if (sharedMediaData[1].fastScrollDataLoaded && !sharedMediaData[1].fastScrollPeriods.isEmpty()) { + fastScrollVisible = true; + } if (currentAdapter != documentsAdapter) { recycleAdapter(currentAdapter); mediaPages[a].listView.setAdapter(documentsAdapter); } } else if (mediaPages[a].selectedType == 2) { + if (sharedMediaData[2].fastScrollDataLoaded && !sharedMediaData[2].fastScrollPeriods.isEmpty()) { + fastScrollVisible = true; + } if (currentAdapter != voiceAdapter) { recycleAdapter(currentAdapter); mediaPages[a].listView.setAdapter(voiceAdapter); @@ -2753,6 +4319,9 @@ private void switchToCurrentSelectedMode(boolean animated) { mediaPages[a].listView.setAdapter(linksAdapter); } } else if (mediaPages[a].selectedType == 4) { + if (sharedMediaData[4].fastScrollDataLoaded && !sharedMediaData[4].fastScrollPeriods.isEmpty()) { + fastScrollVisible = true; + } if (currentAdapter != audioAdapter) { recycleAdapter(currentAdapter); mediaPages[a].listView.setAdapter(audioAdapter); @@ -2773,7 +4342,7 @@ private void switchToCurrentSelectedMode(boolean animated) { mediaPages[a].listView.setAdapter(chatUsersAdapter); } } - if (mediaPages[a].selectedType == 0 || mediaPages[a].selectedType == 2 || mediaPages[a].selectedType == 5 || mediaPages[a].selectedType == 6 || mediaPages[a].selectedType == 7 && !profileActivity.canSearchMembers()) { + if (mediaPages[a].selectedType == 0 || mediaPages[a].selectedType == 2 || mediaPages[a].selectedType == 5 || mediaPages[a].selectedType == 6 || mediaPages[a].selectedType == 7 && !delegate.canSearchMembers()) { if (animated) { searchItemState = 2; } else { @@ -2814,11 +4383,24 @@ private void switchToCurrentSelectedMode(boolean animated) { if (!sharedMediaData[mediaPages[a].selectedType].loading && !sharedMediaData[mediaPages[a].selectedType].endReached[0] && sharedMediaData[mediaPages[a].selectedType].messages.isEmpty()) { sharedMediaData[mediaPages[a].selectedType].loading = true; documentsAdapter.notifyDataSetChanged(); - profileActivity.getMediaDataController().loadMedia(dialog_id, 50, 0, mediaPages[a].selectedType, 1, profileActivity.getClassGuid()); + int type = mediaPages[a].selectedType; + if (type == 0) { + if (sharedMediaData[0].filterType == FILTER_PHOTOS_ONLY) { + type = MediaDataController.MEDIA_PHOTOS_ONLY; + } else if (sharedMediaData[0].filterType == FILTER_VIDEOS_ONLY) { + type = MediaDataController.MEDIA_VIDEOS_ONLY; + } + } + profileActivity.getMediaDataController().loadMedia(dialog_id, 50, 0, 0, type, 1, profileActivity.getClassGuid(), sharedMediaData[mediaPages[a].selectedType].requestIndex); } } mediaPages[a].listView.setVisibility(View.VISIBLE); } + mediaPages[a].listView.setFastScrollVisible(fastScrollVisible); + mediaPages[a].layoutManager.setSpanCount(spanCount); + mediaPages[a].listView.setRecycledViewPool(viewPool); + mediaPages[a].animationSupportingListView.setRecycledViewPool(viewPool); + if (searchItemState == 2 && actionBar.isSearchFieldVisible()) { ignoreSearchCollapse = true; actionBar.closeSearchField(); @@ -2863,6 +4445,8 @@ private boolean onItemLongClick(MessageObject item, View view, int a) { ((SharedAudioCell) view).setChecked(true, true); } else if (view instanceof ContextLinkCell) { ((ContextLinkCell) view).setChecked(true, true); + } else if (view instanceof SharedPhotoVideoCell2) { + ((SharedPhotoVideoCell2) view).setChecked(true, true); } if (!isActionModeShowed) { showActionMode(true); @@ -2871,7 +4455,7 @@ private boolean onItemLongClick(MessageObject item, View view, int a) { } private void onItemClick(int index, View view, MessageObject message, int a, int selectedMode) { - if (message == null) { + if (message == null || photoVideoChangeColumnsAnimation) { return; } if (isActionModeShowed) { @@ -2910,11 +4494,16 @@ private void onItemClick(int index, View view, MessageObject message, int a, int ((SharedAudioCell) view).setChecked(selectedFiles[loadIndex].indexOfKey(message.getId()) >= 0, true); } else if (view instanceof ContextLinkCell) { ((ContextLinkCell) view).setChecked(selectedFiles[loadIndex].indexOfKey(message.getId()) >= 0, true); + } else if (view instanceof SharedPhotoVideoCell2) { + ((SharedPhotoVideoCell2) view).setChecked(selectedFiles[loadIndex].indexOfKey(message.getId()) >= 0, true); } } else { if (selectedMode == 0) { - PhotoViewer.getInstance().setParentActivity(profileActivity.getParentActivity()); - PhotoViewer.getInstance().openPhoto(sharedMediaData[selectedMode].messages, index, dialog_id, mergeDialogId, provider); + int i = index - sharedMediaData[selectedMode].startOffset; + if (i >= 0 && i < sharedMediaData[selectedMode].messages.size()) { + PhotoViewer.getInstance().setParentActivity(profileActivity.getParentActivity()); + PhotoViewer.getInstance().openPhoto(sharedMediaData[selectedMode].messages, i, dialog_id, mergeDialogId, provider); + } } else if (selectedMode == 2 || selectedMode == 4) { if (view instanceof SharedAudioCell) { ((SharedAudioCell) view).didPressedButton(); @@ -3017,18 +4606,8 @@ private void fixLayoutInternal(int num) { selectedMessagesCountTextView.setTextSize(20); } } - - if (AndroidUtilities.isTablet()) { - columnsCount = 3; - } else { - if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) { - columnsCount = 6; - } else { - columnsCount = 3; - } - } if (num == 0) { - photoVideoAdapter.notifyDataSetChanged(); + updatePhotosAdapter(); } } @@ -3204,15 +4783,17 @@ public String getLetter(int position) { } @Override - public int getPositionForScrollProgress(float progress) { - return 0; + public void getPositionForScrollProgress(RecyclerListView listView, float progress, int[] position) { + position[0] = 0; + position[1] = 0; } } - private class SharedDocumentsAdapter extends RecyclerListView.SectionsAdapter { + private class SharedDocumentsAdapter extends RecyclerListView.FastScrollAdapter { private Context mContext; private int currentType; + private boolean inFastScrollMode; public SharedDocumentsAdapter(Context context, int type) { mContext = context; @@ -3220,64 +4801,44 @@ public SharedDocumentsAdapter(Context context, int type) { } @Override - public boolean isEnabled(RecyclerView.ViewHolder holder, int section, int row) { - if (sharedMediaData[currentType].sections.size() == 0 && !sharedMediaData[currentType].loading) { - return false; - } - return section == 0 || row != 0; + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return true; } @Override - public int getSectionCount() { - if (sharedMediaData[currentType].sections.size() == 0 && !sharedMediaData[currentType].loading) { - return 1; + public int getItemCount() { + if (sharedMediaData[currentType].loadingAfterFastScroll) { + return sharedMediaData[currentType].totalCount; } - return sharedMediaData[currentType].sections.size() + ((!sharedMediaData[currentType].sections.isEmpty() && (!sharedMediaData[currentType].endReached[0] || !sharedMediaData[currentType].endReached[1])) ? 1 : 0); - } - - @Override - public Object getItem(int section, int position) { - return null; - } - - @Override - public int getCountForSection(int section) { - if (sharedMediaData[currentType].sections.size() == 0 && !sharedMediaData[currentType].loading) { + if (sharedMediaData[currentType].messages.size() == 0 && !sharedMediaData[currentType].loading) { return 1; } - if (section < sharedMediaData[currentType].sections.size()) { - return sharedMediaData[currentType].sectionArrays.get(sharedMediaData[currentType].sections.get(section)).size() + (section != 0 ? 1 : 0); - } - return 1; - } - - @Override - public View getSectionHeaderView(int section, View view) { - if (view == null) { - view = new GraySectionCell(mContext); - view.setBackgroundColor(Theme.getColor(Theme.key_graySection) & 0xf2ffffff); + if (sharedMediaData[currentType].messages.size() == 0 && (!sharedMediaData[currentType].endReached[0] || !sharedMediaData[currentType].endReached[1]) && sharedMediaData[currentType].startReached) { + return 0; } - if (section == 0) { - view.setAlpha(0.0f); - } else if (section < sharedMediaData[currentType].sections.size()) { - view.setAlpha(1.0f); - String name = sharedMediaData[currentType].sections.get(section); - ArrayList messageObjects = sharedMediaData[currentType].sectionArrays.get(name); - MessageObject messageObject = messageObjects.get(0); - ((GraySectionCell) view).setText(LocaleController.formatSectionDate(messageObject.messageOwner.date)); + if (sharedMediaData[currentType].totalCount == 0) { + int count = sharedMediaData[currentType].getStartOffset() + sharedMediaData[currentType].getMessages().size(); + if (count != 0 && (!sharedMediaData[currentType].endReached[0] || !sharedMediaData[currentType].endReached[1])) { + if (sharedMediaData[currentType].getEndLoadingStubs() != 0) { + count += sharedMediaData[currentType].getEndLoadingStubs(); + } else { + count++; + } + } + return count; + } else { + return sharedMediaData[currentType].totalCount; } - return view; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view; switch (viewType) { - case 0: - view = new GraySectionCell(mContext); - break; case 1: - view = new SharedDocumentCell(mContext); + SharedDocumentCell cell = new SharedDocumentCell(mContext); + cell.setGlobalGradientView(globalGradientView); + view = cell; break; case 2: FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext); @@ -3289,6 +4850,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType } flickerLoadingView.showDate(false); flickerLoadingView.setIsSingleCell(true); + flickerLoadingView.setGlobalGradientView(globalGradientView); break; case 4: View emptyStubView = createEmptyStubView(mContext, currentType, dialog_id); @@ -3318,6 +4880,8 @@ public boolean needPlayMessage(MessageObject messageObject) { } }; } + SharedAudioCell audioCell = (SharedAudioCell) view; + audioCell.setGlobalGradientView(globalGradientView); if (currentType == MediaDataController.MEDIA_MUSIC) { audioCache.add((SharedAudioCell) view); } @@ -3328,62 +4892,45 @@ public boolean needPlayMessage(MessageObject messageObject) { } @Override - public void onBindViewHolder(int section, int position, RecyclerView.ViewHolder holder) { - if (holder.getItemViewType() != 2 && holder.getItemViewType() != 4) { - String name = sharedMediaData[currentType].sections.get(section); - ArrayList messageObjects = sharedMediaData[currentType].sectionArrays.get(name); - switch (holder.getItemViewType()) { - case 0: { - MessageObject messageObject = messageObjects.get(0); - ((GraySectionCell) holder.itemView).setText(LocaleController.formatSectionDate(messageObject.messageOwner.date)); - break; - } - case 1: { - if (section != 0) { - position--; - } - SharedDocumentCell sharedDocumentCell = (SharedDocumentCell) holder.itemView; - MessageObject messageObject = messageObjects.get(position); - sharedDocumentCell.setDocument(messageObject, position != messageObjects.size() - 1 || section == sharedMediaData[currentType].sections.size() - 1 && sharedMediaData[currentType].loading); - if (isActionModeShowed) { - sharedDocumentCell.setChecked(selectedFiles[messageObject.getDialogId() == dialog_id ? 0 : 1].indexOfKey(messageObject.getId()) >= 0, !scrolling); - } else { - sharedDocumentCell.setChecked(false, !scrolling); - } - break; + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + ArrayList messageObjects = sharedMediaData[currentType].messages; + switch (holder.getItemViewType()) { + case 1: { + SharedDocumentCell sharedDocumentCell = (SharedDocumentCell) holder.itemView; + MessageObject messageObject = messageObjects.get(position - sharedMediaData[currentType].startOffset); + sharedDocumentCell.setDocument(messageObject, position != messageObjects.size() - 1); + if (isActionModeShowed) { + sharedDocumentCell.setChecked(selectedFiles[messageObject.getDialogId() == dialog_id ? 0 : 1].indexOfKey(messageObject.getId()) >= 0, !scrolling); + } else { + sharedDocumentCell.setChecked(false, !scrolling); } - case 3: { - if (section != 0) { - position--; - } - SharedAudioCell sharedAudioCell = (SharedAudioCell) holder.itemView; - MessageObject messageObject = messageObjects.get(position); - sharedAudioCell.setMessageObject(messageObject, position != messageObjects.size() - 1 || section == sharedMediaData[currentType].sections.size() - 1 && sharedMediaData[currentType].loading); - if (isActionModeShowed) { - sharedAudioCell.setChecked(selectedFiles[messageObject.getDialogId() == dialog_id ? 0 : 1].indexOfKey(messageObject.getId()) >= 0, !scrolling); - } else { - sharedAudioCell.setChecked(false, !scrolling); - } - break; + break; + } + case 3: { + SharedAudioCell sharedAudioCell = (SharedAudioCell) holder.itemView; + MessageObject messageObject = messageObjects.get(position - sharedMediaData[currentType].startOffset); + sharedAudioCell.setMessageObject(messageObject, position != messageObjects.size() - 1); + if (isActionModeShowed) { + sharedAudioCell.setChecked(selectedFiles[messageObject.getDialogId() == dialog_id ? 0 : 1].indexOfKey(messageObject.getId()) >= 0, !scrolling); + } else { + sharedAudioCell.setChecked(false, !scrolling); } + break; } } } + @Override - public int getItemViewType(int section, int position) { + public int getItemViewType(int position) { if (sharedMediaData[currentType].sections.size() == 0 && !sharedMediaData[currentType].loading) { return 4; } - if (section < sharedMediaData[currentType].sections.size()) { - if (section != 0 && position == 0) { - return 0; + if (position >= sharedMediaData[currentType].startOffset && position < sharedMediaData[currentType].startOffset + sharedMediaData[currentType].messages.size()) { + if (currentType == 2 || currentType == 4) { + return 3; } else { - if (currentType == 2 || currentType == 4) { - return 3; - } else { - return 1; - } + return 1; } } return 2; @@ -3391,12 +4938,62 @@ public int getItemViewType(int section, int position) { @Override public String getLetter(int position) { - return null; + if (sharedMediaData[currentType].fastScrollPeriods == null) { + return ""; + } + int index = position; + ArrayList periods = sharedMediaData[currentType].fastScrollPeriods; + if (!periods.isEmpty()) { + for (int i = 0; i < periods.size(); i++) { + if (index <= periods.get(i).startOffset) { + return periods.get(i).formatedDate; + } + } + return periods.get(periods.size() - 1).formatedDate; + } + return ""; } @Override - public int getPositionForScrollProgress(float progress) { - return 0; + public void getPositionForScrollProgress(RecyclerListView listView, float progress, int[] position) { + int viewHeight = listView.getChildAt(0).getMeasuredHeight(); + int totalHeight = (int) getTotalItemsCount() * viewHeight; + position[0] = (int) ((progress * (totalHeight - listView.getMeasuredHeight())) / viewHeight); + position[1] = (int) (progress * (totalHeight - listView.getMeasuredHeight())) % viewHeight; + } + + @Override + public void onStartFastScroll() { + inFastScrollMode = true; + MediaPage mediaPage = getMediaPage(currentType); + if (mediaPage != null) { + showFastScrollHint(mediaPage, null, false); + } + } + + @Override + public void onFinishFastScroll(RecyclerListView listView) { + if (inFastScrollMode) { + inFastScrollMode = false; + if (listView != null) { + int messageId = 0; + for (int i = 0; i < listView.getChildCount(); i++) { + View child = listView.getChildAt(i); + messageId = getMessageId(child); + if (messageId != 0) { + break; + } + } + if (messageId == 0) { + findPeriodAndJumpToDate(currentType, listView, true); + } + } + } + } + + @Override + public int getTotalItemsCount() { + return sharedMediaData[currentType].totalCount; } } @@ -3505,28 +5102,57 @@ public void requestLayout() { } } - private class SharedPhotoVideoAdapter extends RecyclerListView.SelectionAdapter { + private class SharedPhotoVideoAdapter extends RecyclerListView.FastScrollAdapter { private Context mContext; + private boolean inFastScrollMode; + SharedPhotoVideoCell2.SharedResources sharedResources; public SharedPhotoVideoAdapter(Context context) { mContext = context; } public int getPositionForIndex(int i) { - return i / columnsCount; + return sharedMediaData[0].startOffset + i; } @Override public int getItemCount() { + if (DialogObject.isEncryptedDialog(dialog_id)) { + if (sharedMediaData[0].messages.size() == 0 && !sharedMediaData[0].loading) { + return 1; + } + if (sharedMediaData[0].messages.size() == 0 && (!sharedMediaData[0].endReached[0] || !sharedMediaData[0].endReached[1])) { + return 0; + } + int count = sharedMediaData[0].getStartOffset() + sharedMediaData[0].getMessages().size(); + if (count != 0 && (!sharedMediaData[0].endReached[0] || !sharedMediaData[0].endReached[1])) { + count++; + } + return count; + } + if (sharedMediaData[0].loadingAfterFastScroll) { + return sharedMediaData[0].totalCount; + } if (sharedMediaData[0].messages.size() == 0 && !sharedMediaData[0].loading) { return 1; } - int count = (int) Math.ceil(sharedMediaData[0].messages.size() / (float) columnsCount); - if (count != 0 && (!sharedMediaData[0].endReached[0] || !sharedMediaData[0].endReached[1])) { - count++; + if (sharedMediaData[0].messages.size() == 0 && (!sharedMediaData[0].endReached[0] || !sharedMediaData[0].endReached[1]) && sharedMediaData[0].startReached) { + return 0; + } + if (sharedMediaData[0].totalCount == 0) { + int count = sharedMediaData[0].getStartOffset() + sharedMediaData[0].getMessages().size(); + if (count != 0 && (!sharedMediaData[0].endReached[0] || !sharedMediaData[0].endReached[1])) { + if (sharedMediaData[0].getEndLoadingStubs() != 0) { + count += sharedMediaData[0].getEndLoadingStubs(); + } else { + count++; + } + } + return count; + } else { + return sharedMediaData[0].totalCount; } - return count; } @Override @@ -3539,44 +5165,12 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType View view; switch (viewType) { case 0: - if (!cellCache.isEmpty()) { - view = cellCache.get(0); - cellCache.remove(0); - ViewGroup p = (ViewGroup) view.getParent(); - if (p != null) { - p.removeView(view); - } - } else { - view = new SharedPhotoVideoCell(mContext); + if (sharedResources == null) { + sharedResources = new SharedPhotoVideoCell2.SharedResources(parent.getContext()); } - SharedPhotoVideoCell cell = (SharedPhotoVideoCell) view; - cell.setDelegate(new SharedPhotoVideoCell.SharedPhotoVideoCellDelegate() { - @Override - public void didClickItem(SharedPhotoVideoCell cell, int index, MessageObject messageObject, int a) { - onItemClick(index, cell, messageObject, a, 0); - } - - @Override - public boolean didLongClickItem(SharedPhotoVideoCell cell, int index, MessageObject messageObject, int a) { - if (isActionModeShowed) { - didClickItem(cell, index, messageObject, a); - return true; - } - return onItemLongClick(messageObject, cell, a); - } - }); - cache.add((SharedPhotoVideoCell) view); - break; - case 1: - FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext) { - @Override - public int getColumnsCount() { - return columnsCount; - } - }; - flickerLoadingView.setIsSingleCell(true); - flickerLoadingView.setViewType(FlickerLoadingView.PHOTOS_TYPE); - view = flickerLoadingView; + view = new SharedPhotoVideoCell2(mContext, sharedResources, profileActivity.getCurrentAccount()); + SharedPhotoVideoCell2 cell = (SharedPhotoVideoCell2) view; + cell.setGradientView(globalGradientView); break; default: case 2: @@ -3591,43 +5185,186 @@ public int getColumnsCount() { @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder.getItemViewType() == 0) { - ArrayList messageObjects = sharedMediaData[0].messages; - SharedPhotoVideoCell cell = (SharedPhotoVideoCell) holder.itemView; - cell.setItemsCount(columnsCount); - // cell.setLoading(!sharedMediaData[0].endReached[0] || !sharedMediaData[0].endReached[1]); - cell.setIsFirst(position == 0); - for (int a = 0; a < columnsCount; a++) { - int index = position * columnsCount + a; - if (index < messageObjects.size()) { - MessageObject messageObject = messageObjects.get(index); - cell.setItem(a, sharedMediaData[0].messages.indexOf(messageObject), messageObject); - if (isActionModeShowed) { - cell.setChecked(a, selectedFiles[messageObject.getDialogId() == dialog_id ? 0 : 1].indexOfKey(messageObject.getId()) >= 0, !scrolling); - } else { - cell.setChecked(a, false, !scrolling); - } + ArrayList messageObjects = sharedMediaData[0].getMessages(); + int index = position - sharedMediaData[0].getStartOffset(); + SharedPhotoVideoCell2 cell = (SharedPhotoVideoCell2) holder.itemView; + int oldMessageId = cell.getMessageId(); + + int parentCount = this == photoVideoAdapter ? mediaColumnsCount : animateToColumnsCount; + if (index >= 0 && index < messageObjects.size()) { + MessageObject messageObject = messageObjects.get(index); + boolean animated = messageObject.getId() == oldMessageId; + + if (isActionModeShowed) { + cell.setChecked(selectedFiles[messageObject.getDialogId() == dialog_id ? 0 : 1].indexOfKey(messageObject.getId()) >= 0, animated); } else { - cell.setItem(a, index, null); + cell.setChecked(false, animated); } + cell.setMessageObject(messageObject, parentCount); + } else { + cell.setMessageObject(null, parentCount); + cell.setChecked(false, false); } - cell.requestLayout(); - } else if (holder.getItemViewType() == 1) { - FlickerLoadingView flickerLoadingView = (FlickerLoadingView) holder.itemView; - int count = (int) Math.ceil(sharedMediaData[0].messages.size() / (float) columnsCount); - flickerLoadingView.skipDrawItemsCount(columnsCount - (columnsCount * count - sharedMediaData[0].messages.size())); } } @Override public int getItemViewType(int position) { - if (sharedMediaData[0].messages.size() == 0 && !sharedMediaData[0].loading) { + if (!inFastScrollMode && sharedMediaData[0].getMessages().size() == 0 && !sharedMediaData[0].loading && sharedMediaData[0].startReached) { return 2; } - int count = (int) Math.ceil(sharedMediaData[0].messages.size() / (float) columnsCount); - if (position < count) { + int count = sharedMediaData[0].getStartOffset() + sharedMediaData[0].getMessages().size(); + if (position - sharedMediaData[0].getStartOffset() >= 0 && position < count) { return 0; } - return 1; + return 0; + } + + @Override + public String getLetter(int position) { + if (sharedMediaData[0].fastScrollPeriods == null) { + return ""; + } + int index = position; + ArrayList periods = sharedMediaData[0].fastScrollPeriods; + if (!periods.isEmpty()) { + for (int i = 0; i < periods.size(); i++) { + if (index <= periods.get(i).startOffset) { + return periods.get(i).formatedDate; + } + } + return periods.get(periods.size() - 1).formatedDate; + } + return ""; + } + + @Override + public void getPositionForScrollProgress(RecyclerListView listView, float progress, int[] position) { + int viewHeight = listView.getChildAt(0).getMeasuredHeight(); + int totalHeight = (int) (Math.ceil(getTotalItemsCount() / (float) mediaColumnsCount) * viewHeight); + position[0] = (int) ((progress * (totalHeight - listView.getMeasuredHeight())) / viewHeight) * mediaColumnsCount; + position[1] = (int) (progress * (totalHeight - listView.getMeasuredHeight())) % viewHeight; + } + + @Override + public void onStartFastScroll() { + inFastScrollMode = true; + MediaPage mediaPage = getMediaPage(0); + if (mediaPage != null) { + showFastScrollHint(mediaPage, null, false); + } + } + + @Override + public void onFinishFastScroll(RecyclerListView listView) { + if (inFastScrollMode) { + inFastScrollMode = false; + if (listView != null) { + int messageId = 0; + for (int i = 0; i < listView.getChildCount(); i++) { + View child = listView.getChildAt(i); + if (child instanceof SharedPhotoVideoCell2) { + SharedPhotoVideoCell2 cell = (SharedPhotoVideoCell2) child; + messageId = cell.getMessageId(); + } + if (messageId != 0) { + break; + } + } + if (messageId == 0) { + findPeriodAndJumpToDate(0, listView, true); + } + } + } + } + + @Override + public int getTotalItemsCount() { + return sharedMediaData[0].totalCount; + } + + @Override + public float getScrollProgress(RecyclerListView listView) { + int parentCount = this == photoVideoAdapter ? mediaColumnsCount : animateToColumnsCount; + int cellCount = (int) Math.ceil(getTotalItemsCount() / (float) parentCount); + if (listView.getChildCount() == 0) { + return 0; + } + int cellHeight = listView.getChildAt(0).getMeasuredHeight(); + View firstChild = listView.getChildAt(0); + int firstPosition = listView.getChildAdapterPosition(firstChild); + if (firstPosition < 0) { + return 0; + } + float scrollY = (firstPosition / parentCount) * cellHeight - firstChild.getTop(); + return scrollY / (((float) cellCount) * cellHeight - listView.getMeasuredHeight()); + } + + public boolean fastScrollIsVisible(RecyclerListView listView) { + int parentCount = this == photoVideoAdapter ? mediaColumnsCount : animateToColumnsCount; + int cellCount = (int) Math.ceil(getTotalItemsCount() / (float) parentCount); + if (listView.getChildCount() == 0) { + return false; + } + int cellHeight = listView.getChildAt(0).getMeasuredHeight(); + return cellCount * cellHeight > listView.getMeasuredHeight(); + } + + @Override + public void onFastScrollSingleTap() { + showMediaCalendar(true); + } + } + + private void findPeriodAndJumpToDate(int type, RecyclerListView listView, boolean scrollToPosition) { + ArrayList periods = sharedMediaData[type].fastScrollPeriods; + Period period = null; + int position = ((LinearLayoutManager) listView.getLayoutManager()).findFirstVisibleItemPosition(); + if (position >= 0) { + if (periods != null) { + for (int i = 0; i < periods.size(); i++) { + if (position <= periods.get(i).startOffset) { + period = periods.get(i); + break; + } + } + if (period == null) { + period = periods.get(periods.size() - 1); + } + } + if (period != null) { + jumpToDate(type, period.maxId, period.startOffset + 1, scrollToPosition); + return; + } + } + } + + private void jumpToDate(int type, int messageId, int startOffset, boolean scrollToPosition) { + sharedMediaData[type].messages.clear(); + sharedMediaData[type].messagesDict[0].clear(); + sharedMediaData[type].messagesDict[1].clear(); + sharedMediaData[type].setMaxId(0, messageId); + sharedMediaData[type].setEndReached(0, false); + sharedMediaData[type].startReached = false; + sharedMediaData[type].startOffset = startOffset; + sharedMediaData[type].endLoadingStubs = sharedMediaData[type].totalCount - startOffset - 1; + if (sharedMediaData[type].endLoadingStubs < 0) { + sharedMediaData[type].endLoadingStubs = 0; + } + sharedMediaData[type].min_id = messageId; + sharedMediaData[type].loadingAfterFastScroll = true; + sharedMediaData[type].loading = false; + sharedMediaData[type].requestIndex++; + MediaPage mediaPage = getMediaPage(type); + if (mediaPage != null && mediaPage.listView.getAdapter() != null) { + mediaPage.listView.getAdapter().notifyDataSetChanged(); + } + if (scrollToPosition) { + for (int i = 0; i < mediaPages.length; i++) { + if (mediaPages[i].selectedType == type) { + mediaPages[i].layoutManager.scrollToPositionWithOffset(Math.min(sharedMediaData[type].totalCount - 1, sharedMediaData[type].startOffset), 0); + } + } } } @@ -3707,7 +5444,7 @@ public void queryServerSearch(final String query, final int max_id, long did) { if (searchesInProgress == 0 && count == 0) { mediaPages[a].emptyView.showProgress(false, true); } else if (oldItemCounts == 0) { - animateItemsEnter(mediaPages[a].listView, 0); + animateItemsEnter(mediaPages[a].listView, 0, null); } } } @@ -3845,7 +5582,7 @@ private void updateSearchResults(final ArrayList documents) { if (searchesInProgress == 0 && count == 0) { mediaPages[a].emptyView.showProgress(false, true); } else if (oldItemCount == 0) { - animateItemsEnter(mediaPages[a].listView, 0); + animateItemsEnter(mediaPages[a].listView, 0, null); } } } @@ -4087,7 +5824,7 @@ private void getChats(long max_id, final int count) { if (mediaPages[a].listView != null) { final RecyclerListView listView = mediaPages[a].listView; if (firstLoaded || oldCount == 0) { - animateItemsEnter(listView, 0); + animateItemsEnter(listView, 0, null); } } } @@ -4270,14 +6007,14 @@ public GroupUsersSearchAdapter(Context context) { if (getItemCount() == 0) { mediaPages[a].emptyView.showProgress(false, true); } else { - animateItemsEnter(mediaPages[a].listView, 0); + animateItemsEnter(mediaPages[a].listView, 0, null); } } } } } }); - currentChat = profileActivity.getCurrentChat(); + currentChat = delegate.getCurrentChat(); } private boolean createMenuForParticipant(TLObject participant, boolean resultOnly) { @@ -4290,7 +6027,7 @@ private boolean createMenuForParticipant(TLObject participant, boolean resultOnl p.date = channelParticipant.date; participant = p; } - return profileActivity.onMemberClick((TLRPC.ChatParticipant) participant, true, resultOnly); + return delegate.onMemberClick((TLRPC.ChatParticipant) participant, true, resultOnly); } public void search(final String query, boolean animated) { @@ -4410,7 +6147,7 @@ private void updateSearchResults(final ArrayList names, final Arra if (getItemCount() == 0) { mediaPages[a].emptyView.showProgress(false, true); } else { - animateItemsEnter(mediaPages[a].listView, 0); + animateItemsEnter(mediaPages[a].listView, 0, null); } } } @@ -4601,7 +6338,7 @@ public ArrayList getThemeDescriptions() { arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundBlue)); arrayList.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundPink)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{EmptyStubView.class}, new String[]{"emptyTextView"}, null,null, null, Theme.key_windowBackgroundWhiteGrayText2)); + arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{EmptyStubView.class}, new String[]{"emptyTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText2)); arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{SharedDocumentCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{SharedDocumentCell.class}, new String[]{"dateTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText3)); arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_PROGRESSBAR, new Class[]{SharedDocumentCell.class}, new String[]{"progressView"}, null, null, null, Theme.key_sharedMedia_startStopLoadIcon)); @@ -4646,4 +6383,51 @@ public ArrayList getThemeDescriptions() { return arrayList; } + + public int getNextMediaColumnsCount(int mediaColumnsCount, boolean up) { + int newColumnsCount = mediaColumnsCount; + if (!up) { + if (mediaColumnsCount == 2) { + newColumnsCount = 3; + } else if (mediaColumnsCount == 3) { + newColumnsCount = 4; + } else if (mediaColumnsCount == 4) { + newColumnsCount = 5; + } else if (mediaColumnsCount == 5) { + newColumnsCount = 6; + } else if (mediaColumnsCount == 6) { + newColumnsCount = 9; + } + } else { + if (mediaColumnsCount == 9) { + newColumnsCount = 6; + } else if (mediaColumnsCount == 6) { + newColumnsCount = 5; + } else if (mediaColumnsCount == 5) { + newColumnsCount = 4; + } else if (mediaColumnsCount == 4) { + newColumnsCount = 3; + } else if (mediaColumnsCount == 3) { + newColumnsCount = 2; + } + } + + return newColumnsCount; + } + + public interface Delegate { + void scrollToSharedMedia(); + + boolean onMemberClick(TLRPC.ChatParticipant participant, boolean b, boolean resultOnly); + + TLRPC.Chat getCurrentChat(); + + boolean isFragmentOpened(); + + RecyclerListView getListView(); + + boolean canSearchMembers(); + + void updateSelectedMediaTabText(); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java index cf96d6e1ab6..e9cc088612c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java @@ -18,8 +18,14 @@ import android.graphics.drawable.GradientDrawable; import android.os.Build; import android.view.View; +import android.view.WindowInsets; import android.widget.FrameLayout; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; + +import com.google.android.exoplayer2.util.Log; + import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarLayout; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideChooseView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideChooseView.java index 35a9c624947..c6bf352de8e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideChooseView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideChooseView.java @@ -32,6 +32,8 @@ public class SlideChooseView extends View { private boolean moving; private boolean startMoving; private float startX; + private float xTouchDown; + private float yTouchDown; private int startMovingPreset; @@ -102,8 +104,10 @@ public void setDashedFrom(int from) { @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); + float y = event.getY(); if (event.getAction() == MotionEvent.ACTION_DOWN) { - getParent().requestDisallowInterceptTouchEvent(true); + xTouchDown = x; + yTouchDown = y; for (int a = 0; a < optionsStr.length; a++) { int cx = sideSide + (lineSize + gapSize * 2 + circleSize) * a + circleSize / 2; if (x > cx - AndroidUtilities.dp(15) && x < cx + AndroidUtilities.dp(15)) { @@ -114,6 +118,11 @@ public boolean onTouchEvent(MotionEvent event) { } } } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + if (!moving) { + if (Math.abs(xTouchDown - x) > Math.abs(yTouchDown - y)) { + getParent().requestDisallowInterceptTouchEvent(true); + } + } if (startMoving) { if (Math.abs(startX - x) >= AndroidUtilities.getPixelsInCM(0.5f, true)) { moving = true; @@ -152,6 +161,7 @@ public boolean onTouchEvent(MotionEvent event) { } startMoving = false; moving = false; + getParent().requestDisallowInterceptTouchEvent(false); } return true; } @@ -167,7 +177,6 @@ private void setOption(int index) { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(74), MeasureSpec.EXACTLY)); - int width = MeasureSpec.getSize(widthMeasureSpec); circleSize = AndroidUtilities.dp(6); gapSize = AndroidUtilities.dp(2); sideSide = AndroidUtilities.dp(22); @@ -181,15 +190,9 @@ protected void onDraw(Canvas canvas) { for (int a = 0; a < optionsStr.length; a++) { int cx = sideSide + (lineSize + gapSize * 2 + circleSize) * a + circleSize / 2; - if (a <= selectedIndex) { - int color = getThemedColor(Theme.key_switchTrackChecked); - paint.setColor(color); - linePaint.setColor(color); - } else { - int color = getThemedColor(Theme.key_switchTrack); - paint.setColor(color); - linePaint.setColor(color); - } + int color = a <= selectedIndex ? getThemedColor(Theme.key_switchTrackChecked) : getThemedColor(Theme.key_switchTrack); + paint.setColor(color); + linePaint.setColor(color); canvas.drawCircle(cx, cy, a == selectedIndex ? AndroidUtilities.dp(6) : circleSize / 2, paint); if (a != 0) { int x = cx - circleSize / 2 - gapSize - lineSize; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java index 394bf576c17..1c99475bc97 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java @@ -22,8 +22,9 @@ public class StickerEmptyView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { - public final static int STICKER_TYPE_SEARCH = 1; public final static int STICKER_TYPE_NO_CONTACTS = 0; + public final static int STICKER_TYPE_SEARCH = 1; + public final static int STICKER_TYPE_DONE = 2; private LinearLayout linearLayout; public BackupImageView stickerView; @@ -227,14 +228,24 @@ protected void onDetachedFromWindow() { } private void setSticker() { - TLRPC.TL_messages_stickerSet set = MediaDataController.getInstance(currentAccount).getStickerSetByName(AndroidUtilities.STICKERS_PLACEHOLDER_PACK_NAME); - if (set == null) { - set = MediaDataController.getInstance(currentAccount).getStickerSetByEmojiOrName(AndroidUtilities.STICKERS_PLACEHOLDER_PACK_NAME); + String imageFilter = null; + TLRPC.Document document = null; + TLRPC.TL_messages_stickerSet set = null; + if (stickerType == STICKER_TYPE_DONE) { + document = MediaDataController.getInstance(currentAccount).getEmojiAnimatedSticker("\uD83D\uDC4D"); + } else { + set = MediaDataController.getInstance(currentAccount).getStickerSetByName(AndroidUtilities.STICKERS_PLACEHOLDER_PACK_NAME); + if (set == null) { + set = MediaDataController.getInstance(currentAccount).getStickerSetByEmojiOrName(AndroidUtilities.STICKERS_PLACEHOLDER_PACK_NAME); + } + if (set != null && set.documents.size() >= 2) { + document = set.documents.get(stickerType); + } + imageFilter = "130_130"; } - if (set != null && set.documents.size() >= 2) { - TLRPC.Document document = set.documents.get(stickerType); + if (document != null) { ImageLocation imageLocation = ImageLocation.getForDocument(document); - stickerView.setImage(imageLocation, "130_130", "tgs", stubDrawable, set); + stickerView.setImage(imageLocation, imageFilter, "tgs", stubDrawable, set); stickerView.getImageReceiver().setAutoRepeat(2); } else { MediaDataController.getInstance(currentAccount).loadStickersByEmojiOrName(AndroidUtilities.STICKERS_PLACEHOLDER_PACK_NAME, false, set == null); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java index 5f416711de4..6bbb4294102 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java @@ -1252,6 +1252,8 @@ public void showWithAction(ArrayList dialogIds, int action, Object infoObj leftImageView.setAnimation(R.raw.chats_infotip, 36, 36); leftImageView.setProgress(0); leftImageView.playAnimation(); + + infoTextView.setMovementMethod(new AndroidUtilities.LinkMovementMethodMy()); } else if (currentAction == ACTION_THEME_CHANGED) { infoTextView.setText(LocaleController.getString("ColorThemeChanged", R.string.ColorThemeChanged)); leftImageView.setImageResource(R.drawable.toast_pallete); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UsersAlertBase.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UsersAlertBase.java index 288663e4abe..61b1eb09479 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UsersAlertBase.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UsersAlertBase.java @@ -7,6 +7,7 @@ import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.Context; +import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.PorterDuff; @@ -46,8 +47,8 @@ public class UsersAlertBase extends BottomSheet { protected FrameLayout frameLayout; protected RecyclerListView listView; - protected RecyclerListView.SelectionAdapter searchListViewAdapter; - protected RecyclerListView.SelectionAdapter listViewAdapter; + protected RecyclerView.Adapter searchListViewAdapter; + protected RecyclerView.Adapter listViewAdapter; protected Drawable shadowDrawable; protected View shadow; protected AnimatorSet shadowAnimation; @@ -63,6 +64,7 @@ public class UsersAlertBase extends BottomSheet { private int backgroundColor; protected boolean needSnapToTop = true; + protected boolean isEmptyViewVisible = true; protected String keyScrollUp = Theme.key_sheet_scrollUp; protected String keyListSelector = Theme.key_listSelector; @@ -118,7 +120,7 @@ public UsersAlertBase(Context context, boolean needFocus, int account, Theme.Res listView = new RecyclerListView(context) { @Override protected boolean allowSelectChildAtPosition(float x, float y) { - return y >= AndroidUtilities.dp(58) + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0); + return isAllowSelectChildAtPosition(x, y); } @Override @@ -133,7 +135,7 @@ protected boolean emptyViewIsVisible() { if (getAdapter() == null) { return false; } - return getAdapter().getItemCount() <= 2; + return isEmptyViewVisible && getAdapter().getItemCount() <= 2; } }; listView.setTag(13); @@ -183,10 +185,20 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { listView.setAnimateEmptyView(true, 0); } + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + AndroidUtilities.statusBarHeight = AndroidUtilities.getStatusBarHeight(getContext()); + } + protected ContainerView createContainerView(Context context) { return new ContainerView(context); } + protected boolean isAllowSelectChildAtPosition(float x, float y) { + return y >= AndroidUtilities.dp(58) + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0); + } + protected void updateColorKeys() { } @@ -376,7 +388,7 @@ public void dismiss() { } @SuppressLint("NewApi") - private void updateLayout() { + protected void updateLayout() { if (listView.getChildCount() <= 0) { return; } @@ -396,13 +408,18 @@ private void updateLayout() { runShadowAnimation(true); } if (scrollOffsetY != newOffset) { - listView.setTopGlowOffset(scrollOffsetY = (int) (newOffset)); - frameLayout.setTranslationY(scrollOffsetY); - emptyView.setTranslationY(scrollOffsetY); - containerView.invalidate(); + scrollOffsetY = newOffset; + setTranslationY(newOffset); } } + protected void setTranslationY(int newOffset) { + listView.setTopGlowOffset(newOffset); + frameLayout.setTranslationY(newOffset); + emptyView.setTranslationY(newOffset); + containerView.invalidate(); + } + private void runShadowAnimation(final boolean show) { if (show && shadow.getTag() != null || !show && shadow.getTag() == null) { shadow.setTag(show ? null : 1); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java index d809412d29c..32258c8487a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java @@ -216,7 +216,9 @@ public void onFragmentDestroy() { @Override protected void onTransitionAnimationProgress(boolean isOpen, float progress) { super.onTransitionAnimationProgress(isOpen, progress); - fragmentView.invalidate(); + if (fragmentView != null) { + fragmentView.invalidate(); + } } @Override @@ -402,7 +404,7 @@ public void setPadding(int left, int top, int right, int bottom) { }; listView.setSectionsType(1); listView.setVerticalScrollBarEnabled(false); - listView.setFastScrollEnabled(); + listView.setFastScrollEnabled(RecyclerListView.FastScroll.LETTER_TYPE); listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); listView.setAdapter(listViewAdapter); frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java index 71d1cc112f7..940c57b2a27 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java @@ -146,7 +146,7 @@ public void onTextChanged(EditText editText) { listView.setSectionsType(1); listView.setEmptyView(emptyView); listView.setVerticalScrollBarEnabled(false); - listView.setFastScrollEnabled(); + listView.setFastScrollEnabled(RecyclerListView.FastScroll.LETTER_TYPE); listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); listView.setAdapter(listViewAdapter); listView.setVerticalScrollbarPosition(LocaleController.isRTL ? RecyclerListView.SCROLLBAR_POSITION_LEFT : RecyclerListView.SCROLLBAR_POSITION_RIGHT); @@ -358,8 +358,9 @@ public String getLetter(int position) { } @Override - public int getPositionForScrollProgress(float progress) { - return (int) (getItemCount() * progress); + public void getPositionForScrollProgress(RecyclerListView listView, float progress, int[] position) { + position[0] = (int) (getItemCount() * progress); + position[1] = 0; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DefaultThemesPreviewCell.java b/TMessagesProj/src/main/java/org/telegram/ui/DefaultThemesPreviewCell.java new file mode 100644 index 00000000000..629bb6c3636 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/DefaultThemesPreviewCell.java @@ -0,0 +1,338 @@ +package org.telegram.ui; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.graphics.Paint; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.LinearLayout; + +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.EmojiThemes; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.TextCell; +import org.telegram.ui.Components.ChatThemeBottomSheet; +import org.telegram.ui.Components.FlickerLoadingView; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RLottieDrawable; +import org.telegram.ui.Components.RecyclerListView; + +import java.util.ArrayList; + +@SuppressLint("ViewConstructor") +public class DefaultThemesPreviewCell extends LinearLayout { + + private final RecyclerListView recyclerView; + private final LinearLayoutManager layoutManager; + private final FlickerLoadingView progressView; + private final ChatThemeBottomSheet.Adapter adapter; + RLottieDrawable darkThemeDrawable; + TextCell dayNightCell; + TextCell browseThemesCell; + + private int selectedPosition = -1; + BaseFragment parentFragment; + int currentType; + int themeIndex; + + public DefaultThemesPreviewCell(Context context, BaseFragment parentFragment, int type) { + super(context); + this.currentType = type; + this.parentFragment = parentFragment; + setOrientation(LinearLayout.VERTICAL); + FrameLayout frameLayout = new FrameLayout(context); + addView(frameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + + adapter = new ChatThemeBottomSheet.Adapter(parentFragment.getCurrentAccount(), null, currentType == ThemeActivity.THEME_TYPE_BASIC ? ChatThemeBottomSheet.Adapter.TYPE_DEFAULT : ChatThemeBottomSheet.Adapter.TYPE_GRID); + recyclerView = new RecyclerListView(getContext()); + recyclerView.setAdapter(adapter); + recyclerView.setClipChildren(false); + recyclerView.setClipToPadding(false); + recyclerView.setHasFixedSize(true); + recyclerView.setItemAnimator(null); + recyclerView.setNestedScrollingEnabled(false); + if (currentType == ThemeActivity.THEME_TYPE_BASIC) { + recyclerView.setLayoutManager(layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false)); + } else { + recyclerView.setHasFixedSize(false); + GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 3); + gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + return 1; + } + }); + recyclerView.setLayoutManager(layoutManager = gridLayoutManager); + } + + recyclerView.setPadding(AndroidUtilities.dp(12), 0, AndroidUtilities.dp(12), 0); + recyclerView.setOnItemClickListener((view, position) -> { + ChatThemeBottomSheet.ChatThemeItem chatTheme = adapter.items.get(position); + Theme.ThemeInfo info = chatTheme.chatTheme.getThemeInfo(themeIndex); + int accentId = -1; + if (chatTheme.chatTheme.getEmoticon().equals("\uD83C\uDFE0")) { + accentId = chatTheme.chatTheme.getAccentId(themeIndex); + } + if (info == null) { + TLRPC.TL_theme theme = chatTheme.chatTheme.getTlTheme(themeIndex); + int settingsIndex = chatTheme.chatTheme.getSettingsIndex(themeIndex); + TLRPC.ThemeSettings settings = theme.settings.get(settingsIndex); + String key = Theme.getBaseThemeKey(settings); + info = Theme.getTheme(key); + + if (info != null) { + Theme.ThemeAccent accent = info.accentsByThemeId.get(theme.id); + if (accent == null) { + accent = info.createNewAccent(theme, parentFragment.getCurrentAccount()); + } + accentId = accent.id; + info.setCurrentAccentId(accentId); + } + } + + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, info, false, null, accentId); + + selectedPosition = position; + adapter.setSelectedItem(selectedPosition); + + for (int i = 0; i < recyclerView.getChildCount(); i++) { + ChatThemeBottomSheet.Adapter.ChatThemeView child = (ChatThemeBottomSheet.Adapter.ChatThemeView) recyclerView.getChildAt(i); + if (child != view) { + child.cancelAnimation(); + } + } + ((ChatThemeBottomSheet.Adapter.ChatThemeView) view).playEmojiAnimation(); + }); + + progressView = new FlickerLoadingView(getContext(), null); + progressView.setViewType(FlickerLoadingView.CHAT_THEMES_TYPE); + progressView.setVisibility(View.VISIBLE); + + if (currentType == ThemeActivity.THEME_TYPE_BASIC) { + frameLayout.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 104, Gravity.START, 0, 8, 0, 8)); + frameLayout.addView(recyclerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 104, Gravity.START, 0, 8, 0, 8)); + } else { + frameLayout.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 104, Gravity.START, 0, 8, 0, 8)); + frameLayout.addView(recyclerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.START, 0, 8, 0, 8)); + } + + + recyclerView.setEmptyView(progressView); + recyclerView.setAnimateEmptyView(true, 0); + + if (currentType == ThemeActivity.THEME_TYPE_BASIC) { + darkThemeDrawable = new RLottieDrawable(R.raw.sun_outline, "" + R.raw.sun_outline, AndroidUtilities.dp(28), AndroidUtilities.dp(28), true, null); + darkThemeDrawable.setPlayInDirectionOfCustomEndFrame(true); + darkThemeDrawable.beginApplyLayerColors(); + darkThemeDrawable.commitApplyLayerColors(); + + dayNightCell = new TextCell(context); + dayNightCell.setTextAndIcon(LocaleController.getString("SettingsSwitchToNightMode", R.string.SettingsSwitchToNightMode), darkThemeDrawable, true); + dayNightCell.imageLeft = 21; + addView(dayNightCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + browseThemesCell = new TextCell(context); + browseThemesCell.setTextAndIcon(LocaleController.getString("SettingsBrowseThemes", R.string.SettingsBrowseThemes), R.drawable.msg_colors, false); + + addView(browseThemesCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + dayNightCell.setOnClickListener(new OnClickListener() { + @SuppressLint("NotifyDataSetChanged") + @Override + public void onClick(View view) { + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE); + String dayThemeName = preferences.getString("lastDayTheme", "Blue"); + if (Theme.getTheme(dayThemeName) == null || Theme.getTheme(dayThemeName).isDark()) { + dayThemeName = "Blue"; + } + String nightThemeName = preferences.getString("lastDarkTheme", "Dark Blue"); + if (Theme.getTheme(nightThemeName) == null || !Theme.getTheme(nightThemeName).isDark()) { + nightThemeName = "Dark Blue"; + } + Theme.ThemeInfo themeInfo = Theme.getActiveTheme(); + if (dayThemeName.equals(nightThemeName)) { + if (themeInfo.isDark() || dayThemeName.equals("Dark Blue") || dayThemeName.equals("Night")) { + dayThemeName = "Blue"; + } else { + nightThemeName = "Dark Blue"; + } + } + + boolean toDark; + if (toDark = !Theme.isCurrentThemeDark()) { + themeInfo = Theme.getTheme(nightThemeName); + } else { + themeInfo = Theme.getTheme(dayThemeName); + } + + darkThemeDrawable.setCustomEndFrame(toDark ? darkThemeDrawable.getFramesCount() - 1 : 0); + + dayNightCell.getImageView().playAnimation(); + int[] pos = new int[2]; + dayNightCell.getImageView().getLocationInWindow(pos); + pos[0] += dayNightCell.getImageView().getMeasuredWidth() / 2; + pos[1] += dayNightCell.getImageView().getMeasuredHeight() / 2 + AndroidUtilities.dp(3); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, themeInfo, false, pos, -1, toDark, dayNightCell.getImageView()); + + updateDayNightMode(); + updateSelectedPosition(); + } + }); + + darkThemeDrawable.setPlayInDirectionOfCustomEndFrame(true); + browseThemesCell.setOnClickListener(view -> { + parentFragment.presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_THEMES_BROWSER)); + }); + + if (!Theme.isCurrentThemeDay()) { + darkThemeDrawable.setCurrentFrame(darkThemeDrawable.getFramesCount() - 1); + } + } + + if (!Theme.defaultEmojiThemes.isEmpty()) { + ArrayList themes = new ArrayList<>(); + themes.addAll(Theme.defaultEmojiThemes); + if (currentType == ThemeActivity.THEME_TYPE_BASIC) { + + EmojiThemes chatTheme = EmojiThemes.createPreviewCustom(); + chatTheme.loadPreviewColors(parentFragment.getCurrentAccount()); + ChatThemeBottomSheet.ChatThemeItem item = new ChatThemeBottomSheet.ChatThemeItem(chatTheme); + item.themeIndex = !Theme.isCurrentThemeDay() ? 2 : 0; + themes.add(item); + } + + adapter.setItems(themes); + } + updateDayNightMode(); + updateSelectedPosition(); + updateColors(); + if (selectedPosition >= 0) { + layoutManager.scrollToPositionWithOffset(selectedPosition, AndroidUtilities.dp(16)); + } + } + + public void updateDayNightMode() { + if (currentType == ThemeActivity.THEME_TYPE_BASIC) { + themeIndex = !Theme.isCurrentThemeDay() ? 2 : 0; + } else { + if (Theme.getActiveTheme().getKey().equals("Blue")) { + themeIndex = 0; + } else if (Theme.getActiveTheme().getKey().equals("Day")) { + themeIndex = 1; + } else if (Theme.getActiveTheme().getKey().equals("Night")) { + themeIndex = 2; + } else if (Theme.getActiveTheme().getKey().equals("Dark Blue")) { + themeIndex = 3; + } else { + if (Theme.isCurrentThemeDay() && (themeIndex == 2 || themeIndex == 3)) { + themeIndex = 0; + } + if (!Theme.isCurrentThemeDay() && (themeIndex == 0 || themeIndex == 1)) { + themeIndex = 2; + } + } + + } + if (adapter.items != null) { + for (int i = 0; i < adapter.items.size(); i++) { + adapter.items.get(i).themeIndex = themeIndex; + } + adapter.notifyItemRangeChanged(0, adapter.items.size()); + } + updateSelectedPosition(); + } + + private void updateSelectedPosition() { + if (adapter.items == null) { + return; + } + selectedPosition = -1; + for (int i = 0; i < adapter.items.size(); i++) { + TLRPC.TL_theme theme = adapter.items.get(i).chatTheme.getTlTheme(themeIndex); + if (theme != null) { + int settingsIndex = adapter.items.get(i).chatTheme.getSettingsIndex(themeIndex); + String key = Theme.getBaseThemeKey(theme.settings.get(settingsIndex)); + if (Theme.getCurrentTheme().name.equals(key)) { + Theme.ThemeAccent accent = Theme.getCurrentTheme().accentsByThemeId.get(theme.id); + if (accent != null && accent.id == Theme.getCurrentTheme().currentAccentId) { + selectedPosition = i; + } + } + } + } + if (selectedPosition == -1) { + selectedPosition = adapter.items.size() - 1; + } + adapter.setSelectedItem(selectedPosition); + } + + public void selectTheme(Theme.ThemeInfo themeInfo) { + if (themeInfo.info != null) { + if (!themeInfo.themeLoaded) { + return; + } + } + if (!TextUtils.isEmpty(themeInfo.assetName)) { + Theme.PatternsLoader.createLoader(false); + } + if (currentType != ThemeActivity.THEME_TYPE_OTHER) { + SharedPreferences.Editor editor = ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE).edit(); + editor.putString(currentType == ThemeActivity.THEME_TYPE_NIGHT || themeInfo.isDark() ? "lastDarkTheme" : "lastDayTheme", themeInfo.getKey()); + editor.commit(); + } + if (currentType == ThemeActivity.THEME_TYPE_NIGHT) { + if (themeInfo == Theme.getCurrentNightTheme()) { + return; + } + Theme.setCurrentNightTheme(themeInfo); + } else { + if (themeInfo == Theme.getCurrentTheme()) { + return; + } + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, themeInfo, false, null, -1); + } + //updateRows(); + + int count = getChildCount(); +// for (int a = 0; a < count; a++) { +// View child = getChildAt(a); +// if (child instanceof ThemesHorizontalListCell.InnerThemeView) { +// ((ThemesHorizontalListCell.InnerThemeView) child).updateCurrentThemeCheck(); +// } +// } + } + + public void updateColors() { + if (currentType == ThemeActivity.THEME_TYPE_BASIC) { + darkThemeDrawable.setLayerColor("Sunny.**", Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)); + darkThemeDrawable.setLayerColor("Path.**", Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)); + darkThemeDrawable.setLayerColor("Path 10.**", Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)); + darkThemeDrawable.setLayerColor("Path 11.**", Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)); + + dayNightCell.setBackground(Theme.createSelectorWithBackgroundDrawable(Theme.getColor(Theme.key_windowBackgroundWhite), Theme.getColor(Theme.key_listSelector))); + browseThemesCell.setBackground(Theme.createSelectorWithBackgroundDrawable(Theme.getColor(Theme.key_windowBackgroundWhite), Theme.getColor(Theme.key_listSelector))); + dayNightCell.setColors(null, Theme.key_windowBackgroundWhiteBlueText4); + browseThemesCell.setColors(Theme.key_windowBackgroundWhiteBlueText4, Theme.key_windowBackgroundWhiteBlueText4); + } + } + + @Override + public void setBackgroundColor(int color) { + super.setBackgroundColor(color); + updateColors(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Delegates/ChatActivityMemberRequestsDelegate.java b/TMessagesProj/src/main/java/org/telegram/ui/Delegates/ChatActivityMemberRequestsDelegate.java new file mode 100644 index 00000000000..50ab37044c3 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Delegates/ChatActivityMemberRequestsDelegate.java @@ -0,0 +1,249 @@ +package org.telegram.ui.Delegates; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.os.Build; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ActionBar.ThemeDescription; +import org.telegram.ui.Components.AvatarsImageView; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.MemberRequestsBottomSheet; + +import java.util.List; + +public class ChatActivityMemberRequestsDelegate { + + private final BaseFragment fragment; + private final Callback callback; + private final TLRPC.Chat currentChat; + private final int currentAccount; + + private FrameLayout root; + private AvatarsImageView avatarsView; + private TextView requestsCountTextView; + private ImageView closeView; + + @Nullable + private MemberRequestsBottomSheet bottomSheet; + @Nullable + private TLRPC.ChatFull chatInfo; + @Nullable + private ValueAnimator pendingRequestsAnimator; + private float pendingRequestsEnterOffset; + private int pendingRequestsCount; + private int closePendingRequestsCount = -1; + + public ChatActivityMemberRequestsDelegate(BaseFragment fragment, TLRPC.Chat currentChat, Callback callback) { + this.fragment = fragment; + this.currentChat = currentChat; + this.currentAccount = fragment.getCurrentAccount(); + this.callback = callback; + } + + public View getView() { + if (root == null) { + root = new FrameLayout(fragment.getParentActivity()); + root.setBackgroundResource(R.drawable.blockpanel); + root.getBackground().mutate().setColorFilter(new PorterDuffColorFilter(fragment.getThemedColor(Theme.key_chat_topPanelBackground), PorterDuff.Mode.MULTIPLY)); + root.setVisibility(View.GONE); + pendingRequestsEnterOffset = -getViewHeight(); + + View pendingRequestsSelector = new View(fragment.getParentActivity()); + pendingRequestsSelector.setBackground(Theme.getSelectorDrawable(false)); + pendingRequestsSelector.setOnClickListener((v) -> showBottomSheet()); + root.addView(pendingRequestsSelector, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 2)); + + LinearLayout requestsDataLayout = new LinearLayout(fragment.getParentActivity()); + requestsDataLayout.setOrientation(LinearLayout.HORIZONTAL); + root.addView(requestsDataLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP, 0, 0, 36, 0)); + + avatarsView = new AvatarsImageView(fragment.getParentActivity(), false) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int width = count == 0 ? 0 : (20 * (count - 1) + 24); + super.onMeasure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(width), MeasureSpec.EXACTLY), heightMeasureSpec); + } + }; + avatarsView.reset(); + requestsDataLayout.addView(avatarsView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP, 8, 0, 10, 0)); + + requestsCountTextView = new TextView(fragment.getParentActivity()); + requestsCountTextView.setEllipsize(TextUtils.TruncateAt.END); + requestsCountTextView.setGravity(Gravity.CENTER_VERTICAL); + requestsCountTextView.setSingleLine(); + requestsCountTextView.setText(null); + requestsCountTextView.setTextColor(fragment.getThemedColor(Theme.key_chat_topPanelTitle)); + requestsCountTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + requestsDataLayout.addView(requestsCountTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP, 0, 0, 0, 0)); + + closeView = new ImageView(fragment.getParentActivity()); + if (Build.VERSION.SDK_INT >= 21) { + closeView.setBackground(Theme.createSelectorDrawable(fragment.getThemedColor(Theme.key_inappPlayerClose) & 0x19ffffff, 1, AndroidUtilities.dp(14))); + } + closeView.setColorFilter(new PorterDuffColorFilter(fragment.getThemedColor(Theme.key_chat_topPanelClose), PorterDuff.Mode.MULTIPLY)); + closeView.setContentDescription(LocaleController.getString("Close", R.string.Close)); + closeView.setImageResource(R.drawable.miniplayer_close); + closeView.setScaleType(ImageView.ScaleType.CENTER); + closeView.setOnClickListener((v) -> { + fragment.getMessagesController().setChatPendingRequestsOnClose(currentChat.id, pendingRequestsCount); + closePendingRequestsCount = pendingRequestsCount; + animatePendingRequests(false, true); + }); + root.addView(closeView, LayoutHelper.createFrame(36, LayoutHelper.MATCH_PARENT, Gravity.RIGHT | Gravity.TOP, 0, 0, 2, 0)); + if (chatInfo != null) { + setPendingRequests(chatInfo.requests_pending, chatInfo.recent_requesters, false); + } + } + return root; + } + + public void setChatInfo(@Nullable TLRPC.ChatFull chatInfo, boolean animated) { + this.chatInfo = chatInfo; + if (chatInfo != null) { + setPendingRequests(chatInfo.requests_pending, chatInfo.recent_requesters, animated); + } + } + + public int getViewHeight() { + return AndroidUtilities.dp(40); + } + + public float getViewEnterOffset() { + return pendingRequestsEnterOffset; + } + + public void onBackToScreen() { + if (bottomSheet != null && bottomSheet.isNeedRestoreDialog()) { + showBottomSheet(); + } + } + + private void showBottomSheet() { + if (bottomSheet == null) { + bottomSheet = new MemberRequestsBottomSheet(fragment, currentChat.id) { + @Override + public void dismiss() { + if (bottomSheet != null && !bottomSheet.isNeedRestoreDialog()) { + bottomSheet = null; + } + super.dismiss(); + } + }; + } + fragment.showDialog(bottomSheet); + } + + private void setPendingRequests(int count, List recentRequestersIdList, boolean animated) { + if (root == null) { + return; + } + if (count <= 0) { + if (currentChat != null) { + fragment.getMessagesController().setChatPendingRequestsOnClose(currentChat.id, 0); + closePendingRequestsCount = 0; + } + animatePendingRequests(false, animated); + pendingRequestsCount = 0; + return; + } + if (pendingRequestsCount != count) { + pendingRequestsCount = count; + requestsCountTextView.setText(LocaleController.formatPluralString("JoinUsersRequests", count)); + animatePendingRequests(true, animated); + + if (recentRequestersIdList != null && !recentRequestersIdList.isEmpty()) { + int usersCount = Math.min(3, recentRequestersIdList.size()); + for (int i = 0; i < usersCount; ++i) { + TLRPC.User user = fragment.getMessagesController().getUser(recentRequestersIdList.get(i)); + if (user != null) { + avatarsView.setObject(i, currentAccount, user); + } + } + avatarsView.setCount(usersCount); + avatarsView.commitTransition(true); + } + } + } + + private void animatePendingRequests(boolean appear, boolean animated) { + boolean isVisibleNow = root.getVisibility() == View.VISIBLE; + if (appear == isVisibleNow) { + return; + } + if (appear) { + if (closePendingRequestsCount == -1 && currentChat != null) { + closePendingRequestsCount = fragment.getMessagesController().getChatPendingRequestsOnClosed(currentChat.id); + } + if (pendingRequestsCount == closePendingRequestsCount) { + return; + } + if (closePendingRequestsCount != 0 && currentChat != null) { + fragment.getMessagesController().setChatPendingRequestsOnClose(currentChat.id, 0); + } + } + if (pendingRequestsAnimator != null) { + pendingRequestsAnimator.cancel(); + } + if (animated) { + pendingRequestsAnimator = ValueAnimator.ofFloat(appear ? 0f : 1f, appear ? 1f : 0f); + pendingRequestsAnimator.addUpdateListener(animation -> { + float progress = (float) animation.getAnimatedValue(); + pendingRequestsEnterOffset = -getViewHeight() * (1f - progress); + if (callback != null) { + callback.onEnterOffsetChanged(); + } + }); + pendingRequestsAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + if (appear) { + root.setVisibility(View.VISIBLE); + } + } + @Override + public void onAnimationEnd(Animator animation) { + if (!appear) { + root.setVisibility(View.GONE); + } + } + }); + pendingRequestsAnimator.setDuration(200); + pendingRequestsAnimator.start(); + } else { + root.setVisibility(appear ? View.VISIBLE : View.GONE); + pendingRequestsEnterOffset = appear ? 0 : -getViewHeight(); + if (callback != null) { + callback.onEnterOffsetChanged(); + } + } + } + + public void fillThemeDescriptions(List themeDescriptions) { + themeDescriptions.add(new ThemeDescription(root, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chat_topPanelBackground)); + themeDescriptions.add(new ThemeDescription(requestsCountTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_topPanelTitle)); + themeDescriptions.add(new ThemeDescription(closeView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_topPanelClose)); + } + + public interface Callback { + + void onEnterOffsetChanged(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Delegates/MemberRequestsDelegate.java b/TMessagesProj/src/main/java/org/telegram/ui/Delegates/MemberRequestsDelegate.java new file mode 100644 index 00000000000..d65bd0d70ac --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Delegates/MemberRequestsDelegate.java @@ -0,0 +1,1021 @@ +package org.telegram.ui.Delegates; + +import static android.view.View.GONE; +import static android.view.View.INVISIBLE; +import static android.view.View.VISIBLE; +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.annotation.SuppressLint; +import android.app.Dialog; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.RectF; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Bundle; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextUtils; +import android.util.LongSparseArray; +import android.view.GestureDetector; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.FrameLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.ColorUtils; +import androidx.core.math.MathUtils; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ChatObject; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MemberRequestsController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; +import org.telegram.messenger.Utilities; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.ActionBarMenu; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; +import org.telegram.ui.ActionBar.ActionBarPopupWindow; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.AvatarPreviewPagerIndicator; +import org.telegram.ui.Cells.MemberRequestCell; +import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.BackupImageView; +import org.telegram.ui.Components.Bulletin; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.FlickerLoadingView; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.ProfileGalleryView; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.StickerEmptyView; +import org.telegram.ui.Components.TypefaceSpan; +import org.telegram.ui.LaunchActivity; +import org.telegram.ui.MemberRequestsActivity; +import org.telegram.ui.ProfileActivity; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener { + + public final boolean isChannel; + public boolean isNeedRestoreList; + + private final List currentImporters = new ArrayList<>(); + private final LongSparseArray users = new LongSparseArray<>(); + + private final ArrayList allImporters = new ArrayList<>(); + private final Adapter adapter = new Adapter(); + private final BaseFragment fragment; + private final FrameLayout layoutContainer; + private final MemberRequestsController controller; + private final long chatId; + private final int currentAccount; + private final boolean showSearchMenu; + + private FrameLayout rootLayout; + private StickerEmptyView emptyView; + private StickerEmptyView searchEmptyView; + private RecyclerListView recyclerView; + private FlickerLoadingView loadingView; + + private TLRPC.TL_chatInviteImporter importer; + private PreviewDialog previewDialog; + + private String query; + private Runnable searchRunnable; + private int searchRequestId; + private boolean isLoading; + private boolean hasMore; + private boolean isSearchExpanded; + private boolean isDataLoaded; + private boolean isFirstLoading = true; + private boolean isShowLastItemDivider = true; + + public MemberRequestsDelegate(BaseFragment fragment, FrameLayout layoutContainer, long chatId, boolean showSearchMenu) { + this.fragment = fragment; + this.layoutContainer = layoutContainer; + this.chatId = chatId; + this.currentAccount = fragment.getCurrentAccount(); + this.isChannel = ChatObject.isChannelAndNotMegaGroup(chatId, currentAccount); + this.showSearchMenu = showSearchMenu; + this.controller = MemberRequestsController.getInstance(currentAccount); + } + + public FrameLayout getRootLayout() { + if (rootLayout == null) { + rootLayout = new FrameLayout(fragment.getParentActivity()); + rootLayout.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray, fragment.getResourceProvider())); + + loadingView = getLoadingView(); + rootLayout.addView(loadingView, MATCH_PARENT, MATCH_PARENT); + + searchEmptyView = getSearchEmptyView(); + rootLayout.addView(searchEmptyView, MATCH_PARENT, MATCH_PARENT); + + emptyView = getEmptyView(); + rootLayout.addView(emptyView, LayoutHelper.createFrame(MATCH_PARENT, MATCH_PARENT)); + + LinearLayoutManager layoutManager = new LinearLayoutManager(fragment.getParentActivity()); + recyclerView = new RecyclerListView(fragment.getParentActivity()); + recyclerView.setAdapter(adapter); + recyclerView.setLayoutManager(layoutManager); + recyclerView.setOnItemClickListener(this::onItemClick); + recyclerView.setOnScrollListener(listScrollListener); + recyclerView.setSelectorDrawableColor(Theme.getColor(Theme.key_listSelector, fragment.getResourceProvider())); + rootLayout.addView(recyclerView, MATCH_PARENT, MATCH_PARENT); + } + return rootLayout; + } + + public void setShowLastItemDivider(boolean showLastItemDivider) { + this.isShowLastItemDivider = showLastItemDivider; + } + + public Adapter getAdapter() { + return adapter; + } + + public FlickerLoadingView getLoadingView() { + if (loadingView == null) { + loadingView = new FlickerLoadingView(fragment.getParentActivity(), fragment.getResourceProvider()); + loadingView.setAlpha(0f); + if (isShowLastItemDivider) { + loadingView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite, fragment.getResourceProvider())); + } + loadingView.setColors(Theme.key_windowBackgroundWhite, Theme.key_windowBackgroundGray, null); + loadingView.setViewType(FlickerLoadingView.MEMBER_REQUESTS_TYPE); + } + return loadingView; + } + + public StickerEmptyView getEmptyView() { + if (emptyView == null) { + emptyView = new StickerEmptyView(fragment.getParentActivity(), null, StickerEmptyView.STICKER_TYPE_DONE, fragment.getResourceProvider()); + emptyView.title.setText(isChannel ? LocaleController.getString("NoSubscribeRequests", R.string.NoSubscribeRequests) : LocaleController.getString("NoMemberRequests", R.string.NoMemberRequests)); + emptyView.subtitle.setText(isChannel ? LocaleController.getString("NoSubscribeRequestsDescription", R.string.NoSubscribeRequestsDescription) : LocaleController.getString("NoMemberRequestsDescription", R.string.NoMemberRequestsDescription)); + emptyView.setAnimateLayoutChange(true); + emptyView.setVisibility(GONE); + } + return emptyView; + } + + public StickerEmptyView getSearchEmptyView() { + if (searchEmptyView == null) { + searchEmptyView = new StickerEmptyView(fragment.getParentActivity(), null, StickerEmptyView.STICKER_TYPE_SEARCH, fragment.getResourceProvider()); + if (isShowLastItemDivider) { + searchEmptyView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite, fragment.getResourceProvider())); + } + searchEmptyView.title.setText(LocaleController.getString("NoResult", R.string.NoResult)); + searchEmptyView.subtitle.setText(LocaleController.getString("SearchEmptyViewFilteredSubtitle2", R.string.SearchEmptyViewFilteredSubtitle2)); + searchEmptyView.setAnimateLayoutChange(true); + searchEmptyView.setVisibility(GONE); + } + return searchEmptyView; + } + + public void setRecyclerView(RecyclerListView recyclerView) { + this.recyclerView = recyclerView; + recyclerView.setOnItemClickListener(this::onItemClick); + RecyclerView.OnScrollListener currentScrollListener = recyclerView.getOnScrollListener(); + if (currentScrollListener == null) { + recyclerView.setOnScrollListener(listScrollListener); + } else { + recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + currentScrollListener.onScrollStateChanged(recyclerView, newState); + listScrollListener.onScrollStateChanged(recyclerView, newState); + } + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + currentScrollListener.onScrolled(recyclerView, dx, dy); + listScrollListener.onScrolled(recyclerView, dx, dy); + } + }); + } + } + + public void onItemClick(View view, int position) { + if (view instanceof MemberRequestCell) { + if (isSearchExpanded) { + AndroidUtilities.hideKeyboard(fragment.getParentActivity().getCurrentFocus()); + } + MemberRequestCell cell = (MemberRequestCell) view; + AndroidUtilities.runOnUIThread(() -> { + importer = cell.getImporter(); + TLRPC.User user = users.get(importer.user_id); + if (user == null) { + return; + } + fragment.getMessagesController().putUser(user, false); + boolean isLandscape = AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y; + boolean showProfile = user.photo == null || isLandscape; + if (showProfile) { + isNeedRestoreList = true; + fragment.dismissCurrentDialog(); + Bundle args = new Bundle(); + ProfileActivity profileActivity = new ProfileActivity(args); + args.putLong("user_id", user.id); + args.putBoolean("removeFragmentOnChatOpen", false); + fragment.presentFragment(profileActivity); + } else if (previewDialog == null) { + RecyclerListView parentListView = (RecyclerListView) cell.getParent(); + previewDialog = new PreviewDialog(fragment.getParentActivity(), parentListView, fragment.getResourceProvider(), isChannel); + previewDialog.setImporter(importer, cell.getAvatarImageView()); + previewDialog.setOnDismissListener(dialog -> previewDialog = null); + previewDialog.show(); + } + }, isSearchExpanded ? 100 : 0); + } + } + + public boolean onBackPressed() { + if (previewDialog != null) { + previewDialog.dismiss(); + return false; + } else { + return true; + } + } + + public void setSearchExpanded(boolean isExpanded) { + isSearchExpanded = isExpanded; + } + + public void setQuery(String query) { + if (searchRunnable != null) { + Utilities.searchQueue.cancelRunnable(searchRunnable); + searchRunnable = null; + } + if (searchRequestId != 0) { + ConnectionsManager.getInstance(currentAccount).cancelRequest(searchRequestId, false); + searchRequestId = 0; + } + + this.query = query; + if (isDataLoaded && allImporters.isEmpty()) { + setViewVisible(loadingView, false, false); + return; + } + + if (TextUtils.isEmpty(query)) { + adapter.setItems(allImporters); + setViewVisible(recyclerView, true, true); + setViewVisible(loadingView, false, false); + if (searchEmptyView != null) { + searchEmptyView.setVisibility(INVISIBLE); + } + if (query == null && showSearchMenu) { + fragment.getActionBar().createMenu().getItem(MemberRequestsActivity.searchMenuItem).setVisibility(allImporters.isEmpty() ? GONE : VISIBLE); + } + } else { + adapter.setItems(Collections.emptyList()); + setViewVisible(recyclerView, false, false); + setViewVisible(loadingView, true, true); + Utilities.searchQueue.postRunnable(searchRunnable = this::loadMembers, 300); + } + if (query != null) { + if (emptyView != null) { + emptyView.setVisibility(INVISIBLE); + } + if (searchEmptyView != null) { + searchEmptyView.setVisibility(INVISIBLE); + } + } + } + + public void loadMembers() { + boolean isNeedShowLoading = true; + if (isFirstLoading) { + TLRPC.TL_messages_chatInviteImporters firstImporters = controller.getCachedImporters(chatId); + if (firstImporters != null) { + isNeedShowLoading = false; + isDataLoaded = true; + onImportersLoaded(firstImporters, null, true, true); + } + } + final boolean needShowLoading = isNeedShowLoading; + AndroidUtilities.runOnUIThread(() -> { + final boolean isEmptyQuery = TextUtils.isEmpty(query); + final boolean isEmptyOffset = currentImporters.isEmpty() || isFirstLoading; + final String lastQuery = query; + + isLoading = true; + isFirstLoading = false; + + final Runnable showLoadingRunnable = isEmptyQuery && needShowLoading ? () -> setViewVisible(loadingView, true, true) : null; + if (isEmptyQuery) { + AndroidUtilities.runOnUIThread(showLoadingRunnable, 300); + } + + TLRPC.TL_chatInviteImporter lastInvitedUser = !isEmptyQuery && !currentImporters.isEmpty() + ? currentImporters.get(currentImporters.size() - 1) + : null; + searchRequestId = controller.getImporters(chatId, lastQuery, lastInvitedUser, users, (response, error) -> { + AndroidUtilities.runOnUIThread(() -> { + isLoading = false; + isDataLoaded = true; + if (isEmptyQuery) { + AndroidUtilities.cancelRunOnUIThread(showLoadingRunnable); + } + setViewVisible(loadingView, false, false); + if (!TextUtils.equals(lastQuery, query)) { + return; + } + if (error == null) { + isDataLoaded = true; + TLRPC.TL_messages_chatInviteImporters importers = (TLRPC.TL_messages_chatInviteImporters) response; + onImportersLoaded(importers, lastQuery, isEmptyOffset, false); + } + }); + }); + }); + } + + private void onImportersLoaded(TLRPC.TL_messages_chatInviteImporters importers, String lastQuery, boolean isEmptyOffset, boolean fromCache) { + for (int i = 0; i < importers.users.size(); ++i) { + TLRPC.User user = importers.users.get(i); + users.put(user.id, user); + } + if (isEmptyOffset) { + adapter.setItems(importers.importers); + } else { + adapter.appendItems(importers.importers); + } + if (TextUtils.isEmpty(lastQuery)) { + allImporters.clear(); + allImporters.addAll(importers.importers); + if (showSearchMenu) { + fragment.getActionBar().createMenu().getItem(MemberRequestsActivity.searchMenuItem).setVisibility(allImporters.isEmpty() ? GONE : VISIBLE); + } + } + onImportersChanged(lastQuery, fromCache, false); + hasMore = currentImporters.size() < importers.count; + } + + @Override + public void onAddClicked(TLRPC.TL_chatInviteImporter importer) { + hideChatJoinRequest(importer, true); + } + + @Override + public void onDismissClicked(TLRPC.TL_chatInviteImporter importer) { + hideChatJoinRequest(importer, false); + } + + public void setAdapterItemsEnabled(boolean adapterItemsEnabled) { + if (recyclerView != null) { + int position = adapter.extraFirstHolders(); + if (0 <= position && position < recyclerView.getChildCount()) { + recyclerView.getChildAt(position).setEnabled(adapterItemsEnabled); + } + } + } + + protected void onImportersChanged(String query, boolean fromCache, boolean fromHide) { + boolean isListVisible; + if (TextUtils.isEmpty(query)) { + isListVisible = !allImporters.isEmpty() || fromCache; + if (emptyView != null) { + emptyView.setVisibility(isListVisible ? INVISIBLE : VISIBLE); + } + if (searchEmptyView != null) { + searchEmptyView.setVisibility(INVISIBLE); + } + } else { + isListVisible = !currentImporters.isEmpty() || fromCache; + if (emptyView != null) { + emptyView.setVisibility(INVISIBLE); + } + if (searchEmptyView != null) { + searchEmptyView.setVisibility(isListVisible ? INVISIBLE : VISIBLE); + } + } + setViewVisible(recyclerView, isListVisible, true); + if (allImporters.isEmpty()) { + if (emptyView != null) { + emptyView.setVisibility(VISIBLE); + } + if (searchEmptyView != null) { + searchEmptyView.setVisibility(INVISIBLE); + } + setViewVisible(loadingView, false, false); + if (isSearchExpanded && showSearchMenu) { + fragment.getActionBar().createMenu().closeSearchField(true); + } + } + } + + protected boolean hasAllImporters() { + return !allImporters.isEmpty(); + } + + private void hideChatJoinRequest(TLRPC.TL_chatInviteImporter importer, boolean isApproved) { + TLRPC.User user = users.get(importer.user_id); + if (user == null) { + return; + } + TLRPC.TL_messages_hideChatJoinRequest req = new TLRPC.TL_messages_hideChatJoinRequest(); + req.approved = isApproved; + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(-chatId); + req.user_id = MessagesController.getInstance(currentAccount).getInputUser(user); + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + if (error == null) { + TLRPC.TL_updates updates = (TLRPC.TL_updates) response; + MessagesController.getInstance(currentAccount).processUpdates(updates, false); + } + AndroidUtilities.runOnUIThread(() -> { + if (error == null) { + TLRPC.TL_updates updates = (TLRPC.TL_updates) response; + if (!updates.chats.isEmpty()) { + TLRPC.Chat chat = updates.chats.get(0); + MessagesController.getInstance(currentAccount).loadFullChat(chat.id, 0, true); + } + for (int i = 0; i < allImporters.size(); ++i) { + if (allImporters.get(i).user_id == importer.user_id) { + allImporters.remove(i); + break; + } + } + adapter.removeItem(importer); + onImportersChanged(query, false, true); + if (isApproved) { + Bulletin.MultiLineLayout layout = new Bulletin.MultiLineLayout(fragment.getParentActivity(), fragment.getResourceProvider()); + layout.imageView.setRoundRadius(AndroidUtilities.dp(15)); + layout.imageView.setForUserOrChat(user, new AvatarDrawable(user)); + String userName = UserObject.getFirstName(user); + String message = isChannel + ? LocaleController.formatString("HasBeenAddedToChannel", R.string.HasBeenAddedToChannel, userName) + : LocaleController.formatString("HasBeenAddedToGroup", R.string.HasBeenAddedToGroup, userName); + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(message); + int start = message.indexOf(userName); + stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), start, start + userName.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); + layout.textView.setText(stringBuilder); + if (allImporters.isEmpty()) { + Bulletin.make(fragment, layout, Bulletin.DURATION_LONG).show(); + } else { + Bulletin.make(layoutContainer, layout, Bulletin.DURATION_LONG).show(); + } + } + ActionBarMenu menu = fragment.getActionBar().createMenu(); + if (TextUtils.isEmpty(query) && showSearchMenu) { + menu.getItem(MemberRequestsActivity.searchMenuItem).setVisibility(allImporters.isEmpty() ? GONE : VISIBLE); + } + } else { + AlertsCreator.processError(currentAccount, error, fragment, req); + } + }); + }); + } + + private void hidePreview() { + previewDialog.dismiss(); + importer = null; + } + + private void setViewVisible(View view, boolean isVisible, boolean isAnimated) { + if (view == null) { + return; + } + boolean isCurrentVisible = view.getVisibility() == VISIBLE; + float targetAlpha = isVisible ? 1f : 0f; + if (isVisible == isCurrentVisible && targetAlpha == view.getAlpha()) { + return; + } + if (isAnimated) { + if (isVisible) { + view.setAlpha(0f); + } + view.setVisibility(VISIBLE); + view.animate() + .alpha(targetAlpha) + .setDuration(150) + .start(); + } else { + view.setVisibility(isVisible ? VISIBLE : INVISIBLE); + } + } + + private final RecyclerView.OnScrollListener listScrollListener = new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); + if (hasMore && !isLoading && layoutManager != null) { + int lastPosition = layoutManager.findLastVisibleItemPosition(); + if (adapter.getItemCount() - lastPosition < 10) { + loadMembers(); + } + } + } + }; + + + private class Adapter extends RecyclerListView.SelectionAdapter { + + @NonNull + @Override + public RecyclerListView.Holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view; + switch (viewType) { + default: + case 0: + MemberRequestCell cell = new MemberRequestCell(parent.getContext(), MemberRequestsDelegate.this, isChannel); + cell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite, fragment.getResourceProvider())); + view = cell; + break; + case 1: + view = new View(parent.getContext()); + view.setBackground(Theme.getThemedDrawable(parent.getContext(), R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + break; + case 2: + view = new View(parent.getContext()) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(52), MeasureSpec.EXACTLY)); + } + }; + break; + case 3: + view = new View(parent.getContext()); + break; + } + return new RecyclerListView.Holder(view); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if (holder.getItemViewType() == 0) { + MemberRequestCell cell = (MemberRequestCell) holder.itemView; + position -= extraFirstHolders(); + cell.setData(users, currentImporters.get(position), position != currentImporters.size() - 1); + } else if (holder.getItemViewType() == 2) { + holder.itemView.requestLayout(); + } + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return holder.getItemViewType() == 0; + } + + @Override + public int getItemCount() { + return extraFirstHolders() + currentImporters.size() + extraLastHolders(); + } + + @Override + public int getItemViewType(int position) { + if (isShowLastItemDivider) { + if (position == currentImporters.size() && !currentImporters.isEmpty()) { + return 1; + } + } else { + if (position == 0) { + return 2; + } else if (position == getItemCount() - 1) { + return 3; + } + } + return 0; + } + + @SuppressLint("NotifyDataSetChanged") + public void setItems(List newItems) { + currentImporters.clear(); + currentImporters.addAll(newItems); + notifyDataSetChanged(); + } + + public void appendItems(List newItems) { + currentImporters.addAll(newItems); + if (currentImporters.size() > newItems.size()) { + notifyItemChanged(currentImporters.size() - newItems.size() - 1); + } + notifyItemRangeInserted(currentImporters.size() - newItems.size(), newItems.size()); + } + + public void removeItem(TLRPC.TL_chatInviteImporter item) { + int position = -1; + for (int i = 0; i < currentImporters.size(); ++i) { + if (currentImporters.get(i).user_id == item.user_id) { + position = i; + break; + } + } + if (position >= 0) { + currentImporters.remove(position); + notifyItemRemoved(position + extraFirstHolders()); + if (currentImporters.isEmpty()) { + notifyItemRemoved(1); + } + } + } + + private int extraFirstHolders() { + return isShowLastItemDivider ? 0 : 1; + } + + private int extraLastHolders() { + return isShowLastItemDivider && currentImporters.isEmpty() ? 0 : 1; + } + } + + + private class PreviewDialog extends Dialog { + + private final int shadowPaddingTop; + private final int shadowPaddingLeft; + private final Drawable pagerShadowDrawable = getContext().getResources().getDrawable(R.drawable.popup_fixed_alert2).mutate(); + private final TextView nameText = new TextView(getContext()); + private final TextView bioText = new TextView(getContext()); + private final ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout; + private final ProfileGalleryView viewPager; + private final AvatarPreviewPagerIndicator pagerIndicator; + + private TLRPC.TL_chatInviteImporter importer; + private ValueAnimator animator; + private BackupImageView imageView; + private BitmapDrawable backgroundDrawable; + private float animationProgress; + + public PreviewDialog(@NonNull Context context, @NonNull RecyclerListView parentListView, @NonNull Theme.ResourcesProvider resourcesProvider, boolean isChannel) { + super(context, R.style.TransparentDialog2); + setCancelable(true); + contentView.setVisibility(INVISIBLE); + + int backgroundColor = Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground, fragment.getResourceProvider()); + pagerShadowDrawable.setColorFilter(new PorterDuffColorFilter(backgroundColor, PorterDuff.Mode.MULTIPLY)); + pagerShadowDrawable.setCallback(contentView); + android.graphics.Rect paddingRect = new android.graphics.Rect(); + pagerShadowDrawable.getPadding(paddingRect); + shadowPaddingTop = paddingRect.top; + shadowPaddingLeft = paddingRect.left; + + popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context, resourcesProvider); + popupLayout.setBackgroundColor(backgroundColor); + contentView.addView(popupLayout); + + pagerIndicator = new AvatarPreviewPagerIndicator(getContext()) { + @Override + protected void onDraw(Canvas canvas) { + if (profileGalleryView.getRealCount() > 1) { + super.onDraw(canvas); + } + } + }; + + viewPager = new ProfileGalleryView(context, fragment.getActionBar(), parentListView, pagerIndicator); + viewPager.setCreateThumbFromParent(true); + contentView.addView(viewPager); + + pagerIndicator.setProfileGalleryView(viewPager); + contentView.addView(pagerIndicator); + + nameText.setMaxLines(1); + nameText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, fragment.getResourceProvider())); + nameText.setTextSize(16); + nameText.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + contentView.addView(nameText); + + bioText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText, fragment.getResourceProvider())); + bioText.setTextSize(14); + contentView.addView(bioText); + + ActionBarMenuSubItem addCell = new ActionBarMenuSubItem(context, true, false); + addCell.setColors(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem, resourcesProvider), Theme.getColor(Theme.key_actionBarDefaultSubmenuItemIcon, resourcesProvider)); + addCell.setSelectorColor(Theme.getColor(Theme.key_dialogButtonSelector, resourcesProvider)); + addCell.setTextAndIcon(isChannel ? LocaleController.getString("AddToChannel", R.string.AddToChannel) : LocaleController.getString("AddToGroup", R.string.AddToGroup), R.drawable.actions_requests); + addCell.setOnClickListener((v) -> { + if (importer != null) { + onAddClicked(importer); + } + hidePreview(); + }); + popupLayout.addView(addCell); + + ActionBarMenuSubItem sendMsgCell = new ActionBarMenuSubItem(context, false, false); + sendMsgCell.setColors(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem, resourcesProvider), Theme.getColor(Theme.key_actionBarDefaultSubmenuItemIcon, resourcesProvider)); + sendMsgCell.setSelectorColor(Theme.getColor(Theme.key_dialogButtonSelector, resourcesProvider)); + sendMsgCell.setTextAndIcon(LocaleController.getString("SendMessage", R.string.SendMessage), R.drawable.msg_msgbubble3); + sendMsgCell.setOnClickListener((v) -> { + if (importer != null) { + isNeedRestoreList = true; + super.dismiss(); + fragment.dismissCurrentDialog(); + Bundle args = new Bundle(); + args.putLong("user_id", importer.user_id); + ChatActivity chatActivity = new ChatActivity(args); + fragment.presentFragment(chatActivity); + } + }); + popupLayout.addView(sendMsgCell); + + ActionBarMenuSubItem dismissCell = new ActionBarMenuSubItem(context, false, true); + dismissCell.setColors(Theme.getColor(Theme.key_dialogTextRed2, resourcesProvider), Theme.getColor(Theme.key_dialogRedIcon, resourcesProvider)); + dismissCell.setSelectorColor(Theme.getColor(Theme.key_dialogButtonSelector, resourcesProvider)); + dismissCell.setTextAndIcon(LocaleController.getString("DismissRequest", R.string.DismissRequest), R.drawable.actions_remove_user); + dismissCell.setOnClickListener((v) -> { + if (importer != null) { + onDismissClicked(importer); + } + hidePreview(); + }); + popupLayout.addView(dismissCell); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setWindowAnimations(R.style.DialogNoAnimation); + setContentView(contentView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.width = ViewGroup.LayoutParams.MATCH_PARENT; + params.height = ViewGroup.LayoutParams.MATCH_PARENT; + params.dimAmount = 0; + params.flags &= ~WindowManager.LayoutParams.FLAG_DIM_BEHIND; + params.gravity = Gravity.TOP | Gravity.LEFT; + if (Build.VERSION.SDK_INT >= 21) { + params.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | + WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | + WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + } + if (Build.VERSION.SDK_INT >= 28) { + params.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + } + getWindow().setAttributes(params); + } + + public void setImporter(TLRPC.TL_chatInviteImporter importer, BackupImageView imageView) { + this.importer = importer; + this.imageView = imageView; + viewPager.setParentAvatarImage(imageView); + viewPager.setData(importer.user_id, true); + TLRPC.User user = users.get(importer.user_id); + nameText.setText(UserObject.getUserName(user)); + bioText.setText(importer.about); + bioText.setVisibility(TextUtils.isEmpty(importer.about) ? GONE : VISIBLE); + contentView.requestLayout(); + } + + @Override + public void show() { + super.show(); + AndroidUtilities.runOnUIThread(() -> { + updateBackgroundBitmap(); + runAnimation(true); + }, 80); + } + + @Override + public void dismiss() { + runAnimation(false); + } + + private void runAnimation(boolean show) { + if (animator != null) { + animator.cancel(); + } + + int[] location = new int[2]; + imageView.getLocationOnScreen(location); + final float fromScale = imageView.getWidth() * 1f / getContentWidth(); + final float fromRadius = imageView.getWidth() / 2f / fromScale; + final float xFrom = location[0] - (viewPager.getLeft() + (int)((getContentWidth() * (1f - fromScale) / 2f))); + final float yFrom = location[1] - (viewPager.getTop() + (int)((getContentHeight() * (1f - fromScale) / 2f))); + + int popupLayoutTranslation = -popupLayout.getTop() / 2; + animator = ValueAnimator.ofFloat(show ? 0f : 1f, show ? 1f : 0f); + animator.addUpdateListener(animation -> { + animationProgress = (float) animation.getAnimatedValue(); + float scale = fromScale + (1f - fromScale) * animationProgress; + contentView.setScaleX(scale); + contentView.setScaleY(scale); + contentView.setTranslationX(xFrom * (1f - animationProgress)); + contentView.setTranslationY(yFrom * (1f - animationProgress)); + + int roundRadius = (int) (fromRadius * (1f - animationProgress)); + viewPager.setRoundRadius(roundRadius, roundRadius); + + float alpha = MathUtils.clamp(2 * animationProgress - 1f, 0f, 1f); + pagerShadowDrawable.setAlpha((int)(255 * alpha)); + nameText.setAlpha(alpha); + bioText.setAlpha(alpha); + popupLayout.setTranslationY(popupLayoutTranslation * (1f - animationProgress)); + popupLayout.setAlpha(alpha); + if (backgroundDrawable != null) { + backgroundDrawable.setAlpha((int)(255 * animationProgress)); + } + pagerIndicator.setAlpha(alpha); + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + contentView.setVisibility(VISIBLE); + if (show) { + contentView.setScaleX(fromScale); + contentView.setScaleY(fromScale); + } + } + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + if (!show) { + PreviewDialog.super.dismiss(); + } + } + }); + animator.setDuration(220); + animator.setInterpolator(CubicBezierInterpolator.DEFAULT); + animator.start(); + } + + private Bitmap getBlurredBitmap() { + float factor = 6.0f; + int width = (int) ((contentView.getMeasuredWidth()) / factor); + int height = (int) ((contentView.getMeasuredHeight()) / factor); + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + canvas.scale(1f / factor, 1f / factor); + + canvas.save(); + ((LaunchActivity) fragment.getParentActivity()).getActionBarLayout().draw(canvas); + canvas.drawColor(ColorUtils.setAlphaComponent(Color.BLACK, (int) (255 * 0.3f))); + Dialog dialog = fragment.getVisibleDialog(); + if (dialog != null) { + dialog.getWindow().getDecorView().draw(canvas); + } + Utilities.stackBlurBitmap(bitmap, Math.max(7, Math.max(width, height) / 180)); + + return bitmap; + } + + private void updateBackgroundBitmap() { + int oldAlpha = 255; + if (backgroundDrawable != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + oldAlpha = backgroundDrawable.getAlpha(); + } + backgroundDrawable = new BitmapDrawable(getContext().getResources(), getBlurredBitmap()); + backgroundDrawable.setAlpha(oldAlpha); + getWindow().setBackgroundDrawable(backgroundDrawable); + } + + private int getContentHeight() { + int height = viewPager.getMeasuredHeight(); + height += AndroidUtilities.dp(12) + nameText.getMeasuredHeight(); + if (bioText.getVisibility() != GONE) { + height += AndroidUtilities.dp(4) + bioText.getMeasuredHeight(); + } + height += AndroidUtilities.dp(12) + popupLayout.getMeasuredHeight(); + return height; + } + + private int getContentWidth() { + return viewPager.getMeasuredWidth(); + } + + private final ViewGroup contentView = new ViewGroup(getContext()) { + + private final GestureDetector gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onDown(MotionEvent e) { + return true; + } + @Override + public boolean onSingleTapUp(MotionEvent e) { + boolean isTouchInsideContent = pagerShadowDrawable.getBounds().contains((int) e.getX(), (int) e.getY()) || + popupLayout.getLeft() < e.getX() && e.getX() < popupLayout.getRight() && + popupLayout.getTop() < e.getY() && e.getY() < popupLayout.getBottom(); + if (!isTouchInsideContent) { + dismiss(); + } + return super.onSingleTapUp(e); + } + }); + private final Path clipPath = new Path(); + private final RectF rectF = new RectF(); + private boolean firstSizeChange = true; + + @SuppressLint("ClickableViewAccessibility") + @Override + public boolean onTouchEvent(MotionEvent event) { + return gestureDetector.onTouchEvent(event); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setWillNotDraw(false); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int minSize = Math.min(getMeasuredWidth(), getMeasuredHeight()); + int pagerSize = Math.min(minSize, (int)(getMeasuredHeight() * 0.66)) - AndroidUtilities.dp(12) * 2; + int pagerSpec = MeasureSpec.makeMeasureSpec(pagerSize, MeasureSpec.AT_MOST); + viewPager.measure(pagerSpec, pagerSpec); + pagerIndicator.measure(pagerSpec, pagerSpec); + int textWidthSpec = MeasureSpec.makeMeasureSpec(pagerSize - AndroidUtilities.dp(16) * 2, MeasureSpec.EXACTLY); + nameText.measure(textWidthSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + bioText.measure(textWidthSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + popupLayout.measure(View.MeasureSpec.makeMeasureSpec(viewPager.getMeasuredWidth() + shadowPaddingLeft * 2, MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int top = (getHeight() - getContentHeight()) / 2; + int left = (getWidth() - viewPager.getMeasuredWidth()) / 2; + viewPager.layout(left, top, left + viewPager.getMeasuredWidth(), top + viewPager.getMeasuredHeight()); + pagerIndicator.layout(viewPager.getLeft(), viewPager.getTop(), viewPager.getRight(), viewPager.getTop() + pagerIndicator.getMeasuredHeight()); + top += viewPager.getMeasuredHeight() + AndroidUtilities.dp(12); + nameText.layout(viewPager.getLeft() + AndroidUtilities.dp(16), top, viewPager.getRight() - AndroidUtilities.dp(16), top + nameText.getMeasuredHeight()); + top += nameText.getMeasuredHeight(); + if (bioText.getVisibility() != GONE) { + top += AndroidUtilities.dp(4); + bioText.layout(nameText.getLeft(), top, nameText.getRight(), top + bioText.getMeasuredHeight()); + top += bioText.getMeasuredHeight(); + } + top += AndroidUtilities.dp(12); + pagerShadowDrawable.setBounds( + viewPager.getLeft() - shadowPaddingLeft, + viewPager.getTop() - shadowPaddingTop, + viewPager.getRight() + shadowPaddingLeft, + top + shadowPaddingTop + ); + + left = viewPager.getRight() - popupLayout.getMeasuredWidth() + shadowPaddingLeft; + popupLayout.layout(left, top, viewPager.getRight() + shadowPaddingLeft, top + popupLayout.getMeasuredHeight()); + popupLayout.setVisibility(popupLayout.getBottom() < b ? VISIBLE : GONE); + + int radius = AndroidUtilities.dp(6); + rectF.set(viewPager.getLeft(), viewPager.getTop(), viewPager.getRight(), viewPager.getTop() + radius * 2); + clipPath.reset(); + clipPath.addRoundRect(rectF, radius, radius, Path.Direction.CW); + rectF.set(l, viewPager.getTop() + radius, r, b); + clipPath.addRect(rectF, Path.Direction.CW); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + boolean isLandscape = AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y; + if (isLandscape) { + PreviewDialog.super.dismiss(); + } + if (w != oldw && h != oldh) { + if (!firstSizeChange) { + updateBackgroundBitmap(); + } + firstSizeChange = false; + } + } + + @Override + protected void dispatchDraw(Canvas canvas) { + canvas.save(); + canvas.clipPath(clipPath); + super.dispatchDraw(canvas); + canvas.restore(); + } + + @Override + protected void onDraw(Canvas canvas) { +// if (animationProgress < 1f) { +// canvas.save(); +// } + pagerShadowDrawable.draw(canvas); +// if (animationProgress < 1f) { +// canvas.restore(); +// } + super.onDraw(canvas); + } + + @Override + protected boolean verifyDrawable(@NonNull Drawable who) { + return who == pagerShadowDrawable || super.verifyDrawable(who); + } + }; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/EmojiAnimationsOverlay.java b/TMessagesProj/src/main/java/org/telegram/ui/EmojiAnimationsOverlay.java index 071c675f44e..af4e555051c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/EmojiAnimationsOverlay.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/EmojiAnimationsOverlay.java @@ -21,6 +21,7 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.UserConfig; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Cells.ChatMessageCell; @@ -264,7 +265,7 @@ public void draw(Canvas canvas) { } public void onTapItem(ChatMessageCell view, ChatActivity chatActivity) { - if (chatActivity.currentUser == null || chatActivity.isSecretChat()) { + if (chatActivity.currentUser == null || chatActivity.isSecretChat() || view.getMessageObject() == null || view.getMessageObject().getId() < 0) { return; } boolean show = showAnimationForCell(view, -1, true, false); @@ -277,7 +278,7 @@ public void onTapItem(ChatMessageCell view, ChatActivity chatActivity) { if (printingType != null && printingType == 5) { canShowHint = false; } - if (canShowHint && hintRunnable == null && show && (Bulletin.getVisibleBulletin() == null || !Bulletin.getVisibleBulletin().isShowing()) && SharedConfig.emojiInteractionsHintCount > 0) { + if (canShowHint && hintRunnable == null && show && (Bulletin.getVisibleBulletin() == null || !Bulletin.getVisibleBulletin().isShowing()) && SharedConfig.emojiInteractionsHintCount > 0 && UserConfig.getInstance(currentAccount).getClientUserId() != chatActivity.currentUser.id) { SharedConfig.updateEmojiInteractionsHintCount(SharedConfig.emojiInteractionsHintCount - 1); TLRPC.Document document = MediaDataController.getInstance(currentAccount).getEmojiAnimatedSticker(view.getMessageObject().getStickerEmoji()); StickerSetBulletinLayout layout = new StickerSetBulletinLayout(chatActivity.getParentActivity(), null, StickerSetBulletinLayout.TYPE_EMPTY, document, chatActivity.getResourceProvider()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FilterUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/FilterUsersActivity.java index cbba8dac21e..78f858c0782 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FilterUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FilterUsersActivity.java @@ -620,7 +620,7 @@ public void afterTextChanged(Editable editable) { LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false); listView = new RecyclerListView(context); - listView.setFastScrollEnabled(); + listView.setFastScrollEnabled(RecyclerListView.FastScroll.LETTER_TYPE); listView.setEmptyView(emptyView); listView.setAdapter(adapter = new GroupCreateAdapter(context)); listView.setLayoutManager(linearLayoutManager); @@ -1223,8 +1223,9 @@ public int getItemViewType(int position) { } @Override - public int getPositionForScrollProgress(float progress) { - return (int) (getItemCount() * progress); + public void getPositionForScrollProgress(RecyclerListView listView, float progress, int[] position) { + position[0] = (int) (getItemCount() * progress); + position[1] = 0; } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java b/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java index 35d05c1e334..e2a062cb172 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java @@ -217,11 +217,11 @@ public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObj if (view instanceof SharedDocumentCell) { top += AndroidUtilities.dp(8f); } - final int topOffset = top - object.viewY; + final int topOffset = (int) (top - object.viewY); if (topOffset > view.getHeight()) { listView.scrollBy(0, -(topOffset + pinnedHeader.getHeight())); } else { - int bottomOffset = object.viewY - listView.getHeight(); + int bottomOffset = (int) (object.viewY - listView.getHeight()); if (view instanceof SharedDocumentCell) { bottomOffset -= AndroidUtilities.dp(8f); } @@ -1217,8 +1217,9 @@ public String getLetter(int position) { } @Override - public int getPositionForScrollProgress(float progress) { - return 0; + public void getPositionForScrollProgress(RecyclerListView listView, float progress, int[] position) { + position[0] = 0; + position[1] = 0; } } @@ -1410,8 +1411,9 @@ public String getLetter(int position) { } @Override - public int getPositionForScrollProgress(float progress) { - return 0; + public void getPositionForScrollProgress(RecyclerListView listView, float progress, int[] position) { + position[0] = 0; + position[1] = 0; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java index cae18e2a373..238f64e2845 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java @@ -5008,7 +5008,7 @@ public void requestLayout() { } else { decorView = containerView; } - pinchToZoomHelper = new PinchToZoomHelper(decorView) { + pinchToZoomHelper = new PinchToZoomHelper(decorView, containerView) { @Override protected void invalidateViews() { super.invalidateViews(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java index d6120587375..7e6293a5d9f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java @@ -668,7 +668,7 @@ public void afterTextChanged(Editable editable) { LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false); listView = new RecyclerListView(context); - listView.setFastScrollEnabled(); + listView.setFastScrollEnabled(RecyclerListView.FastScroll.LETTER_TYPE); listView.setEmptyView(emptyView); listView.setAdapter(adapter = new GroupCreateAdapter(context)); listView.setLayoutManager(linearLayoutManager); @@ -1443,8 +1443,9 @@ public int getItemViewType(int position) { } @Override - public int getPositionForScrollProgress(float progress) { - return (int) (getItemCount() * progress); + public void getPositionForScrollProgress(RecyclerListView listView, float progress, int[] position) { + position[0] = (int) (getItemCount() * progress); + position[1] = 0; } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 9ce64534042..cdd061243df 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -1396,6 +1396,9 @@ private boolean handleIntent(Intent intent, boolean isNew, boolean restore, bool } if (exportingChatUri == null) { path = AndroidUtilities.getPath(uri); + if (!BuildVars.NO_SCOPED_STORAGE) { + path = MediaController.copyFileToCache(uri, "file"); + } if (path != null) { if (path.startsWith("file:")) { path = path.replace("file://", ""); @@ -3276,13 +3279,17 @@ public void onError() { int notFound = 2; if (response instanceof TLRPC.TL_theme) { TLRPC.TL_theme t = (TLRPC.TL_theme) response; - if (t.settings != null) { - String key = Theme.getBaseThemeKey(t.settings); + TLRPC.ThemeSettings settings = null; + if (t.settings.size() > 0) { + settings = t.settings.get(0); + } + if (settings != null) { + String key = Theme.getBaseThemeKey(settings); Theme.ThemeInfo info = Theme.getTheme(key); if (info != null) { TLRPC.TL_wallPaper object; - if (t.settings.wallpaper instanceof TLRPC.TL_wallPaper) { - object = (TLRPC.TL_wallPaper) t.settings.wallpaper; + if (settings.wallpaper instanceof TLRPC.TL_wallPaper) { + object = (TLRPC.TL_wallPaper) settings.wallpaper; File path = FileLoader.getPathToAttach(object.document, true); if (!path.exists()) { loadingThemeProgressDialog = progressDialog; @@ -4563,6 +4570,8 @@ public void didReceivedNotification(int id, final int account, Object... args) { themeSwitchImageView.setVisibility(View.VISIBLE); themeSwitchSunDrawable = darkThemeView.getAnimatedDrawable(); float finalRadius = (float) Math.max(Math.sqrt((w - pos[0]) * (w - pos[0]) + (h - pos[1]) * (h - pos[1])), Math.sqrt(pos[0] * pos[0] + (h - pos[1]) * (h - pos[1]))); + float finalRadius2 = (float) Math.max(Math.sqrt((w - pos[0]) * (w - pos[0]) + pos[1] * pos[1]), Math.sqrt(pos[0] * pos[0] + pos[1] * pos[1])); + finalRadius = Math.max(finalRadius, finalRadius2); Animator anim = ViewAnimationUtils.createCircularReveal(toDark ? drawerLayoutContainer : themeSwitchImageView, pos[0], pos[1], toDark ? 0 : finalRadius, toDark ? finalRadius : 0); anim.setDuration(400); anim.setInterpolator(Easings.easeInOutQuad); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LinkEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LinkEditActivity.java index 78ece24e6e6..4cff8d255b8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LinkEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LinkEditActivity.java @@ -1,10 +1,15 @@ package org.telegram.ui; +import android.animation.LayoutTransition; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; import android.os.Vibrator; import android.text.Editable; +import android.text.InputFilter; import android.text.InputType; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; import android.text.TextWatcher; import android.text.method.DigitsKeyListener; import android.util.TypedValue; @@ -17,6 +22,7 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; import org.telegram.tgnet.TLObject; @@ -28,6 +34,7 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.HeaderCell; +import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.Components.AlertsCreator; @@ -48,6 +55,7 @@ public class LinkEditActivity extends BaseFragment { private SlideChooseView timeChooseView; TLRPC.TL_chatInviteExported inviteToEdit; + private TextCheckCell approveCell; private TextView timeEditText; private HeaderCell timeHeaderCell; private TextInfoPrivacyCell divider; @@ -56,9 +64,14 @@ public class LinkEditActivity extends BaseFragment { private TextInfoPrivacyCell dividerUses; private TextView buttonTextView; private TextSettingsCell revokeLink; - private boolean ignoreSet; private ScrollView scrollView; + private EditText nameEditText; + private TextInfoPrivacyCell dividerName; + private TextView createTextView; + + private boolean ignoreSet; private boolean finished; + private boolean firstLayout = true; public LinkEditActivity(int type, long chatId) { this.type = type; @@ -74,7 +87,9 @@ public LinkEditActivity(int type, long chatId) { AlertDialog progressDialog; boolean loading; + boolean scrollToStart; boolean scrollToEnd; + int currentInviteDate; @Override public View createView(Context context) { @@ -95,12 +110,28 @@ public void onItemClick(int id) { } }); + createTextView = new TextView(context); + createTextView.setEllipsize(TextUtils.TruncateAt.END); + createTextView.setGravity(Gravity.CENTER_VERTICAL); + createTextView.setOnClickListener(this::onCreateClicked); + createTextView.setSingleLine(); + if (type == CREATE_TYPE) { + createTextView.setText(LocaleController.getString("CreateLinkHeader", R.string.CreateLinkHeader)); + } else if (type == EDIT_TYPE) { + createTextView.setText(LocaleController.getString("SaveLinkHeader", R.string.SaveLinkHeader)); + } + createTextView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultTitle)); + createTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14f); + createTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + createTextView.setPadding(AndroidUtilities.dp(18), AndroidUtilities.dp(8), AndroidUtilities.dp(18), AndroidUtilities.dp(8)); + int topSpace = actionBar.getOccupyStatusBar() ? (AndroidUtilities.statusBarHeight / AndroidUtilities.dp(2)) : 0; + actionBar.addView(createTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.END | Gravity.CENTER_VERTICAL, 0, topSpace, 0, 0)); + scrollView = new ScrollView(context); SizeNotifierFrameLayout contentView = new SizeNotifierFrameLayout(context) { int oldKeyboardHeight; - @Override protected AdjustPanLayoutHelper createAdjustPanLayoutHelper() { AdjustPanLayoutHelper panLayoutHelper = new AdjustPanLayoutHelper(this) { @@ -149,13 +180,18 @@ protected void onDetachedFromWindow() { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); measureKeyboardHeight(); - if (oldKeyboardHeight != keyboardHeight && keyboardHeight > AndroidUtilities.dp(20)) { + boolean isNeedScrollToEnd = usesEditText.isCursorVisible() || nameEditText.isCursorVisible(); + if (oldKeyboardHeight != keyboardHeight && keyboardHeight > AndroidUtilities.dp(20) && isNeedScrollToEnd) { scrollToEnd = true; invalidate(); + } else if (scrollView.getScrollY() == 0 && !isNeedScrollToEnd) { + scrollToStart = true; + invalidate(); } - if (keyboardHeight < AndroidUtilities.dp(20)) { + if (keyboardHeight != 0 && keyboardHeight < AndroidUtilities.dp(20)) { usesEditText.clearFocus(); + nameEditText.clearFocus(); } oldKeyboardHeight = keyboardHeight; @@ -179,6 +215,9 @@ protected void dispatchDraw(Canvas canvas) { if (scrollToEnd) { scrollToEnd = false; scrollView.smoothScrollTo(0, Math.max(0, scrollView.getChildAt(0).getMeasuredHeight() - scrollView.getMeasuredHeight())); + } else if (scrollToStart) { + scrollToStart = false; + scrollView.smoothScrollTo(0, 0); } } }; @@ -187,8 +226,6 @@ protected void dispatchDraw(Canvas canvas) { LinearLayout linearLayout = new LinearLayout(context) { - boolean firstLayout = true; - @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); @@ -196,7 +233,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int h = MeasureSpec.getSize(heightMeasureSpec); for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); - if (child != buttonTextView) { + if (child != buttonTextView && child.getVisibility() != View.GONE) { elementsHeight += child.getMeasuredHeight(); } } @@ -226,6 +263,9 @@ protected void dispatchDraw(Canvas canvas) { firstLayout = false; } }; + LayoutTransition transition = new LayoutTransition(); + transition.setDuration(100); + linearLayout.setLayoutTransition(transition); linearLayout.setOrientation(LinearLayout.VERTICAL); scrollView.addView(linearLayout); @@ -242,6 +282,37 @@ protected void dispatchDraw(Canvas canvas) { buttonTextView.setText(LocaleController.getString("SaveLink", R.string.SaveLink)); } + approveCell = new TextCheckCell(context) { + @Override + protected void onDraw(Canvas canvas) { + canvas.save(); + canvas.clipRect(0, 0, getWidth(), getHeight()); + super.onDraw(canvas); + canvas.restore(); + } + }; + approveCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundUnchecked)); + approveCell.setColors(Theme.key_windowBackgroundCheckText, Theme.key_switchTrackBlue, Theme.key_switchTrackBlueChecked, Theme.key_switchTrackBlueThumb, Theme.key_switchTrackBlueThumbChecked); + approveCell.setDrawCheckRipple(true); + approveCell.setHeight(56); + approveCell.setTag(Theme.key_windowBackgroundUnchecked); + approveCell.setTextAndCheck(LocaleController.getString("ApproveNewMembers", R.string.ApproveNewMembers), false, false); + approveCell.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + approveCell.setOnClickListener(view -> { + TextCheckCell cell = (TextCheckCell) view; + boolean newIsChecked = !cell.isChecked(); + cell.setBackgroundColorAnimated(newIsChecked, Theme.getColor(newIsChecked ? Theme.key_windowBackgroundChecked : Theme.key_windowBackgroundUnchecked)); + cell.setChecked(newIsChecked); + setUsesVisible(!newIsChecked); + firstLayout = true; + }); + linearLayout.addView(approveCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 56)); + + TextInfoPrivacyCell hintCell = new TextInfoPrivacyCell(context); + hintCell.setBackground(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); + hintCell.setText(LocaleController.getString("ApproveNewMembersDescription", R.string.ApproveNewMembersDescription)); + linearLayout.addView(hintCell); + timeHeaderCell = new HeaderCell(context); timeHeaderCell.setText(LocaleController.getString("LimitByPeriod", R.string.LimitByPeriod)); linearLayout.addView(timeHeaderCell); @@ -339,9 +410,51 @@ public void afterTextChanged(Editable editable) { dividerUses = new TextInfoPrivacyCell(context); dividerUses.setText(LocaleController.getString("UsesLimitHelp", R.string.UsesLimitHelp)); - linearLayout.addView(dividerUses); + nameEditText = new EditText(context) { + @SuppressLint("ClickableViewAccessibility") + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_UP) { + setCursorVisible(true); + } + return super.onTouchEvent(event); + } + }; + nameEditText.addTextChangedListener(new TextWatcher() { + @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } + @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } + @Override + public void afterTextChanged(Editable s) { + SpannableStringBuilder builder = new SpannableStringBuilder(s); + Emoji.replaceEmoji(builder, nameEditText.getPaint().getFontMetricsInt(), (int) nameEditText.getPaint().getTextSize(), false); + int selection = nameEditText.getSelectionStart(); + nameEditText.removeTextChangedListener(this); + nameEditText.setText(builder); + if (selection >= 0) { + nameEditText.setSelection(selection); + } + nameEditText.addTextChangedListener(this); + } + }); + nameEditText.setCursorVisible(false); + nameEditText.setFilters(new InputFilter[]{ new InputFilter.LengthFilter(32) }); + nameEditText.setGravity(Gravity.CENTER_VERTICAL); + nameEditText.setHint(LocaleController.getString("LinkNameHint", R.string.LinkNameHint)); + nameEditText.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + nameEditText.setLines(1); + nameEditText.setPadding(AndroidUtilities.dp(22), 0, AndroidUtilities.dp(22), 0); + nameEditText.setSingleLine(); + nameEditText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + nameEditText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + linearLayout.addView(nameEditText, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 50)); + + dividerName = new TextInfoPrivacyCell(context); + dividerName.setBackground(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + dividerName.setText(LocaleController.getString("LinkNameHelp", R.string.LinkNameHelp)); + linearLayout.addView(dividerName); + if (type == EDIT_TYPE) { revokeLink = new TextSettingsCell(context); revokeLink.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); @@ -371,149 +484,184 @@ public void afterTextChanged(Editable editable) { usesHeaderCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); usesChooseView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); usesEditText.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + nameEditText.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); contentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); - buttonTextView.setOnClickListener(view -> { - if (loading) { - return; + buttonTextView.setOnClickListener(this::onCreateClicked); + buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); + + dividerUses.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + divider.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); + buttonTextView.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(6), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + + usesEditText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + usesEditText.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + + timeEditText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + timeEditText.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + + usesEditText.setCursorVisible(false); + setInviteToEdit(inviteToEdit); + + contentView.setClipChildren(false); + scrollView.setClipChildren(false); + linearLayout.setClipChildren(false); + + return contentView; + } + + private void onCreateClicked(View view) { + if (loading) { + return; + } + + int timeIndex = timeChooseView.getSelectedIndex(); + if (timeIndex < dispalyedDates.size() && dispalyedDates.get(timeIndex) < 0) { + AndroidUtilities.shakeView(timeEditText, 2, 0); + Vibrator vibrator = (Vibrator) timeEditText.getContext().getSystemService(Context.VIBRATOR_SERVICE); + if (vibrator != null) { + vibrator.vibrate(200); } + return; + } - int timeIndex = timeChooseView.getSelectedIndex(); - if (timeIndex < dispalyedDates.size() && dispalyedDates.get(timeIndex) < 0) { - AndroidUtilities.shakeView(timeEditText, 2, 0); - Vibrator vibrator = (Vibrator) timeEditText.getContext().getSystemService(Context.VIBRATOR_SERVICE); - if (vibrator != null) { - vibrator.vibrate(200); - } - return; + if (type == CREATE_TYPE) { + if (progressDialog != null) { + progressDialog.dismiss(); + } + loading = true; + progressDialog = new AlertDialog(getParentActivity(), 3); + progressDialog.showDelayed(500); + TLRPC.TL_messages_exportChatInvite req = new TLRPC.TL_messages_exportChatInvite(); + req.peer = getMessagesController().getInputPeer(-chatId); + req.legacy_revoke_permanent = false; + + int i = timeChooseView.getSelectedIndex(); + req.flags |= 1; + if (i < dispalyedDates.size()) { + req.expire_date = dispalyedDates.get(i) + getConnectionsManager().getCurrentTime(); + } else { + req.expire_date = 0; + } + + i = usesChooseView.getSelectedIndex(); + req.flags |= 2; + if (i < dispalyedUses.size()) { + req.usage_limit = dispalyedUses.get(i); + } else { + req.usage_limit = 0; + } + + req.request_needed = approveCell.isChecked(); + if (req.request_needed) { + req.usage_limit = 0; + } + + req.title = nameEditText.getText().toString(); + if (!TextUtils.isEmpty(req.title)) { + req.flags |= 16; } - if (type == CREATE_TYPE) { + getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + loading = false; if (progressDialog != null) { progressDialog.dismiss(); } - loading = true; - progressDialog = new AlertDialog(context, 3); - progressDialog.showDelayed(500); - TLRPC.TL_messages_exportChatInvite req = new TLRPC.TL_messages_exportChatInvite(); - req.peer = getMessagesController().getInputPeer(-chatId); - req.legacy_revoke_permanent = false; + if (error == null) { + if (callback != null) { + callback.onLinkCreated(response); + } + finishFragment(); + } else { + AlertsCreator.showSimpleAlert(LinkEditActivity.this, error.text); + } + })); + } else if (type == EDIT_TYPE) { + if (progressDialog != null) { + progressDialog.dismiss(); + } + + TLRPC.TL_messages_editExportedChatInvite req = new TLRPC.TL_messages_editExportedChatInvite(); + req.link = inviteToEdit.link; + req.revoked = false; + req.peer = getMessagesController().getInputPeer(-chatId); - int i = timeChooseView.getSelectedIndex(); - req.flags |= 1; - if (i < dispalyedDates.size()) { + boolean edited = false; + + int i = timeChooseView.getSelectedIndex(); + if (i < dispalyedDates.size()) { + if (currentInviteDate != dispalyedDates.get(i)) { + req.flags |= 1; req.expire_date = dispalyedDates.get(i) + getConnectionsManager().getCurrentTime(); - } else { + edited = true; + } + } else { + if (currentInviteDate != 0) { + req.flags |= 1; req.expire_date = 0; + edited = true; } + } - i = usesChooseView.getSelectedIndex(); - req.flags |= 2; - if (i < dispalyedUses.size()) { - req.usage_limit = dispalyedUses.get(i); - } else { + i = usesChooseView.getSelectedIndex(); + + if (i < dispalyedUses.size()) { + int newLimit = dispalyedUses.get(i); + if (inviteToEdit.usage_limit != newLimit) { + req.flags |= 2; + req.usage_limit = newLimit; + edited = true; + } + } else { + if (inviteToEdit.usage_limit != 0) { + req.flags |= 2; req.usage_limit = 0; + edited = true; } + } + + if (inviteToEdit.request_needed != approveCell.isChecked()) { + req.flags |= 8; + req.request_needed = approveCell.isChecked(); + if (req.request_needed) { + req.flags |= 2; + req.usage_limit = 0; + } + edited = true; + } + + String newTitle = nameEditText.getText().toString(); + if (!TextUtils.equals(inviteToEdit.title, newTitle)) { + req.title = newTitle; + req.flags |= 16; + edited = true; + } + if (edited) { + loading = true; + progressDialog = new AlertDialog(getParentActivity(), 3); + progressDialog.showDelayed(500); getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { loading = false; if (progressDialog != null) { progressDialog.dismiss(); } if (error == null) { + if (response instanceof TLRPC.TL_messages_exportedChatInvite) { + inviteToEdit = (TLRPC.TL_chatInviteExported) ((TLRPC.TL_messages_exportedChatInvite) response).invite; + } if (callback != null) { - callback.onLinkCreated(response); + callback.onLinkEdited(inviteToEdit, response); } finishFragment(); } else { AlertsCreator.showSimpleAlert(LinkEditActivity.this, error.text); } })); - } else if (type == EDIT_TYPE) { - if (progressDialog != null) { - progressDialog.dismiss(); - } - loading = true; - progressDialog = new AlertDialog(context, 3); - progressDialog.showDelayed(500); - - TLRPC.TL_messages_editExportedChatInvite req = new TLRPC.TL_messages_editExportedChatInvite(); - req.link = inviteToEdit.link; - req.revoked = false; - req.peer = getMessagesController().getInputPeer(-chatId); - - boolean edited = false; - - int i = timeChooseView.getSelectedIndex(); - if (i < dispalyedDates.size()) { - if (currentInviteDate != dispalyedDates.get(i)) { - req.flags |= 1; - req.expire_date = dispalyedDates.get(i) + getConnectionsManager().getCurrentTime(); - edited = true; - } - } else { - if (currentInviteDate != 0) { - req.flags |= 1; - req.expire_date = 0; - edited = true; - } - } - - i = usesChooseView.getSelectedIndex(); - - if (i < dispalyedUses.size()) { - int newLimit = dispalyedUses.get(i); - if (inviteToEdit.usage_limit != newLimit) { - req.flags |= 2; - req.usage_limit = newLimit; - edited = true; - } - } else { - if (inviteToEdit.usage_limit != 0) { - req.flags |= 2; - req.usage_limit = 0; - edited = true; - } - } - - if (edited) { - getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - loading = false; - if (progressDialog != null) { - progressDialog.dismiss(); - } - if (error == null) { - if (callback != null) { - callback.onLinkEdited(inviteToEdit, response); - } - finishFragment(); - } else { - AlertsCreator.showSimpleAlert(LinkEditActivity.this, error.text); - } - })); - } + } else { + finishFragment(); } - }); - buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); - - dividerUses.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); - divider.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); - buttonTextView.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(6), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); - - usesEditText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - usesEditText.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); - - timeEditText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - timeEditText.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); - - usesEditText.setCursorVisible(false); - setInviteToEdit(inviteToEdit); - - contentView.setClipChildren(false); - scrollView.setClipChildren(false); - linearLayout.setClipChildren(false); - - return contentView; + } } private void chooseUses(int customUses) { @@ -597,7 +745,8 @@ private void resetDates() { for (int i = 0; i < defaultDates.length; i++) { dispalyedDates.add(defaultDates[i]); } - timeChooseView.setOptions(4, LocaleController.formatPluralString("Hours", 1), LocaleController.formatPluralString("Days", 1), LocaleController.formatPluralString("Weeks", 1), LocaleController.getString("NoLimit", R.string.NoLimit)); + String[] options = new String[]{ LocaleController.formatPluralString("Hours", 1), LocaleController.formatPluralString("Days", 1), LocaleController.formatPluralString("Weeks", 1), LocaleController.getString("NoLimit", R.string.NoLimit) }; + timeChooseView.setOptions(options.length - 1, options); } public void setCallback(Callback callback) { @@ -609,11 +758,10 @@ private void resetUses() { for (int i = 0; i < defaultUses.length; i++) { dispalyedUses.add(defaultUses[i]); } - usesChooseView.setOptions(4, "1", "10", "100", LocaleController.getString("NoLimit", R.string.NoLimit)); + String[] options = new String[]{ "1", "10", "100", LocaleController.getString("NoLimit", R.string.NoLimit) }; + usesChooseView.setOptions(options.length - 1, options); } - int currentInviteDate; - public void setInviteToEdit(TLRPC.TL_chatInviteExported invite) { inviteToEdit = invite; if (fragmentView != null && invite != null) { @@ -627,9 +775,25 @@ public void setInviteToEdit(TLRPC.TL_chatInviteExported invite) { chooseUses(invite.usage_limit); usesEditText.setText(Integer.toString(invite.usage_limit)); } + approveCell.setBackgroundColor(Theme.getColor(invite.request_needed ? Theme.key_windowBackgroundChecked : Theme.key_windowBackgroundUnchecked)); + approveCell.setChecked(invite.request_needed); + setUsesVisible(!invite.request_needed); + if (!TextUtils.isEmpty(invite.title)) { + SpannableStringBuilder builder = new SpannableStringBuilder(invite.title); + Emoji.replaceEmoji(builder, nameEditText.getPaint().getFontMetricsInt(), (int) nameEditText.getPaint().getTextSize(), false); + nameEditText.setText(builder); + } } } + private void setUsesVisible(boolean isVisible) { + usesHeaderCell.setVisibility(isVisible ? View.VISIBLE : View.GONE); + usesChooseView.setVisibility(isVisible ? View.VISIBLE : View.GONE); + usesEditText.setVisibility(isVisible ? View.VISIBLE : View.GONE); + dividerUses.setVisibility(isVisible ? View.VISIBLE : View.GONE); + divider.setBackground(Theme.getThemedDrawable(getParentActivity(), isVisible ? R.drawable.greydivider : R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + } + public interface Callback { void onLinkCreated(TLObject response); @@ -666,6 +830,11 @@ public ArrayList getThemeDescriptions() { if (revokeLink != null) { revokeLink.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteRedText5)); } + + createTextView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultTitle)); + dividerName.setBackground(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + nameEditText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + nameEditText.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); } }; ArrayList themeDescriptions = new ArrayList<>(); @@ -682,6 +851,7 @@ public ArrayList getThemeDescriptions() { themeDescriptions.add(new ThemeDescription(divider, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4)); themeDescriptions.add(new ThemeDescription(dividerUses, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4)); + themeDescriptions.add(new ThemeDescription(dividerName, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4)); themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ManageLinksActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ManageLinksActivity.java index 74717c4a612..ff0b533ff58 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ManageLinksActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ManageLinksActivity.java @@ -36,6 +36,7 @@ import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DocumentObject; +import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; @@ -325,6 +326,7 @@ private void loadLinks(boolean notify) { TLRPC.TL_chatInviteExported finalPermanentLink = permanentLink; AndroidUtilities.runOnUIThread(() -> getNotificationCenter().doOnIdle(() -> { + DiffCallback callback = saveListState(); linksLoading = false; hasMore = false; if (finalPermanentLink != null) { @@ -333,13 +335,11 @@ private void loadLinks(boolean notify) { info.exported_invite = finalPermanentLink; } } - DiffCallback callback = saveListState(); boolean updateByDiffUtils = false; if (error == null) { TLRPC.TL_messages_exportedChatInvites invites = (TLRPC.TL_messages_exportedChatInvites) response; - if (revoked) { for (int i = 0; i < invites.invites.size(); i++) { TLRPC.TL_chatInviteExported in = (TLRPC.TL_chatInviteExported) invites.invites.get(i); @@ -560,7 +560,12 @@ protected void onDetachedFromWindow() { recyclerItemsEnterAnimator.onDetached(); } }; - LinearLayoutManager layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false); + LinearLayoutManager layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) { + @Override + public boolean supportsPredictiveItemAnimations() { + return false; + } + }; listView.setLayoutManager(layoutManager); listView.setAdapter(listViewAdapter = new ListAdapter(context)); listView.setOnScrollListener(new RecyclerView.OnScrollListener() { @@ -1358,18 +1363,22 @@ public void setLink(TLRPC.TL_chatInviteExported invite, int position) { return; } - if (invite.link.startsWith("https://t.me/+")) { + if (!TextUtils.isEmpty(invite.title)) { + SpannableStringBuilder builder = new SpannableStringBuilder(invite.title); + Emoji.replaceEmoji(builder, titleView.getPaint().getFontMetricsInt(), (int) titleView.getPaint().getTextSize(), false); + titleView.setText(builder); + } else if (invite.link.startsWith("https://t.me/+")) { titleView.setText(invite.link.substring("https://t.me/+".length())); } else if (invite.link.startsWith("https://t.me/joinchat/")) { titleView.setText(invite.link.substring("https://t.me/joinchat/".length())); - }else if (invite.link.startsWith("https://")) { + } else if (invite.link.startsWith("https://")) { titleView.setText(invite.link.substring("https://".length())); } else { titleView.setText(invite.link); } - String joinedString; - if (invite.usage == 0 && invite.usage_limit == 0) { + String joinedString = ""; + if (invite.usage == 0 && invite.usage_limit == 0 && invite.requested == 0) { joinedString = LocaleController.getString("NoOneJoinedYet", R.string.NoOneJoinedYet); } else { if (invite.usage_limit > 0 && invite.usage == 0 && !invite.expired && !invite.revoked) { @@ -1377,7 +1386,15 @@ public void setLink(TLRPC.TL_chatInviteExported invite, int position) { } else if (invite.usage_limit > 0 && invite.expired && invite.revoked) { joinedString = LocaleController.formatPluralString("PeopleJoined", invite.usage) + ", " + LocaleController.formatPluralString("PeopleJoinedRemaining", (invite.usage_limit - invite.usage)); } else { - joinedString = LocaleController.formatPluralString("PeopleJoined", invite.usage); + if (invite.usage > 0) { + joinedString = LocaleController.formatPluralString("PeopleJoined", invite.usage); + } + if (invite.requested > 0) { + if (invite.usage > 0) { + joinedString = joinedString + ", "; + } + joinedString = joinedString + LocaleController.formatPluralString("JoinRequests", invite.requested); + } } } if (invite.permanent && !invite.revoked) { @@ -1407,10 +1424,8 @@ public void setLink(TLRPC.TL_chatInviteExported invite, int position) { dotDividerSpan.setTopPadding(AndroidUtilities.dp(1.5f)); spannableStringBuilder.append(" . ").setSpan(dotDividerSpan, spannableStringBuilder.length() - 3, spannableStringBuilder.length() - 2, 0); - long currentTime = System.currentTimeMillis() + timeDif * 1000L; long expireTime = invite.expire_date * 1000L; - long timeLeft = expireTime - currentTime; if (timeLeft < 0) { timeLeft = 0; @@ -1496,11 +1511,11 @@ public void onLinkCreated(TLObject response) { AndroidUtilities.runOnUIThread(() -> { DiffCallback callback = saveListState(); invites.add(0, (TLRPC.TL_chatInviteExported) response); - updateRecyclerViewAnimated(callback); if (info != null) { info.invitesCount++; getMessagesStorage().saveChatLinksCount(currentChatId, info.invitesCount); } + updateRecyclerViewAnimated(callback); }, 200); } } @@ -1749,6 +1764,9 @@ protected void onTransitionAnimationEnd(boolean isOpen, boolean backward) { super.onTransitionAnimationEnd(isOpen, backward); if (isOpen) { isOpened = true; + if (backward && inviteLinkBottomSheet != null && inviteLinkBottomSheet.isNeedReopen) { + inviteLinkBottomSheet.show(); + } } NotificationCenter.getInstance(currentAccount).onAnimationFinish(animationIndex); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java deleted file mode 100644 index 11800c4502f..00000000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java +++ /dev/null @@ -1,3027 +0,0 @@ -/* - * This is the source code of Telegram for Android v. 5.x.x. - * It is licensed under GNU GPL v. 2 or later. - * You should have received a copy of the license in this archive (see LICENSE). - * - * Copyright Nikolai Kudashov, 2013-2018. - */ - -package org.telegram.ui; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; -import android.app.Activity; -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.os.Bundle; -import android.text.TextUtils; -import android.util.Property; -import android.util.SparseArray; -import android.view.Gravity; -import android.view.MotionEvent; -import android.view.Surface; -import android.view.VelocityTracker; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.view.WindowManager; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; -import android.widget.EditText; -import android.widget.FrameLayout; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.ApplicationLoader; -import org.telegram.messenger.ChatObject; -import org.telegram.messenger.ContactsController; -import org.telegram.messenger.DialogObject; -import org.telegram.messenger.FileLoader; -import org.telegram.messenger.FileLog; -import org.telegram.messenger.LocaleController; -import org.telegram.messenger.MediaController; -import org.telegram.messenger.MediaDataController; -import org.telegram.messenger.MessageObject; -import org.telegram.messenger.MessagesController; -import org.telegram.messenger.NotificationCenter; -import org.telegram.messenger.R; -import org.telegram.messenger.SendMessagesHelper; -import org.telegram.messenger.UserConfig; -import org.telegram.messenger.Utilities; -import org.telegram.messenger.browser.Browser; -import org.telegram.tgnet.ConnectionsManager; -import org.telegram.tgnet.TLRPC; -import org.telegram.ui.ActionBar.ActionBar; -import org.telegram.ui.ActionBar.ActionBarMenu; -import org.telegram.ui.ActionBar.ActionBarMenuItem; -import org.telegram.ui.ActionBar.BackDrawable; -import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.ActionBar.BottomSheet; -import org.telegram.ui.ActionBar.Theme; -import org.telegram.ui.ActionBar.ThemeDescription; -import org.telegram.ui.Cells.GraySectionCell; -import org.telegram.ui.Cells.LoadingCell; -import org.telegram.ui.Cells.SharedAudioCell; -import org.telegram.ui.Cells.SharedDocumentCell; -import org.telegram.ui.Cells.SharedLinkCell; -import org.telegram.ui.Cells.SharedMediaSectionCell; -import org.telegram.ui.Cells.SharedPhotoVideoCell; -import org.telegram.ui.Components.AlertsCreator; -import org.telegram.ui.Components.AnimationProperties; -import org.telegram.ui.Components.BackupImageView; -import org.telegram.ui.Components.ClippingImageView; -import org.telegram.ui.Components.EmbedBottomSheet; -import org.telegram.ui.Components.FlickerLoadingView; -import org.telegram.ui.Components.FragmentContextView; -import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.NumberTextView; -import org.telegram.ui.Components.RecyclerListView; -import org.telegram.ui.Components.ScrollSlidingTextTabStrip; -import org.telegram.ui.Components.SharedMediaLayout; -import org.telegram.ui.Components.StickerEmptyView; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; - -@SuppressWarnings("unchecked") -public class MediaActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { - - private static class MediaPage extends FrameLayout { - private RecyclerListView listView; - private FlickerLoadingView progressView; - private StickerEmptyView emptyView; - private LinearLayoutManager layoutManager; - private ClippingImageView animatingImageView; - private int selectedType; - - public MediaPage(Context context) { - super(context); - } - } - - private SharedPhotoVideoAdapter photoVideoAdapter; - private SharedLinksAdapter linksAdapter; - private SharedDocumentsAdapter documentsAdapter; - private SharedDocumentsAdapter voiceAdapter; - private SharedDocumentsAdapter audioAdapter; - private MediaSearchAdapter documentsSearchAdapter; - private MediaSearchAdapter audioSearchAdapter; - private MediaSearchAdapter linksSearchAdapter; - private MediaPage[] mediaPages = new MediaPage[2]; - private ActionBarMenuItem searchItem; - private int searchItemState; - private Drawable pinnedHeaderShadowDrawable; - private boolean ignoreSearchCollapse; - private NumberTextView selectedMessagesCountTextView; - private ArrayList cellCache = new ArrayList<>(10); - private ArrayList cache = new ArrayList<>(10); - private ArrayList audioCellCache = new ArrayList<>(10); - private ArrayList audioCache = new ArrayList<>(10); - private FragmentContextView fragmentContextView; - private ScrollSlidingTextTabStrip scrollSlidingTextTabStrip; - private View actionModeBackground; - - private int maximumVelocity; - - private Paint backgroundPaint = new Paint(); - - private int additionalPadding; - - private boolean searchWas; - private boolean searching; - private boolean disableActionBarScrolling; - - private int[] hasMedia; - private int initialTab; - - private SparseArray[] selectedFiles = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; - private int cantDeleteMessagesCount; - private ArrayList actionModeViews = new ArrayList<>(); - private ActionBarMenuItem gotoItem; - private boolean scrolling; - private long mergeDialogId; - protected TLRPC.ChatFull info = null; - - private AnimatorSet tabsAnimation; - private boolean tabsAnimationInProgress; - private boolean animatingForward; - private boolean backAnimation; - - private boolean swipeBackEnabled; - - private long dialogId; - private int columnsCount = 3; - - private static final Interpolator interpolator = t -> { - --t; - return t * t * t * t * t + 1.0F; - }; - - public final Property SCROLL_Y = new AnimationProperties.FloatProperty("animationValue") { - @Override - public void setValue(MediaActivity object, float value) { - object.setScrollY(value); - for (int a = 0; a < mediaPages.length; a++) { - mediaPages[a].listView.checkSection(); - } - } - - @Override - public Float get(MediaActivity object) { - return actionBar.getTranslationY(); - } - }; - - private PhotoViewer.PhotoViewerProvider provider = new PhotoViewer.EmptyPhotoViewerProvider() { - - @Override - public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index, boolean needPreview) { - if (messageObject == null || mediaPages[0].selectedType != 0 && mediaPages[0].selectedType != 1) { - return null; - } - final RecyclerListView listView = mediaPages[0].listView; - for (int a = 0, count = listView.getChildCount(); a < count; a++) { - View view = listView.getChildAt(a); - if (view.getTop() >= mediaPages[0].listView.getMeasuredHeight()) { - continue; - } - BackupImageView imageView = null; - if (view instanceof SharedPhotoVideoCell) { - SharedPhotoVideoCell cell = (SharedPhotoVideoCell) view; - for (int i = 0; i < 6; i++) { - MessageObject message = cell.getMessageObject(i); - if (message == null) { - break; - } - if (message.getId() == messageObject.getId()) { - imageView = cell.getImageView(i); - } - } - } else if (view instanceof SharedDocumentCell) { - SharedDocumentCell cell = (SharedDocumentCell) view; - MessageObject message = cell.getMessage(); - if (message.getId() == messageObject.getId()) { - imageView = cell.getImageView(); - } - } - if (imageView != null) { - int[] coords = new int[2]; - imageView.getLocationInWindow(coords); - PhotoViewer.PlaceProviderObject object = new PhotoViewer.PlaceProviderObject(); - object.viewX = coords[0]; - object.viewY = coords[1] - (Build.VERSION.SDK_INT >= 21 ? 0 : AndroidUtilities.statusBarHeight); - object.parentView = listView; - object.animatingImageView = mediaPages[0].animatingImageView; - object.imageReceiver = imageView.getImageReceiver(); - object.radius = object.imageReceiver.getRoundRadius(); - object.thumb = object.imageReceiver.getBitmapSafe(); - object.parentView.getLocationInWindow(coords); - object.clipTopAddition = (int) (actionBar.getHeight() + actionBar.getTranslationY()); - if (fragmentContextView != null && fragmentContextView.getVisibility() == View.VISIBLE) { - object.clipTopAddition += AndroidUtilities.dp(36); - } - - if (PhotoViewer.isShowingImage(messageObject)) { - final View pinnedHeader = listView.getPinnedHeader(); - if (pinnedHeader != null) { - int top = (int) (actionBar.getHeight() + actionBar.getTranslationY()); - if (fragmentContextView != null && fragmentContextView.getVisibility() == View.VISIBLE) { - top += fragmentContextView.getHeight() - AndroidUtilities.dp(2.5f); - } - if (view instanceof SharedDocumentCell) { - top += AndroidUtilities.dp(8f); - } - final int topOffset = top - object.viewY; - if (topOffset > view.getHeight()) { - scrollWithoutActionBar(listView, -(topOffset + pinnedHeader.getHeight())); - } else { - int bottomOffset = object.viewY - listView.getHeight(); - if (view instanceof SharedDocumentCell) { - bottomOffset -= AndroidUtilities.dp(8f); - } - if (bottomOffset >= 0) { - scrollWithoutActionBar(listView, bottomOffset + view.getHeight()); - } - } - } - } - return object; - } - if (mediaPages[0].selectedType == 0) { - int position = photoVideoAdapter.getPositionForIndex(index); - int firstVisiblePosition = mediaPages[0].layoutManager.findFirstVisibleItemPosition(); - int lastVisiblePosition = mediaPages[0].layoutManager.findLastVisibleItemPosition(); - - if (position <= firstVisiblePosition) { - mediaPages[0].layoutManager.scrollToPositionWithOffset(position, 0); - } else if (position >= lastVisiblePosition && lastVisiblePosition >= 0) { - mediaPages[0].layoutManager.scrollToPositionWithOffset(position, 0, true); - } - } - } - return null; - } - }; - - private SharedMediaLayout.SharedMediaData[] sharedMediaData = new SharedMediaLayout.SharedMediaData[6]; - - private final static int forward = 3; - private final static int delete = 4; - private final static int gotochat = 7; - - public MediaActivity(Bundle args, int[] media) { - this(args, media, null, MediaDataController.MEDIA_PHOTOVIDEO); - } - - public MediaActivity(Bundle args, int[] media, SharedMediaLayout.SharedMediaData[] mediaData, int initTab) { - super(args); - hasMedia = media; - initialTab = initTab; - dialogId = args.getLong("dialog_id", 0); - for (int a = 0; a < sharedMediaData.length; a++) { - sharedMediaData[a] = new SharedMediaLayout.SharedMediaData(); - sharedMediaData[a].max_id[0] = DialogObject.isEncryptedDialog(dialogId) ? Integer.MIN_VALUE : Integer.MAX_VALUE; - if (mergeDialogId != 0 && info != null) { - sharedMediaData[a].max_id[1] = info.migrated_from_max_id; - sharedMediaData[a].endReached[1] = false; - } - if (mediaData != null) { - sharedMediaData[a].totalCount = mediaData[a].totalCount; - sharedMediaData[a].messages.addAll(mediaData[a].messages); - sharedMediaData[a].sections.addAll(mediaData[a].sections); - for (HashMap.Entry> entry : mediaData[a].sectionArrays.entrySet()) { - sharedMediaData[a].sectionArrays.put(entry.getKey(), new ArrayList<>(entry.getValue())); - } - for (int i = 0; i < 2; i++) { - sharedMediaData[a].endReached[i] = mediaData[a].endReached[i]; - sharedMediaData[a].messagesDict[i] = mediaData[a].messagesDict[i].clone(); - sharedMediaData[a].max_id[i] = mediaData[a].max_id[i]; - } - } - } - } - - @Override - public boolean onFragmentCreate() { - super.onFragmentCreate(); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.mediaDidLoad); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagesDeleted); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.didReceiveNewMessages); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messageReceivedByServer); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingDidReset); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingPlayStateChanged); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingDidStart); - return true; - } - - @Override - public void onFragmentDestroy() { - super.onFragmentDestroy(); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.mediaDidLoad); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.didReceiveNewMessages); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagesDeleted); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messageReceivedByServer); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagePlayingDidReset); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagePlayingPlayStateChanged); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagePlayingDidStart); - } - - @Override - public View createView(Context context) { - for (int a = 0; a < 10; a++) { - cellCache.add(new SharedPhotoVideoCell(context)); - if (initialTab == MediaDataController.MEDIA_MUSIC) { - SharedAudioCell cell = new SharedAudioCell(context) { - @Override - public boolean needPlayMessage(MessageObject messageObject) { - if (messageObject.isVoice() || messageObject.isRoundVideo()) { - boolean result = MediaController.getInstance().playMessage(messageObject); - MediaController.getInstance().setVoiceMessagesPlaylist(result ? sharedMediaData[MediaDataController.MEDIA_MUSIC].messages : null, false); - return result; - } else if (messageObject.isMusic()) { - return MediaController.getInstance().setPlaylist(sharedMediaData[MediaDataController.MEDIA_MUSIC].messages, messageObject, mergeDialogId); - } - return false; - } - }; - cell.initStreamingIcons(); - audioCellCache.add(cell); - } - } - - ViewConfiguration configuration = ViewConfiguration.get(context); - maximumVelocity = configuration.getScaledMaximumFlingVelocity(); - - searching = false; - searchWas = false; - if (AndroidUtilities.isTablet()) { - actionBar.setOccupyStatusBar(false); - } - actionBar.setBackButtonDrawable(new BackDrawable(false)); - actionBar.setAddToContainer(false); - actionBar.setClipContent(true); - if (DialogObject.isEncryptedDialog(dialogId)) { - TLRPC.EncryptedChat encryptedChat = getMessagesController().getEncryptedChat(DialogObject.getEncryptedChatId(dialogId)); - if (encryptedChat != null) { - TLRPC.User user = getMessagesController().getUser(encryptedChat.user_id); - if (user != null) { - actionBar.setTitle(ContactsController.formatName(user.first_name, user.last_name)); - } - } - } else if (DialogObject.isUserDialog(dialogId)) { - TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); - if (user != null) { - if (user.self) { - actionBar.setTitle(LocaleController.getString("SavedMessages", R.string.SavedMessages)); - } else { - actionBar.setTitle(ContactsController.formatName(user.first_name, user.last_name)); - } - } - } else { - TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); - if (chat != null) { - actionBar.setTitle(chat.title); - } - } - - if (TextUtils.isEmpty(actionBar.getTitle())) { - actionBar.setTitle(LocaleController.getString("SharedContentTitle", R.string.SharedContentTitle)); - } - actionBar.setExtraHeight(AndroidUtilities.dp(44)); - actionBar.setAllowOverlayTitle(false); - actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { - @Override - public void onItemClick(int id) { - if (id == -1) { - if (!closeActionMode()) { - finishFragment(); - } - } else if (id == delete) { - TLRPC.Chat currentChat = null; - TLRPC.User currentUser = null; - TLRPC.EncryptedChat currentEncryptedChat = null; - if (DialogObject.isEncryptedDialog(dialogId)) { - currentEncryptedChat = MessagesController.getInstance(currentAccount).getEncryptedChat(DialogObject.getEncryptedChatId(dialogId)); - } else if (DialogObject.isUserDialog(dialogId)) { - currentUser = MessagesController.getInstance(currentAccount).getUser(dialogId); - } else { - currentChat = MessagesController.getInstance(currentAccount).getChat(-dialogId); - } - AlertsCreator.createDeleteMessagesAlert(MediaActivity.this, currentUser, currentChat, currentEncryptedChat, null, mergeDialogId, null, selectedFiles, null, false, 1, () -> { - actionBar.hideActionMode(); - actionBar.closeSearchField(); - cantDeleteMessagesCount = 0; - }, null); - } else if (id == forward) { - Bundle args = new Bundle(); - args.putBoolean("onlySelect", true); - args.putInt("dialogsType", 3); - DialogsActivity fragment = new DialogsActivity(args); - fragment.setDelegate((fragment1, dids, message, param) -> { - ArrayList fmessages = new ArrayList<>(); - for (int a = 1; a >= 0; a--) { - ArrayList ids = new ArrayList<>(); - for (int b = 0; b < selectedFiles[a].size(); b++) { - ids.add(selectedFiles[a].keyAt(b)); - } - Collections.sort(ids); - for (Integer id1 : ids) { - if (id1 > 0) { - fmessages.add(selectedFiles[a].get(id1)); - } - } - selectedFiles[a].clear(); - } - cantDeleteMessagesCount = 0; - actionBar.hideActionMode(); - - if (dids.size() > 1 || dids.get(0) == UserConfig.getInstance(currentAccount).getClientUserId() || message != null) { - updateRowsSelection(); - for (int a = 0; a < dids.size(); a++) { - long did = dids.get(a); - if (message != null) { - SendMessagesHelper.getInstance(currentAccount).sendMessage(message.toString(), did, null, null, null, true, null, null, null, true, 0, null); - } - SendMessagesHelper.getInstance(currentAccount).sendMessage(fmessages, did, false, false, true, 0); - } - fragment1.finishFragment(); - } else { - long did = dids.get(0); - Bundle args1 = new Bundle(); - args1.putBoolean("scrollToTopOnResume", true); - if (DialogObject.isEncryptedDialog(did)) { - args1.putInt("enc_id", DialogObject.getEncryptedChatId(did)); - } else if (DialogObject.isUserDialog(did)) { - args1.putLong("user_id", did); - } else { - args1.putLong("chat_id", -did); - } - if (!DialogObject.isEncryptedDialog(did)) { - if (!MessagesController.getInstance(currentAccount).checkCanOpenChat(args1, fragment1)) { - return; - } - } - - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats); - - ChatActivity chatActivity = new ChatActivity(args1); - presentFragment(chatActivity, true); - chatActivity.showFieldPanelForForward(true, fmessages); - - if (!AndroidUtilities.isTablet()) { - removeSelfFromStack(); - } - } - }); - presentFragment(fragment); - } else if (id == gotochat) { - if (selectedFiles[0].size() != 1) { - return; - } - Bundle args = new Bundle(); - if (DialogObject.isEncryptedDialog(dialogId)) { - args.putInt("enc_id", DialogObject.getEncryptedChatId(dialogId)); - } else if (DialogObject.isUserDialog(dialogId)) { - args.putLong("user_id", dialogId); - } else { - long did = dialogId; - TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-did); - if (chat != null && chat.migrated_to != null) { - args.putLong("migrated_to", did); - did = -chat.migrated_to.channel_id; - } - args.putLong("chat_id", -did); - } - args.putInt("message_id", selectedFiles[0].keyAt(0)); - args.putBoolean("need_remove_previous_same_chat_activity", false); - presentFragment(new ChatActivity(args), false); - } - } - }); - - pinnedHeaderShadowDrawable = context.getResources().getDrawable(R.drawable.photos_header_shadow); - pinnedHeaderShadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundGrayShadow), PorterDuff.Mode.MULTIPLY)); - - if (scrollSlidingTextTabStrip != null) { - initialTab = scrollSlidingTextTabStrip.getCurrentTabId(); - } - - scrollSlidingTextTabStrip = new ScrollSlidingTextTabStrip(context); - if (initialTab != -1) { - scrollSlidingTextTabStrip.setInitialTabId(initialTab); - initialTab = -1; - } - actionBar.addView(scrollSlidingTextTabStrip, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 44, Gravity.LEFT | Gravity.BOTTOM)); - scrollSlidingTextTabStrip.setDelegate(new ScrollSlidingTextTabStrip.ScrollSlidingTabStripDelegate() { - @Override - public void onPageSelected(int id, boolean forward) { - if (mediaPages[0].selectedType == id) { - return; - } - swipeBackEnabled = id == scrollSlidingTextTabStrip.getFirstTabId(); - mediaPages[1].selectedType = id; - mediaPages[1].setVisibility(View.VISIBLE); - switchToCurrentSelectedMode(true); - animatingForward = forward; - } - - @Override - public void onPageScrolled(float progress) { - if (progress == 1 && mediaPages[1].getVisibility() != View.VISIBLE) { - return; - } - if (animatingForward) { - mediaPages[0].setTranslationX(-progress * mediaPages[0].getMeasuredWidth()); - mediaPages[1].setTranslationX(mediaPages[0].getMeasuredWidth() - progress * mediaPages[0].getMeasuredWidth()); - } else { - mediaPages[0].setTranslationX(progress * mediaPages[0].getMeasuredWidth()); - mediaPages[1].setTranslationX(progress * mediaPages[0].getMeasuredWidth() - mediaPages[0].getMeasuredWidth()); - } - if (searchItemState == 1) { - searchItem.setAlpha(progress); - } else if (searchItemState == 2) { - searchItem.setAlpha(1.0f - progress); - } - if (progress == 1) { - MediaPage tempPage = mediaPages[0]; - mediaPages[0] = mediaPages[1]; - mediaPages[1] = tempPage; - mediaPages[1].setVisibility(View.GONE); - if (searchItemState == 2) { - searchItem.setVisibility(View.INVISIBLE); - } - searchItemState = 0; - } - } - }); - - for (int a = 1; a >= 0; a--) { - selectedFiles[a].clear(); - } - cantDeleteMessagesCount = 0; - actionModeViews.clear(); - - final ActionBarMenu menu = actionBar.createMenu(); - searchItem = menu.addItem(0, R.drawable.ic_ab_search).setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { - @Override - public void onSearchExpand() { - searching = true; - resetScroll(); - } - - @Override - public void onSearchCollapse() { - searching = false; - searchWas = false; - documentsSearchAdapter.search(null); - linksSearchAdapter.search(null); - audioSearchAdapter.search(null); - if (ignoreSearchCollapse) { - ignoreSearchCollapse = false; - return; - } - - switchToCurrentSelectedMode(false); - } - - @Override - public void onTextChanged(EditText editText) { - String text = editText.getText().toString(); - if (text.length() != 0) { - searchWas = true; - switchToCurrentSelectedMode(false); - } else { - searchWas = false; - switchToCurrentSelectedMode(false); - } - if (mediaPages[0].selectedType == 1) { - if (documentsSearchAdapter == null) { - return; - } - documentsSearchAdapter.search(text); - } else if (mediaPages[0].selectedType == 3) { - if (linksSearchAdapter == null) { - return; - } - linksSearchAdapter.search(text); - } else if (mediaPages[0].selectedType == 4) { - if (audioSearchAdapter == null) { - return; - } - audioSearchAdapter.search(text); - } - } - }); - searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); - searchItem.setContentDescription(LocaleController.getString("Search", R.string.Search)); - searchItem.setVisibility(View.INVISIBLE); - searchItemState = 0; - hasOwnBackground = true; - - final ActionBarMenu actionMode = actionBar.createActionMode(false, null); - actionMode.setBackgroundDrawable(null); - actionBar.setItemsColor(Theme.getColor(Theme.key_actionBarDefaultIcon), true); - actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSelector), true); - - actionModeBackground = new View(context); - actionModeBackground.setBackgroundColor(Theme.getColor(Theme.key_sharedMedia_actionMode)); - actionModeBackground.setAlpha(0.0f); - actionBar.addView(actionModeBackground, actionBar.indexOfChild(actionMode)); - - selectedMessagesCountTextView = new NumberTextView(actionMode.getContext()); - selectedMessagesCountTextView.setTextSize(18); - selectedMessagesCountTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - selectedMessagesCountTextView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultIcon)); - selectedMessagesCountTextView.setOnTouchListener((v, event) -> true); - actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 72, 0, 0, 0)); - - if (!DialogObject.isEncryptedDialog(dialogId)) { - actionModeViews.add(gotoItem = actionMode.addItemWithWidth(gotochat, R.drawable.msg_message, AndroidUtilities.dp(54), LocaleController.getString("AccDescrGoToMessage", R.string.AccDescrGoToMessage))); - actionModeViews.add(actionMode.addItemWithWidth(forward, R.drawable.msg_forward, AndroidUtilities.dp(54), LocaleController.getString("Forward", R.string.Forward))); - } - actionModeViews.add(actionMode.addItemWithWidth(delete, R.drawable.msg_delete, AndroidUtilities.dp(54), LocaleController.getString("Delete", R.string.Delete))); - - photoVideoAdapter = new SharedPhotoVideoAdapter(context); - documentsAdapter = new SharedDocumentsAdapter(context, 1); - voiceAdapter = new SharedDocumentsAdapter(context, 2); - audioAdapter = new SharedDocumentsAdapter(context, 4); - documentsSearchAdapter = new MediaSearchAdapter(context, 1); - audioSearchAdapter = new MediaSearchAdapter(context, 4); - linksSearchAdapter = new MediaSearchAdapter(context, 3); - linksAdapter = new SharedLinksAdapter(context); - - FrameLayout frameLayout; - fragmentView = frameLayout = new FrameLayout(context) { - - private int startedTrackingPointerId; - private boolean startedTracking; - private boolean maybeStartTracking; - private int startedTrackingX; - private int startedTrackingY; - private VelocityTracker velocityTracker; - private boolean globalIgnoreLayout; - - private boolean prepareForMoving(MotionEvent ev, boolean forward) { - int id = scrollSlidingTextTabStrip.getNextPageId(forward); - if (id < 0) { - return false; - } - if (searchItemState != 0) { - if (searchItemState == 2) { - searchItem.setAlpha(1.0f); - } else if (searchItemState == 1) { - searchItem.setAlpha(0.0f); - searchItem.setVisibility(View.INVISIBLE); - } - searchItemState = 0; - } - getParent().requestDisallowInterceptTouchEvent(true); - maybeStartTracking = false; - startedTracking = true; - startedTrackingX = (int) ev.getX(); - actionBar.setEnabled(false); - scrollSlidingTextTabStrip.setEnabled(false); - mediaPages[1].selectedType = id; - mediaPages[1].setVisibility(View.VISIBLE); - animatingForward = forward; - switchToCurrentSelectedMode(true); - if (forward) { - mediaPages[1].setTranslationX(mediaPages[0].getMeasuredWidth()); - } else { - mediaPages[1].setTranslationX(-mediaPages[0].getMeasuredWidth()); - } - return true; - } - - @Override - public void forceHasOverlappingRendering(boolean hasOverlappingRendering) { - super.forceHasOverlappingRendering(hasOverlappingRendering); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int widthSize = MeasureSpec.getSize(widthMeasureSpec); - int heightSize = MeasureSpec.getSize(heightMeasureSpec); - - setMeasuredDimension(widthSize, heightSize); - - measureChildWithMargins(actionBar, widthMeasureSpec, 0, heightMeasureSpec, 0); - int actionBarHeight = actionBar.getMeasuredHeight(); - globalIgnoreLayout = true; - for (int a = 0; a < mediaPages.length; a++) { - if (mediaPages[a] == null) { - continue; - } - if (mediaPages[a].listView != null) { - mediaPages[a].listView.setPadding(0, actionBarHeight + additionalPadding, 0, AndroidUtilities.dp(4)); - } - if (mediaPages[a].emptyView != null) { - mediaPages[a].emptyView.setPadding(0, actionBarHeight + additionalPadding, 0, 0); - } - if (mediaPages[a].progressView != null) { - mediaPages[a].progressView.setPadding(0, actionBarHeight + additionalPadding, 0, 0); - } - } - globalIgnoreLayout = false; - - int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - View child = getChildAt(i); - if (child == null || child.getVisibility() == GONE || child == actionBar) { - continue; - } - measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); - } - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - if (fragmentContextView != null) { - int y = actionBar.getMeasuredHeight(); - fragmentContextView.layout(fragmentContextView.getLeft(), fragmentContextView.getTop() + y, fragmentContextView.getRight(), fragmentContextView.getBottom() + y); - } - } - - @Override - public void setPadding(int left, int top, int right, int bottom) { - additionalPadding = top; - if (fragmentContextView != null) { - fragmentContextView.setTranslationY(top + actionBar.getTranslationY()); - } - int actionBarHeight = actionBar.getMeasuredHeight(); - for (int a = 0; a < mediaPages.length; a++) { - if (mediaPages[a] == null) { - continue; - } - if (mediaPages[a].emptyView != null) { - mediaPages[a].emptyView.setPadding(0, actionBarHeight + additionalPadding, 0, 0); - } - if (mediaPages[a].progressView != null) { - mediaPages[a].progressView.setPadding(0, actionBarHeight + additionalPadding, 0, 0); - } - if (mediaPages[a].listView != null) { - mediaPages[a].listView.setPadding(0, actionBarHeight + additionalPadding, 0, AndroidUtilities.dp(4)); - mediaPages[a].listView.checkSection(); - } - } - fixScrollOffset(); - } - - @Override - protected void dispatchDraw(Canvas canvas) { - super.dispatchDraw(canvas); - if (parentLayout != null) { - parentLayout.drawHeaderShadow(canvas, actionBar.getMeasuredHeight() + (int) actionBar.getTranslationY()); - } - if (fragmentContextView != null && fragmentContextView.isCallStyle()) { - canvas.save(); - canvas.translate(fragmentContextView.getX(), fragmentContextView.getY()); - fragmentContextView.setDrawOverlay(true); - fragmentContextView.draw(canvas); - fragmentContextView.setDrawOverlay(false); - canvas.restore(); - } - } - - @Override - protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - if (child == fragmentContextView && fragmentContextView.isCallStyle()) { - return true; - } - return super.drawChild(canvas, child, drawingTime); - } - - @Override - public void requestLayout() { - if (globalIgnoreLayout) { - return; - } - super.requestLayout(); - } - - public boolean checkTabsAnimationInProgress() { - if (tabsAnimationInProgress) { - boolean cancel = false; - if (backAnimation) { - if (Math.abs(mediaPages[0].getTranslationX()) < 1) { - mediaPages[0].setTranslationX(0); - mediaPages[1].setTranslationX(mediaPages[0].getMeasuredWidth() * (animatingForward ? 1 : -1)); - cancel = true; - } - } else if (Math.abs(mediaPages[1].getTranslationX()) < 1) { - mediaPages[0].setTranslationX(mediaPages[0].getMeasuredWidth() * (animatingForward ? -1 : 1)); - mediaPages[1].setTranslationX(0); - cancel = true; - } - if (cancel) { - if (tabsAnimation != null) { - tabsAnimation.cancel(); - tabsAnimation = null; - } - tabsAnimationInProgress = false; - } - return tabsAnimationInProgress; - } - return false; - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - return checkTabsAnimationInProgress() || scrollSlidingTextTabStrip.isAnimatingIndicator() || onTouchEvent(ev); - } - - @Override - protected void onDraw(Canvas canvas) { - backgroundPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite)); - canvas.drawRect(0, actionBar.getMeasuredHeight() + actionBar.getTranslationY(), getMeasuredWidth(), getMeasuredHeight(), backgroundPaint); - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - if (!parentLayout.checkTransitionAnimation() && !checkTabsAnimationInProgress()) { - if (ev != null) { - if (velocityTracker == null) { - velocityTracker = VelocityTracker.obtain(); - } - velocityTracker.addMovement(ev); - } - if (ev != null && ev.getAction() == MotionEvent.ACTION_DOWN && !startedTracking && !maybeStartTracking) { - startedTrackingPointerId = ev.getPointerId(0); - maybeStartTracking = true; - startedTrackingX = (int) ev.getX(); - startedTrackingY = (int) ev.getY(); - velocityTracker.clear(); - } else if (ev != null && ev.getAction() == MotionEvent.ACTION_MOVE && ev.getPointerId(0) == startedTrackingPointerId) { - int dx = (int) (ev.getX() - startedTrackingX); - int dy = Math.abs((int) ev.getY() - startedTrackingY); - if (startedTracking && (animatingForward && dx > 0 || !animatingForward && dx < 0)) { - if (!prepareForMoving(ev, dx < 0)) { - maybeStartTracking = true; - startedTracking = false; - mediaPages[0].setTranslationX(0); - mediaPages[1].setTranslationX(animatingForward ? mediaPages[0].getMeasuredWidth() : -mediaPages[0].getMeasuredWidth()); - scrollSlidingTextTabStrip.selectTabWithId(mediaPages[1].selectedType, 0); - } - } - if (maybeStartTracking && !startedTracking) { - float touchSlop = AndroidUtilities.getPixelsInCM(0.3f, true); - if (Math.abs(dx) >= touchSlop && Math.abs(dx) > dy) { - prepareForMoving(ev, dx < 0); - } - } else if (startedTracking) { - mediaPages[0].setTranslationX(dx); - if (animatingForward) { - mediaPages[1].setTranslationX(mediaPages[0].getMeasuredWidth() + dx); - } else { - mediaPages[1].setTranslationX(dx - mediaPages[0].getMeasuredWidth()); - } - float scrollProgress = Math.abs(dx) / (float) mediaPages[0].getMeasuredWidth(); - if (searchItemState == 2) { - searchItem.setAlpha(1.0f - scrollProgress); - } else if (searchItemState == 1) { - searchItem.setAlpha(scrollProgress); - } - scrollSlidingTextTabStrip.selectTabWithId(mediaPages[1].selectedType, scrollProgress); - } - } else if (ev == null || ev.getPointerId(0) == startedTrackingPointerId && (ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_POINTER_UP)) { - velocityTracker.computeCurrentVelocity(1000, maximumVelocity); - float velX; - float velY; - if (ev != null && ev.getAction() != MotionEvent.ACTION_CANCEL) { - velX = velocityTracker.getXVelocity(); - velY = velocityTracker.getYVelocity(); - if (!startedTracking) { - if (Math.abs(velX) >= 3000 && Math.abs(velX) > Math.abs(velY)) { - prepareForMoving(ev, velX < 0); - } - } - } else { - velX = 0; - velY = 0; - } - if (startedTracking) { - float x = mediaPages[0].getX(); - tabsAnimation = new AnimatorSet(); - backAnimation = Math.abs(x) < mediaPages[0].getMeasuredWidth() / 3.0f && (Math.abs(velX) < 3500 || Math.abs(velX) < Math.abs(velY)); - float distToMove; - float dx; - if (backAnimation) { - dx = Math.abs(x); - if (animatingForward) { - tabsAnimation.playTogether( - ObjectAnimator.ofFloat(mediaPages[0], View.TRANSLATION_X, 0), - ObjectAnimator.ofFloat(mediaPages[1], View.TRANSLATION_X, mediaPages[1].getMeasuredWidth()) - ); - } else { - tabsAnimation.playTogether( - ObjectAnimator.ofFloat(mediaPages[0], View.TRANSLATION_X, 0), - ObjectAnimator.ofFloat(mediaPages[1], View.TRANSLATION_X, -mediaPages[1].getMeasuredWidth()) - ); - } - } else { - dx = mediaPages[0].getMeasuredWidth() - Math.abs(x); - if (animatingForward) { - tabsAnimation.playTogether( - ObjectAnimator.ofFloat(mediaPages[0], View.TRANSLATION_X, -mediaPages[0].getMeasuredWidth()), - ObjectAnimator.ofFloat(mediaPages[1], View.TRANSLATION_X, 0) - ); - } else { - tabsAnimation.playTogether( - ObjectAnimator.ofFloat(mediaPages[0], View.TRANSLATION_X, mediaPages[0].getMeasuredWidth()), - ObjectAnimator.ofFloat(mediaPages[1], View.TRANSLATION_X, 0) - ); - } - } - tabsAnimation.setInterpolator(interpolator); - - int width = getMeasuredWidth(); - int halfWidth = width / 2; - float distanceRatio = Math.min(1.0f, 1.0f * dx / (float) width); - float distance = (float) halfWidth + (float) halfWidth * AndroidUtilities.distanceInfluenceForSnapDuration(distanceRatio); - velX = Math.abs(velX); - int duration; - if (velX > 0) { - duration = 4 * Math.round(1000.0f * Math.abs(distance / velX)); - } else { - float pageDelta = dx / getMeasuredWidth(); - duration = (int) ((pageDelta + 1.0f) * 100.0f); - } - duration = Math.max(150, Math.min(duration, 600)); - - tabsAnimation.setDuration(duration); - tabsAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animator) { - tabsAnimation = null; - if (backAnimation) { - mediaPages[1].setVisibility(View.GONE); - if (searchItemState == 2) { - searchItem.setAlpha(1.0f); - } else if (searchItemState == 1) { - searchItem.setAlpha(0.0f); - searchItem.setVisibility(View.INVISIBLE); - } - searchItemState = 0; - } else { - MediaPage tempPage = mediaPages[0]; - mediaPages[0] = mediaPages[1]; - mediaPages[1] = tempPage; - mediaPages[1].setVisibility(View.GONE); - if (searchItemState == 2) { - searchItem.setVisibility(View.INVISIBLE); - } - searchItemState = 0; - swipeBackEnabled = mediaPages[0].selectedType == scrollSlidingTextTabStrip.getFirstTabId(); - scrollSlidingTextTabStrip.selectTabWithId(mediaPages[0].selectedType, 1.0f); - } - tabsAnimationInProgress = false; - maybeStartTracking = false; - startedTracking = false; - actionBar.setEnabled(true); - scrollSlidingTextTabStrip.setEnabled(true); - } - }); - tabsAnimation.start(); - tabsAnimationInProgress = true; - startedTracking = false; - } else { - maybeStartTracking = false; - actionBar.setEnabled(true); - scrollSlidingTextTabStrip.setEnabled(true); - } - if (velocityTracker != null) { - velocityTracker.recycle(); - velocityTracker = null; - } - } - return startedTracking; - } - return false; - } - }; - frameLayout.setWillNotDraw(false); - - int scrollToPositionOnRecreate = -1; - int scrollToOffsetOnRecreate = 0; - - for (int a = 0; a < mediaPages.length; a++) { - if (a == 0) { - if (mediaPages[a] != null && mediaPages[a].layoutManager != null) { - scrollToPositionOnRecreate = mediaPages[a].layoutManager.findFirstVisibleItemPosition(); - if (scrollToPositionOnRecreate != mediaPages[a].layoutManager.getItemCount() - 1) { - RecyclerListView.Holder holder = (RecyclerListView.Holder) mediaPages[a].listView.findViewHolderForAdapterPosition(scrollToPositionOnRecreate); - if (holder != null) { - scrollToOffsetOnRecreate = holder.itemView.getTop(); - } else { - scrollToPositionOnRecreate = -1; - } - } else { - scrollToPositionOnRecreate = -1; - } - } - } - final MediaPage mediaPage = new MediaPage(context) { - @Override - public void setTranslationX(float translationX) { - super.setTranslationX(translationX); - if (tabsAnimationInProgress) { - if (mediaPages[0] == this) { - float scrollProgress = Math.abs(mediaPages[0].getTranslationX()) / (float) mediaPages[0].getMeasuredWidth(); - scrollSlidingTextTabStrip.selectTabWithId(mediaPages[1].selectedType, scrollProgress); - if (searchItemState == 2) { - searchItem.setAlpha(1.0f - scrollProgress); - } else if (searchItemState == 1) { - searchItem.setAlpha(scrollProgress); - } - } - } - } - }; - frameLayout.addView(mediaPage, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - mediaPages[a] = mediaPage; - - final LinearLayoutManager layoutManager = mediaPages[a].layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) { - @Override - public boolean supportsPredictiveItemAnimations() { - return false; - } - - @Override - protected void calculateExtraLayoutSpace(@NonNull RecyclerView.State state, @NonNull int[] extraLayoutSpace) { - super.calculateExtraLayoutSpace(state, extraLayoutSpace); - if (mediaPage.selectedType == 0) { - extraLayoutSpace[1] = Math.max(extraLayoutSpace[1], SharedPhotoVideoCell.getItemSize(columnsCount) * 2); - } else if (mediaPage.selectedType == 1) { - extraLayoutSpace[1] = Math.max(extraLayoutSpace[1], AndroidUtilities.dp(56f) * 2); - } - } - }; - mediaPages[a].listView = new RecyclerListView(context) { - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - super.onLayout(changed, l, t, r, b); - updateSections(this, true); - if (mediaPage.selectedType == 0) { - PhotoViewer.getInstance().checkCurrentImageVisibility(); - } - } - }; - mediaPages[a].listView.setScrollingTouchSlop(RecyclerView.TOUCH_SLOP_PAGING); - mediaPages[a].listView.setItemAnimator(null); - mediaPages[a].listView.setClipToPadding(false); - mediaPages[a].listView.setSectionsType(2); - mediaPages[a].listView.setLayoutManager(layoutManager); - mediaPages[a].addView(mediaPages[a].listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - mediaPages[a].listView.setOnItemClickListener((view, position) -> { - if (mediaPage.selectedType == 1 && view instanceof SharedDocumentCell) { - MediaActivity.this.onItemClick(position, view, ((SharedDocumentCell) view).getMessage(), 0, mediaPage.selectedType); - } else if (mediaPage.selectedType == 3 && view instanceof SharedLinkCell) { - MediaActivity.this.onItemClick(position, view, ((SharedLinkCell) view).getMessage(), 0, mediaPage.selectedType); - } else if ((mediaPage.selectedType == 2 || mediaPage.selectedType == 4) && view instanceof SharedAudioCell) { - MediaActivity.this.onItemClick(position, view, ((SharedAudioCell) view).getMessage(), 0, mediaPage.selectedType); - } - }); - mediaPages[a].listView.setOnScrollListener(new RecyclerView.OnScrollListener() { - - @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { - AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); - } - scrolling = newState != RecyclerView.SCROLL_STATE_IDLE; - if (newState != RecyclerView.SCROLL_STATE_DRAGGING) { - int scrollY = (int) -actionBar.getTranslationY(); - int actionBarHeight = ActionBar.getCurrentActionBarHeight(); - if (scrollY != 0 && scrollY != actionBarHeight) { - if (scrollY < actionBarHeight / 2) { - mediaPages[0].listView.smoothScrollBy(0, -scrollY); - } else if (mediaPages[0].listView.canScrollVertically(1)) { - mediaPages[0].listView.smoothScrollBy(0, actionBarHeight - scrollY); - } - } - } - } - - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - if (searching && searchWas) { - return; - } - int firstVisibleItem = layoutManager.findFirstVisibleItemPosition(); - int visibleItemCount = firstVisibleItem == RecyclerView.NO_POSITION ? 0 : Math.abs(layoutManager.findLastVisibleItemPosition() - firstVisibleItem) + 1; - int totalItemCount = recyclerView.getAdapter().getItemCount(); - - final int threshold = mediaPage.selectedType == 0 ? 3 : 6; - if (visibleItemCount != 0 && firstVisibleItem + visibleItemCount > totalItemCount - threshold && !sharedMediaData[mediaPage.selectedType].loading) { - int type; - if (mediaPage.selectedType == 0) { - type = MediaDataController.MEDIA_PHOTOVIDEO; - } else if (mediaPage.selectedType == 1) { - type = MediaDataController.MEDIA_FILE; - } else if (mediaPage.selectedType == 2) { - type = MediaDataController.MEDIA_AUDIO; - } else if (mediaPage.selectedType == 4) { - type = MediaDataController.MEDIA_MUSIC; - } else if (mediaPage.selectedType == 5) { - type = MediaDataController.MEDIA_GIF; - } else { - type = MediaDataController.MEDIA_URL; - } - if (!sharedMediaData[mediaPage.selectedType].endReached[0]) { - sharedMediaData[mediaPage.selectedType].loading = true; - MediaDataController.getInstance(currentAccount).loadMedia(dialogId, 50, sharedMediaData[mediaPage.selectedType].max_id[0], type, 1, classGuid); - } else if (mergeDialogId != 0 && !sharedMediaData[mediaPage.selectedType].endReached[1]) { - sharedMediaData[mediaPage.selectedType].loading = true; - MediaDataController.getInstance(currentAccount).loadMedia(mergeDialogId, 50, sharedMediaData[mediaPage.selectedType].max_id[1], type, 1, classGuid); - } - } - if (recyclerView == mediaPages[0].listView && !searching && !actionBar.isActionModeShowed() && !disableActionBarScrolling) { - float currentTranslation = actionBar.getTranslationY(); - float newTranslation = currentTranslation - dy; - if (newTranslation < -ActionBar.getCurrentActionBarHeight()) { - newTranslation = -ActionBar.getCurrentActionBarHeight(); - } else if (newTranslation > 0) { - newTranslation = 0; - } - if (newTranslation != currentTranslation) { - setScrollY(newTranslation); - } - } - updateSections(recyclerView, false); - } - }); - mediaPages[a].listView.setOnItemLongClickListener((view, position) -> { - if (actionBar.isActionModeShowed()) { - mediaPage.listView.getOnItemClickListener().onItemClick(view, position); - return true; - } - if (mediaPage.selectedType == 1 && view instanceof SharedDocumentCell) { - return MediaActivity.this.onItemLongClick(((SharedDocumentCell) view).getMessage(), view, 0); - } else if (mediaPage.selectedType == 3 && view instanceof SharedLinkCell) { - return MediaActivity.this.onItemLongClick(((SharedLinkCell) view).getMessage(), view, 0); - } else if ((mediaPage.selectedType == 2 || mediaPage.selectedType == 4) && view instanceof SharedAudioCell) { - return MediaActivity.this.onItemLongClick(((SharedAudioCell) view).getMessage(), view, 0); - } - return false; - }); - if (a == 0 && scrollToPositionOnRecreate != -1) { - layoutManager.scrollToPositionWithOffset(scrollToPositionOnRecreate, scrollToOffsetOnRecreate); - } - - final RecyclerListView listView = mediaPages[a].listView; - mediaPages[a].animatingImageView = new ClippingImageView(context) { - @Override - public void invalidate() { - super.invalidate(); - listView.invalidate(); - } - }; - mediaPages[a].animatingImageView.setVisibility(View.GONE); - mediaPages[a].listView.addOverlayView(mediaPages[a].animatingImageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - - mediaPages[a].progressView = new FlickerLoadingView(context) { - - @Override - public int getColumnsCount() { - return columnsCount; - } - - @Override - public int getViewType() { - if (mediaPage.selectedType == 0 || mediaPage.selectedType == 5) { - return 2; - } else if (mediaPage.selectedType == 1) { - return 3; - } else if (mediaPage.selectedType == 2 || mediaPage.selectedType == 4) { - return 4; - } else if (mediaPage.selectedType == 3) { - return 5; - } else if (mediaPage.selectedType == 7) { - return FlickerLoadingView.USERS_TYPE; - } - return 1; - } - - @Override - protected void onDraw(Canvas canvas) { - backgroundPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite)); - canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), backgroundPaint); - super.onDraw(canvas); - } - }; - mediaPages[a].progressView.setUseHeaderOffset(true); - mediaPages[a].progressView.showDate(false); - if (a != 0) { - mediaPages[a].setVisibility(View.GONE); - } - - mediaPages[a].emptyView = new StickerEmptyView(context, mediaPages[a].progressView, StickerEmptyView.STICKER_TYPE_SEARCH); - mediaPages[a].emptyView.setVisibility(View.GONE); - mediaPages[a].emptyView.setAnimateLayoutChange(true); - mediaPages[a].addView(mediaPages[a].emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - mediaPages[a].emptyView.setOnTouchListener((v, event) -> true); - mediaPages[a].emptyView.showProgress(true, false); - mediaPages[a].emptyView.title.setText(LocaleController.getString("NoResult", R.string.NoResult)); - mediaPages[a].emptyView.subtitle.setText(LocaleController.getString("SearchEmptyViewFilteredSubtitle2", R.string.SearchEmptyViewFilteredSubtitle2)); - mediaPages[a].emptyView.addView(mediaPages[a].progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - - mediaPages[a].listView.setEmptyView(mediaPages[a].emptyView); - mediaPages[a].listView.setAnimateEmptyView(true, 0); - } - - if (!AndroidUtilities.isTablet()) { - frameLayout.addView(fragmentContextView = new FragmentContextView(context, this, false), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, 8, 0, 0)); - } - - frameLayout.addView(actionBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - - updateTabs(); - switchToCurrentSelectedMode(false); - swipeBackEnabled = scrollSlidingTextTabStrip.getCurrentTabId() == scrollSlidingTextTabStrip.getFirstTabId(); - - return fragmentView; - } - - private boolean closeActionMode() { - if (actionBar.isActionModeShowed()) { - for (int a = 1; a >= 0; a--) { - selectedFiles[a].clear(); - } - cantDeleteMessagesCount = 0; - actionBar.hideActionMode(); - updateRowsSelection(); - return true; - } else { - return false; - } - } - - private void setScrollY(float value) { - actionBar.setTranslationY(value); - if (fragmentContextView != null) { - fragmentContextView.setTranslationY(additionalPadding + value); - } - for (int a = 0; a < mediaPages.length; a++) { - mediaPages[a].listView.setPinnedSectionOffsetY((int) value); - } - fragmentView.invalidate(); - } - - private void resetScroll() { - if (actionBar.getTranslationY() == 0) { - return; - } - AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.playTogether(ObjectAnimator.ofFloat(this, SCROLL_Y, 0)); - animatorSet.setInterpolator(new DecelerateInterpolator()); - animatorSet.setDuration(180); - animatorSet.start(); - } - - @Override - public void didReceivedNotification(int id, int account, Object... args) { - if (id == NotificationCenter.mediaDidLoad) { - long uid = (Long) args[0]; - int guid = (Integer) args[3]; - if (guid == classGuid) { - int type = (Integer) args[4]; - sharedMediaData[type].loading = false; - sharedMediaData[type].totalCount = (Integer) args[1]; - ArrayList arr = (ArrayList) args[2]; - boolean enc = DialogObject.isEncryptedDialog(dialogId); - int loadIndex = uid == dialogId ? 0 : 1; - - RecyclerListView.Adapter adapter = null; - if (type == 0) { - adapter = photoVideoAdapter; - } else if (type == 1) { - adapter = documentsAdapter; - } else if (type == 2) { - adapter = voiceAdapter; - } else if (type == 3) { - adapter = linksAdapter; - } else if (type == 4) { - adapter = audioAdapter; - } - int oldItemCount; - if (adapter != null) { - oldItemCount = adapter.getItemCount(); - if (adapter instanceof RecyclerListView.SectionsAdapter) { - RecyclerListView.SectionsAdapter sectionsAdapter = (RecyclerListView.SectionsAdapter) adapter; - sectionsAdapter.notifySectionsChanged(); - } - } else { - oldItemCount = 0; - } - for (int a = 0; a < arr.size(); a++) { - MessageObject message = arr.get(a); - sharedMediaData[type].addMessage(message, loadIndex, false, enc); - } - sharedMediaData[type].endReached[loadIndex] = (Boolean) args[5]; - if (loadIndex == 0 && sharedMediaData[type].endReached[loadIndex] && mergeDialogId != 0) { - sharedMediaData[type].loading = true; - MediaDataController.getInstance(currentAccount).loadMedia(mergeDialogId, 50, sharedMediaData[type].max_id[1], type, 1, classGuid); - } - if (adapter != null) { - for (int a = 0; a < mediaPages.length; a++) { - if (mediaPages[a].listView.getAdapter() == adapter) { - mediaPages[a].listView.stopScroll(); - } - } - if (sharedMediaData[type].messages.size() == 0 && !sharedMediaData[type].loading) { - adapter.notifyDataSetChanged(); - } else { - int newItemCount = adapter.getItemCount(); - if (oldItemCount > 1) { - adapter.notifyItemChanged(oldItemCount - 2); - } - if (newItemCount > oldItemCount) { - adapter.notifyItemRangeInserted(oldItemCount, newItemCount); - } else if (newItemCount < oldItemCount) { - adapter.notifyItemRangeRemoved(newItemCount, (oldItemCount - newItemCount)); - } - } - } - scrolling = true; - for (int a = 0; a < mediaPages.length; a++) { - if (oldItemCount == 0 && actionBar.getTranslationY() != 0 && mediaPages[a].listView.getAdapter() == adapter) { - mediaPages[a].layoutManager.scrollToPositionWithOffset(0, (int) actionBar.getTranslationY()); - } - } - } - } else if (id == NotificationCenter.messagesDeleted) { - boolean scheduled = (Boolean) args[2]; - if (scheduled) { - return; - } - TLRPC.Chat currentChat = null; - if (DialogObject.isChatDialog(dialogId)) { - currentChat = MessagesController.getInstance(currentAccount).getChat(-dialogId); - } - long channelId = (Long) args[1]; - int loadIndex = 0; - if (ChatObject.isChannel(currentChat)) { - if (channelId == 0 && mergeDialogId != 0) { - loadIndex = 1; - } else if (channelId == currentChat.id) { - loadIndex = 0; - } else { - return; - } - } else if (channelId != 0) { - return; - } - ArrayList markAsDeletedMessages = (ArrayList) args[0]; - boolean updated = false; - for (int a = 0, N = markAsDeletedMessages.size(); a < N; a++) { - for (int b = 0; b < sharedMediaData.length; b++) { - if (sharedMediaData[b].deleteMessage(markAsDeletedMessages.get(a), loadIndex) != null) { - updated = true; - } - } - } - if (updated) { - scrolling = true; - if (photoVideoAdapter != null) { - photoVideoAdapter.notifyDataSetChanged(); - } - if (documentsAdapter != null) { - documentsAdapter.notifyDataSetChanged(); - } - if (voiceAdapter != null) { - voiceAdapter.notifyDataSetChanged(); - } - if (linksAdapter != null) { - linksAdapter.notifyDataSetChanged(); - } - if (audioAdapter != null) { - audioAdapter.notifyDataSetChanged(); - } - } - } else if (id == NotificationCenter.didReceiveNewMessages) { - boolean scheduled = (Boolean) args[2]; - if (scheduled) { - return; - } - long uid = (Long) args[0]; - if (uid == dialogId) { - ArrayList arr = (ArrayList) args[1]; - boolean enc = DialogObject.isEncryptedDialog(dialogId); - boolean updated = false; - for (int a = 0; a < arr.size(); a++) { - MessageObject obj = arr.get(a); - if (obj.messageOwner.media == null || obj.needDrawBluredPreview()) { - continue; - } - int type = MediaDataController.getMediaType(obj.messageOwner); - if (type == -1) { - return; - } - if (sharedMediaData[type].addMessage(obj, obj.getDialogId() == dialogId ? 0 : 1, true, enc)) { - updated = true; - hasMedia[type] = 1; - } - } - if (updated) { - scrolling = true; - for (int a = 0; a < mediaPages.length; a++) { - RecyclerListView.Adapter adapter = null; - if (mediaPages[a].selectedType == 0) { - adapter = photoVideoAdapter; - } else if (mediaPages[a].selectedType == 1) { - adapter = documentsAdapter; - } else if (mediaPages[a].selectedType == 2) { - adapter = voiceAdapter; - } else if (mediaPages[a].selectedType == 3) { - adapter = linksAdapter; - } else if (mediaPages[a].selectedType == 4) { - adapter = audioAdapter; - } - if (adapter != null) { - int count = adapter.getItemCount(); - photoVideoAdapter.notifyDataSetChanged(); - documentsAdapter.notifyDataSetChanged(); - voiceAdapter.notifyDataSetChanged(); - linksAdapter.notifyDataSetChanged(); - audioAdapter.notifyDataSetChanged(); - if (count == 0 && actionBar.getTranslationY() != 0) { - mediaPages[a].layoutManager.scrollToPositionWithOffset(0, (int) actionBar.getTranslationY()); - } - } - } - updateTabs(); - } - } - } else if (id == NotificationCenter.messageReceivedByServer) { - Boolean scheduled = (Boolean) args[6]; - if (scheduled) { - return; - } - Integer msgId = (Integer) args[0]; - Integer newMsgId = (Integer) args[1]; - for (int a = 0; a < sharedMediaData.length; a++) { - sharedMediaData[a].replaceMid(msgId, newMsgId); - } - } - } - - @Override - public void onResume() { - super.onResume(); - scrolling = true; - if (photoVideoAdapter != null) { - photoVideoAdapter.notifyDataSetChanged(); - } - if (documentsAdapter != null) { - documentsAdapter.notifyDataSetChanged(); - } - if (linksAdapter != null) { - linksAdapter.notifyDataSetChanged(); - } - for (int a = 0; a < mediaPages.length; a++) { - fixLayoutInternal(a); - } - } - - @Override - public boolean isSwipeBackEnabled(MotionEvent event) { - return swipeBackEnabled; - } - - @Override - public void onConfigurationChanged(android.content.res.Configuration newConfig) { - super.onConfigurationChanged(newConfig); - for (int a = 0; a < mediaPages.length; a++) { - if (mediaPages[a].listView != null) { - final int num = a; - ViewTreeObserver obs = mediaPages[a].listView.getViewTreeObserver(); - obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - mediaPages[num].getViewTreeObserver().removeOnPreDrawListener(this); - fixLayoutInternal(num); - return true; - } - }); - } - } - } - - @Override - public boolean onBackPressed() { - return actionBar.isEnabled() && !closeActionMode(); - } - - private void updateSections(RecyclerView listView, boolean checkTopBottom) { - int count = listView.getChildCount(); - int minPositionDateHolder = Integer.MAX_VALUE; - View minDateChild = null; - float padding = listView.getPaddingTop() + actionBar.getTranslationY(); - int minTop = Integer.MAX_VALUE; - int maxBottom = 0; - - for (int a = 0; a < count; a++) { - View view = listView.getChildAt(a); - int bottom = view.getBottom(); - minTop = Math.min(minTop, view.getTop()); - maxBottom = Math.max(bottom, maxBottom); - if (bottom <= padding) { - continue; - } - int position = view.getBottom(); - if (view instanceof SharedMediaSectionCell || view instanceof GraySectionCell) { - if (view.getAlpha() != 1.0f) { - view.setAlpha(1.0f); - } - if (position < minPositionDateHolder) { - minPositionDateHolder = position; - minDateChild = view; - } - } - } - if (minDateChild != null) { - if (minDateChild.getTop() > padding) { - if (minDateChild.getAlpha() != 1.0f) { - minDateChild.setAlpha(1.0f); - } - } else { - if (minDateChild.getAlpha() != 0.0f) { - minDateChild.setAlpha(0.0f); - } - } - } - if (checkTopBottom) { - if (maxBottom != 0 && maxBottom < (listView.getMeasuredHeight() - listView.getPaddingBottom())) { - resetScroll(); - } else if (minTop != Integer.MAX_VALUE && minTop > listView.getPaddingTop() + actionBar.getTranslationY()) { - scrollWithoutActionBar(listView, -listView.computeVerticalScrollOffset()); - resetScroll(); - } - } - } - - public void setChatInfo(TLRPC.ChatFull chatInfo) { - info = chatInfo; - if (info != null && info.migrated_from_chat_id != 0 && mergeDialogId == 0) { - mergeDialogId = -info.migrated_from_chat_id; - for (int a = 0; a < sharedMediaData.length; a++) { - sharedMediaData[a].max_id[1] = info.migrated_from_max_id; - sharedMediaData[a].endReached[1] = false; - } - } - } - - public void updateAdapters() { - if (photoVideoAdapter != null) { - photoVideoAdapter.notifyDataSetChanged(); - } - if (documentsAdapter != null) { - documentsAdapter.notifyDataSetChanged(); - } - if (voiceAdapter != null) { - voiceAdapter.notifyDataSetChanged(); - } - if (linksAdapter != null) { - linksAdapter.notifyDataSetChanged(); - } - if (audioAdapter != null) { - audioAdapter.notifyDataSetChanged(); - } - } - - private void updateRowsSelection() { - for (int i = 0; i < mediaPages.length; i++) { - int count = mediaPages[i].listView.getChildCount(); - for (int a = 0; a < count; a++) { - View child = mediaPages[i].listView.getChildAt(a); - if (child instanceof SharedDocumentCell) { - ((SharedDocumentCell) child).setChecked(false, true); - } else if (child instanceof SharedPhotoVideoCell) { - for (int b = 0; b < 6; b++) { - ((SharedPhotoVideoCell) child).setChecked(b, false, true); - } - } else if (child instanceof SharedLinkCell) { - ((SharedLinkCell) child).setChecked(false, true); - } else if (child instanceof SharedAudioCell) { - ((SharedAudioCell) child).setChecked(false, true); - } - } - } - } - - public void setMergeDialogId(long did) { - mergeDialogId = did; - } - - private void updateTabs() { - if (scrollSlidingTextTabStrip == null) { - return; - } - boolean changed = false; - if ((hasMedia[0] != 0 || hasMedia[1] == 0 && hasMedia[2] == 0 && hasMedia[3] == 0 && hasMedia[4] == 0) && !scrollSlidingTextTabStrip.hasTab(0)) { - changed = true; - } - if (hasMedia[1] != 0) { - if (!scrollSlidingTextTabStrip.hasTab(1)) { - changed = true; - } - } - if (!DialogObject.isEncryptedDialog(dialogId)) { - if (hasMedia[3] != 0 && !scrollSlidingTextTabStrip.hasTab(3)) { - changed = true; - } - if (hasMedia[4] != 0 && !scrollSlidingTextTabStrip.hasTab(4)) { - changed = true; - } - } else { - if (hasMedia[4] != 0 && !scrollSlidingTextTabStrip.hasTab(4)) { - changed = true; - } - } - if (hasMedia[2] != 0 && !scrollSlidingTextTabStrip.hasTab(2)) { - changed = true; - } - if (changed) { - scrollSlidingTextTabStrip.removeTabs(); - if (hasMedia[0] != 0 || hasMedia[1] == 0 && hasMedia[2] == 0 && hasMedia[3] == 0 && hasMedia[4] == 0) { - if (!scrollSlidingTextTabStrip.hasTab(0)) { - scrollSlidingTextTabStrip.addTextTab(0, LocaleController.getString("SharedMediaTab2", R.string.SharedMediaTab2)); - } - } - if (hasMedia[1] != 0) { - if (!scrollSlidingTextTabStrip.hasTab(1)) { - scrollSlidingTextTabStrip.addTextTab(1, LocaleController.getString("SharedFilesTab2", R.string.SharedFilesTab2)); - } - } - if (!DialogObject.isEncryptedDialog(dialogId)) { - if (hasMedia[3] != 0) { - if (!scrollSlidingTextTabStrip.hasTab(3)) { - scrollSlidingTextTabStrip.addTextTab(3, LocaleController.getString("SharedLinksTab2", R.string.SharedLinksTab2)); - } - } - if (hasMedia[4] != 0) { - if (!scrollSlidingTextTabStrip.hasTab(4)) { - scrollSlidingTextTabStrip.addTextTab(4, LocaleController.getString("SharedMusicTab2", R.string.SharedMusicTab2)); - } - } - } else { - if (hasMedia[4] != 0) { - if (!scrollSlidingTextTabStrip.hasTab(4)) { - scrollSlidingTextTabStrip.addTextTab(4, LocaleController.getString("SharedMusicTab2", R.string.SharedMusicTab2)); - } - } - } - if (hasMedia[2] != 0) { - if (!scrollSlidingTextTabStrip.hasTab(2)) { - scrollSlidingTextTabStrip.addTextTab(2, LocaleController.getString("SharedVoiceTab2", R.string.SharedVoiceTab2)); - } - } - } - if (scrollSlidingTextTabStrip.getTabsCount() <= 1) { - scrollSlidingTextTabStrip.setVisibility(View.GONE); - actionBar.setExtraHeight(0); - } else { - scrollSlidingTextTabStrip.setVisibility(View.VISIBLE); - actionBar.setExtraHeight(AndroidUtilities.dp(44)); - } - int id = scrollSlidingTextTabStrip.getCurrentTabId(); - if (id >= 0) { - mediaPages[0].selectedType = id; - } - scrollSlidingTextTabStrip.finishAddingTabs(); - } - - private void switchToCurrentSelectedMode(boolean animated) { - for (int a = 0; a < mediaPages.length; a++) { - mediaPages[a].listView.stopScroll(); - } - int a = animated ? 1 : 0; - RecyclerView.Adapter currentAdapter = mediaPages[a].listView.getAdapter(); - if (searching && searchWas) { - if (animated) { - if (mediaPages[a].selectedType == 0 || mediaPages[a].selectedType == 2) { - searching = false; - searchWas = false; - switchToCurrentSelectedMode(true); - return; - } else { - String text = searchItem.getSearchField().getText().toString(); - if (mediaPages[a].selectedType == 1) { - if (documentsSearchAdapter != null) { - documentsSearchAdapter.search(text); - if (currentAdapter != documentsSearchAdapter) { - recycleAdapter(currentAdapter); - mediaPages[a].listView.setAdapter(documentsSearchAdapter); - } - } - } else if (mediaPages[a].selectedType == 3) { - if (linksSearchAdapter != null) { - linksSearchAdapter.search(text); - if (currentAdapter != linksSearchAdapter) { - recycleAdapter(currentAdapter); - mediaPages[a].listView.setAdapter(linksSearchAdapter); - } - } - } else if (mediaPages[a].selectedType == 4) { - if (audioSearchAdapter != null) { - audioSearchAdapter.search(text); - if (currentAdapter != audioSearchAdapter) { - recycleAdapter(currentAdapter); - mediaPages[a].listView.setAdapter(audioSearchAdapter); - } - } - } - } - } else { - if (mediaPages[a].listView != null) { - if (mediaPages[a].selectedType == 1) { - if (currentAdapter != documentsSearchAdapter) { - recycleAdapter(currentAdapter); - mediaPages[a].listView.setAdapter(documentsSearchAdapter); - } - documentsSearchAdapter.notifyDataSetChanged(); - } else if (mediaPages[a].selectedType == 3) { - if (currentAdapter != linksSearchAdapter) { - recycleAdapter(currentAdapter); - mediaPages[a].listView.setAdapter(linksSearchAdapter); - } - linksSearchAdapter.notifyDataSetChanged(); - } else if (mediaPages[a].selectedType == 4) { - if (currentAdapter != audioSearchAdapter) { - recycleAdapter(currentAdapter); - mediaPages[a].listView.setAdapter(audioSearchAdapter); - } - audioSearchAdapter.notifyDataSetChanged(); - } - } - } - - } else { - mediaPages[a].listView.setPinnedHeaderShadowDrawable(null); - - if (mediaPages[a].selectedType == 0) { - if (currentAdapter != photoVideoAdapter) { - recycleAdapter(currentAdapter); - mediaPages[a].listView.setAdapter(photoVideoAdapter); - } - mediaPages[a].listView.setPinnedHeaderShadowDrawable(pinnedHeaderShadowDrawable); - } else if (mediaPages[a].selectedType == 1) { - if (currentAdapter != documentsAdapter) { - recycleAdapter(currentAdapter); - mediaPages[a].listView.setAdapter(documentsAdapter); - } - } else if (mediaPages[a].selectedType == 2) { - if (currentAdapter != voiceAdapter) { - recycleAdapter(currentAdapter); - mediaPages[a].listView.setAdapter(voiceAdapter); - } - } else if (mediaPages[a].selectedType == 3) { - if (currentAdapter != linksAdapter) { - recycleAdapter(currentAdapter); - mediaPages[a].listView.setAdapter(linksAdapter); - } - } else if (mediaPages[a].selectedType == 4) { - if (currentAdapter != audioAdapter) { - recycleAdapter(currentAdapter); - mediaPages[a].listView.setAdapter(audioAdapter); - } - } - if (mediaPages[a].selectedType == 0 || mediaPages[a].selectedType == 2) { - if (animated) { - searchItemState = 2; - } else { - searchItemState = 0; - searchItem.setVisibility(View.INVISIBLE); - } - } else { - if (animated) { - if (searchItem.getVisibility() == View.INVISIBLE && !actionBar.isSearchFieldVisible()) { - searchItemState = 1; - searchItem.setVisibility(View.VISIBLE); - searchItem.setAlpha(0.0f); - } else { - searchItemState = 0; - } - } else if (searchItem.getVisibility() == View.INVISIBLE) { - searchItemState = 0; - searchItem.setAlpha(1.0f); - searchItem.setVisibility(View.VISIBLE); - } - } - if (!sharedMediaData[mediaPages[a].selectedType].loading && !sharedMediaData[mediaPages[a].selectedType].endReached[0] && sharedMediaData[mediaPages[a].selectedType].messages.isEmpty()) { - sharedMediaData[mediaPages[a].selectedType].loading = true; - MediaDataController.getInstance(currentAccount).loadMedia(dialogId, 50, 0, mediaPages[a].selectedType, 1, classGuid); - } - mediaPages[a].listView.setVisibility(View.VISIBLE); - } - if (searchItemState == 2 && actionBar.isSearchFieldVisible()) { - ignoreSearchCollapse = true; - actionBar.closeSearchField(); - } - - if (actionBar.getTranslationY() != 0) { - mediaPages[a].layoutManager.scrollToPositionWithOffset(0, (int) actionBar.getTranslationY()); - } - } - - private boolean onItemLongClick(MessageObject item, View view, int a) { - if (actionBar.isActionModeShowed() || getParentActivity() == null) { - return false; - } - AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); - selectedFiles[item.getDialogId() == dialogId ? 0 : 1].put(item.getId(), item); - if (!item.canDeleteMessage(false, null)) { - cantDeleteMessagesCount++; - } - actionBar.createActionMode().getItem(delete).setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); - if (gotoItem != null) { - gotoItem.setVisibility(View.VISIBLE); - } - selectedMessagesCountTextView.setNumber(1, false); - AnimatorSet animatorSet = new AnimatorSet(); - ArrayList animators = new ArrayList<>(); - for (int i = 0; i < actionModeViews.size(); i++) { - View view2 = actionModeViews.get(i); - AndroidUtilities.clearDrawableAnimation(view2); - animators.add(ObjectAnimator.ofFloat(view2, View.SCALE_Y, 0.1f, 1.0f)); - } - animatorSet.playTogether(animators); - animatorSet.setDuration(250); - animatorSet.start(); - scrolling = false; - if (view instanceof SharedDocumentCell) { - ((SharedDocumentCell) view).setChecked(true, true); - } else if (view instanceof SharedPhotoVideoCell) { - ((SharedPhotoVideoCell) view).setChecked(a, true, true); - } else if (view instanceof SharedLinkCell) { - ((SharedLinkCell) view).setChecked(true, true); - } else if (view instanceof SharedAudioCell) { - ((SharedAudioCell) view).setChecked(true, true); - } - if (!actionBar.isActionModeShowed()) { - actionBar.showActionMode(true, null, actionModeBackground, null, null, null, 0); - resetScroll(); - } - return true; - } - - private void onItemClick(int index, View view, MessageObject message, int a, int selectedMode) { - if (message == null) { - return; - } - if (actionBar.isActionModeShowed()) { - int loadIndex = message.getDialogId() == dialogId ? 0 : 1; - if (selectedFiles[loadIndex].indexOfKey(message.getId()) >= 0) { - selectedFiles[loadIndex].remove(message.getId()); - if (!message.canDeleteMessage(false, null)) { - cantDeleteMessagesCount--; - } - } else { - if (selectedFiles[0].size() + selectedFiles[1].size() >= 100) { - return; - } - selectedFiles[loadIndex].put(message.getId(), message); - if (!message.canDeleteMessage(false, null)) { - cantDeleteMessagesCount++; - } - } - if (selectedFiles[0].size() == 0 && selectedFiles[1].size() == 0) { - actionBar.hideActionMode(); - } else { - selectedMessagesCountTextView.setNumber(selectedFiles[0].size() + selectedFiles[1].size(), true); - actionBar.createActionMode().getItem(delete).setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); - if (gotoItem != null) { - gotoItem.setVisibility(selectedFiles[0].size() == 1 ? View.VISIBLE : View.GONE); - } - } - scrolling = false; - if (view instanceof SharedDocumentCell) { - ((SharedDocumentCell) view).setChecked(selectedFiles[loadIndex].indexOfKey(message.getId()) >= 0, true); - } else if (view instanceof SharedPhotoVideoCell) { - ((SharedPhotoVideoCell) view).setChecked(a, selectedFiles[loadIndex].indexOfKey(message.getId()) >= 0, true); - } else if (view instanceof SharedLinkCell) { - ((SharedLinkCell) view).setChecked(selectedFiles[loadIndex].indexOfKey(message.getId()) >= 0, true); - } else if (view instanceof SharedAudioCell) { - ((SharedAudioCell) view).setChecked(selectedFiles[loadIndex].indexOfKey(message.getId()) >= 0, true); - } - } else { - if (selectedMode == 0) { - PhotoViewer.getInstance().setParentActivity(getParentActivity()); - PhotoViewer.getInstance().openPhoto(sharedMediaData[selectedMode].messages, index, dialogId, mergeDialogId, provider); - } else if (selectedMode == 2 || selectedMode == 4) { - if (view instanceof SharedAudioCell) { - ((SharedAudioCell) view).didPressedButton(); - } - } else if (selectedMode == 1) { - if (view instanceof SharedDocumentCell) { - SharedDocumentCell cell = (SharedDocumentCell) view; - TLRPC.Document document = message.getDocument(); - if (cell.isLoaded()) { - if (message.canPreviewDocument()) { - PhotoViewer.getInstance().setParentActivity(getParentActivity()); - index = sharedMediaData[selectedMode].messages.indexOf(message); - if (index < 0) { - ArrayList documents = new ArrayList<>(); - documents.add(message); - PhotoViewer.getInstance().openPhoto(documents, 0, 0, 0, provider); - } else { - PhotoViewer.getInstance().openPhoto(sharedMediaData[selectedMode].messages, index, dialogId, mergeDialogId, provider); - } - return; - } - AndroidUtilities.openDocument(message, getParentActivity(), this); - } else if (!cell.isLoading()) { - MessageObject messageObject = cell.getMessage(); - FileLoader.getInstance(currentAccount).loadFile(document, messageObject, 0, 0); - cell.updateFileExistIcon(true); - } else { - FileLoader.getInstance(currentAccount).cancelLoadFile(document); - cell.updateFileExistIcon(true); - } - } - } else if (selectedMode == 3) { - try { - TLRPC.WebPage webPage = message.messageOwner.media != null ? message.messageOwner.media.webpage : null; - String link = null; - if (webPage != null && !(webPage instanceof TLRPC.TL_webPageEmpty)) { - if (webPage.cached_page != null) { - ArticleViewer.getInstance().setParentActivity(getParentActivity(), MediaActivity.this); - ArticleViewer.getInstance().open(message); - return; - } else if (webPage.embed_url != null && webPage.embed_url.length() != 0) { - openWebView(webPage, message); - return; - } else { - link = webPage.url; - } - } - if (link == null) { - link = ((SharedLinkCell) view).getLink(0); - } - if (link != null) { - openUrl(link); - } - } catch (Exception e) { - FileLog.e(e); - } - } - } - } - - private void openUrl(String link) { - if (AndroidUtilities.shouldShowUrlInAlert(link)) { - AlertsCreator.showOpenUrlAlert(this, link, true, true); - } else { - Browser.openUrl(getParentActivity(), link); - } - } - - private void openWebView(TLRPC.WebPage webPage, MessageObject messageObject) { - EmbedBottomSheet.show(getParentActivity(), messageObject, provider, webPage.site_name, webPage.description, webPage.url, webPage.embed_url, webPage.embed_width, webPage.embed_height, false); - } - - private void recycleAdapter(RecyclerView.Adapter adapter) { - if (adapter instanceof SharedPhotoVideoAdapter) { - cellCache.addAll(cache); - cache.clear(); - } else if (adapter == audioAdapter) { - audioCellCache.addAll(audioCache); - audioCache.clear(); - } - } - - private void fixLayoutInternal(int num) { - WindowManager manager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); - int rotation = manager.getDefaultDisplay().getRotation(); - if (num == 0) { - if (!AndroidUtilities.isTablet() && ApplicationLoader.applicationContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { - selectedMessagesCountTextView.setTextSize(18); - } else { - selectedMessagesCountTextView.setTextSize(20); - } - } - - if (AndroidUtilities.isTablet()) { - columnsCount = 3; - } else { - if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) { - columnsCount = 6; - } else { - columnsCount = 3; - } - } - if (num == 0) { - photoVideoAdapter.notifyDataSetChanged(); - fixScrollOffset(); - } - } - - private void fixScrollOffset() { - if (actionBar.getTranslationY() != 0f) { - final RecyclerListView listView = mediaPages[0].listView; - final View child = listView.getChildAt(0); - if (child != null) { - final int offset = (int) (child.getY() - (actionBar.getMeasuredHeight() + actionBar.getTranslationY() + additionalPadding)); - if (offset > 0) { - scrollWithoutActionBar(listView, offset); - } - } - } - } - - private void scrollWithoutActionBar(RecyclerView listView, int dy) { - disableActionBarScrolling = true; - listView.scrollBy(0, dy); - disableActionBarScrolling = false; - } - - SharedLinkCell.SharedLinkCellDelegate sharedLinkCellDelegate = new SharedLinkCell.SharedLinkCellDelegate() { - @Override - public void needOpenWebView(TLRPC.WebPage webPage, MessageObject message) { - MediaActivity.this.openWebView(webPage, message); - } - - @Override - public boolean canPerformActions() { - return !actionBar.isActionModeShowed(); - } - - @Override - public void onLinkPress(String urlFinal, boolean longPress) { - if (longPress) { - BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity()); - builder.setTitle(urlFinal); - builder.setItems(new CharSequence[]{LocaleController.getString("Open", R.string.Open), LocaleController.getString("Copy", R.string.Copy)}, (dialog, which) -> { - if (which == 0) { - openUrl(urlFinal); - } else if (which == 1) { - String url = urlFinal; - if (url.startsWith("mailto:")) { - url = url.substring(7); - } else if (url.startsWith("tel:")) { - url = url.substring(4); - } - AndroidUtilities.addToClipboard(url); - } - }); - showDialog(builder.create()); - } else { - openUrl(urlFinal); - } - } - }; - - private class SharedLinksAdapter extends RecyclerListView.SectionsAdapter { - - private Context mContext; - - public SharedLinksAdapter(Context context) { - mContext = context; - } - - @Override - public Object getItem(int section, int position) { - return null; - } - - @Override - public boolean isEnabled(RecyclerView.ViewHolder holder, int section, int row) { - return row != 0; - } - - @Override - public int getSectionCount() { - if (sharedMediaData[3].sections.size() == 0 && !sharedMediaData[3].loading) { - return 1; - } - return sharedMediaData[3].sections.size() + (sharedMediaData[3].sections.isEmpty() || sharedMediaData[3].endReached[0] && sharedMediaData[3].endReached[1] ? 0 : 1); - } - - @Override - public int getCountForSection(int section) { - if (sharedMediaData[3].sections.size() == 0 && !sharedMediaData[3].loading) { - return 1; - } - if (section < sharedMediaData[3].sections.size()) { - return sharedMediaData[3].sectionArrays.get(sharedMediaData[3].sections.get(section)).size() + 1; - } - return 1; - } - - @Override - public View getSectionHeaderView(int section, View view) { - if (view == null) { - view = new GraySectionCell(mContext); - view.setBackgroundColor(Theme.getColor(Theme.key_graySection) & 0xf2ffffff); - } - if (sharedMediaData[3].sections.size() == 0) { - view.setAlpha(0); - } else if (section < sharedMediaData[3].sections.size()) { - view.setAlpha(1f); - String name = sharedMediaData[3].sections.get(section); - ArrayList messageObjects = sharedMediaData[3].sectionArrays.get(name); - MessageObject messageObject = messageObjects.get(0); - ((GraySectionCell) view).setText(LocaleController.formatSectionDate(messageObject.messageOwner.date)); - } - return view; - } - - @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view; - switch (viewType) { - case 0: - view = new GraySectionCell(mContext); - break; - case 1: - view = new SharedLinkCell(mContext); - ((SharedLinkCell) view).setDelegate(sharedLinkCellDelegate); - break; - case 3: - View emptyStubView = SharedMediaLayout.createEmptyStubView(mContext, 3, dialogId); - emptyStubView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - return new RecyclerListView.Holder(emptyStubView); - case 2: - default: - view = new LoadingCell(mContext, AndroidUtilities.dp(32), AndroidUtilities.dp(54)); - break; - } - return new RecyclerListView.Holder(view); - } - - @Override - public void onBindViewHolder(int section, int position, RecyclerView.ViewHolder holder) { - if (holder.getItemViewType() != 2 && holder.getItemViewType() != 3) { - String name = sharedMediaData[3].sections.get(section); - ArrayList messageObjects = sharedMediaData[3].sectionArrays.get(name); - switch (holder.getItemViewType()) { - case 0: { - MessageObject messageObject = messageObjects.get(0); - ((GraySectionCell) holder.itemView).setText(LocaleController.formatSectionDate(messageObject.messageOwner.date)); - break; - } - case 1: { - SharedLinkCell sharedLinkCell = (SharedLinkCell) holder.itemView; - MessageObject messageObject = messageObjects.get(position - 1); - sharedLinkCell.setLink(messageObject, position != messageObjects.size() || section == sharedMediaData[3].sections.size() - 1 && sharedMediaData[3].loading); - if (actionBar.isActionModeShowed()) { - sharedLinkCell.setChecked(selectedFiles[messageObject.getDialogId() == dialogId ? 0 : 1].indexOfKey(messageObject.getId()) >= 0, !scrolling); - } else { - sharedLinkCell.setChecked(false, !scrolling); - } - break; - } - } - } - } - - @Override - public int getItemViewType(int section, int position) { - if (sharedMediaData[3].sections.size() == 0 && !sharedMediaData[3].loading) { - return 3; - } - if (section < sharedMediaData[3].sections.size()) { - if (position == 0) { - return 0; - } else { - return 1; - } - } - return 2; - } - - @Override - public String getLetter(int position) { - return null; - } - - @Override - public int getPositionForScrollProgress(float progress) { - return 0; - } - } - - private class SharedDocumentsAdapter extends RecyclerListView.SectionsAdapter { - - private Context mContext; - private int currentType; - - public SharedDocumentsAdapter(Context context, int type) { - mContext = context; - currentType = type; - } - - @Override - public boolean isEnabled(RecyclerView.ViewHolder holder, int section, int row) { - return row != 0; - } - - @Override - public int getSectionCount() { - if (sharedMediaData[currentType].sections.size() == 0 && !sharedMediaData[currentType].loading) { - return 1; - } - return sharedMediaData[currentType].sections.size() + (sharedMediaData[currentType].sections.isEmpty() || sharedMediaData[currentType].endReached[0] && sharedMediaData[currentType].endReached[1] ? 0 : 1); - } - - @Override - public Object getItem(int section, int position) { - return null; - } - - @Override - public int getCountForSection(int section) { - if (sharedMediaData[currentType].sections.size() == 0 && !sharedMediaData[currentType].loading) { - return 1; - } - if (section < sharedMediaData[currentType].sections.size()) { - return sharedMediaData[currentType].sectionArrays.get(sharedMediaData[currentType].sections.get(section)).size() + 1; - } - return 1; - } - - @Override - public View getSectionHeaderView(int section, View view) { - if (view == null) { - view = new GraySectionCell(mContext); - view.setBackgroundColor(Theme.getColor(Theme.key_graySection) & 0xf2ffffff); - } - if (sharedMediaData[currentType].sections.size() == 0) { - view.setAlpha(0); - } else if (section < sharedMediaData[currentType].sections.size()) { - view.setAlpha(1f); - String name = sharedMediaData[currentType].sections.get(section); - ArrayList messageObjects = sharedMediaData[currentType].sectionArrays.get(name); - MessageObject messageObject = messageObjects.get(0); - ((GraySectionCell) view).setText(LocaleController.formatSectionDate(messageObject.messageOwner.date)); - } - return view; - } - - @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view; - switch (viewType) { - case 0: - view = new GraySectionCell(mContext); - break; - case 1: - view = new SharedDocumentCell(mContext); - break; - case 2: - view = new LoadingCell(mContext, AndroidUtilities.dp(32), AndroidUtilities.dp(54)); - break; - case 4: - View emptyStubView = SharedMediaLayout.createEmptyStubView(mContext, currentType, dialogId); - emptyStubView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - return new RecyclerListView.Holder(emptyStubView); - case 3: - default: - if (currentType == MediaDataController.MEDIA_MUSIC && !audioCellCache.isEmpty()) { - view = audioCellCache.get(0); - audioCellCache.remove(0); - ViewGroup p = (ViewGroup) view.getParent(); - if (p != null) { - p.removeView(view); - } - } else { - view = new SharedAudioCell(mContext) { - @Override - public boolean needPlayMessage(MessageObject messageObject) { - if (messageObject.isVoice() || messageObject.isRoundVideo()) { - boolean result = MediaController.getInstance().playMessage(messageObject); - MediaController.getInstance().setVoiceMessagesPlaylist(result ? sharedMediaData[currentType].messages : null, false); - return result; - } else if (messageObject.isMusic()) { - return MediaController.getInstance().setPlaylist(sharedMediaData[currentType].messages, messageObject, mergeDialogId); - } - return false; - } - }; - } - if (currentType == MediaDataController.MEDIA_MUSIC) { - audioCache.add((SharedAudioCell) view); - } - break; - } - return new RecyclerListView.Holder(view); - } - - @Override - public void onBindViewHolder(int section, int position, RecyclerView.ViewHolder holder) { - if (holder.getItemViewType() != 2 && holder.getItemViewType() != 4) { - String name = sharedMediaData[currentType].sections.get(section); - ArrayList messageObjects = sharedMediaData[currentType].sectionArrays.get(name); - switch (holder.getItemViewType()) { - case 0: { - MessageObject messageObject = messageObjects.get(0); - ((GraySectionCell) holder.itemView).setText(LocaleController.formatSectionDate(messageObject.messageOwner.date)); - break; - } - case 1: { - SharedDocumentCell sharedDocumentCell = (SharedDocumentCell) holder.itemView; - MessageObject messageObject = messageObjects.get(position - 1); - sharedDocumentCell.setDocument(messageObject, position != messageObjects.size() || section == sharedMediaData[currentType].sections.size() - 1 && sharedMediaData[currentType].loading); - if (actionBar.isActionModeShowed()) { - sharedDocumentCell.setChecked(selectedFiles[messageObject.getDialogId() == dialogId ? 0 : 1].indexOfKey(messageObject.getId()) >= 0, !scrolling); - } else { - sharedDocumentCell.setChecked(false, !scrolling); - } - break; - } - case 3: { - SharedAudioCell sharedAudioCell = (SharedAudioCell) holder.itemView; - MessageObject messageObject = messageObjects.get(position - 1); - sharedAudioCell.setMessageObject(messageObject, position != messageObjects.size() || section == sharedMediaData[currentType].sections.size() - 1 && sharedMediaData[currentType].loading); - if (actionBar.isActionModeShowed()) { - sharedAudioCell.setChecked(selectedFiles[messageObject.getDialogId() == dialogId ? 0 : 1].indexOfKey(messageObject.getId()) >= 0, !scrolling); - } else { - sharedAudioCell.setChecked(false, !scrolling); - } - break; - } - } - } - } - - @Override - public int getItemViewType(int section, int position) { - if (sharedMediaData[currentType].sections.size() == 0 && !sharedMediaData[currentType].loading) { - return 4; - } - if (section < sharedMediaData[currentType].sections.size()) { - if (position == 0) { - return 0; - } else { - if (currentType == 2 || currentType == 4) { - return 3; - } else { - return 1; - } - } - } - return 2; - } - - @Override - public String getLetter(int position) { - return null; - } - - @Override - public int getPositionForScrollProgress(float progress) { - return 0; - } - } - - private class SharedPhotoVideoAdapter extends RecyclerListView.SectionsAdapter { - - private Context mContext; - - public SharedPhotoVideoAdapter(Context context) { - mContext = context; - } - - @Override - public Object getItem(int section, int position) { - return null; - } - - @Override - public boolean isEnabled(RecyclerView.ViewHolder holder, int section, int row) { - return false; - } - - @Override - public int getSectionCount() { - if (sharedMediaData[0].sections.size() == 0 && !sharedMediaData[0].loading) { - return 1; - } - return sharedMediaData[0].sections.size() + (sharedMediaData[0].sections.isEmpty() || sharedMediaData[0].endReached[0] && sharedMediaData[0].endReached[1] ? 0 : 1); - } - - @Override - public int getCountForSection(int section) { - if (sharedMediaData[0].sections.size() == 0 && !sharedMediaData[0].loading) { - return 1; - } - if (section < sharedMediaData[0].sections.size()) { - return (int) Math.ceil(sharedMediaData[0].sectionArrays.get(sharedMediaData[0].sections.get(section)).size() / (float) columnsCount) + 1; - } - return 1; - } - - @Override - public View getSectionHeaderView(int section, View view) { - if (view == null) { - view = new SharedMediaSectionCell(mContext); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite) & 0xe5ffffff); - } - if (sharedMediaData[0].sections.size() == 0) { - view.setAlpha(0); - } else if (section < sharedMediaData[0].sections.size()) { - view.setAlpha(1f); - String name = sharedMediaData[0].sections.get(section); - ArrayList messageObjects = sharedMediaData[0].sectionArrays.get(name); - MessageObject messageObject = messageObjects.get(0); - ((SharedMediaSectionCell) view).setText(LocaleController.formatSectionDate(messageObject.messageOwner.date)); - } - return view; - } - - @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view; - switch (viewType) { - case 0: - view = new SharedMediaSectionCell(mContext); - break; - case 1: - if (!cellCache.isEmpty()) { - view = cellCache.get(0); - cellCache.remove(0); - ViewGroup p = (ViewGroup) view.getParent(); - if (p != null) { - p.removeView(view); - } - } else { - view = new SharedPhotoVideoCell(mContext); - } - SharedPhotoVideoCell cell = (SharedPhotoVideoCell) view; - cell.setDelegate(new SharedPhotoVideoCell.SharedPhotoVideoCellDelegate() { - @Override - public void didClickItem(SharedPhotoVideoCell cell, int index, MessageObject messageObject, int a) { - onItemClick(index, cell, messageObject, a, 0); - } - - @Override - public boolean didLongClickItem(SharedPhotoVideoCell cell, int index, MessageObject messageObject, int a) { - if (actionBar.isActionModeShowed()) { - didClickItem(cell, index, messageObject, a); - return true; - } - return onItemLongClick(messageObject, cell, a); - } - }); - cache.add((SharedPhotoVideoCell) view); - break; - case 3: - View emptyStubView = SharedMediaLayout.createEmptyStubView(mContext, 0, dialogId); - emptyStubView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - return new RecyclerListView.Holder(emptyStubView); - case 2: - default: - view = new LoadingCell(mContext, AndroidUtilities.dp(32), AndroidUtilities.dp(74)); - break; - } - return new RecyclerListView.Holder(view); - } - - @Override - public void onBindViewHolder(int section, int position, RecyclerView.ViewHolder holder) { - if (holder.getItemViewType() != 2 && holder.getItemViewType() != 3) { - String name = sharedMediaData[0].sections.get(section); - ArrayList messageObjects = sharedMediaData[0].sectionArrays.get(name); - switch (holder.getItemViewType()) { - case 0: { - MessageObject messageObject = messageObjects.get(0); - ((SharedMediaSectionCell) holder.itemView).setText(LocaleController.formatSectionDate(messageObject.messageOwner.date)); - break; - } - case 1: { - SharedPhotoVideoCell cell = (SharedPhotoVideoCell) holder.itemView; - cell.setItemsCount(columnsCount); - cell.setIsFirst(position == 1); - for (int a = 0; a < columnsCount; a++) { - int index = (position - 1) * columnsCount + a; - if (index < messageObjects.size()) { - MessageObject messageObject = messageObjects.get(index); - cell.setItem(a, sharedMediaData[0].messages.indexOf(messageObject), messageObject); - if (actionBar.isActionModeShowed()) { - cell.setChecked(a, selectedFiles[messageObject.getDialogId() == dialogId ? 0 : 1].indexOfKey(messageObject.getId()) >= 0, !scrolling); - } else { - cell.setChecked(a, false, !scrolling); - } - } else { - cell.setItem(a, index, null); - } - } - cell.requestLayout(); - break; - } - } - } - } - - @Override - public int getItemViewType(int section, int position) { - if (sharedMediaData[0].sections.size() == 0 && !sharedMediaData[0].loading) { - return 3; - } - if (section < sharedMediaData[0].sections.size()) { - if (position == 0) { - return 0; - } else { - return 1; - } - } - return 2; - } - - @Override - public String getLetter(int position) { - return null; - } - - @Override - public int getPositionForScrollProgress(float progress) { - return 0; - } - - public int getPositionForIndex(int i) { - return i / columnsCount; - } - } - - public class MediaSearchAdapter extends RecyclerListView.SelectionAdapter { - - private Context mContext; - private ArrayList searchResult = new ArrayList<>(); - private Runnable searchRunnable; - protected ArrayList globalSearch = new ArrayList<>(); - private int reqId = 0; - private int lastReqId; - private int currentType; - private int searchesInProgress; - - public MediaSearchAdapter(Context context, int type) { - mContext = context; - currentType = type; - } - - public void queryServerSearch(final String query, final int max_id, long did) { - if (DialogObject.isEncryptedDialog(did)) { - return; - } - if (reqId != 0) { - ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true); - reqId = 0; - searchesInProgress--; - } - if (query == null || query.length() == 0) { - globalSearch.clear(); - lastReqId = 0; - notifyDataSetChanged(); - return; - } - TLRPC.TL_messages_search req = new TLRPC.TL_messages_search(); - req.limit = 50; - req.offset_id = max_id; - if (currentType == 1) { - req.filter = new TLRPC.TL_inputMessagesFilterDocument(); - } else if (currentType == 3) { - req.filter = new TLRPC.TL_inputMessagesFilterUrl(); - } else if (currentType == 4) { - req.filter = new TLRPC.TL_inputMessagesFilterMusic(); - } - req.q = query; - req.peer = MessagesController.getInstance(currentAccount).getInputPeer(did); - if (req.peer == null) { - return; - } - final int currentReqId = ++lastReqId; - searchesInProgress++; - reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - final ArrayList messageObjects = new ArrayList<>(); - if (error == null) { - TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; - for (int a = 0; a < res.messages.size(); a++) { - TLRPC.Message message = res.messages.get(a); - if (max_id != 0 && message.id > max_id) { - continue; - } - messageObjects.add(new MessageObject(currentAccount, message, false, true)); - } - } - AndroidUtilities.runOnUIThread(() -> { - if (reqId != 0) { - if (currentReqId == lastReqId) { - globalSearch = messageObjects; - searchesInProgress--; - int count = getItemCount(); - notifyDataSetChanged(); - - for (int a = 0; a < mediaPages.length; a++) { - if (mediaPages[a].listView.getAdapter() == this && count == 0 && actionBar.getTranslationY() != 0) { - mediaPages[a].layoutManager.scrollToPositionWithOffset(0, (int) actionBar.getTranslationY()); - } - if (mediaPages[a].selectedType == currentType) { - if (searchesInProgress == 0 && count == 0) { - mediaPages[a].emptyView.showProgress(false, true); - } else if (count == 0) { - animateItemsEnter(mediaPages[a].listView, 0); - } - } - } - } - reqId = 0; - } - }); - }, ConnectionsManager.RequestFlagFailOnServerErrors); - ConnectionsManager.getInstance(currentAccount).bindRequestToGuid(reqId, classGuid); - } - - public void search(final String query) { - if (searchRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(searchRunnable); - searchRunnable = null; - } - - if (!searchResult.isEmpty() || !globalSearch.isEmpty() || searchesInProgress != 0) { - searchResult.clear(); - globalSearch.clear(); - if (reqId != 0) { - ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true); - reqId = 0; - searchesInProgress--; - } - } - notifyDataSetChanged(); - if (!TextUtils.isEmpty(query)) { - for (int a = 0; a < mediaPages.length; a++) { - if (mediaPages[a].selectedType == currentType) { - mediaPages[a].emptyView.showProgress(true, true); - } - } - - - AndroidUtilities.runOnUIThread(searchRunnable = () -> { - if (!sharedMediaData[currentType].messages.isEmpty() && (currentType == 1 || currentType == 4)) { - MessageObject messageObject = sharedMediaData[currentType].messages.get(sharedMediaData[currentType].messages.size() - 1); - queryServerSearch(query, messageObject.getId(), messageObject.getDialogId()); - } else if (currentType == 3) { - queryServerSearch(query, 0, dialogId); - } - if (currentType == 1 || currentType == 4) { - final ArrayList copy = new ArrayList<>(sharedMediaData[currentType].messages); - searchesInProgress++; - Utilities.searchQueue.postRunnable(() -> { - String search1 = query.trim().toLowerCase(); - if (search1.length() == 0) { - updateSearchResults(new ArrayList<>()); - return; - } - String search2 = LocaleController.getInstance().getTranslitString(search1); - if (search1.equals(search2) || search2.length() == 0) { - search2 = null; - } - String[] search = new String[1 + (search2 != null ? 1 : 0)]; - search[0] = search1; - if (search2 != null) { - search[1] = search2; - } - - ArrayList resultArray = new ArrayList<>(); - - for (int a = 0; a < copy.size(); a++) { - MessageObject messageObject = copy.get(a); - for (int b = 0; b < search.length; b++) { - String q = search[b]; - String name = messageObject.getDocumentName(); - if (name == null || name.length() == 0) { - continue; - } - name = name.toLowerCase(); - if (name.contains(q)) { - resultArray.add(messageObject); - break; - } - if (currentType == 4) { - TLRPC.Document document; - if (messageObject.type == 0) { - document = messageObject.messageOwner.media.webpage.document; - } else { - document = messageObject.messageOwner.media.document; - } - boolean ok = false; - for (int c = 0; c < document.attributes.size(); c++) { - TLRPC.DocumentAttribute attribute = document.attributes.get(c); - if (attribute instanceof TLRPC.TL_documentAttributeAudio) { - if (attribute.performer != null) { - ok = attribute.performer.toLowerCase().contains(q); - } - if (!ok && attribute.title != null) { - ok = attribute.title.toLowerCase().contains(q); - } - break; - } - } - if (ok) { - resultArray.add(messageObject); - break; - } - } - } - } - - updateSearchResults(resultArray); - }); - } - }, 300); - } - } - - private void updateSearchResults(final ArrayList documents) { - AndroidUtilities.runOnUIThread(() -> { - if (!searching) { - return; - } - searchesInProgress--; - searchResult = documents; - int count = getItemCount(); - notifyDataSetChanged(); - for (int a = 0; a < mediaPages.length; a++) { - if (mediaPages[a].listView.getAdapter() == this && count == 0 && actionBar.getTranslationY() != 0) { - mediaPages[a].layoutManager.scrollToPositionWithOffset(0, (int) actionBar.getTranslationY()); - break; - } - } - }); - } - - - @Override - public boolean isEnabled(RecyclerView.ViewHolder holder) { - return holder.getItemViewType() != searchResult.size() + globalSearch.size(); - } - - @Override - public int getItemCount() { - int count = searchResult.size(); - int globalCount = globalSearch.size(); - if (globalCount != 0) { - count += globalCount; - } - return count; - } - - public boolean isGlobalSearch(int i) { - int localCount = searchResult.size(); - int globalCount = globalSearch.size(); - if (i >= 0 && i < localCount) { - return false; - } else if (i > localCount && i <= globalCount + localCount) { - return true; - } - return false; - } - - public MessageObject getItem(int i) { - if (i < searchResult.size()) { - return searchResult.get(i); - } else { - return globalSearch.get(i - searchResult.size()); - } - } - - @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view; - if (currentType == 1) { - view = new SharedDocumentCell(mContext); - } else if (currentType == 4) { - view = new SharedAudioCell(mContext) { - @Override - public boolean needPlayMessage(MessageObject messageObject) { - if (messageObject.isVoice() || messageObject.isRoundVideo()) { - boolean result = MediaController.getInstance().playMessage(messageObject); - MediaController.getInstance().setVoiceMessagesPlaylist(result ? searchResult : null, false); - if (messageObject.isRoundVideo()) { - MediaController.getInstance().setCurrentVideoVisible(false); - } - return result; - } else if (messageObject.isMusic()) { - return MediaController.getInstance().setPlaylist(searchResult, messageObject, mergeDialogId); - } - return false; - } - }; - } else { - view = new SharedLinkCell(mContext); - ((SharedLinkCell) view).setDelegate(sharedLinkCellDelegate); - } - return new RecyclerListView.Holder(view); - } - - @Override - public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { - if (currentType == 1) { - SharedDocumentCell sharedDocumentCell = (SharedDocumentCell) holder.itemView; - MessageObject messageObject = getItem(position); - sharedDocumentCell.setDocument(messageObject, position != getItemCount() - 1); - if (actionBar.isActionModeShowed()) { - sharedDocumentCell.setChecked(selectedFiles[messageObject.getDialogId() == dialogId ? 0 : 1].indexOfKey(messageObject.getId()) >= 0, !scrolling); - } else { - sharedDocumentCell.setChecked(false, !scrolling); - } - } else if (currentType == 3) { - SharedLinkCell sharedLinkCell = (SharedLinkCell) holder.itemView; - MessageObject messageObject = getItem(position); - sharedLinkCell.setLink(messageObject, position != getItemCount() - 1); - if (actionBar.isActionModeShowed()) { - sharedLinkCell.setChecked(selectedFiles[messageObject.getDialogId() == dialogId ? 0 : 1].indexOfKey(messageObject.getId()) >= 0, !scrolling); - } else { - sharedLinkCell.setChecked(false, !scrolling); - } - } else if (currentType == 4) { - SharedAudioCell sharedAudioCell = (SharedAudioCell) holder.itemView; - MessageObject messageObject = getItem(position); - sharedAudioCell.setMessageObject(messageObject, position != getItemCount() - 1); - if (actionBar.isActionModeShowed()) { - sharedAudioCell.setChecked(selectedFiles[messageObject.getDialogId() == dialogId ? 0 : 1].indexOfKey(messageObject.getId()) >= 0, !scrolling); - } else { - sharedAudioCell.setChecked(false, !scrolling); - } - } - } - - @Override - public int getItemViewType(int i) { - return 0; - } - } - - private void animateItemsEnter(RecyclerListView listView, int oldItemCount) { - if (listView == null) { - return; - } - int n = listView.getChildCount(); - View progressView = null; - for (int i = 0; i < n; i++) { - View child = listView.getChildAt(i); - if (child instanceof FlickerLoadingView) { - progressView = child; - } - } - final View finalProgressView = progressView; - if (progressView != null) { - listView.removeView(progressView); - } - listView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - listView.getViewTreeObserver().removeOnPreDrawListener(this); - int n = listView.getChildCount(); - AnimatorSet animatorSet = new AnimatorSet(); - for (int i = 0; i < n; i++) { - View child = listView.getChildAt(i); - if (listView.getChildAdapterPosition(child) >= oldItemCount - 1) { - child.setAlpha(0); - int s = Math.min(listView.getMeasuredHeight(), Math.max(0, child.getTop())); - int delay = (int) ((s / (float) listView.getMeasuredHeight()) * 100); - ObjectAnimator a = ObjectAnimator.ofFloat(child, View.ALPHA, 0, 1f); - a.setStartDelay(delay); - a.setDuration(200); - animatorSet.playTogether(a); - } - if (finalProgressView != null && finalProgressView.getParent() == null) { - listView.addView(finalProgressView); - RecyclerView.LayoutManager layoutManager = listView.getLayoutManager(); - if (layoutManager != null) { - layoutManager.ignoreView(finalProgressView); - Animator animator = ObjectAnimator.ofFloat(finalProgressView, View.ALPHA, finalProgressView.getAlpha(), 0); - animator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - finalProgressView.setAlpha(1f); - layoutManager.stopIgnoringView(finalProgressView); - listView.removeView(finalProgressView); - } - }); - animator.start(); - } - } - } - - animatorSet.start(); - return true; - } - }); - } - - @Override - public ArrayList getThemeDescriptions() { - ArrayList arrayList = new ArrayList<>(); - - arrayList.add(new ThemeDescription(fragmentView, 0, null, null, null, null, Theme.key_windowBackgroundWhite)); - - arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault)); - - arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon)); - arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle)); - arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector)); - arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUBACKGROUND, null, null, null, null, Theme.key_actionBarDefaultSubmenuBackground)); - arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM, null, null, null, null, Theme.key_actionBarDefaultSubmenuItem)); - arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SUBMENUITEM | ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_actionBarDefaultSubmenuItemIcon)); - - arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_AM_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon)); - arrayList.add(new ThemeDescription(actionModeBackground, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_sharedMedia_actionMode)); - arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_AM_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector)); - arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCH, null, null, null, null, Theme.key_actionBarDefaultSearch)); - arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SEARCHPLACEHOLDER, null, null, null, null, Theme.key_actionBarDefaultSearchPlaceholder)); - - arrayList.add(new ThemeDescription(selectedMessagesCountTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon)); - - arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"frameLayout"}, null, null, null, Theme.key_inappPlayerBackground)); - arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{FragmentContextView.class}, new String[]{"playButton"}, null, null, null, Theme.key_inappPlayerPlayPause)); - arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_inappPlayerTitle)); - arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_FASTSCROLL, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_inappPlayerPerformer)); - arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{FragmentContextView.class}, new String[]{"closeButton"}, null, null, null, Theme.key_inappPlayerClose)); - - arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"frameLayout"}, null, null, null, Theme.key_returnToCallBackground)); - arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_returnToCallText)); - - arrayList.add(new ThemeDescription(scrollSlidingTextTabStrip, 0, new Class[]{ScrollSlidingTextTabStrip.class}, new String[]{"selectorDrawable"}, null, null, null, Theme.key_actionBarTabLine)); - arrayList.add(new ThemeDescription(scrollSlidingTextTabStrip.getTabsContainer(), ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{TextView.class}, null, null, null, Theme.key_actionBarTabActiveText)); - arrayList.add(new ThemeDescription(scrollSlidingTextTabStrip.getTabsContainer(), ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{TextView.class}, null, null, null, Theme.key_actionBarTabUnactiveText)); - arrayList.add(new ThemeDescription(scrollSlidingTextTabStrip.getTabsContainer(), ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, new Class[]{TextView.class}, null, null, null, Theme.key_actionBarTabSelector)); - - for (int a = 0; a < mediaPages.length; a++) { - final int num = a; - ThemeDescription.ThemeDescriptionDelegate cellDelegate = () -> { - if (mediaPages[num].listView != null) { - int count = mediaPages[num].listView.getChildCount(); - for (int a1 = 0; a1 < count; a1++) { - View child = mediaPages[num].listView.getChildAt(a1); - if (child instanceof SharedPhotoVideoCell) { - ((SharedPhotoVideoCell) child).updateCheckboxColor(); - } - } - } - }; - - arrayList.add(new ThemeDescription(mediaPages[a].emptyView, 0, null, null, null, null, Theme.key_windowBackgroundGray)); - arrayList.add(new ThemeDescription(mediaPages[a].progressView, 0, null, null, null, null, Theme.key_windowBackgroundGray)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector)); - arrayList.add(new ThemeDescription(mediaPages[a].emptyView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_emptyListPlaceholder)); - - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_SECTIONS, new Class[]{GraySectionCell.class}, new String[]{"textView"}, null, null, null, Theme.key_graySectionText)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR | ThemeDescription.FLAG_SECTIONS, new Class[]{GraySectionCell.class}, null, null, null, Theme.key_graySection)); - - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{SharedDocumentCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{SharedDocumentCell.class}, new String[]{"dateTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText3)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_PROGRESSBAR, new Class[]{SharedDocumentCell.class}, new String[]{"progressView"}, null, null, null, Theme.key_sharedMedia_startStopLoadIcon)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{SharedDocumentCell.class}, new String[]{"statusImageView"}, null, null, null, Theme.key_sharedMedia_startStopLoadIcon)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_CHECKBOX, new Class[]{SharedDocumentCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_checkbox)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_CHECKBOXCHECK, new Class[]{SharedDocumentCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_checkboxCheck)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{SharedDocumentCell.class}, new String[]{"thumbImageView"}, null, null, null, Theme.key_files_folderIcon)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{SharedDocumentCell.class}, new String[]{"extTextView"}, null, null, null, Theme.key_files_iconText)); - - arrayList.add(new ThemeDescription(mediaPages[a].listView, 0, new Class[]{LoadingCell.class}, new String[]{"progressBar"}, null, null, null, Theme.key_progressCircle)); - - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_CHECKBOX, new Class[]{SharedAudioCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_checkbox)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_CHECKBOXCHECK, new Class[]{SharedAudioCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_checkboxCheck)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{SharedAudioCell.class}, Theme.chat_contextResult_titleTextPaint, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{SharedAudioCell.class}, Theme.chat_contextResult_descriptionTextPaint, null, null, Theme.key_windowBackgroundWhiteGrayText2)); - - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_CHECKBOX, new Class[]{SharedLinkCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_checkbox)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_CHECKBOXCHECK, new Class[]{SharedLinkCell.class}, new String[]{"checkBox"}, null, null, null, Theme.key_checkboxCheck)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, 0, new Class[]{SharedLinkCell.class}, new String[]{"titleTextPaint"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, 0, new Class[]{SharedLinkCell.class}, null, null, null, Theme.key_windowBackgroundWhiteLinkText)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, 0, new Class[]{SharedLinkCell.class}, Theme.linkSelectionPaint, null, null, Theme.key_windowBackgroundWhiteLinkSelection)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, 0, new Class[]{SharedLinkCell.class}, new String[]{"letterDrawable"}, null, null, null, Theme.key_sharedMedia_linkPlaceholderText)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{SharedLinkCell.class}, new String[]{"letterDrawable"}, null, null, null, Theme.key_sharedMedia_linkPlaceholder)); - - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR | ThemeDescription.FLAG_SECTIONS, new Class[]{SharedMediaSectionCell.class}, null, null, null, Theme.key_windowBackgroundWhite)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_SECTIONS, new Class[]{SharedMediaSectionCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, 0, new Class[]{SharedMediaSectionCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - - arrayList.add(new ThemeDescription(mediaPages[a].listView, 0, new Class[]{SharedPhotoVideoCell.class}, new String[]{"backgroundPaint"}, null, null, null, Theme.key_sharedMedia_photoPlaceholder)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_CHECKBOX, new Class[]{SharedPhotoVideoCell.class}, null, null, cellDelegate, Theme.key_checkbox)); - arrayList.add(new ThemeDescription(mediaPages[a].listView, ThemeDescription.FLAG_CHECKBOXCHECK, new Class[]{SharedPhotoVideoCell.class}, null, null, cellDelegate, Theme.key_checkboxCheck)); - - arrayList.add(new ThemeDescription(mediaPages[a].listView, 0, null, null, new Drawable[]{pinnedHeaderShadowDrawable}, null, Theme.key_windowBackgroundGrayShadow)); - - arrayList.add(new ThemeDescription(mediaPages[a].emptyView.title, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(mediaPages[a].emptyView.subtitle, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteGrayText)); - } - - return arrayList; - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MediaCalendarActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MediaCalendarActivity.java new file mode 100644 index 00000000000..4b6d57f30b8 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/MediaCalendarActivity.java @@ -0,0 +1,642 @@ +package org.telegram.ui; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.text.TextPaint; +import android.util.Log; +import android.util.SparseArray; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.core.graphics.ColorUtils; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.DownloadController; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.SimpleTextView; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ActionBar.ThemeDescription; +import org.telegram.ui.Components.FlickerLoadingView; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.SharedMediaLayout; + +import java.time.DayOfWeek; +import java.time.YearMonth; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Random; + +public class MediaCalendarActivity extends BaseFragment { + + FrameLayout contentView; + + RecyclerListView listView; + LinearLayoutManager layoutManager; + TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + TextPaint activeTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + TextPaint textPaint2 = new TextPaint(Paint.ANTI_ALIAS_FLAG); + + Paint blackoutPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + private long dialogId; + private boolean loading; + private boolean checkEnterItems; + + + int startFromYear; + int startFromMonth; + int monthCount; + + CalendarAdapter adapter; + Callback callback; + + + SparseArray> messagesByYearMounth = new SparseArray<>(); + boolean endReached; + int startOffset = 0; + int lastId; + int minMontYear; + private int photosVideosTypeFilter; + private boolean isOpened; + int selectedYear; + int selectedMonth; + + public MediaCalendarActivity(Bundle args, int photosVideosTypeFilter, int selectedDate) { + super(args); + this.photosVideosTypeFilter = photosVideosTypeFilter; + + if (selectedDate != 0) { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(selectedDate * 1000L); + selectedYear = calendar.get(Calendar.YEAR); + selectedMonth = calendar.get(Calendar.MONTH); + } + } + + @Override + public boolean onFragmentCreate() { + dialogId = getArguments().getLong("dialog_id"); + return super.onFragmentCreate(); + } + + @Override + public View createView(Context context) { + textPaint.setTextSize(AndroidUtilities.dp(16)); + textPaint.setTextAlign(Paint.Align.CENTER); + + textPaint2.setTextSize(AndroidUtilities.dp(11)); + textPaint2.setTextAlign(Paint.Align.CENTER); + textPaint2.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + + activeTextPaint.setTextSize(AndroidUtilities.dp(16)); + activeTextPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + activeTextPaint.setTextAlign(Paint.Align.CENTER); + + contentView = new FrameLayout(context); + createActionBar(context); + contentView.addView(actionBar); + actionBar.setTitle(LocaleController.getString("Calendar", R.string.Calendar)); + actionBar.setCastShadows(false); + + listView = new RecyclerListView(context) { + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + checkEnterItems = false; + } + }; + listView.setLayoutManager(layoutManager = new LinearLayoutManager(context)); + layoutManager.setReverseLayout(true); + listView.setAdapter(adapter = new CalendarAdapter()); + listView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + checkLoadNext(); + } + }); + + contentView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 0, 36, 0, 0)); + + final String[] daysOfWeek = new String[]{ + LocaleController.getString("CalendarWeekNameShortMonday", R.string.CalendarWeekNameShortMonday), + LocaleController.getString("CalendarWeekNameShortTuesday", R.string.CalendarWeekNameShortTuesday), + LocaleController.getString("CalendarWeekNameShortWednesday", R.string.CalendarWeekNameShortWednesday), + LocaleController.getString("CalendarWeekNameShortThursday", R.string.CalendarWeekNameShortThursday), + LocaleController.getString("CalendarWeekNameShortFriday", R.string.CalendarWeekNameShortFriday), + LocaleController.getString("CalendarWeekNameShortSaturday", R.string.CalendarWeekNameShortSaturday), + LocaleController.getString("CalendarWeekNameShortSunday", R.string.CalendarWeekNameShortSunday), + }; + + Drawable headerShadowDrawable = ContextCompat.getDrawable(context, R.drawable.header_shadow).mutate(); + + View calendarSignatureView = new View(context) { + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + float xStep = getMeasuredWidth() / 7f; + for (int i = 0; i < 7; i++) { + float cx = xStep * i + xStep / 2f; + float cy = (getMeasuredHeight() - AndroidUtilities.dp(2)) / 2f; + canvas.drawText(daysOfWeek[i], cx, cy + AndroidUtilities.dp(5), textPaint2); + } + headerShadowDrawable.setBounds(0, getMeasuredHeight() - AndroidUtilities.dp(3), getMeasuredWidth(), getMeasuredHeight()); + headerShadowDrawable.draw(canvas); + } + }; + + contentView.addView(calendarSignatureView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, 0, 0, 0, 0, 0)); + actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { + @Override + public void onItemClick(int id) { + if (id == -1) { + finishFragment(); + } + } + }); + + fragmentView = contentView; + + Calendar calendar = Calendar.getInstance(); + startFromYear = calendar.get(Calendar.YEAR); + startFromMonth = calendar.get(Calendar.MONTH); + + if (selectedYear != 0) { + monthCount = (startFromYear - selectedYear) * 12 + startFromMonth - selectedMonth + 1; + layoutManager.scrollToPositionWithOffset(monthCount - 1, AndroidUtilities.dp(120)); + } + if (monthCount < 3) { + monthCount = 3; + } + + + loadNext(); + updateColors(); + activeTextPaint.setColor(Color.WHITE); + actionBar.setBackButtonImage(R.drawable.ic_ab_back); + return fragmentView; + } + + private void updateColors() { + actionBar.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + activeTextPaint.setColor(Color.WHITE); + textPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + textPaint2.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + actionBar.setTitleColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + actionBar.setBackButtonImage(R.drawable.ic_ab_back); + actionBar.setItemsColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), false); + actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_listSelector), false); + } + + private void loadNext() { + if (loading || endReached) { + return; + } + loading = true; + TLRPC.TL_messages_getSearchResultsCalendar req = new TLRPC.TL_messages_getSearchResultsCalendar(); + if (photosVideosTypeFilter == SharedMediaLayout.FILTER_PHOTOS_ONLY) { + req.filter = new TLRPC.TL_inputMessagesFilterPhotos(); + } else if (photosVideosTypeFilter == SharedMediaLayout.FILTER_VIDEOS_ONLY) { + req.filter = new TLRPC.TL_inputMessagesFilterVideo(); + } else { + req.filter = new TLRPC.TL_inputMessagesFilterPhotoVideo(); + } + + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + req.offset_id = lastId; + + Calendar calendar = Calendar.getInstance(); + listView.setItemAnimator(null); + getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (error == null) { + TLRPC.TL_messages_searchResultsCalendar res = (TLRPC.TL_messages_searchResultsCalendar) response; + + for (int i = 0; i < res.periods.size(); i++) { + TLRPC.TL_searchResultsCalendarPeriod period = res.periods.get(i); + calendar.setTimeInMillis(period.date * 1000L); + int month = calendar.get(Calendar.YEAR) * 100 + calendar.get(Calendar.MONTH); + SparseArray messagesByDays = messagesByYearMounth.get(month); + if (messagesByDays == null) { + messagesByDays = new SparseArray<>(); + messagesByYearMounth.put(month, messagesByDays); + } + PeriodDay periodDay = new PeriodDay(); + MessageObject messageObject = new MessageObject(currentAccount, res.messages.get(i), false, false); + periodDay.messageObject = messageObject; + startOffset += res.periods.get(i).count; + periodDay.startOffset = startOffset; + int index = calendar.get(Calendar.DAY_OF_MONTH) - 1; + if (messagesByDays.get(index, null) == null) { + messagesByDays.put(index, periodDay); + } + if (month < minMontYear || minMontYear == 0) { + minMontYear = month; + } + + } + + loading = false; + if (!res.messages.isEmpty()) { + lastId = res.messages.get(res.messages.size() - 1).id; + endReached = false; + checkLoadNext(); + } else { + endReached = true; + } + if (isOpened) { + checkEnterItems = true; + } + listView.invalidate(); + int newMonthCount = (int) (((calendar.getTimeInMillis() / 1000) - res.min_date) / 2629800) + 1; + adapter.notifyItemRangeChanged(0, monthCount); + if (newMonthCount > monthCount) { + adapter.notifyItemRangeInserted(monthCount + 1, newMonthCount); + monthCount = newMonthCount; + } + if (endReached) { + resumeDelayedFragmentAnimation(); + } + } + })); + } + + private void checkLoadNext() { + if (loading || endReached) { + return; + } + int listMinMonth = Integer.MAX_VALUE; + for (int i = 0; i < listView.getChildCount(); i++) { + View child = listView.getChildAt(i); + if (child instanceof MonthView) { + int currentMonth = ((MonthView) child).currentYear * 100 + ((MonthView) child).currentMonthInYear; + if (currentMonth < listMinMonth) { + listMinMonth = currentMonth; + } + } + }; + int min1 = (minMontYear / 100 * 12) + minMontYear % 100; + int min2 = (listMinMonth / 100 * 12) + listMinMonth % 100; + if (min1 + 3 >= min2) { + loadNext(); + } + } + + private class CalendarAdapter extends RecyclerView.Adapter { + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new RecyclerListView.Holder(new MonthView(parent.getContext())); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + MonthView monthView = (MonthView) holder.itemView; + + int year = startFromYear - position / 12; + int month = startFromMonth - position % 12; + if (month < 0) { + month += 12; + year--; + } + boolean animated = monthView.currentYear == year && monthView.currentMonthInYear == month; + monthView.setDate(year, month, messagesByYearMounth.get(year * 100 + month), animated); + } + + @Override + public long getItemId(int position) { + int year = startFromYear - position / 12; + int month = startFromMonth - position % 12; + return year * 100L + month; + } + + @Override + public int getItemCount() { + return monthCount; + } + } + + private class MonthView extends FrameLayout { + + SimpleTextView titleView; + int currentYear; + int currentMonthInYear; + int daysInMonth; + int startDayOfWeek; + int cellCount; + int startMonthTime; + + SparseArray messagesByDays = new SparseArray<>(); + SparseArray imagesByDays = new SparseArray<>(); + + SparseArray animatedFromMessagesByDays = new SparseArray<>(); + SparseArray animatedFromImagesByDays = new SparseArray<>(); + + boolean attached; + float animationProgress = 1f; + + public MonthView(Context context) { + super(context); + setWillNotDraw(false); + titleView = new SimpleTextView(context); + titleView.setTextSize(15); + titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleView.setGravity(Gravity.CENTER); + titleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 28, 0, 0, 12, 0, 4)); + } + + public void setDate(int year, int monthInYear, SparseArray messagesByDays, boolean animated) { + boolean dateChanged = year != currentYear && monthInYear != currentMonthInYear; + currentYear = year; + currentMonthInYear = monthInYear; + this.messagesByDays = messagesByDays; + + if (dateChanged) { + if (imagesByDays != null) { + for (int i = 0; i < imagesByDays.size(); i++) { + imagesByDays.valueAt(i).onDetachedFromWindow(); + imagesByDays.valueAt(i).setParentView(null); + } + imagesByDays = null; + } + } + if (messagesByDays != null) { + if (imagesByDays == null) { + imagesByDays = new SparseArray<>(); + } + + for (int i = 0; i < messagesByDays.size(); i++) { + int key = messagesByDays.keyAt(i); + if (imagesByDays.get(key, null) != null) { + continue; + } + ImageReceiver receiver = new ImageReceiver(); + receiver.setParentView(this); + PeriodDay periodDay = messagesByDays.get(key); + MessageObject messageObject = periodDay.messageObject; + if (messageObject != null) { + if (messageObject.isVideo()) { + TLRPC.Document document = messageObject.getDocument(); + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 50); + TLRPC.PhotoSize qualityThumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 320); + if (thumb == qualityThumb) { + qualityThumb = null; + } + if (thumb != null) { + if (messageObject.strippedThumb != null) { + receiver.setImage(ImageLocation.getForDocument(qualityThumb, document), "44_44", messageObject.strippedThumb, null, messageObject, 0); + } else { + receiver.setImage(ImageLocation.getForDocument(qualityThumb, document), "44_44", ImageLocation.getForDocument(thumb, document), "b", (String) null, messageObject, 0); + } + } + } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && messageObject.messageOwner.media.photo != null && !messageObject.photoThumbs.isEmpty()) { + TLRPC.PhotoSize currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 50); + TLRPC.PhotoSize currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 320, false, currentPhotoObjectThumb, false); + if (messageObject.mediaExists || DownloadController.getInstance(currentAccount).canDownloadMedia(messageObject)) { + if (currentPhotoObject == currentPhotoObjectThumb) { + currentPhotoObjectThumb = null; + } + if (messageObject.strippedThumb != null) { + receiver.setImage(ImageLocation.getForObject(currentPhotoObject, messageObject.photoThumbsObject), "44_44", null, null, messageObject.strippedThumb, currentPhotoObject != null ? currentPhotoObject.size : 0, null, messageObject, messageObject.shouldEncryptPhotoOrVideo() ? 2 : 1); + } else { + receiver.setImage(ImageLocation.getForObject(currentPhotoObject, messageObject.photoThumbsObject), "44_44", ImageLocation.getForObject(currentPhotoObjectThumb, messageObject.photoThumbsObject), "b", currentPhotoObject != null ? currentPhotoObject.size : 0, null, messageObject, messageObject.shouldEncryptPhotoOrVideo() ? 2 : 1); + } + } else { + if (messageObject.strippedThumb != null) { + receiver.setImage(null, null, messageObject.strippedThumb, null, messageObject, 0); + } else { + receiver.setImage(null, null, ImageLocation.getForObject(currentPhotoObjectThumb, messageObject.photoThumbsObject), "b", (String) null, messageObject, 0); + } + } + } + receiver.setRoundRadius(AndroidUtilities.dp(22)); + imagesByDays.put(key, receiver); + } + } + } + + YearMonth yearMonthObject = YearMonth.of(year, monthInYear + 1); + daysInMonth = yearMonthObject.lengthOfMonth(); + + Calendar calendar = Calendar.getInstance(); + calendar.set(year, monthInYear, 0); + startDayOfWeek = (calendar.get(Calendar.DAY_OF_WEEK) + 6) % 7; + startMonthTime= (int) (calendar.getTimeInMillis() / 1000L); + + int totalColumns = daysInMonth + startDayOfWeek; + cellCount = (int) (totalColumns / 7f) + (totalColumns % 7 == 0 ? 0 : 1); + calendar.set(year, monthInYear + 1, 0); + titleView.setText(LocaleController.formatYearMont(calendar.getTimeInMillis() / 1000, true)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(cellCount * (44 + 8) + 44), MeasureSpec.EXACTLY)); + } + + boolean pressed; + float pressedX; + float pressedY; + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + pressed = true; + pressedX = event.getX(); + pressedY = event.getY(); + } else if (event.getAction() == MotionEvent.ACTION_UP) { + if (pressed) { + for (int i = 0; i < imagesByDays.size(); i++) { + if (imagesByDays.valueAt(i).getDrawRegion().contains(pressedX, pressedY)) { + if (callback != null) { + PeriodDay periodDay = messagesByDays.valueAt(i); + callback.onDateSelected(periodDay.messageObject.getId(), periodDay.startOffset); + finishFragment(); + break; + } + } + } + } + pressed = false; + } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { + pressed = false; + } + return pressed; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + int currentCell = 0; + int currentColumn = startDayOfWeek; + + float xStep = getMeasuredWidth() / 7f; + float yStep = AndroidUtilities.dp(44 + 8); + for (int i = 0; i < daysInMonth; i++) { + float cx = xStep * currentColumn + xStep / 2f; + float cy = yStep * currentCell + yStep / 2f + AndroidUtilities.dp(44); + int nowTime = (int) (System.currentTimeMillis() / 1000L); + if (nowTime < startMonthTime + (i + 1) * 86400) { + int oldAlpha = textPaint.getAlpha(); + textPaint.setAlpha((int) (oldAlpha * 0.3f)); + canvas.drawText(Integer.toString(i + 1), cx, cy + AndroidUtilities.dp(5), textPaint); + textPaint.setAlpha(oldAlpha); + } else if (messagesByDays != null && messagesByDays.get(i, null) != null) { + float alpha = 1f; + if (imagesByDays.get(i) != null) { + if (checkEnterItems && !messagesByDays.get(i).wasDrawn) { + messagesByDays.get(i).enterAlpha = 0f; + messagesByDays.get(i).startEnterDelay = (cy + getY()) / listView.getMeasuredHeight() * 150; + } + if (messagesByDays.get(i).startEnterDelay > 0) { + messagesByDays.get(i).startEnterDelay -= 16; + if (messagesByDays.get(i).startEnterDelay < 0) { + messagesByDays.get(i).startEnterDelay = 0; + } else { + invalidate(); + } + } + if (messagesByDays.get(i).startEnterDelay == 0 && messagesByDays.get(i).enterAlpha != 1f) { + messagesByDays.get(i).enterAlpha += 16 / 220f; + if (messagesByDays.get(i).enterAlpha > 1f) { + messagesByDays.get(i).enterAlpha = 1f; + } else { + invalidate(); + } + } + alpha = messagesByDays.get(i).enterAlpha; + if (alpha != 1f) { + canvas.save(); + float s = 0.8f + 0.2f * alpha; + canvas.scale(s, s,cx, cy); + } + imagesByDays.get(i).setAlpha(messagesByDays.get(i).enterAlpha); + imagesByDays.get(i).setImageCoords(cx - AndroidUtilities.dp(44) / 2f, cy - AndroidUtilities.dp(44) / 2f, AndroidUtilities.dp(44), AndroidUtilities.dp(44)); + imagesByDays.get(i).draw(canvas); + blackoutPaint.setColor(ColorUtils.setAlphaComponent(Color.BLACK, (int) (messagesByDays.get(i).enterAlpha * 80))); + canvas.drawCircle(cx, cy, AndroidUtilities.dp(44) / 2f, blackoutPaint); + messagesByDays.get(i).wasDrawn = true; + if (alpha != 1f) { + canvas.restore(); + } + } + if (alpha != 1f) { + int oldAlpha = textPaint.getAlpha(); + textPaint.setAlpha((int) (oldAlpha * (1f - alpha))); + canvas.drawText(Integer.toString(i + 1), cx, cy + AndroidUtilities.dp(5), textPaint); + textPaint.setAlpha(oldAlpha); + + oldAlpha = textPaint.getAlpha(); + activeTextPaint.setAlpha((int) (oldAlpha * alpha)); + canvas.drawText(Integer.toString(i + 1), cx, cy + AndroidUtilities.dp(5), activeTextPaint); + activeTextPaint.setAlpha(oldAlpha); + } else { + canvas.drawText(Integer.toString(i + 1), cx, cy + AndroidUtilities.dp(5), activeTextPaint); + } + + } else { + canvas.drawText(Integer.toString(i + 1), cx, cy + AndroidUtilities.dp(5), textPaint); + } + + currentColumn++; + if (currentColumn >= 7) { + currentColumn = 0; + currentCell++; + } + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + attached = true; + if (imagesByDays != null) { + for (int i = 0; i < imagesByDays.size(); i++) { + imagesByDays.valueAt(i).onAttachedToWindow(); + } + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + attached = false; + if (imagesByDays != null) { + for (int i = 0; i < imagesByDays.size(); i++) { + imagesByDays.valueAt(i).onDetachedFromWindow(); + } + } + } + } + + public void setCallback(Callback callback) { + this.callback = callback; + } + + public interface Callback { + void onDateSelected(int messageId, int startOffset); + } + + private class PeriodDay { + MessageObject messageObject; + int startOffset; + float enterAlpha = 1f; + float startEnterDelay = 1f; + boolean wasDrawn; + } + + @Override + public ArrayList getThemeDescriptions() { + + ThemeDescription.ThemeDescriptionDelegate descriptionDelegate = new ThemeDescription.ThemeDescriptionDelegate() { + @Override + public void didSetColor() { + updateColors(); + } + }; + ArrayList themeDescriptions = new ArrayList<>(); + new ThemeDescription(null, 0, null, null, null, descriptionDelegate, Theme.key_windowBackgroundWhite); + new ThemeDescription(null, 0, null, null, null, descriptionDelegate, Theme.key_windowBackgroundWhiteBlackText); + new ThemeDescription(null, 0, null, null, null, descriptionDelegate, Theme.key_listSelector); + + + return super.getThemeDescriptions(); + } + + @Override + public boolean needDelayOpenAnimation() { + return true; + } + + @Override + protected void onTransitionAnimationStart(boolean isOpen, boolean backward) { + super.onTransitionAnimationStart(isOpen, backward); + isOpened = true; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MemberRequestsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MemberRequestsActivity.java new file mode 100644 index 00000000000..a6040eb29d6 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/MemberRequestsActivity.java @@ -0,0 +1,83 @@ +package org.telegram.ui; + +import android.content.Context; +import android.view.View; +import android.widget.EditText; +import android.widget.FrameLayout; + +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.ActionBarMenu; +import org.telegram.ui.ActionBar.ActionBarMenuItem; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.Delegates.MemberRequestsDelegate; + +public class MemberRequestsActivity extends BaseFragment { + + public static final int searchMenuItem = 0; + + private final MemberRequestsDelegate delegate; + + public MemberRequestsActivity(long chatId) { + delegate = new MemberRequestsDelegate(this, getLayoutContainer(), chatId, true) { + @Override + protected void onImportersChanged(String query, boolean fromCache, boolean fromHide) { + if (fromHide) { + actionBar.setSearchFieldText(""); + } else { + super.onImportersChanged(query, fromCache, fromHide); + } + } + }; + } + + @Override + public View createView(Context context) { + actionBar.setAllowOverlayTitle(true); + actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { + @Override + public void onItemClick(int id) { + if (id == -1) { + finishFragment(); + } + } + }); + actionBar.setBackButtonImage(R.drawable.ic_ab_back); + actionBar.setTitle(delegate.isChannel ? LocaleController.getString("SubscribeRequests", R.string.SubscribeRequests) : LocaleController.getString("MemberRequests", R.string.MemberRequests)); + + ActionBarMenu menu = actionBar.createMenu(); + ActionBarMenuItem searchItem = menu.addItem(searchMenuItem, R.drawable.ic_ab_search) + .setIsSearchField(true) + .setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { + @Override + public void onSearchExpand() { + super.onSearchExpand(); + delegate.setSearchExpanded(true); + } + @Override + public void onSearchCollapse() { + super.onSearchCollapse(); + delegate.setSearchExpanded(false); + delegate.setQuery(null); + } + @Override + public void onTextChanged(EditText editText) { + super.onTextChanged(editText); + delegate.setQuery(editText.getText().toString()); + } + }); + searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); + searchItem.setVisibility(View.GONE); + + FrameLayout rootLayout = delegate.getRootLayout(); + delegate.loadMembers(); + + return fragmentView = rootLayout; + } + + @Override + public boolean onBackPressed() { + return delegate.onBackPressed(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index 38afc23cfb1..e3e57014003 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -66,6 +66,7 @@ import androidx.recyclerview.widget.LinearSmoothScrollerEnd; import androidx.recyclerview.widget.RecyclerView; +import android.text.Editable; import android.text.Layout; import android.text.Selection; import android.text.Spannable; @@ -125,6 +126,7 @@ import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.analytics.AnalyticsListener; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; +import com.google.android.exoplayer2.util.Log; import com.google.android.gms.vision.Frame; import com.google.android.gms.vision.face.Face; import com.google.android.gms.vision.face.FaceDetector; @@ -200,6 +202,7 @@ import org.telegram.ui.Components.GroupedPhotosListView; import org.telegram.ui.Components.HideViewAfterAnimation; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.MediaActivity; import org.telegram.ui.Components.NumberPicker; import org.telegram.ui.Components.OtherDocumentPlaceholderDrawable; import org.telegram.ui.Components.PaintingOverlay; @@ -559,6 +562,11 @@ public int getClassGuid() { return classGuid; } + public void setCaption(CharSequence caption) { + hasCaptionForAllMedia = !TextUtils.isEmpty(caption); + captionForAllMedia = caption; + } + private static class SavedVideoPosition { public final float position; @@ -1085,11 +1093,13 @@ public void restore() { private long currentDialogId; private long mergeDialogId; private int totalImagesCount; + private int startOffset; private int totalImagesCountMerge; private boolean isFirstLoading; private boolean needSearchImageInArr; private boolean loadingMoreImages; private boolean[] endReached = new boolean[]{false, true}; + private boolean startReached = false; private boolean opennedFromMedia; private boolean attachedToWindow; @@ -1709,6 +1719,7 @@ public static class PlaceProviderObject { public ImageReceiver imageReceiver; public int viewX; public int viewY; + public int viewY2; public View parentView; public ImageReceiver.BitmapHolder thumb; public long dialogId; @@ -1723,6 +1734,7 @@ public static class PlaceProviderObject { public int animatingImageViewYOffset; public boolean allowTakeAnimation = true; public boolean canEdit; + public int starOffset; } public static class EmptyPhotoViewerProvider implements PhotoViewerProvider { @@ -3185,10 +3197,10 @@ public void didReceivedNotification(int id, int account, Object... args) { if (needSearchImageInArr && isFirstLoading) { isFirstLoading = false; loadingMoreImages = true; - MediaDataController.getInstance(currentAccount).loadMedia(currentDialogId, 20, 0, sharedMediaType, 1, classGuid); + MediaDataController.getInstance(currentAccount).loadMedia(currentDialogId, 20, 0, 0, sharedMediaType, 1, classGuid, 0); } else if (!imagesArr.isEmpty()) { if (opennedFromMedia) { - actionBar.setTitle(LocaleController.formatString("Of", R.string.Of, currentIndex + 1, totalImagesCount + totalImagesCountMerge)); + actionBar.setTitle(LocaleController.formatString("Of", R.string.Of, startOffset + currentIndex + 1, totalImagesCount + totalImagesCountMerge)); } else { actionBar.setTitle(LocaleController.formatString("Of", R.string.Of, (totalImagesCount + totalImagesCountMerge - imagesArr.size()) + currentIndex + 1, totalImagesCount + totalImagesCountMerge)); } @@ -3203,6 +3215,7 @@ public void didReceivedNotification(int id, int account, Object... args) { int loadIndex = uid == currentDialogId ? 0 : 1; ArrayList arr = (ArrayList) args[2]; endReached[loadIndex] = (Boolean) args[5]; + boolean fromStart = (boolean) args[6]; if (needSearchImageInArr) { if (arr.isEmpty() && (loadIndex != 0 || mergeDialogId == 0) || currentIndex < 0 || currentIndex >= imagesArr.size()) { needSearchImageInArr = false; @@ -3273,16 +3286,26 @@ public void didReceivedNotification(int id, int account, Object... args) { if (!endReached[loadIndex]) { loadingMoreImages = true; - MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, loadFromMaxId, sharedMediaType, 1, classGuid); + MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, loadFromMaxId, 0, sharedMediaType, 1, classGuid, 0); } } } else { int added = 0; - for (MessageObject message : arr) { + for (int i = 0; i < arr.size(); i++) { + MessageObject message = arr.get(fromStart ? arr.size() - 1 - i : i); if (imagesByIds[loadIndex].indexOfKey(message.getId()) < 0) { added++; if (opennedFromMedia) { - imagesArr.add(message); + if (fromStart) { + imagesArr.add(0, message); + startOffset--; + currentIndex++; + if (startOffset < 0) { + startOffset = 0; + } + } else { + imagesArr.add(message); + } } else { imagesArr.add(0, message); } @@ -3290,8 +3313,8 @@ public void didReceivedNotification(int id, int account, Object... args) { } } if (opennedFromMedia) { - if (added == 0) { - totalImagesCount = imagesArr.size(); + if (added == 0 && !fromStart) { + totalImagesCount = startOffset + imagesArr.size(); totalImagesCountMerge = 0; } } else { @@ -3835,7 +3858,7 @@ public void onItemClick(int id) { disableShowCheck = true; Bundle args2 = new Bundle(); args2.putLong("dialog_id", currentDialogId); - MediaActivity mediaActivity = new MediaActivity(args2, new int[]{-1, -1, -1, -1, -1, -1}, null, sharedMediaType); + MediaActivity mediaActivity = new MediaActivity(args2, null); if (parentChatActivity != null) { mediaActivity.setChatInfo(parentChatActivity.getCurrentChatInfo()); } @@ -6703,6 +6726,9 @@ private boolean supportsSendingNewEntities() { return parentChatActivity != null && (parentChatActivity.currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(parentChatActivity.currentEncryptedChat.layer) >= 101); } + public boolean hasCaptionForAllMedia; + public CharSequence captionForAllMedia; + private void closeCaptionEnter(boolean apply) { if (currentIndex < 0 || currentIndex >= imagesArrLocals.size() || captionEditText.getTag() == null) { return; @@ -6713,7 +6739,9 @@ private void closeCaptionEnter(boolean apply) { CharSequence[] result = new CharSequence[] {caption}; ArrayList entities = MediaDataController.getInstance(currentAccount).getEntities(result, supportsSendingNewEntities()); - if (object instanceof MediaController.PhotoEntry) { + if (hasCaptionForAllMedia) { + captionForAllMedia = caption; + } else if (object instanceof MediaController.PhotoEntry) { MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) object; photoEntry.caption = result[0]; photoEntry.entities = entities; @@ -7052,7 +7080,6 @@ public void onOrientationChanged(int orientation) { if (orientationEventListener == null || aspectRatioFrameLayout == null || aspectRatioFrameLayout.getVisibility() != View.VISIBLE) { return; } - FileLog.d("orientation = " + orientation); if (parentActivity != null && fullscreenedByButton != 0) { if (fullscreenedByButton == 1) { if (orientation >= 270 - 30 && orientation <= 270 + 30) { @@ -7598,7 +7625,9 @@ public void onAnimationEnd(Animator animation) { private void updateCaptionTextForCurrentPhoto(Object object) { CharSequence caption = null; - if (object instanceof MediaController.PhotoEntry) { + if (hasCaptionForAllMedia) { + caption = captionForAllMedia; + } else if (object instanceof MediaController.PhotoEntry) { caption = ((MediaController.PhotoEntry) object).caption; } else if (object instanceof TLRPC.BotInlineResult) { //caption = ((TLRPC.BotInlineResult) object).send_message.caption; @@ -7734,7 +7763,7 @@ private boolean hasAnimatedMediaEntities() { private Bitmap createCroppedBitmap(Bitmap bitmap, MediaController.CropState cropState, int[] extraTransform, boolean mirror) { try { - int tr = cropState.transformRotation + (extraTransform != null ? extraTransform[0] : 0); + int tr = (cropState.transformRotation + (extraTransform != null ? extraTransform[0] : 0)) % 360; int w = bitmap.getWidth(); int h = bitmap.getHeight(); int fw = w, rotatedW = w; @@ -9836,6 +9865,7 @@ private void onPhotoShow(final MessageObject messageObject, final TLRPC.FileLoca MessageObject openingObject = imagesArr.get(index); if (!openingObject.scheduled && (parentChatActivity == null || !parentChatActivity.isThreadChat())) { opennedFromMedia = true; + startOffset = object.starOffset; menuItem.showSubItem(gallery_menu_showinchat); if (openingObject.canForwardMessage()) { setItemVisible(sendItem, true, false); @@ -10130,7 +10160,7 @@ private void setIsAboutToSwitchToIndex(int index, boolean init, boolean animated } else { if (totalImagesCount + totalImagesCountMerge != 0 && !needSearchImageInArr) { if (opennedFromMedia) { - if (imagesArr.size() < totalImagesCount + totalImagesCountMerge && !loadingMoreImages && switchingToIndex > imagesArr.size() - 5) { + if (startOffset + imagesArr.size() < totalImagesCount + totalImagesCountMerge && !loadingMoreImages && switchingToIndex > imagesArr.size() - 5) { int loadFromMaxId = imagesArr.isEmpty() ? 0 : imagesArr.get(imagesArr.size() - 1).getId(); int loadIndex = 0; if (endReached[loadIndex] && mergeDialogId != 0) { @@ -10139,8 +10169,18 @@ private void setIsAboutToSwitchToIndex(int index, boolean init, boolean animated loadFromMaxId = 0; } } + if (!placeProvider.loadMore()) { - MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, loadFromMaxId, sharedMediaType, 1, classGuid); + MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, loadFromMaxId, 0, sharedMediaType, 1, classGuid, 0); + loadingMoreImages = true; + } + } + + if (startOffset > 0 && switchingToIndex < 5 && !imagesArr.isEmpty()) { + int loadFromMinId = imagesArr.get(0).getId(); + int loadIndex = 0; + if (!placeProvider.loadMore()) { + MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 40, 0, loadFromMinId, sharedMediaType, 1, classGuid, 0); loadingMoreImages = true; } } @@ -10151,7 +10191,7 @@ private void setIsAboutToSwitchToIndex(int index, boolean init, boolean animated actionBar.setSubtitle(subtitle); actionBar.setTitleScrollNonFitText(true); } else { - actionBar.setTitle(LocaleController.formatString("Of", R.string.Of, switchingToIndex + 1, totalImagesCount + totalImagesCountMerge)); + actionBar.setTitle(LocaleController.formatString("Of", R.string.Of, startOffset + switchingToIndex + 1, totalImagesCount + totalImagesCountMerge)); } } else { if (imagesArr.size() < totalImagesCount + totalImagesCountMerge && !loadingMoreImages && switchingToIndex < 5) { @@ -10164,7 +10204,7 @@ private void setIsAboutToSwitchToIndex(int index, boolean init, boolean animated } } - MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 80, loadFromMaxId, sharedMediaType, 1, classGuid); + MediaDataController.getInstance(currentAccount).loadMedia(loadIndex == 0 ? currentDialogId : mergeDialogId, 80, loadFromMaxId, 0, sharedMediaType, 1, classGuid, 0); loadingMoreImages = true; } actionBar.setTitle(LocaleController.formatString("Of", R.string.Of, (totalImagesCount + totalImagesCountMerge - imagesArr.size()) + switchingToIndex + 1, totalImagesCount + totalImagesCountMerge)); @@ -10393,7 +10433,11 @@ private void setIsAboutToSwitchToIndex(int index, boolean init, boolean animated if (object instanceof MediaController.PhotoEntry) { MediaController.PhotoEntry photoEntry = ((MediaController.PhotoEntry) object); fromCamera = photoEntry.bucketId == 0 && photoEntry.dateTaken == 0 && imagesArrLocals.size() == 1; - caption = photoEntry.caption; + if (hasCaptionForAllMedia) { + caption = captionForAllMedia; + } else { + caption = photoEntry.caption; + } ttl = photoEntry.ttl; isFiltered = photoEntry.isFiltered; isPainted = photoEntry.isPainted; @@ -11962,6 +12006,7 @@ public boolean openPhoto(final MessageObject messageObject, final TLRPC.FileLoca return false; } + hasCaptionForAllMedia = false; doneButtonPressed = false; allowShowFullscreenButton = true; parentChatActivity = chatActivity; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PinchToZoomHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/PinchToZoomHelper.java index 3ff224df9f8..6cb9b919937 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PinchToZoomHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PinchToZoomHelper.java @@ -42,6 +42,7 @@ public class PinchToZoomHelper { private final ViewGroup parentView; + private final ViewGroup fragmentView; private ZoomOverlayView overlayView; private View child; @@ -54,6 +55,9 @@ public class PinchToZoomHelper { float parentOffsetX; float parentOffsetY; + float fragmentOffsetX; + float fragmentOffsetY; + float pinchCenterX; float pinchCenterY; @@ -89,8 +93,9 @@ public class PinchToZoomHelper { private boolean isHardwareVideo; - public PinchToZoomHelper(ViewGroup parentView) { + public PinchToZoomHelper(ViewGroup parentView, ViewGroup fragmentView) { this.parentView = parentView; + this.fragmentView = fragmentView; } public void startZoom(View child, ImageReceiver image, MessageObject messageObject) { @@ -217,6 +222,21 @@ private boolean updateViewsLocation() { currentView = (View) currentView.getParent(); } + float fragmentOffsetX = 0; + float fragmentOffsetY = 0; + currentView = child; + while (currentView != fragmentView) { + if (currentView == null) { + return false; + } + fragmentOffsetX += currentView.getLeft(); + fragmentOffsetY += currentView.getTop(); + currentView = (View) currentView.getParent(); + } + + this.fragmentOffsetX = fragmentOffsetX; + this.fragmentOffsetY = fragmentOffsetY; + this.parentOffsetX = parentOffsetX; this.parentOffsetY = parentOffsetY; return true; @@ -243,8 +263,6 @@ public void onAnimationEnd(Animator animation) { } } }); -// finishTransition.setDuration(350); -// finishTransition.setInterpolator(new OvershootInterpolator(1.05f)); finishTransition.setDuration(220); finishTransition.setInterpolator(CubicBezierInterpolator.DEFAULT); @@ -302,7 +320,7 @@ public boolean isInOverlayModeFor(View child) { public boolean onTouchEvent(MotionEvent ev) { if (updateViewsLocation() && child != null) { - ev.offsetLocation(-parentOffsetX, -parentOffsetY); + ev.offsetLocation(-fragmentOffsetX, -fragmentOffsetY); return child.onTouchEvent(ev); } return false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index d4b54cca951..af95ed94322 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -81,6 +81,8 @@ import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.ViewPager; +import com.google.android.exoplayer2.util.Log; + import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; @@ -179,7 +181,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; -public class ProfileActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, DialogsActivity.DialogsActivityDelegate, SharedMediaLayout.SharedMediaPreloaderDelegate, ImageUpdater.ImageUpdaterDelegate { +public class ProfileActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, DialogsActivity.DialogsActivityDelegate, SharedMediaLayout.SharedMediaPreloaderDelegate, ImageUpdater.ImageUpdaterDelegate, SharedMediaLayout.Delegate { private RecyclerListView listView; private RecyclerListView searchListView; @@ -403,6 +405,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private int membersEndRow; private int addMemberRow; private int subscribersRow; + private int subscribersRequestsRow; private int administratorsRow; private int blockedUsersRow; private int membersSectionRow; @@ -1884,7 +1887,7 @@ public void onItemClick(final int id) { did = -chatId; } ArrayList users = chatInfo != null && chatInfo.participants != null && chatInfo.participants.participants.size() > 5 ? sortedUsers : null; - sharedMediaLayout = new SharedMediaLayout(context, did, sharedMediaPreloader, userInfo != null ? userInfo.common_chats_count : 0, sortedUsers, chatInfo, users != null, this) { + sharedMediaLayout = new SharedMediaLayout(context, did, sharedMediaPreloader, userInfo != null ? userInfo.common_chats_count : 0, sortedUsers, chatInfo, users != null, this, this, SharedMediaLayout.VIEW_TYPE_PROFILE_ACTIVITY) { @Override protected void onSelectedTabChanged() { updateSelectedMediaTabText(); @@ -1996,6 +1999,12 @@ public boolean dispatchTouchEvent(MotionEvent ev) { if (pinchToZoomHelper.isInOverlayMode()) { return pinchToZoomHelper.onTouchEvent(ev); } + if (sharedMediaLayout != null && sharedMediaLayout.isInFastScroll() && sharedMediaLayout.getY() == 0) { + return sharedMediaLayout.dispatchFastScrollEvent(ev); + } + if (sharedMediaLayout != null && sharedMediaLayout.checkPinchToZoom(ev)) { + return true; + } return super.dispatchTouchEvent(ev); } @@ -2604,6 +2613,9 @@ public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerVi ChatUsersActivity fragment = new ChatUsersActivity(args); fragment.setInfo(chatInfo); presentFragment(fragment); + } else if (position == subscribersRequestsRow) { + MemberRequestsActivity activity = new MemberRequestsActivity(chatId); + presentFragment(activity); } else if (position == administratorsRow) { Bundle args = new Bundle(); args.putLong("chat_id", chatId); @@ -2737,6 +2749,7 @@ public boolean onItemClick(View view, int position) { SharedConfig.messageSeenHintCount = 3; SharedConfig.emojiInteractionsHintCount = 3; SharedConfig.dayNightThemeSwitchHintCount = 3; + SharedConfig.fastScrollHintCount = 3; ChatThemeController.getInstance(currentAccount).clearCache(); } else if (which == 7) { VoIPHelper.showCallDebugSettings(getParentActivity()); @@ -3172,6 +3185,7 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { scrolling = newState != RecyclerView.SCROLL_STATE_IDLE; searchItem.setEnabled(!scrolling && !isPulledDown); } + sharedMediaLayout.scrollingByUser = listView.scrollingByUser; } @Override @@ -3290,7 +3304,7 @@ public void onAnimationEnd(Animator animation) { } else { decorView = frameLayout; } - pinchToZoomHelper = new PinchToZoomHelper(decorView) { + pinchToZoomHelper = new PinchToZoomHelper(decorView, frameLayout) { Paint statusBarPaint; @Override @@ -3376,6 +3390,11 @@ public TLRPC.Chat getCurrentChat() { return currentChat; } + @Override + public boolean isFragmentOpened() { + return isFragmentOpened; + } + private void openAvatar() { if (listView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING) { return; @@ -3444,7 +3463,8 @@ private void onWriteButtonClick() { if (!getMessagesController().checkCanOpenChat(args, ProfileActivity.this)) { return; } - if (!AndroidUtilities.isTablet()) { + boolean removeFragment = arguments.getBoolean("removeFragmentOnChatOpen", true); + if (!AndroidUtilities.isTablet() && removeFragment) { getNotificationCenter().removeObserver(ProfileActivity.this, NotificationCenter.closeChats); getNotificationCenter().postNotificationName(NotificationCenter.closeChats); } @@ -3454,7 +3474,7 @@ private void onWriteButtonClick() { } ChatActivity chatActivity = new ChatActivity(args); chatActivity.setPreloadedSticker(getMediaDataController().getGreetingsSticker(), false); - presentFragment(chatActivity, true); + presentFragment(chatActivity, removeFragment); if (AndroidUtilities.isTablet()) { finishFragment(); } @@ -3852,7 +3872,7 @@ private void getChannelParticipants(boolean reload) { participant.inviter_id = participant.channelParticipant.inviter_id; participant.user_id = MessageObject.getPeerId(participant.channelParticipant.peer); participant.date = participant.channelParticipant.date; - if (participantsMap.indexOfKey(participant.user_id) < 0) { + if (participant.user_id != 0 && participantsMap.indexOfKey(participant.user_id) < 0) { if (chatInfo.participants == null) { chatInfo.participants = new TLRPC.TL_chatParticipants(); } @@ -3953,6 +3973,11 @@ private void setMediaHeaderVisible(boolean visible) { if (sharedMediaLayout.isSearchItemVisible()) { mediaSearchItem.setVisibility(View.VISIBLE); } + if (sharedMediaLayout.isCalendarItemVisible()) { + sharedMediaLayout.photoVideoOptionsItem.setVisibility(View.VISIBLE); + } else { + sharedMediaLayout.photoVideoOptionsItem.setVisibility(View.INVISIBLE); + } } ArrayList animators = new ArrayList<>(); @@ -3967,6 +3992,8 @@ private void setMediaHeaderVisible(boolean visible) { animators.add(ObjectAnimator.ofFloat(editItem, View.TRANSLATION_Y, visible ? -AndroidUtilities.dp(10) : 0.0f)); animators.add(ObjectAnimator.ofFloat(mediaSearchItem, View.ALPHA, visible ? 1.0f : 0.0f)); animators.add(ObjectAnimator.ofFloat(mediaSearchItem, View.TRANSLATION_Y, visible ? 0.0f : AndroidUtilities.dp(10))); + animators.add(ObjectAnimator.ofFloat(sharedMediaLayout.photoVideoOptionsItem, View.ALPHA, visible ? 1.0f : 0.0f)); + animators.add(ObjectAnimator.ofFloat(sharedMediaLayout.photoVideoOptionsItem, View.TRANSLATION_Y, visible ? 0.0f : AndroidUtilities.dp(10))); animators.add(ObjectAnimator.ofFloat(actionBar, ACTIONBAR_HEADER_PROGRESS, visible ? 1.0f : 0.0f)); animators.add(ObjectAnimator.ofFloat(onlineTextView[1], View.ALPHA, visible ? 0.0f : 1.0f)); animators.add(ObjectAnimator.ofFloat(mediaCounterTextView, View.ALPHA, visible ? 1.0f : 0.0f)); @@ -3996,6 +4023,9 @@ public void onAnimationEnd(Animator animation) { if (sharedMediaLayout.isSearchItemVisible()) { mediaSearchItem.setVisibility(View.VISIBLE); } + + sharedMediaLayout.photoVideoOptionsItem.setVisibility(View.INVISIBLE); + headerShadowAnimatorSet = new AnimatorSet(); headerShadowAnimatorSet.playTogether(ObjectAnimator.ofFloat(ProfileActivity.this, HEADER_SHADOW, 1.0f)); headerShadowAnimatorSet.setDuration(100); @@ -4117,14 +4147,23 @@ private void checkListViewScroll() { } } - private void updateSelectedMediaTabText() { + public void updateSelectedMediaTabText() { if (sharedMediaLayout == null || mediaCounterTextView == null) { return; } int id = sharedMediaLayout.getClosestTab(); int[] mediaCount = sharedMediaPreloader.getLastMediaCount(); if (id == 0) { - mediaCounterTextView.setText(LocaleController.formatPluralString("Media", mediaCount[MediaDataController.MEDIA_PHOTOVIDEO])); + if (mediaCount[MediaDataController.MEDIA_VIDEOS_ONLY] == 0 && mediaCount[MediaDataController.MEDIA_PHOTOS_ONLY] == 0) { + mediaCounterTextView.setText(LocaleController.formatPluralString("Media", mediaCount[MediaDataController.MEDIA_PHOTOVIDEO])); + } else if (sharedMediaLayout.getPhotosVideosTypeFilter() == SharedMediaLayout.FILTER_PHOTOS_ONLY || mediaCount[MediaDataController.MEDIA_VIDEOS_ONLY] == 0) { + mediaCounterTextView.setText(LocaleController.formatPluralString("Photos", mediaCount[MediaDataController.MEDIA_PHOTOS_ONLY])); + } else if (sharedMediaLayout.getPhotosVideosTypeFilter() == SharedMediaLayout.FILTER_VIDEOS_ONLY || mediaCount[MediaDataController.MEDIA_PHOTOS_ONLY] == 0) { + mediaCounterTextView.setText(LocaleController.formatPluralString("Videos", mediaCount[MediaDataController.MEDIA_VIDEOS_ONLY])); + } else { + String str = String.format("%s, %s", LocaleController.formatPluralString("Photos", mediaCount[MediaDataController.MEDIA_PHOTOS_ONLY]), LocaleController.formatPluralString("Videos", mediaCount[MediaDataController.MEDIA_VIDEOS_ONLY])); + mediaCounterTextView.setText(str); + } } else if (id == 1) { mediaCounterTextView.setText(LocaleController.formatPluralString("Files", mediaCount[MediaDataController.MEDIA_FILE])); } else if (id == 2) { @@ -4844,9 +4883,18 @@ public void onPause() { @Override public boolean isSwipeBackEnabled(MotionEvent event) { + if (avatarsViewPager != null && avatarsViewPager.getVisibility() == View.VISIBLE && avatarsViewPager.getRealCount() > 1) { + avatarsViewPager.getHitRect(rect); + if (rect.contains((int) event.getX(), (int) event.getY() - actionBar.getMeasuredHeight())) { + return false; + } + } if (sharedMediaRow == -1 || sharedMediaLayout == null) { return true; } + if (!sharedMediaLayout.isSwipeBackEnabled()) { + return false; + } sharedMediaLayout.getHitRect(rect); if (!rect.contains((int) event.getX(), (int) event.getY() - actionBar.getMeasuredHeight())) { return true; @@ -4854,6 +4902,14 @@ public boolean isSwipeBackEnabled(MotionEvent event) { return sharedMediaLayout.isCurrentTabFirst(); } + @Override + public boolean canBeginSlide() { + if (!sharedMediaLayout.isSwipeBackEnabled()) { + return false; + } + return super.canBeginSlide(); + } + public UndoView getUndoView() { return undoView; } @@ -5419,6 +5475,7 @@ private void updateRowsIds() { membersEndRow = -1; addMemberRow = -1; subscribersRow = -1; + subscribersRequestsRow = -1; administratorsRow = -1; blockedUsersRow = -1; membersSectionRow = -1; @@ -5568,6 +5625,9 @@ private void updateRowsIds() { if (chatInfo != null && (currentChat.creator || chatInfo.can_view_participants)) { membersHeaderRow = rowCount++; subscribersRow = rowCount++; + if (chatInfo.requests_pending > 0) { + subscribersRequestsRow = rowCount++; + } administratorsRow = rowCount++; if (chatInfo.banned_count != 0 || chatInfo.kicked_count != 0) { blockedUsersRow = rowCount++; @@ -7016,6 +7076,10 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { textCell.setTextAndIcon(LocaleController.getString("ChannelMembers", R.string.ChannelMembers), R.drawable.actions_viewmembers, position != membersSectionRow - 1); } } + } else if (position == subscribersRequestsRow) { + if (chatInfo != null) { + textCell.setTextAndValueAndIcon(LocaleController.getString("SubscribeRequests", R.string.SubscribeRequests), String.format("%d", chatInfo.requests_pending), R.drawable.actions_requests, position != membersSectionRow - 1); + } } else if (position == administratorsRow) { if (chatInfo != null) { textCell.setTextAndValueAndIcon(LocaleController.getString("ChannelAdministrators", R.string.ChannelAdministrators), String.format("%d", chatInfo.admins_count), R.drawable.actions_addadmin, position != membersSectionRow - 1); @@ -7230,7 +7294,7 @@ public int getItemViewType(int position) { } else if (position == userInfoRow || position == channelInfoRow) { return 3; } else if (position == settingsTimerRow || position == settingsKeyRow || position == reportRow || - position == subscribersRow || position == administratorsRow || position == blockedUsersRow || + position == subscribersRow || position == subscribersRequestsRow || position == administratorsRow || position == blockedUsersRow || position == addMemberRow || position == joinRow || position == unblockRow || position == sendMessageRow || position == notificationRow || position == privacyRow || position == languageRow || position == dataRow || position == chatRow || @@ -8014,7 +8078,11 @@ public void updateListAnimated(boolean updateOnlineCount) { saveScrollPosition(); updateRowsIds(); diffCallback.fillPositions(diffCallback.newPositionToItem); - DiffUtil.calculateDiff(diffCallback).dispatchUpdatesTo(listAdapter); + try { + DiffUtil.calculateDiff(diffCallback).dispatchUpdatesTo(listAdapter); + } catch (Exception e) { + listAdapter.notifyDataSetChanged(); + } if (savedScrollPosition >= 0) { layoutManager.scrollToPositionWithOffset(savedScrollPosition, savedScrollOffset - listView.getPaddingTop()); } @@ -8158,6 +8226,7 @@ public void fillPositions(SparseIntArray sparseIntArray) { put(++pointer, membersHeaderRow, sparseIntArray); put(++pointer, addMemberRow, sparseIntArray); put(++pointer, subscribersRow, sparseIntArray); + put(++pointer, subscribersRequestsRow, sparseIntArray); put(++pointer, administratorsRow, sparseIntArray); put(++pointer, blockedUsersRow, sparseIntArray); put(++pointer, membersSectionRow, sparseIntArray); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SponsoredMessageInfoView.java b/TMessagesProj/src/main/java/org/telegram/ui/SponsoredMessageInfoView.java index f3b4c5bb229..ebbd1a28970 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SponsoredMessageInfoView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SponsoredMessageInfoView.java @@ -10,6 +10,7 @@ import android.view.View; import android.widget.FrameLayout; import android.widget.LinearLayout; +import android.widget.ScrollView; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; @@ -94,7 +95,9 @@ public void onClick(View view) { linearLayout.addView(button, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 34, Gravity.CENTER_HORIZONTAL, 0, 14, 0, 0)); linearLayout.addView(description4, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 14, 0, 0)); - addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 22, 12, 22, 22)); + ScrollView scrollView = new ScrollView(getContext()); + scrollView.addView(linearLayout); + addView(scrollView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 22, 12, 22, 22)); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java index a8129efce07..cdb9e3da0fe 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java @@ -538,6 +538,7 @@ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { frameLayout.addView(recyclerListView); avatarContainer = new ChatAvatarContainer(context, null, false); + avatarContainer.setOccupyStatusBar(!AndroidUtilities.isTablet()); actionBar.addView(avatarContainer, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, !inPreviewMode ? 56 : 0, 0, 40, 0)); TLRPC.Chat chatLocal = getMessagesController().getChat(chat.id); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java index a8d2d312037..d9132050542 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java @@ -64,6 +64,7 @@ import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.EmojiThemes; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.BrightnessControlCell; @@ -81,6 +82,7 @@ import org.telegram.ui.Cells.ThemesHorizontalListCell; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.SeekBarView; import org.telegram.ui.Components.ShareAlert; @@ -89,6 +91,7 @@ import java.io.File; import java.io.FileOutputStream; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; @@ -101,6 +104,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No public final static int THEME_TYPE_BASIC = 0; public final static int THEME_TYPE_NIGHT = 1; public final static int THEME_TYPE_OTHER = 2; + public final static int THEME_TYPE_THEMES_BROWSER = 3; private ListAdapter listAdapter; private RecyclerListView listView; @@ -164,6 +168,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No private int chatListRow; private int chatListInfoRow; private int themeListRow; + private int themeListRow2; private int themeAccentListRow; private int themeInfoRow; @@ -171,6 +176,11 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No private int swipeGestureRow; private int swipeGestureInfoRow; + private int selectThemeHeaderRow; + private int themePreviewRow; + private int editThemeRow; + private int createNewThemeRow; + private int rowCount; private boolean updatingLocation; @@ -185,6 +195,9 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No private final static int share_theme = 2; private final static int edit_theme = 3; private final static int reset_settings = 4; + private final static int day_night_switch = 5; + + private RLottieDrawable sunDrawable; private class GpsLocationListener implements LocationListener { @@ -443,6 +456,7 @@ private void updateRows(boolean notify) { int oldRowCount = rowCount; int prevThemeAccentListRow = themeAccentListRow; + int prevEditThemeRow = editThemeRow; rowCount = 0; emojiRow = -1; @@ -463,6 +477,7 @@ private void updateRows(boolean notify) { scheduleToRow = -1; scheduleFromToInfoRow = -1; themeListRow = -1; + themeListRow2 = -1; themeAccentListRow = -1; themeInfoRow = -1; preferedHeaderRow = -1; @@ -496,11 +511,16 @@ private void updateRows(boolean notify) { swipeGestureRow = -1; swipeGestureInfoRow = -1; + selectThemeHeaderRow = -1; + themePreviewRow = -1; + editThemeRow = -1; + createNewThemeRow = -1; + defaultThemes.clear(); darkThemes.clear(); for (int a = 0, N = Theme.themes.size(); a < N; a++) { Theme.ThemeInfo themeInfo = Theme.themes.get(a); - if (currentType != THEME_TYPE_BASIC) { + if (currentType != THEME_TYPE_BASIC && currentType != THEME_TYPE_THEMES_BROWSER) { if (themeInfo.isLight() || themeInfo.info != null && themeInfo.info.document == null) { continue; } @@ -513,12 +533,38 @@ private void updateRows(boolean notify) { } Collections.sort(defaultThemes, (o1, o2) -> Integer.compare(o1.sortIndex, o2.sortIndex)); - if (currentType == THEME_TYPE_BASIC) { + if (currentType == THEME_TYPE_THEMES_BROWSER) { + selectThemeHeaderRow = rowCount++; + themeListRow2 = rowCount++; + chatListInfoRow = rowCount++; + + themePreviewRow = rowCount++; + themeHeaderRow = rowCount++; + themeListRow = rowCount++; + hasThemeAccents = Theme.getCurrentTheme().hasAccentColors(); + if (themesHorizontalListCell != null) { + themesHorizontalListCell.setDrawDivider(hasThemeAccents); + } + if (hasThemeAccents) { + themeAccentListRow = rowCount++; + } + bubbleRadiusInfoRow = rowCount++; + + Theme.ThemeInfo themeInfo = Theme.getCurrentTheme(); + Theme.ThemeAccent accent = themeInfo.getAccent(false); + if (themeInfo.themeAccents != null && !themeInfo.themeAccents.isEmpty() && accent != null && accent.id >= 100) { + editThemeRow = rowCount++; + } + createNewThemeRow = rowCount++; + swipeGestureInfoRow = rowCount++; + } else if (currentType == THEME_TYPE_BASIC) { textSizeHeaderRow = rowCount++; textSizeRow = rowCount++; backgroundRow = rowCount++; newThemeInfoRow = rowCount++; themeHeaderRow = rowCount++; + // TODO + //themeListRow2 = rowCount++; themeListRow = rowCount++; hasThemeAccents = Theme.getCurrentTheme().hasAccentColors(); if (themesHorizontalListCell != null) { @@ -527,6 +573,7 @@ private void updateRows(boolean notify) { if (hasThemeAccents) { themeAccentListRow = rowCount++; } + // themeInfoRow = rowCount++; bubbleRadiusHeaderRow = rowCount++; @@ -605,9 +652,18 @@ private void updateRows(boolean notify) { listAdapter.notifyItemInserted(themeAccentListRow); } else if (prevThemeAccentListRow != -1 && themeAccentListRow == -1) { listAdapter.notifyItemRemoved(prevThemeAccentListRow); + if (prevEditThemeRow != -1) { + prevEditThemeRow--; + } } else if (themeAccentListRow != -1) { listAdapter.notifyItemChanged(themeAccentListRow); } + + if (prevEditThemeRow == -1 && editThemeRow != -1) { + listAdapter.notifyItemInserted(editThemeRow); + } else if (prevEditThemeRow != -1 && editThemeRow == -1) { + listAdapter.notifyItemRemoved(prevEditThemeRow); + } } } else { int start = nightTypeInfoRow + 1; @@ -744,17 +800,31 @@ public void didReceivedNotification(int id, int account, Object... args) { }); } else if (id == NotificationCenter.needSetDayNightTheme) { updateMenuItem(); + checkCurrentDayNight(); } } @Override public View createView(Context context) { + lastIsDarkTheme = !Theme.isCurrentThemeDay(); + actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(false); if (AndroidUtilities.isTablet()) { actionBar.setOccupyStatusBar(false); } - if (currentType == THEME_TYPE_BASIC) { + if (currentType == THEME_TYPE_THEMES_BROWSER) { + actionBar.setTitle(LocaleController.getString("BrowseThemes", R.string.BrowseThemes)); + ActionBarMenu menu = actionBar.createMenu(); + sunDrawable = new RLottieDrawable(R.raw.sun, "" + R.raw.sun, AndroidUtilities.dp(28), AndroidUtilities.dp(28), true, null); + if (lastIsDarkTheme) { + sunDrawable.setCurrentFrame(sunDrawable.getFramesCount() - 1); + } else { + sunDrawable.setCurrentFrame(0); + } + sunDrawable.setPlayInDirectionOfCustomEndFrame(true); + menuItem = menu.addItem(day_night_switch, sunDrawable); + } else if (currentType == THEME_TYPE_BASIC) { actionBar.setTitle(LocaleController.getString("ChatSettings", R.string.ChatSettings)); ActionBarMenu menu = actionBar.createMenu(); menuItem = menu.addItem(0, R.drawable.ic_ab_other); @@ -773,15 +843,7 @@ public void onItemClick(int id) { if (id == -1) { finishFragment(); } else if (id == create_theme) { - if (getParentActivity() == null) { - return; - } - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("NewTheme", R.string.NewTheme)); - builder.setMessage(LocaleController.getString("CreateNewThemeAlert", R.string.CreateNewThemeAlert)); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - builder.setPositiveButton(LocaleController.getString("CreateTheme", R.string.CreateTheme), (dialog, which) -> AlertsCreator.createThemeCreateDialog(ThemeActivity.this, 0, null, null)); - showDialog(builder.create()); + createNewTheme(); } else if (id == share_theme) { Theme.ThemeInfo currentTheme = Theme.getCurrentTheme(); Theme.ThemeAccent accent = currentTheme.getAccent(false); @@ -793,9 +855,7 @@ public void onItemClick(int id) { showDialog(new ShareAlert(getParentActivity(), null, link, false, link, false)); } } else if (id == edit_theme) { - Theme.ThemeInfo currentTheme = Theme.getCurrentTheme(); - Theme.ThemeAccent accent = currentTheme.getAccent(false); - presentFragment(new ThemePreviewActivity(currentTheme, false, ThemePreviewActivity.SCREEN_TYPE_ACCENT_COLOR, accent.id >= 100, currentType == THEME_TYPE_NIGHT)); + editTheme(); } else if (id == reset_settings) { if (getParentActivity() == null) { return; @@ -847,6 +907,39 @@ public void onItemClick(int id) { if (button != null) { button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); } + } else if (id == day_night_switch) { + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE); + String dayThemeName = preferences.getString("lastDayTheme", "Blue"); + if (Theme.getTheme(dayThemeName) == null || Theme.getTheme(dayThemeName).isDark()) { + dayThemeName = "Blue"; + } + String nightThemeName = preferences.getString("lastDarkTheme", "Dark Blue"); + if (Theme.getTheme(nightThemeName) == null || !Theme.getTheme(nightThemeName).isDark()) { + nightThemeName = "Dark Blue"; + } + Theme.ThemeInfo themeInfo = Theme.getActiveTheme(); + if (dayThemeName.equals(nightThemeName)) { + if (themeInfo.isDark() || dayThemeName.equals("Dark Blue") || dayThemeName.equals("Night")) { + dayThemeName = "Blue"; + } else { + nightThemeName = "Dark Blue"; + } + } + + boolean toDark; + if (toDark = dayThemeName.equals(themeInfo.getKey())) { + themeInfo = Theme.getTheme(nightThemeName); + } else { + themeInfo = Theme.getTheme(dayThemeName); + } + + int[] pos = new int[2]; + menuItem.getIconView().getLocationInWindow(pos); + pos[0] += menuItem.getIconView().getMeasuredWidth() / 2; + pos[1] += menuItem.getIconView().getMeasuredHeight() / 2; + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, themeInfo, false, pos, -1, toDark, menuItem.getIconView()); + updateRows(true); + //AndroidUtilities.updateVisibleRows(listView); } } }); @@ -1049,12 +1142,34 @@ public void onItemClick(int id) { showDialog(dialog); } else if (position == scheduleUpdateLocationRow) { updateSunTime(null, true); + } else if (position == createNewThemeRow) { + createNewTheme(); + } else if (position == editThemeRow) { + editTheme(); } }); return fragmentView; } + private void editTheme() { + Theme.ThemeInfo currentTheme = Theme.getCurrentTheme(); + Theme.ThemeAccent accent = currentTheme.getAccent(false); + presentFragment(new ThemePreviewActivity(currentTheme, false, ThemePreviewActivity.SCREEN_TYPE_ACCENT_COLOR, accent.id >= 100, currentType == THEME_TYPE_NIGHT)); + } + + private void createNewTheme() { + if (getParentActivity() == null) { + return; + } + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString("NewTheme", R.string.NewTheme)); + builder.setMessage(LocaleController.getString("CreateNewThemeAlert", R.string.CreateNewThemeAlert)); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setPositiveButton(LocaleController.getString("CreateTheme", R.string.CreateTheme), (dialog, which) -> AlertsCreator.createThemeCreateDialog(ThemeActivity.this, 0, null, null)); + showDialog(builder.create()); + } + @Override public void onResume() { super.onResume(); @@ -1759,6 +1874,7 @@ public boolean onInterceptTouchEvent(MotionEvent e) { if (currentTheme.currentAccentId != accent.id) { NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, currentTheme, currentType == THEME_TYPE_NIGHT, null, accent.id); + EmojiThemes.saveCustomTheme(currentTheme, accent.id); } else { presentFragment(new ThemePreviewActivity(currentTheme, false, ThemePreviewActivity.SCREEN_TYPE_ACCENT_COLOR, accent.id >= 100, currentType == THEME_TYPE_NIGHT)); } @@ -1862,6 +1978,18 @@ public boolean onInterceptTouchEvent(MotionEvent e) { case 15: view = new SwipeGestureSettingsView(mContext, currentAccount); break; + case 16: + ThemePreviewMessagesCell messagesCell = new ThemePreviewMessagesCell(mContext, parentLayout, 0); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + messagesCell.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); + } + view = messagesCell; + break; + case 17: + DefaultThemesPreviewCell cell = new DefaultThemesPreviewCell(mContext, ThemeActivity.this, currentType); + view = cell; + view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + break; } return new RecyclerListView.Holder(view); } @@ -1957,7 +2085,11 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } else if (position == settingsRow) { headerCell.setText(LocaleController.getString("SETTINGS", R.string.SETTINGS)); } else if (position == themeHeaderRow) { - headerCell.setText(LocaleController.getString("ColorTheme", R.string.ColorTheme)); + if (currentType == THEME_TYPE_THEMES_BROWSER) { + headerCell.setText(LocaleController.getString("BuildMyOwnTheme", R.string.BuildMyOwnTheme)); + } else { + headerCell.setText(LocaleController.getString("ColorTheme", R.string.ColorTheme)); + } } else if (position == textSizeHeaderRow) { headerCell.setText(LocaleController.getString("TextSizeHeader", R.string.TextSizeHeader)); } else if (position == chatListHeaderRow) { @@ -1966,6 +2098,8 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { headerCell.setText(LocaleController.getString("BubbleRadius", R.string.BubbleRadius)); } else if (position == swipeGestureHeaderRow) { headerCell.setText(LocaleController.getString("ChatListSwipeGesture", R.string.ChatListSwipeGesture)); + } else if (position == selectThemeHeaderRow) { + headerCell.setText(LocaleController.getString("SelectTheme", R.string.SelectTheme)); } break; } @@ -2039,12 +2173,21 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } case 14: { TextCell cell = (TextCell) holder.itemView; + cell.setColors(Theme.key_windowBackgroundWhiteBlueText4, Theme.key_windowBackgroundWhiteBlueText4); if (position == backgroundRow) { cell.setTextAndIcon(LocaleController.getString("ChangeChatBackground", R.string.ChangeChatBackground), R.drawable.msg_background, false); - cell.setColors(Theme.key_windowBackgroundWhiteBlueText4, Theme.key_windowBackgroundWhiteBlueText4); + } else if (position == editThemeRow) { + cell.setTextAndIcon(LocaleController.getString("EditCurrentTheme", R.string.EditCurrentTheme), R.drawable.msg_theme, true); + } else if (position == createNewThemeRow) { + cell.setTextAndIcon(LocaleController.getString("CreateNewTheme", R.string.CreateNewTheme), R.drawable.msg_colors, false); } break; } + case 17: { + DefaultThemesPreviewCell cell = (DefaultThemesPreviewCell) holder.itemView; + cell.updateDayNightMode(); + break; + } } } @@ -2075,7 +2218,7 @@ public int getItemViewType(int position) { return 4; } else if (position == scheduleHeaderRow || position == automaticHeaderRow || position == preferedHeaderRow || position == settingsRow || position == themeHeaderRow || position == textSizeHeaderRow || - position == chatListHeaderRow || position == bubbleRadiusHeaderRow || position == swipeGestureHeaderRow) { + position == chatListHeaderRow || position == bubbleRadiusHeaderRow || position == swipeGestureHeaderRow || position == selectThemeHeaderRow) { return 5; } else if (position == automaticBrightnessRow) { return 6; @@ -2095,10 +2238,14 @@ public int getItemViewType(int position) { return 12; } else if (position == bubbleRadiusRow) { return 13; - } else if (position == backgroundRow) { + } else if (position == backgroundRow || position == editThemeRow || position == createNewThemeRow) { return 14; } else if (position == swipeGestureRow) { return 15; + } else if (position == themePreviewRow) { + return 16; + } else if (position == themeListRow2) { + return 17; } return 1; } @@ -2114,7 +2261,7 @@ private static abstract class TintRecyclerListView extends RecyclerListView { public ArrayList getThemeDescriptions() { ArrayList themeDescriptions = new ArrayList<>(); - themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{TextSettingsCell.class, TextCheckCell.class, HeaderCell.class, BrightnessControlCell.class, ThemeTypeCell.class, TextSizeCell.class, BubbleRadiusCell.class, ChatListCell.class, NotificationsCheckCell.class, ThemesHorizontalListCell.class, TintRecyclerListView.class, TextCell.class, SwipeGestureSettingsView.class}, null, null, null, Theme.key_windowBackgroundWhite)); + themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{TextSettingsCell.class, TextCheckCell.class, HeaderCell.class, BrightnessControlCell.class, ThemeTypeCell.class, TextSizeCell.class, BubbleRadiusCell.class, ChatListCell.class, NotificationsCheckCell.class, ThemesHorizontalListCell.class, TintRecyclerListView.class, TextCell.class, SwipeGestureSettingsView.class, DefaultThemesPreviewCell.class}, null, null, null, Theme.key_windowBackgroundWhite)); themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault)); @@ -2201,4 +2348,26 @@ public ArrayList getThemeDescriptions() { return themeDescriptions; } + + boolean lastIsDarkTheme; + + public void checkCurrentDayNight() { + if (currentType != THEME_TYPE_THEMES_BROWSER) { + return; + } + boolean toDark = !Theme.isCurrentThemeDay(); + if (lastIsDarkTheme != toDark) { + lastIsDarkTheme = toDark; + sunDrawable.setCustomEndFrame(toDark ? sunDrawable.getFramesCount() - 1 : 0); + menuItem.getIconView().playAnimation(); + } + if (themeListRow2 >= 0) { + for (int i = 0; i < listView.getChildCount(); i++) { + if (listView.getChildAt(i) instanceof DefaultThemesPreviewCell) { + DefaultThemesPreviewCell cell = (DefaultThemesPreviewCell) listView.getChildAt(i); + cell.updateDayNightMode(); + } + } + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java index ec797bb0f42..37be135ba62 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java @@ -4373,7 +4373,7 @@ public boolean isEnabled(RecyclerView.ViewHolder holder) { public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { View view; if (viewType == 0) { - view = new ChatMessageCell(mContext, new Theme.ResourcesProvider() { + view = new ChatMessageCell(mContext, false, new Theme.ResourcesProvider() { @Override public Integer getColor(String key) { return Theme.getColor(key); diff --git a/TMessagesProj/src/main/res/drawable-hdpi/actions_requests.png b/TMessagesProj/src/main/res/drawable-hdpi/actions_requests.png new file mode 100644 index 00000000000..448317b8900 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/actions_requests.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/calendar_date.9.png b/TMessagesProj/src/main/res/drawable-hdpi/calendar_date.9.png new file mode 100644 index 00000000000..c324f375155 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/calendar_date.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_layer_close.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_layer_close.png new file mode 100644 index 00000000000..edd0f0ec24b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/ic_layer_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_calendar2.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_calendar2.png new file mode 100644 index 00000000000..7c43b92b3a7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_calendar2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomin.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomin.png new file mode 100644 index 00000000000..823e37fe344 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomout.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomout.png new file mode 100644 index 00000000000..3a5a0c5b75a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomout.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/actions_requests.png b/TMessagesProj/src/main/res/drawable-mdpi/actions_requests.png new file mode 100644 index 00000000000..e23b2a3cf7a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/actions_requests.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/calendar_date.9.png b/TMessagesProj/src/main/res/drawable-mdpi/calendar_date.9.png new file mode 100644 index 00000000000..c5d27c7c9fa Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/calendar_date.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_layer_close.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_layer_close.png new file mode 100644 index 00000000000..bb40d67fada Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/ic_layer_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_calendar2.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_calendar2.png new file mode 100644 index 00000000000..8a208ec1855 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_calendar2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomin.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomin.png new file mode 100644 index 00000000000..afd98f35154 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomout.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomout.png new file mode 100644 index 00000000000..86231ecbe1c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomout.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/actions_requests.png b/TMessagesProj/src/main/res/drawable-xhdpi/actions_requests.png new file mode 100644 index 00000000000..b41165d47dd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/actions_requests.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/calendar_date.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/calendar_date.9.png new file mode 100644 index 00000000000..be88ce560ad Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/calendar_date.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_layer_close.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_layer_close.png new file mode 100644 index 00000000000..7462d61284d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_layer_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_calendar2.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calendar2.png new file mode 100644 index 00000000000..a8a76d000e2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calendar2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomin.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomin.png new file mode 100644 index 00000000000..ecf15e47129 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomout.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomout.png new file mode 100644 index 00000000000..f166591542d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomout.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/actions_requests.png b/TMessagesProj/src/main/res/drawable-xxhdpi/actions_requests.png new file mode 100644 index 00000000000..35930d36429 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/actions_requests.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/calendar_date.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/calendar_date.9.png new file mode 100644 index 00000000000..ce1acf88e79 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/calendar_date.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_layer_close.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_layer_close.png new file mode 100644 index 00000000000..c968963a095 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_layer_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calendar2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calendar2.png new file mode 100644 index 00000000000..965ac9719b9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calendar2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomin.png new file mode 100644 index 00000000000..b8863b8eb52 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomout.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomout.png new file mode 100644 index 00000000000..03459cb52f3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomout.png differ diff --git a/TMessagesProj/src/main/res/raw/timer_3.json b/TMessagesProj/src/main/res/raw/timer_3.json new file mode 100644 index 00000000000..9c648db3fe9 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/timer_3.json @@ -0,0 +1 @@ +{"v":"5.5.7","meta":{"g":"LottieFiles AE 0.1.20","a":"","k":"","d":"","tc":""},"fr":60,"ip":0,"op":66,"w":512,"h":512,"nm":"Timer 3","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"NULL SCALE","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[256,256,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.4,0.4,0.4],"y":[0.966,0.966,1]},"o":{"x":[0.28,0.28,0.28],"y":[0,0,0]},"t":0,"s":[30,30,100]},{"i":{"x":[0.7,0.7,0.7],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0.394,0.394,0]},"t":9,"s":[95,95,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":41,"s":[105,105,100]},{"t":44,"s":[100,100,100]}],"ix":6}},"ao":0,"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"CLOCK","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.7,0.7,0.7],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":34,"s":[80,80,100]},{"i":{"x":[0.7,0.7,0.7],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":44,"s":[110,110,100]},{"i":{"x":[0.7,0.7,0.7],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":52,"s":[82,82,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":59,"s":[92,92,100]},{"t":65,"s":[90,90,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":37,"s":[{"i":[[11.211,0],[0,0],[0,0],[0,0],[0,0],[-9.796,7.035],[0,0],[0,0],[0,0]],"o":[[-21,0],[0,0],[-2.305,12.015],[0,0],[7.291,8.293],[15.745,-11.307],[0,0],[0,0],[-0.598,-11.062]],"v":[[-6,-122.848],[-27,-101.848],[-28.463,6.836],[-24.073,27.731],[41.295,111.116],[69.984,113.783],[73.601,84.305],[14.264,9.224],[14.969,-103]],"c":true}]},{"t":46,"s":[{"i":[[11.211,0],[0,0],[0,0],[0,0],[0,0],[-8.163,8.879],[0,0],[0,0],[0,0]],"o":[[-21,0],[0,0],[0.793,12.208],[0,0],[8.824,6.639],[13.119,-14.27],[0,0],[0,0],[-0.598,-11.062]],"v":[[-6,-122.848],[-27,-101.848],[-26.959,15.958],[-17.453,35.076],[61.581,101.988],[90.214,98.77],[87.766,69.173],[14.994,7.518],[14.969,-103]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[-109.352,0],[0,-109.352],[109.352,0],[0,109.352]],"o":[[109.352,0],[0,109.352],[-109.352,0],[0,-109.352]],"v":[[0,-198],[198,0],[0,198],[-198,0]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Combined-Shape","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":37,"op":81,"st":3,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Circle","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":130,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[90,90,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-100.751,0],[0,-100.751],[100.751,0],[0,100.751]],"o":[[100.751,0],[0,100.751],[-100.751,0],[0,-100.751]],"v":[[0,-182.427],[182.426,0],[0,182.426],[-182.427,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":3,"s":[64]},{"t":46,"s":[0]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":30,"ix":5},"lc":2,"lj":2,"bm":0,"d":[{"n":"d","nm":"dash","v":{"a":0,"k":0,"ix":1}},{"n":"o","nm":"offset","v":{"a":0,"k":-17,"ix":7}}],"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":37,"st":3,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Circle Dashes","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":130,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[90,90,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-100.751,0],[0,-100.751],[100.751,0],[0,100.751]],"o":[[100.751,0],[0,100.751],[-100.751,0],[0,-100.751]],"v":[[0,-182.427],[182.426,0],[0,182.426],[-182.427,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":30,"ix":5},"lc":2,"lj":2,"bm":0,"d":[{"n":"d","nm":"dash","v":{"a":0,"k":2,"ix":1}},{"n":"g","nm":"gap","v":{"a":0,"k":75,"ix":2}},{"n":"o","nm":"offset","v":{"a":0,"k":108,"ix":7}}],"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":37,"st":3,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Arrow 1","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":3,"s":[204]},{"t":46,"s":[0]}],"ix":10},"p":{"a":0,"k":[-5.75,12.531,0],"ix":2},"a":{"a":0,"k":[-6.389,13.924,0],"ix":1},"s":{"a":0,"k":[90,90,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.126,-15.958],[0,0],[0,0],[-8.163,8.879],[0,0],[2.494,3.074]],"o":[[-0.833,11.803],[0,0],[8.824,6.639],[13.119,-14.27],[0,0],[-13.883,-15.574]],"v":[[-26.959,15.958],[-17.029,36.066],[61.581,101.988],[90.214,98.77],[87.766,69.173],[14.994,7.518]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-5.681,15.34],"ix":2},"a":{"a":0,"k":[-5.681,15.34],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Combined-Shape","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":37,"st":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Arrow 2","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":3,"s":[28]},{"t":46,"s":[0]}],"ix":10},"p":{"a":0,"k":[-5.75,12.5,0],"ix":2},"a":{"a":0,"k":[-6.389,13.889,0],"ix":1},"s":{"a":0,"k":[90,90,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[11.211,0],[0,0],[0,0],[-0.398,-7.127],[-0.792,23.558],[0,0]],"o":[[-21,0],[0,0],[0.086,2.004],[0.924,16.553],[0.302,-8.972],[-0.598,-11.062]],"v":[[-6,-122.848],[-27,-101.848],[-26.959,15.958],[-27.036,15.947],[14.959,7.553],[14.969,-103]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-5.681,15.34],"ix":2},"a":{"a":0,"k":[-5.681,15.34],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Combined-Shape","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":37,"st":1,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-v21/styles.xml b/TMessagesProj/src/main/res/values-v21/styles.xml index fc0fb67117d..501832ddfe7 100644 --- a/TMessagesProj/src/main/res/values-v21/styles.xml +++ b/TMessagesProj/src/main/res/values-v21/styles.xml @@ -166,4 +166,9 @@ true + + diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index ad0941e8637..b16c674b6e1 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -4743,4 +4743,70 @@ To protect privacy, views are only stored for **7 days** If **%s** were viewing the chat now, they would also see this animation. Tap here to view how **%s** will see this theme when using night mode. + Attach... + Calendar + Zoom in + Zoom out + Show photos + Show videos + You can hold and move this bar for faster scrolling + Switch to Night Mode + Browse Themes + Browse Themes + Build my own theme + Edit Current Theme + Create a New Theme + Approve New Members + Turn this on if you want users to join only after they are approved by an admin. + No join requests + Request to Join Group + Request to Join Channel + This group accepts new members only after they are approved by its admins. + This channel accepts new subscribers only after they are approved by its admins. + Request to join sent + You will be added to the group once its admins approve your request. + You will be added to the channel once its admins approve your request. + Member Requests + Subscribe Requests + %1$d requested to join + %1$d requested to join + %1$d requested to join + %1$d requested to join + %1$d requested to join + %1$d requested to join + %1$d users requested to join + %1$d user requested to join + %1$d users requested to join + %1$d users requested to join + %1$d users requested to join + %1$d users requested to join + You have no pending requests\nto join your group. + Add to Group + Add to Channel + Dismiss + Dismiss request + requested to join %1$s + added by %1$s %2$s + %1$s has been added to the group + %1$s has been added to the channel + Search member requests + Your request to join the group was approved + Your request to join the channel was approved + un1 joined via invite link un2, approved by un3 + No join requests + There are no pending requests\nto join this channel. + M + T + W + T + F + S + S + Link Name (Optional) + Only you and other admins will see this name. + CREATE + SAVE + un1 was accepted into the group + %1$s was accepted into the group + %2$s|%1$s was accepted into the group