From d6a7a2ff94bfefd84bc86b67fead921c98381718 Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Tue, 5 Mar 2019 14:13:57 +0100 Subject: [PATCH 1/5] First batch of mention changes Signed-off-by: Mario Danic --- .../MentionAutocompleteCallback.java | 14 +++++-- .../talk/controllers/ChatController.java | 22 ++++++++--- .../com/nextcloud/talk/utils/text/Spans.java | 39 +++++++++++++++++++ 3 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/com/nextcloud/talk/utils/text/Spans.java diff --git a/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java b/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java index c8e89c780..b40898dbb 100644 --- a/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java +++ b/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java @@ -20,9 +20,15 @@ package com.nextcloud.talk.callbacks; +import android.graphics.Typeface; import android.text.Editable; +import android.text.Spanned; +import android.text.style.StyleSpan; +import android.text.style.TypefaceSpan; +import com.nextcloud.talk.R; import com.nextcloud.talk.models.json.mention.Mention; import com.nextcloud.talk.utils.MagicCharPolicy; +import com.nextcloud.talk.utils.text.Spans; import com.otaliastudios.autocomplete.AutocompleteCallback; public class MentionAutocompleteCallback implements AutocompleteCallback { @@ -30,10 +36,12 @@ public class MentionAutocompleteCallback implements AutocompleteCallback { - sendMessage(input); - return true; - }); - + messageInputView.getButton().setOnClickListener(v -> submitMessage()); messageInputView.getButton().setContentDescription(getResources() .getString(R.string.nc_description_send_message_button)); @@ -665,6 +662,21 @@ public class ChatController extends BaseController implements MessagesListAdapte } } + private void submitMessage() { + final Editable editable = messageInput.getEditableText(); + Spans.MentionSpan mentionSpans[] = editable.getSpans(0, editable.length(), Spans.MentionSpan.class); + Spans.MentionSpan mentionSpan; + mentionAutocomplete.setEnabled(false); + for (int i = 0; i < mentionSpans.length; i++) { + mentionSpan = mentionSpans[i]; + editable.replace(editable.getSpanStart(mentionSpan), editable.getSpanEnd(mentionSpan), "@" + mentionSpan.getId()); + } + + mentionAutocomplete.setEnabled(true); + messageInput.setText(""); + sendMessage(editable); + } + private void sendMessage(CharSequence message) { ncApi.sendChatMessage(credentials, ApiUtils.getUrlForChat(conversationUser.getBaseUrl(), roomToken), diff --git a/app/src/main/java/com/nextcloud/talk/utils/text/Spans.java b/app/src/main/java/com/nextcloud/talk/utils/text/Spans.java new file mode 100644 index 000000000..1bcd93e54 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/utils/text/Spans.java @@ -0,0 +1,39 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * Copyright (C) 2017-2018 Mario Danic + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.nextcloud.talk.utils.text; + +import android.text.style.StyleSpan; +import lombok.Data; + +public class Spans { + @Data + public static class MentionSpan extends StyleSpan { + String id; + String label; + + public MentionSpan(int style, String id, String label) { + super(style); + this.id = id; + this.label = label; + } + + } +} From f4508bc4fea212a1dce7a0a198132a75607b814e Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Tue, 5 Mar 2019 14:31:13 +0100 Subject: [PATCH 2/5] Improve mention Signed-off-by: Mario Danic --- .../java/com/nextcloud/talk/controllers/ChatController.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java index 16780a83d..59e36a3bc 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java @@ -666,13 +666,11 @@ public class ChatController extends BaseController implements MessagesListAdapte final Editable editable = messageInput.getEditableText(); Spans.MentionSpan mentionSpans[] = editable.getSpans(0, editable.length(), Spans.MentionSpan.class); Spans.MentionSpan mentionSpan; - mentionAutocomplete.setEnabled(false); for (int i = 0; i < mentionSpans.length; i++) { mentionSpan = mentionSpans[i]; editable.replace(editable.getSpanStart(mentionSpan), editable.getSpanEnd(mentionSpan), "@" + mentionSpan.getId()); } - mentionAutocomplete.setEnabled(true); messageInput.setText(""); sendMessage(editable); } From dfae11f65c59830e074319d0446419649bf3bf7d Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Tue, 5 Mar 2019 14:37:15 +0100 Subject: [PATCH 3/5] Fix mentions when in the middle of text Signed-off-by: Mario Danic --- .../talk/callbacks/MentionAutocompleteCallback.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java b/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java index b40898dbb..f58bbb13e 100644 --- a/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java +++ b/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java @@ -23,9 +23,6 @@ package com.nextcloud.talk.callbacks; import android.graphics.Typeface; import android.text.Editable; import android.text.Spanned; -import android.text.style.StyleSpan; -import android.text.style.TypefaceSpan; -import com.nextcloud.talk.R; import com.nextcloud.talk.models.json.mention.Mention; import com.nextcloud.talk.utils.MagicCharPolicy; import com.nextcloud.talk.utils.text.Spans; @@ -41,7 +38,7 @@ public class MentionAutocompleteCallback implements AutocompleteCallback Date: Tue, 5 Mar 2019 21:06:16 +0100 Subject: [PATCH 4/5] Improve coloring Signed-off-by: Mario Danic --- .../MagicIncomingTextMessageViewHolder.java | 3 +-- .../MagicOutcomingTextMessageViewHolder.java | 5 ++-- .../MagicSystemMessageViewHolder.java | 4 +-- .../MentionAutocompleteCallback.java | 2 +- .../talk/controllers/ChatController.java | 10 +++++++ .../nextcloud/talk/utils/DisplayUtils.java | 27 ++++++++++++------- 6 files changed, 34 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.java b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.java index c891571fa..0136b95d7 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.java @@ -143,8 +143,7 @@ public class MagicIncomingTextMessageViewHolder .nc_incoming_text_mention_others); } - messageString = DisplayUtils.searchAndColor(messageText.getText().toString(), - messageString, "@" + individualHashMap.get("name"), color); + messageString = DisplayUtils.searchAndColor(message.getText(), "@" + individualHashMap.get("name"), color); } else if (individualHashMap.get("type").equals("file")) { itemView.setOnClickListener(v -> { Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap.get("link"))); diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.java b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.java index d7a725a39..da3dd2c52 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.java @@ -90,8 +90,9 @@ public class MagicOutcomingTextMessageViewHolder extends MessageHolders.Outcomin Map individualHashMap = message.getMessageParameters().get(key); if (individualHashMap.get("type").equals("user") || individualHashMap.get("type").equals("guest")) { if (!individualHashMap.get("id").equals(message.getActiveUserId())) { - messageString = DisplayUtils.searchAndColor(messageText.getText().toString(), - messageString, "@" + individualHashMap.get("name"), NextcloudTalkApplication + messageString = + DisplayUtils.searchAndColor(message.getText(), + "@" + individualHashMap.get("name"), NextcloudTalkApplication .getSharedApplication().getResources().getColor(R.color.nc_outcoming_text_default)); } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicSystemMessageViewHolder.java b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicSystemMessageViewHolder.java index 30ca90f47..7d11602e1 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicSystemMessageViewHolder.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicSystemMessageViewHolder.java @@ -67,8 +67,8 @@ public class MagicSystemMessageViewHolder extends MessageHolders.IncomingTextMes color = context.getResources().getColor(R.color.nc_incoming_text_mention_others); } - messageString = DisplayUtils.searchAndColor(message.getText(), - messageString, "@" + individualHashMap.get("name"), color); + messageString = + DisplayUtils.searchAndColor(message.getText(), "@" + individualHashMap.get("name"), color); } } } diff --git a/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java b/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java index f58bbb13e..9785db472 100644 --- a/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java +++ b/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java @@ -38,7 +38,7 @@ public class MentionAutocompleteCallback implements AutocompleteCallback= editable.getSpanStart(mentionSpan) && start < editable.getSpanEnd(mentionSpan)) { + editable.removeSpan(mentionSpan); + } + } } @Override diff --git a/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java b/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java index 97e05b267..7f19fbc7f 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java +++ b/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java @@ -203,27 +203,34 @@ public class DisplayUtils { } - public static Spannable searchAndColor(String text, Spannable spannable, String searchText, @ColorInt int color) { + public static Spannable searchAndColor(String text, String searchText, @ColorInt int color) { + + Spannable spannableString = new SpannableString(text); if (TextUtils.isEmpty(text) || TextUtils.isEmpty(searchText)) { - return spannable; + return spannableString; } - Matcher m = Pattern.compile(searchText, Pattern.CASE_INSENSITIVE | Pattern.LITERAL) - .matcher(text); + Matcher m = Pattern.compile(searchText, + Pattern.CASE_INSENSITIVE | Pattern.LITERAL | Pattern.MULTILINE) + .matcher(spannableString); int textSize = NextcloudTalkApplication.getSharedApplication().getResources().getDimensionPixelSize(R.dimen .chat_text_size); + + int lastStartIndex = -1; while (m.find()) { - int start = text.indexOf(m.group()); - int end = text.indexOf(m.group()) + m.group().length(); - spannable.setSpan(new ForegroundColorSpan(color), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - spannable.setSpan(new StyleSpan(Typeface.BOLD), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - spannable.setSpan(new AbsoluteSizeSpan(textSize), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + int start = text.indexOf(m.group(), lastStartIndex); + int end = start + m.group().length(); + lastStartIndex = end; + spannableString.setSpan(new ForegroundColorSpan(color), start, end, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + spannableString.setSpan(new StyleSpan(Typeface.BOLD), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + spannableString.setSpan(new AbsoluteSizeSpan(textSize), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } - return spannable; + return spannableString; } public static Drawable getMessageSelector(@ColorInt int normalColor, @ColorInt int selectedColor, From ccce05e1649158571a82a00d5ece39f600d3c0ae Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Tue, 5 Mar 2019 21:49:53 +0100 Subject: [PATCH 5/5] Fix #159 Signed-off-by: Mario Danic --- .../com/nextcloud/talk/controllers/ChatController.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java index 7a49271f0..2d9bc2fa5 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java @@ -370,7 +370,7 @@ public class ChatController extends BaseController implements MessagesListAdapte @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (s.length() == 1000) { - messageInput.setError(getResources().getString(R.string.nc_limit_hit)); + messageInput.setError(Objects.requireNonNull(getResources()).getString(R.string.nc_limit_hit)); } else { messageInput.setError(null); } @@ -381,7 +381,10 @@ public class ChatController extends BaseController implements MessagesListAdapte for (int i = 0; i < mentionSpans.length; i++) { mentionSpan = mentionSpans[i]; if (start >= editable.getSpanStart(mentionSpan) && start < editable.getSpanEnd(mentionSpan)) { - editable.removeSpan(mentionSpan); + if (!editable.subSequence(editable.getSpanStart(mentionSpan), + editable.getSpanEnd(mentionSpan)).toString().trim().equals(mentionSpan.getLabel())) { + editable.removeSpan(mentionSpan); + } } } }