-
Notifications
You must be signed in to change notification settings - Fork 117
Ignore reactions and the read status of the blocked users #359
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,6 +33,8 @@ | |
| import org.telegram.tgnet.Vector; | ||
| import org.telegram.ui.ActionBar.Theme; | ||
|
|
||
| import tw.nekomimi.nekogram.helpers.MessageHelper; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
|
|
@@ -142,14 +144,14 @@ protected void onAttachedToWindow() { | |
| for (Object obj : v.objects) { | ||
| if (obj instanceof Long) { | ||
| long l = (long) obj; | ||
| if (fromId != l) { | ||
| if (fromId != l && !shouldFilterBlockedPeer(l)) { | ||
| usersToRequest.add(l); | ||
| dates.add(0); | ||
| } | ||
| } else if (obj instanceof TLRPC.TL_readParticipantDate) { | ||
| long userId = ((TLRPC.TL_readParticipantDate) obj).user_id; | ||
| int date = ((TLRPC.TL_readParticipantDate) obj).date; | ||
| if (fromId != userId) { | ||
| if (fromId != userId && !shouldFilterBlockedPeer(userId)) { | ||
| usersToRequest.add(userId); | ||
| dates.add(date); | ||
| } | ||
|
|
@@ -235,7 +237,7 @@ private void loadReactions() { | |
| ConnectionsManager.getInstance(currentAccount).sendRequest(getList, (response, error) -> { | ||
| if (response instanceof TLRPC.TL_messages_messageReactionsList) { | ||
| TLRPC.TL_messages_messageReactionsList list = (TLRPC.TL_messages_messageReactionsList) response; | ||
| int c = list.count; | ||
| int c = Math.max(0, list.count - filterBlockedReactionPeers(list.reactions)); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reaction count is inaccurate — subtracts blocked peers from a 3-item sample, not the total.
Concrete example: message has 100 reactions including 10 from blocked users, sample contains 0 of them → Possible directions:
|
||
| int ic = list.users.size(); | ||
| LastSeenHelper.saveLastSeenFromPeerReactions(list.reactions, UserConfig.getInstance(currentAccount).getClientUserId()); | ||
| post(() -> { | ||
|
|
@@ -277,6 +279,9 @@ private void loadReactions() { | |
| iconView.animate().alpha(1f).start(); | ||
| } | ||
| for (TLRPC.User u : list.users) { | ||
| if (shouldFilterBlockedPeer(u.id)) { | ||
| continue; | ||
| } | ||
| if (message.messageOwner.from_id != null && u.id != message.messageOwner.from_id.user_id) { | ||
| boolean hasSame = false; | ||
| for (int i = 0; i < users.size(); i++) { | ||
|
|
@@ -291,6 +296,9 @@ private void loadReactions() { | |
| } | ||
| } | ||
| for (TLRPC.Chat u : list.chats) { | ||
| if (shouldFilterBlockedPeer(-u.id)) { | ||
| continue; | ||
| } | ||
| if (message.messageOwner.from_id != null && u.id != message.messageOwner.from_id.user_id) { | ||
| boolean hasSame = false; | ||
| for (int i = 0; i < users.size(); i++) { | ||
|
|
@@ -311,6 +319,30 @@ private void loadReactions() { | |
| }, ConnectionsManager.RequestFlagInvokeAfter); | ||
| } | ||
|
|
||
| private int filterBlockedReactionPeers(List<TLRPC.MessagePeerReaction> reactions) { | ||
| if (reactions == null || reactions.isEmpty()) { | ||
| return 0; | ||
| } | ||
| int removed = 0; | ||
| for (int i = reactions.size() - 1; i >= 0; i--) { | ||
| TLRPC.MessagePeerReaction reaction = reactions.get(i); | ||
| if (reaction == null || reaction.peer_id == null) { | ||
| continue; | ||
| } | ||
| long peerId = MessageObject.getPeerId(reaction.peer_id); | ||
| if (shouldFilterBlockedPeer(peerId)) { | ||
| reactions.remove(i); | ||
| removed++; | ||
| } | ||
| } | ||
| return removed; | ||
| } | ||
|
|
||
| private boolean shouldFilterBlockedPeer(long peerId) { | ||
| return peerId != 0 && message != null && message.isSupergroup() && | ||
| MessageHelper.getInstance(currentAccount).isBlockedOrFilteredPeer(peerId); | ||
| } | ||
|
|
||
| public List<UserSeen> getSeenUsers() { | ||
| return seenUsers; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,6 +31,8 @@ | |
| import org.telegram.ui.Cells.ReactedUserHolderView; | ||
| import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; | ||
|
|
||
| import tw.nekomimi.nekogram.helpers.MessageHelper; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Collections; | ||
| import java.util.Comparator; | ||
|
|
@@ -64,6 +66,7 @@ public class ReactedUsersListView extends FrameLayout { | |
| private OnHeightChangedListener onHeightChangedListener; | ||
| private OnProfileSelectedListener onProfileSelectedListener; | ||
| private OnCustomEmojiSelectedListener onCustomEmojiSelectedListener; | ||
| private OnCountChangedListener onCountChangedListener; | ||
| ArrayList<ReactionsLayoutInBubble.VisibleReaction> customReactionsEmoji = new ArrayList<>(); | ||
| ArrayList<TLRPC.InputStickerSet> customEmojiStickerSets = new ArrayList<>(); | ||
| MessageContainsEmojiButton messageContainsEmojiButton; | ||
|
|
@@ -198,6 +201,9 @@ public int getAdditionalHeight() { | |
| public ReactedUsersListView setSeenUsers(List<ReactedHeaderView.UserSeen> users) { | ||
| if (userReactions != null && !userReactions.isEmpty()) { | ||
| for (ReactedHeaderView.UserSeen p : users) { | ||
| if (shouldFilterBlockedPeer(p.dialogId)) { | ||
| continue; | ||
| } | ||
| TLObject user = p.user; | ||
| if (user != null && p.date > 0) { | ||
| for (int i = 0; i < userReactions.size(); ++i) { | ||
|
|
@@ -213,6 +219,9 @@ public ReactedUsersListView setSeenUsers(List<ReactedHeaderView.UserSeen> users) | |
| } | ||
| List<TLRPC.TL_messagePeerReaction> nr = new ArrayList<>(users.size()); | ||
| for (ReactedHeaderView.UserSeen p : users) { | ||
| if (shouldFilterBlockedPeer(p.dialogId)) { | ||
| continue; | ||
| } | ||
| ArrayList<TLRPC.MessagePeerReaction> userReactions = peerReactionMap.get(p.dialogId); | ||
| if (userReactions != null) { | ||
| continue; | ||
|
|
@@ -244,6 +253,11 @@ public ReactedUsersListView setSeenUsers(List<ReactedHeaderView.UserSeen> users) | |
| return this; | ||
| } | ||
|
|
||
| private boolean shouldFilterBlockedPeer(long peerId) { | ||
| return peerId != 0 && message != null && message.isSupergroup() && | ||
| MessageHelper.getInstance(currentAccount).isBlockedOrFilteredPeer(peerId); | ||
| } | ||
|
Comment on lines
+256
to
+259
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Inspect MessageHelper for existing reaction/blocked-peer filtering APIs
fd -t f 'MessageHelper.java' | xargs -I {} rg -nP -C2 '\b(isBlockedOrFilteredPeer|filterBlockedMessageReactions|shouldFilterBlockedPeer|filterBlockedReactionPeers)\b' {}
# Locate all current duplicates of these helpers across the codebase
rg -nP -C1 '\b(shouldFilterBlockedPeer|filterBlockedReactionPeers)\s*\(' --type=javaRepository: risin42/NagramX Length of output: 8095 Consider centralizing These helpers are duplicated near-verbatim across Suggested approach: // In MessageHelper
public boolean shouldFilterBlockedPeer(MessageObject message, long peerId) { ... }
public int filterBlockedReactionPeers(MessageObject message, List<TLRPC.MessagePeerReaction> reactions) { ... } |
||
|
|
||
| @Override | ||
| protected void onAttachedToWindow() { | ||
| super.onAttachedToWindow(); | ||
|
|
@@ -273,6 +287,10 @@ private void load() { | |
| TLRPC.TL_messages_messageReactionsList res = (TLRPC.TL_messages_messageReactionsList) response; | ||
| MessagesController.getInstance(currentAccount).putUsers(res.users, false); | ||
| MessagesController.getInstance(currentAccount).putChats(res.chats, false); | ||
| int filteredCount = Math.max(0, res.count - filterBlockedReactionPeers(res.reactions)); | ||
| if (onCountChangedListener != null) { | ||
| onCountChangedListener.onCountChanged(this, filteredCount); | ||
| } | ||
|
Comment on lines
+290
to
+293
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use cumulative blocked-removal when reporting filtered total.
Suggested fix@@
- private boolean showReactionPreview;
+ private boolean showReactionPreview;
+ private int filteredRemovedTotal;
@@
private void load() {
isLoading = true;
+ if (offset == null) {
+ filteredRemovedTotal = 0;
+ }
@@
- int filteredCount = Math.max(0, res.count - filterBlockedReactionPeers(res.reactions));
+ filteredRemovedTotal += filterBlockedReactionPeers(res.reactions);
+ int filteredCount = Math.max(0, res.count - filteredRemovedTotal);
if (onCountChangedListener != null) {
onCountChangedListener.onCountChanged(this, filteredCount);
} |
||
| LastSeenHelper.saveLastSeenFromPeerReactions(res.reactions, UserConfig.getInstance(currentAccount).getClientUserId()); | ||
|
|
||
| HashSet<ReactionsLayoutInBubble.VisibleReaction> visibleCustomEmojiReactions = new HashSet<>(); | ||
|
|
@@ -340,6 +358,26 @@ public void onAnimationEnd(Animator animation) { | |
| }, ConnectionsManager.RequestFlagInvokeAfter); | ||
| } | ||
|
|
||
| private int filterBlockedReactionPeers(List<TLRPC.MessagePeerReaction> reactions) { | ||
| if (reactions == null || reactions.isEmpty() || message == null || !message.isSupergroup()) { | ||
| return 0; | ||
| } | ||
| MessageHelper messageHelper = MessageHelper.getInstance(currentAccount); | ||
| int removed = 0; | ||
| for (int i = reactions.size() - 1; i >= 0; i--) { | ||
| TLRPC.MessagePeerReaction reaction = reactions.get(i); | ||
| if (reaction == null || reaction.peer_id == null) { | ||
| continue; | ||
| } | ||
| long peerId = MessageObject.getPeerId(reaction.peer_id); | ||
| if (peerId != 0 && messageHelper.isBlockedOrFilteredPeer(peerId)) { | ||
| reactions.remove(i); | ||
| removed++; | ||
| } | ||
| } | ||
| return removed; | ||
| } | ||
|
|
||
| private void updateCustomReactionsButton() { | ||
| customEmojiStickerSets.clear(); | ||
| ArrayList<TLRPC.InputStickerSet> sets = new ArrayList<>(); | ||
|
|
@@ -393,10 +431,19 @@ public ReactedUsersListView setOnHeightChangedListener(OnHeightChangedListener o | |
| return this; | ||
| } | ||
|
|
||
| public ReactedUsersListView setOnCountChangedListener(OnCountChangedListener onCountChangedListener) { | ||
| this.onCountChangedListener = onCountChangedListener; | ||
| return this; | ||
| } | ||
|
|
||
| public interface OnHeightChangedListener { | ||
| void onHeightChanged(ReactedUsersListView view, int newHeight); | ||
| } | ||
|
|
||
| public interface OnCountChangedListener { | ||
| void onCountChanged(ReactedUsersListView view, int count); | ||
| } | ||
|
|
||
| public interface OnProfileSelectedListener { | ||
| void onProfileSelected(ReactedUsersListView view, long userId, TLRPC.MessagePeerReaction messagePeerReaction); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1042,15 +1042,78 @@ public boolean isBlockedUser(long senderId) { | |
| return getMessagesController().blockePeers.indexOfKey(senderId) >= 0 || AyuFilter.isCustomFilteredPeer(senderId); | ||
| } | ||
|
|
||
| public boolean isBlockedOrFilteredPeer(long peerId) { | ||
| return isBlockedUser(peerId) || AyuFilter.isBlockedChannel(peerId); | ||
| } | ||
|
|
||
| public boolean isBlockedOrFiltered(TLRPC.Message message) { | ||
| if (message == null) { | ||
| return false; | ||
| } | ||
| long fromId = MessageObject.getFromChatId(message); | ||
| boolean blocked = isBlockedUser(fromId) || AyuFilter.isBlockedChannel(fromId); | ||
| boolean blocked = isBlockedOrFilteredPeer(fromId); | ||
| return blocked || AyuFilter.isFiltered(new MessageObject(currentAccount, message, false, false), null); | ||
| } | ||
|
|
||
| public boolean filterBlockedMessageReactions(TLRPC.TL_messageReactions reactions) { | ||
| if (reactions == null || !NekoConfig.ignoreBlocked.Bool()) { | ||
| return false; | ||
| } | ||
| boolean changed = false; | ||
| if (reactions.recent_reactions != null) { | ||
| for (int i = reactions.recent_reactions.size() - 1; i >= 0; i--) { | ||
| TLRPC.MessagePeerReaction reaction = reactions.recent_reactions.get(i); | ||
| if (reaction == null || reaction.peer_id == null) { | ||
| continue; | ||
| } | ||
| long peerId = MessageObject.getPeerId(reaction.peer_id); | ||
| if (peerId != 0 && isBlockedOrFilteredPeer(peerId)) { | ||
| reactions.recent_reactions.remove(i); | ||
| decrementReactionCount(reactions, reaction.reaction); | ||
| changed = true; | ||
| } | ||
| } | ||
| } | ||
| if (reactions.top_reactors != null) { | ||
| for (int i = reactions.top_reactors.size() - 1; i >= 0; i--) { | ||
| TLRPC.MessageReactor reactor = reactions.top_reactors.get(i); | ||
| if (reactor == null || reactor.peer_id == null) { | ||
| continue; | ||
| } | ||
| long peerId = MessageObject.getPeerId(reactor.peer_id); | ||
| if (peerId != 0 && isBlockedOrFilteredPeer(peerId)) { | ||
| reactions.top_reactors.remove(i); | ||
| changed = true; | ||
| } | ||
| } | ||
| } | ||
| return changed; | ||
| } | ||
|
Comment on lines
+1058
to
+1091
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Search for TLRPC.MessageReactor and TLRPC.TL_messageReactions definitions
ast-grep --pattern 'class $_ {
$$$
top_reactors
$$$
}'
# Search for usage patterns where top_reactors and recent_reactions are accessed together
rg -nP -A5 -B5 'top_reactors.*recent_reactions|recent_reactions.*top_reactors'
# Look for comments or documentation about the relationship
rg -nP 'top_reactors' --type=java -C3Repository: risin42/NagramX Length of output: 14907 🏁 Script executed: #!/bin/bash
# Find MessageReactor class definition
rg -n "class MessageReactor|class TL_messageReactor" --type=java -A 10
# Find decrementReactionCount method
rg -n "decrementReactionCount" --type=java -A 15
# Check if MessageReactor has a reaction field
rg -n "MessageReactor" --type=java | grep -E "reaction|count" | head -20Repository: risin42/NagramX Length of output: 8335 🏁 Script executed: #!/bin/bash
# Find MessagePeerReaction class definition to compare
rg -n "class MessagePeerReaction" --type=java -A 10
# Check how MessageReactor relates to reactions
rg -n "top_reactors" --type=java -B5 -A5 | grep -E "reaction|count" | head -30Repository: risin42/NagramX Length of output: 5648 Inconsistent reaction count handling when filtering When removing from The root cause is that |
||
|
|
||
| private static void decrementReactionCount(TLRPC.TL_messageReactions reactions, TLRPC.Reaction removedReaction) { | ||
| if (removedReaction == null || reactions.results == null) { | ||
| return; | ||
| } | ||
| for (int i = reactions.results.size() - 1; i >= 0; i--) { | ||
| TLRPC.ReactionCount count = reactions.results.get(i); | ||
| if (count == null || !sameReaction(count.reaction, removedReaction)) { | ||
| continue; | ||
| } | ||
| count.count--; | ||
| if (count.count <= 0) { | ||
| reactions.results.remove(i); | ||
| } | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| private static boolean sameReaction(TLRPC.Reaction first, TLRPC.Reaction second) { | ||
| if (first == null || second == null) { | ||
| return false; | ||
| } | ||
| return first.equals(second) || first instanceof TLRPC.TL_reactionPaid && second instanceof TLRPC.TL_reactionPaid; | ||
| } | ||
|
|
||
| public static void copyVideoFrameToClipboard(File videoFile, long positionMs, View bulletinContainer, Theme.ResourcesProvider resourcesProvider, Runnable fallbackAction) { | ||
| Utilities.globalQueue.postRunnable(() -> { | ||
| Bitmap bitmap = null; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: risin42/NagramX
Length of output: 2984
🏁 Script executed:
Repository: risin42/NagramX
Length of output: 3310
🏁 Script executed:
Repository: risin42/NagramX
Length of output: 6612
🏁 Script executed:
Repository: risin42/NagramX
Length of output: 8775
Capture of view reference in asynchronously-firing listener creates stale reference risk.
The
tabHolderis captured fromtabsView.getChildAt(position)before the listener is set, but the listener fires asynchronously (via network response in ReactedUsersListView lines 284-292). Combined with view caching in the ViewPager adapter:tabHolderreference from creation timeSafer approach: Look up the view inside the lambda when the callback actually fires, rather than capturing the reference beforehand.
Suggested fix