From c99bf67ef77392cb2220527c66ed973a95f2230d Mon Sep 17 00:00:00 2001 From: xtaodada Date: Sun, 11 Feb 2024 12:17:10 +0800 Subject: [PATCH] feat: remote peer color --- .../org/telegram/messenger/ChatObject.java | 16 + .../org/telegram/messenger/UserObject.java | 25 +- .../java/org/telegram/ui/LaunchActivity.java | 2 + .../org/telegram/ui/PeerColorActivity.java | 15 +- .../helpers/remote/PeerColorHelper.java | 321 ++++++++++++++++++ ...ColorHelper.kt => LocalPeerColorHelper.kt} | 2 +- 6 files changed, 362 insertions(+), 19 deletions(-) create mode 100644 TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/remote/PeerColorHelper.java rename TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/helper/{PeerColorHelper.kt => LocalPeerColorHelper.kt} (98%) diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java index 1113b1c703..c572f6c701 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java @@ -32,6 +32,8 @@ import java.util.HashSet; import java.util.List; +import tw.nekomimi.nekogram.helpers.remote.PeerColorHelper; + public class ChatObject { public static final int CHAT_TYPE_CHAT = 0; @@ -2096,22 +2098,36 @@ public static MessagesController.PeerColor getPeerColorForAvatar(int currentAcco public static int getColorId(TLRPC.Chat chat) { if (chat == null) return 0; + + Integer replace = PeerColorHelper.getInstance().getColorId(chat); + if (replace != null) return replace; + if (chat.color != null && (chat.color.flags & 1) != 0) return chat.color.color; return (int) (chat.id % 7); } public static long getEmojiId(TLRPC.Chat chat) { + Long replace = PeerColorHelper.getInstance().getEmojiId(chat); + if (replace != null) return replace; + if (chat != null && chat.color != null && (chat.color.flags & 2) != 0) return chat.color.background_emoji_id; return 0; } public static int getProfileColorId(TLRPC.Chat chat) { if (chat == null) return 0; + + Integer replace = PeerColorHelper.getInstance().getProfileColorId(chat); + if (replace != null) return replace; + if (chat.profile_color != null && (chat.profile_color.flags & 1) != 0) return chat.profile_color.color; return -1; } public static long getProfileEmojiId(TLRPC.Chat chat) { + Long replace = PeerColorHelper.getInstance().getProfileEmojiId(chat); + if (replace != null) return replace; + if (chat != null && chat.profile_color != null && (chat.profile_color.flags & 2) != 0) return chat.profile_color.background_emoji_id; return 0; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserObject.java index 9e144fb50c..ffb25421cf 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UserObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserObject.java @@ -15,8 +15,9 @@ import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.tgnet.TLRPC; +import tw.nekomimi.nekogram.helpers.remote.PeerColorHelper; import xyz.nextalone.nagram.helper.MessageHelper; -import xyz.nextalone.nagram.helper.PeerColorHelper; +import xyz.nextalone.nagram.helper.LocalPeerColorHelper; public class UserObject { @@ -160,30 +161,44 @@ public static MessagesController.PeerColor getPeerColorForAvatar(int currentAcco public static int getColorId(TLRPC.User user) { if (user == null) return 0; - Integer replace = PeerColorHelper.getColorId(user); + + Integer replace = LocalPeerColorHelper.getColorId(user); + if (replace != null) return replace; + replace = PeerColorHelper.getInstance().getColorId(user); if (replace != null) return replace; + if (user.color != null && (user.color.flags & 1) != 0) return user.color.color; return (int) (user.id % 7); } public static long getEmojiId(TLRPC.User user) { - Long replace = PeerColorHelper.getEmojiId(user); + Long replace = LocalPeerColorHelper.getEmojiId(user); if (replace != null) return replace; + replace = PeerColorHelper.getInstance().getEmojiId(user); + if (replace != null) return replace; + if (user != null && user.color != null && (user.color.flags & 2) != 0) return user.color.background_emoji_id; return 0; } public static int getProfileColorId(TLRPC.User user) { if (user == null) return 0; - Integer replace = PeerColorHelper.getProfileColorId(user); + + Integer replace = LocalPeerColorHelper.getProfileColorId(user); + if (replace != null) return replace; + replace = PeerColorHelper.getInstance().getProfileColorId(user); if (replace != null) return replace; + if (user.profile_color != null && (user.profile_color.flags & 1) != 0) return user.profile_color.color; return -1; } public static long getProfileEmojiId(TLRPC.User user) { - Long replace = PeerColorHelper.getProfileEmojiId(user); + Long replace = LocalPeerColorHelper.getProfileEmojiId(user); if (replace != null) return replace; + replace = PeerColorHelper.getInstance().getProfileEmojiId(user); + if (replace != null) return replace; + if (user != null && user.profile_color != null && (user.profile_color.flags & 2) != 0) return user.profile_color.background_emoji_id; return 0; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 220afe103c..bc66f35b70 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -222,6 +222,7 @@ import tw.nekomimi.nekogram.InternalUpdater; import tw.nekomimi.nekogram.helpers.SettingsHelper; import tw.nekomimi.nekogram.helpers.remote.EmojiHelper; +import tw.nekomimi.nekogram.helpers.remote.PeerColorHelper; import tw.nekomimi.nekogram.helpers.remote.WallpaperHelper; import tw.nekomimi.nekogram.ui.BottomBuilder; import tw.nekomimi.nekogram.NekoConfig; @@ -1027,6 +1028,7 @@ public void onViewDetachedFromWindow(View v) { } EmojiHelper.getInstance().checkEmojiPacks(); WallpaperHelper.getInstance().checkWallPaper(); + PeerColorHelper.getInstance().checkPeerColor(); BackupAgent.requestBackup(this); RestrictedLanguagesSelectActivity.checkRestrictedLanguages(false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PeerColorActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PeerColorActivity.java index 710b4c2d78..d2736ee98d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PeerColorActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PeerColorActivity.java @@ -27,11 +27,8 @@ import android.graphics.Shader; import android.graphics.drawable.Drawable; import android.os.Build; -import android.os.Bundle; -import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.text.Spanned; -import android.text.TextUtils; import android.text.style.ReplacementSpan; import android.util.SparseIntArray; import android.util.TypedValue; @@ -50,15 +47,10 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.google.common.io.CharSource; - import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; -import org.telegram.messenger.BotWebViewVibrationEffect; import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; -import org.telegram.messenger.ChatThemeController; -import org.telegram.messenger.DialogObject; import org.telegram.messenger.Emoji; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; @@ -92,13 +84,11 @@ import org.telegram.ui.Components.Easings; import org.telegram.ui.Components.FilledTabsView; import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.Premium.PremiumGradient; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.SimpleThemeDescription; -import org.telegram.ui.Components.SpannableStringLight; import org.telegram.ui.Components.Text; import org.telegram.ui.Components.ViewPagerFixed; import org.telegram.ui.Stories.StoriesUtilities; @@ -108,8 +98,7 @@ import java.util.ArrayList; import java.util.List; -import xyz.nextalone.nagram.NaConfig; -import xyz.nextalone.nagram.helper.PeerColorHelper; +import xyz.nextalone.nagram.helper.LocalPeerColorHelper; public class PeerColorActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { @@ -1139,7 +1128,7 @@ private void apply() { if (isChannel) { finishFragment(); } else { - PeerColorHelper.apply(namePage.selectedColor, namePage.selectedEmoji, profilePage.selectedColor, profilePage.selectedEmoji); + LocalPeerColorHelper.apply(namePage.selectedColor, namePage.selectedEmoji, profilePage.selectedColor, profilePage.selectedEmoji); final TLRPC.User me = getUserConfig().getCurrentUser(); if (me.color == null) { me.color = new TLRPC.TL_peerColor(); diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/remote/PeerColorHelper.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/remote/PeerColorHelper.java new file mode 100644 index 0000000000..59d1fecdc4 --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/helpers/remote/PeerColorHelper.java @@ -0,0 +1,321 @@ +package tw.nekomimi.nekogram.helpers.remote; + +import android.text.TextUtils; +import android.util.Base64; + +import org.json.JSONException; +import org.json.JSONObject; +import org.telegram.messenger.FileLog; +import org.telegram.tgnet.AbstractSerializedData; +import org.telegram.tgnet.SerializedData; +import org.telegram.tgnet.TLRPC; + +import java.util.ArrayList; +import java.util.HashMap; + +public class PeerColorHelper extends BaseRemoteHelper { + private static final String PEERCOLOR_TAG = "peercolor"; + private static volatile PeerColorHelper Instance; + private final ArrayList peerColorInfo = new ArrayList<>(); + private final HashMap peerColorInfoMap = new HashMap<>(); + private boolean loading = false; + + public static PeerColorHelper getInstance() { + PeerColorHelper localInstance = Instance; + if (localInstance == null) { + synchronized (PeerColorHelper.class) { + localInstance = Instance; + if (localInstance == null) { + Instance = localInstance = new PeerColorHelper(); + } + return localInstance; + } + } + return localInstance; + } + + @Override + protected void onError(String text, Delegate delegate) { + + } + + @Override + protected String getTag() { + return PEERCOLOR_TAG; + } + + @Override + protected void onLoadSuccess(ArrayList responses, Delegate delegate) { + var tag = getTag(); + var json = responses.size() > 0 ? responses.get(0) : null; + if (json == null) { + preferences.edit() + .remove(tag + "_update_time") + .remove(tag) + .apply(); + return; + } + + try { + ArrayList peerColors = new ArrayList<>(); + var array = json.getJSONArray("peerColors"); + + for (int i = 0; i < array.length(); i++) { + var obj = array.getJSONObject(i); + var info = new PeerColorInfo( + obj.getLong("chat_id"), + obj.getInt("version") + ); + info.setValue(obj); + if (peerColorInfoMap.containsKey(info.chatId)) { + var oldInfo = peerColorInfoMap.get(info.chatId); + if (oldInfo != null && oldInfo.version == info.version) { + peerColors.add(oldInfo); + } else { + peerColors.add(info); + } + } else { + peerColors.add(info); + } + } + + peerColorInfo.clear(); + peerColorInfo.addAll(peerColors); + peerColorInfoMap.clear(); + for (PeerColorInfo info : peerColorInfo) { + peerColorInfoMap.put(info.chatId, info); + } + savePeerColorInfo(); + } catch (JSONException e) { + FileLog.e(e); + delegate.onTLResponse(null, e.getLocalizedMessage()); + } + } + + public void loadPeerColorInfo() { + var tag = getTag(); + String list = preferences.getString(tag, ""); + peerColorInfo.clear(); + peerColorInfoMap.clear(); + if (!TextUtils.isEmpty(list)) { + byte[] bytes = Base64.decode(list, Base64.DEFAULT); + SerializedData data = new SerializedData(bytes); + int count = data.readInt32(false); + for (int a = 0; a < count; a++) { + PeerColorInfo info = PeerColorInfo.deserialize(data); + peerColorInfo.add(info); + peerColorInfoMap.put(info.chatId, info); + } + data.cleanup(); + } + } + + public void savePeerColorInfo() { + var tag = getTag(); + SerializedData serializedData = new SerializedData(); + serializedData.writeInt32(peerColorInfo.size()); + for (PeerColorInfo info : peerColorInfo) { + info.serializeToStream(serializedData); + } + preferences.edit() + .putLong(tag + "_update_time", System.currentTimeMillis()) + .putString(tag, Base64.encodeToString(serializedData.toByteArray(), Base64.NO_WRAP | Base64.NO_PADDING)) + .apply(); + serializedData.cleanup(); + } + + public boolean needUpdate() { + var tag = getTag(); + long oldTime = preferences.getLong(tag + "_update_time", 0L); + long nowTime = System.currentTimeMillis(); + int TTL = 15 * 60; + return oldTime + TTL <= nowTime; + } + + public void checkPeerColor() { + if (loading) { + return; + } + loading = true; + loadPeerColorInfo(); + if (needUpdate()) { + load(); + } + loading = false; + } + + public Integer getColorId(long chatId) { + if (!peerColorInfoMap.containsKey(chatId)) { + return null; + } + var info = peerColorInfoMap.get(chatId); + if (info != null && (info.flags & 1) != 0) { + return info.colorId; + } + return null; + } + + public Integer getColorId(TLRPC.User user) { + return getColorId(user.id); + } + + public Integer getColorId(TLRPC.Chat chat) { + return getColorId(-chat.id); + } + + public Long getEmojiId(long chatId) { + if (!peerColorInfoMap.containsKey(chatId)) { + return null; + } + var info = peerColorInfoMap.get(chatId); + if (info != null && (info.flags & 2) != 0) { + return info.emojiId; + } + return null; + } + + public Long getEmojiId(TLRPC.User user) { + if (user == null) return null; + return getEmojiId(user.id); + } + + public Long getEmojiId(TLRPC.Chat chat) { + if (chat == null) return null; + return getEmojiId(-chat.id); + } + + public Integer getProfileColorId(long chatId) { + if (!peerColorInfoMap.containsKey(chatId)) { + return null; + } + var info = peerColorInfoMap.get(chatId); + if (info != null && (info.flags & 4) != 0) { + return info.profileColorId; + } + return null; + } + + public Integer getProfileColorId(TLRPC.User user) { + return getProfileColorId(user.id); + } + + public Integer getProfileColorId(TLRPC.Chat chat) { + return getProfileColorId(-chat.id); + } + + public Long getProfileEmojiId(long chatId) { + if (!peerColorInfoMap.containsKey(chatId)) { + return null; + } + var info = peerColorInfoMap.get(chatId); + if (info != null && (info.flags & 8) != 0) { + return info.profileEmojiId; + } + return null; + } + + public Long getProfileEmojiId(TLRPC.User user) { + if (user == null) return null; + return getProfileEmojiId(user.id); + } + + public Long getProfileEmojiId(TLRPC.Chat chat) { + if (chat == null) return null; + return getEmojiId(-chat.id); + } + + public static class PeerColorInfo { + private int flags; + public long chatId; + public int version; + public int colorId; + public long emojiId; + public int profileColorId; + public long profileEmojiId; + + public PeerColorInfo(long chatId, int version) { + this.chatId = chatId; + this.version = version; + } + + public PeerColorInfo() { + } + + public void setValue(JSONObject obj) { + this.setColorId(obj); + this.setEmojiId(obj); + this.setProfileColorId(obj); + this.setProfileEmojiId(obj); + } + + public void setColorId(JSONObject obj) { + try { + this.colorId = obj.getInt("colorId"); + this.flags |= 1; + } catch (Exception ignored) { + } + } + + public void setEmojiId(JSONObject obj) { + try { + this.emojiId = obj.getLong("emojiId"); + this.flags |= 2; + } catch (Exception ignored) { + } + } + + public void setProfileColorId(JSONObject obj) { + try { + this.profileColorId = obj.getInt("profileColorId"); + this.flags |= 4; + } catch (Exception ignored) { + } + } + + public void setProfileEmojiId(JSONObject obj) { + try { + this.profileEmojiId = obj.getLong("profileEmojiId"); + this.flags |= 8; + } catch (Exception ignored) { + } + } + + public static PeerColorInfo deserialize(AbstractSerializedData stream) { + PeerColorInfo peerColorInfo = new PeerColorInfo(); + peerColorInfo.flags = stream.readInt32(false); + peerColorInfo.chatId = stream.readInt64(false); + peerColorInfo.version = stream.readInt32(false); + if ((peerColorInfo.flags & 1) != 0) { + peerColorInfo.colorId = stream.readInt32(false); + } + if ((peerColorInfo.flags & 2) != 0) { + peerColorInfo.emojiId = stream.readInt64(false); + } + if ((peerColorInfo.flags & 4) != 0) { + peerColorInfo.profileColorId = stream.readInt32(false); + } + if ((peerColorInfo.flags & 8) != 0) { + peerColorInfo.profileEmojiId = stream.readInt64(false); + } + return peerColorInfo; + } + + public void serializeToStream(AbstractSerializedData serializedData) { + serializedData.writeInt32(flags); + serializedData.writeInt64(chatId); + serializedData.writeInt32(version); + if ((flags & 1) != 0) { + serializedData.writeInt32(colorId); + } + if ((flags & 2) != 0) { + serializedData.writeInt64(emojiId); + } + if ((flags & 4) != 0) { + serializedData.writeInt32(profileColorId); + } + if ((flags & 8) != 0) { + serializedData.writeInt64(profileEmojiId); + } + } + } +} diff --git a/TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/helper/PeerColorHelper.kt b/TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/helper/LocalPeerColorHelper.kt similarity index 98% rename from TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/helper/PeerColorHelper.kt rename to TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/helper/LocalPeerColorHelper.kt index 44a549922a..5b73af4b75 100644 --- a/TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/helper/PeerColorHelper.kt +++ b/TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/helper/LocalPeerColorHelper.kt @@ -13,7 +13,7 @@ data class LocalQuoteColorData ( ) -object PeerColorHelper { +object LocalPeerColorHelper { var loaded: Boolean = false var data: LocalQuoteColorData? = null