2018-07-30 04:07:02 +02:00
/ *
2019-01-23 18:03:33 +01:00
* This is the source code of Telegram for Android v . 5 . x . x .
2018-07-30 04:07:02 +02:00
* It is licensed under GNU GPL v . 2 or later .
* You should have received a copy of the license in this archive ( see LICENSE ) .
*
2019-01-23 18:03:33 +01:00
* Copyright Nikolai Kudashov , 2013 - 2018 .
2018-07-30 04:07:02 +02:00
* /
package org.telegram.messenger ;
import android.app.Activity ;
import android.content.Context ;
import android.content.Intent ;
import android.content.SharedPreferences ;
import android.content.pm.ShortcutManager ;
import android.graphics.Bitmap ;
import android.graphics.BitmapFactory ;
import android.graphics.BitmapShader ;
import android.graphics.Canvas ;
import android.graphics.Color ;
import android.graphics.Paint ;
import android.graphics.Path ;
import android.graphics.PorterDuff ;
import android.graphics.PorterDuffXfermode ;
import android.graphics.RectF ;
import android.graphics.Shader ;
import android.graphics.drawable.Drawable ;
import android.os.Build ;
2019-07-18 15:01:39 +02:00
import android.text.Spannable ;
2018-07-30 04:07:02 +02:00
import android.text.SpannableStringBuilder ;
import android.text.Spanned ;
import android.text.SpannedString ;
import android.text.TextUtils ;
2019-07-18 15:01:39 +02:00
import android.text.style.CharacterStyle ;
2018-07-30 04:07:02 +02:00
import android.util.SparseArray ;
2021-03-09 12:40:50 +01:00
import android.widget.Toast ;
2018-07-30 04:07:02 +02:00
2021-02-04 18:59:00 +01:00
import androidx.core.content.pm.ShortcutInfoCompat ;
import androidx.core.content.pm.ShortcutManagerCompat ;
import androidx.core.graphics.drawable.IconCompat ;
2018-07-30 04:07:02 +02:00
import org.telegram.SQLite.SQLiteCursor ;
import org.telegram.SQLite.SQLiteDatabase ;
2021-07-15 16:24:57 +02:00
import org.telegram.SQLite.SQLiteException ;
2018-07-30 04:07:02 +02:00
import org.telegram.SQLite.SQLitePreparedStatement ;
import org.telegram.messenger.support.SparseLongArray ;
import org.telegram.tgnet.ConnectionsManager ;
import org.telegram.tgnet.NativeByteBuffer ;
import org.telegram.tgnet.SerializedData ;
import org.telegram.tgnet.TLObject ;
import org.telegram.tgnet.TLRPC ;
import org.telegram.ui.ActionBar.BaseFragment ;
import org.telegram.ui.Components.AvatarDrawable ;
2020-03-30 14:00:09 +02:00
import org.telegram.ui.Components.Bulletin ;
import org.telegram.ui.Components.StickerSetBulletinLayout ;
2018-07-30 04:07:02 +02:00
import org.telegram.ui.Components.StickersArchiveAlert ;
2019-07-18 15:01:39 +02:00
import org.telegram.ui.Components.TextStyleSpan ;
2018-07-30 04:07:02 +02:00
import org.telegram.ui.Components.URLSpanReplacement ;
import org.telegram.ui.Components.URLSpanUserMention ;
import org.telegram.ui.LaunchActivity ;
import java.io.File ;
import java.util.ArrayList ;
2020-12-23 08:48:30 +01:00
import java.util.Arrays ;
2018-07-30 04:07:02 +02:00
import java.util.Collections ;
import java.util.Comparator ;
import java.util.HashMap ;
2020-04-24 11:21:58 +02:00
import java.util.HashSet ;
2018-07-30 04:07:02 +02:00
import java.util.List ;
import java.util.Locale ;
import java.util.Map ;
2020-07-26 10:03:38 +02:00
import java.util.UUID ;
2020-06-04 18:47:15 +02:00
import java.util.concurrent.ConcurrentHashMap ;
2019-05-14 14:08:05 +02:00
import java.util.concurrent.CountDownLatch ;
2018-07-30 04:07:02 +02:00
2021-09-20 00:10:42 +02:00
import androidx.collection.LongSparseArray ;
2021-10-30 08:05:57 +02:00
import tw.nekomimi.nkmr.NekomuraConfig ;
2021-03-09 12:40:50 +01:00
import tw.nekomimi.nekogram.NekoXConfig ;
import tw.nekomimi.nekogram.PinnedStickerHelper ;
2020-01-18 07:35:06 +01:00
2021-09-20 00:10:42 +02:00
import com.google.android.exoplayer2.util.Log ;
2018-07-30 04:07:02 +02:00
@SuppressWarnings ( " unchecked " )
2019-07-18 15:01:39 +02:00
public class MediaDataController extends BaseController {
2018-07-30 04:07:02 +02:00
2020-07-26 10:03:38 +02:00
public static String SHORTCUT_CATEGORY = " org.telegram.messenger.SHORTCUT_SHARE " ;
2021-03-12 13:37:39 +01:00
private static SparseArray < MediaDataController > Instance = new SparseArray < > ( ) ;
2021-03-09 12:40:50 +01:00
2019-07-18 15:01:39 +02:00
public static MediaDataController getInstance ( int num ) {
2021-03-12 13:37:39 +01:00
MediaDataController localInstance = Instance . get ( num ) ;
2018-07-30 04:07:02 +02:00
if ( localInstance = = null ) {
2019-07-18 15:01:39 +02:00
synchronized ( MediaDataController . class ) {
2021-03-12 13:37:39 +01:00
localInstance = Instance . get ( num ) ;
2018-07-30 04:07:02 +02:00
if ( localInstance = = null ) {
2021-03-12 13:37:39 +01:00
Instance . put ( num , localInstance = new MediaDataController ( num ) ) ;
2018-07-30 04:07:02 +02:00
}
}
}
return localInstance ;
}
2019-07-18 15:01:39 +02:00
public MediaDataController ( int num ) {
super ( num ) ;
2018-07-30 04:07:02 +02:00
if ( currentAccount = = 0 ) {
2020-09-30 15:48:47 +02:00
draftPreferences = ApplicationLoader . applicationContext . getSharedPreferences ( " drafts " , Activity . MODE_PRIVATE ) ;
2018-07-30 04:07:02 +02:00
} else {
2020-09-30 15:48:47 +02:00
draftPreferences = ApplicationLoader . applicationContext . getSharedPreferences ( " drafts " + currentAccount , Activity . MODE_PRIVATE ) ;
2018-07-30 04:07:02 +02:00
}
2020-09-30 15:48:47 +02:00
Map < String , ? > values = draftPreferences . getAll ( ) ;
2018-07-30 04:07:02 +02:00
for ( Map . Entry < String , ? > entry : values . entrySet ( ) ) {
try {
String key = entry . getKey ( ) ;
long did = Utilities . parseLong ( key ) ;
byte [ ] bytes = Utilities . hexToBytes ( ( String ) entry . getValue ( ) ) ;
SerializedData serializedData = new SerializedData ( bytes ) ;
2020-09-30 15:48:47 +02:00
boolean isThread = false ;
if ( key . startsWith ( " r_ " ) | | ( isThread = key . startsWith ( " rt_ " ) ) ) {
2018-07-30 04:07:02 +02:00
TLRPC . Message message = TLRPC . Message . TLdeserialize ( serializedData , serializedData . readInt32 ( true ) , true ) ;
if ( message ! = null ) {
2020-09-30 15:48:47 +02:00
message . readAttachPath ( serializedData , getUserConfig ( ) . clientUserId ) ;
SparseArray < TLRPC . Message > threads = draftMessages . get ( did ) ;
if ( threads = = null ) {
threads = new SparseArray < > ( ) ;
draftMessages . put ( did , threads ) ;
}
int threadId = isThread ? Utilities . parseInt ( key . substring ( key . lastIndexOf ( '_' ) + 1 ) ) : 0 ;
threads . put ( threadId , message ) ;
2018-07-30 04:07:02 +02:00
}
} else {
TLRPC . DraftMessage draftMessage = TLRPC . DraftMessage . TLdeserialize ( serializedData , serializedData . readInt32 ( true ) , true ) ;
if ( draftMessage ! = null ) {
2020-09-30 15:48:47 +02:00
SparseArray < TLRPC . DraftMessage > threads = drafts . get ( did ) ;
if ( threads = = null ) {
threads = new SparseArray < > ( ) ;
drafts . put ( did , threads ) ;
}
int threadId = key . startsWith ( " t_ " ) ? Utilities . parseInt ( key . substring ( key . lastIndexOf ( '_' ) + 1 ) ) : 0 ;
threads . put ( threadId , draftMessage ) ;
2018-07-30 04:07:02 +02:00
}
}
serializedData . cleanup ( ) ;
} catch ( Exception e ) {
//igonre
}
}
}
public static final int TYPE_IMAGE = 0 ;
public static final int TYPE_MASK = 1 ;
public static final int TYPE_FAVE = 2 ;
public static final int TYPE_FEATURED = 3 ;
2019-08-22 01:53:26 +02:00
public static final int TYPE_EMOJI = 4 ;
2018-07-30 04:07:02 +02:00
2021-04-14 03:44:46 +02:00
public static final int TYPE_GREETINGS = 3 ;
2020-06-06 08:07:06 +02:00
private ArrayList < TLRPC . TL_messages_stickerSet > [ ] stickerSets = new ArrayList [ ] { new ArrayList < > ( ) , new ArrayList < > ( ) , new ArrayList < > ( 0 ) , new ArrayList < > ( ) , new ArrayList < > ( ) } ;
private LongSparseArray < TLRPC . Document > [ ] stickersByIds = new LongSparseArray [ ] { new LongSparseArray < > ( ) , new LongSparseArray < > ( ) , new LongSparseArray < > ( ) , new LongSparseArray < > ( ) , new LongSparseArray < > ( ) } ;
2018-07-30 04:07:02 +02:00
private LongSparseArray < TLRPC . TL_messages_stickerSet > stickerSetsById = new LongSparseArray < > ( ) ;
private LongSparseArray < TLRPC . TL_messages_stickerSet > installedStickerSetsById = new LongSparseArray < > ( ) ;
private LongSparseArray < TLRPC . TL_messages_stickerSet > groupStickerSets = new LongSparseArray < > ( ) ;
2020-06-04 18:47:15 +02:00
private ConcurrentHashMap < String , TLRPC . TL_messages_stickerSet > stickerSetsByName = new ConcurrentHashMap < > ( 100 , 1 . 0f , 1 ) ;
2020-04-24 11:21:58 +02:00
private HashMap < String , TLRPC . TL_messages_stickerSet > diceStickerSetsByEmoji = new HashMap < > ( ) ;
private LongSparseArray < String > diceEmojiStickerSetsById = new LongSparseArray < > ( ) ;
private HashSet < String > loadingDiceStickerSets = new HashSet < > ( ) ;
2020-03-30 14:00:09 +02:00
private LongSparseArray < Runnable > removingStickerSetsUndos = new LongSparseArray < > ( ) ;
private Runnable [ ] scheduledLoadStickers = new Runnable [ 5 ] ;
2019-08-22 01:53:26 +02:00
private boolean [ ] loadingStickers = new boolean [ 5 ] ;
private boolean [ ] stickersLoaded = new boolean [ 5 ] ;
2021-09-20 00:10:42 +02:00
private long [ ] loadHash = new long [ 5 ] ;
2019-08-22 01:53:26 +02:00
private int [ ] loadDate = new int [ 5 ] ;
2018-07-30 04:07:02 +02:00
2020-06-04 18:47:15 +02:00
private HashMap < String , ArrayList < TLRPC . Message > > verifyingMessages = new HashMap < > ( ) ;
2019-06-04 12:14:50 +02:00
private int [ ] archivedStickersCount = new int [ 2 ] ;
2018-07-30 04:07:02 +02:00
private LongSparseArray < String > stickersByEmoji = new LongSparseArray < > ( ) ;
private HashMap < String , ArrayList < TLRPC . Document > > allStickers = new HashMap < > ( ) ;
private HashMap < String , ArrayList < TLRPC . Document > > allStickersFeatured = new HashMap < > ( ) ;
2021-04-14 03:44:46 +02:00
private ArrayList < TLRPC . Document > [ ] recentStickers = new ArrayList [ ] { new ArrayList < > ( ) , new ArrayList < > ( ) , new ArrayList < > ( ) , new ArrayList < > ( ) } ;
private boolean [ ] loadingRecentStickers = new boolean [ 4 ] ;
private boolean [ ] recentStickersLoaded = new boolean [ 4 ] ;
2018-07-30 04:07:02 +02:00
private ArrayList < TLRPC . Document > recentGifs = new ArrayList < > ( ) ;
private boolean loadingRecentGifs ;
private boolean recentGifsLoaded ;
2021-09-20 00:10:42 +02:00
private long loadFeaturedHash ;
2018-07-30 04:07:02 +02:00
private int loadFeaturedDate ;
private ArrayList < TLRPC . StickerSetCovered > featuredStickerSets = new ArrayList < > ( ) ;
private LongSparseArray < TLRPC . StickerSetCovered > featuredStickerSetsById = new LongSparseArray < > ( ) ;
private ArrayList < Long > unreadStickerSets = new ArrayList < > ( ) ;
private ArrayList < Long > readingStickerSets = new ArrayList < > ( ) ;
private boolean loadingFeaturedStickers ;
private boolean featuredStickersLoaded ;
2021-04-14 03:44:46 +02:00
private TLRPC . Document greetingsSticker ;
2018-07-30 04:07:02 +02:00
public void cleanup ( ) {
2021-04-14 03:44:46 +02:00
for ( int a = 0 ; a < recentStickers . length ; a + + ) {
2018-07-30 04:07:02 +02:00
recentStickers [ a ] . clear ( ) ;
loadingRecentStickers [ a ] = false ;
recentStickersLoaded [ a ] = false ;
}
for ( int a = 0 ; a < 4 ; a + + ) {
loadHash [ a ] = 0 ;
loadDate [ a ] = 0 ;
stickerSets [ a ] . clear ( ) ;
loadingStickers [ a ] = false ;
stickersLoaded [ a ] = false ;
}
2020-10-30 11:26:29 +01:00
loadingPinnedMessages . clear ( ) ;
2018-07-30 04:07:02 +02:00
loadFeaturedDate = 0 ;
loadFeaturedHash = 0 ;
allStickers . clear ( ) ;
allStickersFeatured . clear ( ) ;
stickersByEmoji . clear ( ) ;
featuredStickerSetsById . clear ( ) ;
featuredStickerSets . clear ( ) ;
unreadStickerSets . clear ( ) ;
recentGifs . clear ( ) ;
stickerSetsById . clear ( ) ;
installedStickerSetsById . clear ( ) ;
stickerSetsByName . clear ( ) ;
2020-04-24 11:21:58 +02:00
diceStickerSetsByEmoji . clear ( ) ;
diceEmojiStickerSetsById . clear ( ) ;
loadingDiceStickerSets . clear ( ) ;
2018-07-30 04:07:02 +02:00
loadingFeaturedStickers = false ;
featuredStickersLoaded = false ;
loadingRecentGifs = false ;
recentGifsLoaded = false ;
2019-05-14 14:08:05 +02:00
currentFetchingEmoji . clear ( ) ;
2019-09-10 12:56:11 +02:00
if ( Build . VERSION . SDK_INT > = 25 ) {
Utilities . globalQueue . postRunnable ( ( ) - > {
try {
2020-07-26 10:03:38 +02:00
ShortcutManagerCompat . removeAllDynamicShortcuts ( ApplicationLoader . applicationContext ) ;
2019-09-10 12:56:11 +02:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
} ) ;
}
2020-06-04 18:47:15 +02:00
verifyingMessages . clear ( ) ;
2019-05-14 14:08:05 +02:00
2018-07-30 04:07:02 +02:00
loading = false ;
loaded = false ;
hints . clear ( ) ;
inlineBots . clear ( ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . reloadHints ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . reloadInlineHints ) ;
2018-07-30 04:07:02 +02:00
drafts . clear ( ) ;
draftMessages . clear ( ) ;
2020-09-30 15:48:47 +02:00
draftPreferences . edit ( ) . clear ( ) . commit ( ) ;
2018-07-30 04:07:02 +02:00
botInfos . clear ( ) ;
botKeyboards . clear ( ) ;
botKeyboardsByMids . clear ( ) ;
}
public void checkStickers ( int type ) {
if ( ! loadingStickers [ type ] & & ( ! stickersLoaded [ type ] | | Math . abs ( System . currentTimeMillis ( ) / 1000 - loadDate [ type ] ) > = 60 * 60 ) ) {
loadStickers ( type , true , false ) ;
}
}
public void checkFeaturedStickers ( ) {
if ( ! loadingFeaturedStickers & & ( ! featuredStickersLoaded | | Math . abs ( System . currentTimeMillis ( ) / 1000 - loadFeaturedDate ) > = 60 * 60 ) ) {
loadFeaturedStickers ( true , false ) ;
}
}
public ArrayList < TLRPC . Document > getRecentStickers ( int type ) {
2021-08-28 16:05:34 +02:00
return getRecentStickers ( type , 0 ) ;
}
public ArrayList < TLRPC . Document > getRecentStickers ( int type , int padding ) {
2018-07-30 04:07:02 +02:00
ArrayList < TLRPC . Document > arrayList = recentStickers [ type ] ;
2021-10-30 08:05:57 +02:00
return new ArrayList < > ( arrayList . subList ( 0 , Math . min ( arrayList . size ( ) , NekomuraConfig . maxRecentStickerCount . Int ( ) + padding ) ) ) ;
2018-07-30 04:07:02 +02:00
}
public ArrayList < TLRPC . Document > getRecentStickersNoCopy ( int type ) {
return recentStickers [ type ] ;
}
public boolean isStickerInFavorites ( TLRPC . Document document ) {
2019-09-10 12:56:11 +02:00
if ( document = = null ) {
return false ;
}
2018-07-30 04:07:02 +02:00
for ( int a = 0 ; a < recentStickers [ TYPE_FAVE ] . size ( ) ; a + + ) {
TLRPC . Document d = recentStickers [ TYPE_FAVE ] . get ( a ) ;
if ( d . id = = document . id & & d . dc_id = = document . dc_id ) {
return true ;
}
}
return false ;
}
2021-09-20 00:10:42 +02:00
public void addRecentSticker ( int type , Object parentObject , TLRPC . Document document , int date , boolean remove ) {
2021-04-14 03:44:46 +02:00
if ( type = = TYPE_GREETINGS | | ! MessageObject . isStickerDocument ( document ) & & ! MessageObject . isAnimatedStickerDocument ( document , true ) ) {
2019-08-22 01:53:26 +02:00
return ;
}
2018-07-30 04:07:02 +02:00
boolean found = false ;
for ( int a = 0 ; a < recentStickers [ type ] . size ( ) ; a + + ) {
TLRPC . Document image = recentStickers [ type ] . get ( a ) ;
if ( image . id = = document . id ) {
recentStickers [ type ] . remove ( a ) ;
if ( ! remove ) {
recentStickers [ type ] . add ( 0 , image ) ;
}
found = true ;
2019-05-14 14:08:05 +02:00
break ;
2018-07-30 04:07:02 +02:00
}
}
if ( ! found & & ! remove ) {
recentStickers [ type ] . add ( 0 , document ) ;
}
int maxCount ;
if ( type = = TYPE_FAVE ) {
if ( remove ) {
2021-02-23 12:53:38 +01:00
NotificationCenter . getGlobalInstance ( ) . postNotificationName ( NotificationCenter . showBulletin , Bulletin . TYPE_STICKER , document , StickerSetBulletinLayout . TYPE_REMOVED_FROM_FAVORITES ) ;
2018-07-30 04:07:02 +02:00
} else {
2021-02-23 12:53:38 +01:00
NotificationCenter . getGlobalInstance ( ) . postNotificationName ( NotificationCenter . showBulletin , Bulletin . TYPE_STICKER , document , StickerSetBulletinLayout . TYPE_ADDED_TO_FAVORITES ) ;
2018-07-30 04:07:02 +02:00
}
TLRPC . TL_messages_faveSticker req = new TLRPC . TL_messages_faveSticker ( ) ;
req . id = new TLRPC . TL_inputDocument ( ) ;
req . id . id = document . id ;
req . id . access_hash = document . access_hash ;
2019-01-23 18:03:33 +01:00
req . id . file_reference = document . file_reference ;
if ( req . id . file_reference = = null ) {
req . id . file_reference = new byte [ 0 ] ;
}
2018-07-30 04:07:02 +02:00
req . unfave = remove ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2019-01-23 18:03:33 +01:00
if ( error ! = null & & FileRefController . isFileRefError ( error . text ) & & parentObject ! = null ) {
2019-07-18 15:01:39 +02:00
getFileRefController ( ) . requestReference ( parentObject , req ) ;
2020-03-30 14:00:09 +02:00
} else {
AndroidUtilities . runOnUIThread ( ( ) - > getMediaDataController ( ) . loadRecents ( MediaDataController . TYPE_FAVE , false , false , true ) ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
2021-10-30 08:05:57 +02:00
maxCount = NekomuraConfig . unlimitedFavedStickers . Bool ( ) ? Integer . MAX_VALUE : getMessagesController ( ) . maxFaveStickersCount ;
2018-07-30 04:07:02 +02:00
} else {
2020-03-30 14:00:09 +02:00
if ( type = = TYPE_IMAGE & & remove ) {
2021-02-23 12:53:38 +01:00
NotificationCenter . getGlobalInstance ( ) . postNotificationName ( NotificationCenter . showBulletin , Bulletin . TYPE_STICKER , document , StickerSetBulletinLayout . TYPE_REMOVED_FROM_RECENT ) ;
2020-03-30 14:00:09 +02:00
TLRPC . TL_messages_saveRecentSticker req = new TLRPC . TL_messages_saveRecentSticker ( ) ;
req . id = new TLRPC . TL_inputDocument ( ) ;
req . id . id = document . id ;
req . id . access_hash = document . access_hash ;
req . id . file_reference = document . file_reference ;
if ( req . id . file_reference = = null ) {
req . id . file_reference = new byte [ 0 ] ;
}
req . unsave = true ;
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
if ( error ! = null & & FileRefController . isFileRefError ( error . text ) & & parentObject ! = null ) {
getFileRefController ( ) . requestReference ( parentObject , req ) ;
}
} ) ;
}
2019-07-18 15:01:39 +02:00
maxCount = getMessagesController ( ) . maxRecentStickersCount ;
2018-07-30 04:07:02 +02:00
}
if ( recentStickers [ type ] . size ( ) > maxCount | | remove ) {
2021-09-20 00:10:42 +02:00
TLRPC . Document old = remove ? document : recentStickers [ type ] . remove ( recentStickers [ type ] . size ( ) - 1 ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
int cacheType ;
if ( type = = TYPE_IMAGE ) {
cacheType = 3 ;
} else if ( type = = TYPE_MASK ) {
cacheType = 4 ;
} else {
cacheType = 5 ;
}
try {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " DELETE FROM web_recent_v3 WHERE id = ' " + old . id + " ' AND type = " + cacheType ) . stepThis ( ) . dispose ( ) ;
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
if ( ! remove ) {
ArrayList < TLRPC . Document > arrayList = new ArrayList < > ( ) ;
arrayList . add ( document ) ;
2019-05-14 14:08:05 +02:00
processLoadedRecentDocuments ( type , arrayList , false , date , false ) ;
2018-07-30 04:07:02 +02:00
}
2020-03-30 14:00:09 +02:00
if ( type = = TYPE_FAVE | | type = = TYPE_IMAGE & & remove ) {
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . recentDocumentsDidLoad , false , type ) ;
2018-07-30 04:07:02 +02:00
}
}
public ArrayList < TLRPC . Document > getRecentGifs ( ) {
return new ArrayList < > ( recentGifs ) ;
}
2021-09-20 00:10:42 +02:00
public void removeRecentGif ( TLRPC . Document document ) {
2020-06-04 18:47:15 +02:00
for ( int i = 0 , N = recentGifs . size ( ) ; i < N ; i + + ) {
if ( recentGifs . get ( i ) . id = = document . id ) {
recentGifs . remove ( i ) ;
break ;
}
}
2018-07-30 04:07:02 +02:00
TLRPC . TL_messages_saveGif req = new TLRPC . TL_messages_saveGif ( ) ;
req . id = new TLRPC . TL_inputDocument ( ) ;
req . id . id = document . id ;
req . id . access_hash = document . access_hash ;
2019-01-23 18:03:33 +01:00
req . id . file_reference = document . file_reference ;
if ( req . id . file_reference = = null ) {
req . id . file_reference = new byte [ 0 ] ;
}
2018-07-30 04:07:02 +02:00
req . unsave = true ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2019-01-23 18:03:33 +01:00
if ( error ! = null & & FileRefController . isFileRefError ( error . text ) ) {
2019-07-18 15:01:39 +02:00
getFileRefController ( ) . requestReference ( " gif " , req ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " DELETE FROM web_recent_v3 WHERE id = ' " + document . id + " ' AND type = 2 " ) . stepThis ( ) . dispose ( ) ;
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2019-05-14 14:08:05 +02:00
public boolean hasRecentGif ( TLRPC . Document document ) {
for ( int a = 0 ; a < recentGifs . size ( ) ; a + + ) {
TLRPC . Document image = recentGifs . get ( a ) ;
if ( image . id = = document . id ) {
recentGifs . remove ( a ) ;
recentGifs . add ( 0 , image ) ;
return true ;
}
}
return false ;
}
2018-07-30 04:07:02 +02:00
public void addRecentGif ( TLRPC . Document document , int date ) {
2020-03-30 14:00:09 +02:00
if ( document = = null ) {
return ;
}
2018-07-30 04:07:02 +02:00
boolean found = false ;
for ( int a = 0 ; a < recentGifs . size ( ) ; a + + ) {
TLRPC . Document image = recentGifs . get ( a ) ;
if ( image . id = = document . id ) {
recentGifs . remove ( a ) ;
recentGifs . add ( 0 , image ) ;
found = true ;
2019-05-14 14:08:05 +02:00
break ;
2018-07-30 04:07:02 +02:00
}
}
if ( ! found ) {
recentGifs . add ( 0 , document ) ;
}
2019-07-18 15:01:39 +02:00
if ( recentGifs . size ( ) > getMessagesController ( ) . maxRecentGifsCount ) {
2021-09-20 00:10:42 +02:00
TLRPC . Document old = recentGifs . remove ( recentGifs . size ( ) - 1 ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " DELETE FROM web_recent_v3 WHERE id = ' " + old . id + " ' AND type = 2 " ) . stepThis ( ) . dispose ( ) ;
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
ArrayList < TLRPC . Document > arrayList = new ArrayList < > ( ) ;
arrayList . add ( document ) ;
2019-05-14 14:08:05 +02:00
processLoadedRecentDocuments ( 0 , arrayList , true , date , false ) ;
2018-07-30 04:07:02 +02:00
}
public boolean isLoadingStickers ( int type ) {
return loadingStickers [ type ] ;
}
2019-01-23 18:03:33 +01:00
public void replaceStickerSet ( TLRPC . TL_messages_stickerSet set ) {
TLRPC . TL_messages_stickerSet existingSet = stickerSetsById . get ( set . set . id ) ;
2020-04-24 11:21:58 +02:00
String emoji = diceEmojiStickerSetsById . get ( set . set . id ) ;
if ( emoji ! = null ) {
diceStickerSetsByEmoji . put ( emoji , set ) ;
putDiceStickersToCache ( emoji , set , ( int ) ( System . currentTimeMillis ( ) / 1000 ) ) ;
}
2019-01-23 18:03:33 +01:00
boolean isGroupSet = false ;
if ( existingSet = = null ) {
existingSet = stickerSetsByName . get ( set . set . short_name ) ;
}
if ( existingSet = = null ) {
existingSet = groupStickerSets . get ( set . set . id ) ;
if ( existingSet ! = null ) {
isGroupSet = true ;
}
}
if ( existingSet = = null ) {
return ;
}
boolean changed = false ;
2019-08-22 01:53:26 +02:00
if ( " AnimatedEmojies " . equals ( set . set . short_name ) ) {
changed = true ;
existingSet . documents = set . documents ;
existingSet . packs = set . packs ;
existingSet . set = set . set ;
AndroidUtilities . runOnUIThread ( ( ) - > {
LongSparseArray < TLRPC . Document > stickersById = getStickerByIds ( TYPE_EMOJI ) ;
for ( int b = 0 ; b < set . documents . size ( ) ; b + + ) {
TLRPC . Document document = set . documents . get ( b ) ;
stickersById . put ( document . id , document ) ;
}
} ) ;
} else {
LongSparseArray < TLRPC . Document > documents = new LongSparseArray < > ( ) ;
for ( int a = 0 , size = set . documents . size ( ) ; a < size ; a + + ) {
TLRPC . Document document = set . documents . get ( a ) ;
documents . put ( document . id , document ) ;
}
for ( int a = 0 , size = existingSet . documents . size ( ) ; a < size ; a + + ) {
2019-12-31 14:08:08 +01:00
TLRPC . Document document = existingSet . documents . get ( a ) ;
2019-08-22 01:53:26 +02:00
TLRPC . Document newDocument = documents . get ( document . id ) ;
if ( newDocument ! = null ) {
existingSet . documents . set ( a , newDocument ) ;
changed = true ;
}
2019-01-23 18:03:33 +01:00
}
}
if ( changed ) {
if ( isGroupSet ) {
putSetToCache ( existingSet ) ;
} else {
2019-08-22 01:53:26 +02:00
int type = set . set . masks ? TYPE_MASK : TYPE_IMAGE ;
2019-01-23 18:03:33 +01:00
putStickersToCache ( type , stickerSets [ type ] , loadDate [ type ] , loadHash [ type ] ) ;
2019-08-22 01:53:26 +02:00
if ( " AnimatedEmojies " . equals ( set . set . short_name ) ) {
type = TYPE_EMOJI ;
putStickersToCache ( type , stickerSets [ type ] , loadDate [ type ] , loadHash [ type ] ) ;
}
2019-01-23 18:03:33 +01:00
}
}
}
2018-07-30 04:07:02 +02:00
public TLRPC . TL_messages_stickerSet getStickerSetByName ( String name ) {
return stickerSetsByName . get ( name ) ;
}
2020-09-30 15:48:47 +02:00
public TLRPC . TL_messages_stickerSet getStickerSetByEmojiOrName ( String emoji ) {
2020-04-24 11:21:58 +02:00
return diceStickerSetsByEmoji . get ( emoji ) ;
}
2018-07-30 04:07:02 +02:00
public TLRPC . TL_messages_stickerSet getStickerSetById ( long id ) {
return stickerSetsById . get ( id ) ;
}
public TLRPC . TL_messages_stickerSet getGroupStickerSetById ( TLRPC . StickerSet stickerSet ) {
TLRPC . TL_messages_stickerSet set = stickerSetsById . get ( stickerSet . id ) ;
if ( set = = null ) {
set = groupStickerSets . get ( stickerSet . id ) ;
if ( set = = null | | set . set = = null ) {
loadGroupStickerSet ( stickerSet , true ) ;
} else if ( set . set . hash ! = stickerSet . hash ) {
loadGroupStickerSet ( stickerSet , false ) ;
}
}
return set ;
}
public void putGroupStickerSet ( TLRPC . TL_messages_stickerSet stickerSet ) {
groupStickerSets . put ( stickerSet . set . id , stickerSet ) ;
}
2021-09-20 00:10:42 +02:00
private void loadGroupStickerSet ( TLRPC . StickerSet stickerSet , boolean cache ) {
2018-07-30 04:07:02 +02:00
if ( cache ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2021-09-20 00:10:42 +02:00
TLRPC . TL_messages_stickerSet set ;
2019-07-18 15:01:39 +02:00
SQLiteCursor cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( " SELECT document FROM web_recent_v3 WHERE id = 's_ " + stickerSet . id + " ' " ) ;
2019-01-23 18:03:33 +01:00
if ( cursor . next ( ) & & ! cursor . isNull ( 0 ) ) {
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
set = TLRPC . TL_messages_stickerSet . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
data . reuse ( ) ;
2018-07-30 04:07:02 +02:00
} else {
set = null ;
}
2019-01-23 18:03:33 +01:00
} else {
set = null ;
}
cursor . dispose ( ) ;
if ( set = = null | | set . set = = null | | set . set . hash ! = stickerSet . hash ) {
loadGroupStickerSet ( stickerSet , false ) ;
}
if ( set ! = null & & set . set ! = null ) {
AndroidUtilities . runOnUIThread ( ( ) - > {
groupStickerSets . put ( set . set . id , set ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . groupStickersDidLoad , set . set . id ) ;
2019-01-23 18:03:33 +01:00
} ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} catch ( Throwable e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
} else {
TLRPC . TL_messages_getStickerSet req = new TLRPC . TL_messages_getStickerSet ( ) ;
req . stickerset = new TLRPC . TL_inputStickerSetID ( ) ;
req . stickerset . id = stickerSet . id ;
req . stickerset . access_hash = stickerSet . access_hash ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2019-01-23 18:03:33 +01:00
if ( response ! = null ) {
TLRPC . TL_messages_stickerSet set = ( TLRPC . TL_messages_stickerSet ) response ;
AndroidUtilities . runOnUIThread ( ( ) - > {
groupStickerSets . put ( set . set . id , set ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . groupStickersDidLoad , set . set . id ) ;
2019-01-23 18:03:33 +01:00
} ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
}
2019-01-23 18:03:33 +01:00
private void putSetToCache ( TLRPC . TL_messages_stickerSet set ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2019-07-18 15:01:39 +02:00
SQLiteDatabase database = getMessagesStorage ( ) . getDatabase ( ) ;
2019-01-23 18:03:33 +01:00
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO web_recent_v3 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?) " ) ;
state . requery ( ) ;
state . bindString ( 1 , " s_ " + set . set . id ) ;
state . bindInteger ( 2 , 6 ) ;
state . bindString ( 3 , " " ) ;
state . bindString ( 4 , " " ) ;
state . bindString ( 5 , " " ) ;
state . bindInteger ( 6 , 0 ) ;
state . bindInteger ( 7 , 0 ) ;
state . bindInteger ( 8 , 0 ) ;
state . bindInteger ( 9 , 0 ) ;
NativeByteBuffer data = new NativeByteBuffer ( set . getObjectSize ( ) ) ;
set . serializeToStream ( data ) ;
state . bindByteBuffer ( 10 , data ) ;
state . step ( ) ;
data . reuse ( ) ;
state . dispose ( ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
} ) ;
}
2018-07-30 04:07:02 +02:00
public HashMap < String , ArrayList < TLRPC . Document > > getAllStickers ( ) {
return allStickers ;
}
public HashMap < String , ArrayList < TLRPC . Document > > getAllStickersFeatured ( ) {
return allStickersFeatured ;
}
2019-08-22 01:53:26 +02:00
public TLRPC . Document getEmojiAnimatedSticker ( CharSequence message ) {
String emoji = message . toString ( ) . replace ( " \ uFE0F " , " " ) ;
ArrayList < TLRPC . TL_messages_stickerSet > arrayList = getStickerSets ( MediaDataController . TYPE_EMOJI ) ;
for ( int a = 0 , N = arrayList . size ( ) ; a < N ; a + + ) {
TLRPC . TL_messages_stickerSet set = arrayList . get ( a ) ;
for ( int b = 0 , N2 = set . packs . size ( ) ; b < N2 ; b + + ) {
TLRPC . TL_stickerPack pack = set . packs . get ( b ) ;
if ( ! pack . documents . isEmpty ( ) & & TextUtils . equals ( pack . emoticon , emoji ) ) {
LongSparseArray < TLRPC . Document > stickerByIds = getStickerByIds ( MediaDataController . TYPE_EMOJI ) ;
return stickerByIds . get ( pack . documents . get ( 0 ) ) ;
}
}
}
return null ;
}
2018-07-30 04:07:02 +02:00
public boolean canAddStickerToFavorites ( ) {
return ! stickersLoaded [ 0 ] | | stickerSets [ 0 ] . size ( ) > = 5 | | ! recentStickers [ TYPE_FAVE ] . isEmpty ( ) ;
}
public ArrayList < TLRPC . TL_messages_stickerSet > getStickerSets ( int type ) {
if ( type = = TYPE_FEATURED ) {
return stickerSets [ 2 ] ;
} else {
return stickerSets [ type ] ;
}
}
2019-08-22 01:53:26 +02:00
public LongSparseArray < TLRPC . Document > getStickerByIds ( int type ) {
return stickersByIds [ type ] ;
}
2018-07-30 04:07:02 +02:00
public ArrayList < TLRPC . StickerSetCovered > getFeaturedStickerSets ( ) {
return featuredStickerSets ;
}
public ArrayList < Long > getUnreadStickerSets ( ) {
return unreadStickerSets ;
}
2019-05-14 14:08:05 +02:00
public boolean areAllTrendingStickerSetsUnread ( ) {
for ( int a = 0 , N = featuredStickerSets . size ( ) ; a < N ; a + + ) {
TLRPC . StickerSetCovered pack = featuredStickerSets . get ( a ) ;
2019-07-18 15:01:39 +02:00
if ( isStickerPackInstalled ( pack . set . id ) | | pack . covers . isEmpty ( ) & & pack . cover = = null ) {
2019-05-14 14:08:05 +02:00
continue ;
}
if ( ! unreadStickerSets . contains ( pack . set . id ) ) {
return false ;
}
}
return true ;
}
2018-07-30 04:07:02 +02:00
public boolean isStickerPackInstalled ( long id ) {
return installedStickerSetsById . indexOfKey ( id ) > = 0 ;
}
public boolean isStickerPackUnread ( long id ) {
return unreadStickerSets . contains ( id ) ;
}
public boolean isStickerPackInstalled ( String name ) {
return stickerSetsByName . containsKey ( name ) ;
}
public String getEmojiForSticker ( long id ) {
String value = stickersByEmoji . get ( id ) ;
return value ! = null ? value : " " ;
}
2021-09-20 00:10:42 +02:00
public static long calcDocumentsHash ( ArrayList < TLRPC . Document > arrayList ) {
2020-07-26 10:03:38 +02:00
return calcDocumentsHash ( arrayList , 200 ) ;
}
2021-09-20 00:10:42 +02:00
public static long calcDocumentsHash ( ArrayList < TLRPC . Document > arrayList , int maxCount ) {
2018-07-30 04:07:02 +02:00
if ( arrayList = = null ) {
return 0 ;
}
long acc = 0 ;
2020-07-26 10:03:38 +02:00
for ( int a = 0 , N = Math . min ( maxCount , arrayList . size ( ) ) ; a < N ; a + + ) {
2018-07-30 04:07:02 +02:00
TLRPC . Document document = arrayList . get ( a ) ;
if ( document = = null ) {
continue ;
}
2021-09-20 00:10:42 +02:00
acc = calcHash ( acc , document . id ) ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
return acc ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
public void loadRecents ( int type , boolean gif , boolean cache , boolean force ) {
2021-10-30 08:05:57 +02:00
if ( NekomuraConfig . unlimitedFavedStickers . Bool ( ) & & type = = TYPE_FAVE & & ! cache ) {
2020-04-18 03:24:49 +02:00
return ;
}
2018-07-30 04:07:02 +02:00
if ( gif ) {
if ( loadingRecentGifs ) {
return ;
}
loadingRecentGifs = true ;
if ( recentGifsLoaded ) {
cache = false ;
}
} else {
if ( loadingRecentStickers [ type ] ) {
return ;
}
loadingRecentStickers [ type ] = true ;
if ( recentStickersLoaded [ type ] ) {
cache = false ;
}
}
if ( cache ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2021-09-20 00:10:42 +02:00
int cacheType ;
2019-01-23 18:03:33 +01:00
if ( gif ) {
cacheType = 2 ;
} else if ( type = = TYPE_IMAGE ) {
cacheType = 3 ;
} else if ( type = = TYPE_MASK ) {
cacheType = 4 ;
2021-04-14 03:44:46 +02:00
} else if ( type = = TYPE_GREETINGS ) {
cacheType = 6 ;
2019-01-23 18:03:33 +01:00
} else {
cacheType = 5 ;
}
2019-07-18 15:01:39 +02:00
SQLiteCursor cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( " SELECT document FROM web_recent_v3 WHERE type = " + cacheType + " ORDER BY date DESC " ) ;
2021-09-20 00:10:42 +02:00
ArrayList < TLRPC . Document > arrayList = new ArrayList < > ( ) ;
2019-01-23 18:03:33 +01:00
while ( cursor . next ( ) ) {
if ( ! cursor . isNull ( 0 ) ) {
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
TLRPC . Document document = TLRPC . Document . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
if ( document ! = null ) {
arrayList . add ( document ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
data . reuse ( ) ;
2018-07-30 04:07:02 +02:00
}
}
}
2019-01-23 18:03:33 +01:00
cursor . dispose ( ) ;
AndroidUtilities . runOnUIThread ( ( ) - > {
if ( gif ) {
recentGifs = arrayList ;
loadingRecentGifs = false ;
recentGifsLoaded = true ;
} else {
recentStickers [ type ] = arrayList ;
loadingRecentStickers [ type ] = false ;
recentStickersLoaded [ type ] = true ;
}
2021-04-14 03:44:46 +02:00
if ( type = = TYPE_GREETINGS ) {
preloadNextGreetingsSticker ( ) ;
}
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . recentDocumentsDidLoad , gif , type ) ;
2019-01-23 18:03:33 +01:00
loadRecents ( type , gif , false , false ) ;
} ) ;
} catch ( Throwable e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
} else {
SharedPreferences preferences = MessagesController . getEmojiSettings ( currentAccount ) ;
if ( ! force ) {
long lastLoadTime ;
if ( gif ) {
lastLoadTime = preferences . getLong ( " lastGifLoadTime " , 0 ) ;
} else if ( type = = TYPE_IMAGE ) {
lastLoadTime = preferences . getLong ( " lastStickersLoadTime " , 0 ) ;
} else if ( type = = TYPE_MASK ) {
lastLoadTime = preferences . getLong ( " lastStickersLoadTimeMask " , 0 ) ;
2021-04-14 03:44:46 +02:00
} else if ( type = = TYPE_GREETINGS ) {
lastLoadTime = preferences . getLong ( " lastStickersLoadTimeGreet " , 0 ) ;
2018-07-30 04:07:02 +02:00
} else {
lastLoadTime = preferences . getLong ( " lastStickersLoadTimeFavs " , 0 ) ;
}
if ( Math . abs ( System . currentTimeMillis ( ) - lastLoadTime ) < 60 * 60 * 1000 ) {
if ( gif ) {
loadingRecentGifs = false ;
} else {
loadingRecentStickers [ type ] = false ;
}
return ;
}
}
if ( gif ) {
TLRPC . TL_messages_getSavedGifs req = new TLRPC . TL_messages_getSavedGifs ( ) ;
req . hash = calcDocumentsHash ( recentGifs ) ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2019-01-23 18:03:33 +01:00
ArrayList < TLRPC . Document > arrayList = null ;
if ( response instanceof TLRPC . TL_messages_savedGifs ) {
TLRPC . TL_messages_savedGifs res = ( TLRPC . TL_messages_savedGifs ) response ;
arrayList = res . gifs ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
processLoadedRecentDocuments ( type , arrayList , true , 0 , true ) ;
2018-07-30 04:07:02 +02:00
} ) ;
} else {
TLObject request ;
if ( type = = TYPE_FAVE ) {
TLRPC . TL_messages_getFavedStickers req = new TLRPC . TL_messages_getFavedStickers ( ) ;
req . hash = calcDocumentsHash ( recentStickers [ type ] ) ;
request = req ;
2021-04-14 03:44:46 +02:00
} else if ( type = = TYPE_GREETINGS ) {
TLRPC . TL_messages_getStickers req = new TLRPC . TL_messages_getStickers ( ) ;
req . emoticon = " \ uD83D \ uDC4B " + Emoji . fixEmoji ( " ⭐ " ) ;
req . hash = calcDocumentsHash ( recentStickers [ type ] ) ;
request = req ;
2018-07-30 04:07:02 +02:00
} else {
TLRPC . TL_messages_getRecentStickers req = new TLRPC . TL_messages_getRecentStickers ( ) ;
req . hash = calcDocumentsHash ( recentStickers [ type ] ) ;
req . attached = type = = TYPE_MASK ;
request = req ;
}
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( request , ( response , error ) - > {
2019-01-23 18:03:33 +01:00
ArrayList < TLRPC . Document > arrayList = null ;
2021-04-14 03:44:46 +02:00
if ( type = = TYPE_GREETINGS ) {
if ( response instanceof TLRPC . TL_messages_stickers ) {
TLRPC . TL_messages_stickers res = ( TLRPC . TL_messages_stickers ) response ;
arrayList = res . stickers ;
}
} else if ( type = = TYPE_FAVE ) {
2019-01-23 18:03:33 +01:00
if ( response instanceof TLRPC . TL_messages_favedStickers ) {
TLRPC . TL_messages_favedStickers res = ( TLRPC . TL_messages_favedStickers ) response ;
arrayList = res . stickers ;
}
} else {
if ( response instanceof TLRPC . TL_messages_recentStickers ) {
TLRPC . TL_messages_recentStickers res = ( TLRPC . TL_messages_recentStickers ) response ;
arrayList = res . stickers ;
2018-07-30 04:07:02 +02:00
}
}
2021-04-14 03:44:46 +02:00
processLoadedRecentDocuments ( type , arrayList , false , 0 , true ) ;
2018-07-30 04:07:02 +02:00
} ) ;
}
}
}
2021-04-14 03:44:46 +02:00
private void preloadNextGreetingsSticker ( ) {
if ( recentStickers [ TYPE_GREETINGS ] . isEmpty ( ) ) {
return ;
}
greetingsSticker = recentStickers [ TYPE_GREETINGS ] . get ( Utilities . random . nextInt ( recentStickers [ TYPE_GREETINGS ] . size ( ) ) ) ;
getFileLoader ( ) . loadFile ( ImageLocation . getForDocument ( greetingsSticker ) , greetingsSticker , null , 0 , 1 ) ;
}
public TLRPC . Document getGreetingsSticker ( ) {
TLRPC . Document result = greetingsSticker ;
preloadNextGreetingsSticker ( ) ;
return result ;
}
2021-09-20 00:10:42 +02:00
protected void processLoadedRecentDocuments ( int type , ArrayList < TLRPC . Document > documents , boolean gif , int date , boolean replace ) {
2018-07-30 04:07:02 +02:00
if ( documents ! = null ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2019-07-18 15:01:39 +02:00
SQLiteDatabase database = getMessagesStorage ( ) . getDatabase ( ) ;
2019-01-23 18:03:33 +01:00
int maxCount ;
if ( gif ) {
2019-07-18 15:01:39 +02:00
maxCount = getMessagesController ( ) . maxRecentGifsCount ;
2019-01-23 18:03:33 +01:00
} else {
2021-04-14 03:44:46 +02:00
if ( type = = TYPE_GREETINGS ) {
maxCount = 200 ;
} else if ( type = = TYPE_FAVE ) {
2021-10-30 08:05:57 +02:00
maxCount = NekomuraConfig . unlimitedFavedStickers . Bool ( ) ? Integer . MAX_VALUE : getMessagesController ( ) . maxFaveStickersCount ;
2018-07-30 04:07:02 +02:00
} else {
2019-07-18 15:01:39 +02:00
maxCount = getMessagesController ( ) . maxRecentStickersCount ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
}
database . beginTransaction ( ) ;
2019-05-14 14:08:05 +02:00
2019-01-23 18:03:33 +01:00
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO web_recent_v3 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?) " ) ;
int count = documents . size ( ) ;
int cacheType ;
if ( gif ) {
cacheType = 2 ;
} else if ( type = = TYPE_IMAGE ) {
cacheType = 3 ;
} else if ( type = = TYPE_MASK ) {
cacheType = 4 ;
2021-04-14 03:44:46 +02:00
} else if ( type = = TYPE_GREETINGS ) {
cacheType = 6 ;
2019-01-23 18:03:33 +01:00
} else {
cacheType = 5 ;
}
2019-05-14 14:08:05 +02:00
if ( replace ) {
database . executeFast ( " DELETE FROM web_recent_v3 WHERE type = " + cacheType ) . stepThis ( ) . dispose ( ) ;
}
2019-01-23 18:03:33 +01:00
for ( int a = 0 ; a < count ; a + + ) {
if ( a = = maxCount ) {
break ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
TLRPC . Document document = documents . get ( a ) ;
state . requery ( ) ;
state . bindString ( 1 , " " + document . id ) ;
state . bindInteger ( 2 , cacheType ) ;
state . bindString ( 3 , " " ) ;
state . bindString ( 4 , " " ) ;
state . bindString ( 5 , " " ) ;
state . bindInteger ( 6 , 0 ) ;
state . bindInteger ( 7 , 0 ) ;
state . bindInteger ( 8 , 0 ) ;
state . bindInteger ( 9 , date ! = 0 ? date : count - a ) ;
NativeByteBuffer data = new NativeByteBuffer ( document . getObjectSize ( ) ) ;
document . serializeToStream ( data ) ;
state . bindByteBuffer ( 10 , data ) ;
state . step ( ) ;
2021-04-14 03:44:46 +02:00
data . reuse ( ) ;
2019-01-23 18:03:33 +01:00
}
state . dispose ( ) ;
database . commitTransaction ( ) ;
if ( documents . size ( ) > = maxCount ) {
database . beginTransaction ( ) ;
for ( int a = maxCount ; a < documents . size ( ) ; a + + ) {
database . executeFast ( " DELETE FROM web_recent_v3 WHERE id = ' " + documents . get ( a ) . id + " ' AND type = " + cacheType ) . stepThis ( ) . dispose ( ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
database . commitTransaction ( ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
if ( date = = 0 ) {
2019-01-23 18:03:33 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > {
SharedPreferences . Editor editor = MessagesController . getEmojiSettings ( currentAccount ) . edit ( ) ;
if ( gif ) {
loadingRecentGifs = false ;
recentGifsLoaded = true ;
editor . putLong ( " lastGifLoadTime " , System . currentTimeMillis ( ) ) . commit ( ) ;
} else {
loadingRecentStickers [ type ] = false ;
recentStickersLoaded [ type ] = true ;
if ( type = = TYPE_IMAGE ) {
editor . putLong ( " lastStickersLoadTime " , System . currentTimeMillis ( ) ) . commit ( ) ;
} else if ( type = = TYPE_MASK ) {
editor . putLong ( " lastStickersLoadTimeMask " , System . currentTimeMillis ( ) ) . commit ( ) ;
2021-04-14 03:44:46 +02:00
} else if ( type = = TYPE_GREETINGS ) {
editor . putLong ( " lastStickersLoadTimeGreet " , System . currentTimeMillis ( ) ) . commit ( ) ;
2018-07-30 04:07:02 +02:00
} else {
2019-01-23 18:03:33 +01:00
editor . putLong ( " lastStickersLoadTimeFavs " , System . currentTimeMillis ( ) ) . commit ( ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
}
if ( documents ! = null ) {
if ( gif ) {
recentGifs = documents ;
2018-07-30 04:07:02 +02:00
} else {
2019-01-23 18:03:33 +01:00
recentStickers [ type ] = documents ;
2018-07-30 04:07:02 +02:00
}
2021-04-14 03:44:46 +02:00
if ( type = = TYPE_GREETINGS ) {
preloadNextGreetingsSticker ( ) ;
}
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . recentDocumentsDidLoad , gif , type ) ;
2019-01-23 18:03:33 +01:00
} else {
2018-07-30 04:07:02 +02:00
}
} ) ;
}
}
2021-09-20 00:10:42 +02:00
public void reorderStickers ( int type , ArrayList < Long > order ) {
2019-01-23 18:03:33 +01:00
Collections . sort ( stickerSets [ type ] , ( lhs , rhs ) - > {
int index1 = order . indexOf ( lhs . set . id ) ;
int index2 = order . indexOf ( rhs . set . id ) ;
if ( index1 > index2 ) {
return 1 ;
} else if ( index1 < index2 ) {
return - 1 ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
return 0 ;
2018-07-30 04:07:02 +02:00
} ) ;
loadHash [ type ] = calcStickersHash ( stickerSets [ type ] ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . stickersDidLoad , type ) ;
2018-07-30 04:07:02 +02:00
loadStickers ( type , false , true ) ;
}
public void calcNewHash ( int type ) {
loadHash [ type ] = calcStickersHash ( stickerSets [ type ] ) ;
}
2021-09-20 00:10:42 +02:00
public void storeTempStickerSet ( TLRPC . TL_messages_stickerSet set ) {
2020-06-04 18:47:15 +02:00
stickerSetsById . put ( set . set . id , set ) ;
stickerSetsByName . put ( set . set . short_name , set ) ;
}
2021-09-20 00:10:42 +02:00
public void addNewStickerSet ( TLRPC . TL_messages_stickerSet set ) {
2018-07-30 04:07:02 +02:00
if ( stickerSetsById . indexOfKey ( set . set . id ) > = 0 | | stickerSetsByName . containsKey ( set . set . short_name ) ) {
return ;
}
int type = set . set . masks ? TYPE_MASK : TYPE_IMAGE ;
stickerSets [ type ] . add ( 0 , set ) ;
stickerSetsById . put ( set . set . id , set ) ;
installedStickerSetsById . put ( set . set . id , set ) ;
stickerSetsByName . put ( set . set . short_name , set ) ;
LongSparseArray < TLRPC . Document > stickersById = new LongSparseArray < > ( ) ;
for ( int a = 0 ; a < set . documents . size ( ) ; a + + ) {
TLRPC . Document document = set . documents . get ( a ) ;
stickersById . put ( document . id , document ) ;
}
for ( int a = 0 ; a < set . packs . size ( ) ; a + + ) {
TLRPC . TL_stickerPack stickerPack = set . packs . get ( a ) ;
stickerPack . emoticon = stickerPack . emoticon . replace ( " \ uFE0F " , " " ) ;
ArrayList < TLRPC . Document > arrayList = allStickers . get ( stickerPack . emoticon ) ;
if ( arrayList = = null ) {
arrayList = new ArrayList < > ( ) ;
allStickers . put ( stickerPack . emoticon , arrayList ) ;
}
for ( int c = 0 ; c < stickerPack . documents . size ( ) ; c + + ) {
Long id = stickerPack . documents . get ( c ) ;
if ( stickersByEmoji . indexOfKey ( id ) < 0 ) {
stickersByEmoji . put ( id , stickerPack . emoticon ) ;
}
TLRPC . Document sticker = stickersById . get ( id ) ;
if ( sticker ! = null ) {
arrayList . add ( sticker ) ;
}
}
}
loadHash [ type ] = calcStickersHash ( stickerSets [ type ] ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . stickersDidLoad , type ) ;
2018-07-30 04:07:02 +02:00
loadStickers ( type , false , true ) ;
}
public void loadFeaturedStickers ( boolean cache , boolean force ) {
2021-10-30 08:05:57 +02:00
if ( loadingFeaturedStickers | | NekomuraConfig . disableTrending . Bool ( ) ) {
2018-07-30 04:07:02 +02:00
return ;
}
loadingFeaturedStickers = true ;
if ( cache ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
ArrayList < TLRPC . StickerSetCovered > newStickerArray = null ;
ArrayList < Long > unread = new ArrayList < > ( ) ;
int date = 0 ;
2021-09-20 00:10:42 +02:00
long hash = 0 ;
2019-01-23 18:03:33 +01:00
SQLiteCursor cursor = null ;
try {
2019-07-18 15:01:39 +02:00
cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( " SELECT data, unread, date, hash FROM stickers_featured WHERE 1 " ) ;
2019-01-23 18:03:33 +01:00
if ( cursor . next ( ) ) {
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
newStickerArray = new ArrayList < > ( ) ;
int count = data . readInt32 ( false ) ;
for ( int a = 0 ; a < count ; a + + ) {
TLRPC . StickerSetCovered stickerSet = TLRPC . StickerSetCovered . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
newStickerArray . add ( stickerSet ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
data . reuse ( ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
data = cursor . byteBufferValue ( 1 ) ;
if ( data ! = null ) {
int count = data . readInt32 ( false ) ;
for ( int a = 0 ; a < count ; a + + ) {
unread . add ( data . readInt64 ( false ) ) ;
}
data . reuse ( ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
date = cursor . intValue ( 2 ) ;
hash = calcFeaturedStickersHash ( newStickerArray ) ;
}
} catch ( Throwable e ) {
FileLog . e ( e ) ;
} finally {
if ( cursor ! = null ) {
cursor . dispose ( ) ;
2018-07-30 04:07:02 +02:00
}
}
2019-01-23 18:03:33 +01:00
processLoadedFeaturedStickers ( newStickerArray , unread , true , date , hash ) ;
2018-07-30 04:07:02 +02:00
} ) ;
} else {
2021-09-20 00:10:42 +02:00
TLRPC . TL_messages_getFeaturedStickers req = new TLRPC . TL_messages_getFeaturedStickers ( ) ;
2018-07-30 04:07:02 +02:00
req . hash = force ? 0 : loadFeaturedHash ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > AndroidUtilities . runOnUIThread ( ( ) - > {
2019-01-23 18:03:33 +01:00
if ( response instanceof TLRPC . TL_messages_featuredStickers ) {
TLRPC . TL_messages_featuredStickers res = ( TLRPC . TL_messages_featuredStickers ) response ;
processLoadedFeaturedStickers ( res . sets , res . unread , false , ( int ) ( System . currentTimeMillis ( ) / 1000 ) , res . hash ) ;
} else {
processLoadedFeaturedStickers ( null , null , false , ( int ) ( System . currentTimeMillis ( ) / 1000 ) , req . hash ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} ) ) ;
2021-02-04 18:59:00 +01:00
}
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
private void processLoadedFeaturedStickers ( ArrayList < TLRPC . StickerSetCovered > res , ArrayList < Long > unreadStickers , boolean cache , int date , long hash ) {
2019-01-23 18:03:33 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > {
loadingFeaturedStickers = false ;
featuredStickersLoaded = true ;
2018-07-30 04:07:02 +02:00
} ) ;
2019-01-23 18:03:33 +01:00
Utilities . stageQueue . postRunnable ( ( ) - > {
if ( cache & & ( res = = null | | Math . abs ( System . currentTimeMillis ( ) / 1000 - date ) > = 60 * 60 ) | | ! cache & & res = = null & & hash = = 0 ) {
AndroidUtilities . runOnUIThread ( ( ) - > {
if ( res ! = null & & hash ! = 0 ) {
loadFeaturedHash = hash ;
}
loadFeaturedStickers ( false , false ) ;
} , res = = null & & ! cache ? 1000 : 0 ) ;
if ( res = = null ) {
return ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
}
if ( res ! = null ) {
try {
2021-09-20 00:10:42 +02:00
ArrayList < TLRPC . StickerSetCovered > stickerSetsNew = new ArrayList < > ( ) ;
LongSparseArray < TLRPC . StickerSetCovered > stickerSetsByIdNew = new LongSparseArray < > ( ) ;
2019-01-23 18:03:33 +01:00
for ( int a = 0 ; a < res . size ( ) ; a + + ) {
TLRPC . StickerSetCovered stickerSet = res . get ( a ) ;
stickerSetsNew . add ( stickerSet ) ;
stickerSetsByIdNew . put ( stickerSet . set . id , stickerSet ) ;
}
if ( ! cache ) {
putFeaturedStickersToCache ( stickerSetsNew , unreadStickers , date , hash ) ;
}
AndroidUtilities . runOnUIThread ( ( ) - > {
unreadStickerSets = unreadStickers ;
featuredStickerSetsById = stickerSetsByIdNew ;
featuredStickerSets = stickerSetsNew ;
loadFeaturedHash = hash ;
loadFeaturedDate = date ;
loadStickers ( TYPE_FEATURED , true , false ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . featuredStickersDidLoad ) ;
2018-07-30 04:07:02 +02:00
} ) ;
2019-01-23 18:03:33 +01:00
} catch ( Throwable e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
} else {
2019-01-23 18:03:33 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > loadFeaturedDate = date ) ;
putFeaturedStickersToCache ( null , null , date , 0 ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2021-09-20 00:10:42 +02:00
private void putFeaturedStickersToCache ( ArrayList < TLRPC . StickerSetCovered > stickers , ArrayList < Long > unreadStickers , int date , long hash ) {
ArrayList < TLRPC . StickerSetCovered > stickersFinal = stickers ! = null ? new ArrayList < > ( stickers ) : null ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
if ( stickersFinal ! = null ) {
2019-07-18 15:01:39 +02:00
SQLitePreparedStatement state = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " REPLACE INTO stickers_featured VALUES(?, ?, ?, ?, ?) " ) ;
2019-01-23 18:03:33 +01:00
state . requery ( ) ;
int size = 4 ;
for ( int a = 0 ; a < stickersFinal . size ( ) ; a + + ) {
size + = stickersFinal . get ( a ) . getObjectSize ( ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
NativeByteBuffer data = new NativeByteBuffer ( size ) ;
NativeByteBuffer data2 = new NativeByteBuffer ( 4 + unreadStickers . size ( ) * 8 ) ;
data . writeInt32 ( stickersFinal . size ( ) ) ;
for ( int a = 0 ; a < stickersFinal . size ( ) ; a + + ) {
stickersFinal . get ( a ) . serializeToStream ( data ) ;
}
data2 . writeInt32 ( unreadStickers . size ( ) ) ;
for ( int a = 0 ; a < unreadStickers . size ( ) ; a + + ) {
data2 . writeInt64 ( unreadStickers . get ( a ) ) ;
}
state . bindInteger ( 1 , 1 ) ;
state . bindByteBuffer ( 2 , data ) ;
state . bindByteBuffer ( 3 , data2 ) ;
state . bindInteger ( 4 , date ) ;
2021-09-20 00:10:42 +02:00
state . bindLong ( 5 , hash ) ;
2019-01-23 18:03:33 +01:00
state . step ( ) ;
data . reuse ( ) ;
data2 . reuse ( ) ;
state . dispose ( ) ;
} else {
2019-07-18 15:01:39 +02:00
SQLitePreparedStatement state = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " UPDATE stickers_featured SET date = ? " ) ;
2019-01-23 18:03:33 +01:00
state . requery ( ) ;
state . bindInteger ( 1 , date ) ;
state . step ( ) ;
state . dispose ( ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2021-09-20 00:10:42 +02:00
private long calcFeaturedStickersHash ( ArrayList < TLRPC . StickerSetCovered > sets ) {
if ( sets = = null | | sets . isEmpty ( ) ) {
return 0 ;
}
2018-07-30 04:07:02 +02:00
long acc = 0 ;
for ( int a = 0 ; a < sets . size ( ) ; a + + ) {
TLRPC . StickerSet set = sets . get ( a ) . set ;
if ( set . archived ) {
continue ;
}
2021-09-20 00:10:42 +02:00
acc = calcHash ( acc , set . id ) ;
2018-07-30 04:07:02 +02:00
if ( unreadStickerSets . contains ( set . id ) ) {
2021-09-20 00:10:42 +02:00
acc = calcHash ( acc , 1 ) ;
2018-07-30 04:07:02 +02:00
}
}
2021-09-20 00:10:42 +02:00
return acc ;
}
public static long calcHash ( long hash , long id ) {
hash ^ = id > > 21 ;
hash ^ = id < < 35 ;
hash ^ = id > > 4 ;
return hash + id ;
2018-07-30 04:07:02 +02:00
}
public void markFaturedStickersAsRead ( boolean query ) {
if ( unreadStickerSets . isEmpty ( ) ) {
return ;
}
unreadStickerSets . clear ( ) ;
loadFeaturedHash = calcFeaturedStickersHash ( featuredStickerSets ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . featuredStickersDidLoad ) ;
2018-07-30 04:07:02 +02:00
putFeaturedStickersToCache ( featuredStickerSets , unreadStickerSets , loadFeaturedDate , loadFeaturedHash ) ;
if ( query ) {
TLRPC . TL_messages_readFeaturedStickers req = new TLRPC . TL_messages_readFeaturedStickers ( ) ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2018-07-30 04:07:02 +02:00
} ) ;
}
}
2021-09-20 00:10:42 +02:00
public long getFeaturesStickersHashWithoutUnread ( ) {
2018-07-30 04:07:02 +02:00
long acc = 0 ;
for ( int a = 0 ; a < featuredStickerSets . size ( ) ; a + + ) {
TLRPC . StickerSet set = featuredStickerSets . get ( a ) . set ;
if ( set . archived ) {
continue ;
}
2021-09-20 00:10:42 +02:00
acc = calcHash ( acc , set . id ) ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
return acc ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
public void markFaturedStickersByIdAsRead ( long id ) {
2018-07-30 04:07:02 +02:00
if ( ! unreadStickerSets . contains ( id ) | | readingStickerSets . contains ( id ) ) {
return ;
}
readingStickerSets . add ( id ) ;
TLRPC . TL_messages_readFeaturedStickers req = new TLRPC . TL_messages_readFeaturedStickers ( ) ;
req . id . add ( id ) ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2018-07-30 04:07:02 +02:00
} ) ;
2019-01-23 18:03:33 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > {
unreadStickerSets . remove ( id ) ;
readingStickerSets . remove ( id ) ;
loadFeaturedHash = calcFeaturedStickersHash ( featuredStickerSets ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . featuredStickersDidLoad ) ;
2019-01-23 18:03:33 +01:00
putFeaturedStickersToCache ( featuredStickerSets , unreadStickerSets , loadFeaturedDate , loadFeaturedHash ) ;
2018-07-30 04:07:02 +02:00
} , 1000 ) ;
}
public int getArchivedStickersCount ( int type ) {
return archivedStickersCount [ type ] ;
}
2020-06-04 18:47:15 +02:00
public void verifyAnimatedStickerMessage ( TLRPC . Message message ) {
verifyAnimatedStickerMessage ( message , false ) ;
}
public void verifyAnimatedStickerMessage ( TLRPC . Message message , boolean safe ) {
if ( message = = null ) {
return ;
}
TLRPC . Document document = MessageObject . getDocument ( message ) ;
String name = MessageObject . getStickerSetName ( document ) ;
if ( TextUtils . isEmpty ( name ) ) {
return ;
}
TLRPC . TL_messages_stickerSet stickerSet = stickerSetsByName . get ( name ) ;
if ( stickerSet ! = null ) {
for ( int a = 0 , N = stickerSet . documents . size ( ) ; a < N ; a + + ) {
TLRPC . Document sticker = stickerSet . documents . get ( a ) ;
if ( sticker . id = = document . id & & sticker . dc_id = = document . dc_id ) {
message . stickerVerified = 1 ;
break ;
}
}
return ;
}
if ( safe ) {
AndroidUtilities . runOnUIThread ( ( ) - > verifyAnimatedStickerMessageInternal ( message , name ) ) ;
} else {
verifyAnimatedStickerMessageInternal ( message , name ) ;
}
}
private void verifyAnimatedStickerMessageInternal ( TLRPC . Message message , String name ) {
ArrayList < TLRPC . Message > messages = verifyingMessages . get ( name ) ;
if ( messages = = null ) {
messages = new ArrayList < > ( ) ;
verifyingMessages . put ( name , messages ) ;
}
messages . add ( message ) ;
TLRPC . TL_messages_getStickerSet req = new TLRPC . TL_messages_getStickerSet ( ) ;
req . stickerset = MessageObject . getInputStickerSet ( message ) ;
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > AndroidUtilities . runOnUIThread ( ( ) - > {
ArrayList < TLRPC . Message > arrayList = verifyingMessages . get ( name ) ;
if ( response ! = null ) {
TLRPC . TL_messages_stickerSet set = ( TLRPC . TL_messages_stickerSet ) response ;
storeTempStickerSet ( set ) ;
for ( int b = 0 , N2 = arrayList . size ( ) ; b < N2 ; b + + ) {
TLRPC . Message m = arrayList . get ( b ) ;
TLRPC . Document d = MessageObject . getDocument ( m ) ;
for ( int a = 0 , N = set . documents . size ( ) ; a < N ; a + + ) {
TLRPC . Document sticker = set . documents . get ( a ) ;
if ( sticker . id = = d . id & & sticker . dc_id = = d . dc_id ) {
m . stickerVerified = 1 ;
break ;
}
}
if ( m . stickerVerified = = 0 ) {
m . stickerVerified = 2 ;
}
}
} else {
for ( int b = 0 , N2 = arrayList . size ( ) ; b < N2 ; b + + ) {
arrayList . get ( b ) . stickerVerified = 2 ;
}
}
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . didVerifyMessagesStickers , arrayList ) ;
getMessagesStorage ( ) . updateMessageVerifyFlags ( arrayList ) ;
} ) ) ;
}
2021-09-20 00:10:42 +02:00
public void loadArchivedStickersCount ( int type , boolean cache ) {
2018-07-30 04:07:02 +02:00
if ( cache ) {
SharedPreferences preferences = MessagesController . getNotificationsSettings ( currentAccount ) ;
int count = preferences . getInt ( " archivedStickersCount " + type , - 1 ) ;
if ( count = = - 1 ) {
loadArchivedStickersCount ( type , false ) ;
} else {
archivedStickersCount [ type ] = count ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . archivedStickersCountDidLoad , type ) ;
2018-07-30 04:07:02 +02:00
}
2021-04-11 02:53:15 +02:00
} else if ( ! getUserConfig ( ) . getCurrentUser ( ) . bot ) {
2018-07-30 04:07:02 +02:00
TLRPC . TL_messages_getArchivedStickers req = new TLRPC . TL_messages_getArchivedStickers ( ) ;
req . limit = 0 ;
req . masks = type = = TYPE_MASK ;
2019-07-18 15:01:39 +02:00
int reqId = getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > AndroidUtilities . runOnUIThread ( ( ) - > {
2019-01-23 18:03:33 +01:00
if ( error = = null ) {
TLRPC . TL_messages_archivedStickers res = ( TLRPC . TL_messages_archivedStickers ) response ;
archivedStickersCount [ type ] = res . count ;
SharedPreferences preferences = MessagesController . getNotificationsSettings ( currentAccount ) ;
preferences . edit ( ) . putInt ( " archivedStickersCount " + type , res . count ) . commit ( ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . archivedStickersCountDidLoad , type ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} ) ) ;
2018-07-30 04:07:02 +02:00
}
}
2021-09-20 00:10:42 +02:00
private void processLoadStickersResponse ( int type , TLRPC . TL_messages_allStickers res ) {
ArrayList < TLRPC . TL_messages_stickerSet > newStickerArray = new ArrayList < > ( ) ;
2018-07-30 04:07:02 +02:00
if ( res . sets . isEmpty ( ) ) {
processLoadedStickers ( type , newStickerArray , false , ( int ) ( System . currentTimeMillis ( ) / 1000 ) , res . hash ) ;
} else {
2021-09-20 00:10:42 +02:00
LongSparseArray < TLRPC . TL_messages_stickerSet > newStickerSets = new LongSparseArray < > ( ) ;
2021-03-09 12:40:50 +01:00
// NekoX: Pin Sticker
2021-10-30 08:05:57 +02:00
if ( NekomuraConfig . enableStickerPin . Bool ( ) & & type = = MediaDataController . TYPE_IMAGE ) {
2021-03-09 12:40:50 +01:00
PinnedStickerHelper ins = PinnedStickerHelper . getInstance ( UserConfig . selectedAccount ) ;
if ( ins . reorderPinnedStickersForSS ( res . sets , true ) )
AndroidUtilities . runOnUIThread ( ( ) - > {
if ( BuildVars . DEBUG_VERSION ) {
Toast . makeText ( ApplicationLoader . applicationContext , " Reorder loaded stickers, sync now. Pinned: " + ins . pinnedList . size ( ) , Toast . LENGTH_SHORT ) . show ( ) ;
}
ins . sendOrderSyncForSS ( res . sets ) ;
} ) ;
}
for ( int a = 0 ; a < res . sets . size ( ) ; a + + ) { // reload all sitckers here
2021-09-20 00:10:42 +02:00
TLRPC . StickerSet stickerSet = res . sets . get ( a ) ;
2018-07-30 04:07:02 +02:00
TLRPC . TL_messages_stickerSet oldSet = stickerSetsById . get ( stickerSet . id ) ;
if ( oldSet ! = null & & oldSet . set . hash = = stickerSet . hash ) {
oldSet . set . archived = stickerSet . archived ;
oldSet . set . installed = stickerSet . installed ;
oldSet . set . official = stickerSet . official ;
newStickerSets . put ( oldSet . set . id , oldSet ) ;
newStickerArray . add ( oldSet ) ;
if ( newStickerSets . size ( ) = = res . sets . size ( ) ) {
processLoadedStickers ( type , newStickerArray , false , ( int ) ( System . currentTimeMillis ( ) / 1000 ) , res . hash ) ;
}
continue ;
}
2021-03-09 12:40:50 +01:00
// oldset == null, new sticker comes here
2018-07-30 04:07:02 +02:00
newStickerArray . add ( null ) ;
2021-09-20 00:10:42 +02:00
int index = a ;
2018-07-30 04:07:02 +02:00
TLRPC . TL_messages_getStickerSet req = new TLRPC . TL_messages_getStickerSet ( ) ;
req . stickerset = new TLRPC . TL_inputStickerSetID ( ) ;
req . stickerset . id = stickerSet . id ;
req . stickerset . access_hash = stickerSet . access_hash ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > AndroidUtilities . runOnUIThread ( ( ) - > {
2019-01-23 18:03:33 +01:00
TLRPC . TL_messages_stickerSet res1 = ( TLRPC . TL_messages_stickerSet ) response ;
newStickerArray . set ( index , res1 ) ;
newStickerSets . put ( stickerSet . id , res1 ) ;
if ( newStickerSets . size ( ) = = res . sets . size ( ) ) {
for ( int a1 = 0 ; a1 < newStickerArray . size ( ) ; a1 + + ) {
if ( newStickerArray . get ( a1 ) = = null ) {
newStickerArray . remove ( a1 ) ;
2019-05-14 14:08:05 +02:00
a1 - - ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
}
processLoadedStickers ( type , newStickerArray , false , ( int ) ( System . currentTimeMillis ( ) / 1000 ) , res . hash ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} ) ) ;
2018-07-30 04:07:02 +02:00
}
}
}
2020-09-30 15:48:47 +02:00
public void loadStickersByEmojiOrName ( String name , boolean isEmoji , boolean cache ) {
if ( loadingDiceStickerSets . contains ( name ) | | isEmoji & & diceStickerSetsByEmoji . get ( name ) ! = null ) {
2020-04-24 11:21:58 +02:00
return ;
}
2020-09-30 15:48:47 +02:00
loadingDiceStickerSets . add ( name ) ;
2020-04-24 11:21:58 +02:00
if ( cache ) {
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
TLRPC . TL_messages_stickerSet stickerSet = null ;
int date = 0 ;
SQLiteCursor cursor = null ;
try {
2020-09-30 15:48:47 +02:00
cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( " SELECT data, date FROM stickers_dice WHERE emoji = ? " , name ) ;
2020-04-24 11:21:58 +02:00
if ( cursor . next ( ) ) {
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
stickerSet = TLRPC . TL_messages_stickerSet . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
data . reuse ( ) ;
}
date = cursor . intValue ( 1 ) ;
}
} catch ( Throwable e ) {
FileLog . e ( e ) ;
} finally {
if ( cursor ! = null ) {
cursor . dispose ( ) ;
}
}
2020-09-30 15:48:47 +02:00
processLoadedDiceStickers ( name , isEmoji , stickerSet , true , date ) ;
2020-04-24 11:21:58 +02:00
} ) ;
} else {
TLRPC . TL_messages_getStickerSet req = new TLRPC . TL_messages_getStickerSet ( ) ;
2020-09-30 15:48:47 +02:00
if ( isEmoji ) {
TLRPC . TL_inputStickerSetDice inputStickerSetDice = new TLRPC . TL_inputStickerSetDice ( ) ;
inputStickerSetDice . emoticon = name ;
req . stickerset = inputStickerSetDice ;
} else {
TLRPC . TL_inputStickerSetShortName inputStickerSetShortName = new TLRPC . TL_inputStickerSetShortName ( ) ;
inputStickerSetShortName . short_name = name ;
req . stickerset = inputStickerSetShortName ;
}
2020-04-24 11:21:58 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > AndroidUtilities . runOnUIThread ( ( ) - > {
2021-01-30 07:18:23 +01:00
if ( BuildConfig . DEBUG & & error ! = null ) { //supress test backend warning
return ;
}
2020-04-24 11:21:58 +02:00
if ( response instanceof TLRPC . TL_messages_stickerSet ) {
2020-09-30 15:48:47 +02:00
processLoadedDiceStickers ( name , isEmoji , ( TLRPC . TL_messages_stickerSet ) response , false , ( int ) ( System . currentTimeMillis ( ) / 1000 ) ) ;
2020-04-24 11:21:58 +02:00
} else {
2020-09-30 15:48:47 +02:00
processLoadedDiceStickers ( name , isEmoji , null , false , ( int ) ( System . currentTimeMillis ( ) / 1000 ) ) ;
2020-04-24 11:21:58 +02:00
}
} ) ) ;
}
}
2021-09-20 00:10:42 +02:00
private void processLoadedDiceStickers ( String name , boolean isEmoji , TLRPC . TL_messages_stickerSet res , boolean cache , int date ) {
2020-09-30 15:48:47 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > loadingDiceStickerSets . remove ( name ) ) ;
2020-04-24 11:21:58 +02:00
Utilities . stageQueue . postRunnable ( ( ) - > {
if ( cache & & ( res = = null | | Math . abs ( System . currentTimeMillis ( ) / 1000 - date ) > = 60 * 60 * 24 ) | | ! cache & & res = = null ) {
2020-09-30 15:48:47 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > loadStickersByEmojiOrName ( name , isEmoji , false ) , res = = null & & ! cache ? 1000 : 0 ) ;
2020-04-24 11:21:58 +02:00
if ( res = = null ) {
return ;
}
}
if ( res ! = null ) {
if ( ! cache ) {
2020-09-30 15:48:47 +02:00
putDiceStickersToCache ( name , res , date ) ;
2020-04-24 11:21:58 +02:00
}
AndroidUtilities . runOnUIThread ( ( ) - > {
2020-09-30 15:48:47 +02:00
diceStickerSetsByEmoji . put ( name , res ) ;
diceEmojiStickerSetsById . put ( res . set . id , name ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . diceStickersDidLoad , name ) ;
2020-04-24 11:21:58 +02:00
} ) ;
} else if ( ! cache ) {
2020-09-30 15:48:47 +02:00
putDiceStickersToCache ( name , null , date ) ;
2020-04-24 11:21:58 +02:00
}
} ) ;
}
2021-09-20 00:10:42 +02:00
private void putDiceStickersToCache ( String emoji , TLRPC . TL_messages_stickerSet stickers , int date ) {
2020-04-24 11:21:58 +02:00
if ( TextUtils . isEmpty ( emoji ) ) {
return ;
}
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
try {
if ( stickers ! = null ) {
SQLitePreparedStatement state = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " REPLACE INTO stickers_dice VALUES(?, ?, ?) " ) ;
state . requery ( ) ;
NativeByteBuffer data = new NativeByteBuffer ( stickers . getObjectSize ( ) ) ;
stickers . serializeToStream ( data ) ;
state . bindString ( 1 , emoji ) ;
state . bindByteBuffer ( 2 , data ) ;
state . bindInteger ( 3 , date ) ;
state . step ( ) ;
data . reuse ( ) ;
state . dispose ( ) ;
} else {
SQLitePreparedStatement state = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " UPDATE stickers_dice SET date = ? " ) ;
state . requery ( ) ;
state . bindInteger ( 1 , date ) ;
state . step ( ) ;
state . dispose ( ) ;
}
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
} ) ;
}
2021-09-20 00:10:42 +02:00
public void loadStickers ( int type , boolean cache , boolean useHash ) {
2020-03-30 14:00:09 +02:00
loadStickers ( type , cache , useHash , false ) ;
}
2021-09-20 00:10:42 +02:00
public void loadStickers ( int type , boolean cache , boolean force , boolean scheduleIfLoading ) {
2018-07-30 04:07:02 +02:00
if ( loadingStickers [ type ] ) {
2020-03-30 14:00:09 +02:00
if ( scheduleIfLoading ) {
scheduledLoadStickers [ type ] = ( ) - > loadStickers ( type , false , force , false ) ;
}
2018-07-30 04:07:02 +02:00
return ;
}
if ( type = = TYPE_FEATURED ) {
2019-07-18 15:01:39 +02:00
if ( featuredStickerSets . isEmpty ( ) | | ! getMessagesController ( ) . preloadFeaturedStickers ) {
2018-07-30 04:07:02 +02:00
return ;
}
2019-08-22 01:53:26 +02:00
} else if ( type ! = TYPE_EMOJI ) {
2018-07-30 04:07:02 +02:00
loadArchivedStickersCount ( type , cache ) ;
}
loadingStickers [ type ] = true ;
if ( cache ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
ArrayList < TLRPC . TL_messages_stickerSet > newStickerArray = null ;
int date = 0 ;
2021-09-20 00:10:42 +02:00
long hash = 0 ;
2019-01-23 18:03:33 +01:00
SQLiteCursor cursor = null ;
try {
2019-07-18 15:01:39 +02:00
cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( " SELECT data, date, hash FROM stickers_v2 WHERE id = " + ( type + 1 ) ) ;
2019-01-23 18:03:33 +01:00
if ( cursor . next ( ) ) {
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
newStickerArray = new ArrayList < > ( ) ;
int count = data . readInt32 ( false ) ;
for ( int a = 0 ; a < count ; a + + ) {
TLRPC . TL_messages_stickerSet stickerSet = TLRPC . TL_messages_stickerSet . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
newStickerArray . add ( stickerSet ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
data . reuse ( ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
date = cursor . intValue ( 1 ) ;
hash = calcStickersHash ( newStickerArray ) ;
}
} catch ( Throwable e ) {
FileLog . e ( e ) ;
} finally {
if ( cursor ! = null ) {
cursor . dispose ( ) ;
2018-07-30 04:07:02 +02:00
}
}
2019-01-23 18:03:33 +01:00
processLoadedStickers ( type , newStickerArray , true , date , hash ) ;
2018-07-30 04:07:02 +02:00
} ) ;
2021-04-11 02:53:15 +02:00
} else if ( ! getUserConfig ( ) . getCurrentUser ( ) . bot ) {
2018-07-30 04:07:02 +02:00
if ( type = = TYPE_FEATURED ) {
TLRPC . TL_messages_allStickers response = new TLRPC . TL_messages_allStickers ( ) ;
response . hash = loadFeaturedHash ;
for ( int a = 0 , size = featuredStickerSets . size ( ) ; a < size ; a + + ) {
response . sets . add ( featuredStickerSets . get ( a ) . set ) ;
}
processLoadStickersResponse ( type , response ) ;
2019-08-22 01:53:26 +02:00
} else if ( type = = TYPE_EMOJI ) {
TLRPC . TL_messages_getStickerSet req = new TLRPC . TL_messages_getStickerSet ( ) ;
req . stickerset = new TLRPC . TL_inputStickerSetAnimatedEmoji ( ) ;
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
if ( response instanceof TLRPC . TL_messages_stickerSet ) {
2021-09-20 00:10:42 +02:00
ArrayList < TLRPC . TL_messages_stickerSet > newStickerArray = new ArrayList < > ( ) ;
2019-08-22 01:53:26 +02:00
newStickerArray . add ( ( TLRPC . TL_messages_stickerSet ) response ) ;
processLoadedStickers ( type , newStickerArray , false , ( int ) ( System . currentTimeMillis ( ) / 1000 ) , calcStickersHash ( newStickerArray ) ) ;
} else {
processLoadedStickers ( type , null , false , ( int ) ( System . currentTimeMillis ( ) / 1000 ) , 0 ) ;
}
} ) ;
2018-07-30 04:07:02 +02:00
} else {
2019-08-22 01:53:26 +02:00
TLObject req ;
2021-09-20 00:10:42 +02:00
long hash ;
2019-08-22 01:53:26 +02:00
if ( type = = TYPE_IMAGE ) {
req = new TLRPC . TL_messages_getAllStickers ( ) ;
hash = ( ( TLRPC . TL_messages_getAllStickers ) req ) . hash = force ? 0 : loadHash [ type ] ;
2019-01-23 18:03:33 +01:00
} else {
2019-08-22 01:53:26 +02:00
req = new TLRPC . TL_messages_getMaskStickers ( ) ;
hash = ( ( TLRPC . TL_messages_getMaskStickers ) req ) . hash = force ? 0 : loadHash [ type ] ;
2018-07-30 04:07:02 +02:00
}
2019-08-22 01:53:26 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > AndroidUtilities . runOnUIThread ( ( ) - > {
if ( response instanceof TLRPC . TL_messages_allStickers ) {
processLoadStickersResponse ( type , ( TLRPC . TL_messages_allStickers ) response ) ;
} else {
processLoadedStickers ( type , null , false , ( int ) ( System . currentTimeMillis ( ) / 1000 ) , hash ) ;
}
} ) ) ;
}
2018-07-30 04:07:02 +02:00
}
}
2021-09-20 00:10:42 +02:00
private void putStickersToCache ( int type , ArrayList < TLRPC . TL_messages_stickerSet > stickers , int date , long hash ) {
ArrayList < TLRPC . TL_messages_stickerSet > stickersFinal = stickers ! = null ? new ArrayList < > ( stickers ) : null ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
if ( stickersFinal ! = null ) {
2019-07-18 15:01:39 +02:00
SQLitePreparedStatement state = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " REPLACE INTO stickers_v2 VALUES(?, ?, ?, ?) " ) ;
2019-01-23 18:03:33 +01:00
state . requery ( ) ;
int size = 4 ;
for ( int a = 0 ; a < stickersFinal . size ( ) ; a + + ) {
size + = stickersFinal . get ( a ) . getObjectSize ( ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
NativeByteBuffer data = new NativeByteBuffer ( size ) ;
data . writeInt32 ( stickersFinal . size ( ) ) ;
for ( int a = 0 ; a < stickersFinal . size ( ) ; a + + ) {
stickersFinal . get ( a ) . serializeToStream ( data ) ;
}
state . bindInteger ( 1 , type + 1 ) ;
state . bindByteBuffer ( 2 , data ) ;
state . bindInteger ( 3 , date ) ;
2021-09-20 00:10:42 +02:00
state . bindLong ( 4 , hash ) ;
2019-01-23 18:03:33 +01:00
state . step ( ) ;
data . reuse ( ) ;
state . dispose ( ) ;
} else {
2019-07-18 15:01:39 +02:00
SQLitePreparedStatement state = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " UPDATE stickers_v2 SET date = ? " ) ;
2019-01-23 18:03:33 +01:00
state . requery ( ) ;
2021-09-20 00:10:42 +02:00
state . bindLong ( 1 , date ) ;
2019-01-23 18:03:33 +01:00
state . step ( ) ;
state . dispose ( ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
public String getStickerSetName ( long setId ) {
TLRPC . TL_messages_stickerSet stickerSet = stickerSetsById . get ( setId ) ;
if ( stickerSet ! = null ) {
return stickerSet . set . short_name ;
}
TLRPC . StickerSetCovered stickerSetCovered = featuredStickerSetsById . get ( setId ) ;
if ( stickerSetCovered ! = null ) {
return stickerSetCovered . set . short_name ;
}
return null ;
}
public static long getStickerSetId ( TLRPC . Document document ) {
for ( int a = 0 ; a < document . attributes . size ( ) ; a + + ) {
TLRPC . DocumentAttribute attribute = document . attributes . get ( a ) ;
if ( attribute instanceof TLRPC . TL_documentAttributeSticker ) {
if ( attribute . stickerset instanceof TLRPC . TL_inputStickerSetID ) {
return attribute . stickerset . id ;
}
break ;
}
}
return - 1 ;
}
2019-05-14 14:08:05 +02:00
public static TLRPC . InputStickerSet getInputStickerSet ( TLRPC . Document document ) {
for ( int a = 0 ; a < document . attributes . size ( ) ; a + + ) {
TLRPC . DocumentAttribute attribute = document . attributes . get ( a ) ;
if ( attribute instanceof TLRPC . TL_documentAttributeSticker ) {
if ( attribute . stickerset instanceof TLRPC . TL_inputStickerSetEmpty ) {
return null ;
}
return attribute . stickerset ;
}
}
return null ;
}
2021-09-20 00:10:42 +02:00
private static long calcStickersHash ( ArrayList < TLRPC . TL_messages_stickerSet > sets ) {
2018-07-30 04:07:02 +02:00
long acc = 0 ;
for ( int a = 0 ; a < sets . size ( ) ; a + + ) {
TLRPC . StickerSet set = sets . get ( a ) . set ;
if ( set . archived ) {
continue ;
}
2021-09-20 00:10:42 +02:00
acc = calcHash ( acc , set . hash ) ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
return acc ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
private void processLoadedStickers ( int type , ArrayList < TLRPC . TL_messages_stickerSet > res , boolean cache , int date , long hash ) {
2019-01-23 18:03:33 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > {
loadingStickers [ type ] = false ;
stickersLoaded [ type ] = true ;
2020-03-30 14:00:09 +02:00
if ( scheduledLoadStickers [ type ] ! = null ) {
scheduledLoadStickers [ type ] . run ( ) ;
scheduledLoadStickers [ type ] = null ;
}
2018-07-30 04:07:02 +02:00
} ) ;
2019-01-23 18:03:33 +01:00
Utilities . stageQueue . postRunnable ( ( ) - > {
if ( cache & & ( res = = null | | Math . abs ( System . currentTimeMillis ( ) / 1000 - date ) > = 60 * 60 ) | | ! cache & & res = = null & & hash = = 0 ) {
AndroidUtilities . runOnUIThread ( ( ) - > {
if ( res ! = null & & hash ! = 0 ) {
loadHash [ type ] = hash ;
}
loadStickers ( type , false , false ) ;
} , res = = null & & ! cache ? 1000 : 0 ) ;
if ( res = = null ) {
return ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
}
if ( res ! = null ) {
try {
2021-09-20 00:10:42 +02:00
ArrayList < TLRPC . TL_messages_stickerSet > stickerSetsNew = new ArrayList < > ( ) ;
LongSparseArray < TLRPC . TL_messages_stickerSet > stickerSetsByIdNew = new LongSparseArray < > ( ) ;
HashMap < String , TLRPC . TL_messages_stickerSet > stickerSetsByNameNew = new HashMap < > ( ) ;
LongSparseArray < String > stickersByEmojiNew = new LongSparseArray < > ( ) ;
LongSparseArray < TLRPC . Document > stickersByIdNew = new LongSparseArray < > ( ) ;
HashMap < String , ArrayList < TLRPC . Document > > allStickersNew = new HashMap < > ( ) ;
2019-01-23 18:03:33 +01:00
for ( int a = 0 ; a < res . size ( ) ; a + + ) {
TLRPC . TL_messages_stickerSet stickerSet = res . get ( a ) ;
2020-03-30 14:00:09 +02:00
if ( stickerSet = = null | | removingStickerSetsUndos . indexOfKey ( stickerSet . set . id ) > = 0 ) {
2019-01-23 18:03:33 +01:00
continue ;
}
stickerSetsNew . add ( stickerSet ) ;
stickerSetsByIdNew . put ( stickerSet . set . id , stickerSet ) ;
stickerSetsByNameNew . put ( stickerSet . set . short_name , stickerSet ) ;
for ( int b = 0 ; b < stickerSet . documents . size ( ) ; b + + ) {
TLRPC . Document document = stickerSet . documents . get ( b ) ;
if ( document = = null | | document instanceof TLRPC . TL_documentEmpty ) {
2018-07-30 04:07:02 +02:00
continue ;
}
2019-01-23 18:03:33 +01:00
stickersByIdNew . put ( document . id , document ) ;
}
if ( ! stickerSet . set . archived ) {
for ( int b = 0 ; b < stickerSet . packs . size ( ) ; b + + ) {
TLRPC . TL_stickerPack stickerPack = stickerSet . packs . get ( b ) ;
if ( stickerPack = = null | | stickerPack . emoticon = = null ) {
2018-07-30 04:07:02 +02:00
continue ;
}
2019-01-23 18:03:33 +01:00
stickerPack . emoticon = stickerPack . emoticon . replace ( " \ uFE0F " , " " ) ;
ArrayList < TLRPC . Document > arrayList = allStickersNew . get ( stickerPack . emoticon ) ;
if ( arrayList = = null ) {
arrayList = new ArrayList < > ( ) ;
allStickersNew . put ( stickerPack . emoticon , arrayList ) ;
}
for ( int c = 0 ; c < stickerPack . documents . size ( ) ; c + + ) {
Long id = stickerPack . documents . get ( c ) ;
if ( stickersByEmojiNew . indexOfKey ( id ) < 0 ) {
stickersByEmojiNew . put ( id , stickerPack . emoticon ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
TLRPC . Document sticker = stickersByIdNew . get ( id ) ;
if ( sticker ! = null ) {
arrayList . add ( sticker ) ;
2018-07-30 04:07:02 +02:00
}
}
}
}
2019-01-23 18:03:33 +01:00
}
2018-07-30 04:07:02 +02:00
2019-01-23 18:03:33 +01:00
if ( ! cache ) {
putStickersToCache ( type , stickerSetsNew , date , hash ) ;
}
AndroidUtilities . runOnUIThread ( ( ) - > {
for ( int a = 0 ; a < stickerSets [ type ] . size ( ) ; a + + ) {
TLRPC . StickerSet set = stickerSets [ type ] . get ( a ) . set ;
stickerSetsById . remove ( set . id ) ;
stickerSetsByName . remove ( set . short_name ) ;
2019-08-22 01:53:26 +02:00
if ( type ! = TYPE_FEATURED & & type ! = TYPE_EMOJI ) {
installedStickerSetsById . remove ( set . id ) ;
}
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
for ( int a = 0 ; a < stickerSetsByIdNew . size ( ) ; a + + ) {
stickerSetsById . put ( stickerSetsByIdNew . keyAt ( a ) , stickerSetsByIdNew . valueAt ( a ) ) ;
2019-08-22 01:53:26 +02:00
if ( type ! = TYPE_FEATURED & & type ! = TYPE_EMOJI ) {
2019-01-23 18:03:33 +01:00
installedStickerSetsById . put ( stickerSetsByIdNew . keyAt ( a ) , stickerSetsByIdNew . valueAt ( a ) ) ;
2018-07-30 04:07:02 +02:00
}
}
2019-01-23 18:03:33 +01:00
stickerSetsByName . putAll ( stickerSetsByNameNew ) ;
stickerSets [ type ] = stickerSetsNew ;
loadHash [ type ] = hash ;
loadDate [ type ] = date ;
2019-08-22 01:53:26 +02:00
stickersByIds [ type ] = stickersByIdNew ;
2019-01-23 18:03:33 +01:00
if ( type = = TYPE_IMAGE ) {
allStickers = allStickersNew ;
stickersByEmoji = stickersByEmojiNew ;
} else if ( type = = TYPE_FEATURED ) {
allStickersFeatured = allStickersNew ;
}
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . stickersDidLoad , type ) ;
2018-07-30 04:07:02 +02:00
} ) ;
2019-01-23 18:03:33 +01:00
} catch ( Throwable e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} else if ( ! cache ) {
AndroidUtilities . runOnUIThread ( ( ) - > loadDate [ type ] = date ) ;
putStickersToCache ( type , null , date , 0 ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2020-03-30 14:00:09 +02:00
public boolean cancelRemovingStickerSet ( long id ) {
2021-09-20 00:10:42 +02:00
Runnable undoAction = removingStickerSetsUndos . get ( id ) ;
2020-03-30 14:00:09 +02:00
if ( undoAction ! = null ) {
undoAction . run ( ) ;
return true ;
} else {
return false ;
}
}
public void preloadStickerSetThumb ( TLRPC . TL_messages_stickerSet stickerSet ) {
2020-12-23 08:48:30 +01:00
TLRPC . PhotoSize thumb = FileLoader . getClosestPhotoSizeWithSize ( stickerSet . set . thumbs , 90 ) ;
if ( thumb ! = null ) {
2021-09-20 00:10:42 +02:00
ArrayList < TLRPC . Document > documents = stickerSet . documents ;
2020-03-30 14:00:09 +02:00
if ( documents ! = null & & ! documents . isEmpty ( ) ) {
2021-06-25 02:43:10 +02:00
loadStickerSetThumbInternal ( thumb , stickerSet , documents . get ( 0 ) , stickerSet . set . thumb_version ) ;
2020-03-30 14:00:09 +02:00
}
}
}
public void preloadStickerSetThumb ( TLRPC . StickerSetCovered stickerSet ) {
2020-12-23 08:48:30 +01:00
TLRPC . PhotoSize thumb = FileLoader . getClosestPhotoSizeWithSize ( stickerSet . set . thumbs , 90 ) ;
if ( thumb ! = null ) {
2021-09-20 00:10:42 +02:00
TLRPC . Document sticker ;
2020-03-30 14:00:09 +02:00
if ( stickerSet . cover ! = null ) {
sticker = stickerSet . cover ;
} else if ( ! stickerSet . covers . isEmpty ( ) ) {
sticker = stickerSet . covers . get ( 0 ) ;
} else {
return ;
}
2021-06-25 02:43:10 +02:00
loadStickerSetThumbInternal ( thumb , stickerSet , sticker , stickerSet . set . thumb_version ) ;
2020-03-30 14:00:09 +02:00
}
}
2021-06-25 02:43:10 +02:00
private void loadStickerSetThumbInternal ( TLRPC . PhotoSize thumb , Object parentObject , TLRPC . Document sticker , int thumbVersion ) {
2021-09-20 00:10:42 +02:00
ImageLocation imageLocation = ImageLocation . getForSticker ( thumb , sticker , thumbVersion ) ;
2020-03-30 14:00:09 +02:00
if ( imageLocation ! = null ) {
2021-09-20 00:10:42 +02:00
String ext = imageLocation . imageType = = FileLoader . IMAGE_TYPE_LOTTIE ? " tgs " : " webp " ;
2020-03-30 14:00:09 +02:00
getFileLoader ( ) . loadFile ( imageLocation , parentObject , ext , 2 , 1 ) ;
}
}
2021-03-09 12:40:50 +01:00
/ * *
* @param toggle 0 - remove , 1 - archive , 2 - add
* /
2021-09-20 00:10:42 +02:00
public void toggleStickerSet ( Context context , TLObject stickerSetObject , int toggle , BaseFragment baseFragment , boolean showSettings , boolean showTooltip ) {
TLRPC . StickerSet stickerSet ;
TLRPC . TL_messages_stickerSet messages_stickerSet ;
2020-03-30 14:00:09 +02:00
if ( stickerSetObject instanceof TLRPC . TL_messages_stickerSet ) {
messages_stickerSet = ( ( TLRPC . TL_messages_stickerSet ) stickerSetObject ) ;
stickerSet = messages_stickerSet . set ;
} else if ( stickerSetObject instanceof TLRPC . StickerSetCovered ) {
stickerSet = ( ( TLRPC . StickerSetCovered ) stickerSetObject ) . set ;
if ( toggle ! = 2 ) {
messages_stickerSet = stickerSetsById . get ( stickerSet . id ) ;
if ( messages_stickerSet = = null ) {
return ;
}
} else {
messages_stickerSet = null ;
}
} else {
throw new IllegalArgumentException ( " Invalid type of the given stickerSetObject: " + stickerSetObject . getClass ( ) ) ;
}
2021-09-20 00:10:42 +02:00
int type = stickerSet . masks ? TYPE_MASK : TYPE_IMAGE ;
2020-03-30 14:00:09 +02:00
2021-10-30 08:05:57 +02:00
if ( NekomuraConfig . enableStickerPin . Bool ( ) & & type = = MediaDataController . TYPE_IMAGE & & ( toggle = = 0 | | toggle = = 1 ) ) {
2021-03-09 12:40:50 +01:00
PinnedStickerHelper . getInstance ( currentAccount ) . removePinnedStickerLocal ( stickerSet . id ) ;
}
2020-03-30 14:00:09 +02:00
stickerSet . archived = toggle = = 1 ;
int currentIndex = 0 ;
for ( int a = 0 ; a < stickerSets [ type ] . size ( ) ; a + + ) {
TLRPC . TL_messages_stickerSet set = stickerSets [ type ] . get ( a ) ;
if ( set . set . id = = stickerSet . id ) {
currentIndex = a ;
stickerSets [ type ] . remove ( a ) ;
if ( toggle = = 2 ) {
stickerSets [ type ] . add ( 0 , set ) ;
} else {
stickerSetsById . remove ( set . set . id ) ;
installedStickerSetsById . remove ( set . set . id ) ;
stickerSetsByName . remove ( set . set . short_name ) ;
}
break ;
}
}
loadHash [ type ] = calcStickersHash ( stickerSets [ type ] ) ;
putStickersToCache ( type , stickerSets [ type ] , loadDate [ type ] , loadHash [ type ] ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . stickersDidLoad , type ) ;
2020-06-25 17:28:24 +02:00
if ( context = = null & & baseFragment ! = null ) context = baseFragment . getParentActivity ( ) ;
2020-03-30 14:00:09 +02:00
if ( toggle = = 2 ) {
if ( ! cancelRemovingStickerSet ( stickerSet . id ) ) {
toggleStickerSetInternal ( context , toggle , baseFragment , showSettings , stickerSetObject , stickerSet , type , showTooltip ) ;
}
} else if ( ! showTooltip | | baseFragment = = null ) {
toggleStickerSetInternal ( context , toggle , baseFragment , showSettings , stickerSetObject , stickerSet , type , false ) ;
} else {
2021-09-20 00:10:42 +02:00
StickerSetBulletinLayout bulletinLayout = new StickerSetBulletinLayout ( context , stickerSetObject , toggle ) ;
2021-10-30 08:05:57 +02:00
int finalCurrentIndex = NekomuraConfig . enableStickerPin . Bool ( ) & & type = = TYPE_IMAGE & & PinnedStickerHelper . getInstance ( UserConfig . selectedAccount ) . isPinned ( stickerSet . id )
2021-03-09 12:40:50 +01:00
? PinnedStickerHelper . getInstance ( UserConfig . selectedAccount ) . pinnedList . size ( )
: currentIndex ;
// NekoX: Pin Sticker, Fix undo for Archiving and Deleting
2020-06-25 17:28:24 +02:00
Context finalContext = context ;
2021-09-20 00:10:42 +02:00
Bulletin . UndoButton undoButton = new Bulletin . UndoButton ( context , false ) . setUndoAction ( ( ) - > {
2020-03-30 14:00:09 +02:00
stickerSet . archived = false ;
stickerSets [ type ] . add ( finalCurrentIndex , messages_stickerSet ) ;
stickerSetsById . put ( stickerSet . id , messages_stickerSet ) ;
installedStickerSetsById . put ( stickerSet . id , messages_stickerSet ) ;
stickerSetsByName . put ( stickerSet . short_name , messages_stickerSet ) ;
removingStickerSetsUndos . remove ( stickerSet . id ) ;
loadHash [ type ] = calcStickersHash ( stickerSets [ type ] ) ;
putStickersToCache ( type , stickerSets [ type ] , loadDate [ type ] , loadHash [ type ] ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . stickersDidLoad , type ) ;
2020-06-25 17:28:24 +02:00
} ) . setDelayedAction ( ( ) - > toggleStickerSetInternal ( finalContext , toggle , baseFragment , showSettings , stickerSetObject , stickerSet , type , false ) ) ;
2020-03-30 14:00:09 +02:00
bulletinLayout . setButton ( undoButton ) ;
removingStickerSetsUndos . put ( stickerSet . id , undoButton : : undo ) ;
Bulletin . make ( baseFragment , bulletinLayout , Bulletin . DURATION_LONG ) . show ( ) ;
}
}
private void toggleStickerSetInternal ( Context context , int toggle , BaseFragment baseFragment , boolean showSettings , TLObject stickerSetObject , TLRPC . StickerSet stickerSet , int type , boolean showTooltip ) {
2018-07-30 04:07:02 +02:00
TLRPC . TL_inputStickerSetID stickerSetID = new TLRPC . TL_inputStickerSetID ( ) ;
stickerSetID . access_hash = stickerSet . access_hash ;
stickerSetID . id = stickerSet . id ;
2020-03-30 14:00:09 +02:00
if ( toggle ! = 0 ) {
TLRPC . TL_messages_installStickerSet req = new TLRPC . TL_messages_installStickerSet ( ) ;
req . stickerset = stickerSetID ;
req . archived = toggle = = 1 ;
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > AndroidUtilities . runOnUIThread ( ( ) - > {
removingStickerSetsUndos . remove ( stickerSet . id ) ;
if ( response instanceof TLRPC . TL_messages_stickerSetInstallResultArchive ) {
processStickerSetInstallResultArchive ( baseFragment , showSettings , type , ( TLRPC . TL_messages_stickerSetInstallResultArchive ) response ) ;
}
loadStickers ( type , false , false , true ) ;
if ( error = = null & & showTooltip & & baseFragment ! = null ) {
Bulletin . make ( baseFragment , new StickerSetBulletinLayout ( context , stickerSetObject , StickerSetBulletinLayout . TYPE_ADDED ) , Bulletin . DURATION_SHORT ) . show ( ) ;
}
} ) ) ;
} else {
TLRPC . TL_messages_uninstallStickerSet req = new TLRPC . TL_messages_uninstallStickerSet ( ) ;
req . stickerset = stickerSetID ;
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > AndroidUtilities . runOnUIThread ( ( ) - > {
removingStickerSetsUndos . remove ( stickerSet . id ) ;
loadStickers ( type , false , true ) ;
} ) ) ;
}
}
2021-03-09 12:40:50 +01:00
/ * *
* @param toggle 0 - uninstall , 1 - archive , 2 - unarchive
* /
2021-09-20 00:10:42 +02:00
public void toggleStickerSets ( ArrayList < TLRPC . StickerSet > stickerSetList , int type , int toggle , BaseFragment baseFragment , boolean showSettings ) {
int stickerSetListSize = stickerSetList . size ( ) ;
ArrayList < TLRPC . InputStickerSet > inputStickerSets = new ArrayList < > ( stickerSetListSize ) ;
2020-03-30 14:00:09 +02:00
for ( int i = 0 ; i < stickerSetListSize ; i + + ) {
2021-09-20 00:10:42 +02:00
TLRPC . StickerSet stickerSet = stickerSetList . get ( i ) ;
TLRPC . InputStickerSet inputStickerSet = new TLRPC . TL_inputStickerSetID ( ) ;
2020-03-30 14:00:09 +02:00
inputStickerSet . access_hash = stickerSet . access_hash ;
inputStickerSet . id = stickerSet . id ;
inputStickerSets . add ( inputStickerSet ) ;
if ( toggle ! = 0 ) {
stickerSet . archived = toggle = = 1 ;
}
for ( int a = 0 , size = stickerSets [ type ] . size ( ) ; a < size ; a + + ) {
2018-07-30 04:07:02 +02:00
TLRPC . TL_messages_stickerSet set = stickerSets [ type ] . get ( a ) ;
2020-03-30 14:00:09 +02:00
if ( set . set . id = = inputStickerSet . id ) {
2018-07-30 04:07:02 +02:00
stickerSets [ type ] . remove ( a ) ;
2020-03-30 14:00:09 +02:00
if ( toggle = = 2 ) {
2018-07-30 04:07:02 +02:00
stickerSets [ type ] . add ( 0 , set ) ;
} else {
stickerSetsById . remove ( set . set . id ) ;
installedStickerSetsById . remove ( set . set . id ) ;
stickerSetsByName . remove ( set . set . short_name ) ;
}
break ;
}
}
2020-03-30 14:00:09 +02:00
}
loadHash [ type ] = calcStickersHash ( this . stickerSets [ type ] ) ;
putStickersToCache ( type , this . stickerSets [ type ] , loadDate [ type ] , loadHash [ type ] ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . stickersDidLoad , type ) ;
2021-09-20 00:10:42 +02:00
TLRPC . TL_messages_toggleStickerSets req = new TLRPC . TL_messages_toggleStickerSets ( ) ;
2020-03-30 14:00:09 +02:00
req . stickersets = inputStickerSets ;
switch ( toggle ) {
case 0 :
req . uninstall = true ;
break ;
case 1 :
req . archive = true ;
break ;
case 2 :
req . unarchive = true ;
break ;
}
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > AndroidUtilities . runOnUIThread ( ( ) - > {
if ( toggle ! = 0 ) {
if ( response instanceof TLRPC . TL_messages_stickerSetInstallResultArchive ) {
processStickerSetInstallResultArchive ( baseFragment , showSettings , type , ( TLRPC . TL_messages_stickerSetInstallResultArchive ) response ) ;
2018-07-30 04:07:02 +02:00
}
2020-03-30 14:00:09 +02:00
loadStickers ( type , false , false , true ) ;
} else {
2019-01-23 18:03:33 +01:00
loadStickers ( type , false , true ) ;
2020-03-30 14:00:09 +02:00
}
} ) ) ;
}
public void processStickerSetInstallResultArchive ( BaseFragment baseFragment , boolean showSettings , int type , TLRPC . TL_messages_stickerSetInstallResultArchive response ) {
for ( int i = 0 , size = response . sets . size ( ) ; i < size ; i + + ) {
installedStickerSetsById . remove ( response . sets . get ( i ) . set . id ) ;
}
loadArchivedStickersCount ( type , false ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . needAddArchivedStickers , response . sets ) ;
if ( baseFragment ! = null & & baseFragment . getParentActivity ( ) ! = null ) {
2021-09-20 00:10:42 +02:00
StickersArchiveAlert alert = new StickersArchiveAlert ( baseFragment . getParentActivity ( ) , showSettings ? baseFragment : null , response . sets ) ;
2020-03-30 14:00:09 +02:00
baseFragment . showDialog ( alert . create ( ) ) ;
2018-07-30 04:07:02 +02:00
}
}
//---------------- STICKERS END ----------------
private int reqId ;
private int mergeReqId ;
private long lastMergeDialogId ;
2020-09-30 15:48:47 +02:00
private int lastReplyMessageId ;
2019-12-31 14:08:08 +01:00
private long lastDialogId ;
2018-07-30 04:07:02 +02:00
private int lastReqId ;
2019-12-31 14:08:08 +01:00
private int lastGuid ;
private TLRPC . User lastSearchUser ;
2020-10-30 11:26:29 +01:00
private TLRPC . Chat lastSearchChat ;
2019-06-04 12:14:50 +02:00
private int [ ] messagesSearchCount = new int [ ] { 0 , 0 } ;
private boolean [ ] messagesSearchEndReached = new boolean [ ] { false , false } ;
2018-07-30 04:07:02 +02:00
private ArrayList < MessageObject > searchResultMessages = new ArrayList < > ( ) ;
2019-06-04 12:14:50 +02:00
private SparseArray < MessageObject > [ ] searchResultMessagesMap = new SparseArray [ ] { new SparseArray < > ( ) , new SparseArray < > ( ) } ;
2018-07-30 04:07:02 +02:00
private String lastSearchQuery ;
private int lastReturnedNum ;
2019-12-31 14:08:08 +01:00
private boolean loadingMoreSearchMessages ;
2018-07-30 04:07:02 +02:00
private int getMask ( ) {
int mask = 0 ;
if ( lastReturnedNum < searchResultMessages . size ( ) - 1 | | ! messagesSearchEndReached [ 0 ] | | ! messagesSearchEndReached [ 1 ] ) {
mask | = 1 ;
}
if ( lastReturnedNum > 0 ) {
mask | = 2 ;
}
return mask ;
}
2019-12-31 14:08:08 +01:00
public ArrayList < MessageObject > getFoundMessageObjects ( ) {
return searchResultMessages ;
}
public void clearFoundMessageObjects ( ) {
searchResultMessages . clear ( ) ;
}
2021-09-20 00:10:42 +02:00
public boolean isMessageFound ( int messageId , boolean mergeDialog ) {
2018-07-30 04:07:02 +02:00
return searchResultMessagesMap [ mergeDialog ? 1 : 0 ] . indexOfKey ( messageId ) > = 0 ;
}
2021-09-20 00:10:42 +02:00
public void searchMessagesInChat ( String query , long dialogId , long mergeDialogId , int guid , int direction , int replyMessageId , TLRPC . User user , TLRPC . Chat chat ) {
2020-10-30 11:26:29 +01:00
searchMessagesInChat ( query , dialogId , mergeDialogId , guid , direction , replyMessageId , false , user , chat , true ) ;
2019-12-31 14:08:08 +01:00
}
public void jumpToSearchedMessage ( int guid , int index ) {
if ( index < 0 | | index > = searchResultMessages . size ( ) ) {
return ;
}
lastReturnedNum = index ;
MessageObject messageObject = searchResultMessages . get ( lastReturnedNum ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . chatSearchResultsAvailable , guid , messageObject . getId ( ) , getMask ( ) , messageObject . getDialogId ( ) , lastReturnedNum , messagesSearchCount [ 0 ] + messagesSearchCount [ 1 ] , true ) ;
2018-07-30 04:07:02 +02:00
}
2019-12-31 14:08:08 +01:00
public void loadMoreSearchMessages ( ) {
if ( loadingMoreSearchMessages | | messagesSearchEndReached [ 0 ] & & lastMergeDialogId = = 0 & & messagesSearchEndReached [ 1 ] ) {
return ;
}
int temp = searchResultMessages . size ( ) ;
lastReturnedNum = searchResultMessages . size ( ) ;
2020-10-30 11:26:29 +01:00
searchMessagesInChat ( null , lastDialogId , lastMergeDialogId , lastGuid , 1 , lastReplyMessageId , false , lastSearchUser , lastSearchChat , false ) ;
2019-12-31 14:08:08 +01:00
lastReturnedNum = temp ;
loadingMoreSearchMessages = true ;
}
2021-09-20 00:10:42 +02:00
private void searchMessagesInChat ( String query , long dialogId , long mergeDialogId , int guid , int direction , int replyMessageId , boolean internal , TLRPC . User user , TLRPC . Chat chat , boolean jumpToMessage ) {
2018-07-30 04:07:02 +02:00
int max_id = 0 ;
2019-12-31 14:08:08 +01:00
long queryWithDialog = dialogId ;
2018-07-30 04:07:02 +02:00
boolean firstQuery = ! internal ;
if ( reqId ! = 0 ) {
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . cancelRequest ( reqId , true ) ;
2018-07-30 04:07:02 +02:00
reqId = 0 ;
}
if ( mergeReqId ! = 0 ) {
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . cancelRequest ( mergeReqId , true ) ;
2018-07-30 04:07:02 +02:00
mergeReqId = 0 ;
}
if ( query = = null ) {
if ( searchResultMessages . isEmpty ( ) ) {
return ;
}
if ( direction = = 1 ) {
lastReturnedNum + + ;
if ( lastReturnedNum < searchResultMessages . size ( ) ) {
MessageObject messageObject = searchResultMessages . get ( lastReturnedNum ) ;
2019-12-31 14:08:08 +01:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . chatSearchResultsAvailable , guid , messageObject . getId ( ) , getMask ( ) , messageObject . getDialogId ( ) , lastReturnedNum , messagesSearchCount [ 0 ] + messagesSearchCount [ 1 ] , jumpToMessage ) ;
2018-07-30 04:07:02 +02:00
return ;
} else {
if ( messagesSearchEndReached [ 0 ] & & mergeDialogId = = 0 & & messagesSearchEndReached [ 1 ] ) {
lastReturnedNum - - ;
return ;
}
firstQuery = false ;
query = lastSearchQuery ;
MessageObject messageObject = searchResultMessages . get ( searchResultMessages . size ( ) - 1 ) ;
2019-12-31 14:08:08 +01:00
if ( messageObject . getDialogId ( ) = = dialogId & & ! messagesSearchEndReached [ 0 ] ) {
2018-07-30 04:07:02 +02:00
max_id = messageObject . getId ( ) ;
2019-12-31 14:08:08 +01:00
queryWithDialog = dialogId ;
2018-07-30 04:07:02 +02:00
} else {
if ( messageObject . getDialogId ( ) = = mergeDialogId ) {
max_id = messageObject . getId ( ) ;
}
queryWithDialog = mergeDialogId ;
messagesSearchEndReached [ 1 ] = false ;
}
}
} else if ( direction = = 2 ) {
lastReturnedNum - - ;
if ( lastReturnedNum < 0 ) {
lastReturnedNum = 0 ;
return ;
}
if ( lastReturnedNum > = searchResultMessages . size ( ) ) {
lastReturnedNum = searchResultMessages . size ( ) - 1 ;
}
MessageObject messageObject = searchResultMessages . get ( lastReturnedNum ) ;
2019-12-31 14:08:08 +01:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . chatSearchResultsAvailable , guid , messageObject . getId ( ) , getMask ( ) , messageObject . getDialogId ( ) , lastReturnedNum , messagesSearchCount [ 0 ] + messagesSearchCount [ 1 ] , jumpToMessage ) ;
2018-07-30 04:07:02 +02:00
return ;
} else {
return ;
}
} else if ( firstQuery ) {
messagesSearchEndReached [ 0 ] = messagesSearchEndReached [ 1 ] = false ;
messagesSearchCount [ 0 ] = messagesSearchCount [ 1 ] = 0 ;
searchResultMessages . clear ( ) ;
searchResultMessagesMap [ 0 ] . clear ( ) ;
searchResultMessagesMap [ 1 ] . clear ( ) ;
2019-12-31 14:08:08 +01:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . chatSearchResultsLoading , guid ) ;
2018-07-30 04:07:02 +02:00
}
if ( messagesSearchEndReached [ 0 ] & & ! messagesSearchEndReached [ 1 ] & & mergeDialogId ! = 0 ) {
queryWithDialog = mergeDialogId ;
}
2019-12-31 14:08:08 +01:00
if ( queryWithDialog = = dialogId & & firstQuery ) {
2018-07-30 04:07:02 +02:00
if ( mergeDialogId ! = 0 ) {
2021-09-20 00:10:42 +02:00
TLRPC . InputPeer inputPeer = getMessagesController ( ) . getInputPeer ( mergeDialogId ) ;
2018-07-30 04:07:02 +02:00
if ( inputPeer = = null ) {
return ;
}
2021-09-20 00:10:42 +02:00
TLRPC . TL_messages_search req = new TLRPC . TL_messages_search ( ) ;
2018-07-30 04:07:02 +02:00
req . peer = inputPeer ;
lastMergeDialogId = mergeDialogId ;
req . limit = 1 ;
2020-10-30 11:26:29 +01:00
req . q = query ;
2018-07-30 04:07:02 +02:00
if ( user ! = null ) {
2020-10-30 11:26:29 +01:00
req . from_id = MessagesController . getInputPeer ( user ) ;
req . flags | = 1 ;
} else if ( chat ! = null ) {
req . from_id = MessagesController . getInputPeer ( chat ) ;
2018-07-30 04:07:02 +02:00
req . flags | = 1 ;
}
req . filter = new TLRPC . TL_inputMessagesFilterEmpty ( ) ;
2019-07-18 15:01:39 +02:00
mergeReqId = getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > AndroidUtilities . runOnUIThread ( ( ) - > {
2019-01-23 18:03:33 +01:00
if ( lastMergeDialogId = = mergeDialogId ) {
mergeReqId = 0 ;
if ( response ! = null ) {
TLRPC . messages_Messages res = ( TLRPC . messages_Messages ) response ;
messagesSearchEndReached [ 1 ] = res . messages . isEmpty ( ) ;
messagesSearchCount [ 1 ] = res instanceof TLRPC . TL_messages_messagesSlice ? res . count : res . messages . size ( ) ;
2020-10-30 11:26:29 +01:00
searchMessagesInChat ( req . q , dialogId , mergeDialogId , guid , direction , replyMessageId , true , user , chat , jumpToMessage ) ;
2021-01-28 15:15:51 +01:00
} else {
messagesSearchEndReached [ 1 ] = true ;
messagesSearchCount [ 1 ] = 0 ;
searchMessagesInChat ( req . q , dialogId , mergeDialogId , guid , direction , replyMessageId , true , user , chat , jumpToMessage ) ;
2019-01-23 18:03:33 +01:00
}
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} ) , ConnectionsManager . RequestFlagFailOnServerErrors ) ;
2018-07-30 04:07:02 +02:00
return ;
} else {
lastMergeDialogId = 0 ;
messagesSearchEndReached [ 1 ] = true ;
messagesSearchCount [ 1 ] = 0 ;
}
}
2021-09-20 00:10:42 +02:00
TLRPC . TL_messages_search req = new TLRPC . TL_messages_search ( ) ;
req . peer = getMessagesController ( ) . getInputPeer ( queryWithDialog ) ;
2018-07-30 04:07:02 +02:00
if ( req . peer = = null ) {
return ;
}
2019-12-31 14:08:08 +01:00
lastGuid = guid ;
lastDialogId = dialogId ;
lastSearchUser = user ;
2020-10-30 11:26:29 +01:00
lastSearchChat = chat ;
2020-09-30 15:48:47 +02:00
lastReplyMessageId = replyMessageId ;
2018-07-30 04:07:02 +02:00
req . limit = 21 ;
req . q = query ! = null ? query : " " ;
req . offset_id = max_id ;
if ( user ! = null ) {
2020-10-30 11:26:29 +01:00
req . from_id = MessagesController . getInputPeer ( user ) ;
req . flags | = 1 ;
} else if ( chat ! = null ) {
req . from_id = MessagesController . getInputPeer ( chat ) ;
2018-07-30 04:07:02 +02:00
req . flags | = 1 ;
}
2020-09-30 15:48:47 +02:00
if ( lastReplyMessageId ! = 0 ) {
req . top_msg_id = lastReplyMessageId ;
req . flags | = 2 ;
}
2018-07-30 04:07:02 +02:00
req . filter = new TLRPC . TL_inputMessagesFilterEmpty ( ) ;
2021-09-20 00:10:42 +02:00
int currentReqId = + + lastReqId ;
2018-07-30 04:07:02 +02:00
lastSearchQuery = query ;
2021-09-20 00:10:42 +02:00
long queryWithDialogFinal = queryWithDialog ;
2020-10-02 23:48:16 +02:00
String finalQuery = query ;
reqId = getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
ArrayList < MessageObject > messageObjects = new ArrayList < > ( ) ;
if ( error = = null ) {
TLRPC . messages_Messages res = ( TLRPC . messages_Messages ) response ;
int N = Math . min ( res . messages . size ( ) , 20 ) ;
for ( int a = 0 ; a < N ; a + + ) {
TLRPC . Message message = res . messages . get ( a ) ;
MessageObject messageObject = new MessageObject ( currentAccount , message , false , false ) ;
messageObject . setQuery ( finalQuery ) ;
messageObjects . add ( messageObject ) ;
2019-12-31 14:08:08 +01:00
}
2020-10-02 23:48:16 +02:00
}
AndroidUtilities . runOnUIThread ( ( ) - > {
if ( currentReqId = = lastReqId ) {
reqId = 0 ;
if ( ! jumpToMessage ) {
loadingMoreSearchMessages = false ;
2019-01-23 18:03:33 +01:00
}
2020-10-02 23:48:16 +02:00
if ( response ! = 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 ( message instanceof TLRPC . TL_messageEmpty | | message . action instanceof TLRPC . TL_messageActionHistoryClear ) {
res . messages . remove ( a ) ;
a - - ;
2018-07-30 04:07:02 +02:00
}
}
2020-10-02 23:48:16 +02:00
getMessagesStorage ( ) . putUsersAndChats ( res . users , res . chats , true , true ) ;
getMessagesController ( ) . putUsers ( res . users , false ) ;
getMessagesController ( ) . putChats ( res . chats , false ) ;
if ( req . offset_id = = 0 & & queryWithDialogFinal = = dialogId ) {
lastReturnedNum = 0 ;
searchResultMessages . clear ( ) ;
searchResultMessagesMap [ 0 ] . clear ( ) ;
searchResultMessagesMap [ 1 ] . clear ( ) ;
messagesSearchCount [ 0 ] = 0 ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . chatSearchResultsLoading , guid ) ;
}
boolean added = false ;
int N = Math . min ( res . messages . size ( ) , 20 ) ;
for ( int a = 0 ; a < N ; a + + ) {
TLRPC . Message message = res . messages . get ( a ) ;
added = true ;
MessageObject messageObject = messageObjects . get ( a ) ;
searchResultMessages . add ( messageObject ) ;
searchResultMessagesMap [ queryWithDialogFinal = = dialogId ? 0 : 1 ] . put ( messageObject . getId ( ) , messageObject ) ;
}
messagesSearchEndReached [ queryWithDialogFinal = = dialogId ? 0 : 1 ] = res . messages . size ( ) < 21 ;
messagesSearchCount [ queryWithDialogFinal = = dialogId ? 0 : 1 ] = res instanceof TLRPC . TL_messages_messagesSlice | | res instanceof TLRPC . TL_messages_channelMessages ? res . count : res . messages . size ( ) ;
if ( searchResultMessages . isEmpty ( ) ) {
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . chatSearchResultsAvailable , guid , 0 , getMask ( ) , ( long ) 0 , 0 , 0 , jumpToMessage ) ;
} else {
if ( added ) {
if ( lastReturnedNum > = searchResultMessages . size ( ) ) {
lastReturnedNum = searchResultMessages . size ( ) - 1 ;
}
MessageObject messageObject = searchResultMessages . get ( lastReturnedNum ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . chatSearchResultsAvailable , guid , messageObject . getId ( ) , getMask ( ) , messageObject . getDialogId ( ) , lastReturnedNum , messagesSearchCount [ 0 ] + messagesSearchCount [ 1 ] , jumpToMessage ) ;
}
}
if ( queryWithDialogFinal = = dialogId & & messagesSearchEndReached [ 0 ] & & mergeDialogId ! = 0 & & ! messagesSearchEndReached [ 1 ] ) {
2020-10-30 11:26:29 +01:00
searchMessagesInChat ( lastSearchQuery , dialogId , mergeDialogId , guid , 0 , replyMessageId , true , user , chat , jumpToMessage ) ;
2020-10-02 23:48:16 +02:00
}
2019-01-23 18:03:33 +01:00
}
}
2020-10-02 23:48:16 +02:00
} ) ;
} , ConnectionsManager . RequestFlagFailOnServerErrors ) ;
2018-07-30 04:07:02 +02:00
}
public String getLastSearchQuery ( ) {
return lastSearchQuery ;
}
//---------------- MESSAGE SEARCH END ----------------
public final static int MEDIA_PHOTOVIDEO = 0 ;
public final static int MEDIA_FILE = 1 ;
public final static int MEDIA_AUDIO = 2 ;
public final static int MEDIA_URL = 3 ;
public final static int MEDIA_MUSIC = 4 ;
2020-03-30 14:00:09 +02:00
public final static int MEDIA_GIF = 5 ;
public final static int MEDIA_TYPES_COUNT = 6 ;
2018-07-30 04:07:02 +02:00
2021-09-20 11:14:20 +02:00
public void loadMedia ( long dialogId , int count , int max_id , int type , int fromCache , int classGuid ) {
loadMedia ( dialogId , count , max_id , type , fromCache , classGuid , false ) ;
2020-02-14 23:18:28 +01:00
}
2021-09-20 11:14:20 +02:00
public void loadMedia ( long dialogId , int count , int max_id , int type , int fromCache , int classGuid , boolean skipPhotos ) {
2021-09-20 00:10:42 +02:00
boolean isChannel = DialogObject . isChatDialog ( dialogId ) & & ChatObject . isChannel ( - dialogId , currentAccount ) ;
2018-07-30 04:07:02 +02:00
2020-04-24 11:21:58 +02:00
if ( BuildVars . LOGS_ENABLED ) {
2021-09-20 00:10:42 +02:00
FileLog . d ( " load media did " + dialogId + " count = " + count + " max_id " + max_id + " type = " + type + " cache = " + fromCache + " classGuid = " + classGuid ) ;
2020-02-14 18:15:39 +01:00
}
2021-09-20 00:10:42 +02:00
if ( fromCache ! = 0 | | DialogObject . isEncryptedDialog ( dialogId ) ) {
2021-09-20 11:14:20 +02:00
loadMediaDatabase ( dialogId , count , max_id , type , classGuid , isChannel , fromCache , skipPhotos ) ;
2018-07-30 04:07:02 +02:00
} else {
TLRPC . TL_messages_search req = new TLRPC . TL_messages_search ( ) ;
2019-01-23 18:03:33 +01:00
req . limit = count ;
2018-07-30 04:07:02 +02:00
req . offset_id = max_id ;
if ( type = = MEDIA_PHOTOVIDEO ) {
2020-02-14 23:18:28 +01:00
req . filter = skipPhotos
2021-03-09 12:40:50 +01:00
? new TLRPC . TL_inputMessagesFilterVideo ( )
: new TLRPC . TL_inputMessagesFilterPhotoVideo ( ) ;
2018-07-30 04:07:02 +02:00
} else if ( type = = MEDIA_FILE ) {
req . filter = new TLRPC . TL_inputMessagesFilterDocument ( ) ;
} else if ( type = = MEDIA_AUDIO ) {
req . filter = new TLRPC . TL_inputMessagesFilterRoundVoice ( ) ;
} else if ( type = = MEDIA_URL ) {
req . filter = new TLRPC . TL_inputMessagesFilterUrl ( ) ;
} else if ( type = = MEDIA_MUSIC ) {
req . filter = new TLRPC . TL_inputMessagesFilterMusic ( ) ;
2020-03-30 14:00:09 +02:00
} else if ( type = = MEDIA_GIF ) {
req . filter = new TLRPC . TL_inputMessagesFilterGif ( ) ;
2018-07-30 04:07:02 +02:00
}
req . q = " " ;
2021-09-20 00:10:42 +02:00
req . peer = getMessagesController ( ) . getInputPeer ( dialogId ) ;
2018-07-30 04:07:02 +02:00
if ( req . peer = = null ) {
return ;
}
2019-07-18 15:01:39 +02:00
int reqId = getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2019-01-23 18:03:33 +01:00
if ( error = = null ) {
2021-09-20 00:10:42 +02:00
TLRPC . messages_Messages res = ( TLRPC . messages_Messages ) response ;
getMessagesController ( ) . removeDeletedMessagesFromArray ( dialogId , res . messages ) ;
2021-09-20 11:14:20 +02:00
processLoadedMedia ( res , dialogId , count , max_id , type , 0 , classGuid , isChannel , res . messages . size ( ) = = 0 , skipPhotos ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . bindRequestToGuid ( reqId , classGuid ) ;
2018-07-30 04:07:02 +02:00
}
}
2021-09-20 00:10:42 +02:00
public void getMediaCounts ( long dialogId , int classGuid ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2021-03-09 12:40:50 +01:00
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 } ;
2021-09-20 00:10:42 +02:00
SQLiteCursor cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT type, count, old FROM media_counts_v2 WHERE uid = %d " , dialogId ) ) ;
2019-01-23 18:03:33 +01:00
while ( cursor . next ( ) ) {
int type = cursor . intValue ( 0 ) ;
if ( type > = 0 & & type < MEDIA_TYPES_COUNT ) {
countsFinal [ type ] = counts [ type ] = cursor . intValue ( 1 ) ;
old [ type ] = cursor . intValue ( 2 ) ;
}
}
cursor . dispose ( ) ;
2021-09-20 00:10:42 +02:00
if ( DialogObject . isEncryptedDialog ( dialogId ) ) {
2019-01-23 18:03:33 +01:00
for ( int a = 0 ; a < counts . length ; a + + ) {
if ( counts [ a ] = = - 1 ) {
2021-09-20 00:10:42 +02:00
cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT COUNT(mid) FROM media_v3 WHERE uid = %d AND type = %d LIMIT 1 " , dialogId , a ) ) ;
2019-01-23 18:03:33 +01:00
if ( cursor . next ( ) ) {
counts [ a ] = cursor . intValue ( 0 ) ;
} else {
counts [ a ] = 0 ;
}
cursor . dispose ( ) ;
2021-09-20 00:10:42 +02:00
putMediaCountDatabase ( dialogId , a , counts [ a ] ) ;
2019-01-23 18:03:33 +01:00
}
}
2021-09-20 00:10:42 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > getNotificationCenter ( ) . postNotificationName ( NotificationCenter . mediaCountsDidLoad , dialogId , counts ) ) ;
2019-01-23 18:03:33 +01:00
} else {
boolean missing = false ;
2020-12-23 08:48:30 +01:00
TLRPC . TL_messages_getSearchCounters req = new TLRPC . TL_messages_getSearchCounters ( ) ;
2021-09-20 00:10:42 +02:00
req . peer = getMessagesController ( ) . getInputPeer ( dialogId ) ;
2019-01-23 18:03:33 +01:00
for ( int a = 0 ; a < counts . length ; a + + ) {
2020-12-23 08:48:30 +01:00
if ( req . peer = = null ) {
counts [ a ] = 0 ;
continue ;
}
2019-01-23 18:03:33 +01:00
if ( counts [ a ] = = - 1 | | old [ a ] = = 1 ) {
if ( a = = MEDIA_PHOTOVIDEO ) {
2020-12-23 08:48:30 +01:00
req . filters . add ( new TLRPC . TL_inputMessagesFilterPhotoVideo ( ) ) ;
2019-01-23 18:03:33 +01:00
} else if ( a = = MEDIA_FILE ) {
2020-12-23 08:48:30 +01:00
req . filters . add ( new TLRPC . TL_inputMessagesFilterDocument ( ) ) ;
2019-01-23 18:03:33 +01:00
} else if ( a = = MEDIA_AUDIO ) {
2020-12-23 08:48:30 +01:00
req . filters . add ( new TLRPC . TL_inputMessagesFilterRoundVoice ( ) ) ;
2019-01-23 18:03:33 +01:00
} else if ( a = = MEDIA_URL ) {
2020-12-23 08:48:30 +01:00
req . filters . add ( new TLRPC . TL_inputMessagesFilterUrl ( ) ) ;
2019-01-23 18:03:33 +01:00
} else if ( a = = MEDIA_MUSIC ) {
2020-12-23 08:48:30 +01:00
req . filters . add ( new TLRPC . TL_inputMessagesFilterMusic ( ) ) ;
} else {
req . filters . add ( new TLRPC . TL_inputMessagesFilterGif ( ) ) ;
2019-01-23 18:03:33 +01:00
}
if ( counts [ a ] = = - 1 ) {
missing = true ;
} else if ( old [ a ] = = 1 ) {
counts [ a ] = - 1 ;
}
}
}
2020-12-23 08:48:30 +01:00
if ( ! req . filters . isEmpty ( ) ) {
int reqId = getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
Arrays . fill ( counts , 0 ) ;
if ( response ! = null ) {
TLRPC . Vector res = ( TLRPC . Vector ) response ;
for ( int a = 0 , N = res . objects . size ( ) ; a < N ; a + + ) {
TLRPC . TL_messages_searchCounter searchCounter = ( TLRPC . TL_messages_searchCounter ) res . objects . get ( a ) ;
int type ;
if ( searchCounter . filter instanceof TLRPC . TL_inputMessagesFilterPhotoVideo ) {
type = MEDIA_PHOTOVIDEO ;
} else if ( searchCounter . filter instanceof TLRPC . TL_inputMessagesFilterDocument ) {
type = MEDIA_FILE ;
} else if ( searchCounter . filter instanceof TLRPC . TL_inputMessagesFilterRoundVoice ) {
type = MEDIA_AUDIO ;
} else if ( searchCounter . filter instanceof TLRPC . TL_inputMessagesFilterUrl ) {
type = MEDIA_URL ;
} else if ( searchCounter . filter instanceof TLRPC . TL_inputMessagesFilterMusic ) {
type = MEDIA_MUSIC ;
} else if ( searchCounter . filter instanceof TLRPC . TL_inputMessagesFilterGif ) {
type = MEDIA_GIF ;
} else {
continue ;
}
counts [ type ] = searchCounter . count ;
2021-09-20 00:10:42 +02:00
putMediaCountDatabase ( dialogId , type , counts [ type ] ) ;
2020-12-23 08:48:30 +01:00
}
}
2021-09-20 00:10:42 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > getNotificationCenter ( ) . postNotificationName ( NotificationCenter . mediaCountsDidLoad , dialogId , counts ) ) ;
2020-12-23 08:48:30 +01:00
} ) ;
getConnectionsManager ( ) . bindRequestToGuid ( reqId , classGuid ) ;
}
2019-01-23 18:03:33 +01:00
if ( ! missing ) {
2021-09-20 00:10:42 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > getNotificationCenter ( ) . postNotificationName ( NotificationCenter . mediaCountsDidLoad , dialogId , countsFinal ) ) ;
2019-01-23 18:03:33 +01:00
}
}
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
} ) ;
}
2021-09-20 00:10:42 +02:00
public void getMediaCount ( long dialogId , int type , int classGuid , boolean fromCache ) {
if ( fromCache | | DialogObject . isEncryptedDialog ( dialogId ) ) {
getMediaCountDatabase ( dialogId , type , classGuid ) ;
2018-07-30 04:07:02 +02:00
} else {
2020-12-23 08:48:30 +01:00
TLRPC . TL_messages_getSearchCounters req = new TLRPC . TL_messages_getSearchCounters ( ) ;
2018-07-30 04:07:02 +02:00
if ( type = = MEDIA_PHOTOVIDEO ) {
2020-12-23 08:48:30 +01:00
req . filters . add ( new TLRPC . TL_inputMessagesFilterPhotoVideo ( ) ) ;
2018-07-30 04:07:02 +02:00
} else if ( type = = MEDIA_FILE ) {
2020-12-23 08:48:30 +01:00
req . filters . add ( new TLRPC . TL_inputMessagesFilterDocument ( ) ) ;
2018-07-30 04:07:02 +02:00
} else if ( type = = MEDIA_AUDIO ) {
2020-12-23 08:48:30 +01:00
req . filters . add ( new TLRPC . TL_inputMessagesFilterRoundVoice ( ) ) ;
2018-07-30 04:07:02 +02:00
} else if ( type = = MEDIA_URL ) {
2020-12-23 08:48:30 +01:00
req . filters . add ( new TLRPC . TL_inputMessagesFilterUrl ( ) ) ;
2018-07-30 04:07:02 +02:00
} else if ( type = = MEDIA_MUSIC ) {
2020-12-23 08:48:30 +01:00
req . filters . add ( new TLRPC . TL_inputMessagesFilterMusic ( ) ) ;
2020-03-30 14:00:09 +02:00
} else if ( type = = MEDIA_GIF ) {
2020-12-23 08:48:30 +01:00
req . filters . add ( new TLRPC . TL_inputMessagesFilterGif ( ) ) ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
req . peer = getMessagesController ( ) . getInputPeer ( dialogId ) ;
2018-07-30 04:07:02 +02:00
if ( req . peer = = null ) {
return ;
}
2019-07-18 15:01:39 +02:00
int reqId = getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2020-12-23 08:48:30 +01:00
if ( response ! = null ) {
2021-09-20 00:10:42 +02:00
TLRPC . Vector res = ( TLRPC . Vector ) response ;
2020-12-23 08:48:30 +01:00
if ( ! res . objects . isEmpty ( ) ) {
TLRPC . TL_messages_searchCounter counter = ( TLRPC . TL_messages_searchCounter ) res . objects . get ( 0 ) ;
2021-09-20 00:10:42 +02:00
processLoadedMediaCount ( counter . count , dialogId , type , classGuid , false , 0 ) ;
2018-07-30 04:07:02 +02:00
}
}
} ) ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . bindRequestToGuid ( reqId , classGuid ) ;
2018-07-30 04:07:02 +02:00
}
}
public static int getMediaType ( TLRPC . Message message ) {
if ( message = = null ) {
return - 1 ;
}
if ( message . media instanceof TLRPC . TL_messageMediaPhoto ) {
return MEDIA_PHOTOVIDEO ;
} else if ( message . media instanceof TLRPC . TL_messageMediaDocument ) {
2020-12-23 08:48:30 +01:00
TLRPC . Document document = message . media . document ;
if ( document = = null ) {
return - 1 ;
}
boolean isAnimated = false ;
boolean isVideo = false ;
boolean isVoice = false ;
boolean isMusic = false ;
boolean isSticker = false ;
for ( int a = 0 ; a < document . attributes . size ( ) ; a + + ) {
TLRPC . DocumentAttribute attribute = document . attributes . get ( a ) ;
if ( attribute instanceof TLRPC . TL_documentAttributeVideo ) {
isVoice = attribute . round_message ;
isVideo = ! attribute . round_message ;
} else if ( attribute instanceof TLRPC . TL_documentAttributeAnimated ) {
isAnimated = true ;
} else if ( attribute instanceof TLRPC . TL_documentAttributeAudio ) {
isVoice = attribute . voice ;
isMusic = ! attribute . voice ;
} else if ( attribute instanceof TLRPC . TL_documentAttributeSticker ) {
isSticker = true ;
}
}
if ( isVoice ) {
2018-07-30 04:07:02 +02:00
return MEDIA_AUDIO ;
2020-12-23 08:48:30 +01:00
} else if ( isVideo & & ! isAnimated ) {
2018-07-30 04:07:02 +02:00
return MEDIA_PHOTOVIDEO ;
2020-12-23 08:48:30 +01:00
} else if ( isSticker ) {
2018-07-30 04:07:02 +02:00
return - 1 ;
2020-12-23 08:48:30 +01:00
} else if ( isAnimated ) {
2020-03-30 14:00:09 +02:00
return MEDIA_GIF ;
2020-12-23 08:48:30 +01:00
} else if ( isMusic ) {
2018-07-30 04:07:02 +02:00
return MEDIA_MUSIC ;
} else {
return MEDIA_FILE ;
}
} else if ( ! message . entities . isEmpty ( ) ) {
for ( int a = 0 ; a < message . entities . size ( ) ; a + + ) {
TLRPC . MessageEntity entity = message . entities . get ( a ) ;
if ( entity instanceof TLRPC . TL_messageEntityUrl | | entity instanceof TLRPC . TL_messageEntityTextUrl | | entity instanceof TLRPC . TL_messageEntityEmail ) {
return MEDIA_URL ;
}
}
}
return - 1 ;
}
public static boolean canAddMessageToMedia ( TLRPC . Message message ) {
if ( message instanceof TLRPC . TL_message_secret & & ( message . media instanceof TLRPC . TL_messageMediaPhoto | | MessageObject . isVideoMessage ( message ) | | MessageObject . isGifMessage ( message ) ) & & message . media . ttl_seconds ! = 0 & & message . media . ttl_seconds < = 60 ) {
return false ;
} else if ( ! ( message instanceof TLRPC . TL_message_secret ) & & message instanceof TLRPC . TL_message & & ( message . media instanceof TLRPC . TL_messageMediaPhoto | | message . media instanceof TLRPC . TL_messageMediaDocument ) & & message . media . ttl_seconds ! = 0 ) {
return false ;
2020-12-23 08:48:30 +01:00
} else {
return getMediaType ( message ) ! = - 1 ;
2018-07-30 04:07:02 +02:00
}
}
2021-09-20 11:14:20 +02:00
private void processLoadedMedia ( TLRPC . messages_Messages res , long dialogId , int count , int max_id , int type , int fromCache , int classGuid , boolean isChannel , boolean topReached , boolean skipPhotos ) {
2020-04-24 11:21:58 +02:00
if ( BuildVars . LOGS_ENABLED ) {
2021-09-20 00:10:42 +02:00
FileLog . d ( " process load media did " + dialogId + " count = " + count + " max_id " + max_id + " type = " + type + " cache = " + fromCache + " classGuid = " + classGuid ) ;
2020-02-14 18:15:39 +01:00
}
2021-09-20 00:10:42 +02:00
if ( fromCache ! = 0 & & res . messages . isEmpty ( ) & & ! DialogObject . isEncryptedDialog ( dialogId ) ) {
2019-01-23 18:03:33 +01:00
if ( fromCache = = 2 ) {
return ;
}
2021-09-20 11:14:20 +02:00
loadMedia ( dialogId , count , max_id , type , 0 , classGuid , skipPhotos ) ;
2018-07-30 04:07:02 +02:00
} else {
2019-01-23 18:03:33 +01:00
if ( fromCache = = 0 ) {
2018-07-30 04:07:02 +02:00
ImageLoader . saveMessagesThumbs ( res . messages ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . putUsersAndChats ( res . users , res . chats , true , true ) ;
2021-09-20 00:10:42 +02:00
putMediaDatabase ( dialogId , type , res . messages , max_id , topReached ) ;
2018-07-30 04:07:02 +02:00
}
2020-06-04 18:47:15 +02:00
Utilities . searchQueue . postRunnable ( ( ) - > {
2021-09-20 00:10:42 +02:00
LongSparseArray < TLRPC . User > usersDict = new LongSparseArray < > ( ) ;
2020-04-24 11:21:58 +02:00
for ( int a = 0 ; a < res . users . size ( ) ; a + + ) {
TLRPC . User u = res . users . get ( a ) ;
usersDict . put ( u . id , u ) ;
}
2021-09-20 00:10:42 +02:00
ArrayList < MessageObject > objects = new ArrayList < > ( ) ;
2020-04-24 11:21:58 +02:00
for ( int a = 0 ; a < res . messages . size ( ) ; a + + ) {
TLRPC . Message message = res . messages . get ( a ) ;
2021-03-09 12:40:50 +01:00
2020-02-14 23:18:28 +01:00
if ( skipPhotos & & message . media ! = null & & message . media . photo ! = null ) {
continue ;
}
2021-06-25 02:43:10 +02:00
MessageObject messageObject = new MessageObject ( currentAccount , message , usersDict , true , true ) ;
messageObject . createStrippedThumb ( ) ;
objects . add ( messageObject ) ;
2020-04-24 11:21:58 +02:00
}
2018-07-30 04:07:02 +02:00
2020-04-24 11:21:58 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > {
int totalCount = res . count ;
getMessagesController ( ) . putUsers ( res . users , fromCache ! = 0 ) ;
getMessagesController ( ) . putChats ( res . chats , fromCache ! = 0 ) ;
2021-09-20 00:10:42 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . mediaDidLoad , dialogId , totalCount , objects , classGuid , type , topReached ) ;
2020-04-24 11:21:58 +02:00
} ) ;
2018-07-30 04:07:02 +02:00
} ) ;
}
}
2021-09-20 00:10:42 +02:00
private void processLoadedMediaCount ( int count , long dialogId , int type , int classGuid , boolean fromCache , int old ) {
2019-01-23 18:03:33 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > {
2021-09-20 00:10:42 +02:00
boolean isEncryptedDialog = DialogObject . isEncryptedDialog ( dialogId ) ;
boolean reload = fromCache & & ( count = = - 1 | | count = = 0 & & type = = 2 ) & & ! isEncryptedDialog ;
if ( reload | | old = = 1 & & ! isEncryptedDialog ) {
getMediaCount ( dialogId , type , classGuid , false ) ;
2019-01-23 18:03:33 +01:00
}
if ( ! reload ) {
if ( ! fromCache ) {
2021-09-20 00:10:42 +02:00
putMediaCountDatabase ( dialogId , type , count ) ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . mediaCountDidLoad , dialogId , ( fromCache & & count = = - 1 ? 0 : count ) , fromCache , type ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2021-09-20 00:10:42 +02:00
private void putMediaCountDatabase ( long uid , int type , int count ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2019-07-18 15:01:39 +02:00
SQLitePreparedStatement state2 = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " REPLACE INTO media_counts_v2 VALUES(?, ?, ?, ?) " ) ;
2019-01-23 18:03:33 +01:00
state2 . requery ( ) ;
state2 . bindLong ( 1 , uid ) ;
state2 . bindInteger ( 2 , type ) ;
state2 . bindInteger ( 3 , count ) ;
state2 . bindInteger ( 4 , 0 ) ;
state2 . step ( ) ;
state2 . dispose ( ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2021-09-20 00:10:42 +02:00
private void getMediaCountDatabase ( long dialogId , int type , int classGuid ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
int count = - 1 ;
int old = 0 ;
2021-09-20 00:10:42 +02:00
SQLiteCursor cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT count, old FROM media_counts_v2 WHERE uid = %d AND type = %d LIMIT 1 " , dialogId , type ) ) ;
2019-01-23 18:03:33 +01:00
if ( cursor . next ( ) ) {
count = cursor . intValue ( 0 ) ;
old = cursor . intValue ( 1 ) ;
}
cursor . dispose ( ) ;
2021-09-20 00:10:42 +02:00
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 ) ) ;
2018-07-30 04:07:02 +02:00
if ( cursor . next ( ) ) {
count = cursor . intValue ( 0 ) ;
}
cursor . dispose ( ) ;
2019-01-23 18:03:33 +01:00
if ( count ! = - 1 ) {
2021-09-20 00:10:42 +02:00
putMediaCountDatabase ( dialogId , type , count ) ;
2018-07-30 04:07:02 +02:00
}
}
2021-09-20 00:10:42 +02:00
processLoadedMediaCount ( count , dialogId , type , classGuid , true , old ) ;
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2021-09-20 11:14:20 +02:00
private void loadMediaDatabase ( long uid , int count , int max_id , int type , int classGuid , boolean isChannel , int fromCache , boolean skipPhotos ) {
2020-03-30 14:00:09 +02:00
Runnable runnable = new Runnable ( ) {
@Override
public void run ( ) {
boolean topReached = false ;
TLRPC . TL_messages_messages res = new TLRPC . TL_messages_messages ( ) ;
try {
2021-09-20 00:10:42 +02:00
ArrayList < Long > usersToLoad = new ArrayList < > ( ) ;
ArrayList < Long > chatsToLoad = new ArrayList < > ( ) ;
2020-03-30 14:00:09 +02:00
int countToLoad = count + 1 ;
2018-07-30 04:07:02 +02:00
2020-03-30 14:00:09 +02:00
SQLiteCursor cursor ;
SQLiteDatabase database = getMessagesStorage ( ) . getDatabase ( ) ;
boolean isEnd = false ;
2021-09-20 00:10:42 +02:00
if ( ! DialogObject . isEncryptedDialog ( uid ) ) {
2020-03-30 14:00:09 +02:00
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 ) ) ;
2018-07-30 04:07:02 +02:00
if ( cursor . next ( ) ) {
2020-03-30 14:00:09 +02:00
isEnd = cursor . intValue ( 0 ) = = 1 ;
} else {
cursor . dispose ( ) ;
2021-09-20 00:10:42 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT min(mid) FROM media_v3 WHERE uid = %d AND type = %d AND mid > 0 " , uid , type ) ) ;
2020-03-30 14:00:09 +02:00
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 ( ) ;
}
2018-07-30 04:07:02 +02:00
}
}
2020-07-26 10:03:38 +02:00
cursor . dispose ( ) ;
2018-07-30 04:07:02 +02:00
2021-09-20 00:10:42 +02:00
int holeMessageId = 0 ;
if ( max_id ! = 0 ) {
2020-03-30 14:00:09 +02:00
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 ) ) ;
if ( cursor . next ( ) ) {
holeMessageId = cursor . intValue ( 0 ) ;
}
cursor . dispose ( ) ;
if ( holeMessageId > 1 ) {
2021-09-20 00:10:42 +02:00
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 ) ) ;
2020-03-30 14:00:09 +02:00
} else {
2021-09-20 00:10:42 +02:00
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 ) ) ;
2018-07-30 04:07:02 +02:00
}
} else {
2020-03-30 14:00:09 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT max(end) FROM media_holes_v2 WHERE uid = %d AND type = %d " , uid , type ) ) ;
if ( cursor . next ( ) ) {
holeMessageId = cursor . intValue ( 0 ) ;
}
cursor . dispose ( ) ;
if ( holeMessageId > 1 ) {
2021-09-20 00:10:42 +02:00
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 ) ) ;
2020-03-30 14:00:09 +02:00
} else {
2021-09-20 00:10:42 +02:00
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 ) ) ;
2019-01-23 18:03:33 +01:00
}
}
2020-03-30 14:00:09 +02:00
} else {
isEnd = true ;
if ( max_id ! = 0 ) {
2021-09-20 00:10:42 +02:00
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 ) ) ;
2018-07-30 04:07:02 +02:00
} else {
2021-09-20 00:10:42 +02:00
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 ) ) ;
2018-07-30 04:07:02 +02:00
}
}
2020-03-30 14:00:09 +02:00
while ( cursor . next ( ) ) {
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
message . readAttachPath ( data , getUserConfig ( ) . clientUserId ) ;
data . reuse ( ) ;
message . id = cursor . intValue ( 1 ) ;
message . dialog_id = uid ;
2021-09-20 00:10:42 +02:00
if ( DialogObject . isEncryptedDialog ( uid ) ) {
2020-03-30 14:00:09 +02:00
message . random_id = cursor . longValue ( 2 ) ;
}
2020-02-14 23:18:28 +01:00
if ( skipPhotos & & message . media ! = null & & message . media . photo ! = null ) {
continue ;
}
2020-03-30 14:00:09 +02:00
res . messages . add ( message ) ;
MessagesStorage . addUsersAndChatsFromMessage ( message , usersToLoad , chatsToLoad ) ;
2018-07-30 04:07:02 +02:00
}
}
2020-03-30 14:00:09 +02:00
cursor . dispose ( ) ;
2018-07-30 04:07:02 +02:00
2020-03-30 14:00:09 +02:00
if ( ! usersToLoad . isEmpty ( ) ) {
getMessagesStorage ( ) . getUsersInternal ( TextUtils . join ( " , " , usersToLoad ) , res . users ) ;
}
if ( ! chatsToLoad . isEmpty ( ) ) {
getMessagesStorage ( ) . getChatsInternal ( TextUtils . join ( " , " , chatsToLoad ) , res . chats ) ;
}
if ( res . messages . size ( ) > count ) {
res . messages . remove ( res . messages . size ( ) - 1 ) ;
} else {
topReached = isEnd ;
}
} catch ( Exception e ) {
res . messages . clear ( ) ;
res . chats . clear ( ) ;
res . users . clear ( ) ;
FileLog . e ( e ) ;
} finally {
Runnable task = this ;
AndroidUtilities . runOnUIThread ( ( ) - > getMessagesStorage ( ) . completeTaskForGuid ( task , classGuid ) ) ;
2020-02-14 23:18:28 +01:00
processLoadedMedia ( res , uid , count , max_id , type , fromCache , classGuid , isChannel , topReached , skipPhotos ) ;
2019-01-23 18:03:33 +01:00
}
2018-07-30 04:07:02 +02:00
}
2020-03-30 14:00:09 +02:00
} ;
MessagesStorage messagesStorage = getMessagesStorage ( ) ;
messagesStorage . getStorageQueue ( ) . postRunnable ( runnable ) ;
messagesStorage . bindTaskToGuid ( runnable , classGuid ) ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
private void putMediaDatabase ( long uid , int type , ArrayList < TLRPC . Message > messages , int max_id , boolean topReached ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
if ( messages . isEmpty ( ) | | topReached ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . doneHolesInMedia ( uid , max_id , type ) ;
2019-01-23 18:03:33 +01:00
if ( messages . isEmpty ( ) ) {
return ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getDatabase ( ) . beginTransaction ( ) ;
2021-09-20 00:10:42 +02:00
SQLitePreparedStatement state2 = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " REPLACE INTO media_v3 VALUES(?, ?, ?, ?, ?) " ) ;
2019-01-23 18:03:33 +01:00
for ( TLRPC . Message message : messages ) {
if ( canAddMessageToMedia ( message ) ) {
state2 . requery ( ) ;
NativeByteBuffer data = new NativeByteBuffer ( message . getObjectSize ( ) ) ;
message . serializeToStream ( data ) ;
2021-09-20 00:10:42 +02:00
state2 . bindInteger ( 1 , message . id ) ;
2019-01-23 18:03:33 +01:00
state2 . bindLong ( 2 , uid ) ;
state2 . bindInteger ( 3 , message . date ) ;
state2 . bindInteger ( 4 , type ) ;
state2 . bindByteBuffer ( 5 , data ) ;
state2 . step ( ) ;
data . reuse ( ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
}
state2 . dispose ( ) ;
if ( ! topReached | | max_id ! = 0 ) {
int minId = topReached ? 1 : messages . get ( messages . size ( ) - 1 ) . id ;
if ( max_id ! = 0 ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . closeHolesInMedia ( uid , minId , max_id , type ) ;
2019-01-23 18:03:33 +01:00
} else {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . closeHolesInMedia ( uid , minId , Integer . MAX_VALUE , type ) ;
2018-07-30 04:07:02 +02:00
}
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getDatabase ( ) . commitTransaction ( ) ;
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2021-09-20 00:10:42 +02:00
public void loadMusic ( long dialogId , long maxId , long minId ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2021-09-20 00:10:42 +02:00
ArrayList < MessageObject > arrayListBegin = new ArrayList < > ( ) ;
ArrayList < MessageObject > arrayListEnd = new ArrayList < > ( ) ;
2019-01-23 18:03:33 +01:00
try {
2020-07-26 10:03:38 +02:00
for ( int a = 0 ; a < 2 ; a + + ) {
ArrayList < MessageObject > arrayList = a = = 0 ? arrayListBegin : arrayListEnd ;
SQLiteCursor cursor ;
if ( a = = 0 ) {
2021-09-20 00:10:42 +02:00
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 ) ) ;
2020-07-26 10:03:38 +02:00
} else {
2021-09-20 00:10:42 +02:00
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 ) ) ;
2020-07-26 10:03:38 +02:00
}
} else {
2021-09-20 00:10:42 +02:00
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 ) ) ;
2020-07-26 10:03:38 +02:00
} else {
2021-09-20 00:10:42 +02:00
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 ) ) ;
2020-07-26 10:03:38 +02:00
}
}
2018-07-30 04:07:02 +02:00
2020-07-26 10:03:38 +02:00
while ( cursor . next ( ) ) {
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
message . readAttachPath ( data , getUserConfig ( ) . clientUserId ) ;
data . reuse ( ) ;
if ( MessageObject . isMusicMessage ( message ) ) {
message . id = cursor . intValue ( 1 ) ;
2021-09-20 00:10:42 +02:00
message . dialog_id = dialogId ;
2020-08-14 18:58:22 +02:00
arrayList . add ( 0 , new MessageObject ( currentAccount , message , false , true ) ) ;
2020-07-26 10:03:38 +02:00
}
2018-07-30 04:07:02 +02:00
}
}
2020-07-26 10:03:38 +02:00
cursor . dispose ( ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > getNotificationCenter ( ) . postNotificationName ( NotificationCenter . musicDidLoad , dialogId , arrayListBegin , arrayListEnd ) ) ;
2018-07-30 04:07:02 +02:00
} ) ;
}
//---------------- MEDIA END ----------------
public ArrayList < TLRPC . TL_topPeer > hints = new ArrayList < > ( ) ;
public ArrayList < TLRPC . TL_topPeer > inlineBots = new ArrayList < > ( ) ;
boolean loaded ;
boolean loading ;
private static Paint roundPaint , erasePaint ;
private static RectF bitmapRect ;
private static Path roundPath ;
public void buildShortcuts ( ) {
2020-07-26 10:03:38 +02:00
if ( Build . VERSION . SDK_INT < 23 ) {
2018-07-30 04:07:02 +02:00
return ;
}
2020-07-26 10:03:38 +02:00
int maxShortcuts = ShortcutManagerCompat . getMaxShortcutCountPerActivity ( ApplicationLoader . applicationContext ) - 2 ;
if ( maxShortcuts < = 0 ) {
maxShortcuts = 5 ;
}
2021-09-20 00:10:42 +02:00
ArrayList < TLRPC . TL_topPeer > hintsFinal = new ArrayList < > ( ) ;
2019-12-31 14:08:08 +01:00
if ( SharedConfig . passcodeHash . length ( ) < = 0 ) {
for ( int a = 0 ; a < hints . size ( ) ; a + + ) {
hintsFinal . add ( hints . get ( a ) ) ;
2020-07-26 10:03:38 +02:00
if ( hintsFinal . size ( ) = = maxShortcuts - 2 ) {
2019-12-31 14:08:08 +01:00
break ;
}
2018-07-30 04:07:02 +02:00
}
}
2019-01-23 18:03:33 +01:00
Utilities . globalQueue . postRunnable ( ( ) - > {
try {
2020-07-26 10:03:38 +02:00
if ( SharedConfig . directShareHash = = null ) {
SharedConfig . directShareHash = UUID . randomUUID ( ) . toString ( ) ;
ApplicationLoader . applicationContext . getSharedPreferences ( " mainconfig " , Activity . MODE_PRIVATE ) . edit ( ) . putString ( " directShareHash2 " , SharedConfig . directShareHash ) . commit ( ) ;
}
List < ShortcutInfoCompat > currentShortcuts = ShortcutManagerCompat . getDynamicShortcuts ( ApplicationLoader . applicationContext ) ;
2019-01-23 18:03:33 +01:00
ArrayList < String > shortcutsToUpdate = new ArrayList < > ( ) ;
ArrayList < String > newShortcutsIds = new ArrayList < > ( ) ;
ArrayList < String > shortcutsToDelete = new ArrayList < > ( ) ;
2018-07-30 04:07:02 +02:00
2019-01-23 18:03:33 +01:00
if ( currentShortcuts ! = null & & ! currentShortcuts . isEmpty ( ) ) {
newShortcutsIds . add ( " compose " ) ;
2018-07-30 04:07:02 +02:00
for ( int a = 0 ; a < hintsFinal . size ( ) ; a + + ) {
TLRPC . TL_topPeer hint = hintsFinal . get ( a ) ;
2021-09-20 00:10:42 +02:00
newShortcutsIds . add ( " did3_ " + MessageObject . getPeerId ( hint . peer ) ) ;
2019-01-23 18:03:33 +01:00
}
for ( int a = 0 ; a < currentShortcuts . size ( ) ; a + + ) {
String id = currentShortcuts . get ( a ) . getId ( ) ;
if ( ! newShortcutsIds . remove ( id ) ) {
shortcutsToDelete . add ( id ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
shortcutsToUpdate . add ( id ) ;
}
if ( newShortcutsIds . isEmpty ( ) & & shortcutsToDelete . isEmpty ( ) ) {
return ;
}
}
2018-07-30 04:07:02 +02:00
2019-01-23 18:03:33 +01:00
Intent intent = new Intent ( ApplicationLoader . applicationContext , LaunchActivity . class ) ;
intent . setAction ( " new_dialog " ) ;
2020-07-26 10:03:38 +02:00
ArrayList < ShortcutInfoCompat > arrayList = new ArrayList < > ( ) ;
arrayList . add ( new ShortcutInfoCompat . Builder ( ApplicationLoader . applicationContext , " compose " )
2019-01-23 18:03:33 +01:00
. setShortLabel ( LocaleController . getString ( " NewConversationShortcut " , R . string . NewConversationShortcut ) )
. setLongLabel ( LocaleController . getString ( " NewConversationShortcut " , R . string . NewConversationShortcut ) )
2020-07-26 10:03:38 +02:00
. setIcon ( IconCompat . createWithResource ( ApplicationLoader . applicationContext , R . drawable . shortcut_compose ) )
2019-01-23 18:03:33 +01:00
. setIntent ( intent )
. build ( ) ) ;
if ( shortcutsToUpdate . contains ( " compose " ) ) {
2020-07-26 10:03:38 +02:00
ShortcutManagerCompat . updateShortcuts ( ApplicationLoader . applicationContext , arrayList ) ;
2019-01-23 18:03:33 +01:00
} else {
2020-07-26 10:03:38 +02:00
ShortcutManagerCompat . addDynamicShortcuts ( ApplicationLoader . applicationContext , arrayList ) ;
2019-01-23 18:03:33 +01:00
}
arrayList . clear ( ) ;
2018-07-30 04:07:02 +02:00
2019-01-23 18:03:33 +01:00
if ( ! shortcutsToDelete . isEmpty ( ) ) {
2020-07-26 10:03:38 +02:00
ShortcutManagerCompat . removeDynamicShortcuts ( ApplicationLoader . applicationContext , shortcutsToDelete ) ;
2019-01-23 18:03:33 +01:00
}
2018-07-30 04:07:02 +02:00
2020-07-26 10:03:38 +02:00
HashSet < String > category = new HashSet < > ( 1 ) ;
category . add ( SHORTCUT_CATEGORY ) ;
2019-01-23 18:03:33 +01:00
for ( int a = 0 ; a < hintsFinal . size ( ) ; a + + ) {
Intent shortcutIntent = new Intent ( ApplicationLoader . applicationContext , OpenChatReceiver . class ) ;
TLRPC . TL_topPeer hint = hintsFinal . get ( a ) ;
2018-07-30 04:07:02 +02:00
2019-01-23 18:03:33 +01:00
TLRPC . User user = null ;
TLRPC . Chat chat = null ;
2021-09-20 00:10:42 +02:00
long peerId = MessageObject . getPeerId ( hint . peer ) ;
if ( DialogObject . isUserDialog ( peerId ) ) {
shortcutIntent . putExtra ( " userId " , peerId ) ;
user = getMessagesController ( ) . getUser ( peerId ) ;
2019-01-23 18:03:33 +01:00
} else {
2021-09-20 00:10:42 +02:00
chat = getMessagesController ( ) . getChat ( - peerId ) ;
shortcutIntent . putExtra ( " chatId " , - peerId ) ;
2019-01-23 18:03:33 +01:00
}
2019-06-04 12:14:50 +02:00
if ( ( user = = null | | UserObject . isDeleted ( user ) ) & & chat = = null ) {
2019-01-23 18:03:33 +01:00
continue ;
}
String name ;
TLRPC . FileLocation photo = null ;
2018-07-30 04:07:02 +02:00
2019-01-23 18:03:33 +01:00
if ( user ! = null ) {
name = ContactsController . formatName ( user . first_name , user . last_name ) ;
if ( user . photo ! = null ) {
photo = user . photo . photo_small ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} else {
name = chat . title ;
if ( chat . photo ! = null ) {
photo = chat . photo . photo_small ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
}
shortcutIntent . putExtra ( " currentAccount " , currentAccount ) ;
2021-09-20 00:10:42 +02:00
shortcutIntent . setAction ( " com.tmessages.openchat " + peerId ) ;
shortcutIntent . putExtra ( " dialogId " , peerId ) ;
2020-07-26 10:03:38 +02:00
shortcutIntent . putExtra ( " hash " , SharedConfig . directShareHash ) ;
2019-01-23 18:03:33 +01:00
shortcutIntent . addFlags ( Intent . FLAG_ACTIVITY_CLEAR_TOP ) ;
Bitmap bitmap = null ;
if ( photo ! = null ) {
try {
File path = FileLoader . getPathToAttach ( photo , true ) ;
bitmap = BitmapFactory . decodeFile ( path . toString ( ) ) ;
if ( bitmap ! = null ) {
int size = AndroidUtilities . dp ( 48 ) ;
Bitmap result = Bitmap . createBitmap ( size , size , Bitmap . Config . ARGB_8888 ) ;
Canvas canvas = new Canvas ( result ) ;
if ( roundPaint = = null ) {
roundPaint = new Paint ( Paint . ANTI_ALIAS_FLAG | Paint . FILTER_BITMAP_FLAG ) ;
bitmapRect = new RectF ( ) ;
erasePaint = new Paint ( Paint . ANTI_ALIAS_FLAG ) ;
erasePaint . setXfermode ( new PorterDuffXfermode ( PorterDuff . Mode . CLEAR ) ) ;
roundPath = new Path ( ) ;
roundPath . addCircle ( size / 2 , size / 2 , size / 2 - AndroidUtilities . dp ( 2 ) , Path . Direction . CW ) ;
roundPath . toggleInverseFillType ( ) ;
}
bitmapRect . set ( AndroidUtilities . dp ( 2 ) , AndroidUtilities . dp ( 2 ) , AndroidUtilities . dp ( 46 ) , AndroidUtilities . dp ( 46 ) ) ;
canvas . drawBitmap ( bitmap , null , bitmapRect , roundPaint ) ;
canvas . drawPath ( roundPath , erasePaint ) ;
try {
canvas . setBitmap ( null ) ;
} catch ( Exception ignore ) {
}
bitmap = result ;
}
} catch ( Throwable e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
}
2021-09-20 00:10:42 +02:00
String id = " did3_ " + peerId ;
2019-01-23 18:03:33 +01:00
if ( TextUtils . isEmpty ( name ) ) {
name = " " ;
}
2020-07-26 10:03:38 +02:00
ShortcutInfoCompat . Builder builder = new ShortcutInfoCompat . Builder ( ApplicationLoader . applicationContext , id )
2019-01-23 18:03:33 +01:00
. setShortLabel ( name )
. setLongLabel ( name )
. setIntent ( shortcutIntent ) ;
2020-07-26 10:03:38 +02:00
if ( SharedConfig . directShare ) {
builder . setCategories ( category ) ;
}
2019-01-23 18:03:33 +01:00
if ( bitmap ! = null ) {
2020-07-26 10:03:38 +02:00
builder . setIcon ( IconCompat . createWithBitmap ( bitmap ) ) ;
2019-01-23 18:03:33 +01:00
} else {
2020-07-26 10:03:38 +02:00
builder . setIcon ( IconCompat . createWithResource ( ApplicationLoader . applicationContext , R . drawable . shortcut_user ) ) ;
2019-01-23 18:03:33 +01:00
}
arrayList . add ( builder . build ( ) ) ;
if ( shortcutsToUpdate . contains ( id ) ) {
2020-07-26 10:03:38 +02:00
ShortcutManagerCompat . updateShortcuts ( ApplicationLoader . applicationContext , arrayList ) ;
2019-01-23 18:03:33 +01:00
} else {
2020-07-26 10:03:38 +02:00
ShortcutManagerCompat . addDynamicShortcuts ( ApplicationLoader . applicationContext , arrayList ) ;
2019-01-23 18:03:33 +01:00
}
arrayList . clear ( ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} catch ( Throwable ignore ) {
2018-07-30 04:07:02 +02:00
}
} ) ;
}
public void loadHints ( boolean cache ) {
2019-07-18 15:01:39 +02:00
if ( loading | | ! getUserConfig ( ) . suggestContacts ) {
2018-07-30 04:07:02 +02:00
return ;
}
if ( cache ) {
if ( loaded ) {
return ;
}
loading = true ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2021-09-20 00:10:42 +02:00
ArrayList < TLRPC . TL_topPeer > hintsNew = new ArrayList < > ( ) ;
ArrayList < TLRPC . TL_topPeer > inlineBotsNew = new ArrayList < > ( ) ;
ArrayList < TLRPC . User > users = new ArrayList < > ( ) ;
ArrayList < TLRPC . Chat > chats = new ArrayList < > ( ) ;
long selfUserId = getUserConfig ( ) . getClientUserId ( ) ;
2019-01-23 18:03:33 +01:00
try {
2021-09-20 00:10:42 +02:00
ArrayList < Long > usersToLoad = new ArrayList < > ( ) ;
ArrayList < Long > chatsToLoad = new ArrayList < > ( ) ;
2019-07-18 15:01:39 +02:00
SQLiteCursor cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( " SELECT did, type, rating FROM chat_hints WHERE 1 ORDER BY rating DESC " ) ;
2019-01-23 18:03:33 +01:00
while ( cursor . next ( ) ) {
2021-09-20 00:10:42 +02:00
long did = cursor . longValue ( 0 ) ;
2019-01-23 18:03:33 +01:00
if ( did = = selfUserId ) {
continue ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
int type = cursor . intValue ( 1 ) ;
TLRPC . TL_topPeer peer = new TLRPC . TL_topPeer ( ) ;
peer . rating = cursor . doubleValue ( 2 ) ;
if ( did > 0 ) {
peer . peer = new TLRPC . TL_peerUser ( ) ;
peer . peer . user_id = did ;
usersToLoad . add ( did ) ;
} else {
peer . peer = new TLRPC . TL_peerChat ( ) ;
peer . peer . chat_id = - did ;
chatsToLoad . add ( - did ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
if ( type = = 0 ) {
hintsNew . add ( peer ) ;
} else if ( type = = 1 ) {
inlineBotsNew . add ( peer ) ;
2018-07-30 04:07:02 +02:00
}
}
2019-01-23 18:03:33 +01:00
cursor . dispose ( ) ;
if ( ! usersToLoad . isEmpty ( ) ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getUsersInternal ( TextUtils . join ( " , " , usersToLoad ) , users ) ;
2019-01-23 18:03:33 +01:00
}
if ( ! chatsToLoad . isEmpty ( ) ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getChatsInternal ( TextUtils . join ( " , " , chatsToLoad ) , chats ) ;
2019-01-23 18:03:33 +01:00
}
AndroidUtilities . runOnUIThread ( ( ) - > {
2019-07-18 15:01:39 +02:00
getMessagesController ( ) . putUsers ( users , true ) ;
getMessagesController ( ) . putChats ( chats , true ) ;
2019-01-23 18:03:33 +01:00
loading = false ;
loaded = true ;
hints = hintsNew ;
inlineBots = inlineBotsNew ;
buildShortcuts ( ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . reloadHints ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . reloadInlineHints ) ;
if ( Math . abs ( getUserConfig ( ) . lastHintsSyncTime - ( int ) ( System . currentTimeMillis ( ) / 1000 ) ) > = 24 * 60 * 60 ) {
2019-01-23 18:03:33 +01:00
loadHints ( false ) ;
}
} ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
loaded = true ;
} else {
loading = true ;
TLRPC . TL_contacts_getTopPeers req = new TLRPC . TL_contacts_getTopPeers ( ) ;
req . hash = 0 ;
req . bots_pm = false ;
req . correspondents = true ;
req . groups = false ;
req . channels = false ;
req . bots_inline = true ;
req . offset = 0 ;
req . limit = 20 ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2019-01-23 18:03:33 +01:00
if ( response instanceof TLRPC . TL_contacts_topPeers ) {
AndroidUtilities . runOnUIThread ( ( ) - > {
2021-09-20 00:10:42 +02:00
TLRPC . TL_contacts_topPeers topPeers = ( TLRPC . TL_contacts_topPeers ) response ;
2019-07-18 15:01:39 +02:00
getMessagesController ( ) . putUsers ( topPeers . users , false ) ;
getMessagesController ( ) . putChats ( topPeers . chats , false ) ;
2019-01-23 18:03:33 +01:00
for ( int a = 0 ; a < topPeers . categories . size ( ) ; a + + ) {
TLRPC . TL_topPeerCategoryPeers category = topPeers . categories . get ( a ) ;
if ( category . category instanceof TLRPC . TL_topPeerCategoryBotsInline ) {
inlineBots = category . peers ;
2019-07-18 15:01:39 +02:00
getUserConfig ( ) . botRatingLoadTime = ( int ) ( System . currentTimeMillis ( ) / 1000 ) ;
2019-01-23 18:03:33 +01:00
} else {
hints = category . peers ;
2021-09-20 00:10:42 +02:00
long selfUserId = getUserConfig ( ) . getClientUserId ( ) ;
2019-01-23 18:03:33 +01:00
for ( int b = 0 ; b < hints . size ( ) ; b + + ) {
TLRPC . TL_topPeer topPeer = hints . get ( b ) ;
if ( topPeer . peer . user_id = = selfUserId ) {
hints . remove ( b ) ;
break ;
}
}
2019-07-18 15:01:39 +02:00
getUserConfig ( ) . ratingLoadTime = ( int ) ( System . currentTimeMillis ( ) / 1000 ) ;
2019-01-23 18:03:33 +01:00
}
}
2019-07-18 15:01:39 +02:00
getUserConfig ( ) . saveConfig ( false ) ;
2019-01-23 18:03:33 +01:00
buildShortcuts ( ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . reloadHints ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . reloadInlineHints ) ;
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " DELETE FROM chat_hints WHERE 1 " ) . stepThis ( ) . dispose ( ) ;
getMessagesStorage ( ) . getDatabase ( ) . beginTransaction ( ) ;
getMessagesStorage ( ) . putUsersAndChats ( topPeers . users , topPeers . chats , false , false ) ;
2019-01-23 18:03:33 +01:00
2019-07-18 15:01:39 +02:00
SQLitePreparedStatement state = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " REPLACE INTO chat_hints VALUES(?, ?, ?, ?) " ) ;
2018-07-30 04:07:02 +02:00
for ( int a = 0 ; a < topPeers . categories . size ( ) ; a + + ) {
2019-01-23 18:03:33 +01:00
int type ;
2018-07-30 04:07:02 +02:00
TLRPC . TL_topPeerCategoryPeers category = topPeers . categories . get ( a ) ;
if ( category . category instanceof TLRPC . TL_topPeerCategoryBotsInline ) {
2019-01-23 18:03:33 +01:00
type = 1 ;
2018-07-30 04:07:02 +02:00
} else {
2019-01-23 18:03:33 +01:00
type = 0 ;
}
for ( int b = 0 ; b < category . peers . size ( ) ; b + + ) {
TLRPC . TL_topPeer peer = category . peers . get ( b ) ;
state . requery ( ) ;
2021-09-20 00:10:42 +02:00
state . bindLong ( 1 , MessageObject . getPeerId ( peer . peer ) ) ;
2019-01-23 18:03:33 +01:00
state . bindInteger ( 2 , type ) ;
state . bindDouble ( 3 , peer . rating ) ;
state . bindInteger ( 4 , 0 ) ;
state . step ( ) ;
2018-07-30 04:07:02 +02:00
}
}
2019-01-23 18:03:33 +01:00
state . dispose ( ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getDatabase ( ) . commitTransaction ( ) ;
2019-01-23 18:03:33 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > {
2019-07-18 15:01:39 +02:00
getUserConfig ( ) . suggestContacts = true ;
getUserConfig ( ) . lastHintsSyncTime = ( int ) ( System . currentTimeMillis ( ) / 1000 ) ;
getUserConfig ( ) . saveConfig ( false ) ;
2018-07-30 04:07:02 +02:00
} ) ;
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
2019-01-23 18:03:33 +01:00
} ) ;
} else if ( response instanceof TLRPC . TL_contacts_topPeersDisabled ) {
AndroidUtilities . runOnUIThread ( ( ) - > {
2019-07-18 15:01:39 +02:00
getUserConfig ( ) . suggestContacts = false ;
getUserConfig ( ) . lastHintsSyncTime = ( int ) ( System . currentTimeMillis ( ) / 1000 ) ;
getUserConfig ( ) . saveConfig ( false ) ;
2019-01-23 18:03:33 +01:00
clearTopPeers ( ) ;
} ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
}
public void clearTopPeers ( ) {
hints . clear ( ) ;
inlineBots . clear ( ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . reloadHints ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . reloadInlineHints ) ;
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " DELETE FROM chat_hints WHERE 1 " ) . stepThis ( ) . dispose ( ) ;
2019-01-23 18:03:33 +01:00
} catch ( Exception ignore ) {
2018-07-30 04:07:02 +02:00
}
} ) ;
buildShortcuts ( ) ;
}
2021-09-20 00:10:42 +02:00
public void increaseInlineRaiting ( long uid ) {
2019-07-18 15:01:39 +02:00
if ( ! getUserConfig ( ) . suggestContacts ) {
2018-07-30 04:07:02 +02:00
return ;
}
int dt ;
2019-07-18 15:01:39 +02:00
if ( getUserConfig ( ) . botRatingLoadTime ! = 0 ) {
dt = Math . max ( 1 , ( ( int ) ( System . currentTimeMillis ( ) / 1000 ) ) - getUserConfig ( ) . botRatingLoadTime ) ;
2018-07-30 04:07:02 +02:00
} else {
dt = 60 ;
}
TLRPC . TL_topPeer peer = null ;
for ( int a = 0 ; a < inlineBots . size ( ) ; a + + ) {
TLRPC . TL_topPeer p = inlineBots . get ( a ) ;
if ( p . peer . user_id = = uid ) {
peer = p ;
break ;
}
}
if ( peer = = null ) {
peer = new TLRPC . TL_topPeer ( ) ;
peer . peer = new TLRPC . TL_peerUser ( ) ;
peer . peer . user_id = uid ;
inlineBots . add ( peer ) ;
}
2019-07-18 15:01:39 +02:00
peer . rating + = Math . exp ( dt / getMessagesController ( ) . ratingDecay ) ;
2019-01-23 18:03:33 +01:00
Collections . sort ( inlineBots , ( lhs , rhs ) - > {
if ( lhs . rating > rhs . rating ) {
return - 1 ;
} else if ( lhs . rating < rhs . rating ) {
return 1 ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
return 0 ;
2018-07-30 04:07:02 +02:00
} ) ;
if ( inlineBots . size ( ) > 20 ) {
inlineBots . remove ( inlineBots . size ( ) - 1 ) ;
}
savePeer ( uid , 1 , peer . rating ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . reloadInlineHints ) ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
public void removeInline ( long dialogId ) {
2018-07-30 04:07:02 +02:00
TLRPC . TL_topPeerCategoryPeers category = null ;
for ( int a = 0 ; a < inlineBots . size ( ) ; a + + ) {
2021-09-20 00:10:42 +02:00
if ( inlineBots . get ( a ) . peer . user_id = = dialogId ) {
2018-07-30 04:07:02 +02:00
inlineBots . remove ( a ) ;
TLRPC . TL_contacts_resetTopPeerRating req = new TLRPC . TL_contacts_resetTopPeerRating ( ) ;
req . category = new TLRPC . TL_topPeerCategoryBotsInline ( ) ;
2021-09-20 00:10:42 +02:00
req . peer = getMessagesController ( ) . getInputPeer ( dialogId ) ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2018-07-30 04:07:02 +02:00
} ) ;
2021-09-20 00:10:42 +02:00
deletePeer ( dialogId , 1 ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . reloadInlineHints ) ;
2018-07-30 04:07:02 +02:00
return ;
}
}
}
2021-09-20 00:10:42 +02:00
public void removePeer ( long uid ) {
2018-07-30 04:07:02 +02:00
for ( int a = 0 ; a < hints . size ( ) ; a + + ) {
if ( hints . get ( a ) . peer . user_id = = uid ) {
hints . remove ( a ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . reloadHints ) ;
2018-07-30 04:07:02 +02:00
TLRPC . TL_contacts_resetTopPeerRating req = new TLRPC . TL_contacts_resetTopPeerRating ( ) ;
req . category = new TLRPC . TL_topPeerCategoryCorrespondents ( ) ;
2019-07-18 15:01:39 +02:00
req . peer = getMessagesController ( ) . getInputPeer ( uid ) ;
2018-07-30 04:07:02 +02:00
deletePeer ( uid , 0 ) ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2018-07-30 04:07:02 +02:00
} ) ;
return ;
}
}
}
2021-09-20 00:10:42 +02:00
public void increasePeerRaiting ( long dialogId ) {
2019-07-18 15:01:39 +02:00
if ( ! getUserConfig ( ) . suggestContacts ) {
2018-07-30 04:07:02 +02:00
return ;
}
2021-09-20 00:10:42 +02:00
if ( ! DialogObject . isUserDialog ( dialogId ) ) {
2018-07-30 04:07:02 +02:00
return ;
}
2021-09-20 00:10:42 +02:00
TLRPC . User user = getMessagesController ( ) . getUser ( dialogId ) ;
if ( user = = null | | user . bot | | user . self ) {
2018-07-30 04:07:02 +02:00
return ;
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
double dt = 0 ;
try {
int lastTime = 0 ;
int lastMid = 0 ;
2021-09-20 00:10:42 +02:00
SQLiteCursor cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT MAX(mid), MAX(date) FROM messages_v2 WHERE uid = %d AND out = 1 " , dialogId ) ) ;
2019-01-23 18:03:33 +01:00
if ( cursor . next ( ) ) {
lastMid = cursor . intValue ( 0 ) ;
lastTime = cursor . intValue ( 1 ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
cursor . dispose ( ) ;
2019-07-18 15:01:39 +02:00
if ( lastMid > 0 & & getUserConfig ( ) . ratingLoadTime ! = 0 ) {
dt = ( lastTime - getUserConfig ( ) . ratingLoadTime ) ;
2019-01-23 18:03:33 +01:00
}
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
2021-09-20 00:10:42 +02:00
double dtFinal = dt ;
2019-01-23 18:03:33 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > {
TLRPC . TL_topPeer peer = null ;
for ( int a = 0 ; a < hints . size ( ) ; a + + ) {
TLRPC . TL_topPeer p = hints . get ( a ) ;
2021-09-20 00:10:42 +02:00
if ( p . peer . user_id = = dialogId ) {
2019-01-23 18:03:33 +01:00
peer = p ;
break ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
}
if ( peer = = null ) {
peer = new TLRPC . TL_topPeer ( ) ;
2021-09-20 00:10:42 +02:00
peer . peer = new TLRPC . TL_peerUser ( ) ;
peer . peer . user_id = dialogId ;
2019-01-23 18:03:33 +01:00
hints . add ( peer ) ;
}
2019-07-18 15:01:39 +02:00
peer . rating + = Math . exp ( dtFinal / getMessagesController ( ) . ratingDecay ) ;
2019-01-23 18:03:33 +01:00
Collections . sort ( hints , ( lhs , rhs ) - > {
if ( lhs . rating > rhs . rating ) {
return - 1 ;
} else if ( lhs . rating < rhs . rating ) {
return 1 ;
}
return 0 ;
2018-07-30 04:07:02 +02:00
} ) ;
2019-01-23 18:03:33 +01:00
2021-09-20 00:10:42 +02:00
savePeer ( dialogId , 0 , peer . rating ) ;
2019-01-23 18:03:33 +01:00
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . reloadHints ) ;
2019-01-23 18:03:33 +01:00
} ) ;
2018-07-30 04:07:02 +02:00
} ) ;
}
2021-09-20 00:10:42 +02:00
private void savePeer ( long did , int type , double rating ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2019-07-18 15:01:39 +02:00
SQLitePreparedStatement state = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " REPLACE INTO chat_hints VALUES(?, ?, ?, ?) " ) ;
2019-01-23 18:03:33 +01:00
state . requery ( ) ;
2021-09-20 00:10:42 +02:00
state . bindLong ( 1 , did ) ;
2019-01-23 18:03:33 +01:00
state . bindInteger ( 2 , type ) ;
state . bindDouble ( 3 , rating ) ;
state . bindInteger ( 4 , ( int ) System . currentTimeMillis ( ) / 1000 ) ;
state . step ( ) ;
state . dispose ( ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2021-09-20 00:10:42 +02:00
private void deletePeer ( long dialogId , int type ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2021-09-20 00:10:42 +02:00
getMessagesStorage ( ) . getDatabase ( ) . executeFast ( String . format ( Locale . US , " DELETE FROM chat_hints WHERE did = %d AND type = %d " , dialogId , type ) ) . stepThis ( ) . dispose ( ) ;
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2021-09-20 00:10:42 +02:00
private Intent createIntrnalShortcutIntent ( long dialogId ) {
2018-07-30 04:07:02 +02:00
Intent shortcutIntent = new Intent ( ApplicationLoader . applicationContext , OpenChatReceiver . class ) ;
2021-09-20 00:10:42 +02:00
if ( DialogObject . isEncryptedDialog ( dialogId ) ) {
int encryptedChatId = DialogObject . getEncryptedChatId ( dialogId ) ;
shortcutIntent . putExtra ( " encId " , encryptedChatId ) ;
TLRPC . EncryptedChat encryptedChat = getMessagesController ( ) . getEncryptedChat ( encryptedChatId ) ;
2018-07-30 04:07:02 +02:00
if ( encryptedChat = = null ) {
return null ;
}
2021-09-20 00:10:42 +02:00
} else if ( DialogObject . isUserDialog ( dialogId ) ) {
shortcutIntent . putExtra ( " userId " , dialogId ) ;
} else if ( DialogObject . isChatDialog ( dialogId ) ) {
shortcutIntent . putExtra ( " chatId " , - dialogId ) ;
2018-07-30 04:07:02 +02:00
} else {
return null ;
}
shortcutIntent . putExtra ( " currentAccount " , currentAccount ) ;
2021-09-20 00:10:42 +02:00
shortcutIntent . setAction ( " com.tmessages.openchat " + dialogId ) ;
2018-07-30 04:07:02 +02:00
shortcutIntent . addFlags ( Intent . FLAG_ACTIVITY_CLEAR_TOP ) ;
return shortcutIntent ;
}
2021-09-20 00:10:42 +02:00
public void installShortcut ( long dialogId ) {
2018-07-30 04:07:02 +02:00
try {
2021-09-20 00:10:42 +02:00
Intent shortcutIntent = createIntrnalShortcutIntent ( dialogId ) ;
2018-07-30 04:07:02 +02:00
TLRPC . User user = null ;
TLRPC . Chat chat = null ;
2021-09-20 00:10:42 +02:00
if ( DialogObject . isEncryptedDialog ( dialogId ) ) {
int encryptedChatId = DialogObject . getEncryptedChatId ( dialogId ) ;
TLRPC . EncryptedChat encryptedChat = getMessagesController ( ) . getEncryptedChat ( encryptedChatId ) ;
2018-07-30 04:07:02 +02:00
if ( encryptedChat = = null ) {
return ;
}
2019-07-18 15:01:39 +02:00
user = getMessagesController ( ) . getUser ( encryptedChat . user_id ) ;
2021-09-20 00:10:42 +02:00
} else if ( DialogObject . isUserDialog ( dialogId ) ) {
user = getMessagesController ( ) . getUser ( dialogId ) ;
} else if ( DialogObject . isChatDialog ( dialogId ) ) {
chat = getMessagesController ( ) . getChat ( - dialogId ) ;
2018-07-30 04:07:02 +02:00
} else {
return ;
}
if ( user = = null & & chat = = null ) {
return ;
}
String name ;
TLRPC . FileLocation photo = null ;
2020-09-30 15:48:47 +02:00
boolean overrideAvatar = false ;
2018-07-30 04:07:02 +02:00
if ( user ! = null ) {
2020-09-30 15:48:47 +02:00
if ( UserObject . isReplyUser ( user ) ) {
name = LocaleController . getString ( " RepliesTitle " , R . string . RepliesTitle ) ;
overrideAvatar = true ;
} else if ( UserObject . isUserSelf ( user ) ) {
2018-07-30 04:07:02 +02:00
name = LocaleController . getString ( " SavedMessages " , R . string . SavedMessages ) ;
2020-09-30 15:48:47 +02:00
overrideAvatar = true ;
2018-07-30 04:07:02 +02:00
} else {
name = ContactsController . formatName ( user . first_name , user . last_name ) ;
if ( user . photo ! = null ) {
photo = user . photo . photo_small ;
}
}
} else {
name = chat . title ;
if ( chat . photo ! = null ) {
photo = chat . photo . photo_small ;
}
}
Bitmap bitmap = null ;
2020-09-30 15:48:47 +02:00
if ( overrideAvatar | | photo ! = null ) {
2018-07-30 04:07:02 +02:00
try {
2020-09-30 15:48:47 +02:00
if ( ! overrideAvatar ) {
2018-07-30 04:07:02 +02:00
File path = FileLoader . getPathToAttach ( photo , true ) ;
bitmap = BitmapFactory . decodeFile ( path . toString ( ) ) ;
}
2020-09-30 15:48:47 +02:00
if ( overrideAvatar | | bitmap ! = null ) {
2018-07-30 04:07:02 +02:00
int size = AndroidUtilities . dp ( 58 ) ;
Bitmap result = Bitmap . createBitmap ( size , size , Bitmap . Config . ARGB_8888 ) ;
result . eraseColor ( Color . TRANSPARENT ) ;
Canvas canvas = new Canvas ( result ) ;
2020-09-30 15:48:47 +02:00
if ( overrideAvatar ) {
2018-07-30 04:07:02 +02:00
AvatarDrawable avatarDrawable = new AvatarDrawable ( user ) ;
2020-09-30 15:48:47 +02:00
if ( UserObject . isReplyUser ( user ) ) {
avatarDrawable . setAvatarType ( AvatarDrawable . AVATAR_TYPE_REPLIES ) ;
} else {
avatarDrawable . setAvatarType ( AvatarDrawable . AVATAR_TYPE_SAVED ) ;
}
2018-07-30 04:07:02 +02:00
avatarDrawable . setBounds ( 0 , 0 , size , size ) ;
avatarDrawable . draw ( canvas ) ;
} else {
BitmapShader shader = new BitmapShader ( bitmap , Shader . TileMode . CLAMP , Shader . TileMode . CLAMP ) ;
if ( roundPaint = = null ) {
roundPaint = new Paint ( Paint . ANTI_ALIAS_FLAG ) ;
bitmapRect = new RectF ( ) ;
}
float scale = size / ( float ) bitmap . getWidth ( ) ;
canvas . save ( ) ;
canvas . scale ( scale , scale ) ;
roundPaint . setShader ( shader ) ;
bitmapRect . set ( 0 , 0 , bitmap . getWidth ( ) , bitmap . getHeight ( ) ) ;
canvas . drawRoundRect ( bitmapRect , bitmap . getWidth ( ) , bitmap . getHeight ( ) , roundPaint ) ;
canvas . restore ( ) ;
}
Drawable drawable = ApplicationLoader . applicationContext . getResources ( ) . getDrawable ( R . drawable . book_logo ) ;
int w = AndroidUtilities . dp ( 15 ) ;
int left = size - w - AndroidUtilities . dp ( 2 ) ;
int top = size - w - AndroidUtilities . dp ( 2 ) ;
drawable . setBounds ( left , top , left + w , top + w ) ;
drawable . draw ( canvas ) ;
try {
canvas . setBitmap ( null ) ;
} catch ( Exception e ) {
//don't promt, this will crash on 2.x
}
bitmap = result ;
}
} catch ( Throwable e ) {
FileLog . e ( e ) ;
}
}
if ( Build . VERSION . SDK_INT > = 26 ) {
2020-07-26 10:03:38 +02:00
ShortcutInfoCompat . Builder pinShortcutInfo =
2021-09-20 00:10:42 +02:00
new ShortcutInfoCompat . Builder ( ApplicationLoader . applicationContext , " sdid_ " + dialogId )
2018-07-30 04:07:02 +02:00
. setShortLabel ( name )
. setIntent ( shortcutIntent ) ;
if ( bitmap ! = null ) {
2020-07-26 10:03:38 +02:00
pinShortcutInfo . setIcon ( IconCompat . createWithBitmap ( bitmap ) ) ;
2018-07-30 04:07:02 +02:00
} else {
if ( user ! = null ) {
if ( user . bot ) {
2020-07-26 10:03:38 +02:00
pinShortcutInfo . setIcon ( IconCompat . createWithResource ( ApplicationLoader . applicationContext , R . drawable . book_bot ) ) ;
2018-07-30 04:07:02 +02:00
} else {
2020-07-26 10:03:38 +02:00
pinShortcutInfo . setIcon ( IconCompat . createWithResource ( ApplicationLoader . applicationContext , R . drawable . book_user ) ) ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
} else {
2018-07-30 04:07:02 +02:00
if ( ChatObject . isChannel ( chat ) & & ! chat . megagroup ) {
2020-07-26 10:03:38 +02:00
pinShortcutInfo . setIcon ( IconCompat . createWithResource ( ApplicationLoader . applicationContext , R . drawable . book_channel ) ) ;
2018-07-30 04:07:02 +02:00
} else {
2020-07-26 10:03:38 +02:00
pinShortcutInfo . setIcon ( IconCompat . createWithResource ( ApplicationLoader . applicationContext , R . drawable . book_group ) ) ;
2018-07-30 04:07:02 +02:00
}
}
}
2020-07-26 10:03:38 +02:00
ShortcutManagerCompat . requestPinShortcut ( ApplicationLoader . applicationContext , pinShortcutInfo . build ( ) , null ) ;
2018-07-30 04:07:02 +02:00
} else {
Intent addIntent = new Intent ( ) ;
if ( bitmap ! = null ) {
addIntent . putExtra ( Intent . EXTRA_SHORTCUT_ICON , bitmap ) ;
} else {
if ( user ! = null ) {
if ( user . bot ) {
addIntent . putExtra ( Intent . EXTRA_SHORTCUT_ICON_RESOURCE , Intent . ShortcutIconResource . fromContext ( ApplicationLoader . applicationContext , R . drawable . book_bot ) ) ;
} else {
addIntent . putExtra ( Intent . EXTRA_SHORTCUT_ICON_RESOURCE , Intent . ShortcutIconResource . fromContext ( ApplicationLoader . applicationContext , R . drawable . book_user ) ) ;
}
2021-09-20 00:10:42 +02:00
} else {
2018-07-30 04:07:02 +02:00
if ( ChatObject . isChannel ( chat ) & & ! chat . megagroup ) {
addIntent . putExtra ( Intent . EXTRA_SHORTCUT_ICON_RESOURCE , Intent . ShortcutIconResource . fromContext ( ApplicationLoader . applicationContext , R . drawable . book_channel ) ) ;
} else {
addIntent . putExtra ( Intent . EXTRA_SHORTCUT_ICON_RESOURCE , Intent . ShortcutIconResource . fromContext ( ApplicationLoader . applicationContext , R . drawable . book_group ) ) ;
}
}
}
addIntent . putExtra ( Intent . EXTRA_SHORTCUT_INTENT , shortcutIntent ) ;
addIntent . putExtra ( Intent . EXTRA_SHORTCUT_NAME , name ) ;
addIntent . putExtra ( " duplicate " , false ) ;
addIntent . setAction ( " com.android.launcher.action.INSTALL_SHORTCUT " ) ;
ApplicationLoader . applicationContext . sendBroadcast ( addIntent ) ;
}
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
}
2021-09-20 00:10:42 +02:00
public void uninstallShortcut ( long dialogId ) {
2018-07-30 04:07:02 +02:00
try {
if ( Build . VERSION . SDK_INT > = 26 ) {
ArrayList < String > arrayList = new ArrayList < > ( ) ;
2021-09-20 00:10:42 +02:00
arrayList . add ( " sdid_ " + dialogId ) ;
arrayList . add ( " ndid_ " + dialogId ) ;
2020-07-26 10:03:38 +02:00
ShortcutManagerCompat . removeDynamicShortcuts ( ApplicationLoader . applicationContext , arrayList ) ;
if ( Build . VERSION . SDK_INT > = 30 ) {
ShortcutManager shortcutManager = ApplicationLoader . applicationContext . getSystemService ( ShortcutManager . class ) ;
shortcutManager . removeLongLivedShortcuts ( arrayList ) ;
}
2018-07-30 04:07:02 +02:00
} else {
TLRPC . User user = null ;
TLRPC . Chat chat = null ;
2021-09-20 00:10:42 +02:00
if ( DialogObject . isEncryptedDialog ( dialogId ) ) {
int encryptedChatId = DialogObject . getEncryptedChatId ( dialogId ) ;
TLRPC . EncryptedChat encryptedChat = getMessagesController ( ) . getEncryptedChat ( encryptedChatId ) ;
2018-07-30 04:07:02 +02:00
if ( encryptedChat = = null ) {
return ;
}
2019-07-18 15:01:39 +02:00
user = getMessagesController ( ) . getUser ( encryptedChat . user_id ) ;
2021-09-20 00:10:42 +02:00
} else if ( DialogObject . isUserDialog ( dialogId ) ) {
user = getMessagesController ( ) . getUser ( dialogId ) ;
} else if ( DialogObject . isChatDialog ( dialogId ) ) {
chat = getMessagesController ( ) . getChat ( - dialogId ) ;
2018-07-30 04:07:02 +02:00
} else {
return ;
}
if ( user = = null & & chat = = null ) {
return ;
}
String name ;
if ( user ! = null ) {
name = ContactsController . formatName ( user . first_name , user . last_name ) ;
} else {
name = chat . title ;
}
Intent addIntent = new Intent ( ) ;
2021-09-20 00:10:42 +02:00
addIntent . putExtra ( Intent . EXTRA_SHORTCUT_INTENT , createIntrnalShortcutIntent ( dialogId ) ) ;
2018-07-30 04:07:02 +02:00
addIntent . putExtra ( Intent . EXTRA_SHORTCUT_NAME , name ) ;
addIntent . putExtra ( " duplicate " , false ) ;
addIntent . setAction ( " com.android.launcher.action.UNINSTALL_SHORTCUT " ) ;
ApplicationLoader . applicationContext . sendBroadcast ( addIntent ) ;
}
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
}
//---------------- SEARCH END ----------------
2019-01-23 18:03:33 +01:00
private static Comparator < TLRPC . MessageEntity > entityComparator = ( entity1 , entity2 ) - > {
if ( entity1 . offset > entity2 . offset ) {
return 1 ;
} else if ( entity1 . offset < entity2 . offset ) {
return - 1 ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
return 0 ;
2018-07-30 04:07:02 +02:00
} ;
2020-10-30 11:26:29 +01:00
private LongSparseArray < Boolean > loadingPinnedMessages = new LongSparseArray < > ( ) ;
public void loadPinnedMessages ( long dialogId , int maxId , int fallback ) {
if ( loadingPinnedMessages . indexOfKey ( dialogId ) > = 0 ) {
return ;
}
loadingPinnedMessages . put ( dialogId , true ) ;
TLRPC . TL_messages_search req = new TLRPC . TL_messages_search ( ) ;
2021-09-20 00:10:42 +02:00
req . peer = getMessagesController ( ) . getInputPeer ( dialogId ) ;
2020-10-30 11:26:29 +01:00
req . limit = 40 ;
req . offset_id = maxId ;
req . q = " " ;
req . filter = new TLRPC . TL_inputMessagesFilterPinned ( ) ;
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
ArrayList < Integer > ids = new ArrayList < > ( ) ;
HashMap < Integer , MessageObject > messages = new HashMap < > ( ) ;
int totalCount = 0 ;
boolean endReached ;
if ( response instanceof TLRPC . messages_Messages ) {
TLRPC . messages_Messages res = ( TLRPC . messages_Messages ) response ;
2021-09-20 00:10:42 +02:00
LongSparseArray < TLRPC . User > usersDict = new LongSparseArray < > ( ) ;
2020-10-30 11:26:29 +01:00
for ( int a = 0 ; a < res . users . size ( ) ; a + + ) {
TLRPC . User user = res . users . get ( a ) ;
usersDict . put ( user . id , user ) ;
}
2021-09-20 00:10:42 +02:00
LongSparseArray < TLRPC . Chat > chatsDict = new LongSparseArray < > ( ) ;
2020-10-30 11:26:29 +01:00
for ( int a = 0 ; a < res . chats . size ( ) ; a + + ) {
TLRPC . Chat chat = res . chats . get ( a ) ;
chatsDict . put ( chat . id , chat ) ;
}
getMessagesStorage ( ) . putUsersAndChats ( res . users , res . chats , true , true ) ;
getMessagesController ( ) . putUsers ( res . users , false ) ;
getMessagesController ( ) . putChats ( res . chats , false ) ;
for ( int a = 0 , N = res . messages . size ( ) ; a < N ; a + + ) {
TLRPC . Message message = res . messages . get ( a ) ;
if ( message instanceof TLRPC . TL_messageService | | message instanceof TLRPC . TL_messageEmpty ) {
continue ;
}
ids . add ( message . id ) ;
messages . put ( message . id , new MessageObject ( currentAccount , message , usersDict , chatsDict , false , false ) ) ;
}
if ( fallback ! = 0 & & ids . isEmpty ( ) ) {
ids . add ( fallback ) ;
}
endReached = res . messages . size ( ) < req . limit ;
totalCount = Math . max ( res . count , res . messages . size ( ) ) ;
} else {
if ( fallback ! = 0 ) {
ids . add ( fallback ) ;
totalCount = 1 ;
}
endReached = false ;
}
getMessagesStorage ( ) . updatePinnedMessages ( dialogId , ids , true , totalCount , maxId , endReached , messages ) ;
AndroidUtilities . runOnUIThread ( ( ) - > loadingPinnedMessages . remove ( dialogId ) ) ;
} ) ;
}
2021-09-20 00:10:42 +02:00
public ArrayList < MessageObject > loadPinnedMessages ( long dialogId , long channelId , ArrayList < Integer > mids , boolean useQueue ) {
2018-07-30 04:07:02 +02:00
if ( useQueue ) {
2020-10-30 11:26:29 +01:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > loadPinnedMessageInternal ( dialogId , channelId , mids , false ) ) ;
2018-07-30 04:07:02 +02:00
} else {
2020-10-30 11:26:29 +01:00
return loadPinnedMessageInternal ( dialogId , channelId , mids , true ) ;
2018-07-30 04:07:02 +02:00
}
return null ;
}
2021-09-20 00:10:42 +02:00
private ArrayList < MessageObject > loadPinnedMessageInternal ( long dialogId , long channelId , ArrayList < Integer > mids , boolean returnValue ) {
2018-07-30 04:07:02 +02:00
try {
2020-10-30 11:26:29 +01:00
ArrayList < Integer > midsCopy = new ArrayList < > ( mids ) ;
CharSequence longIds ;
2019-01-23 18:03:33 +01:00
if ( channelId ! = 0 ) {
2020-10-30 11:26:29 +01:00
StringBuilder builder = new StringBuilder ( ) ;
for ( int a = 0 , N = mids . size ( ) ; a < N ; a + + ) {
2021-09-20 00:10:42 +02:00
Integer messageId = mids . get ( a ) ;
2020-10-30 11:26:29 +01:00
if ( builder . length ( ) ! = 0 ) {
builder . append ( " , " ) ;
}
builder . append ( messageId ) ;
}
longIds = builder ;
2019-01-23 18:03:33 +01:00
} else {
2020-10-30 11:26:29 +01:00
longIds = TextUtils . join ( " , " , mids ) ;
2019-01-23 18:03:33 +01:00
}
2018-07-30 04:07:02 +02:00
2020-10-30 11:26:29 +01:00
ArrayList < TLRPC . Message > results = new ArrayList < > ( ) ;
2021-09-20 00:10:42 +02:00
ArrayList < TLRPC . User > users = new ArrayList < > ( ) ;
ArrayList < TLRPC . Chat > chats = new ArrayList < > ( ) ;
ArrayList < Long > usersToLoad = new ArrayList < > ( ) ;
ArrayList < Long > chatsToLoad = new ArrayList < > ( ) ;
long selfUserId = getUserConfig ( ) . clientUserId ;
2018-07-30 04:07:02 +02:00
2021-09-20 00:10:42 +02:00
SQLiteCursor cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT data, mid, date FROM messages_v2 WHERE mid IN (%s) AND uid = %d " , longIds , dialogId ) ) ;
2020-10-30 11:26:29 +01:00
while ( cursor . next ( ) ) {
2018-07-30 04:07:02 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2020-10-30 11:26:29 +01:00
TLRPC . Message result = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2021-09-20 00:10:42 +02:00
if ( ! ( result . action instanceof TLRPC . TL_messageActionHistoryClear ) ) {
result . readAttachPath ( data , selfUserId ) ;
2018-07-30 04:07:02 +02:00
result . id = cursor . intValue ( 1 ) ;
result . date = cursor . intValue ( 2 ) ;
2019-01-23 18:03:33 +01:00
result . dialog_id = dialogId ;
2018-07-30 04:07:02 +02:00
MessagesStorage . addUsersAndChatsFromMessage ( result , usersToLoad , chatsToLoad ) ;
2020-10-30 11:26:29 +01:00
results . add ( result ) ;
2021-09-20 00:10:42 +02:00
midsCopy . remove ( ( Integer ) result . id ) ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
data . reuse ( ) ;
2018-07-30 04:07:02 +02:00
}
}
cursor . dispose ( ) ;
2020-10-30 11:26:29 +01:00
if ( ! midsCopy . isEmpty ( ) ) {
cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT data FROM chat_pinned_v2 WHERE uid = %d AND mid IN (%s) " , dialogId , TextUtils . join ( " , " , midsCopy ) ) ) ;
while ( cursor . next ( ) ) {
2018-07-30 04:07:02 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2020-10-30 11:26:29 +01:00
TLRPC . Message result = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2021-09-20 00:10:42 +02:00
if ( ! ( result . action instanceof TLRPC . TL_messageActionHistoryClear ) ) {
result . readAttachPath ( data , selfUserId ) ;
2019-01-23 18:03:33 +01:00
result . dialog_id = dialogId ;
2018-07-30 04:07:02 +02:00
MessagesStorage . addUsersAndChatsFromMessage ( result , usersToLoad , chatsToLoad ) ;
2020-10-30 11:26:29 +01:00
results . add ( result ) ;
2021-09-20 00:10:42 +02:00
midsCopy . remove ( ( Integer ) result . id ) ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
data . reuse ( ) ;
2018-07-30 04:07:02 +02:00
}
}
cursor . dispose ( ) ;
}
2020-10-30 11:26:29 +01:00
if ( ! midsCopy . isEmpty ( ) ) {
2019-01-23 18:03:33 +01:00
if ( channelId ! = 0 ) {
2021-09-20 00:10:42 +02:00
TLRPC . TL_channels_getMessages req = new TLRPC . TL_channels_getMessages ( ) ;
2019-07-18 15:01:39 +02:00
req . channel = getMessagesController ( ) . getInputChannel ( channelId ) ;
2020-10-30 11:26:29 +01:00
req . id = midsCopy ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2018-07-30 04:07:02 +02:00
boolean ok = false ;
if ( error = = null ) {
TLRPC . messages_Messages messagesRes = ( TLRPC . messages_Messages ) response ;
removeEmptyMessages ( messagesRes . messages ) ;
if ( ! messagesRes . messages . isEmpty ( ) ) {
2020-10-30 11:26:29 +01:00
TLRPC . Chat chat = getMessagesController ( ) . getChat ( channelId ) ;
2018-07-30 04:07:02 +02:00
ImageLoader . saveMessagesThumbs ( messagesRes . messages ) ;
2020-10-30 11:26:29 +01:00
broadcastPinnedMessage ( messagesRes . messages , messagesRes . users , messagesRes . chats , false , false ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . putUsersAndChats ( messagesRes . users , messagesRes . chats , true , true ) ;
2020-10-30 11:26:29 +01:00
savePinnedMessages ( dialogId , messagesRes . messages ) ;
2018-07-30 04:07:02 +02:00
ok = true ;
}
}
if ( ! ok ) {
2020-10-30 11:26:29 +01:00
getMessagesStorage ( ) . updatePinnedMessages ( dialogId , req . id , false , - 1 , 0 , false , null ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} ) ;
} else {
2021-09-20 00:10:42 +02:00
TLRPC . TL_messages_getMessages req = new TLRPC . TL_messages_getMessages ( ) ;
2020-10-30 11:26:29 +01:00
req . id = midsCopy ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2019-01-23 18:03:33 +01:00
boolean ok = false ;
if ( error = = null ) {
TLRPC . messages_Messages messagesRes = ( TLRPC . messages_Messages ) response ;
removeEmptyMessages ( messagesRes . messages ) ;
if ( ! messagesRes . messages . isEmpty ( ) ) {
ImageLoader . saveMessagesThumbs ( messagesRes . messages ) ;
2020-10-30 11:26:29 +01:00
broadcastPinnedMessage ( messagesRes . messages , messagesRes . users , messagesRes . chats , false , false ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . putUsersAndChats ( messagesRes . users , messagesRes . chats , true , true ) ;
2020-10-30 11:26:29 +01:00
savePinnedMessages ( dialogId , messagesRes . messages ) ;
2019-01-23 18:03:33 +01:00
ok = true ;
}
}
if ( ! ok ) {
2021-03-09 12:40:50 +01:00
getMessagesStorage ( ) . updatePinnedMessages ( dialogId , req . id , false , - 1 , 0 , false , null ) ;
2019-01-23 18:03:33 +01:00
}
} ) ;
}
2020-10-30 11:26:29 +01:00
}
if ( ! results . isEmpty ( ) ) {
2021-03-19 11:25:58 +01:00
if ( ! usersToLoad . isEmpty ( ) ) {
getMessagesStorage ( ) . getUsersInternal ( TextUtils . join ( " , " , usersToLoad ) , users ) ;
}
if ( ! chatsToLoad . isEmpty ( ) ) {
getMessagesStorage ( ) . getChatsInternal ( TextUtils . join ( " , " , chatsToLoad ) , chats ) ;
}
2018-07-30 04:07:02 +02:00
if ( returnValue ) {
2020-10-30 11:26:29 +01:00
return broadcastPinnedMessage ( results , users , chats , true , true ) ;
2018-07-30 04:07:02 +02:00
} else {
2020-10-30 11:26:29 +01:00
broadcastPinnedMessage ( results , users , chats , true , false ) ;
2018-07-30 04:07:02 +02:00
}
}
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
return null ;
}
2020-10-30 11:26:29 +01:00
private void savePinnedMessages ( long dialogId , ArrayList < TLRPC . Message > arrayList ) {
if ( arrayList . isEmpty ( ) ) {
return ;
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getDatabase ( ) . beginTransaction ( ) ;
2020-10-30 11:26:29 +01:00
//SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("UPDATE chat_pinned_v2 SET data = ? WHERE uid = ? AND mid = ?");
SQLitePreparedStatement state = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " REPLACE INTO chat_pinned_v2 VALUES(?, ?, ?) " ) ;
for ( int a = 0 , N = arrayList . size ( ) ; a < N ; a + + ) {
TLRPC . Message message = arrayList . get ( a ) ;
NativeByteBuffer data = new NativeByteBuffer ( message . getObjectSize ( ) ) ;
message . serializeToStream ( data ) ;
state . requery ( ) ;
state . bindLong ( 1 , dialogId ) ;
state . bindInteger ( 2 , message . id ) ;
state . bindByteBuffer ( 3 , data ) ;
state . step ( ) ;
data . reuse ( ) ;
}
2019-01-23 18:03:33 +01:00
state . dispose ( ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getDatabase ( ) . commitTransaction ( ) ;
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2021-09-20 00:10:42 +02:00
private ArrayList < MessageObject > broadcastPinnedMessage ( ArrayList < TLRPC . Message > results , ArrayList < TLRPC . User > users , ArrayList < TLRPC . Chat > chats , boolean isCache , boolean returnValue ) {
2020-10-30 11:26:29 +01:00
if ( results . isEmpty ( ) ) {
return null ;
}
2021-09-20 00:10:42 +02:00
LongSparseArray < TLRPC . User > usersDict = new LongSparseArray < > ( ) ;
2018-07-30 04:07:02 +02:00
for ( int a = 0 ; a < users . size ( ) ; a + + ) {
TLRPC . User user = users . get ( a ) ;
usersDict . put ( user . id , user ) ;
}
2021-09-20 00:10:42 +02:00
LongSparseArray < TLRPC . Chat > chatsDict = new LongSparseArray < > ( ) ;
2018-07-30 04:07:02 +02:00
for ( int a = 0 ; a < chats . size ( ) ; a + + ) {
TLRPC . Chat chat = chats . get ( a ) ;
chatsDict . put ( chat . id , chat ) ;
}
2020-10-30 11:26:29 +01:00
ArrayList < MessageObject > messageObjects = new ArrayList < > ( ) ;
2018-07-30 04:07:02 +02:00
if ( returnValue ) {
2020-10-30 11:26:29 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > {
getMessagesController ( ) . putUsers ( users , isCache ) ;
getMessagesController ( ) . putChats ( chats , isCache ) ;
} ) ;
2021-02-23 12:53:38 +01:00
int checkedCount = 0 ;
2020-10-30 11:26:29 +01:00
for ( int a = 0 , N = results . size ( ) ; a < N ; a + + ) {
2021-02-23 12:53:38 +01:00
TLRPC . Message message = results . get ( a ) ;
if ( message . media instanceof TLRPC . TL_messageMediaDocument | | message . media instanceof TLRPC . TL_messageMediaPhoto ) {
checkedCount + + ;
}
messageObjects . add ( new MessageObject ( currentAccount , message , usersDict , chatsDict , false , checkedCount < 30 ) ) ;
2020-10-30 11:26:29 +01:00
}
return messageObjects ;
2018-07-30 04:07:02 +02:00
} else {
2019-01-23 18:03:33 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > {
2019-07-18 15:01:39 +02:00
getMessagesController ( ) . putUsers ( users , isCache ) ;
getMessagesController ( ) . putChats ( chats , isCache ) ;
2021-02-23 12:53:38 +01:00
int checkedCount = 0 ;
2020-10-30 11:26:29 +01:00
for ( int a = 0 , N = results . size ( ) ; a < N ; a + + ) {
2021-02-23 12:53:38 +01:00
TLRPC . Message message = results . get ( a ) ;
if ( message . media instanceof TLRPC . TL_messageMediaDocument | | message . media instanceof TLRPC . TL_messageMediaPhoto ) {
checkedCount + + ;
}
messageObjects . add ( new MessageObject ( currentAccount , message , usersDict , chatsDict , false , checkedCount < 30 ) ) ;
2020-10-30 11:26:29 +01:00
}
AndroidUtilities . runOnUIThread ( ( ) - > getNotificationCenter ( ) . postNotificationName ( NotificationCenter . didLoadPinnedMessages , messageObjects . get ( 0 ) . getDialogId ( ) , null , true , messageObjects , null , 0 , - 1 , false ) ) ;
2018-07-30 04:07:02 +02:00
} ) ;
}
return null ;
}
private static void removeEmptyMessages ( ArrayList < TLRPC . Message > messages ) {
for ( int a = 0 ; a < messages . size ( ) ; a + + ) {
TLRPC . Message message = messages . get ( a ) ;
if ( message = = null | | message instanceof TLRPC . TL_messageEmpty | | message . action instanceof TLRPC . TL_messageActionHistoryClear ) {
messages . remove ( a ) ;
a - - ;
}
}
}
2021-09-20 00:10:42 +02:00
public void loadReplyMessagesForMessages ( ArrayList < MessageObject > messages , long dialogId , boolean scheduled , Runnable callback ) {
if ( DialogObject . isEncryptedDialog ( dialogId ) ) {
ArrayList < Long > replyMessages = new ArrayList < > ( ) ;
LongSparseArray < ArrayList < MessageObject > > replyMessageRandomOwners = new LongSparseArray < > ( ) ;
2018-07-30 04:07:02 +02:00
for ( int a = 0 ; a < messages . size ( ) ; a + + ) {
MessageObject messageObject = messages . get ( a ) ;
2020-10-30 11:26:29 +01:00
if ( messageObject = = null ) {
continue ;
}
2018-07-30 04:07:02 +02:00
if ( messageObject . isReply ( ) & & messageObject . replyMessageObject = = null ) {
2020-09-30 15:48:47 +02:00
long id = messageObject . messageOwner . reply_to . reply_to_random_id ;
2018-07-30 04:07:02 +02:00
ArrayList < MessageObject > messageObjects = replyMessageRandomOwners . get ( id ) ;
if ( messageObjects = = null ) {
messageObjects = new ArrayList < > ( ) ;
replyMessageRandomOwners . put ( id , messageObjects ) ;
}
messageObjects . add ( messageObject ) ;
if ( ! replyMessages . contains ( id ) ) {
replyMessages . add ( id ) ;
}
}
}
if ( replyMessages . isEmpty ( ) ) {
2019-12-31 14:08:08 +01:00
if ( callback ! = null ) {
callback . run ( ) ;
}
2018-07-30 04:07:02 +02:00
return ;
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2020-12-24 06:36:01 +01:00
ArrayList < MessageObject > loadedMessages = new ArrayList < > ( ) ;
2021-09-20 00:10:42 +02:00
SQLiteCursor cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT m.data, m.mid, m.date, r.random_id FROM randoms_v2 as r INNER JOIN messages_v2 as m ON r.mid = m.mid AND r.uid = m.uid WHERE r.random_id IN(%s) " , TextUtils . join ( " , " , replyMessages ) ) ) ;
2019-01-23 18:03:33 +01:00
while ( cursor . next ( ) ) {
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2019-07-18 15:01:39 +02:00
message . readAttachPath ( data , getUserConfig ( ) . clientUserId ) ;
2019-01-23 18:03:33 +01:00
data . reuse ( ) ;
message . id = cursor . intValue ( 1 ) ;
message . date = cursor . intValue ( 2 ) ;
message . dialog_id = dialogId ;
long value = cursor . longValue ( 3 ) ;
ArrayList < MessageObject > arrayList = replyMessageRandomOwners . get ( value ) ;
replyMessageRandomOwners . remove ( value ) ;
if ( arrayList ! = null ) {
2020-08-14 18:58:22 +02:00
MessageObject messageObject = new MessageObject ( currentAccount , message , false , false ) ;
2020-12-24 06:36:01 +01:00
loadedMessages . add ( messageObject ) ;
2019-01-23 18:03:33 +01:00
for ( int b = 0 ; b < arrayList . size ( ) ; b + + ) {
MessageObject object = arrayList . get ( b ) ;
object . replyMessageObject = messageObject ;
2020-09-30 15:48:47 +02:00
object . messageOwner . reply_to = new TLRPC . TL_messageReplyHeader ( ) ;
object . messageOwner . reply_to . reply_to_msg_id = messageObject . getId ( ) ;
2018-07-30 04:07:02 +02:00
}
}
}
2019-01-23 18:03:33 +01:00
}
cursor . dispose ( ) ;
if ( replyMessageRandomOwners . size ( ) ! = 0 ) {
for ( int b = 0 ; b < replyMessageRandomOwners . size ( ) ; b + + ) {
ArrayList < MessageObject > arrayList = replyMessageRandomOwners . valueAt ( b ) ;
for ( int a = 0 ; a < arrayList . size ( ) ; a + + ) {
2020-09-30 15:48:47 +02:00
TLRPC . Message message = arrayList . get ( a ) . messageOwner ;
if ( message . reply_to ! = null ) {
message . reply_to . reply_to_random_id = 0 ;
}
2018-07-30 04:07:02 +02:00
}
}
}
2021-08-07 01:55:04 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > getNotificationCenter ( ) . postNotificationName ( NotificationCenter . replyMessagesDidLoad , dialogId , loadedMessages , null ) ) ;
2019-12-31 14:08:08 +01:00
if ( callback ! = null ) {
callback . run ( ) ;
}
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
} else {
2021-09-20 00:10:42 +02:00
LongSparseArray < SparseArray < ArrayList < MessageObject > > > replyMessageOwners = new LongSparseArray < > ( ) ;
LongSparseArray < ArrayList < Integer > > dialogReplyMessagesIds = new LongSparseArray < > ( ) ;
2018-07-30 04:07:02 +02:00
for ( int a = 0 ; a < messages . size ( ) ; a + + ) {
MessageObject messageObject = messages . get ( a ) ;
2020-10-30 11:26:29 +01:00
if ( messageObject = = null ) {
continue ;
}
2021-09-27 18:38:27 +02:00
if ( messageObject . getId ( ) > 0 & & messageObject . isReply ( ) ) {
2021-09-20 00:10:42 +02:00
int messageId = messageObject . messageOwner . reply_to . reply_to_msg_id ;
2021-09-27 18:38:27 +02:00
long channelId = 0 ;
if ( messageObject . messageOwner . reply_to . reply_to_peer_id ! = null ) {
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 ) {
channelId = messageObject . messageOwner . peer_id . channel_id ;
}
if ( messageObject . replyMessageObject ! = null ) {
if ( messageObject . replyMessageObject . messageOwner = = null | | messageObject . replyMessageObject . messageOwner . peer_id = = null | | messageObject . messageOwner instanceof TLRPC . TL_messageEmpty ) {
continue ;
}
if ( messageObject . replyMessageObject . messageOwner . peer_id . channel_id = = channelId ) {
continue ;
}
}
2021-09-20 00:10:42 +02:00
SparseArray < ArrayList < MessageObject > > sparseArray = replyMessageOwners . get ( dialogId ) ;
ArrayList < Integer > ids = dialogReplyMessagesIds . get ( channelId ) ;
if ( sparseArray = = null ) {
sparseArray = new SparseArray < > ( ) ;
replyMessageOwners . put ( dialogId , sparseArray ) ;
}
if ( ids = = null ) {
ids = new ArrayList < > ( ) ;
dialogReplyMessagesIds . put ( channelId , ids ) ;
}
2021-09-27 18:38:27 +02:00
ArrayList < MessageObject > arrayList = sparseArray . get ( messageId ) ;
2021-09-20 00:10:42 +02:00
if ( arrayList = = null ) {
arrayList = new ArrayList < > ( ) ;
2021-09-27 18:38:27 +02:00
sparseArray . put ( messageId , arrayList ) ;
if ( ! ids . contains ( messageId ) ) {
ids . add ( messageId ) ;
2020-09-30 15:48:47 +02:00
}
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
arrayList . add ( messageObject ) ;
2018-07-30 04:07:02 +02:00
}
}
2021-09-20 00:10:42 +02:00
if ( replyMessageOwners . isEmpty ( ) ) {
2019-12-31 14:08:08 +01:00
if ( callback ! = null ) {
callback . run ( ) ;
}
2018-07-30 04:07:02 +02:00
return ;
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2021-09-20 00:10:42 +02:00
ArrayList < TLRPC . Message > result = new ArrayList < > ( ) ;
ArrayList < TLRPC . User > users = new ArrayList < > ( ) ;
ArrayList < TLRPC . Chat > chats = new ArrayList < > ( ) ;
ArrayList < Long > usersToLoad = new ArrayList < > ( ) ;
ArrayList < Long > chatsToLoad = new ArrayList < > ( ) ;
for ( int b = 0 , N2 = replyMessageOwners . size ( ) ; b < N2 ; b + + ) {
long did = replyMessageOwners . keyAt ( b ) ;
SparseArray < ArrayList < MessageObject > > owners = replyMessageOwners . valueAt ( b ) ;
ArrayList < Integer > ids = dialogReplyMessagesIds . get ( did ) ;
if ( ids = = null ) {
continue ;
}
SQLiteCursor cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT data, mid, date, uid FROM messages_v2 WHERE mid IN(%s) AND uid = %d " , TextUtils . join ( " , " , ids ) , dialogId ) ) ;
while ( cursor . next ( ) ) {
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
message . readAttachPath ( data , getUserConfig ( ) . clientUserId ) ;
data . reuse ( ) ;
message . id = cursor . intValue ( 1 ) ;
message . date = cursor . intValue ( 2 ) ;
message . dialog_id = dialogId ;
MessagesStorage . addUsersAndChatsFromMessage ( message , usersToLoad , chatsToLoad ) ;
result . add ( message ) ;
long channelId = message . peer_id ! = null ? message . peer_id . channel_id : 0 ;
ArrayList < Integer > mids = dialogReplyMessagesIds . get ( channelId ) ;
if ( mids ! = null ) {
mids . remove ( ( Integer ) message . id ) ;
if ( mids . isEmpty ( ) ) {
dialogReplyMessagesIds . remove ( channelId ) ;
}
2020-09-30 15:48:47 +02:00
}
}
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
cursor . dispose ( ) ;
2019-01-23 18:03:33 +01:00
}
if ( ! usersToLoad . isEmpty ( ) ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getUsersInternal ( TextUtils . join ( " , " , usersToLoad ) , users ) ;
2019-01-23 18:03:33 +01:00
}
if ( ! chatsToLoad . isEmpty ( ) ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getChatsInternal ( TextUtils . join ( " , " , chatsToLoad ) , chats ) ;
2019-01-23 18:03:33 +01:00
}
broadcastReplyMessages ( result , replyMessageOwners , users , chats , dialogId , true ) ;
2021-09-20 00:10:42 +02:00
if ( ! dialogReplyMessagesIds . isEmpty ( ) ) {
for ( int a = 0 , N = dialogReplyMessagesIds . size ( ) ; a < N ; a + + ) {
long channelId = dialogReplyMessagesIds . keyAt ( a ) ;
2020-09-30 15:48:47 +02:00
if ( channelId ! = 0 ) {
2021-09-20 00:10:42 +02:00
TLRPC . TL_channels_getMessages req = new TLRPC . TL_channels_getMessages ( ) ;
2020-09-30 15:48:47 +02:00
req . channel = getMessagesController ( ) . getInputChannel ( channelId ) ;
2021-09-20 00:10:42 +02:00
req . id = dialogReplyMessagesIds . valueAt ( a ) ;
2020-09-30 15:48:47 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
if ( error = = null ) {
TLRPC . messages_Messages messagesRes = ( TLRPC . messages_Messages ) response ;
2021-09-27 18:38:27 +02:00
for ( int i = 0 ; i < messagesRes . messages . size ( ) ; i + + ) {
TLRPC . Message message = messagesRes . messages . get ( i ) ;
if ( message . dialog_id = = 0 ) {
message . dialog_id = dialogId ;
}
}
2020-09-30 15:48:47 +02:00
MessageObject . fixMessagePeer ( messagesRes . messages , channelId ) ;
ImageLoader . saveMessagesThumbs ( messagesRes . messages ) ;
broadcastReplyMessages ( messagesRes . messages , replyMessageOwners , messagesRes . users , messagesRes . chats , dialogId , false ) ;
getMessagesStorage ( ) . putUsersAndChats ( messagesRes . users , messagesRes . chats , true , true ) ;
saveReplyMessages ( replyMessageOwners , messagesRes . messages , scheduled ) ;
}
if ( callback ! = null ) {
AndroidUtilities . runOnUIThread ( callback ) ;
}
} ) ;
} else {
TLRPC . TL_messages_getMessages req = new TLRPC . TL_messages_getMessages ( ) ;
2021-09-20 00:10:42 +02:00
req . id = dialogReplyMessagesIds . valueAt ( a ) ;
2020-09-30 15:48:47 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
if ( error = = null ) {
TLRPC . messages_Messages messagesRes = ( TLRPC . messages_Messages ) response ;
2021-09-20 00:10:42 +02:00
for ( int i = 0 ; i < messagesRes . messages . size ( ) ; i + + ) {
TLRPC . Message message = messagesRes . messages . get ( i ) ;
if ( message . dialog_id = = 0 ) {
message . dialog_id = dialogId ;
}
}
2020-09-30 15:48:47 +02:00
ImageLoader . saveMessagesThumbs ( messagesRes . messages ) ;
broadcastReplyMessages ( messagesRes . messages , replyMessageOwners , messagesRes . users , messagesRes . chats , dialogId , false ) ;
getMessagesStorage ( ) . putUsersAndChats ( messagesRes . users , messagesRes . chats , true , true ) ;
saveReplyMessages ( replyMessageOwners , messagesRes . messages , scheduled ) ;
}
if ( callback ! = null ) {
AndroidUtilities . runOnUIThread ( callback ) ;
}
} ) ;
}
2018-07-30 04:07:02 +02:00
}
2019-12-31 14:08:08 +01:00
} else {
if ( callback ! = null ) {
AndroidUtilities . runOnUIThread ( callback ) ;
}
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
}
2021-09-20 00:10:42 +02:00
private void saveReplyMessages ( LongSparseArray < SparseArray < ArrayList < MessageObject > > > replyMessageOwners , ArrayList < TLRPC . Message > result , boolean scheduled ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getDatabase ( ) . beginTransaction ( ) ;
2019-09-10 12:56:11 +02:00
SQLitePreparedStatement state ;
if ( scheduled ) {
2021-09-20 00:10:42 +02:00
state = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " UPDATE scheduled_messages_v2 SET replydata = ? WHERE mid = ? AND uid = ? " ) ;
2019-09-10 12:56:11 +02:00
} else {
2021-09-20 00:10:42 +02:00
state = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " UPDATE messages_v2 SET replydata = ? WHERE mid = ? AND uid = ? " ) ;
2019-09-10 12:56:11 +02:00
}
2019-01-23 18:03:33 +01:00
for ( int a = 0 ; a < result . size ( ) ; a + + ) {
TLRPC . Message message = result . get ( a ) ;
2021-09-20 00:10:42 +02:00
long dialogId = MessageObject . getDialogId ( message ) ;
SparseArray < ArrayList < MessageObject > > sparseArray = replyMessageOwners . get ( dialogId ) ;
if ( sparseArray = = null ) {
continue ;
}
ArrayList < MessageObject > messageObjects = sparseArray . get ( message . id ) ;
2019-01-23 18:03:33 +01:00
if ( messageObjects ! = null ) {
NativeByteBuffer data = new NativeByteBuffer ( message . getObjectSize ( ) ) ;
message . serializeToStream ( data ) ;
for ( int b = 0 ; b < messageObjects . size ( ) ; b + + ) {
MessageObject messageObject = messageObjects . get ( b ) ;
state . requery ( ) ;
state . bindByteBuffer ( 1 , data ) ;
2021-09-20 00:10:42 +02:00
state . bindInteger ( 2 , messageObject . getId ( ) ) ;
state . bindLong ( 3 , messageObject . getDialogId ( ) ) ;
2019-01-23 18:03:33 +01:00
state . step ( ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
data . reuse ( ) ;
2018-07-30 04:07:02 +02:00
}
}
2019-01-23 18:03:33 +01:00
state . dispose ( ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getDatabase ( ) . commitTransaction ( ) ;
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2021-09-20 00:10:42 +02:00
private void broadcastReplyMessages ( ArrayList < TLRPC . Message > result , LongSparseArray < SparseArray < ArrayList < MessageObject > > > replyMessageOwners , ArrayList < TLRPC . User > users , ArrayList < TLRPC . Chat > chats , long dialog_id , boolean isCache ) {
LongSparseArray < TLRPC . User > usersDict = new LongSparseArray < > ( ) ;
2018-07-30 04:07:02 +02:00
for ( int a = 0 ; a < users . size ( ) ; a + + ) {
TLRPC . User user = users . get ( a ) ;
usersDict . put ( user . id , user ) ;
}
2021-09-20 00:10:42 +02:00
LongSparseArray < TLRPC . Chat > chatsDict = new LongSparseArray < > ( ) ;
2018-07-30 04:07:02 +02:00
for ( int a = 0 ; a < chats . size ( ) ; a + + ) {
TLRPC . Chat chat = chats . get ( a ) ;
chatsDict . put ( chat . id , chat ) ;
}
2021-09-20 00:10:42 +02:00
ArrayList < MessageObject > messageObjects = new ArrayList < > ( ) ;
2020-08-14 18:58:22 +02:00
for ( int a = 0 , N = result . size ( ) ; a < N ; a + + ) {
messageObjects . add ( new MessageObject ( currentAccount , result . get ( a ) , usersDict , chatsDict , false , false ) ) ;
}
2019-01-23 18:03:33 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > {
2019-07-18 15:01:39 +02:00
getMessagesController ( ) . putUsers ( users , isCache ) ;
getMessagesController ( ) . putChats ( chats , isCache ) ;
2019-01-23 18:03:33 +01:00
boolean changed = false ;
2020-08-14 18:58:22 +02:00
for ( int a = 0 , N = messageObjects . size ( ) ; a < N ; a + + ) {
MessageObject messageObject = messageObjects . get ( a ) ;
2021-09-20 00:10:42 +02:00
long dialogId = messageObject . getDialogId ( ) ;
SparseArray < ArrayList < MessageObject > > sparseArray = replyMessageOwners . get ( dialogId ) ;
if ( sparseArray = = null ) {
continue ;
}
ArrayList < MessageObject > arrayList = sparseArray . get ( messageObject . getId ( ) ) ;
2019-01-23 18:03:33 +01:00
if ( arrayList ! = null ) {
for ( int b = 0 ; b < arrayList . size ( ) ; b + + ) {
MessageObject m = arrayList . get ( b ) ;
m . replyMessageObject = messageObject ;
if ( m . messageOwner . action instanceof TLRPC . TL_messageActionPinMessage ) {
m . generatePinMessageText ( null , null ) ;
} else if ( m . messageOwner . action instanceof TLRPC . TL_messageActionGameScore ) {
m . generateGameMessageText ( null ) ;
} else if ( m . messageOwner . action instanceof TLRPC . TL_messageActionPaymentSent ) {
m . generatePaymentSentMessageText ( null ) ;
}
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
changed = true ;
2018-07-30 04:07:02 +02:00
}
}
2019-01-23 18:03:33 +01:00
if ( changed ) {
2021-08-07 01:55:04 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . replyMessagesDidLoad , dialog_id , messageObjects , replyMessageOwners ) ;
2019-01-23 18:03:33 +01:00
}
2018-07-30 04:07:02 +02:00
} ) ;
}
public static void sortEntities ( ArrayList < TLRPC . MessageEntity > entities ) {
Collections . sort ( entities , entityComparator ) ;
}
2020-05-01 04:08:26 +02:00
private static boolean checkInclusion ( int index , ArrayList < TLRPC . MessageEntity > entities , boolean end ) {
2018-07-30 04:07:02 +02:00
if ( entities = = null | | entities . isEmpty ( ) ) {
return false ;
}
int count = entities . size ( ) ;
for ( int a = 0 ; a < count ; a + + ) {
TLRPC . MessageEntity entity = entities . get ( a ) ;
2020-05-01 04:08:26 +02:00
if ( ( end ? entity . offset < index : entity . offset < = index ) & & entity . offset + entity . length > index ) {
2018-07-30 04:07:02 +02:00
return true ;
}
}
return false ;
}
private static boolean checkIntersection ( int start , int end , ArrayList < TLRPC . MessageEntity > entities ) {
if ( entities = = null | | entities . isEmpty ( ) ) {
return false ;
}
int count = entities . size ( ) ;
for ( int a = 0 ; a < count ; a + + ) {
TLRPC . MessageEntity entity = entities . get ( a ) ;
if ( entity . offset > start & & entity . offset + entity . length < = end ) {
return true ;
}
}
return false ;
}
private static void removeOffsetAfter ( int start , int countToRemove , ArrayList < TLRPC . MessageEntity > entities ) {
int count = entities . size ( ) ;
for ( int a = 0 ; a < count ; a + + ) {
TLRPC . MessageEntity entity = entities . get ( a ) ;
if ( entity . offset > start ) {
entity . offset - = countToRemove ;
}
}
}
public CharSequence substring ( CharSequence source , int start , int end ) {
if ( source instanceof SpannableStringBuilder ) {
2019-06-04 12:14:50 +02:00
return source . subSequence ( start , end ) ;
2018-07-30 04:07:02 +02:00
} else if ( source instanceof SpannedString ) {
2019-06-04 12:14:50 +02:00
return source . subSequence ( start , end ) ;
2018-07-30 04:07:02 +02:00
} else {
return TextUtils . substring ( source , start , end ) ;
}
}
2019-07-18 15:01:39 +02:00
private static CharacterStyle createNewSpan ( CharacterStyle baseSpan , TextStyleSpan . TextStyleRun textStyleRun , TextStyleSpan . TextStyleRun newStyleRun , boolean allowIntersection ) {
TextStyleSpan . TextStyleRun run = new TextStyleSpan . TextStyleRun ( textStyleRun ) ;
if ( newStyleRun ! = null ) {
if ( allowIntersection ) {
run . merge ( newStyleRun ) ;
} else {
run . replace ( newStyleRun ) ;
}
}
if ( baseSpan instanceof TextStyleSpan ) {
return new TextStyleSpan ( run ) ;
} else if ( baseSpan instanceof URLSpanReplacement ) {
URLSpanReplacement span = ( URLSpanReplacement ) baseSpan ;
return new URLSpanReplacement ( span . getURL ( ) , run ) ;
}
return null ;
}
public static void addStyleToText ( TextStyleSpan span , int start , int end , Spannable editable , boolean allowIntersection ) {
try {
CharacterStyle [ ] spans = editable . getSpans ( start , end , CharacterStyle . class ) ;
if ( spans ! = null & & spans . length > 0 ) {
for ( int a = 0 ; a < spans . length ; a + + ) {
CharacterStyle oldSpan = spans [ a ] ;
TextStyleSpan . TextStyleRun textStyleRun ;
TextStyleSpan . TextStyleRun newStyleRun = span ! = null ? span . getTextStyleRun ( ) : new TextStyleSpan . TextStyleRun ( ) ;
if ( oldSpan instanceof TextStyleSpan ) {
TextStyleSpan textStyleSpan = ( TextStyleSpan ) oldSpan ;
textStyleRun = textStyleSpan . getTextStyleRun ( ) ;
} else if ( oldSpan instanceof URLSpanReplacement ) {
URLSpanReplacement urlSpanReplacement = ( URLSpanReplacement ) oldSpan ;
textStyleRun = urlSpanReplacement . getTextStyleRun ( ) ;
if ( textStyleRun = = null ) {
textStyleRun = new TextStyleSpan . TextStyleRun ( ) ;
}
} else {
continue ;
}
if ( textStyleRun = = null ) {
continue ;
}
int spanStart = editable . getSpanStart ( oldSpan ) ;
int spanEnd = editable . getSpanEnd ( oldSpan ) ;
editable . removeSpan ( oldSpan ) ;
if ( spanStart > start & & end > spanEnd ) {
editable . setSpan ( createNewSpan ( oldSpan , textStyleRun , newStyleRun , allowIntersection ) , spanStart , spanEnd , Spanned . SPAN_EXCLUSIVE_EXCLUSIVE ) ;
if ( span ! = null ) {
editable . setSpan ( new TextStyleSpan ( new TextStyleSpan . TextStyleRun ( newStyleRun ) ) , spanEnd , end , Spanned . SPAN_EXCLUSIVE_EXCLUSIVE ) ;
}
end = spanStart ;
} else {
int startTemp = start ;
if ( spanStart < = start ) {
if ( spanStart ! = start ) {
editable . setSpan ( createNewSpan ( oldSpan , textStyleRun , null , allowIntersection ) , spanStart , start , Spanned . SPAN_EXCLUSIVE_EXCLUSIVE ) ;
}
if ( spanEnd > start ) {
if ( span ! = null ) {
editable . setSpan ( createNewSpan ( oldSpan , textStyleRun , newStyleRun , allowIntersection ) , start , Math . min ( spanEnd , end ) , Spanned . SPAN_EXCLUSIVE_EXCLUSIVE ) ;
}
start = spanEnd ;
}
}
if ( spanEnd > = end ) {
if ( spanEnd ! = end ) {
editable . setSpan ( createNewSpan ( oldSpan , textStyleRun , null , allowIntersection ) , end , spanEnd , Spanned . SPAN_EXCLUSIVE_EXCLUSIVE ) ;
}
if ( end > spanStart & & spanEnd < = startTemp ) {
if ( span ! = null ) {
editable . setSpan ( createNewSpan ( oldSpan , textStyleRun , newStyleRun , allowIntersection ) , spanStart , Math . min ( spanEnd , end ) , Spanned . SPAN_EXCLUSIVE_EXCLUSIVE ) ;
}
end = spanStart ;
}
}
}
}
}
if ( span ! = null & & start < end ) {
editable . setSpan ( span , start , end , Spanned . SPAN_EXCLUSIVE_EXCLUSIVE ) ;
}
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
}
public static ArrayList < TextStyleSpan . TextStyleRun > getTextStyleRuns ( ArrayList < TLRPC . MessageEntity > entities , CharSequence text ) {
ArrayList < TextStyleSpan . TextStyleRun > runs = new ArrayList < > ( ) ;
ArrayList < TLRPC . MessageEntity > entitiesCopy = new ArrayList < > ( entities ) ;
Collections . sort ( entitiesCopy , ( o1 , o2 ) - > {
if ( o1 . offset > o2 . offset ) {
return 1 ;
} else if ( o1 . offset < o2 . offset ) {
return - 1 ;
}
return 0 ;
} ) ;
for ( int a = 0 , N = entitiesCopy . size ( ) ; a < N ; a + + ) {
TLRPC . MessageEntity entity = entitiesCopy . get ( a ) ;
if ( entity . length < = 0 | | entity . offset < 0 | | entity . offset > = text . length ( ) ) {
continue ;
} else if ( entity . offset + entity . length > text . length ( ) ) {
entity . length = text . length ( ) - entity . offset ;
}
TextStyleSpan . TextStyleRun newRun = new TextStyleSpan . TextStyleRun ( ) ;
newRun . start = entity . offset ;
newRun . end = newRun . start + entity . length ;
TLRPC . MessageEntity urlEntity = null ;
if ( entity instanceof TLRPC . TL_messageEntityStrike ) {
newRun . flags = TextStyleSpan . FLAG_STYLE_STRIKE ;
} else if ( entity instanceof TLRPC . TL_messageEntityUnderline ) {
newRun . flags = TextStyleSpan . FLAG_STYLE_UNDERLINE ;
} else if ( entity instanceof TLRPC . TL_messageEntityBlockquote ) {
newRun . flags = TextStyleSpan . FLAG_STYLE_QUOTE ;
} else if ( entity instanceof TLRPC . TL_messageEntityBold ) {
newRun . flags = TextStyleSpan . FLAG_STYLE_BOLD ;
} else if ( entity instanceof TLRPC . TL_messageEntityItalic ) {
newRun . flags = TextStyleSpan . FLAG_STYLE_ITALIC ;
} else if ( entity instanceof TLRPC . TL_messageEntityCode | | entity instanceof TLRPC . TL_messageEntityPre ) {
newRun . flags = TextStyleSpan . FLAG_STYLE_MONO ;
} else if ( entity instanceof TLRPC . TL_messageEntityMentionName ) {
newRun . flags = TextStyleSpan . FLAG_STYLE_MENTION ;
newRun . urlEntity = entity ;
} else if ( entity instanceof TLRPC . TL_inputMessageEntityMentionName ) {
newRun . flags = TextStyleSpan . FLAG_STYLE_MENTION ;
newRun . urlEntity = entity ;
} else {
newRun . flags = TextStyleSpan . FLAG_STYLE_URL ;
newRun . urlEntity = entity ;
}
for ( int b = 0 , N2 = runs . size ( ) ; b < N2 ; b + + ) {
TextStyleSpan . TextStyleRun run = runs . get ( b ) ;
if ( newRun . start > run . start ) {
if ( newRun . start > = run . end ) {
continue ;
}
if ( newRun . end < run . end ) {
TextStyleSpan . TextStyleRun r = new TextStyleSpan . TextStyleRun ( newRun ) ;
r . merge ( run ) ;
b + + ;
N2 + + ;
runs . add ( b , r ) ;
r = new TextStyleSpan . TextStyleRun ( run ) ;
r . start = newRun . end ;
b + + ;
N2 + + ;
runs . add ( b , r ) ;
2021-09-20 00:10:42 +02:00
} else {
2019-07-18 15:01:39 +02:00
TextStyleSpan . TextStyleRun r = new TextStyleSpan . TextStyleRun ( newRun ) ;
r . merge ( run ) ;
r . end = run . end ;
b + + ;
N2 + + ;
runs . add ( b , r ) ;
}
int temp = newRun . start ;
newRun . start = run . end ;
run . end = temp ;
} else {
if ( run . start > = newRun . end ) {
continue ;
}
int temp = run . start ;
if ( newRun . end = = run . end ) {
run . merge ( newRun ) ;
} else if ( newRun . end < run . end ) {
TextStyleSpan . TextStyleRun r = new TextStyleSpan . TextStyleRun ( run ) ;
r . merge ( newRun ) ;
r . end = newRun . end ;
b + + ;
N2 + + ;
runs . add ( b , r ) ;
run . start = newRun . end ;
} else {
TextStyleSpan . TextStyleRun r = new TextStyleSpan . TextStyleRun ( newRun ) ;
r . start = run . end ;
b + + ;
N2 + + ;
runs . add ( b , r ) ;
run . merge ( newRun ) ;
}
newRun . end = temp ;
}
}
if ( newRun . start < newRun . end ) {
runs . add ( newRun ) ;
}
}
return runs ;
}
2021-07-30 16:49:55 +02:00
public void addStyle ( int flags , int spanStart , int spanEnd , ArrayList < TLRPC . MessageEntity > entities ) {
if ( ( flags & TextStyleSpan . FLAG_STYLE_BOLD ) ! = 0 ) {
TLRPC . MessageEntity entity = new TLRPC . TL_messageEntityBold ( ) ;
entity . offset = spanStart ;
entity . length = spanEnd - spanStart ;
entities . add ( entity ) ;
}
if ( ( flags & TextStyleSpan . FLAG_STYLE_ITALIC ) ! = 0 ) {
TLRPC . MessageEntity entity = new TLRPC . TL_messageEntityItalic ( ) ;
entity . offset = spanStart ;
entity . length = spanEnd - spanStart ;
entities . add ( entity ) ;
}
if ( ( flags & TextStyleSpan . FLAG_STYLE_MONO ) ! = 0 ) {
TLRPC . MessageEntity entity = new TLRPC . TL_messageEntityCode ( ) ;
entity . offset = spanStart ;
entity . length = spanEnd - spanStart ;
entities . add ( entity ) ;
}
if ( ( flags & TextStyleSpan . FLAG_STYLE_STRIKE ) ! = 0 ) {
TLRPC . MessageEntity entity = new TLRPC . TL_messageEntityStrike ( ) ;
entity . offset = spanStart ;
entity . length = spanEnd - spanStart ;
entities . add ( entity ) ;
}
if ( ( flags & TextStyleSpan . FLAG_STYLE_UNDERLINE ) ! = 0 ) {
TLRPC . MessageEntity entity = new TLRPC . TL_messageEntityUnderline ( ) ;
entity . offset = spanStart ;
entity . length = spanEnd - spanStart ;
entities . add ( entity ) ;
}
if ( ( flags & TextStyleSpan . FLAG_STYLE_QUOTE ) ! = 0 ) {
TLRPC . MessageEntity entity = new TLRPC . TL_messageEntityBlockquote ( ) ;
entity . offset = spanStart ;
entity . length = spanEnd - spanStart ;
entities . add ( entity ) ;
}
}
2019-12-31 14:08:08 +01:00
public ArrayList < TLRPC . MessageEntity > getEntities ( CharSequence [ ] message , boolean allowStrike ) {
2018-07-30 04:07:02 +02:00
if ( message = = null | | message [ 0 ] = = null ) {
return null ;
}
ArrayList < TLRPC . MessageEntity > entities = null ;
int index ;
int start = - 1 ;
int lastIndex = 0 ;
boolean isPre = false ;
final String mono = " ` " ;
final String pre = " ``` " ;
final String bold = " ** " ;
final String italic = " __ " ;
2019-12-31 14:08:08 +01:00
final String strike = " ~~ " ;
2018-07-30 04:07:02 +02:00
while ( ( index = TextUtils . indexOf ( message [ 0 ] , ! isPre ? mono : pre , lastIndex ) ) ! = - 1 ) {
if ( start = = - 1 ) {
isPre = message [ 0 ] . length ( ) - index > 2 & & message [ 0 ] . charAt ( index + 1 ) = = '`' & & message [ 0 ] . charAt ( index + 2 ) = = '`' ;
start = index ;
lastIndex = index + ( isPre ? 3 : 1 ) ;
} else {
if ( entities = = null ) {
entities = new ArrayList < > ( ) ;
}
for ( int a = index + ( isPre ? 3 : 1 ) ; a < message [ 0 ] . length ( ) ; a + + ) {
if ( message [ 0 ] . charAt ( a ) = = '`' ) {
index + + ;
} else {
break ;
}
}
lastIndex = index + ( isPre ? 3 : 1 ) ;
if ( isPre ) {
int firstChar = start > 0 ? message [ 0 ] . charAt ( start - 1 ) : 0 ;
boolean replacedFirst = firstChar = = ' ' | | firstChar = = '\n' ;
CharSequence startMessage = substring ( message [ 0 ] , 0 , start - ( replacedFirst ? 1 : 0 ) ) ;
CharSequence content = substring ( message [ 0 ] , start + 3 , index ) ;
firstChar = index + 3 < message [ 0 ] . length ( ) ? message [ 0 ] . charAt ( index + 3 ) : 0 ;
CharSequence endMessage = substring ( message [ 0 ] , index + 3 + ( firstChar = = ' ' | | firstChar = = '\n' ? 1 : 0 ) , message [ 0 ] . length ( ) ) ;
if ( startMessage . length ( ) ! = 0 ) {
2019-01-23 18:03:33 +01:00
startMessage = AndroidUtilities . concat ( startMessage , " \ n " ) ;
2018-07-30 04:07:02 +02:00
} else {
replacedFirst = true ;
}
if ( endMessage . length ( ) ! = 0 ) {
2019-01-23 18:03:33 +01:00
endMessage = AndroidUtilities . concat ( " \ n " , endMessage ) ;
2018-07-30 04:07:02 +02:00
}
if ( ! TextUtils . isEmpty ( content ) ) {
2019-01-23 18:03:33 +01:00
message [ 0 ] = AndroidUtilities . concat ( startMessage , content , endMessage ) ;
2018-07-30 04:07:02 +02:00
TLRPC . TL_messageEntityPre entity = new TLRPC . TL_messageEntityPre ( ) ;
entity . offset = start + ( replacedFirst ? 0 : 1 ) ;
entity . length = index - start - 3 + ( replacedFirst ? 0 : 1 ) ;
entity . language = " " ;
entities . add ( entity ) ;
lastIndex - = 6 ;
}
} else {
if ( start + 1 ! = index ) {
2019-01-23 18:03:33 +01:00
message [ 0 ] = AndroidUtilities . concat ( substring ( message [ 0 ] , 0 , start ) , substring ( message [ 0 ] , start + 1 , index ) , substring ( message [ 0 ] , index + 1 , message [ 0 ] . length ( ) ) ) ;
2018-07-30 04:07:02 +02:00
TLRPC . TL_messageEntityCode entity = new TLRPC . TL_messageEntityCode ( ) ;
entity . offset = start ;
entity . length = index - start - 1 ;
entities . add ( entity ) ;
lastIndex - = 2 ;
}
}
start = - 1 ;
isPre = false ;
}
}
if ( start ! = - 1 & & isPre ) {
2019-01-23 18:03:33 +01:00
message [ 0 ] = AndroidUtilities . concat ( substring ( message [ 0 ] , 0 , start ) , substring ( message [ 0 ] , start + 2 , message [ 0 ] . length ( ) ) ) ;
2018-07-30 04:07:02 +02:00
if ( entities = = null ) {
entities = new ArrayList < > ( ) ;
}
TLRPC . TL_messageEntityCode entity = new TLRPC . TL_messageEntityCode ( ) ;
entity . offset = start ;
entity . length = 1 ;
entities . add ( entity ) ;
}
if ( message [ 0 ] instanceof Spanned ) {
Spanned spannable = ( Spanned ) message [ 0 ] ;
2019-07-18 15:01:39 +02:00
TextStyleSpan [ ] spans = spannable . getSpans ( 0 , message [ 0 ] . length ( ) , TextStyleSpan . class ) ;
2018-07-30 04:07:02 +02:00
if ( spans ! = null & & spans . length > 0 ) {
for ( int a = 0 ; a < spans . length ; a + + ) {
2019-07-18 15:01:39 +02:00
TextStyleSpan span = spans [ a ] ;
2018-07-30 04:07:02 +02:00
int spanStart = spannable . getSpanStart ( span ) ;
int spanEnd = spannable . getSpanEnd ( span ) ;
2020-05-01 04:08:26 +02:00
if ( checkInclusion ( spanStart , entities , false ) | | checkInclusion ( spanEnd , entities , true ) | | checkIntersection ( spanStart , spanEnd , entities ) ) {
2018-07-30 04:07:02 +02:00
continue ;
}
if ( entities = = null ) {
entities = new ArrayList < > ( ) ;
}
2021-07-30 16:49:55 +02:00
addStyle ( span . getStyleFlags ( ) , spanStart , spanEnd , entities ) ;
2018-07-30 04:07:02 +02:00
}
}
2019-06-04 12:14:50 +02:00
URLSpanUserMention [ ] spansMentions = spannable . getSpans ( 0 , message [ 0 ] . length ( ) , URLSpanUserMention . class ) ;
2018-07-30 04:07:02 +02:00
if ( spansMentions ! = null & & spansMentions . length > 0 ) {
if ( entities = = null ) {
entities = new ArrayList < > ( ) ;
}
for ( int b = 0 ; b < spansMentions . length ; b + + ) {
TLRPC . TL_inputMessageEntityMentionName entity = new TLRPC . TL_inputMessageEntityMentionName ( ) ;
2021-09-20 00:10:42 +02:00
entity . user_id = getMessagesController ( ) . getInputUser ( Utilities . parseLong ( spansMentions [ b ] . getURL ( ) ) ) ;
2018-07-30 04:07:02 +02:00
if ( entity . user_id ! = null ) {
entity . offset = spannable . getSpanStart ( spansMentions [ b ] ) ;
entity . length = Math . min ( spannable . getSpanEnd ( spansMentions [ b ] ) , message [ 0 ] . length ( ) ) - entity . offset ;
if ( message [ 0 ] . charAt ( entity . offset + entity . length - 1 ) = = ' ' ) {
entity . length - - ;
}
entities . add ( entity ) ;
}
}
}
2019-06-04 12:14:50 +02:00
URLSpanReplacement [ ] spansUrlReplacement = spannable . getSpans ( 0 , message [ 0 ] . length ( ) , URLSpanReplacement . class ) ;
2018-07-30 04:07:02 +02:00
if ( spansUrlReplacement ! = null & & spansUrlReplacement . length > 0 ) {
if ( entities = = null ) {
entities = new ArrayList < > ( ) ;
}
for ( int b = 0 ; b < spansUrlReplacement . length ; b + + ) {
TLRPC . TL_messageEntityTextUrl entity = new TLRPC . TL_messageEntityTextUrl ( ) ;
entity . offset = spannable . getSpanStart ( spansUrlReplacement [ b ] ) ;
entity . length = Math . min ( spannable . getSpanEnd ( spansUrlReplacement [ b ] ) , message [ 0 ] . length ( ) ) - entity . offset ;
entity . url = spansUrlReplacement [ b ] . getURL ( ) ;
entities . add ( entity ) ;
2021-07-30 16:49:55 +02:00
TextStyleSpan . TextStyleRun style = spansUrlReplacement [ b ] . getTextStyleRun ( ) ;
if ( style ! = null ) {
addStyle ( style . flags , entity . offset , entity . offset + entity . length , entities ) ;
}
2018-07-30 04:07:02 +02:00
}
}
}
2019-12-31 14:08:08 +01:00
int count = allowStrike ? 3 : 2 ;
for ( int c = 0 ; c < count ; c + + ) {
2018-07-30 04:07:02 +02:00
lastIndex = 0 ;
start = - 1 ;
2019-12-31 14:08:08 +01:00
String checkString ;
char checkChar ;
switch ( c ) {
case 0 :
checkString = bold ;
checkChar = '*' ;
break ;
case 1 :
checkString = italic ;
checkChar = '_' ;
break ;
case 2 :
default :
checkString = strike ;
checkChar = '~' ;
break ;
}
2018-07-30 04:07:02 +02:00
while ( ( index = TextUtils . indexOf ( message [ 0 ] , checkString , lastIndex ) ) ! = - 1 ) {
if ( start = = - 1 ) {
char prevChar = index = = 0 ? ' ' : message [ 0 ] . charAt ( index - 1 ) ;
2020-05-01 04:08:26 +02:00
if ( ! checkInclusion ( index , entities , false ) & & ( prevChar = = ' ' | | prevChar = = '\n' ) ) {
2018-07-30 04:07:02 +02:00
start = index ;
}
lastIndex = index + 2 ;
} else {
for ( int a = index + 2 ; a < message [ 0 ] . length ( ) ; a + + ) {
if ( message [ 0 ] . charAt ( a ) = = checkChar ) {
index + + ;
} else {
break ;
}
}
lastIndex = index + 2 ;
2020-05-01 04:08:26 +02:00
if ( checkInclusion ( index , entities , false ) | | checkIntersection ( start , index , entities ) ) {
2018-07-30 04:07:02 +02:00
start = - 1 ;
continue ;
}
if ( start + 2 ! = index ) {
if ( entities = = null ) {
entities = new ArrayList < > ( ) ;
}
try {
2019-01-23 18:03:33 +01:00
message [ 0 ] = AndroidUtilities . concat ( substring ( message [ 0 ] , 0 , start ) , substring ( message [ 0 ] , start + 2 , index ) , substring ( message [ 0 ] , index + 2 , message [ 0 ] . length ( ) ) ) ;
2018-07-30 04:07:02 +02:00
} catch ( Exception e ) {
message [ 0 ] = substring ( message [ 0 ] , 0 , start ) . toString ( ) + substring ( message [ 0 ] , start + 2 , index ) . toString ( ) + substring ( message [ 0 ] , index + 2 , message [ 0 ] . length ( ) ) . toString ( ) ;
}
TLRPC . MessageEntity entity ;
if ( c = = 0 ) {
entity = new TLRPC . TL_messageEntityBold ( ) ;
2019-12-31 14:08:08 +01:00
} else if ( c = = 1 ) {
2018-07-30 04:07:02 +02:00
entity = new TLRPC . TL_messageEntityItalic ( ) ;
2019-12-31 14:08:08 +01:00
} else {
entity = new TLRPC . TL_messageEntityStrike ( ) ;
2018-07-30 04:07:02 +02:00
}
entity . offset = start ;
entity . length = index - start - 2 ;
removeOffsetAfter ( entity . offset + entity . length , 4 , entities ) ;
entities . add ( entity ) ;
lastIndex - = 4 ;
}
start = - 1 ;
}
}
}
return entities ;
}
//---------------- MESSAGES END ----------------
2019-12-31 14:08:08 +01:00
private LongSparseArray < Integer > draftsFolderIds = new LongSparseArray < > ( ) ;
2020-09-30 15:48:47 +02:00
private LongSparseArray < SparseArray < TLRPC . DraftMessage > > drafts = new LongSparseArray < > ( ) ;
private LongSparseArray < SparseArray < TLRPC . Message > > draftMessages = new LongSparseArray < > ( ) ;
2018-07-30 04:07:02 +02:00
private boolean inTransaction ;
2020-09-30 15:48:47 +02:00
private SharedPreferences draftPreferences ;
2018-07-30 04:07:02 +02:00
private boolean loadingDrafts ;
2019-12-31 14:08:08 +01:00
public void loadDraftsIfNeed ( ) {
2019-07-18 15:01:39 +02:00
if ( getUserConfig ( ) . draftsLoaded | | loadingDrafts ) {
2018-07-30 04:07:02 +02:00
return ;
}
loadingDrafts = true ;
2019-12-31 14:08:08 +01:00
getConnectionsManager ( ) . sendRequest ( new TLRPC . TL_messages_getAllDrafts ( ) , ( response , error ) - > {
2019-01-23 18:03:33 +01:00
if ( error ! = null ) {
2019-12-31 14:08:08 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > loadingDrafts = false ) ;
} else {
getMessagesController ( ) . processUpdates ( ( TLRPC . Updates ) response , false ) ;
AndroidUtilities . runOnUIThread ( ( ) - > {
loadingDrafts = false ;
2021-09-20 00:10:42 +02:00
UserConfig userConfig = getUserConfig ( ) ;
2019-12-31 14:08:08 +01:00
userConfig . draftsLoaded = true ;
userConfig . saveConfig ( false ) ;
} ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2021-09-20 00:10:42 +02:00
public int getDraftFolderId ( long dialogId ) {
return draftsFolderIds . get ( dialogId , 0 ) ;
2019-12-31 14:08:08 +01:00
}
2021-09-20 00:10:42 +02:00
public void setDraftFolderId ( long dialogId , int folderId ) {
draftsFolderIds . put ( dialogId , folderId ) ;
2019-12-31 14:08:08 +01:00
}
public void clearDraftsFolderIds ( ) {
draftsFolderIds . clear ( ) ;
}
2020-09-30 15:48:47 +02:00
public LongSparseArray < SparseArray < TLRPC . DraftMessage > > getDrafts ( ) {
2019-12-31 14:08:08 +01:00
return drafts ;
}
2021-09-20 00:10:42 +02:00
public TLRPC . DraftMessage getDraft ( long dialogId , int threadId ) {
SparseArray < TLRPC . DraftMessage > threads = drafts . get ( dialogId ) ;
2020-09-30 15:48:47 +02:00
if ( threads = = null ) {
return null ;
}
return threads . get ( threadId ) ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
public TLRPC . Message getDraftMessage ( long dialogId , int threadId ) {
SparseArray < TLRPC . Message > threads = draftMessages . get ( dialogId ) ;
2020-09-30 15:48:47 +02:00
if ( threads = = null ) {
return null ;
}
return threads . get ( threadId ) ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
public void saveDraft ( long dialogId , int threadId , CharSequence message , ArrayList < TLRPC . MessageEntity > entities , TLRPC . Message replyToMessage , boolean noWebpage ) {
saveDraft ( dialogId , threadId , message , entities , replyToMessage , noWebpage , false ) ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
public void saveDraft ( long dialogId , int threadId , CharSequence message , ArrayList < TLRPC . MessageEntity > entities , TLRPC . Message replyToMessage , boolean noWebpage , boolean clean ) {
2018-07-30 04:07:02 +02:00
TLRPC . DraftMessage draftMessage ;
if ( ! TextUtils . isEmpty ( message ) | | replyToMessage ! = null ) {
draftMessage = new TLRPC . TL_draftMessage ( ) ;
} else {
draftMessage = new TLRPC . TL_draftMessageEmpty ( ) ;
}
draftMessage . date = ( int ) ( System . currentTimeMillis ( ) / 1000 ) ;
draftMessage . message = message = = null ? " " : message . toString ( ) ;
draftMessage . no_webpage = noWebpage ;
if ( replyToMessage ! = null ) {
draftMessage . reply_to_msg_id = replyToMessage . id ;
draftMessage . flags | = 1 ;
}
if ( entities ! = null & & ! entities . isEmpty ( ) ) {
draftMessage . entities = entities ;
draftMessage . flags | = 8 ;
}
2021-09-20 00:10:42 +02:00
SparseArray < TLRPC . DraftMessage > threads = drafts . get ( dialogId ) ;
2020-09-30 15:48:47 +02:00
TLRPC . DraftMessage currentDraft = threads = = null ? null : threads . get ( threadId ) ;
2018-07-30 04:07:02 +02:00
if ( ! clean ) {
if ( currentDraft ! = null & & currentDraft . message . equals ( draftMessage . message ) & & currentDraft . reply_to_msg_id = = draftMessage . reply_to_msg_id & & currentDraft . no_webpage = = draftMessage . no_webpage | |
currentDraft = = null & & TextUtils . isEmpty ( draftMessage . message ) & & draftMessage . reply_to_msg_id = = 0 ) {
return ;
}
}
2021-09-20 00:10:42 +02:00
saveDraft ( dialogId , threadId , draftMessage , replyToMessage , false ) ;
2020-09-30 15:48:47 +02:00
if ( threadId = = 0 ) {
2021-09-20 00:10:42 +02:00
if ( ! DialogObject . isEncryptedDialog ( dialogId ) ) {
2020-09-30 15:48:47 +02:00
TLRPC . TL_messages_saveDraft req = new TLRPC . TL_messages_saveDraft ( ) ;
2021-09-20 00:10:42 +02:00
req . peer = getMessagesController ( ) . getInputPeer ( dialogId ) ;
2020-09-30 15:48:47 +02:00
if ( req . peer = = null ) {
return ;
}
req . message = draftMessage . message ;
req . no_webpage = draftMessage . no_webpage ;
req . reply_to_msg_id = draftMessage . reply_to_msg_id ;
req . entities = draftMessage . entities ;
req . flags = draftMessage . flags ;
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2018-07-30 04:07:02 +02:00
2020-09-30 15:48:47 +02:00
} ) ;
}
getMessagesController ( ) . sortDialogs ( null ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . dialogsNeedReload ) ;
2018-07-30 04:07:02 +02:00
}
}
2021-09-20 00:10:42 +02:00
public void saveDraft ( long dialogId , int threadId , TLRPC . DraftMessage draft , TLRPC . Message replyToMessage , boolean fromServer ) {
2020-09-30 15:48:47 +02:00
SharedPreferences . Editor editor = draftPreferences . edit ( ) ;
2021-09-20 00:10:42 +02:00
MessagesController messagesController = getMessagesController ( ) ;
2018-07-30 04:07:02 +02:00
if ( draft = = null | | draft instanceof TLRPC . TL_draftMessageEmpty ) {
2020-09-30 15:48:47 +02:00
{
2021-09-20 00:10:42 +02:00
SparseArray < TLRPC . DraftMessage > threads = drafts . get ( dialogId ) ;
2020-09-30 15:48:47 +02:00
if ( threads ! = null ) {
threads . remove ( threadId ) ;
if ( threads . size ( ) = = 0 ) {
2021-09-20 00:10:42 +02:00
drafts . remove ( dialogId ) ;
2020-09-30 15:48:47 +02:00
}
}
}
{
2021-09-20 00:10:42 +02:00
SparseArray < TLRPC . Message > threads = draftMessages . get ( dialogId ) ;
2020-09-30 15:48:47 +02:00
if ( threads ! = null ) {
threads . remove ( threadId ) ;
if ( threads . size ( ) = = 0 ) {
2021-09-20 00:10:42 +02:00
draftMessages . remove ( dialogId ) ;
2020-09-30 15:48:47 +02:00
}
}
}
if ( threadId = = 0 ) {
2021-09-20 11:14:20 +02:00
draftPreferences . edit ( ) . remove ( " " + dialogId ) . remove ( " r_ " + dialogId ) . apply ( ) ;
2020-09-30 15:48:47 +02:00
} else {
2021-09-20 00:10:42 +02:00
draftPreferences . edit ( ) . remove ( " t_ " + dialogId + " _ " + threadId ) . remove ( " rt_ " + dialogId + " _ " + threadId ) . commit ( ) ;
2020-09-30 15:48:47 +02:00
}
2021-09-20 00:10:42 +02:00
messagesController . removeDraftDialogIfNeed ( dialogId ) ;
2018-07-30 04:07:02 +02:00
} else {
2021-09-20 00:10:42 +02:00
SparseArray < TLRPC . DraftMessage > threads = drafts . get ( dialogId ) ;
2020-09-30 15:48:47 +02:00
if ( threads = = null ) {
threads = new SparseArray < > ( ) ;
2021-09-20 00:10:42 +02:00
drafts . put ( dialogId , threads ) ;
2020-09-30 15:48:47 +02:00
}
threads . put ( threadId , draft ) ;
if ( threadId = = 0 ) {
2021-09-20 00:10:42 +02:00
messagesController . putDraftDialogIfNeed ( dialogId , draft ) ;
2020-09-30 15:48:47 +02:00
}
2018-07-30 04:07:02 +02:00
try {
SerializedData serializedData = new SerializedData ( draft . getObjectSize ( ) ) ;
draft . serializeToStream ( serializedData ) ;
2021-09-20 00:10:42 +02:00
editor . putString ( threadId = = 0 ? ( " " + dialogId ) : ( " t_ " + dialogId + " _ " + threadId ) , Utilities . bytesToHex ( serializedData . toByteArray ( ) ) ) ;
2018-07-30 04:07:02 +02:00
serializedData . cleanup ( ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
}
2021-09-20 00:10:42 +02:00
SparseArray < TLRPC . Message > threads = draftMessages . get ( dialogId ) ;
2018-07-30 04:07:02 +02:00
if ( replyToMessage = = null ) {
2020-09-30 15:48:47 +02:00
if ( threads ! = null ) {
threads . remove ( threadId ) ;
if ( threads . size ( ) = = 0 ) {
2021-09-20 00:10:42 +02:00
draftMessages . remove ( dialogId ) ;
2020-09-30 15:48:47 +02:00
}
}
if ( threadId = = 0 ) {
2021-09-20 00:10:42 +02:00
editor . remove ( " r_ " + dialogId ) ;
2020-09-30 15:48:47 +02:00
} else {
2021-09-20 00:10:42 +02:00
editor . remove ( " rt_ " + dialogId + " _ " + threadId ) ;
2020-09-30 15:48:47 +02:00
}
2018-07-30 04:07:02 +02:00
} else {
2020-09-30 15:48:47 +02:00
if ( threads = = null ) {
threads = new SparseArray < > ( ) ;
2021-09-20 00:10:42 +02:00
draftMessages . put ( dialogId , threads ) ;
2020-09-30 15:48:47 +02:00
}
threads . put ( threadId , replyToMessage ) ;
2018-07-30 04:07:02 +02:00
SerializedData serializedData = new SerializedData ( replyToMessage . getObjectSize ( ) ) ;
replyToMessage . serializeToStream ( serializedData ) ;
2021-09-20 00:10:42 +02:00
editor . putString ( threadId = = 0 ? ( " r_ " + dialogId ) : ( " rt_ " + dialogId + " _ " + threadId ) , Utilities . bytesToHex ( serializedData . toByteArray ( ) ) ) ;
2018-07-30 04:07:02 +02:00
serializedData . cleanup ( ) ;
}
2020-06-25 17:28:24 +02:00
editor . apply ( ) ;
2020-09-30 15:48:47 +02:00
if ( fromServer & & threadId = = 0 ) {
2021-09-20 00:10:42 +02:00
if ( draft ! = null & & draft . reply_to_msg_id ! = 0 & & replyToMessage = = null ) {
2018-07-30 04:07:02 +02:00
TLRPC . User user = null ;
TLRPC . Chat chat = null ;
2021-09-20 00:10:42 +02:00
if ( DialogObject . isUserDialog ( dialogId ) ) {
user = getMessagesController ( ) . getUser ( dialogId ) ;
2018-07-30 04:07:02 +02:00
} else {
2021-09-20 00:10:42 +02:00
chat = getMessagesController ( ) . getChat ( - dialogId ) ;
2018-07-30 04:07:02 +02:00
}
if ( user ! = null | | chat ! = null ) {
2021-09-20 00:10:42 +02:00
long channelId = ChatObject . isChannel ( chat ) ? chat . id : 0 ;
int messageId = draft . reply_to_msg_id ;
2018-07-30 04:07:02 +02:00
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
TLRPC . Message message = null ;
2021-09-20 00:10:42 +02:00
SQLiteCursor cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT data FROM messages_v2 WHERE mid = %d and uid = %d " , messageId , dialogId ) ) ;
2019-01-23 18:03:33 +01:00
if ( cursor . next ( ) ) {
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2019-07-18 15:01:39 +02:00
message . readAttachPath ( data , getUserConfig ( ) . clientUserId ) ;
2019-01-23 18:03:33 +01:00
data . reuse ( ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
}
cursor . dispose ( ) ;
if ( message = = null ) {
2021-09-20 00:10:42 +02:00
if ( channelId ! = 0 ) {
TLRPC . TL_channels_getMessages req = new TLRPC . TL_channels_getMessages ( ) ;
req . channel = getMessagesController ( ) . getInputChannel ( channelId ) ;
req . id . add ( messageId ) ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2019-01-23 18:03:33 +01:00
if ( error = = null ) {
TLRPC . messages_Messages messagesRes = ( TLRPC . messages_Messages ) response ;
if ( ! messagesRes . messages . isEmpty ( ) ) {
2021-09-20 00:10:42 +02:00
saveDraftReplyMessage ( dialogId , threadId , messagesRes . messages . get ( 0 ) ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
}
} ) ;
2018-07-30 04:07:02 +02:00
} else {
2019-01-23 18:03:33 +01:00
TLRPC . TL_messages_getMessages req = new TLRPC . TL_messages_getMessages ( ) ;
2021-09-20 00:10:42 +02:00
req . id . add ( messageId ) ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( req , ( response , error ) - > {
2019-01-23 18:03:33 +01:00
if ( error = = null ) {
TLRPC . messages_Messages messagesRes = ( TLRPC . messages_Messages ) response ;
if ( ! messagesRes . messages . isEmpty ( ) ) {
2021-09-20 00:10:42 +02:00
saveDraftReplyMessage ( dialogId , threadId , messagesRes . messages . get ( 0 ) ) ;
2019-01-23 18:03:33 +01:00
}
}
} ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} else {
2021-09-20 00:10:42 +02:00
saveDraftReplyMessage ( dialogId , threadId , message ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
}
2021-09-20 00:10:42 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . newDraftReceived , dialogId ) ;
2018-07-30 04:07:02 +02:00
}
}
2021-09-20 00:10:42 +02:00
private void saveDraftReplyMessage ( long dialogId , int threadId , TLRPC . Message message ) {
2018-07-30 04:07:02 +02:00
if ( message = = null ) {
return ;
}
2019-01-23 18:03:33 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > {
2021-09-20 00:10:42 +02:00
SparseArray < TLRPC . DraftMessage > threads = drafts . get ( dialogId ) ;
2020-09-30 15:48:47 +02:00
TLRPC . DraftMessage draftMessage = threads ! = null ? threads . get ( threadId ) : null ;
2019-01-23 18:03:33 +01:00
if ( draftMessage ! = null & & draftMessage . reply_to_msg_id = = message . id ) {
2021-09-20 00:10:42 +02:00
SparseArray < TLRPC . Message > threads2 = draftMessages . get ( dialogId ) ;
2020-09-30 15:48:47 +02:00
if ( threads2 = = null ) {
threads2 = new SparseArray < > ( ) ;
2021-09-20 00:10:42 +02:00
draftMessages . put ( dialogId , threads2 ) ;
2020-09-30 15:48:47 +02:00
}
threads2 . put ( threadId , message ) ;
2019-01-23 18:03:33 +01:00
SerializedData serializedData = new SerializedData ( message . getObjectSize ( ) ) ;
message . serializeToStream ( serializedData ) ;
2021-09-20 11:14:20 +02:00
draftPreferences . edit ( ) . putString ( threadId = = 0 ? ( " r_ " + dialogId ) : ( " rt_ " + dialogId + " _ " + threadId ) , Utilities . bytesToHex ( serializedData . toByteArray ( ) ) ) . apply ( ) ;
2021-09-20 00:10:42 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . newDraftReceived , dialogId ) ;
2019-01-23 18:03:33 +01:00
serializedData . cleanup ( ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2019-12-31 14:08:08 +01:00
public void clearAllDrafts ( boolean notify ) {
2018-07-30 04:07:02 +02:00
drafts . clear ( ) ;
draftMessages . clear ( ) ;
2019-12-31 14:08:08 +01:00
draftsFolderIds . clear ( ) ;
2020-10-01 11:01:48 +02:00
draftPreferences . edit ( ) . clear ( ) . apply ( ) ;
2019-12-31 14:08:08 +01:00
if ( notify ) {
getMessagesController ( ) . sortDialogs ( null ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . dialogsNeedReload ) ;
}
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
public void cleanDraft ( long dialogId , int threadId , boolean replyOnly ) {
SparseArray < TLRPC . DraftMessage > threads2 = drafts . get ( dialogId ) ;
2020-09-30 15:48:47 +02:00
TLRPC . DraftMessage draftMessage = threads2 ! = null ? threads2 . get ( threadId ) : null ;
2018-07-30 04:07:02 +02:00
if ( draftMessage = = null ) {
return ;
}
if ( ! replyOnly ) {
2020-09-30 15:48:47 +02:00
{
2021-09-20 00:10:42 +02:00
SparseArray < TLRPC . DraftMessage > threads = drafts . get ( dialogId ) ;
2020-09-30 15:48:47 +02:00
if ( threads ! = null ) {
threads . remove ( threadId ) ;
if ( threads . size ( ) = = 0 ) {
2021-09-20 00:10:42 +02:00
drafts . remove ( dialogId ) ;
2020-09-30 15:48:47 +02:00
}
}
}
{
2021-09-20 00:10:42 +02:00
SparseArray < TLRPC . Message > threads = draftMessages . get ( dialogId ) ;
2020-09-30 15:48:47 +02:00
if ( threads ! = null ) {
threads . remove ( threadId ) ;
if ( threads . size ( ) = = 0 ) {
2021-09-20 00:10:42 +02:00
draftMessages . remove ( dialogId ) ;
2020-09-30 15:48:47 +02:00
}
}
}
if ( threadId = = 0 ) {
2021-09-20 11:14:20 +02:00
draftPreferences . edit ( ) . remove ( " " + dialogId ) . remove ( " r_ " + dialogId ) . apply ( ) ;
2020-09-30 15:48:47 +02:00
getMessagesController ( ) . sortDialogs ( null ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . dialogsNeedReload ) ;
} else {
2021-09-20 00:10:42 +02:00
draftPreferences . edit ( ) . remove ( " t_ " + dialogId + " _ " + threadId ) . remove ( " rt_ " + dialogId + " _ " + threadId ) . commit ( ) ;
2020-09-30 15:48:47 +02:00
}
2018-07-30 04:07:02 +02:00
} else if ( draftMessage . reply_to_msg_id ! = 0 ) {
draftMessage . reply_to_msg_id = 0 ;
draftMessage . flags & = ~ 1 ;
2021-09-20 00:10:42 +02:00
saveDraft ( dialogId , threadId , draftMessage . message , draftMessage . entities , null , draftMessage . no_webpage , true ) ;
2018-07-30 04:07:02 +02:00
}
}
public void beginTransaction ( ) {
inTransaction = true ;
}
public void endTransaction ( ) {
inTransaction = false ;
}
//---------------- DRAFT END ----------------
2021-07-15 16:24:57 +02:00
private HashMap < String , TLRPC . BotInfo > botInfos = new HashMap < > ( ) ;
2018-07-30 04:07:02 +02:00
private LongSparseArray < TLRPC . Message > botKeyboards = new LongSparseArray < > ( ) ;
private SparseLongArray botKeyboardsByMids = new SparseLongArray ( ) ;
2021-09-20 00:10:42 +02:00
public void clearBotKeyboard ( long dialogId , ArrayList < Integer > messages ) {
2019-01-23 18:03:33 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > {
if ( messages ! = null ) {
for ( int a = 0 ; a < messages . size ( ) ; a + + ) {
long did1 = botKeyboardsByMids . get ( messages . get ( a ) ) ;
if ( did1 ! = 0 ) {
botKeyboards . remove ( did1 ) ;
botKeyboardsByMids . delete ( messages . get ( a ) ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . botKeyboardDidLoad , null , did1 ) ;
2018-07-30 04:07:02 +02:00
}
}
2019-01-23 18:03:33 +01:00
} else {
2021-09-20 00:10:42 +02:00
botKeyboards . remove ( dialogId ) ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . botKeyboardDidLoad , null , dialogId ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2021-09-20 00:10:42 +02:00
public void loadBotKeyboard ( long dialogId ) {
TLRPC . Message keyboard = botKeyboards . get ( dialogId ) ;
2018-07-30 04:07:02 +02:00
if ( keyboard ! = null ) {
2021-09-20 00:10:42 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . botKeyboardDidLoad , keyboard , dialogId ) ;
2018-07-30 04:07:02 +02:00
return ;
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
TLRPC . Message botKeyboard = null ;
2021-09-20 00:10:42 +02:00
SQLiteCursor cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT info FROM bot_keyboard WHERE uid = %d " , dialogId ) ) ;
2019-01-23 18:03:33 +01:00
if ( cursor . next ( ) ) {
NativeByteBuffer data ;
2018-07-30 04:07:02 +02:00
2019-01-23 18:03:33 +01:00
if ( ! cursor . isNull ( 0 ) ) {
data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
botKeyboard = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
data . reuse ( ) ;
2018-07-30 04:07:02 +02:00
}
}
2019-01-23 18:03:33 +01:00
}
cursor . dispose ( ) ;
2018-07-30 04:07:02 +02:00
2019-01-23 18:03:33 +01:00
if ( botKeyboard ! = null ) {
2021-09-20 00:10:42 +02:00
TLRPC . Message botKeyboardFinal = botKeyboard ;
AndroidUtilities . runOnUIThread ( ( ) - > getNotificationCenter ( ) . postNotificationName ( NotificationCenter . botKeyboardDidLoad , botKeyboardFinal , dialogId ) ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2021-09-20 00:10:42 +02:00
private TLRPC . BotInfo loadBotInfoInternal ( long uid , long dialogId ) throws SQLiteException {
2021-07-15 16:24:57 +02:00
TLRPC . BotInfo botInfo = null ;
SQLiteCursor cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT info FROM bot_info_v2 WHERE uid = %d AND dialogId = %d " , uid , dialogId ) ) ;
if ( cursor . next ( ) ) {
NativeByteBuffer data ;
if ( ! cursor . isNull ( 0 ) ) {
data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
botInfo = TLRPC . BotInfo . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
data . reuse ( ) ;
}
}
}
cursor . dispose ( ) ;
return botInfo ;
}
2021-09-20 00:10:42 +02:00
public void loadBotInfo ( long uid , long dialogId , boolean cache , int classGuid ) {
2018-07-30 04:07:02 +02:00
if ( cache ) {
2021-07-15 16:24:57 +02:00
TLRPC . BotInfo botInfo = botInfos . get ( uid + " _ " + dialogId ) ;
2018-07-30 04:07:02 +02:00
if ( botInfo ! = null ) {
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . botInfoDidLoad , botInfo , classGuid ) ;
2018-07-30 04:07:02 +02:00
return ;
}
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2021-07-15 16:24:57 +02:00
TLRPC . BotInfo botInfo = loadBotInfoInternal ( uid , dialogId ) ;
2019-01-23 18:03:33 +01:00
if ( botInfo ! = null ) {
2021-09-20 00:10:42 +02:00
AndroidUtilities . runOnUIThread ( ( ) - > getNotificationCenter ( ) . postNotificationName ( NotificationCenter . botInfoDidLoad , botInfo , classGuid ) ) ;
2018-07-30 04:07:02 +02:00
}
2019-01-23 18:03:33 +01:00
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
2021-09-20 00:10:42 +02:00
public void putBotKeyboard ( long dialogId , TLRPC . Message message ) {
2018-07-30 04:07:02 +02:00
if ( message = = null ) {
return ;
}
try {
int mid = 0 ;
2021-09-20 00:10:42 +02:00
SQLiteCursor cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT mid FROM bot_keyboard WHERE uid = %d " , dialogId ) ) ;
2018-07-30 04:07:02 +02:00
if ( cursor . next ( ) ) {
mid = cursor . intValue ( 0 ) ;
}
cursor . dispose ( ) ;
if ( mid > = message . id ) {
return ;
}
2019-07-18 15:01:39 +02:00
SQLitePreparedStatement state = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " REPLACE INTO bot_keyboard VALUES(?, ?, ?) " ) ;
2018-07-30 04:07:02 +02:00
state . requery ( ) ;
NativeByteBuffer data = new NativeByteBuffer ( message . getObjectSize ( ) ) ;
message . serializeToStream ( data ) ;
2021-09-20 00:10:42 +02:00
state . bindLong ( 1 , dialogId ) ;
2018-07-30 04:07:02 +02:00
state . bindInteger ( 2 , message . id ) ;
state . bindByteBuffer ( 3 , data ) ;
state . step ( ) ;
data . reuse ( ) ;
state . dispose ( ) ;
2019-01-23 18:03:33 +01:00
AndroidUtilities . runOnUIThread ( ( ) - > {
2021-09-20 00:10:42 +02:00
TLRPC . Message old = botKeyboards . get ( dialogId ) ;
botKeyboards . put ( dialogId , message ) ;
long channelId = MessageObject . getChannelId ( message ) ;
if ( channelId = = 0 ) {
if ( old ! = null ) {
botKeyboardsByMids . delete ( old . id ) ;
}
botKeyboardsByMids . put ( message . id , dialogId ) ;
2018-07-30 04:07:02 +02:00
}
2021-09-20 00:10:42 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . botKeyboardDidLoad , message , dialogId ) ;
2018-07-30 04:07:02 +02:00
} ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
}
2021-06-25 02:43:10 +02:00
public void putBotInfo ( long dialogId , TLRPC . BotInfo botInfo ) {
2018-07-30 04:07:02 +02:00
if ( botInfo = = null ) {
return ;
}
2021-07-15 16:24:57 +02:00
botInfos . put ( botInfo . user_id + " _ " + dialogId , botInfo ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-01-23 18:03:33 +01:00
try {
2021-06-25 02:43:10 +02:00
SQLitePreparedStatement state = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " REPLACE INTO bot_info_v2 VALUES(?, ?, ?) " ) ;
2019-01-23 18:03:33 +01:00
state . requery ( ) ;
NativeByteBuffer data = new NativeByteBuffer ( botInfo . getObjectSize ( ) ) ;
botInfo . serializeToStream ( data ) ;
2021-09-20 00:10:42 +02:00
state . bindLong ( 1 , botInfo . user_id ) ;
2021-07-15 16:24:57 +02:00
state . bindLong ( 2 , dialogId ) ;
state . bindByteBuffer ( 3 , data ) ;
state . step ( ) ;
data . reuse ( ) ;
state . dispose ( ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
} ) ;
}
public void updateBotInfo ( long dialogId , TLRPC . TL_updateBotCommands update ) {
TLRPC . BotInfo botInfo = botInfos . get ( update . bot_id + " _ " + dialogId ) ;
if ( botInfo ! = null ) {
botInfo . commands = update . commands ;
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . botInfoDidLoad , botInfo , 0 ) ;
}
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
try {
TLRPC . BotInfo info = loadBotInfoInternal ( update . bot_id , dialogId ) ;
if ( info ! = null ) {
info . commands = update . commands ;
}
SQLitePreparedStatement state = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " REPLACE INTO bot_info_v2 VALUES(?, ?, ?) " ) ;
state . requery ( ) ;
NativeByteBuffer data = new NativeByteBuffer ( info . getObjectSize ( ) ) ;
info . serializeToStream ( data ) ;
2021-09-20 00:10:42 +02:00
state . bindLong ( 1 , info . user_id ) ;
2021-06-25 02:43:10 +02:00
state . bindLong ( 2 , dialogId ) ;
state . bindByteBuffer ( 3 , data ) ;
2019-01-23 18:03:33 +01:00
state . step ( ) ;
data . reuse ( ) ;
state . dispose ( ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
2018-07-30 04:07:02 +02:00
}
} ) ;
}
//---------------- BOT END ----------------
2019-05-14 14:08:05 +02:00
//---------------- EMOJI START ----------------
public static class KeywordResult {
public String emoji ;
public String keyword ;
}
public interface KeywordResultCallback {
void run ( ArrayList < KeywordResult > param , String alias ) ;
}
private HashMap < String , Boolean > currentFetchingEmoji = new HashMap < > ( ) ;
public void fetchNewEmojiKeywords ( String [ ] langCodes ) {
if ( langCodes = = null ) {
return ;
}
for ( int a = 0 ; a < langCodes . length ; a + + ) {
String langCode = langCodes [ a ] ;
if ( TextUtils . isEmpty ( langCode ) ) {
return ;
}
if ( currentFetchingEmoji . get ( langCode ) ! = null ) {
return ;
}
currentFetchingEmoji . put ( langCode , true ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-05-14 14:08:05 +02:00
int version = - 1 ;
String alias = null ;
long date = 0 ;
try {
2019-07-18 15:01:39 +02:00
SQLiteCursor cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( " SELECT alias, version, date FROM emoji_keywords_info_v2 WHERE lang = ? " , langCode ) ;
2019-05-14 14:08:05 +02:00
if ( cursor . next ( ) ) {
alias = cursor . stringValue ( 0 ) ;
version = cursor . intValue ( 1 ) ;
date = cursor . longValue ( 2 ) ;
}
cursor . dispose ( ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
if ( ! BuildVars . DEBUG_VERSION & & Math . abs ( System . currentTimeMillis ( ) - date ) < 60 * 60 * 1000 ) {
AndroidUtilities . runOnUIThread ( ( ) - > currentFetchingEmoji . remove ( langCode ) ) ;
return ;
}
TLObject request ;
if ( version = = - 1 ) {
TLRPC . TL_messages_getEmojiKeywords req = new TLRPC . TL_messages_getEmojiKeywords ( ) ;
req . lang_code = langCode ;
request = req ;
} else {
TLRPC . TL_messages_getEmojiKeywordsDifference req = new TLRPC . TL_messages_getEmojiKeywordsDifference ( ) ;
req . lang_code = langCode ;
req . from_version = version ;
request = req ;
}
String aliasFinal = alias ;
int versionFinal = version ;
2019-07-18 15:01:39 +02:00
getConnectionsManager ( ) . sendRequest ( request , ( response , error ) - > {
2019-05-14 14:08:05 +02:00
if ( response ! = null ) {
TLRPC . TL_emojiKeywordsDifference res = ( TLRPC . TL_emojiKeywordsDifference ) response ;
if ( versionFinal ! = - 1 & & ! res . lang_code . equals ( aliasFinal ) ) {
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-05-14 14:08:05 +02:00
try {
2019-07-18 15:01:39 +02:00
SQLitePreparedStatement deleteState = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " DELETE FROM emoji_keywords_info_v2 WHERE lang = ? " ) ;
2019-05-14 14:08:05 +02:00
deleteState . bindString ( 1 , langCode ) ;
deleteState . step ( ) ;
deleteState . dispose ( ) ;
AndroidUtilities . runOnUIThread ( ( ) - > {
currentFetchingEmoji . remove ( langCode ) ;
fetchNewEmojiKeywords ( new String [ ] { langCode } ) ;
} ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
} ) ;
} else {
putEmojiKeywords ( langCode , res ) ;
}
} else {
AndroidUtilities . runOnUIThread ( ( ) - > currentFetchingEmoji . remove ( langCode ) ) ;
}
} ) ;
} ) ;
}
}
private void putEmojiKeywords ( String lang , TLRPC . TL_emojiKeywordsDifference res ) {
if ( res = = null ) {
return ;
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2019-05-14 14:08:05 +02:00
try {
if ( ! res . keywords . isEmpty ( ) ) {
2019-07-18 15:01:39 +02:00
SQLitePreparedStatement insertState = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " REPLACE INTO emoji_keywords_v2 VALUES(?, ?, ?) " ) ;
SQLitePreparedStatement deleteState = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " DELETE FROM emoji_keywords_v2 WHERE lang = ? AND keyword = ? AND emoji = ? " ) ;
getMessagesStorage ( ) . getDatabase ( ) . beginTransaction ( ) ;
2019-05-14 14:08:05 +02:00
for ( int a = 0 , N = res . keywords . size ( ) ; a < N ; a + + ) {
TLRPC . EmojiKeyword keyword = res . keywords . get ( a ) ;
if ( keyword instanceof TLRPC . TL_emojiKeyword ) {
TLRPC . TL_emojiKeyword emojiKeyword = ( TLRPC . TL_emojiKeyword ) keyword ;
String key = emojiKeyword . keyword . toLowerCase ( ) ;
for ( int b = 0 , N2 = emojiKeyword . emoticons . size ( ) ; b < N2 ; b + + ) {
insertState . requery ( ) ;
insertState . bindString ( 1 , res . lang_code ) ;
insertState . bindString ( 2 , key ) ;
insertState . bindString ( 3 , emojiKeyword . emoticons . get ( b ) ) ;
insertState . step ( ) ;
}
} else if ( keyword instanceof TLRPC . TL_emojiKeywordDeleted ) {
TLRPC . TL_emojiKeywordDeleted keywordDeleted = ( TLRPC . TL_emojiKeywordDeleted ) keyword ;
String key = keywordDeleted . keyword . toLowerCase ( ) ;
for ( int b = 0 , N2 = keywordDeleted . emoticons . size ( ) ; b < N2 ; b + + ) {
deleteState . requery ( ) ;
deleteState . bindString ( 1 , res . lang_code ) ;
deleteState . bindString ( 2 , key ) ;
deleteState . bindString ( 3 , keywordDeleted . emoticons . get ( b ) ) ;
deleteState . step ( ) ;
}
}
}
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getDatabase ( ) . commitTransaction ( ) ;
2019-05-14 14:08:05 +02:00
insertState . dispose ( ) ;
deleteState . dispose ( ) ;
}
2019-07-18 15:01:39 +02:00
SQLitePreparedStatement infoState = getMessagesStorage ( ) . getDatabase ( ) . executeFast ( " REPLACE INTO emoji_keywords_info_v2 VALUES(?, ?, ?, ?) " ) ;
2019-05-14 14:08:05 +02:00
infoState . bindString ( 1 , lang ) ;
infoState . bindString ( 2 , res . lang_code ) ;
infoState . bindInteger ( 3 , res . version ) ;
infoState . bindLong ( 4 , System . currentTimeMillis ( ) ) ;
infoState . step ( ) ;
infoState . dispose ( ) ;
AndroidUtilities . runOnUIThread ( ( ) - > {
currentFetchingEmoji . remove ( lang ) ;
2019-07-18 15:01:39 +02:00
getNotificationCenter ( ) . postNotificationName ( NotificationCenter . newEmojiSuggestionsAvailable , lang ) ;
2019-05-14 14:08:05 +02:00
} ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
} ) ;
}
public void getEmojiSuggestions ( String [ ] langCodes , String keyword , boolean fullMatch , KeywordResultCallback callback ) {
getEmojiSuggestions ( langCodes , keyword , fullMatch , callback , null ) ;
}
public void getEmojiSuggestions ( String [ ] langCodes , String keyword , boolean fullMatch , KeywordResultCallback callback , CountDownLatch sync ) {
if ( callback = = null ) {
return ;
}
if ( TextUtils . isEmpty ( keyword ) | | langCodes = = null ) {
callback . run ( new ArrayList < > ( ) , null ) ;
return ;
}
ArrayList < String > recentEmoji = new ArrayList < > ( Emoji . recentEmoji ) ;
2019-07-18 15:01:39 +02:00
getMessagesStorage ( ) . getStorageQueue ( ) . postRunnable ( ( ) - > {
2020-06-06 08:07:06 +02:00
ArrayList < KeywordResult > result = new ArrayList < > ( ) ;
2019-05-14 14:08:05 +02:00
HashMap < String , Boolean > resultMap = new HashMap < > ( ) ;
String alias = null ;
try {
SQLiteCursor cursor ;
boolean hasAny = false ;
for ( int a = 0 ; a < langCodes . length ; a + + ) {
2019-07-18 15:01:39 +02:00
cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( " SELECT alias FROM emoji_keywords_info_v2 WHERE lang = ? " , langCodes [ a ] ) ;
2019-05-14 14:08:05 +02:00
if ( cursor . next ( ) ) {
alias = cursor . stringValue ( 0 ) ;
}
cursor . dispose ( ) ;
if ( alias ! = null ) {
hasAny = true ;
}
}
if ( ! hasAny ) {
AndroidUtilities . runOnUIThread ( ( ) - > {
for ( int a = 0 ; a < langCodes . length ; a + + ) {
if ( currentFetchingEmoji . get ( langCodes [ a ] ) ! = null ) {
return ;
}
}
callback . run ( result , null ) ;
} ) ;
return ;
}
String key = keyword . toLowerCase ( ) ;
for ( int a = 0 ; a < 2 ; a + + ) {
if ( a = = 1 ) {
String translitKey = LocaleController . getInstance ( ) . getTranslitString ( key , false , false ) ;
if ( translitKey . equals ( key ) ) {
continue ;
}
key = translitKey ;
}
String key2 = null ;
StringBuilder nextKey = new StringBuilder ( key ) ;
int pos = nextKey . length ( ) ;
while ( pos > 0 ) {
pos - - ;
char value = nextKey . charAt ( pos ) ;
value + + ;
nextKey . setCharAt ( pos , value ) ;
if ( value ! = 0 ) {
key2 = nextKey . toString ( ) ;
break ;
}
}
if ( fullMatch ) {
2019-07-18 15:01:39 +02:00
cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( " SELECT emoji, keyword FROM emoji_keywords_v2 WHERE keyword = ? " , key ) ;
2019-05-14 14:08:05 +02:00
} else if ( key2 ! = null ) {
2019-07-18 15:01:39 +02:00
cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( " SELECT emoji, keyword FROM emoji_keywords_v2 WHERE keyword >= ? AND keyword < ? " , key , key2 ) ;
2019-05-14 14:08:05 +02:00
} else {
key + = " % " ;
2019-07-18 15:01:39 +02:00
cursor = getMessagesStorage ( ) . getDatabase ( ) . queryFinalized ( " SELECT emoji, keyword FROM emoji_keywords_v2 WHERE keyword LIKE ? " , key ) ;
2019-05-14 14:08:05 +02:00
}
while ( cursor . next ( ) ) {
String value = cursor . stringValue ( 0 ) . replace ( " \ ufe0f " , " " ) ;
if ( resultMap . get ( value ) ! = null ) {
continue ;
}
resultMap . put ( value , true ) ;
KeywordResult keywordResult = new KeywordResult ( ) ;
keywordResult . emoji = value ;
keywordResult . keyword = cursor . stringValue ( 1 ) ;
result . add ( keywordResult ) ;
}
cursor . dispose ( ) ;
}
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
Collections . sort ( result , ( o1 , o2 ) - > {
int idx1 = recentEmoji . indexOf ( o1 . emoji ) ;
if ( idx1 < 0 ) {
idx1 = Integer . MAX_VALUE ;
}
int idx2 = recentEmoji . indexOf ( o2 . emoji ) ;
if ( idx2 < 0 ) {
idx2 = Integer . MAX_VALUE ;
}
if ( idx1 < idx2 ) {
return - 1 ;
} else if ( idx1 > idx2 ) {
return 1 ;
} else {
int len1 = o1 . keyword . length ( ) ;
int len2 = o2 . keyword . length ( ) ;
if ( len1 < len2 ) {
return - 1 ;
} else if ( len1 > len2 ) {
return 1 ;
}
return 0 ;
}
} ) ;
String aliasFinal = alias ;
if ( sync ! = null ) {
callback . run ( result , aliasFinal ) ;
sync . countDown ( ) ;
} else {
AndroidUtilities . runOnUIThread ( ( ) - > callback . run ( result , aliasFinal ) ) ;
}
} ) ;
if ( sync ! = null ) {
try {
sync . await ( ) ;
} catch ( Throwable ignore ) {
}
}
}
//---------------- EMOJI END ----------------
2018-07-30 04:07:02 +02:00
}