mirror of
				https://github.com/pierre42100/ComunicAndroid
				synced 2025-11-04 03:24:04 +00:00 
			
		
		
		
	Parse URLs in conversation messages
This commit is contained in:
		@@ -95,6 +95,16 @@ public class StringsUtils {
 | 
			
		||||
        return !TextUtils.isEmpty(mail) && Patterns.EMAIL_ADDRESS.matcher(mail).matches();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check whether a specified string is an URL or not
 | 
			
		||||
     *
 | 
			
		||||
     * @param string The string to check
 | 
			
		||||
     * @return TRUE if the string is an URL / FALSE else
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean isURL(CharSequence string){
 | 
			
		||||
        return !TextUtils.isEmpty(string) && Patterns.WEB_URL.matcher(string).matches();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Generate the SHA-1 summary of a given string
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ import org.communiquons.android.comunic.client.data.models.ConversationMessage;
 | 
			
		||||
import org.communiquons.android.comunic.client.data.models.UserInfo;
 | 
			
		||||
import org.communiquons.android.comunic.client.data.utils.StringsUtils;
 | 
			
		||||
import org.communiquons.android.comunic.client.ui.listeners.OnConversationMessageActionsListener;
 | 
			
		||||
import org.communiquons.android.comunic.client.ui.views.ContentTextView;
 | 
			
		||||
import org.communiquons.android.comunic.client.ui.views.EnlargeableWebImageView;
 | 
			
		||||
import org.communiquons.android.comunic.client.ui.views.WebUserAccountImage;
 | 
			
		||||
 | 
			
		||||
@@ -122,7 +123,7 @@ public class ConversationMessageAdapter extends RecyclerView.Adapter {
 | 
			
		||||
    private class BaseMessageHolder extends RecyclerView.ViewHolder
 | 
			
		||||
            implements View.OnLongClickListener{
 | 
			
		||||
 | 
			
		||||
        private TextView mMessage;
 | 
			
		||||
        ContentTextView mMessage;
 | 
			
		||||
        private TextView mSentDate;
 | 
			
		||||
        private EnlargeableWebImageView mImage;
 | 
			
		||||
 | 
			
		||||
@@ -133,7 +134,7 @@ public class ConversationMessageAdapter extends RecyclerView.Adapter {
 | 
			
		||||
            mImage = itemView.findViewById(R.id.messageImage);
 | 
			
		||||
            mSentDate = itemView.findViewById(R.id.text_message_time);
 | 
			
		||||
 | 
			
		||||
            itemView.setOnLongClickListener(this);
 | 
			
		||||
            mMessage.setOnLongClickListener(this);
 | 
			
		||||
            mImage.setOnLongClickListener(this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -156,7 +157,7 @@ public class ConversationMessageAdapter extends RecyclerView.Adapter {
 | 
			
		||||
        void bind(int pos){
 | 
			
		||||
            ConversationMessage message = mList.get(pos);
 | 
			
		||||
 | 
			
		||||
            mMessage.setText(message.getContent());
 | 
			
		||||
            mMessage.setParsedText(message.getContent());
 | 
			
		||||
            mMessage.setVisibility(mMessage.getText().length() > 0 ? View.VISIBLE : View.GONE);
 | 
			
		||||
 | 
			
		||||
            mImage.setVisibility(message.hasImage() ? View.VISIBLE : View.GONE);
 | 
			
		||||
@@ -193,6 +194,8 @@ public class ConversationMessageAdapter extends RecyclerView.Adapter {
 | 
			
		||||
 | 
			
		||||
        SentMessageHolder(@NonNull View itemView) {
 | 
			
		||||
            super(itemView);
 | 
			
		||||
 | 
			
		||||
            mMessage.setLinksColor(R.color.conversation_user_links_color);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -209,6 +212,8 @@ public class ConversationMessageAdapter extends RecyclerView.Adapter {
 | 
			
		||||
 | 
			
		||||
            mUserAccountImage = itemView.findViewById(R.id.account_image);
 | 
			
		||||
            mUserName = itemView.findViewById(R.id.user_name);
 | 
			
		||||
 | 
			
		||||
            mMessage.setLinksColor(R.color.conversation_otheruser_links_color);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void setUserInfoVisibility(boolean visible){
 | 
			
		||||
 
 | 
			
		||||
@@ -31,13 +31,23 @@ abstract class BaseFrameLayoutView extends FrameLayout {
 | 
			
		||||
        super(context, attrs, defStyleAttr, defStyleRes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get hosting activity
 | 
			
		||||
     *
 | 
			
		||||
     * @return Hosting activity, if found, null else
 | 
			
		||||
     */
 | 
			
		||||
    protected Activity getActivity(){
 | 
			
		||||
        Context context = getContext();
 | 
			
		||||
        return GetActivityFromContext(getContext());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get an activity from context
 | 
			
		||||
     *
 | 
			
		||||
     * @param context The context to parse
 | 
			
		||||
     * @return The activity
 | 
			
		||||
     */
 | 
			
		||||
    static Activity GetActivityFromContext(Context context){
 | 
			
		||||
 | 
			
		||||
        while(context instanceof ContextWrapper){
 | 
			
		||||
            if(context instanceof Activity)
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,126 @@
 | 
			
		||||
package org.communiquons.android.comunic.client.ui.views;
 | 
			
		||||
 | 
			
		||||
import android.app.Activity;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.graphics.Color;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.support.annotation.Nullable;
 | 
			
		||||
import android.text.SpannableStringBuilder;
 | 
			
		||||
import android.text.Spanned;
 | 
			
		||||
import android.text.TextPaint;
 | 
			
		||||
import android.text.method.LinkMovementMethod;
 | 
			
		||||
import android.text.style.ClickableSpan;
 | 
			
		||||
import android.util.AttributeSet;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
 | 
			
		||||
import org.communiquons.android.comunic.client.data.utils.StringsUtils;
 | 
			
		||||
import org.communiquons.android.comunic.client.ui.utils.UiUtils;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * TextView extension which parses the content passed to the
 | 
			
		||||
 * view in order to make links live
 | 
			
		||||
 *
 | 
			
		||||
 * @author Pierre HUBERT
 | 
			
		||||
 */
 | 
			
		||||
public class ContentTextView extends android.support.v7.widget.AppCompatTextView {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Debug tag
 | 
			
		||||
     */
 | 
			
		||||
    private static final String TAG = ContentTextView.class.getSimpleName();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The color of detected links
 | 
			
		||||
     */
 | 
			
		||||
    private int mLinksColor = Color.BLUE;
 | 
			
		||||
 | 
			
		||||
    public ContentTextView(Context context) {
 | 
			
		||||
        this(context, null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ContentTextView(Context context, @Nullable AttributeSet attrs) {
 | 
			
		||||
        this(context, attrs, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ContentTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
 | 
			
		||||
        super(context, attrs, defStyleAttr);
 | 
			
		||||
        setMovementMethod(LinkMovementMethod.getInstance());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected Activity getActivity(){
 | 
			
		||||
        return BaseFrameLayoutView.GetActivityFromContext(getContext());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set the color of selected links
 | 
			
		||||
     *
 | 
			
		||||
     * @param res_id The ID of the target color
 | 
			
		||||
     */
 | 
			
		||||
    public void setLinksColor(int res_id){
 | 
			
		||||
        this.mLinksColor = UiUtils.getColor(getContext(), res_id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set na new text, with links parsed
 | 
			
		||||
     *
 | 
			
		||||
     * @param text The text to parse
 | 
			
		||||
     */
 | 
			
		||||
    public void setParsedText(String text) {
 | 
			
		||||
        super.setText(text);
 | 
			
		||||
 | 
			
		||||
        //Parse text
 | 
			
		||||
        SpannableStringBuilder ssb = new SpannableStringBuilder(text);
 | 
			
		||||
 | 
			
		||||
        String[] parts = text.split("\\s+");
 | 
			
		||||
        int pos = 0;
 | 
			
		||||
        for (String part : parts) {
 | 
			
		||||
 | 
			
		||||
            //Mark it as URL
 | 
			
		||||
            if (StringsUtils.isURL(part)) {
 | 
			
		||||
 | 
			
		||||
                ClickableSpan clickableSpan = new URLClickableSpan(part);
 | 
			
		||||
                ssb.setSpan(clickableSpan, pos, pos + part.length(),
 | 
			
		||||
                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            pos += part.length() + 1;
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        setText(ssb);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Base ClickableSpan class
 | 
			
		||||
     */
 | 
			
		||||
    private abstract class BaseClickableSpan extends ClickableSpan {
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void updateDrawState(TextPaint ds) {
 | 
			
		||||
            super.updateDrawState(ds);
 | 
			
		||||
            ds.setUnderlineText(false);
 | 
			
		||||
            ds.setColor(mLinksColor);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Clickable span class for URL
 | 
			
		||||
     */
 | 
			
		||||
    private class URLClickableSpan extends BaseClickableSpan {
 | 
			
		||||
 | 
			
		||||
        private String mURL;
 | 
			
		||||
 | 
			
		||||
        private URLClickableSpan(String url){
 | 
			
		||||
            super();
 | 
			
		||||
            mURL = url;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onClick(View widget) {
 | 
			
		||||
            getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(mURL)));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
 | 
			
		||||
<android.support.constraint.ConstraintLayout
 | 
			
		||||
    xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:app="http://schemas.android.com/apk/res-auto"
 | 
			
		||||
    xmlns:tools="http://schemas.android.com/tools"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
@@ -39,7 +38,7 @@
 | 
			
		||||
            app:layout_constraintTop_toTopOf="@id/account_image"
 | 
			
		||||
            tools:text="John Doe" />
 | 
			
		||||
 | 
			
		||||
        <TextView
 | 
			
		||||
        <org.communiquons.android.comunic.client.ui.views.ContentTextView
 | 
			
		||||
            android:id="@+id/message_body"
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
@@ -62,12 +61,12 @@
 | 
			
		||||
        android:layout_height="98dp"
 | 
			
		||||
        android:layout_marginStart="60dp"
 | 
			
		||||
        android:layout_marginTop="2dp"
 | 
			
		||||
        android:scaleType="fitStart"
 | 
			
		||||
        app:layout_constraintBottom_toBottomOf="parent"
 | 
			
		||||
        app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
        app:layout_constraintTop_toBottomOf="@id/constraintLayout2"
 | 
			
		||||
        app:layout_constraintVertical_bias="0.0"
 | 
			
		||||
        app:srcCompat="@drawable/img_placeholder"
 | 
			
		||||
        android:scaleType="fitStart"/>
 | 
			
		||||
        app:srcCompat="@drawable/img_placeholder" />
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <TextView
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,17 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
 | 
			
		||||
<android.support.constraint.ConstraintLayout
 | 
			
		||||
    xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:app="http://schemas.android.com/apk/res-auto"
 | 
			
		||||
    xmlns:tools="http://schemas.android.com/tools"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="wrap_content"
 | 
			
		||||
    android:paddingTop="16dp">
 | 
			
		||||
 | 
			
		||||
    <TextView
 | 
			
		||||
    <org.communiquons.android.comunic.client.ui.views.ContentTextView
 | 
			
		||||
        android:id="@+id/message_body"
 | 
			
		||||
        android:layout_width="wrap_content"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:layout_marginRight="8dp"
 | 
			
		||||
        android:layout_marginEnd="8dp"
 | 
			
		||||
        android:background="@drawable/conversation_message_currentuser_bg"
 | 
			
		||||
        android:maxWidth="240dp"
 | 
			
		||||
        android:padding="8dp"
 | 
			
		||||
@@ -45,10 +44,10 @@
 | 
			
		||||
        android:layout_marginEnd="8dp"
 | 
			
		||||
        android:layout_marginStart="8dp"
 | 
			
		||||
        android:layout_marginTop="@dimen/conversation_message_time_padding_top"
 | 
			
		||||
        android:text="11:40"
 | 
			
		||||
        android:textSize="10sp"
 | 
			
		||||
        app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
        app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
        app:layout_constraintTop_toTopOf="parent" />
 | 
			
		||||
        app:layout_constraintTop_toTopOf="parent"
 | 
			
		||||
        tools:text="11:40" />
 | 
			
		||||
 | 
			
		||||
</android.support.constraint.ConstraintLayout>
 | 
			
		||||
@@ -22,8 +22,10 @@
 | 
			
		||||
    <!-- Conversation messages -->
 | 
			
		||||
    <color name="conversation_user_messages_background">#3F51B5</color>
 | 
			
		||||
    <color name="conversation_user_messages_textColor">#FFFFFF</color>
 | 
			
		||||
    <color name="conversation_user_links_color">#c5cae9</color>
 | 
			
		||||
    <color name="conversation_otheruser_messages_background">#D8D8D8</color>
 | 
			
		||||
    <color name="conversation_otheruser_messages_textColor">#000000</color>
 | 
			
		||||
    <color name="conversation_otheruser_links_color">@color/conversation_user_messages_background</color>
 | 
			
		||||
 | 
			
		||||
    <!-- Conversations footer -->
 | 
			
		||||
    <color name="conversation_footer_bg">#8c9eff</color>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user