mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-23 18:15:22 +00:00
Fixes #1346 - properly this time!
This commit is contained in:
parent
d65705c845
commit
04fb296787
@ -12,6 +12,7 @@ import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.SpannableString
|
||||
import android.widget.Toast
|
||||
|
||||
import androidx.activity.viewModels
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.isVisible
|
||||
@ -21,20 +22,25 @@ import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
import network.loki.messenger.R
|
||||
import network.loki.messenger.databinding.ActivityHomeBinding
|
||||
import network.loki.messenger.databinding.ViewMessageRequestBannerBinding
|
||||
import network.loki.messenger.libsession_util.ConfigBase
|
||||
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.messaging.jobs.JobQueue
|
||||
import org.session.libsession.messaging.sending_receiving.MessageSender
|
||||
@ -47,6 +53,7 @@ import org.session.libsession.utilities.recipients.Recipient
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.session.libsignal.utilities.ThreadUtils
|
||||
import org.session.libsignal.utilities.toHexString
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||
import org.thoughtcrime.securesms.conversation.start.NewConversationFragment
|
||||
@ -82,8 +89,10 @@ import org.thoughtcrime.securesms.util.disableClipping
|
||||
import org.thoughtcrime.securesms.util.push
|
||||
import org.thoughtcrime.securesms.util.show
|
||||
import org.thoughtcrime.securesms.util.themeState
|
||||
|
||||
import java.io.IOException
|
||||
import java.util.Locale
|
||||
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
|
@ -2,7 +2,9 @@ package org.thoughtcrime.securesms.home.search
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.delay
|
||||
@ -13,11 +15,14 @@ import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.mapLatest
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.plus
|
||||
import org.session.libsignal.utilities.Log
|
||||
|
||||
import org.session.libsignal.utilities.SettableFuture
|
||||
|
||||
import org.thoughtcrime.securesms.search.SearchRepository
|
||||
import org.thoughtcrime.securesms.search.model.SearchResult
|
||||
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
@ -25,8 +30,7 @@ class GlobalSearchViewModel @Inject constructor(private val searchRepository: Se
|
||||
|
||||
private val executor = viewModelScope + SupervisorJob()
|
||||
|
||||
private val _result: MutableStateFlow<GlobalSearchResult> =
|
||||
MutableStateFlow(GlobalSearchResult.EMPTY)
|
||||
private val _result: MutableStateFlow<GlobalSearchResult> = MutableStateFlow(GlobalSearchResult.EMPTY)
|
||||
|
||||
val result: StateFlow<GlobalSearchResult> = _result
|
||||
|
||||
@ -34,7 +38,6 @@ class GlobalSearchViewModel @Inject constructor(private val searchRepository: Se
|
||||
|
||||
private var settableFuture = SettableFuture<SearchResult>()
|
||||
|
||||
|
||||
fun postQuery(charSequence: CharSequence?) {
|
||||
charSequence ?: return
|
||||
_queryText.value = charSequence
|
||||
@ -45,7 +48,7 @@ class GlobalSearchViewModel @Inject constructor(private val searchRepository: Se
|
||||
_queryText
|
||||
.buffer(onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
||||
.mapLatest { query ->
|
||||
// Minimum search term is 2 characters - for a single char we do nothing
|
||||
// Minimum search term is 2 characters
|
||||
if (query.trim().length < 2) {
|
||||
SearchResult.EMPTY
|
||||
} else {
|
||||
@ -55,9 +58,7 @@ class GlobalSearchViewModel @Inject constructor(private val searchRepository: Se
|
||||
delay(300)
|
||||
|
||||
// If we already have a search running then stop it
|
||||
if (!settableFuture.isDone) {
|
||||
Log.w("[ACL]", "Cancelling settable future..")
|
||||
settableFuture.cancel(true); }
|
||||
if (!settableFuture.isDone) { settableFuture.cancel(true) }
|
||||
|
||||
settableFuture = SettableFuture<SearchResult>()
|
||||
searchRepository.query(query.toString(), settableFuture::set)
|
||||
|
@ -4,7 +4,6 @@ import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.DatabaseUtils;
|
||||
import android.database.MergeCursor;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
@ -36,28 +35,18 @@ import java.util.concurrent.Executor;
|
||||
|
||||
import kotlin.Pair;
|
||||
|
||||
/**
|
||||
* Manages data retrieval for search.
|
||||
*/
|
||||
// Class to manage data retrieval for search
|
||||
public class SearchRepository {
|
||||
|
||||
private static final String TAG = SearchRepository.class.getSimpleName();
|
||||
|
||||
private static final Set<Character> BANNED_CHARACTERS = new HashSet<>();
|
||||
static {
|
||||
// Several ranges of invalid ASCII characters
|
||||
for (int i = 33; i <= 47; i++) {
|
||||
BANNED_CHARACTERS.add((char) i);
|
||||
}
|
||||
for (int i = 58; i <= 64; i++) {
|
||||
BANNED_CHARACTERS.add((char) i);
|
||||
}
|
||||
for (int i = 91; i <= 96; i++) {
|
||||
BANNED_CHARACTERS.add((char) i);
|
||||
}
|
||||
for (int i = 123; i <= 126; i++) {
|
||||
BANNED_CHARACTERS.add((char) i);
|
||||
}
|
||||
// Construct a list containing several ranges of invalid ASCII characters
|
||||
// See: https://www.ascii-code.com/
|
||||
for (int i = 33; i <= 47; i++) { BANNED_CHARACTERS.add((char) i); } // !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /
|
||||
for (int i = 58; i <= 64; i++) { BANNED_CHARACTERS.add((char) i); } // :, ;, <, =, >, ?, @
|
||||
for (int i = 91; i <= 96; i++) { BANNED_CHARACTERS.add((char) i); } // [, \, ], ^, _, `
|
||||
for (int i = 123; i <= 126; i++) { BANNED_CHARACTERS.add((char) i); } // {, |, }, ~
|
||||
}
|
||||
|
||||
private final Context context;
|
||||
@ -86,54 +75,25 @@ public class SearchRepository {
|
||||
}
|
||||
|
||||
public void query(@NonNull String query, @NonNull Callback<SearchResult> callback) {
|
||||
|
||||
Log.w("[ACL]", "Hit SearchRepository.query - query string is: \"" + query + "\"");
|
||||
|
||||
String cleanQuery = sanitizeQuery(query).trim();
|
||||
Log.w("[ACL]", "When sanitized and trimmed this is: \"" + cleanQuery + "\"");
|
||||
|
||||
// If the sanitized search is empty or is less than 2 chars then abort
|
||||
String cleanQuery = sanitizeQuery(query).trim();
|
||||
if (cleanQuery.isEmpty() || cleanQuery.length() < 2) {
|
||||
Log.w("[ACL]", "Trimmed query is empty or less than 2 chars so returning empty SearchResult");
|
||||
callback.onResult(SearchResult.EMPTY);
|
||||
return;
|
||||
}
|
||||
|
||||
executor.execute(() -> {
|
||||
Stopwatch timer = new Stopwatch("FtsQuery");
|
||||
|
||||
// ACL
|
||||
//String cleanQuery = sanitizeQuery(query).trim();
|
||||
|
||||
|
||||
/*
|
||||
if (cleanQuery.isEmpty())
|
||||
{
|
||||
Log.w("[ACL]", "Aborting empty search query.");
|
||||
Log.d(TAG, "Aborting empty search query.");
|
||||
timer.stop(TAG);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
Log.w("[ACL]", "Clean query is non-empty and is: \"" + cleanQuery + "\"");
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
timer.split("clean");
|
||||
|
||||
Log.w("[ACL]", "About to query contacts.");
|
||||
Pair<CursorList<Contact>, List<String>> contacts = queryContacts(cleanQuery);
|
||||
timer.split("contacts");
|
||||
timer.split("Contacts");
|
||||
|
||||
|
||||
Log.w("[ACL]", "About to query conversations.");
|
||||
CursorList<GroupRecord> conversations = queryConversations(cleanQuery, contacts.getSecond());
|
||||
timer.split("conversations");
|
||||
timer.split("Conversations");
|
||||
|
||||
Log.w("[ACL]", "About to query messages.");
|
||||
CursorList<MessageResult> messages = queryMessages(cleanQuery);
|
||||
timer.split("messages");
|
||||
timer.split("Messages");
|
||||
|
||||
timer.stop(TAG);
|
||||
|
||||
@ -182,11 +142,10 @@ public class SearchRepository {
|
||||
MergeCursor merged = new MergeCursor(new Cursor[]{addressThreads, individualRecipients});
|
||||
|
||||
return new Pair<>(new CursorList<>(merged, new ContactModelBuilder(contactDatabase, threadDatabase)), contactStrings);
|
||||
|
||||
}
|
||||
|
||||
private CursorList<GroupRecord> queryConversations(@NonNull String query, List<String> matchingAddresses) {
|
||||
List<String> numbers = contactAccessor.getNumbersForThreadSearchFilter(context, query);
|
||||
List<String> numbers = contactAccessor.getNumbersForThreadSearchFilter(context, query);
|
||||
String localUserNumber = TextSecurePreferences.getLocalNumber(context);
|
||||
if (localUserNumber != null) {
|
||||
matchingAddresses.remove(localUserNumber);
|
||||
@ -270,9 +229,7 @@ public class SearchRepository {
|
||||
|
||||
private final Context context;
|
||||
|
||||
RecipientModelBuilder(@NonNull Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
RecipientModelBuilder(@NonNull Context context) { this.context = context; }
|
||||
|
||||
@Override
|
||||
public Recipient build(@NonNull Cursor cursor) {
|
||||
@ -315,9 +272,7 @@ public class SearchRepository {
|
||||
|
||||
private final Context context;
|
||||
|
||||
MessageModelBuilder(@NonNull Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
MessageModelBuilder(@NonNull Context context) { this.context = context; }
|
||||
|
||||
@Override
|
||||
public MessageResult build(@NonNull Cursor cursor) {
|
||||
|
@ -39,13 +39,9 @@ public class Stopwatch {
|
||||
out.append(splits.get(i).time - splits.get(i - 1).time);
|
||||
out.append("ms ");
|
||||
}
|
||||
|
||||
out.append("total: ").append(splits.get(splits.size() - 1).time - startTime).append("ms.");
|
||||
}
|
||||
|
||||
Log.d(tag, out.toString());
|
||||
|
||||
Log.w("[ACL]", out.toString());
|
||||
}
|
||||
|
||||
private static class Split {
|
||||
|
Loading…
Reference in New Issue
Block a user