allow tab completion in conferences

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java | 43 +
src/main/java/eu/siacs/conversations/ui/EditMessage.java          | 20 
2 files changed, 59 insertions(+), 4 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java 🔗

@@ -37,6 +37,7 @@ import android.widget.Toast;
 import net.java.otr4j.session.SessionStatus;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.concurrent.ConcurrentLinkedQueue;
@@ -1226,6 +1227,48 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 		updateSendButton();
 	}
 
+	private int completionIndex = 0;
+	private int lastCompletionLength = 0;
+	private String incomplete;
+	private int lastCompletionCursor;
+	private boolean firstWord = false;
+
+	@Override
+	public boolean onTabPressed(boolean repeated) {
+		if (conversation == null || conversation.getMode() == Conversation.MODE_SINGLE) {
+			return false;
+		}
+		if (repeated) {
+			completionIndex++;
+		} else {
+			lastCompletionLength = 0;
+			completionIndex = 0;
+			final String content = mEditMessage.getText().toString();
+			lastCompletionCursor = mEditMessage.getSelectionEnd();
+			int start = lastCompletionCursor > 0 ? content.lastIndexOf(" ",lastCompletionCursor-1) + 1 : 0;
+			firstWord = start == 0;
+			incomplete = content.substring(start,lastCompletionCursor);
+		}
+		List<String> completions = new ArrayList<>();
+		for(MucOptions.User user : conversation.getMucOptions().getUsers()) {
+			if (user.getName().startsWith(incomplete)) {
+				completions.add(user.getName()+(firstWord ? ": " : " "));
+			}
+		}
+		Collections.sort(completions);
+		if (completions.size() > completionIndex) {
+			String completion = completions.get(completionIndex).substring(incomplete.length());
+			mEditMessage.getEditableText().delete(lastCompletionCursor,lastCompletionCursor + lastCompletionLength);
+			mEditMessage.getEditableText().insert(lastCompletionCursor, completion);
+			lastCompletionLength = completion.length();
+		} else {
+			completionIndex = -1;
+			mEditMessage.getEditableText().delete(lastCompletionCursor,lastCompletionCursor + lastCompletionLength);
+			lastCompletionLength = 0;
+		}
+		return true;
+	}
+
 	@Override
 	public void onActivityResult(int requestCode, int resultCode,
 	                                final Intent data) {

src/main/java/eu/siacs/conversations/ui/EditMessage.java 🔗

@@ -32,14 +32,24 @@ public class EditMessage extends EditText {
 
 	private boolean isUserTyping = false;
 
+	private boolean lastInputWasTab = false;
+
 	protected KeyboardListener keyboardListener;
 
 	@Override
 	public boolean onKeyDown(int keyCode, KeyEvent event) {
 		if (keyCode == KeyEvent.KEYCODE_ENTER && !event.isShiftPressed()) {
+			lastInputWasTab = false;
 			if (keyboardListener != null && keyboardListener.onEnterPressed()) {
 				return true;
 			}
+		} else if (keyCode == KeyEvent.KEYCODE_TAB) {
+			if (keyboardListener != null && keyboardListener.onTabPressed(this.lastInputWasTab)) {
+				lastInputWasTab = true;
+				return true;
+			}
+		} else {
+			lastInputWasTab = false;
 		}
 		return super.onKeyDown(keyCode, event);
 	}
@@ -47,6 +57,7 @@ public class EditMessage extends EditText {
 	@Override
 	public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
 		super.onTextChanged(text,start,lengthBefore,lengthAfter);
+		lastInputWasTab = false;
 		if (this.mTypingHandler != null && this.keyboardListener != null) {
 			this.mTypingHandler.removeCallbacks(mTypingTimeout);
 			this.mTypingHandler.postDelayed(mTypingTimeout, Config.TYPING_TIMEOUT * 1000);
@@ -69,10 +80,11 @@ public class EditMessage extends EditText {
 	}
 
 	public interface KeyboardListener {
-		public boolean onEnterPressed();
-		public void onTypingStarted();
-		public void onTypingStopped();
-		public void onTextDeleted();
+		boolean onEnterPressed();
+		void onTypingStarted();
+		void onTypingStopped();
+		void onTextDeleted();
+		boolean onTabPressed(boolean repeated);
 	}
 
 }