2014-10-31 20:02:29 +01:00
/ *
* This is the source code of Telegram for Android v . 1 . 7 . x .
* It is licensed under GNU GPL v . 2 or later .
* You should have received a copy of the license in this archive ( see LICENSE ) .
*
* Copyright Nikolai Kudashov , 2013 - 2014 .
* /
package org.telegram.ui.Adapters ;
import android.content.Context ;
2014-12-01 18:56:31 +01:00
import android.text.TextUtils ;
2014-10-31 20:02:29 +01:00
import android.view.View ;
import android.view.ViewGroup ;
import org.telegram.SQLite.SQLiteCursor ;
import org.telegram.android.AndroidUtilities ;
import org.telegram.android.ContactsController ;
import org.telegram.android.LocaleController ;
import org.telegram.android.MessageObject ;
import org.telegram.android.MessagesController ;
import org.telegram.android.MessagesStorage ;
import org.telegram.messenger.ByteBufferDesc ;
import org.telegram.messenger.ConnectionsManager ;
import org.telegram.messenger.FileLog ;
import org.telegram.messenger.R ;
import org.telegram.messenger.RPCRequest ;
import org.telegram.messenger.TLClassStore ;
import org.telegram.messenger.TLObject ;
import org.telegram.messenger.TLRPC ;
import org.telegram.messenger.UserConfig ;
import org.telegram.messenger.Utilities ;
import org.telegram.ui.Cells.DialogCell ;
2014-11-10 12:05:22 +01:00
import org.telegram.ui.Cells.GreySectionCell ;
2015-03-26 18:34:47 +01:00
import org.telegram.ui.Cells.HashtagSearchCell ;
2014-11-19 02:23:46 +01:00
import org.telegram.ui.Cells.LoadingCell ;
2014-11-10 12:05:22 +01:00
import org.telegram.ui.Cells.ProfileSearchCell ;
2014-10-31 20:02:29 +01:00
import java.util.ArrayList ;
2014-12-01 18:56:31 +01:00
import java.util.Collections ;
import java.util.Comparator ;
import java.util.HashMap ;
import java.util.Locale ;
2014-10-31 20:02:29 +01:00
import java.util.Timer ;
import java.util.TimerTask ;
2015-03-26 18:34:47 +01:00
public class DialogsSearchAdapter extends BaseSearchAdapter {
2014-12-01 18:56:31 +01:00
2014-10-31 20:02:29 +01:00
private Context mContext ;
private Timer searchTimer ;
2015-01-02 23:15:07 +01:00
private ArrayList < TLObject > searchResult = new ArrayList < > ( ) ;
private ArrayList < CharSequence > searchResultNames = new ArrayList < > ( ) ;
private ArrayList < MessageObject > searchResultMessages = new ArrayList < > ( ) ;
2015-03-26 18:34:47 +01:00
private ArrayList < String > searchResultHashtags = new ArrayList < > ( ) ;
2014-11-06 22:34:47 +01:00
private String lastSearchText ;
2014-10-31 20:02:29 +01:00
private long reqId = 0 ;
private int lastReqId ;
private MessagesActivitySearchAdapterDelegate delegate ;
2015-03-19 00:09:45 +01:00
private int needMessagesSearch ;
2014-11-19 02:23:46 +01:00
private boolean messagesSearchEndReached ;
private String lastMessagesSearchString ;
2014-11-21 01:14:44 +01:00
private int lastSearchId = 0 ;
2014-10-31 20:02:29 +01:00
2014-12-01 18:56:31 +01:00
private class DialogSearchResult {
public TLObject object ;
public int date ;
public CharSequence name ;
}
2015-03-19 00:09:45 +01:00
public interface MessagesActivitySearchAdapterDelegate {
void searchStateChanged ( boolean searching ) ;
2014-10-31 20:02:29 +01:00
}
2015-03-19 00:09:45 +01:00
public DialogsSearchAdapter ( Context context , int messagesSearch ) {
2014-10-31 20:02:29 +01:00
mContext = context ;
2014-11-17 23:04:31 +01:00
needMessagesSearch = messagesSearch ;
2014-10-31 20:02:29 +01:00
}
public void setDelegate ( MessagesActivitySearchAdapterDelegate delegate ) {
this . delegate = delegate ;
}
2014-11-19 02:23:46 +01:00
public boolean isMessagesSearchEndReached ( ) {
return messagesSearchEndReached ;
}
public void loadMoreSearchMessages ( ) {
searchMessagesInternal ( lastMessagesSearchString ) ;
}
2015-03-26 18:34:47 +01:00
public String getLastSearchString ( ) {
return lastMessagesSearchString ;
}
2014-10-31 20:02:29 +01:00
private void searchMessagesInternal ( final String query ) {
2015-03-19 00:09:45 +01:00
if ( needMessagesSearch = = 0 ) {
2014-11-17 23:04:31 +01:00
return ;
}
2014-10-31 20:02:29 +01:00
if ( reqId ! = 0 ) {
ConnectionsManager . getInstance ( ) . cancelRpc ( reqId , true ) ;
reqId = 0 ;
}
if ( query = = null | | query . length ( ) = = 0 ) {
searchResultMessages . clear ( ) ;
lastReqId = 0 ;
2014-11-19 02:23:46 +01:00
lastMessagesSearchString = null ;
2014-10-31 20:02:29 +01:00
notifyDataSetChanged ( ) ;
if ( delegate ! = null ) {
delegate . searchStateChanged ( false ) ;
}
return ;
}
2014-11-19 02:23:46 +01:00
final TLRPC . TL_messages_search req = new TLRPC . TL_messages_search ( ) ;
req . limit = 20 ;
2014-10-31 20:02:29 +01:00
req . peer = new TLRPC . TL_inputPeerEmpty ( ) ;
req . q = query ;
2014-11-19 02:23:46 +01:00
if ( lastMessagesSearchString ! = null & & query . equals ( lastMessagesSearchString ) & & ! searchResultMessages . isEmpty ( ) ) {
2015-03-19 00:09:45 +01:00
req . max_id = searchResultMessages . get ( searchResultMessages . size ( ) - 1 ) . getId ( ) ;
2014-11-19 02:23:46 +01:00
}
lastMessagesSearchString = query ;
2014-10-31 20:02:29 +01:00
req . filter = new TLRPC . TL_inputMessagesFilterEmpty ( ) ;
final int currentReqId = + + lastReqId ;
if ( delegate ! = null ) {
delegate . searchStateChanged ( true ) ;
}
reqId = ConnectionsManager . getInstance ( ) . performRpc ( req , new RPCRequest . RPCRequestDelegate ( ) {
@Override
public void run ( final TLObject response , final TLRPC . TL_error error ) {
2014-11-06 22:34:47 +01:00
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
2014-10-31 20:02:29 +01:00
@Override
public void run ( ) {
if ( currentReqId = = lastReqId ) {
if ( error = = null ) {
TLRPC . messages_Messages res = ( TLRPC . messages_Messages ) response ;
MessagesStorage . getInstance ( ) . putUsersAndChats ( res . users , res . chats , true , true ) ;
MessagesController . getInstance ( ) . putUsers ( res . users , false ) ;
MessagesController . getInstance ( ) . putChats ( res . chats , false ) ;
2014-11-19 02:23:46 +01:00
if ( req . max_id = = 0 ) {
searchResultMessages . clear ( ) ;
}
2014-10-31 20:02:29 +01:00
for ( TLRPC . Message message : res . messages ) {
2015-02-01 19:51:02 +01:00
searchResultMessages . add ( new MessageObject ( message , null , false ) ) ;
2014-10-31 20:02:29 +01:00
}
2014-11-19 02:23:46 +01:00
messagesSearchEndReached = res . messages . size ( ) ! = 20 ;
2014-10-31 20:02:29 +01:00
notifyDataSetChanged ( ) ;
}
}
if ( delegate ! = null ) {
delegate . searchStateChanged ( false ) ;
}
reqId = 0 ;
}
} ) ;
}
} , true , RPCRequest . RPCRequestClassGeneric | RPCRequest . RPCRequestClassFailOnServerErrors ) ;
}
2014-11-21 01:14:44 +01:00
private void searchDialogsInternal ( final String query , final boolean serverOnly , final int searchId ) {
2015-03-19 00:09:45 +01:00
if ( needMessagesSearch = = 2 ) {
return ;
}
2014-10-31 20:02:29 +01:00
MessagesStorage . getInstance ( ) . getStorageQueue ( ) . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2015-02-01 19:51:02 +01:00
String search1 = query . trim ( ) . toLowerCase ( ) ;
if ( search1 . length ( ) = = 0 ) {
2014-11-21 01:14:44 +01:00
lastSearchId = - 1 ;
updateSearchResults ( new ArrayList < TLObject > ( ) , new ArrayList < CharSequence > ( ) , new ArrayList < TLRPC . User > ( ) , lastSearchId ) ;
2014-10-31 20:02:29 +01:00
return ;
}
2015-02-01 19:51:02 +01:00
String search2 = LocaleController . getInstance ( ) . getTranslitString ( search1 ) ;
if ( search1 . equals ( search2 ) | | search2 . length ( ) = = 0 ) {
search2 = null ;
}
String search [ ] = new String [ 1 + ( search2 ! = null ? 1 : 0 ) ] ;
search [ 0 ] = search1 ;
if ( search2 ! = null ) {
search [ 1 ] = search2 ;
}
2014-10-31 20:02:29 +01:00
2015-01-02 23:15:07 +01:00
ArrayList < Integer > usersToLoad = new ArrayList < > ( ) ;
ArrayList < Integer > chatsToLoad = new ArrayList < > ( ) ;
ArrayList < Integer > encryptedToLoad = new ArrayList < > ( ) ;
ArrayList < TLRPC . User > encUsers = new ArrayList < > ( ) ;
2014-12-01 18:56:31 +01:00
int resultCount = 0 ;
2015-01-02 23:15:07 +01:00
HashMap < Long , DialogSearchResult > dialogsResult = new HashMap < > ( ) ;
2015-03-19 00:09:45 +01:00
SQLiteCursor cursor = MessagesStorage . getInstance ( ) . getDatabase ( ) . queryFinalized ( " SELECT did, date FROM dialogs ORDER BY date DESC LIMIT 200 " ) ;
2014-10-31 20:02:29 +01:00
while ( cursor . next ( ) ) {
2014-12-01 18:56:31 +01:00
long id = cursor . longValue ( 0 ) ;
DialogSearchResult dialogSearchResult = new DialogSearchResult ( ) ;
dialogSearchResult . date = cursor . intValue ( 1 ) ;
dialogsResult . put ( id , dialogSearchResult ) ;
2015-03-26 18:34:47 +01:00
int lower_id = ( int ) id ;
int high_id = ( int ) ( id > > 32 ) ;
2014-12-01 18:56:31 +01:00
if ( lower_id ! = 0 ) {
if ( high_id = = 1 ) {
if ( ! serverOnly & & ! chatsToLoad . contains ( lower_id ) ) {
chatsToLoad . add ( lower_id ) ;
}
} else {
if ( lower_id > 0 ) {
if ( ! usersToLoad . contains ( lower_id ) ) {
usersToLoad . add ( lower_id ) ;
}
} else {
if ( ! chatsToLoad . contains ( - lower_id ) ) {
chatsToLoad . add ( - lower_id ) ;
}
}
}
} else if ( ! serverOnly ) {
if ( ! encryptedToLoad . contains ( high_id ) ) {
encryptedToLoad . add ( high_id ) ;
}
2014-10-31 20:02:29 +01:00
}
2014-12-01 18:56:31 +01:00
}
cursor . dispose ( ) ;
if ( ! usersToLoad . isEmpty ( ) ) {
cursor = MessagesStorage . getInstance ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT data, status, name FROM users WHERE uid IN(%s) " , TextUtils . join ( " , " , usersToLoad ) ) ) ;
while ( cursor . next ( ) ) {
String name = cursor . stringValue ( 2 ) ;
2015-02-26 02:32:51 +01:00
String tName = LocaleController . getInstance ( ) . getTranslitString ( name ) ;
if ( name . equals ( tName ) ) {
tName = null ;
}
2014-12-01 18:56:31 +01:00
String username = null ;
int usernamePos = name . lastIndexOf ( " ;;; " ) ;
if ( usernamePos ! = - 1 ) {
username = name . substring ( usernamePos + 3 ) ;
}
int found = 0 ;
2015-02-01 19:51:02 +01:00
for ( String q : search ) {
2015-02-26 02:32:51 +01:00
if ( name . startsWith ( q ) | | name . contains ( " " + q ) | | tName ! = null & & ( tName . startsWith ( q ) | | tName . contains ( " " + q ) ) ) {
2015-02-01 19:51:02 +01:00
found = 1 ;
} else if ( username ! = null & & username . startsWith ( q ) ) {
found = 2 ;
}
if ( found ! = 0 ) {
ByteBufferDesc data = MessagesStorage . getInstance ( ) . getBuffersStorage ( ) . getFreeBuffer ( cursor . byteArrayLength ( 0 ) ) ;
if ( data ! = null & & cursor . byteBufferValue ( 0 , data . buffer ) ! = 0 ) {
TLRPC . User user = ( TLRPC . User ) TLClassStore . Instance ( ) . TLdeserialize ( data , data . readInt32 ( ) ) ;
if ( user . id ! = UserConfig . getClientUserId ( ) ) {
DialogSearchResult dialogSearchResult = dialogsResult . get ( ( long ) user . id ) ;
if ( user . status ! = null ) {
user . status . expires = cursor . intValue ( 1 ) ;
}
if ( found = = 1 ) {
dialogSearchResult . name = Utilities . generateSearchName ( user . first_name , user . last_name , q ) ;
} else {
dialogSearchResult . name = Utilities . generateSearchName ( " @ " + user . username , null , " @ " + q ) ;
}
dialogSearchResult . object = user ;
resultCount + + ;
2014-12-01 18:56:31 +01:00
}
2014-10-31 20:02:29 +01:00
}
2015-02-01 19:51:02 +01:00
MessagesStorage . getInstance ( ) . getBuffersStorage ( ) . reuseFreeBuffer ( data ) ;
break ;
2014-12-01 18:56:31 +01:00
}
}
}
cursor . dispose ( ) ;
}
if ( ! chatsToLoad . isEmpty ( ) ) {
cursor = MessagesStorage . getInstance ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT data, name FROM chats WHERE uid IN(%s) " , TextUtils . join ( " , " , chatsToLoad ) ) ) ;
while ( cursor . next ( ) ) {
String name = cursor . stringValue ( 1 ) ;
2015-02-26 02:32:51 +01:00
String tName = LocaleController . getInstance ( ) . getTranslitString ( name ) ;
if ( name . equals ( tName ) ) {
tName = null ;
}
2015-02-01 19:51:02 +01:00
for ( String q : search ) {
2015-02-26 02:32:51 +01:00
if ( name . startsWith ( q ) | | name . contains ( " " + q ) | | tName ! = null & & ( tName . startsWith ( q ) | | tName . contains ( " " + q ) ) ) {
2015-02-01 19:51:02 +01:00
ByteBufferDesc data = MessagesStorage . getInstance ( ) . getBuffersStorage ( ) . getFreeBuffer ( cursor . byteArrayLength ( 0 ) ) ;
if ( data ! = null & & cursor . byteBufferValue ( 0 , data . buffer ) ! = 0 ) {
TLRPC . Chat chat = ( TLRPC . Chat ) TLClassStore . Instance ( ) . TLdeserialize ( data , data . readInt32 ( ) ) ;
long dialog_id ;
if ( chat . id > 0 ) {
dialog_id = - chat . id ;
} else {
dialog_id = AndroidUtilities . makeBroadcastId ( chat . id ) ;
}
DialogSearchResult dialogSearchResult = dialogsResult . get ( dialog_id ) ;
dialogSearchResult . name = Utilities . generateSearchName ( chat . title , null , q ) ;
dialogSearchResult . object = chat ;
resultCount + + ;
2014-10-31 20:02:29 +01:00
}
2015-02-01 19:51:02 +01:00
MessagesStorage . getInstance ( ) . getBuffersStorage ( ) . reuseFreeBuffer ( data ) ;
break ;
2014-10-31 20:02:29 +01:00
}
}
}
2014-12-01 18:56:31 +01:00
cursor . dispose ( ) ;
2014-10-31 20:02:29 +01:00
}
2014-12-01 18:56:31 +01:00
if ( ! encryptedToLoad . isEmpty ( ) ) {
cursor = MessagesStorage . getInstance ( ) . getDatabase ( ) . queryFinalized ( String . format ( Locale . US , " SELECT q.data, u.name, q.user, q.g, q.authkey, q.ttl, u.data, u.status, q.layer, q.seq_in, q.seq_out, q.use_count, q.exchange_id, q.key_date, q.fprint, q.fauthkey, q.khash FROM enc_chats as q INNER JOIN users as u ON q.user = u.uid WHERE q.uid IN(%s) " , TextUtils . join ( " , " , encryptedToLoad ) ) ) ;
2014-10-31 20:02:29 +01:00
while ( cursor . next ( ) ) {
String name = cursor . stringValue ( 1 ) ;
2015-02-26 02:32:51 +01:00
String tName = LocaleController . getInstance ( ) . getTranslitString ( name ) ;
if ( name . equals ( tName ) ) {
tName = null ;
}
2014-10-31 20:02:29 +01:00
String username = null ;
int usernamePos = name . lastIndexOf ( " ;;; " ) ;
if ( usernamePos ! = - 1 ) {
username = name . substring ( usernamePos + 2 ) ;
}
int found = 0 ;
2015-02-01 19:51:02 +01:00
for ( String q : search ) {
2015-02-26 02:32:51 +01:00
if ( name . startsWith ( q ) | | name . contains ( " " + q ) | | tName ! = null & & ( tName . startsWith ( q ) | | tName . contains ( " " + q ) ) ) {
2015-02-01 19:51:02 +01:00
found = 1 ;
} else if ( username ! = null & & username . startsWith ( q ) ) {
found = 2 ;
}
2014-10-31 20:02:29 +01:00
2015-02-01 19:51:02 +01:00
if ( found ! = 0 ) {
ByteBufferDesc data = MessagesStorage . getInstance ( ) . getBuffersStorage ( ) . getFreeBuffer ( cursor . byteArrayLength ( 0 ) ) ;
ByteBufferDesc data2 = MessagesStorage . getInstance ( ) . getBuffersStorage ( ) . getFreeBuffer ( cursor . byteArrayLength ( 6 ) ) ;
if ( data ! = null & & cursor . byteBufferValue ( 0 , data . buffer ) ! = 0 & & cursor . byteBufferValue ( 6 , data2 . buffer ) ! = 0 ) {
TLRPC . EncryptedChat chat = ( TLRPC . EncryptedChat ) TLClassStore . Instance ( ) . TLdeserialize ( data , data . readInt32 ( ) ) ;
DialogSearchResult dialogSearchResult = dialogsResult . get ( ( long ) chat . id < < 32 ) ;
chat . user_id = cursor . intValue ( 2 ) ;
chat . a_or_b = cursor . byteArrayValue ( 3 ) ;
chat . auth_key = cursor . byteArrayValue ( 4 ) ;
chat . ttl = cursor . intValue ( 5 ) ;
chat . layer = cursor . intValue ( 8 ) ;
chat . seq_in = cursor . intValue ( 9 ) ;
chat . seq_out = cursor . intValue ( 10 ) ;
int use_count = cursor . intValue ( 11 ) ;
chat . key_use_count_in = ( short ) ( use_count > > 16 ) ;
chat . key_use_count_out = ( short ) ( use_count ) ;
chat . exchange_id = cursor . longValue ( 12 ) ;
chat . key_create_date = cursor . intValue ( 13 ) ;
chat . future_key_fingerprint = cursor . longValue ( 14 ) ;
chat . future_auth_key = cursor . byteArrayValue ( 15 ) ;
chat . key_hash = cursor . byteArrayValue ( 16 ) ;
TLRPC . User user = ( TLRPC . User ) TLClassStore . Instance ( ) . TLdeserialize ( data2 , data2 . readInt32 ( ) ) ;
if ( user . status ! = null ) {
user . status . expires = cursor . intValue ( 7 ) ;
}
if ( found = = 1 ) {
2015-04-09 20:00:14 +02:00
dialogSearchResult . name = AndroidUtilities . replaceTags ( " <c#ff00a60e> " + ContactsController . formatName ( user . first_name , user . last_name ) + " </c> " ) ;
2015-02-01 19:51:02 +01:00
} else {
dialogSearchResult . name = Utilities . generateSearchName ( " @ " + user . username , null , " @ " + q ) ;
}
dialogSearchResult . object = chat ;
encUsers . add ( user ) ;
resultCount + + ;
2014-10-31 20:02:29 +01:00
}
2015-02-01 19:51:02 +01:00
MessagesStorage . getInstance ( ) . getBuffersStorage ( ) . reuseFreeBuffer ( data ) ;
MessagesStorage . getInstance ( ) . getBuffersStorage ( ) . reuseFreeBuffer ( data2 ) ;
break ;
2014-10-31 20:02:29 +01:00
}
}
}
cursor . dispose ( ) ;
}
2015-01-02 23:15:07 +01:00
ArrayList < DialogSearchResult > searchResults = new ArrayList < > ( resultCount ) ;
2014-12-01 18:56:31 +01:00
for ( DialogSearchResult dialogSearchResult : dialogsResult . values ( ) ) {
if ( dialogSearchResult . object ! = null & & dialogSearchResult . name ! = null ) {
searchResults . add ( dialogSearchResult ) ;
}
}
Collections . sort ( searchResults , new Comparator < DialogSearchResult > ( ) {
@Override
public int compare ( DialogSearchResult lhs , DialogSearchResult rhs ) {
if ( lhs . date < rhs . date ) {
return 1 ;
} else if ( lhs . date > rhs . date ) {
return - 1 ;
}
return 0 ;
}
} ) ;
2015-01-02 23:15:07 +01:00
ArrayList < TLObject > resultArray = new ArrayList < > ( ) ;
ArrayList < CharSequence > resultArrayNames = new ArrayList < > ( ) ;
2014-12-01 18:56:31 +01:00
for ( DialogSearchResult dialogSearchResult : searchResults ) {
resultArray . add ( dialogSearchResult . object ) ;
resultArrayNames . add ( dialogSearchResult . name ) ;
}
cursor = MessagesStorage . getInstance ( ) . getDatabase ( ) . queryFinalized ( " SELECT u.data, u.status, u.name, u.uid FROM users as u INNER JOIN contacts as c ON u.uid = c.uid " ) ;
2014-10-31 20:02:29 +01:00
while ( cursor . next ( ) ) {
2014-12-01 18:56:31 +01:00
int uid = cursor . intValue ( 3 ) ;
2015-03-26 18:34:47 +01:00
if ( dialogsResult . containsKey ( ( long ) uid ) ) {
2014-12-01 18:56:31 +01:00
continue ;
}
String name = cursor . stringValue ( 2 ) ;
2015-02-26 02:32:51 +01:00
String tName = LocaleController . getInstance ( ) . getTranslitString ( name ) ;
if ( name . equals ( tName ) ) {
tName = null ;
}
2014-12-01 18:56:31 +01:00
String username = null ;
int usernamePos = name . lastIndexOf ( " ;;; " ) ;
if ( usernamePos ! = - 1 ) {
username = name . substring ( usernamePos + 3 ) ;
}
int found = 0 ;
2015-02-01 19:51:02 +01:00
for ( String q : search ) {
2015-02-26 02:32:51 +01:00
if ( name . startsWith ( q ) | | name . contains ( " " + q ) | | tName ! = null & & ( tName . startsWith ( q ) | | tName . contains ( " " + q ) ) ) {
2015-02-01 19:51:02 +01:00
found = 1 ;
} else if ( username ! = null & & username . startsWith ( q ) ) {
found = 2 ;
}
if ( found ! = 0 ) {
ByteBufferDesc data = MessagesStorage . getInstance ( ) . getBuffersStorage ( ) . getFreeBuffer ( cursor . byteArrayLength ( 0 ) ) ;
if ( data ! = null & & cursor . byteBufferValue ( 0 , data . buffer ) ! = 0 ) {
TLRPC . User user = ( TLRPC . User ) TLClassStore . Instance ( ) . TLdeserialize ( data , data . readInt32 ( ) ) ;
if ( user . id ! = UserConfig . getClientUserId ( ) ) {
if ( user . status ! = null ) {
user . status . expires = cursor . intValue ( 1 ) ;
}
if ( found = = 1 ) {
resultArrayNames . add ( Utilities . generateSearchName ( user . first_name , user . last_name , q ) ) ;
} else {
resultArrayNames . add ( Utilities . generateSearchName ( " @ " + user . username , null , " @ " + q ) ) ;
}
resultArray . add ( user ) ;
2014-12-01 18:56:31 +01:00
}
2014-10-31 20:02:29 +01:00
}
2015-02-01 19:51:02 +01:00
MessagesStorage . getInstance ( ) . getBuffersStorage ( ) . reuseFreeBuffer ( data ) ;
break ;
2014-10-31 20:02:29 +01:00
}
}
}
cursor . dispose ( ) ;
2014-12-01 18:56:31 +01:00
2014-11-21 01:14:44 +01:00
updateSearchResults ( resultArray , resultArrayNames , encUsers , searchId ) ;
2014-10-31 20:02:29 +01:00
} catch ( Exception e ) {
FileLog . e ( " tmessages " , e ) ;
}
}
} ) ;
}
2014-11-21 01:14:44 +01:00
private void updateSearchResults ( final ArrayList < TLObject > result , final ArrayList < CharSequence > names , final ArrayList < TLRPC . User > encUsers , final int searchId ) {
2014-11-06 22:34:47 +01:00
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
2014-10-31 20:02:29 +01:00
@Override
public void run ( ) {
2014-11-21 01:14:44 +01:00
if ( searchId ! = lastSearchId ) {
return ;
}
2014-10-31 20:02:29 +01:00
for ( TLObject obj : result ) {
if ( obj instanceof TLRPC . User ) {
TLRPC . User user = ( TLRPC . User ) obj ;
MessagesController . getInstance ( ) . putUser ( user , true ) ;
} else if ( obj instanceof TLRPC . Chat ) {
TLRPC . Chat chat = ( TLRPC . Chat ) obj ;
MessagesController . getInstance ( ) . putChat ( chat , true ) ;
} else if ( obj instanceof TLRPC . EncryptedChat ) {
TLRPC . EncryptedChat chat = ( TLRPC . EncryptedChat ) obj ;
MessagesController . getInstance ( ) . putEncryptedChat ( chat , true ) ;
}
}
for ( TLRPC . User user : encUsers ) {
MessagesController . getInstance ( ) . putUser ( user , true ) ;
}
searchResult = result ;
searchResultNames = names ;
notifyDataSetChanged ( ) ;
}
} ) ;
}
public String getLastSearchText ( ) {
2014-11-06 22:34:47 +01:00
return lastSearchText ;
2014-10-31 20:02:29 +01:00
}
public boolean isGlobalSearch ( int i ) {
2014-11-06 22:34:47 +01:00
return i > searchResult . size ( ) & & i < = globalSearch . size ( ) + searchResult . size ( ) ;
2014-10-31 20:02:29 +01:00
}
2015-03-26 18:34:47 +01:00
@Override
public void clearRecentHashtags ( ) {
super . clearRecentHashtags ( ) ;
searchResultHashtags . clear ( ) ;
notifyDataSetChanged ( ) ;
}
@Override
protected void setHashtags ( ArrayList < HashtagObject > arrayList , HashMap < String , HashtagObject > hashMap ) {
super . setHashtags ( arrayList , hashMap ) ;
for ( HashtagObject hashtagObject : arrayList ) {
searchResultHashtags . add ( hashtagObject . hashtag ) ;
}
if ( delegate ! = null ) {
delegate . searchStateChanged ( false ) ;
}
notifyDataSetChanged ( ) ;
}
2014-11-06 22:34:47 +01:00
public void searchDialogs ( final String query , final boolean serverOnly ) {
2014-11-19 02:23:46 +01:00
if ( query ! = null & & lastSearchText ! = null & & query . equals ( lastSearchText ) ) {
2014-10-31 20:02:29 +01:00
return ;
}
try {
if ( searchTimer ! = null ) {
searchTimer . cancel ( ) ;
}
} catch ( Exception e ) {
FileLog . e ( " tmessages " , e ) ;
}
if ( query = = null | | query . length ( ) = = 0 ) {
2015-03-26 18:34:47 +01:00
hashtagsLoadedFromDb = false ;
2014-11-06 22:34:47 +01:00
searchResult . clear ( ) ;
searchResultNames . clear ( ) ;
2015-03-26 18:34:47 +01:00
searchResultHashtags . clear ( ) ;
2015-03-19 00:09:45 +01:00
if ( needMessagesSearch ! = 2 ) {
queryServerSearch ( null ) ;
}
2014-11-06 22:34:47 +01:00
searchMessagesInternal ( null ) ;
2014-10-31 20:02:29 +01:00
notifyDataSetChanged ( ) ;
} else {
2015-03-26 18:34:47 +01:00
if ( query . startsWith ( " # " ) & & query . length ( ) = = 1 ) {
messagesSearchEndReached = true ;
if ( ! hashtagsLoadedFromDb ) {
loadRecentHashtags ( ) ;
if ( delegate ! = null ) {
delegate . searchStateChanged ( true ) ;
}
notifyDataSetChanged ( ) ;
return ;
}
2015-04-09 20:00:14 +02:00
searchResultMessages . clear ( ) ;
2015-03-26 18:34:47 +01:00
searchResultHashtags . clear ( ) ;
for ( HashtagObject hashtagObject : hashtags ) {
searchResultHashtags . add ( hashtagObject . hashtag ) ;
}
if ( delegate ! = null ) {
delegate . searchStateChanged ( false ) ;
}
notifyDataSetChanged ( ) ;
return ;
} else {
searchResultHashtags . clear ( ) ;
}
2014-11-21 01:14:44 +01:00
final int searchId = + + lastSearchId ;
2014-10-31 20:02:29 +01:00
searchTimer = new Timer ( ) ;
searchTimer . schedule ( new TimerTask ( ) {
@Override
public void run ( ) {
try {
searchTimer . cancel ( ) ;
searchTimer = null ;
} catch ( Exception e ) {
FileLog . e ( " tmessages " , e ) ;
}
2014-11-21 01:14:44 +01:00
searchDialogsInternal ( query , serverOnly , searchId ) ;
2014-11-06 22:34:47 +01:00
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
2015-03-19 00:09:45 +01:00
if ( needMessagesSearch ! = 2 ) {
queryServerSearch ( query ) ;
}
2014-11-06 22:34:47 +01:00
searchMessagesInternal ( query ) ;
}
} ) ;
2014-10-31 20:02:29 +01:00
}
} , 200 , 300 ) ;
}
}
@Override
public boolean areAllItemsEnabled ( ) {
return false ;
}
@Override
public boolean isEnabled ( int i ) {
2015-03-26 18:34:47 +01:00
if ( ! searchResultHashtags . isEmpty ( ) ) {
return i ! = 0 ;
}
int localCount = searchResult . size ( ) ;
int globalCount = globalSearch . isEmpty ( ) ? 0 : globalSearch . size ( ) + 1 ;
int messagesCount = searchResultMessages . isEmpty ( ) ? 0 : searchResultMessages . size ( ) + 1 ;
if ( i > = 0 & & i < localCount | | i > localCount & & i < globalCount + localCount ) {
return true ;
} else if ( i > globalCount + localCount & & i < globalCount + localCount + messagesCount ) {
return true ;
} else if ( messagesCount ! = 0 & & i = = globalCount + localCount + messagesCount ) {
return true ;
}
return false ;
2014-10-31 20:02:29 +01:00
}
@Override
public int getCount ( ) {
2015-03-26 18:34:47 +01:00
if ( ! searchResultHashtags . isEmpty ( ) ) {
return searchResultHashtags . size ( ) + 1 ;
}
2014-11-06 22:34:47 +01:00
int count = searchResult . size ( ) ;
int globalCount = globalSearch . size ( ) ;
int messagesCount = searchResultMessages . size ( ) ;
if ( globalCount ! = 0 ) {
count + = globalCount + 1 ;
}
if ( messagesCount ! = 0 ) {
2014-11-19 02:23:46 +01:00
count + = messagesCount + 1 + ( messagesSearchEndReached ? 0 : 1 ) ;
2014-10-31 20:02:29 +01:00
}
2014-11-06 22:34:47 +01:00
return count ;
2014-10-31 20:02:29 +01:00
}
@Override
public Object getItem ( int i ) {
2015-03-26 18:34:47 +01:00
if ( ! searchResultHashtags . isEmpty ( ) ) {
return searchResultHashtags . get ( i - 1 ) ;
}
2014-11-06 22:34:47 +01:00
int localCount = searchResult . size ( ) ;
int globalCount = globalSearch . isEmpty ( ) ? 0 : globalSearch . size ( ) + 1 ;
int messagesCount = searchResultMessages . isEmpty ( ) ? 0 : searchResultMessages . size ( ) + 1 ;
if ( i > = 0 & & i < localCount ) {
return searchResult . get ( i ) ;
} else if ( i > localCount & & i < globalCount + localCount ) {
return globalSearch . get ( i - localCount - 1 ) ;
} else if ( i > globalCount + localCount & & i < globalCount + localCount + messagesCount ) {
return searchResultMessages . get ( i - localCount - globalCount - 1 ) ;
2014-10-31 20:02:29 +01:00
}
return null ;
}
@Override
public long getItemId ( int i ) {
return i ;
}
@Override
public boolean hasStableIds ( ) {
return true ;
}
@Override
public View getView ( int i , View view , ViewGroup viewGroup ) {
int type = getItemViewType ( i ) ;
if ( type = = 1 ) {
if ( view = = null ) {
2014-11-10 12:05:22 +01:00
view = new GreySectionCell ( mContext ) ;
2014-10-31 20:02:29 +01:00
}
2015-03-26 18:34:47 +01:00
if ( ! searchResultHashtags . isEmpty ( ) ) {
( ( GreySectionCell ) view ) . setText ( LocaleController . getString ( " Hashtags " , R . string . Hashtags ) . toUpperCase ( ) ) ;
} else if ( ! globalSearch . isEmpty ( ) & & i = = searchResult . size ( ) ) {
2014-11-10 12:05:22 +01:00
( ( GreySectionCell ) view ) . setText ( LocaleController . getString ( " GlobalSearch " , R . string . GlobalSearch ) ) ;
2014-11-06 22:34:47 +01:00
} else {
2014-11-10 12:05:22 +01:00
( ( GreySectionCell ) view ) . setText ( LocaleController . getString ( " SearchMessages " , R . string . SearchMessages ) ) ;
2014-11-06 22:34:47 +01:00
}
2014-10-31 20:02:29 +01:00
} else if ( type = = 0 ) {
if ( view = = null ) {
2014-11-10 12:05:22 +01:00
view = new ProfileSearchCell ( mContext ) ;
2014-10-31 20:02:29 +01:00
}
TLRPC . User user = null ;
TLRPC . Chat chat = null ;
TLRPC . EncryptedChat encryptedChat = null ;
2014-11-06 22:34:47 +01:00
int localCount = searchResult . size ( ) ;
2014-11-10 12:05:22 +01:00
int globalCount = globalSearch . isEmpty ( ) ? 0 : globalSearch . size ( ) + 1 ;
2014-11-06 22:34:47 +01:00
2014-11-10 12:05:22 +01:00
( ( ProfileSearchCell ) view ) . useSeparator = ( i ! = getCount ( ) - 1 & & i ! = localCount - 1 & & i ! = localCount + globalCount - 1 ) ;
2014-10-31 20:02:29 +01:00
Object obj = getItem ( i ) ;
if ( obj instanceof TLRPC . User ) {
2015-04-09 20:00:14 +02:00
/ * user = MessagesController . getInstance ( ) . getUser ( ( ( TLRPC . User ) obj ) . id ) ;
2014-10-31 20:02:29 +01:00
if ( user = = null ) {
user = ( TLRPC . User ) obj ;
2015-04-09 20:00:14 +02:00
} * /
user = ( TLRPC . User ) obj ;
2014-10-31 20:02:29 +01:00
} else if ( obj instanceof TLRPC . Chat ) {
chat = MessagesController . getInstance ( ) . getChat ( ( ( TLRPC . Chat ) obj ) . id ) ;
} else if ( obj instanceof TLRPC . EncryptedChat ) {
encryptedChat = MessagesController . getInstance ( ) . getEncryptedChat ( ( ( TLRPC . EncryptedChat ) obj ) . id ) ;
user = MessagesController . getInstance ( ) . getUser ( encryptedChat . user_id ) ;
}
CharSequence username = null ;
CharSequence name = null ;
if ( i < searchResult . size ( ) ) {
name = searchResultNames . get ( i ) ;
if ( name ! = null & & user ! = null & & user . username ! = null & & user . username . length ( ) > 0 ) {
if ( name . toString ( ) . startsWith ( " @ " + user . username ) ) {
username = name ;
name = null ;
}
}
} else if ( i > searchResult . size ( ) & & user ! = null & & user . username ! = null ) {
2015-01-02 23:15:07 +01:00
String foundUserName = lastFoundUsername ;
if ( foundUserName . startsWith ( " @ " ) ) {
foundUserName = foundUserName . substring ( 1 ) ;
}
2014-10-31 20:02:29 +01:00
try {
2015-04-09 20:00:14 +02:00
username = AndroidUtilities . replaceTags ( String . format ( " <c#ff4d83b3>@%s</c>%s " , user . username . substring ( 0 , foundUserName . length ( ) ) , user . username . substring ( foundUserName . length ( ) ) ) ) ;
2014-10-31 20:02:29 +01:00
} catch ( Exception e ) {
username = user . username ;
FileLog . e ( " tmessages " , e ) ;
}
}
2014-11-10 12:05:22 +01:00
( ( ProfileSearchCell ) view ) . setData ( user , chat , encryptedChat , name , username ) ;
2014-10-31 20:02:29 +01:00
} else if ( type = = 2 ) {
if ( view = = null ) {
view = new DialogCell ( mContext ) ;
}
( ( DialogCell ) view ) . useSeparator = ( i ! = getCount ( ) - 1 ) ;
2014-11-06 22:34:47 +01:00
MessageObject messageObject = ( MessageObject ) getItem ( i ) ;
2015-02-26 02:32:51 +01:00
( ( DialogCell ) view ) . setDialog ( messageObject . getDialogId ( ) , messageObject , messageObject . messageOwner . date ) ;
2014-11-19 02:23:46 +01:00
} else if ( type = = 3 ) {
if ( view = = null ) {
view = new LoadingCell ( mContext ) ;
}
2015-03-26 18:34:47 +01:00
} else if ( type = = 4 ) {
if ( view = = null ) {
view = new HashtagSearchCell ( mContext ) ;
}
( ( HashtagSearchCell ) view ) . setText ( searchResultHashtags . get ( i - 1 ) ) ;
( ( HashtagSearchCell ) view ) . setNeedDivider ( i ! = searchResultHashtags . size ( ) ) ;
2014-10-31 20:02:29 +01:00
}
return view ;
}
@Override
public int getItemViewType ( int i ) {
2015-03-26 18:34:47 +01:00
if ( ! searchResultHashtags . isEmpty ( ) ) {
return i = = 0 ? 1 : 4 ;
}
2014-11-06 22:34:47 +01:00
int localCount = searchResult . size ( ) ;
int globalCount = globalSearch . isEmpty ( ) ? 0 : globalSearch . size ( ) + 1 ;
int messagesCount = searchResultMessages . isEmpty ( ) ? 0 : searchResultMessages . size ( ) + 1 ;
if ( i > = 0 & & i < localCount | | i > localCount & & i < globalCount + localCount ) {
2014-10-31 20:02:29 +01:00
return 0 ;
2014-11-06 22:34:47 +01:00
} else if ( i > globalCount + localCount & & i < globalCount + localCount + messagesCount ) {
return 2 ;
2014-11-19 02:23:46 +01:00
} else if ( messagesCount ! = 0 & & i = = globalCount + localCount + messagesCount ) {
return 3 ;
2014-10-31 20:02:29 +01:00
}
2014-11-06 22:34:47 +01:00
return 1 ;
2014-10-31 20:02:29 +01:00
}
@Override
public int getViewTypeCount ( ) {
2015-03-26 18:34:47 +01:00
return 5 ;
2014-10-31 20:02:29 +01:00
}
@Override
public boolean isEmpty ( ) {
2015-03-26 18:34:47 +01:00
return searchResult . isEmpty ( ) & & globalSearch . isEmpty ( ) & & searchResultMessages . isEmpty ( ) & & searchResultHashtags . isEmpty ( ) ;
2014-10-31 20:02:29 +01:00
}
}