From c262cd5d6e07c53c8cb92ec0e7ccb10719125cff Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sun, 5 Nov 2017 21:34:40 +0100 Subject: [PATCH] support for basic IM styling --- .../ui/ConversationFragment.java | 5 + .../ui/adapter/MessageAdapter.java | 8 +- .../conversations/utils/ImStyleParser.java | 108 ++++++++++++++ .../conversations/utils/StylingHelper.java | 134 ++++++++++++++++++ 4 files changed, 253 insertions(+), 2 deletions(-) create mode 100644 src/main/java/eu/siacs/conversations/utils/ImStyleParser.java create mode 100644 src/main/java/eu/siacs/conversations/utils/StylingHelper.java diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 3658275da..63816d193 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -15,6 +15,8 @@ import android.support.v13.view.inputmethod.InputConnectionCompat; import android.support.v13.view.inputmethod.InputContentInfoCompat; import android.text.Editable; import android.text.InputType; +import android.text.TextWatcher; +import android.text.style.StyleSpan; import android.util.Log; import android.util.Pair; import android.view.ContextMenu; @@ -73,6 +75,7 @@ import eu.siacs.conversations.ui.adapter.MessageAdapter.OnContactPictureLongClic import eu.siacs.conversations.ui.widget.EditMessage; import eu.siacs.conversations.ui.widget.ListSelectionManager; import eu.siacs.conversations.utils.NickValidityChecker; +import eu.siacs.conversations.utils.StylingHelper; import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xmpp.XmppConnection; import eu.siacs.conversations.xmpp.chatstate.ChatState; @@ -462,6 +465,8 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } }); + mEditMessage.addTextChangedListener(new StylingHelper.MessageEditorStyler(mEditMessage)); + mEditMessage.setOnEditorActionListener(mEditorActionListener); mEditMessage.setRichContentListener(new String[]{"image/*"}, mEditorContentListener); diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 2f35d49e0..b4b74faa3 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -68,6 +68,7 @@ import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.Emoticons; import eu.siacs.conversations.utils.GeoHelper; import eu.siacs.conversations.utils.Patterns; +import eu.siacs.conversations.utils.StylingHelper; import eu.siacs.conversations.utils.UIHelper; import eu.siacs.conversations.xmpp.mam.MamReference; @@ -473,8 +474,11 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie } Matcher matcher = Emoticons.generatePattern(body).matcher(body); while(matcher.find()) { - body.setSpan(new RelativeSizeSpan(1.2f), matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } + body.setSpan(new RelativeSizeSpan(1.2f), matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + + StylingHelper.format(body, true); + Linkify.addLinks(body, XMPP_PATTERN, "xmpp"); Linkify.addLinks(body, Patterns.AUTOLINK_WEB_URL, "http", WEBURL_MATCH_FILTER, WEBURL_TRANSFORM_FILTER); Linkify.addLinks(body, GeoHelper.GEO_URI, "geo"); diff --git a/src/main/java/eu/siacs/conversations/utils/ImStyleParser.java b/src/main/java/eu/siacs/conversations/utils/ImStyleParser.java new file mode 100644 index 000000000..1d164bf48 --- /dev/null +++ b/src/main/java/eu/siacs/conversations/utils/ImStyleParser.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2017, Daniel Gultsch All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package eu.siacs.conversations.utils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ImStyleParser { + + final static List KEYWORDS = Arrays.asList('*', '_', '~', '`'); + final static List NO_SUB_PARSING_KEYWORDS = Arrays.asList('`'); + final static boolean ALLOW_EMPTY = false; + + public static List