Show user selection view dynamically

This commit is contained in:
Niels Andriesse 2019-10-10 14:44:08 +11:00
parent 9207e479a6
commit 25f1405512
3 changed files with 87 additions and 38 deletions

View File

@ -3,5 +3,5 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/userSelectionView" android:id="@+id/userSelectionView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="200dp" android:layout_height="0dp"
android:paddingTop="6dp" /> android:paddingTop="6dp" />

View File

@ -244,6 +244,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import network.loki.messenger.R; import network.loki.messenger.R;
import nl.komponents.kovenant.combine.Tuple2;
import static org.thoughtcrime.securesms.TransportOption.Type; import static org.thoughtcrime.securesms.TransportOption.Type;
import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord; import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
@ -296,23 +297,24 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private static final int SMS_DEFAULT = 11; private static final int SMS_DEFAULT = 11;
private static final int MEDIA_SENDER = 12; private static final int MEDIA_SENDER = 12;
private GlideRequests glideRequests; private GlideRequests glideRequests;
protected ComposeText composeText; protected ComposeText composeText;
private AnimatingToggle buttonToggle; private AnimatingToggle buttonToggle;
private SendButton sendButton; private SendButton sendButton;
private ImageButton attachButton; private ImageButton attachButton;
protected ConversationTitleView titleView; protected ConversationTitleView titleView;
private TextView charactersLeft; private TextView charactersLeft;
private ConversationFragment fragment; private ConversationFragment fragment;
private Button unblockButton; private Button unblockButton;
private Button makeDefaultSmsButton; private Button makeDefaultSmsButton;
private Button registerButton; private Button registerButton;
private InputAwareLayout container; private InputAwareLayout container;
private View composePanel; private View composePanel;
protected Stub<ReminderView> reminderView; protected Stub<ReminderView> reminderView;
private Stub<UnverifiedBannerView> unverifiedBannerView; private Stub<UnverifiedBannerView> unverifiedBannerView;
private Stub<GroupShareProfileView> groupShareProfileView; private Stub<GroupShareProfileView> groupShareProfileView;
private TypingStatusTextWatcher typingTextWatcher; private TypingStatusTextWatcher typingTextWatcher;
private MentionTextWatcher mentionTextWatcher;
private ConversationSearchBottomBar searchNav; private ConversationSearchBottomBar searchNav;
private MenuItem searchViewItem; private MenuItem searchViewItem;
@ -342,6 +344,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private final DynamicNoActionBarTheme dynamicTheme = new DynamicNoActionBarTheme(); private final DynamicNoActionBarTheme dynamicTheme = new DynamicNoActionBarTheme();
private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
private UserSelectionView userSelectionView;
private int mentionStartIndex = -1;
@Override @Override
protected void onPreCreate() { protected void onPreCreate() {
@ -393,16 +397,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
composeText.addTextChangedListener(typingTextWatcher); composeText.addTextChangedListener(typingTextWatcher);
} }
composeText.setSelection(composeText.length(), composeText.length()); composeText.setSelection(composeText.length(), composeText.length());
composeText.addTextChangedListener(mentionTextWatcher);
} }
}); });
} }
}); });
LokiAPIUtilities.INSTANCE.populateUserIDCacheIfNeeded(threadId, this); LokiAPIUtilities.INSTANCE.populateUserIDCacheIfNeeded(threadId, this);
UserSelectionView userSelectionView = findViewById(R.id.userSelectionView);
LokiUserDatabase userDatabase = DatabaseFactory.getLokiUserDatabase(this);
userSelectionView.setHasGroupContext(true);
userSelectionView.setUsers(LokiAPI.Companion.getUserIDs("", threadId, userDatabase));
if (this.recipient.isGroupRecipient()) { if (this.recipient.isGroupRecipient()) {
if (this.recipient.getName().equals("Loki Public Chat")) { if (this.recipient.getName().equals("Loki Public Chat")) {
@ -1562,6 +1563,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
inlineAttachmentToggle = ViewUtil.findById(this, R.id.inline_attachment_container); inlineAttachmentToggle = ViewUtil.findById(this, R.id.inline_attachment_container);
inputPanel = ViewUtil.findById(this, R.id.bottom_panel); inputPanel = ViewUtil.findById(this, R.id.bottom_panel);
searchNav = ViewUtil.findById(this, R.id.conversation_search_nav); searchNav = ViewUtil.findById(this, R.id.conversation_search_nav);
userSelectionView = ViewUtil.findById(this, R.id.userSelectionView);
ImageButton quickCameraToggle = ViewUtil.findById(this, R.id.quick_camera_toggle); ImageButton quickCameraToggle = ViewUtil.findById(this, R.id.quick_camera_toggle);
ImageButton inlineAttachmentButton = ViewUtil.findById(this, R.id.inline_attachment_button); ImageButton inlineAttachmentButton = ViewUtil.findById(this, R.id.inline_attachment_button);
@ -1574,6 +1576,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
attachmentManager = new AttachmentManager(this, this); attachmentManager = new AttachmentManager(this, this);
audioRecorder = new AudioRecorder(this); audioRecorder = new AudioRecorder(this);
typingTextWatcher = new TypingStatusTextWatcher(); typingTextWatcher = new TypingStatusTextWatcher();
mentionTextWatcher = new MentionTextWatcher();
SendButtonListener sendButtonListener = new SendButtonListener(); SendButtonListener sendButtonListener = new SendButtonListener();
ComposeKeyPressedListener composeKeyPressedListener = new ComposeKeyPressedListener(); ComposeKeyPressedListener composeKeyPressedListener = new ComposeKeyPressedListener();
@ -2601,7 +2604,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void silentlySetComposeText(String text) { private void silentlySetComposeText(String text) {
typingTextWatcher.setEnabled(false); typingTextWatcher.setEnabled(false);
mentionTextWatcher.setEnabled(false);
composeText.setText(text); composeText.setText(text);
mentionTextWatcher.setEnabled(true);
typingTextWatcher.setEnabled(true); typingTextWatcher.setEnabled(true);
} }
@ -2716,7 +2721,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
} }
private class TypingStatusTextWatcher extends SimpleTextWatcher { private class TypingStatusTextWatcher extends SimpleTextWatcher {
private boolean enabled = true; private boolean enabled = true;
@Override @Override
@ -2731,6 +2735,36 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
} }
} }
private class MentionTextWatcher extends SimpleTextWatcher {
private boolean enabled = true;
@Override
public void onTextChanged(String text) {
if (!enabled) { return; }
int currentEndIndex = (text.length() != 0) ? text.length() - 1 : 0;
char lastCharacter = text.charAt(currentEndIndex);
LokiUserDatabase userDatabase = DatabaseFactory.getLokiUserDatabase(ConversationActivity.this);
if (lastCharacter == '@') {
List<Tuple2<String, String>> users = LokiAPI.Companion.getUsers("", threadId, userDatabase);
mentionStartIndex = currentEndIndex + 1;
userSelectionView.show(users, threadId);
} else if (!Character.isAlphabetic(lastCharacter) || !Character.isUpperCase(lastCharacter) || !Character.isLowerCase(lastCharacter)) {
mentionStartIndex = -1;
userSelectionView.hide();
} else {
if (mentionStartIndex != -1) {
String query = text.substring(mentionStartIndex);
List<Tuple2<String, String>> users = LokiAPI.Companion.getUsers(query, threadId, userDatabase);
userSelectionView.show(users, threadId);
}
}
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
@Override @Override
public void setThreadId(long threadId) { public void setThreadId(long threadId) {
this.threadId = threadId; this.threadId = threadId;
@ -2757,11 +2791,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
} }
inputPanel.setQuote(GlideApp.with(this), inputPanel.setQuote(GlideApp.with(this),
messageRecord.getDateSent(), messageRecord.getDateSent(),
author, author,
body, body,
slideDeck, slideDeck,
recipient); recipient);
} else if (messageRecord.isMms() && !((MmsMessageRecord) messageRecord).getLinkPreviews().isEmpty()) { } else if (messageRecord.isMms() && !((MmsMessageRecord) messageRecord).getLinkPreviews().isEmpty()) {
LinkPreview linkPreview = ((MmsMessageRecord) messageRecord).getLinkPreviews().get(0); LinkPreview linkPreview = ((MmsMessageRecord) messageRecord).getLinkPreviews().get(0);
@ -2772,18 +2806,18 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
} }
inputPanel.setQuote(GlideApp.with(this), inputPanel.setQuote(GlideApp.with(this),
messageRecord.getDateSent(), messageRecord.getDateSent(),
author, author,
messageRecord.getBody(), messageRecord.getBody(),
slideDeck, slideDeck,
recipient); recipient);
} else { } else {
inputPanel.setQuote(GlideApp.with(this), inputPanel.setQuote(GlideApp.with(this),
messageRecord.getDateSent(), messageRecord.getDateSent(),
author, author,
messageRecord.getBody(), messageRecord.getBody(),
messageRecord.isMms() ? ((MmsMessageRecord) messageRecord).getSlideDeck() : new SlideDeck(), messageRecord.isMms() ? ((MmsMessageRecord) messageRecord).getSlideDeck() : new SlideDeck(),
recipient); recipient);
} }
} }

