Update search query results when messages disappear.

Previously, if a message disappeared while looking at it in the search
results, it'd still stick around. Now they'll disappear from the results
in real-time.
This commit is contained in:
Greyson Parrelli 2018-06-15 09:20:08 -07:00
parent febf3c249e
commit 3563efc7de
4 changed files with 63 additions and 10 deletions

View File

@ -1,6 +1,8 @@
package org.thoughtcrime.securesms.database;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.database.MatrixCursor;
import android.support.annotation.NonNull;
@ -22,8 +24,6 @@ import java.util.ListIterator;
*/
public class CursorList<T> implements List<T>, Closeable {
private static final Cursor EMPTY_CURSOR = new MatrixCursor(new String[] { "a" }, 0);
private final Cursor cursor;
private final ModelBuilder<T> modelBuilder;
@ -34,7 +34,11 @@ public class CursorList<T> implements List<T>, Closeable {
public static <T> CursorList<T> emptyList() {
//noinspection ConstantConditions,unchecked
return (CursorList<T>) new CursorList(EMPTY_CURSOR, null);
return (CursorList<T>) new CursorList(emptyCursor(), null);
}
private static Cursor emptyCursor() {
return new MatrixCursor(new String[] { "a" }, 0);
}
@Override
@ -183,6 +187,14 @@ public class CursorList<T> implements List<T>, Closeable {
}
}
public void registerContentObserver(@NonNull ContentObserver observer) {
cursor.registerContentObserver(observer);
}
public void unregisterContentObserver(@NonNull ContentObserver observer) {
cursor.unregisterContentObserver(observer);
}
public interface ModelBuilder<T> {
T build(@NonNull Cursor cursor);
}

View File

@ -83,7 +83,9 @@ public class SearchDatabase extends Database {
String prefixQuery = query + '*';
return db.rawQuery(MESSAGES_QUERY, new String[] { prefixQuery, prefixQuery });
Cursor cursor = db.rawQuery(MESSAGES_QUERY, new String[] { prefixQuery, prefixQuery });
setNotifyConverationListListeners(cursor);
return cursor;
}
}

View File

@ -4,7 +4,10 @@ import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.ViewModel;
import android.arch.lifecycle.ViewModelProvider;
import android.database.ContentObserver;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import org.thoughtcrime.securesms.search.model.SearchResult;
import org.thoughtcrime.securesms.util.Debouncer;
@ -19,16 +22,25 @@ import org.thoughtcrime.securesms.util.Debouncer;
*/
class SearchViewModel extends ViewModel {
private final ClosingLiveData searchResult;
private final ObservingLiveData searchResult;
private final SearchRepository searchRepository;
private final Debouncer debouncer;
private String lastQuery;
SearchViewModel(@NonNull SearchRepository searchRepository) {
this.searchResult = new ClosingLiveData();
this.searchResult = new ObservingLiveData();
this.searchRepository = searchRepository;
this.debouncer = new Debouncer(500);
searchResult.registerContentObserver(new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
if (!TextUtils.isEmpty(getLastQuery())) {
searchRepository.query(getLastQuery(), searchResult::postValue);
}
}
});
}
LiveData<SearchResult> getSearchResult() {
@ -54,23 +66,36 @@ class SearchViewModel extends ViewModel {
/**
* Ensures that the previous {@link SearchResult} is always closed whenever we set a new one.
*/
private static class ClosingLiveData extends MutableLiveData<SearchResult> {
private static class ObservingLiveData extends MutableLiveData<SearchResult> {
private ContentObserver observer;
@Override
public void setValue(SearchResult value) {
SearchResult previous = getValue();
if (previous != null) {
previous.unregisterContentObserver(observer);
previous.close();
}
value.registerContentObserver(observer);
super.setValue(value);
}
public void close() {
void close() {
SearchResult value = getValue();
if (value != null) {
value.unregisterContentObserver(observer);
value.close();
}
}
void registerContentObserver(@NonNull ContentObserver observer) {
this.observer = observer;
}
}
public static class Factory extends ViewModelProvider.NewInstanceFactory {

View File

@ -1,5 +1,7 @@
package org.thoughtcrime.securesms.search.model;
import android.database.ContentObserver;
import android.database.DataSetObserver;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.database.CursorList;
@ -56,6 +58,18 @@ public class SearchResult {
return size() == 0;
}
public void registerContentObserver(@NonNull ContentObserver observer) {
contacts.registerContentObserver(observer);
conversations.registerContentObserver(observer);
messages.registerContentObserver(observer);
}
public void unregisterContentObserver(@NonNull ContentObserver observer) {
contacts.unregisterContentObserver(observer);
conversations.unregisterContentObserver(observer);
messages.unregisterContentObserver(observer);
}
public void close() {
contacts.close();
conversations.close();