2022-11-05 13:34:47 +01:00
package org.telegram.messenger ;
import android.content.SharedPreferences ;
import android.text.TextPaint ;
import android.text.TextUtils ;
import android.util.SparseArray ;
import androidx.collection.LongSparseArray ;
import org.telegram.SQLite.SQLiteCursor ;
import org.telegram.messenger.support.LongSparseIntArray ;
import org.telegram.tgnet.ConnectionsManager ;
import org.telegram.tgnet.NativeByteBuffer ;
import org.telegram.tgnet.RequestDelegate ;
import org.telegram.tgnet.TLObject ;
import org.telegram.tgnet.TLRPC ;
2022-11-12 09:41:35 +01:00
import org.telegram.ui.ActionBar.AlertDialog ;
import org.telegram.ui.ActionBar.BaseFragment ;
2022-11-05 13:34:47 +01:00
import org.telegram.ui.Components.Forum.ForumUtilities ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.Collections ;
import java.util.Comparator ;
import java.util.HashMap ;
import java.util.HashSet ;
import java.util.List ;
import java.util.Locale ;
public class TopicsController extends BaseController {
public static final int TOPIC_FLAG_TITLE = 1 ;
public static final int TOPIC_FLAG_ICON = 2 ;
public static final int TOPIC_FLAG_PIN = 4 ;
public static final int TOPIC_FLAG_CLOSE = 8 ;
private static final int MAX_PRELOAD_COUNT = 20 ;
public static final int LOAD_TYPE_PRELOAD = 0 ;
public static final int LOAD_TYPE_LOAD_NEXT = 1 ;
public static final int LOAD_TYPE_LOAD_UNKNOWN = 2 ;
LongSparseArray < ArrayList < TLRPC . TL_forumTopic > > topicsByChatId = new LongSparseArray < > ( ) ;
LongSparseArray < LongSparseArray < TLRPC . TL_forumTopic > > topicsMapByChatId = new LongSparseArray < > ( ) ;
LongSparseIntArray topicsIsLoading = new LongSparseIntArray ( ) ;
LongSparseIntArray endIsReached = new LongSparseIntArray ( ) ;
LongSparseArray < TLRPC . TL_forumTopic > topicsByTopMsgId = new LongSparseArray < > ( ) ;
LongSparseIntArray currentOpenTopicsCounter = new LongSparseIntArray ( ) ;
LongSparseIntArray openedTopicsBuChatId = new LongSparseIntArray ( ) ;
public TopicsController ( int num ) {
super ( num ) ;
}
public void preloadTopics ( long chatId ) {
loadTopics ( chatId , true , LOAD_TYPE_PRELOAD ) ;
}
public void loadTopics ( long chatId ) {
loadTopics ( chatId , false , LOAD_TYPE_LOAD_NEXT ) ;
}
2022-11-12 09:41:35 +01:00
public void loadTopics ( long chatId , boolean fromCache , int loadType ) {
2022-11-05 13:34:47 +01:00
if ( topicsIsLoading . get ( chatId , 0 ) ! = 0 ) {
return ;
}
if ( BuildVars . DEBUG_PRIVATE_VERSION ) {
FileLog . d ( " load topics " + chatId + " fromCache= " + fromCache + " loadType= " + loadType ) ;
}
2022-11-20 22:12:39 +01:00
topicsIsLoading . put ( chatId , 1 ) ;
2022-11-05 13:34:47 +01:00
if ( fromCache ) {
getMessagesStorage ( ) . loadTopics ( - chatId , topics - > {
AndroidUtilities . runOnUIThread ( ( ) - > {
if ( BuildVars . DEBUG_PRIVATE_VERSION ) {
FileLog . d ( " loaded from cache " + chatId + " topics_count= " + ( topics = = null ? 0 : topics . size ( ) ) ) ;
}
topicsIsLoading . put ( chatId , 0 ) ;
processTopics ( chatId , topics , null , fromCache , loadType , - 1 ) ;
2022-11-12 09:41:35 +01:00
if ( ! endIsReached ( chatId ) ) {
endIsReached . put ( chatId , getUserConfig ( ) . getPreferences ( ) . getBoolean ( " topics_end_reached_ " + chatId , false ) ? 1 : 0 ) ;
}
2022-11-05 13:34:47 +01:00
} ) ;
} ) ;
return ;
}
TLRPC . TL_channels_getForumTopics getForumTopics = new TLRPC . TL_channels_getForumTopics ( ) ;
getForumTopics . channel = getMessagesController ( ) . getInputChannel ( chatId ) ;
if ( loadType = = LOAD_TYPE_PRELOAD ) {
getForumTopics . limit = MAX_PRELOAD_COUNT ;
} else if ( loadType = = LOAD_TYPE_LOAD_NEXT ) {
getForumTopics . limit = 100 ;
TopicsLoadOffset loadOffsets = getLoadOffset ( chatId ) ;
getForumTopics . offset_date = loadOffsets . lastMessageDate ;
getForumTopics . offset_id = loadOffsets . lastMessageId ;
getForumTopics . offset_topic = loadOffsets . lastTopicId ;
if ( BuildVars . DEBUG_PRIVATE_VERSION ) {
FileLog . d ( " offset_date= " + loadOffsets . lastMessageDate + " offset_id= " + loadOffsets . lastMessageId + " offset_topic= " + loadOffsets . lastTopicId ) ;
}
}
getConnectionsManager ( ) . sendRequest ( getForumTopics , ( response , error ) - > {
if ( response ! = null ) {
SparseArray < TLRPC . Message > messagesMap = new SparseArray < > ( ) ;
TLRPC . TL_messages_forumTopics topics = ( TLRPC . TL_messages_forumTopics ) response ;
for ( int i = 0 ; i < topics . messages . size ( ) ; i + + ) {
messagesMap . put ( topics . messages . get ( i ) . id , topics . messages . get ( i ) ) ;
}
AndroidUtilities . runOnUIThread ( ( ) - > {
2022-11-20 22:12:39 +01:00
getMessagesStorage ( ) . putUsersAndChats ( ( ( TLRPC . TL_messages_forumTopics ) response ) . users , ( ( TLRPC . TL_messages_forumTopics ) response ) . chats , true , false ) ;
2022-11-05 13:34:47 +01:00
getMessagesController ( ) . putUsers ( ( ( TLRPC . TL_messages_forumTopics ) response ) . users , false ) ;
getMessagesController ( ) . putChats ( ( ( TLRPC . TL_messages_forumTopics ) response ) . chats , false ) ;
topicsIsLoading . put ( chatId , 0 ) ;
processTopics ( chatId , topics . topics , messagesMap , false , loadType , ( ( TLRPC . TL_messages_forumTopics ) response ) . count ) ;
getMessagesStorage ( ) . putMessages ( topics . messages , false , true , false , 0 , false , 0 ) ;
getMessagesStorage ( ) . saveTopics ( - chatId , topicsByChatId . get ( chatId ) , true , true ) ;
if ( ! topics . topics . isEmpty ( ) & & loadType = = LOAD_TYPE_LOAD_NEXT ) {
TLRPC . TL_forumTopic lastTopic = topics . topics . get ( topics . topics . size ( ) - 1 ) ;
TLRPC . Message lastTopicMessage = messagesMap . get ( lastTopic . top_message ) ;
2022-11-12 09:41:35 +01:00
saveLoadOffset ( chatId , lastTopic . top_message , lastTopicMessage = = null ? 0 : lastTopicMessage . date , lastTopic . id ) ;
2022-11-05 13:34:47 +01:00
} else if ( getTopics ( chatId ) = = null | | getTopics ( chatId ) . size ( ) < topics . count ) {
clearLoadingOffset ( chatId ) ;
loadTopics ( chatId ) ;
}
} ) ;
} else {
AndroidUtilities . runOnUIThread ( ( ) - > {
topicsIsLoading . put ( chatId , 0 ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . topicsDidLoaded , chatId , false ) ;
} ) ;
}
} ) ;
}
public void processTopics ( long chatId , ArrayList < TLRPC . TL_forumTopic > newTopics , SparseArray < TLRPC . Message > messagesMap , boolean fromCache , int loadType , int totalCount ) {
ArrayList < TLRPC . TL_forumTopic > topics = topicsByChatId . get ( chatId ) ;
ArrayList < TLRPC . TL_forumTopic > topicsToReload = null ;
LongSparseArray < TLRPC . TL_forumTopic > topicsMap = topicsMapByChatId . get ( chatId ) ;
if ( topics = = null ) {
topics = new ArrayList < > ( ) ;
topicsByChatId . put ( chatId , topics ) ;
}
if ( topicsMap = = null ) {
topicsMap = new LongSparseArray < > ( ) ;
topicsMapByChatId . put ( chatId , topicsMap ) ;
}
2022-11-12 09:41:35 +01:00
2022-11-05 13:34:47 +01:00
boolean changed = false ;
if ( newTopics ! = null ) {
for ( int i = 0 ; i < newTopics . size ( ) ; i + + ) {
TLRPC . TL_forumTopic newTopic = newTopics . get ( i ) ;
2022-11-12 09:41:35 +01:00
if ( newTopic instanceof TLRPC . TL_forumTopicDeleted ) {
continue ;
}
2022-11-05 13:34:47 +01:00
if ( ! topicsMap . containsKey ( newTopic . id ) ) {
if ( messagesMap ! = null ) {
newTopic . topMessage = messagesMap . get ( newTopic . top_message ) ;
newTopic . topicStartMessage = messagesMap . get ( newTopic . id ) ;
}
2022-11-12 09:41:35 +01:00
if ( newTopic . topMessage = = null & & ! newTopic . isShort ) {
2022-11-05 13:34:47 +01:00
if ( topicsToReload = = null ) {
topicsToReload = new ArrayList < > ( ) ;
}
topicsToReload . add ( newTopic ) ;
}
2022-11-20 22:12:39 +01:00
if ( newTopic . topicStartMessage = = null ) {
newTopic . topicStartMessage = new TLRPC . TL_message ( ) ;
newTopic . topicStartMessage . message = " " ;
newTopic . topicStartMessage . id = newTopic . id ;
newTopic . topicStartMessage . peer_id = getMessagesController ( ) . getPeer ( - chatId ) ;
newTopic . topicStartMessage . action = new TLRPC . TL_messageActionTopicCreate ( ) ;
newTopic . topicStartMessage . action . title = newTopic . title ;
}
topics . add ( newTopic ) ;
topicsMap . put ( newTopic . id , newTopic ) ;
topicsByTopMsgId . put ( messageHash ( newTopic . top_message , chatId ) , newTopic ) ;
changed = true ;
2022-11-05 13:34:47 +01:00
}
}
}
2022-11-12 09:41:35 +01:00
int pinnedTopics = 0 ;
for ( int i = 0 ; i < topics . size ( ) ; + + i ) {
TLRPC . TL_forumTopic topic = topics . get ( i ) ;
if ( topic ! = null & & topic . pinned ) {
int newPinnedOrder = pinnedTopics + + ;
if ( topic . pinnedOrder ! = newPinnedOrder ) {
topic . pinnedOrder = newPinnedOrder ;
changed = true ;
}
}
}
2022-11-20 22:12:39 +01:00
2022-11-05 13:34:47 +01:00
2022-11-12 09:41:35 +01:00
if ( topicsToReload ! = null & & loadType ! = LOAD_TYPE_LOAD_UNKNOWN ) {
2022-11-05 13:34:47 +01:00
reloadTopics ( chatId , topicsToReload ) ;
} else if ( loadType = = LOAD_TYPE_LOAD_NEXT & & topics . size ( ) > = totalCount & & totalCount > = 0 ) {
endIsReached . put ( chatId , 1 ) ;
2022-11-12 09:41:35 +01:00
getUserConfig ( ) . getPreferences ( ) . edit ( ) . putBoolean ( " topics_end_reached_ " + chatId , true ) . apply ( ) ;
2022-11-05 13:34:47 +01:00
}
2022-11-20 22:12:39 +01:00
if ( changed ) {
sortTopics ( chatId ) ;
}
2022-11-05 13:34:47 +01:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . topicsDidLoaded , chatId , true ) ;
if ( ( loadType = = LOAD_TYPE_PRELOAD | | ( loadType = = LOAD_TYPE_PRELOAD & & ! fromCache ) ) & & fromCache & & topicsByChatId . get ( chatId ) . isEmpty ( ) ) {
2022-11-12 09:41:35 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > {
loadTopics ( chatId , false , LOAD_TYPE_PRELOAD ) ;
} ) ;
2022-11-05 13:34:47 +01:00
}
}
private long messageHash ( int messageId , long chatId ) {
return chatId + ( ( long ) messageId < < 12 ) ;
}
public ArrayList < TLRPC . TL_forumTopic > getTopics ( long chatId ) {
return topicsByChatId . get ( chatId ) ;
}
private void sortTopics ( long chatId ) {
sortTopics ( chatId , true ) ;
}
2022-11-12 09:41:35 +01:00
public void sortTopics ( long chatId , boolean notify ) {
2022-11-05 13:34:47 +01:00
ArrayList < TLRPC . TL_forumTopic > topics = topicsByChatId . get ( chatId ) ;
if ( topics ! = null ) {
if ( openedTopicsBuChatId . get ( chatId , 0 ) > 0 ) {
2022-11-12 09:41:35 +01:00
Collections . sort ( topics , Comparator . comparingInt ( o - > o . topMessage = = null ? Integer . MAX_VALUE : - ( o . pinned ? Integer . MAX_VALUE - o . pinnedOrder : o . topMessage . date ) ) ) ;
2022-11-05 13:34:47 +01:00
}
if ( notify ) {
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . topicsDidLoaded , chatId , true ) ;
}
}
}
public void updateTopicsWithDeletedMessages ( long dialogId , ArrayList < Integer > messages ) {
if ( dialogId > 0 ) {
return ;
}
long chatId = - dialogId ;
AndroidUtilities . runOnUIThread ( ( ) - > {
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
ArrayList < TLRPC . TL_forumTopic > topicsToUpdate = null ;
try {
SQLiteCursor cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT topic_id, top_message FROM topics WHERE did = %d AND top_message IN (%s) " , dialogId , TextUtils . join ( " , " , messages ) ) ) ;
while ( cursor . next ( ) ) {
if ( topicsToUpdate = = null ) {
topicsToUpdate = new ArrayList < > ( ) ;
}
TLRPC . TL_forumTopic topic = new TLRPC . TL_forumTopic ( ) ;
topic . id = cursor . intValue ( 0 ) ;
topic . top_message = cursor . intValue ( 1 ) ;
topic . from_id = getMessagesController ( ) . getPeer ( getUserConfig ( ) . clientUserId ) ;
topic . notify_settings = new TLRPC . TL_peerNotifySettings ( ) ;
topicsToUpdate . add ( topic ) ;
}
cursor . dispose ( ) ;
if ( topicsToUpdate ! = null ) {
for ( int i = 0 ; i < topicsToUpdate . size ( ) ; i + + ) {
TLRPC . TL_forumTopic topic = topicsToUpdate . get ( i ) ;
cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT mid, data FROM messages_topics WHERE uid = %d AND topic_id = %d ORDER BY mid DESC LIMIT 1 " , dialogId , topic . id ) ) ;
if ( cursor . next ( ) ) {
NativeByteBuffer data = cursor . byteBufferValue ( 1 ) ;
if ( data ! = null ) {
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
message . readAttachPath ( data , getUserConfig ( ) . clientUserId ) ;
data . reuse ( ) ;
topicsByTopMsgId . remove ( messageHash ( topic . top_message , chatId ) ) ;
topic . top_message = message . id ;
topic . topMessage = message ;
topic . groupedMessages = null ;
topicsByTopMsgId . put ( messageHash ( topic . top_message , chatId ) , topic ) ;
}
}
cursor . dispose ( ) ;
}
for ( int i = 0 ; i < topicsToUpdate . size ( ) ; i + + ) {
getMessagesStorage ( ) . getDatabase ( ) . executeFast ( String . format ( Locale . US , " UPDATE topics SET top_message = %d WHERE did = %d AND topic_id = %d " , topicsToUpdate . get ( i ) . top_message , dialogId , topicsToUpdate . get ( i ) . id ) ) . stepThis ( ) . dispose ( ) ;
}
}
} catch ( Exception e ) {
e . printStackTrace ( ) ;
}
ArrayList < TLRPC . TL_forumTopic > finalTopicsToUpdate = topicsToUpdate ;
getMessagesStorage ( ) . loadGroupedMessagesForTopics ( dialogId , finalTopicsToUpdate ) ;
if ( finalTopicsToUpdate ! = null ) {
AndroidUtilities . runOnUIThread ( ( ) - > {
boolean changed = false ;
ArrayList < TLRPC . TL_forumTopic > topicsToReload = null ;
for ( int i = 0 ; i < finalTopicsToUpdate . size ( ) ; i + + ) {
TLRPC . TL_forumTopic fromUpdate = finalTopicsToUpdate . get ( i ) ;
LongSparseArray < TLRPC . TL_forumTopic > map = topicsMapByChatId . get ( chatId ) ;
TLRPC . TL_forumTopic toUpdate ;
if ( map ! = null ) {
toUpdate = map . get ( fromUpdate . id ) ;
if ( toUpdate ! = null & & fromUpdate . top_message ! = - 1 & & fromUpdate . topMessage ! = null ) {
topicsByTopMsgId . remove ( messageHash ( toUpdate . top_message , chatId ) ) ;
toUpdate . top_message = fromUpdate . topMessage . id ;
toUpdate . topMessage = fromUpdate . topMessage ;
toUpdate . groupedMessages = fromUpdate . groupedMessages ;
topicsByTopMsgId . put ( messageHash ( toUpdate . top_message , chatId ) , toUpdate ) ;
changed = true ;
} else if ( fromUpdate . top_message = = - 1 | | fromUpdate . topMessage = = null ) {
if ( topicsToReload = = null ) {
topicsToReload = new ArrayList < > ( ) ;
}
topicsToReload . add ( fromUpdate ) ;
}
}
}
if ( changed ) {
sortTopics ( chatId ) ;
}
if ( topicsToReload ! = null ) {
reloadTopics ( chatId , topicsToReload ) ;
}
} ) ;
}
} ) ;
} ) ;
}
private void reloadTopics ( long chatId , ArrayList < TLRPC . TL_forumTopic > topicsToReload ) {
TLRPC . TL_channels_getForumTopicsByID req = new TLRPC . TL_channels_getForumTopicsByID ( ) ;
for ( int i = 0 ; i < topicsToReload . size ( ) ; i + + ) {
req . topics . add ( topicsToReload . get ( i ) . id ) ;
}
req . channel = getMessagesController ( ) . getInputChannel ( chatId ) ;
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > AndroidUtilities . runOnUIThread ( ( ) - > {
if ( response ! = null ) {
SparseArray < TLRPC . Message > messagesMap = new SparseArray < > ( ) ;
TLRPC . TL_messages_forumTopics topics = ( TLRPC . TL_messages_forumTopics ) response ;
for ( int i = 0 ; i < topics . messages . size ( ) ; i + + ) {
messagesMap . put ( topics . messages . get ( i ) . id , topics . messages . get ( i ) ) ;
}
AndroidUtilities . runOnUIThread ( ( ) - > {
getMessagesController ( ) . putUsers ( ( ( TLRPC . TL_messages_forumTopics ) response ) . users , false ) ;
getMessagesController ( ) . putChats ( ( ( TLRPC . TL_messages_forumTopics ) response ) . chats , false ) ;
processTopics ( chatId , topics . topics , messagesMap , false , LOAD_TYPE_LOAD_UNKNOWN , - 1 ) ;
getMessagesStorage ( ) . putMessages ( topics . messages , false , true , false , 0 , false , 0 ) ;
getMessagesStorage ( ) . saveTopics ( - chatId , topicsByChatId . get ( chatId ) , true , true ) ;
} ) ;
}
} ) ) ;
}
2022-11-20 22:12:39 +01:00
public void updateMaxReadId ( long chatId , int topicId , int readMaxId , int unreadCount , int mentionsUnread ) {
2022-11-05 13:34:47 +01:00
TLRPC . TL_forumTopic topic = findTopic ( chatId , topicId ) ;
if ( topic ! = null ) {
topic . read_inbox_max_id = readMaxId ;
topic . unread_count = unreadCount ;
2022-11-20 22:12:39 +01:00
if ( mentionsUnread > = 0 ) {
topic . unread_mentions_count = mentionsUnread ;
}
2022-11-05 13:34:47 +01:00
sortTopics ( chatId ) ;
}
}
public TLRPC . TL_forumTopic findTopic ( long chatId , int topicId ) {
LongSparseArray < TLRPC . TL_forumTopic > topicsMap = topicsMapByChatId . get ( chatId ) ;
if ( topicsMap ! = null ) {
return topicsMap . get ( topicId ) ;
}
return null ;
}
public String getTopicName ( TLRPC . Chat chat , MessageObject message ) {
if ( message . messageOwner . reply_to = = null ) {
return null ;
}
int topicId = message . messageOwner . reply_to . reply_to_top_id ;
if ( topicId = = 0 ) {
topicId = message . messageOwner . reply_to . reply_to_msg_id ;
}
if ( topicId ! = 0 ) {
TLRPC . TL_forumTopic topic = findTopic ( chat . id , topicId ) ;
if ( topic ! = null ) {
return topic . title ;
}
}
return " " ;
}
public CharSequence getTopicIconName ( TLRPC . Chat chat , MessageObject message , TextPaint paint ) {
if ( message . messageOwner . reply_to = = null ) {
return null ;
}
int topicId = message . messageOwner . reply_to . reply_to_top_id ;
if ( topicId = = 0 ) {
topicId = message . messageOwner . reply_to . reply_to_msg_id ;
}
if ( topicId ! = 0 ) {
TLRPC . TL_forumTopic topic = findTopic ( chat . id , topicId ) ;
if ( topic ! = null ) {
return ForumUtilities . getTopicSpannedName ( topic , paint ) ;
}
}
return null ;
}
private final static int [ ] countsTmp = new int [ 4 ] ;
public int [ ] getForumUnreadCount ( long chatId ) {
ArrayList < TLRPC . TL_forumTopic > topics = topicsByChatId . get ( chatId ) ;
Arrays . fill ( countsTmp , 0 ) ;
if ( topics ! = null ) {
for ( int i = 0 ; i < topics . size ( ) ; i + + ) {
TLRPC . TL_forumTopic topic = topics . get ( i ) ;
countsTmp [ 0 ] + = topic . unread_count > 0 ? 1 : 0 ;
countsTmp [ 1 ] + = topic . unread_mentions_count > 0 ? 1 : 0 ;
countsTmp [ 2 ] + = topic . unread_reactions_count > 0 ? 1 : 0 ;
if ( ! getMessagesController ( ) . isDialogMuted ( - chatId , topic . id ) ) {
countsTmp [ 3 ] + = topic . unread_count ;
}
}
}
return countsTmp ;
}
public void onTopicCreated ( long dialogId , TLRPC . TL_forumTopic forumTopic , boolean saveInDatabase ) {
LongSparseArray < TLRPC . TL_forumTopic > map = topicsMapByChatId . get ( - dialogId ) ;
if ( findTopic ( - dialogId , forumTopic . id ) ! = null ) {
return ;
}
if ( map = = null ) {
map = new LongSparseArray < > ( ) ;
topicsMapByChatId . put ( - dialogId , map ) ;
}
ArrayList < TLRPC . TL_forumTopic > list = topicsByChatId . get ( - dialogId ) ;
if ( list = = null ) {
list = new ArrayList < > ( ) ;
topicsByChatId . put ( - dialogId , list ) ;
}
map . put ( forumTopic . id , forumTopic ) ;
list . add ( forumTopic ) ;
if ( saveInDatabase ) {
getMessagesStorage ( ) . saveTopics ( dialogId , Collections . singletonList ( forumTopic ) , false , true ) ;
}
sortTopics ( - dialogId , true ) ;
}
public void onTopicEdited ( long dialogId , TLRPC . TL_forumTopic forumTopic ) {
getMessagesStorage ( ) . updateTopicData ( dialogId , forumTopic , TOPIC_FLAG_ICON + TOPIC_FLAG_TITLE ) ;
sortTopics ( - dialogId ) ;
}
public void deleteTopics ( long chatId , ArrayList < Integer > topicIds ) {
ArrayList < TLRPC . TL_forumTopic > topicsArray = topicsByChatId . get ( chatId ) ;
LongSparseArray < TLRPC . TL_forumTopic > topicsMap = topicsMapByChatId . get ( chatId ) ;
if ( topicsMap ! = null & & topicsArray ! = null ) {
for ( int i = 0 ; i < topicIds . size ( ) ; i + + ) {
int topicId = topicIds . get ( i ) ;
TLRPC . TL_forumTopic topic = topicsMap . get ( topicId ) ;
topicsMap . remove ( topicId ) ;
if ( topic ! = null ) {
topicsByTopMsgId . remove ( messageHash ( topic . top_message , chatId ) ) ;
topicsArray . remove ( topic ) ;
}
}
sortTopics ( chatId ) ;
}
for ( int i = 0 ; i < topicIds . size ( ) ; i + + ) {
deleteTopic ( chatId , topicIds . get ( i ) , 0 ) ;
}
}
private void deleteTopic ( long chatId , int topicId , int offset ) {
TLRPC . TL_channels_deleteTopicHistory deleteTopicHistory = new TLRPC . TL_channels_deleteTopicHistory ( ) ;
deleteTopicHistory . channel = getMessagesController ( ) . getInputChannel ( chatId ) ;
deleteTopicHistory . top_msg_id = topicId ;
if ( offset = = 0 ) {
getMessagesStorage ( ) . removeTopic ( - chatId , topicId ) ;
}
ConnectionsManager . getInstance ( currentAccount ) . sendRequest ( deleteTopicHistory , new RequestDelegate ( ) {
@Override
public void run ( TLObject response , TLRPC . TL_error error ) {
if ( error = = null ) {
TLRPC . TL_messages_affectedHistory res = ( TLRPC . TL_messages_affectedHistory ) response ;
getMessagesController ( ) . processNewChannelDifferenceParams ( res . pts , res . pts_count , chatId ) ;
if ( res . offset > 0 ) {
deleteTopic ( chatId , topicId , res . offset ) ;
}
}
}
} ) ;
}
public void toggleCloseTopic ( long chatId , int topicId , boolean close ) {
TLRPC . TL_channels_editForumTopic req = new TLRPC . TL_channels_editForumTopic ( ) ;
req . channel = getMessagesController ( ) . getInputChannel ( chatId ) ;
req . topic_id = topicId ;
req . flags | = 4 ;
req . closed = close ;
LongSparseArray < TLRPC . TL_forumTopic > topicsMap = topicsMapByChatId . get ( chatId ) ;
if ( topicsMap ! = null ) {
TLRPC . TL_forumTopic topic = topicsMap . get ( topicId ) ;
if ( topic ! = null ) {
topic . closed = close ;
getMessagesStorage ( ) . updateTopicData ( - chatId , topic , TOPIC_FLAG_CLOSE ) ;
}
}
ConnectionsManager . getInstance ( currentAccount ) . sendRequest ( req , new RequestDelegate ( ) {
@Override
public void run ( TLObject response , TLRPC . TL_error error ) {
if ( error = = null ) {
}
}
} ) ;
}
2022-11-12 09:41:35 +01:00
public ArrayList < Integer > getCurrentPinnedOrder ( long chatId ) {
ArrayList < TLRPC . TL_forumTopic > topics = getTopics ( chatId ) ;
ArrayList < Integer > newOrder = new ArrayList < > ( ) ;
if ( topics ! = null ) {
for ( int i = 0 ; i < topics . size ( ) ; + + i ) {
TLRPC . TL_forumTopic topic = topics . get ( i ) ;
if ( topic = = null ) {
continue ;
}
if ( topic . pinned ) {
newOrder . add ( topic . id ) ;
}
}
}
return newOrder ;
}
2022-11-05 13:34:47 +01:00
2022-11-12 09:41:35 +01:00
public void applyPinnedOrder ( long chatId , ArrayList < Integer > order ) {
applyPinnedOrder ( chatId , order , true ) ;
}
public void applyPinnedOrder ( long chatId , ArrayList < Integer > order , boolean notify ) {
if ( order = = null ) {
return ;
}
ArrayList < TLRPC . TL_forumTopic > topics = getTopics ( chatId ) ;
boolean updated = false ;
2022-11-05 13:34:47 +01:00
if ( topics ! = null ) {
for ( int i = 0 ; i < topics . size ( ) ; + + i ) {
TLRPC . TL_forumTopic topic = topics . get ( i ) ;
2022-11-12 09:41:35 +01:00
if ( topic = = null ) {
continue ;
}
int newPinnedOrder = order . indexOf ( topic . id ) ;
boolean newPinned = newPinnedOrder > = 0 ;
if ( topic . pinned ! = newPinned | | newPinned & & topic . pinnedOrder ! = newPinnedOrder ) {
updated = true ;
topic . pinned = newPinned ;
topic . pinnedOrder = newPinnedOrder ;
getMessagesStorage ( ) . updateTopicData ( chatId , topic , TopicsController . TOPIC_FLAG_PIN ) ;
2022-11-05 13:34:47 +01:00
}
}
2022-11-12 09:41:35 +01:00
} else {
updated = true ;
2022-11-05 13:34:47 +01:00
}
2022-11-12 09:41:35 +01:00
if ( notify & & updated ) {
AndroidUtilities . runOnUIThread ( ( ) - > {
NotificationCenter . getInstance ( currentAccount ) . postNotificationName ( NotificationCenter . updateInterfaces , MessagesController . UPDATE_MASK_SELECT_DIALOG ) ;
} ) ;
}
}
public void pinTopic ( long chatId , int topicId , boolean pin , BaseFragment fragment ) {
TLRPC . TL_channels_updatePinnedForumTopic req = new TLRPC . TL_channels_updatePinnedForumTopic ( ) ;
req . channel = getMessagesController ( ) . getInputChannel ( chatId ) ;
req . topic_id = topicId ;
req . pinned = pin ;
ArrayList < Integer > prevOrder = getCurrentPinnedOrder ( chatId ) ;
ArrayList < Integer > newOrder = new ArrayList < > ( prevOrder ) ;
newOrder . remove ( ( Integer ) topicId ) ;
if ( pin ) {
newOrder . add ( 0 , topicId ) ;
}
applyPinnedOrder ( chatId , newOrder ) ;
2022-11-05 13:34:47 +01:00
ConnectionsManager . getInstance ( currentAccount ) . sendRequest ( req , ( response , error ) - > {
2022-11-12 09:41:35 +01:00
if ( error ! = null ) {
if ( " PINNED_TOO_MUCH " . equals ( error . text ) ) {
if ( fragment = = null ) {
return ;
}
applyPinnedOrder ( chatId , prevOrder ) ;
fragment . showDialog (
new AlertDialog . Builder ( fragment . getContext ( ) )
. setTitle ( LocaleController . getString ( " LimitReached " , R . string . LimitReached ) )
. setMessage ( LocaleController . formatString ( " LimitReachedPinnedTopics " , R . string . LimitReachedPinnedTopics , MessagesController . getInstance ( currentAccount ) . topicsPinnedLimit ) )
. setPositiveButton ( LocaleController . getString ( " OK " , R . string . OK ) , null )
. create ( )
) ;
} else if ( " PINNED_TOPIC_NOT_MODIFIED " . equals ( error . text ) ) {
reloadTopics ( chatId , false ) ;
}
2022-11-05 13:34:47 +01:00
}
} ) ;
}
2022-11-12 09:41:35 +01:00
public void reorderPinnedTopics ( long chatId , ArrayList < Integer > topics ) {
TLRPC . TL_channels_reorderPinnedForumTopics req = new TLRPC . TL_channels_reorderPinnedForumTopics ( ) ;
req . channel = getMessagesController ( ) . getInputChannel ( chatId ) ;
if ( topics ! = null ) {
req . order . addAll ( topics ) ;
}
req . force = true ;
applyPinnedOrder ( chatId , topics , false ) ;
ConnectionsManager . getInstance ( currentAccount ) . sendRequest ( req , null ) ;
}
2022-11-05 13:34:47 +01:00
public void updateMentionsUnread ( long dialogId , int topicId , int topicMentionsCount ) {
AndroidUtilities . runOnUIThread ( ( ) - > {
TLRPC . TL_forumTopic topic = findTopic ( - dialogId , topicId ) ;
if ( topic ! = null ) {
topic . unread_mentions_count = topicMentionsCount ;
sortTopics ( - dialogId , true ) ;
}
} ) ;
}
public int updateReactionsUnread ( long dialogId , int topicId , int count , boolean increment ) {
TLRPC . TL_forumTopic topic = findTopic ( - dialogId , topicId ) ;
int totalCount = - 1 ;
if ( topic ! = null ) {
if ( increment ) {
topic . unread_reactions_count + = count ;
if ( topic . unread_reactions_count < 0 ) {
topic . unread_reactions_count = 0 ;
}
} else {
topic . unread_reactions_count = count ;
}
totalCount = topic . unread_reactions_count ;
sortTopics ( - dialogId , true ) ;
}
return totalCount ;
}
public void markAllReactionsAsRead ( long chatId , int topicId ) {
TLRPC . TL_forumTopic topic = findTopic ( chatId , topicId ) ;
if ( topic ! = null & & topic . unread_reactions_count > 0 ) {
topic . unread_reactions_count = 0 ;
sortTopics ( chatId ) ;
}
}
LongSparseArray < TopicsLoadOffset > offsets = new LongSparseArray < > ( ) ;
public TopicsLoadOffset getLoadOffset ( long chatId ) {
TopicsLoadOffset offset = offsets . get ( chatId ) ;
if ( offset ! = null ) {
return offset ;
}
return new TopicsLoadOffset ( ) ;
// SharedPreferences sharedPreferences = getUserConfig().getPreferences();
// TopicsLoadOffset topicsLoadOffset = new TopicsLoadOffset();
// topicsLoadOffset.lastMessageId = sharedPreferences.getInt("topics_load_offset_message_id_" + chatId, 0);
// topicsLoadOffset.lastMessageDate = sharedPreferences.getInt("topics_load_offset_date_" + chatId, 0);
// topicsLoadOffset.lastMessageId = sharedPreferences.getInt("topics_load_offset_topic_id_" + chatId, 0);
// return topicsLoadOffset;
}
public void saveLoadOffset ( long chatId , int lastMessageId , int lastMessageDate , int lastTopicId ) {
TopicsLoadOffset offset = new TopicsLoadOffset ( ) ;
offset . lastMessageId = lastMessageId ;
offset . lastMessageDate = lastMessageDate ;
offset . lastTopicId = lastTopicId ;
offsets . put ( chatId , offset ) ;
// SharedPreferences.Editor editor = getUserConfig().getPreferences().edit();
// editor.putInt("topics_load_offset_message_id_" + chatId, lastMessageId);
// editor.putInt("topics_load_offset_date_" + chatId, lastMessageDate);
// editor.putInt("topics_load_offset_topic_id_" + chatId, lastTopicId);
// editor.apply();
}
public void clearLoadingOffset ( long chatId ) {
offsets . remove ( chatId ) ;
// SharedPreferences.Editor editor = getUserConfig().getPreferences().edit();
// editor.remove("topics_load_offset_message_id_" + chatId);
// editor.remove("topics_load_offset_date_" + chatId);
// editor.remove("topics_load_offset_topic_id_" + chatId);
// editor.apply();
}
public boolean endIsReached ( long chatId ) {
return endIsReached . get ( chatId , 0 ) = = 1 ;
}
public void processUpdate ( List < TopicUpdate > topicUpdates ) {
AndroidUtilities . runOnUIThread ( ( ) - > {
HashSet < Long > changedDialogs = new HashSet < > ( ) ;
LongSparseArray < ArrayList < TLRPC . TL_forumTopic > > topicsToReload = null ;
for ( int i = 0 ; i < topicUpdates . size ( ) ; i + + ) {
TopicUpdate update = topicUpdates . get ( i ) ;
if ( update . reloadTopic ) {
if ( topicsToReload = = null ) {
topicsToReload = new LongSparseArray < > ( ) ;
}
ArrayList < TLRPC . TL_forumTopic > arrayList = topicsToReload . get ( update . dialogId ) ;
if ( arrayList = = null ) {
arrayList = new ArrayList < > ( ) ;
topicsToReload . put ( update . dialogId , arrayList ) ;
}
TLRPC . TL_forumTopic forumTopic = new TLRPC . TL_forumTopic ( ) ;
forumTopic . id = update . topicId ;
arrayList . add ( forumTopic ) ;
} else {
TLRPC . TL_forumTopic topic = findTopic ( - update . dialogId , update . topicId ) ;
if ( topic ! = null ) {
if ( update . onlyCounters ) {
if ( update . unreadCount > = 0 ) {
topic . unread_count = update . unreadCount ;
}
if ( update . unreadMentions > = 0 ) {
topic . unread_mentions_count = update . unreadMentions ;
}
} else {
topicsByTopMsgId . remove ( messageHash ( topic . top_message , - update . dialogId ) ) ;
topic . topMessage = update . topMessage ;
topic . groupedMessages = update . groupedMessages ;
topic . top_message = update . topMessageId ;
topic . unread_count = update . unreadCount ;
topic . unread_mentions_count = update . unreadMentions ;
topicsByTopMsgId . put ( messageHash ( topic . top_message , - update . dialogId ) , topic ) ;
}
changedDialogs . add ( - update . dialogId ) ;
}
}
}
for ( Long changedDialog : changedDialogs ) {
sortTopics ( changedDialog , true ) ;
}
if ( topicsToReload ! = null ) {
for ( int i = 0 ; i < topicsToReload . size ( ) ; i + + ) {
long dialogId = topicsToReload . keyAt ( i ) ;
ArrayList < TLRPC . TL_forumTopic > topics = topicsToReload . valueAt ( i ) ;
reloadTopics ( - dialogId , topics ) ;
}
}
} ) ;
}
public boolean isLoading ( long chatId ) {
return topicsIsLoading . get ( chatId , 0 ) = = 1 & & ( topicsByChatId . get ( chatId ) = = null | | topicsByChatId . get ( chatId ) . isEmpty ( ) ) ;
}
public void onTopicsDeletedServerSide ( ArrayList < MessagesStorage . TopicKey > topicsToDelete ) {
AndroidUtilities . runOnUIThread ( ( ) - > {
HashSet < Long > changedChatId = new HashSet < > ( ) ;
for ( int i = 0 ; i < topicsToDelete . size ( ) ; i + + ) {
MessagesStorage . TopicKey topicKey = topicsToDelete . get ( i ) ;
long chatId = - topicKey . dialogId ;
LongSparseArray < TLRPC . TL_forumTopic > topicsMap = topicsMapByChatId . get ( chatId ) ;
if ( topicsMap ! = null ) {
topicsMap . remove ( topicKey . topicId ) ;
}
ArrayList < TLRPC . TL_forumTopic > topics = topicsByChatId . get ( chatId ) ;
if ( topics ! = null ) {
for ( int k = 0 ; k < topics . size ( ) ; k + + ) {
if ( topics . get ( k ) . id = = topicKey . topicId ) {
topics . remove ( k ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . dialogDeleted , - chatId , topicKey . topicId ) ;
changedChatId . add ( chatId ) ;
break ;
}
}
}
}
for ( Long chatId : changedChatId ) {
sortTopics ( chatId , true ) ;
}
} ) ;
}
public void reloadTopics ( long chatId ) {
2022-11-12 09:41:35 +01:00
reloadTopics ( chatId , true ) ;
}
public void reloadTopics ( long chatId , boolean fromCache ) {
2022-11-05 13:34:47 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > {
2022-11-12 09:41:35 +01:00
getUserConfig ( ) . getPreferences ( ) . edit ( ) . remove ( " topics_end_reached_ " + chatId ) . apply ( ) ;
2022-11-05 13:34:47 +01:00
topicsByChatId . remove ( chatId ) ;
topicsMapByChatId . remove ( chatId ) ;
endIsReached . delete ( chatId ) ;
clearLoadingOffset ( chatId ) ;
2022-11-06 02:16:18 +01:00
2022-11-05 13:34:47 +01:00
TLRPC . Chat chat = getMessagesController ( ) . getChat ( chatId ) ;
if ( chat ! = null & & chat . forum ) {
2022-11-12 09:41:35 +01:00
if ( fromCache ) {
preloadTopics ( chatId ) ;
} else {
loadTopics ( chatId , false , LOAD_TYPE_PRELOAD ) ;
}
2022-11-05 13:34:47 +01:00
}
2022-11-06 02:16:18 +01:00
sortTopics ( chatId ) ;
2022-11-05 13:34:47 +01:00
} ) ;
}
public void databaseCleared ( ) {
AndroidUtilities . runOnUIThread ( ( ) - > {
topicsByChatId . clear ( ) ;
topicsMapByChatId . clear ( ) ;
endIsReached . clear ( ) ;
SharedPreferences . Editor editor = getUserConfig ( ) . getPreferences ( ) . edit ( ) ;
for ( String key : getUserConfig ( ) . getPreferences ( ) . getAll ( ) . keySet ( ) ) {
if ( key . startsWith ( " topics_load_offset_message_id_ " ) ) {
editor . remove ( key ) ;
}
if ( key . startsWith ( " topics_load_offset_date_ " ) ) {
editor . remove ( key ) ;
}
if ( key . startsWith ( " topics_load_offset_topic_id_ " ) ) {
editor . remove ( key ) ;
}
2022-11-12 09:41:35 +01:00
if ( key . startsWith ( " topics_end_reached_ " ) ) {
editor . remove ( key ) ;
}
2022-11-05 13:34:47 +01:00
}
editor . apply ( ) ;
} ) ;
}
public void updateReadOutbox ( HashMap < MessagesStorage . TopicKey , Integer > topicsReadOutbox ) {
AndroidUtilities . runOnUIThread ( ( ) - > {
HashSet < Long > updatedChats = new HashSet < > ( ) ;
for ( MessagesStorage . TopicKey topicKey : topicsReadOutbox . keySet ( ) ) {
int value = topicsReadOutbox . get ( topicKey ) ;
TLRPC . TL_forumTopic topic = findTopic ( - topicKey . dialogId , topicKey . topicId ) ;
if ( topic ! = null ) {
topic . read_outbox_max_id = Math . max ( topic . read_outbox_max_id , value ) ;
updatedChats . add ( - topicKey . dialogId ) ;
2022-11-20 22:12:39 +01:00
if ( topic . topMessage ! = null & & topic . read_outbox_max_id > = topic . topMessage . id ) {
2022-11-05 13:34:47 +01:00
topic . topMessage . unread = false ;
}
}
}
//TODO topics
// optimize move to mask update
for ( Long chatId : updatedChats ) {
NotificationCenter . getInstance ( currentAccount ) . postNotificationName ( NotificationCenter . topicsDidLoaded , chatId , true ) ;
}
} ) ;
}
public void updateTopicInUi ( long dialogId , TLRPC . TL_forumTopic forumTopic , int flags ) {
TLRPC . TL_forumTopic topic = findTopic ( - dialogId , forumTopic . id ) ;
if ( topic ! = null ) {
if ( ( flags & TOPIC_FLAG_TITLE ) ! = 0 ) {
topic . title = forumTopic . title ;
}
if ( ( flags & TOPIC_FLAG_ICON ) ! = 0 ) {
topic . icon_emoji_id = forumTopic . icon_emoji_id ;
}
if ( ( flags & TOPIC_FLAG_CLOSE ) ! = 0 ) {
topic . closed = forumTopic . closed ;
}
if ( ( flags & TOPIC_FLAG_PIN ) ! = 0 ) {
topic . pinned = forumTopic . pinned ;
}
sortTopics ( - dialogId ) ;
}
}
public void processEditedMessages ( LongSparseArray < ArrayList < MessageObject > > editingMessagesFinal ) {
HashSet < Long > changedChatId = new HashSet < > ( ) ;
for ( int i = 0 ; i < editingMessagesFinal . size ( ) ; i + + ) {
ArrayList < MessageObject > messageObjects = editingMessagesFinal . valueAt ( i ) ;
for ( int j = 0 ; j < messageObjects . size ( ) ; j + + ) {
TLRPC . TL_forumTopic topic = topicsByTopMsgId . get ( messageHash ( messageObjects . get ( j ) . getId ( ) , - messageObjects . get ( j ) . getDialogId ( ) ) ) ;
if ( topic ! = null ) {
topic . topMessage = messageObjects . get ( j ) . messageOwner ;
changedChatId . add ( - messageObjects . get ( j ) . getDialogId ( ) ) ;
}
}
}
for ( Long chatId : changedChatId ) {
sortTopics ( chatId , true ) ;
}
}
public void processEditedMessage ( TLRPC . Message newMsg ) {
TLRPC . TL_forumTopic topic = topicsByTopMsgId . get ( messageHash ( newMsg . id , - newMsg . dialog_id ) ) ;
if ( topic ! = null ) {
topic . topMessage = newMsg ;
sortTopics ( - newMsg . dialog_id , true ) ;
}
}
private class TopicsLoadOffset {
int lastMessageId ;
int lastMessageDate ;
int lastTopicId ;
}
public static class TopicUpdate {
long dialogId ;
int topicId ;
int unreadMentions ;
int unreadCount ;
int topMessageId ;
TLRPC . Message topMessage ;
ArrayList < MessageObject > groupedMessages ;
boolean reloadTopic ;
boolean onlyCounters ;
}
public void onTopicFragmentResume ( long chatId ) {
int v = openedTopicsBuChatId . get ( chatId , 0 ) ;
openedTopicsBuChatId . put ( chatId , v + 1 ) ;
sortTopics ( chatId ) ;
}
public void onTopicFragmentPause ( long chatId ) {
int v = openedTopicsBuChatId . get ( chatId , 0 ) ;
v - - ;
if ( v < 0 ) {
v = 0 ;
}
openedTopicsBuChatId . put ( chatId , v ) ;
}
}