Show mention picker immediately after @ entered.
parent
d563de4207
commit
1634d7d531
|
@ -102,7 +102,7 @@ public class ComposeText extends EmojiEditText {
|
|||
if (selectionStart == selectionEnd) {
|
||||
doAfterCursorChange(getText());
|
||||
} else {
|
||||
updateQuery("");
|
||||
updateQuery(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,7 +284,7 @@ public class ComposeText extends EmojiEditText {
|
|||
if (enoughToFilter(text)) {
|
||||
performFiltering(text);
|
||||
} else {
|
||||
updateQuery("");
|
||||
updateQuery(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -292,10 +292,10 @@ public class ComposeText extends EmojiEditText {
|
|||
int end = getSelectionEnd();
|
||||
int start = findQueryStart(text, end);
|
||||
CharSequence query = text.subSequence(start, end);
|
||||
updateQuery(query);
|
||||
updateQuery(query.toString());
|
||||
}
|
||||
|
||||
private void updateQuery(@NonNull CharSequence query) {
|
||||
private void updateQuery(@Nullable String query) {
|
||||
if (mentionQueryChangedListener != null) {
|
||||
mentionQueryChangedListener.onQueryChanged(query);
|
||||
}
|
||||
|
@ -306,7 +306,7 @@ public class ComposeText extends EmojiEditText {
|
|||
if (end < 0) {
|
||||
return false;
|
||||
}
|
||||
return end - findQueryStart(text, end) >= 1;
|
||||
return findQueryStart(text, end) != -1;
|
||||
}
|
||||
|
||||
public void replaceTextWithMention(@NonNull String displayName, @NonNull RecipientId recipientId) {
|
||||
|
@ -340,7 +340,7 @@ public class ComposeText extends EmojiEditText {
|
|||
|
||||
private int findQueryStart(@NonNull CharSequence text, int inputCursorPosition) {
|
||||
if (inputCursorPosition == 0) {
|
||||
return inputCursorPosition;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int delimiterSearchIndex = inputCursorPosition - 1;
|
||||
|
@ -351,7 +351,7 @@ public class ComposeText extends EmojiEditText {
|
|||
if (delimiterSearchIndex >= 0 && text.charAt(delimiterSearchIndex) == MENTION_STARTER) {
|
||||
return delimiterSearchIndex + 1;
|
||||
}
|
||||
return inputCursorPosition;
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static class CommitContentListener implements InputConnectionCompat.OnCommitContentListener {
|
||||
|
@ -391,6 +391,6 @@ public class ComposeText extends EmojiEditText {
|
|||
}
|
||||
|
||||
public interface MentionQueryChangedListener {
|
||||
void onQueryChanged(CharSequence query);
|
||||
void onQueryChanged(@Nullable String query);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Context;
|
|||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
|
@ -26,8 +27,8 @@ final class MentionsPickerRepository {
|
|||
}
|
||||
|
||||
@WorkerThread
|
||||
@NonNull List<Recipient> search(MentionQuery mentionQuery) {
|
||||
if (TextUtils.isEmpty(mentionQuery.query)) {
|
||||
@NonNull List<Recipient> search(@NonNull MentionQuery mentionQuery) {
|
||||
if (mentionQuery.query == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
@ -40,10 +41,10 @@ final class MentionsPickerRepository {
|
|||
}
|
||||
|
||||
static class MentionQuery {
|
||||
private final String query;
|
||||
private final List<GroupMemberEntry.FullMember> members;
|
||||
@Nullable private final String query;
|
||||
@NonNull private final List<GroupMemberEntry.FullMember> members;
|
||||
|
||||
MentionQuery(@NonNull String query, @NonNull List<GroupMemberEntry.FullMember> members) {
|
||||
MentionQuery(@Nullable String query, @NonNull List<GroupMemberEntry.FullMember> members) {
|
||||
this.query = query;
|
||||
this.members = members;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.thoughtcrime.securesms.conversation.ui.mentions;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.Transformations;
|
||||
|
@ -20,22 +21,23 @@ import org.thoughtcrime.securesms.util.SingleLiveEvent;
|
|||
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MentionsPickerViewModel extends ViewModel {
|
||||
|
||||
private final SingleLiveEvent<Recipient> selectedRecipient;
|
||||
private final LiveData<List<MappingModel<?>>> mentionList;
|
||||
private final MutableLiveData<LiveGroup> group;
|
||||
private final MutableLiveData<String> liveQuery;
|
||||
private final MutableLiveData<Query> liveQuery;
|
||||
|
||||
MentionsPickerViewModel(@NonNull MentionsPickerRepository mentionsPickerRepository) {
|
||||
group = new MutableLiveData<>();
|
||||
liveQuery = new MutableLiveData<>();
|
||||
liveQuery = new MutableLiveData<>(Query.NONE);
|
||||
selectedRecipient = new SingleLiveEvent<>();
|
||||
|
||||
LiveData<List<FullMember>> fullMembers = Transformations.distinctUntilChanged(Transformations.switchMap(group, LiveGroup::getFullMembers));
|
||||
LiveData<String> query = Transformations.distinctUntilChanged(liveQuery);
|
||||
LiveData<MentionQuery> mentionQuery = LiveDataUtil.combineLatest(query, fullMembers, MentionQuery::new);
|
||||
LiveData<Query> query = Transformations.distinctUntilChanged(liveQuery);
|
||||
LiveData<MentionQuery> mentionQuery = LiveDataUtil.combineLatest(query, fullMembers, (q, m) -> new MentionQuery(q.query, m));
|
||||
|
||||
mentionList = LiveDataUtil.mapAsync(mentionQuery, q -> Stream.of(mentionsPickerRepository.search(q)).<MappingModel<?>>map(MentionViewState::new).toList());
|
||||
}
|
||||
|
@ -52,8 +54,8 @@ public class MentionsPickerViewModel extends ViewModel {
|
|||
return selectedRecipient;
|
||||
}
|
||||
|
||||
public void onQueryChange(@NonNull CharSequence query) {
|
||||
liveQuery.setValue(query.toString());
|
||||
public void onQueryChange(@Nullable String query) {
|
||||
liveQuery.setValue(query == null ? Query.NONE : new Query(query));
|
||||
}
|
||||
|
||||
public void onRecipientChange(@NonNull Recipient recipient) {
|
||||
|
@ -64,6 +66,39 @@ public class MentionsPickerViewModel extends ViewModel {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a nullable query string so it can be properly propagated through
|
||||
* {@link LiveDataUtil#combineLatest(LiveData, LiveData, LiveDataUtil.Combine)}.
|
||||
*/
|
||||
private static class Query {
|
||||
static final Query NONE = new Query(null);
|
||||
|
||||
@Nullable private final String query;
|
||||
|
||||
Query(@Nullable String query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (object == null || getClass() != object.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Query other = (Query) object;
|
||||
return Objects.equals(query, other.query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(query);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Factory implements ViewModelProvider.Factory {
|
||||
@Override
|
||||
public @NonNull <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
|
||||
|
|
|
@ -1938,10 +1938,6 @@ public class RecipientDatabase extends Database {
|
|||
}
|
||||
|
||||
public @NonNull List<Recipient> queryRecipientsForMentions(@NonNull String query, @Nullable List<RecipientId> recipientIds) {
|
||||
if (TextUtils.isEmpty(query)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
query = buildCaseInsensitiveGlobPattern(query);
|
||||
|
||||
String ids = null;
|
||||
|
|
Loading…
Reference in New Issue