Fixes #1346 - properly this time!

This commit is contained in:
Al Lansley 2024-04-04 11:27:47 +11:00
parent d65705c845
commit 04fb296787
4 changed files with 32 additions and 71 deletions

View File

@ -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

View File

@ -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)

View File

@ -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,7 +142,6 @@ 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) {
@ -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) {

View File

@ -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 {