View File

@ -8,11 +8,12 @@ import android.view.ViewGroup
import android.widget.BaseAdapter import android.widget.BaseAdapter
import android.widget.ListView import android.widget.ListView
import nl.komponents.kovenant.combine.Tuple2 import nl.komponents.kovenant.combine.Tuple2
import org.thoughtcrime.securesms.database.DatabaseFactory
class UserSelectionView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : ListView(context, attrs, defStyleAttr) { class UserSelectionView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : ListView(context, attrs, defStyleAttr) {
var users = listOf<Tuple2<String, String>>() private var users = listOf<Tuple2<String, String>>()
set(newValue) { field = newValue; userSelectionViewAdapter.users = newValue } set(newValue) { field = newValue; userSelectionViewAdapter.users = newValue }
var hasGroupContext = false private var hasGroupContext = false
private val userSelectionViewAdapter by lazy { Adapter(context) } private val userSelectionViewAdapter by lazy { Adapter(context) }
@ -49,4 +50,18 @@ class UserSelectionView(context: Context, attrs: AttributeSet?, defStyleAttr: In
adapter = userSelectionViewAdapter adapter = userSelectionViewAdapter
userSelectionViewAdapter.users = users userSelectionViewAdapter.users = users
} }
fun show(users: List<Tuple2<String, String>>, threadID: Long) {
hasGroupContext = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadID)!!.isGroupRecipient
this.users = users
val layoutParams = this.layoutParams as ViewGroup.LayoutParams
layoutParams.height = toPx(6 + Math.min(users.count(), 4) * 52, resources)
this.layoutParams = layoutParams
}
fun hide() {
val layoutParams = this.layoutParams as ViewGroup.LayoutParams
layoutParams.height = 0
this.layoutParams = layoutParams
}
} }