aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Schneppe <christian@pix-art.de>2019-02-09 14:34:49 +0100
committerChristian Schneppe <christian@pix-art.de>2019-02-09 14:34:49 +0100
commit7aa49998425b768244715b19c9779202c0145230 (patch)
tree9c26023bfe027ac232df19a8e041fdd15265e5b1
parent42c3129b66fe555c37fa67b6421230199cc64968 (diff)
show web link previews in chat
fixes #113
-rw-r--r--build.gradle5
-rw-r--r--src/main/java/de/pixart/messenger/entities/Message.java16
-rw-r--r--src/main/java/de/pixart/messenger/ui/SettingsActivity.java1
-rw-r--r--src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java60
-rw-r--r--src/main/java/de/pixart/messenger/ui/util/MyLinkify.java1
-rw-r--r--src/main/java/de/pixart/messenger/ui/widget/RichLinkView.java184
-rw-r--r--src/main/java/de/pixart/messenger/utils/XmppUri.java8
-rw-r--r--src/main/res/layout/link_layout.xml55
-rw-r--r--src/main/res/layout/message_content.xml5
-rw-r--r--src/main/res/values/bools.xml1
-rw-r--r--src/main/res/values/strings.xml4
-rw-r--r--src/main/res/xml/preferences.xml5
12 files changed, 329 insertions, 16 deletions
diff --git a/build.gradle b/build.gradle
index 00a3ef732..037813199 100644
--- a/build.gradle
+++ b/build.gradle
@@ -69,7 +69,6 @@ dependencies {
implementation 'com.android.support:exifinterface:28.0.0'
implementation 'com.android.support:design:28.0.0'
implementation 'com.android.support:cardview-v7:28.0.0'
- implementation 'com.github.bumptech.glide:glide:3.8.0'
implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.10.0'
implementation 'com.github.rtoshiro.fullscreenvideoview:fullscreenvideoview:1.1.3'
implementation 'pub.devrel:easypermissions:2.0.0'
@@ -81,7 +80,9 @@ dependencies {
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.15' // last working version for minSDK 16
implementation 'me.drakeet.support:toastcompat:1.1.0'
implementation 'org.osmdroid:osmdroid-android:6.0.3'
- implementation "com.leinardi.android:speed-dial:2.0.1"
+ implementation 'com.leinardi.android:speed-dial:2.0.1'
+ implementation 'io.github.ponnamkarthik:richlinkpreview:1.0.9'
+ implementation 'com.squareup.picasso:picasso:2.71828'
}
ext {
diff --git a/src/main/java/de/pixart/messenger/entities/Message.java b/src/main/java/de/pixart/messenger/entities/Message.java
index ba44a10ae..178a8e425 100644
--- a/src/main/java/de/pixart/messenger/entities/Message.java
+++ b/src/main/java/de/pixart/messenger/entities/Message.java
@@ -5,6 +5,7 @@ import android.database.Cursor;
import android.graphics.Color;
import android.text.SpannableStringBuilder;
import android.util.Log;
+import android.webkit.URLUtil;
import java.lang.ref.WeakReference;
import java.net.MalformedURLException;
@@ -14,15 +15,18 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import java.util.regex.Pattern;
import de.pixart.messenger.Config;
import de.pixart.messenger.crypto.axolotl.FingerprintStatus;
import de.pixart.messenger.services.AvatarService;
+import de.pixart.messenger.ui.util.MyLinkify;
import de.pixart.messenger.utils.CryptoHelper;
import de.pixart.messenger.utils.Emoticons;
import de.pixart.messenger.utils.GeoHelper;
import de.pixart.messenger.utils.MessageUtils;
import de.pixart.messenger.utils.MimeUtils;
+import de.pixart.messenger.utils.Patterns;
import de.pixart.messenger.utils.UIHelper;
import de.pixart.messenger.utils.XmppUri;
import rocks.xmpp.addr.Jid;
@@ -108,6 +112,7 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
private Boolean isGeoUri = null;
private Boolean isXmppUri = null;
+ private Boolean isWebUri = null;
private Boolean isEmojisOnly = null;
private Boolean treatAsDownloadable = null;
private FileParams fileParams = null;
@@ -602,6 +607,7 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
this.getBody().length() + message.getBody().length() <= Config.MAX_DISPLAY_MESSAGE_CHARS &&
!message.isGeoUri()&&
!this.isGeoUri() &&
+ !this.isWebUri() &&
!message.treatAsDownloadable() &&
!this.treatAsDownloadable() &&
!message.getBody().startsWith(ME_COMMAND) &&
@@ -767,7 +773,7 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
public synchronized boolean isXmppUri() {
if (isXmppUri == null) {
- isXmppUri = XmppUri.isXmppUri(body.trim());
+ isXmppUri = XmppUri.XMPP_URI.matcher(body).matches();
}
return isXmppUri;
}
@@ -779,6 +785,14 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
return isGeoUri;
}
+ public synchronized boolean isWebUri() {
+ String url = body.toLowerCase().trim();
+ if (isWebUri == null) {
+ isWebUri = URLUtil.isValidUrl(url) && Patterns.WEB_URL.matcher(url).matches();
+ }
+ return isWebUri;
+ }
+
public synchronized void resetFileParams() {
this.fileParams = null;
}
diff --git a/src/main/java/de/pixart/messenger/ui/SettingsActivity.java b/src/main/java/de/pixart/messenger/ui/SettingsActivity.java
index ecae24588..a7076f4c5 100644
--- a/src/main/java/de/pixart/messenger/ui/SettingsActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/SettingsActivity.java
@@ -60,6 +60,7 @@ public class SettingsActivity extends XmppActivity implements
public static final String QUICK_SHARE_ATTACHMENT_CHOICE = "quick_share_attachment_choice";
public static final String NUMBER_OF_ACCOUNTS = "number_of_accounts";
public static final String PLAY_GIF_INSIDE = "play_gif_inside";
+ public static final String SHOW_LINKS_INSIDE = "show_links_inside";
public static final String PREFER_XMPP_AVATAR = "prefer_xmpp_avatar";
public static final int REQUEST_CREATE_BACKUP = 0xbf8701;
diff --git a/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java
index 7e3d26728..897e37e85 100644
--- a/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java
+++ b/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java
@@ -10,6 +10,7 @@ import android.net.Uri;
import android.preference.PreferenceManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
+import android.text.Editable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
@@ -35,8 +36,7 @@ import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
-import com.bumptech.glide.Glide;
-import com.bumptech.glide.load.engine.DiskCacheStrategy;
+import com.squareup.picasso.Picasso;
import java.io.UnsupportedEncodingException;
import java.net.URL;
@@ -70,6 +70,7 @@ import de.pixart.messenger.ui.util.ViewUtil;
import de.pixart.messenger.ui.widget.ClickableMovementMethod;
import de.pixart.messenger.ui.widget.CopyTextView;
import de.pixart.messenger.ui.widget.ListSelectionManager;
+import de.pixart.messenger.ui.widget.RichLinkView;
import de.pixart.messenger.utils.CryptoHelper;
import de.pixart.messenger.utils.EmojiWrapper;
import de.pixart.messenger.utils.Emoticons;
@@ -77,9 +78,11 @@ import de.pixart.messenger.utils.GeoHelper;
import de.pixart.messenger.utils.StylingHelper;
import de.pixart.messenger.utils.UIHelper;
import de.pixart.messenger.xmpp.mam.MamReference;
+import io.github.ponnamkarthik.richlinkpreview.ViewListener;
import pl.droidsonroids.gif.GifImageView;
import static de.pixart.messenger.ui.SettingsActivity.PLAY_GIF_INSIDE;
+import static de.pixart.messenger.ui.SettingsActivity.SHOW_LINKS_INSIDE;
public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextView.CopyHandler {
@@ -356,6 +359,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
viewHolder.audioPlayer.setVisibility(View.GONE);
viewHolder.image.setVisibility(View.GONE);
viewHolder.gifImage.setVisibility(View.GONE);
+ viewHolder.richlinkview.setVisibility(View.GONE);
viewHolder.messageBody.setVisibility(View.VISIBLE);
viewHolder.messageBody.setText(text);
if (darkBackground) {
@@ -371,6 +375,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
viewHolder.audioPlayer.setVisibility(View.GONE);
viewHolder.image.setVisibility(View.GONE);
viewHolder.gifImage.setVisibility(View.GONE);
+ viewHolder.richlinkview.setVisibility(View.GONE);
viewHolder.messageBody.setVisibility(View.VISIBLE);
if (darkBackground) {
viewHolder.messageBody.setTextAppearance(getContext(), R.style.TextAppearance_Conversations_Body1_Emoji_OnDark);
@@ -415,6 +420,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
});
viewHolder.image.setVisibility(View.GONE);
viewHolder.gifImage.setVisibility(View.GONE);
+ viewHolder.richlinkview.setVisibility(View.GONE);
viewHolder.messageBody.setVisibility(View.GONE);
}
@@ -490,6 +496,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
viewHolder.download_button.setVisibility(View.GONE);
viewHolder.image.setVisibility(View.GONE);
viewHolder.gifImage.setVisibility(View.GONE);
+ viewHolder.richlinkview.setVisibility(View.GONE);
viewHolder.audioPlayer.setVisibility(View.GONE);
viewHolder.messageBody.setVisibility(View.VISIBLE);
if (darkBackground) {
@@ -587,6 +594,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
viewHolder.audioPlayer.setVisibility(View.GONE);
viewHolder.image.setVisibility(View.GONE);
viewHolder.gifImage.setVisibility(View.GONE);
+ viewHolder.richlinkview.setVisibility(View.GONE);
viewHolder.messageBody.setVisibility(View.GONE);
viewHolder.download_button.setVisibility(View.VISIBLE);
viewHolder.download_button.setText(text);
@@ -598,6 +606,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
viewHolder.audioPlayer.setVisibility(View.GONE);
viewHolder.image.setVisibility(View.GONE);
viewHolder.gifImage.setVisibility(View.GONE);
+ viewHolder.richlinkview.setVisibility(View.GONE);
viewHolder.messageBody.setVisibility(View.GONE);
viewHolder.download_button.setVisibility(View.VISIBLE);
final String mimeType = message.getMimeType();
@@ -658,12 +667,45 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
viewHolder.download_button.setText(activity.getString(R.string.open_x_file, UIHelper.getFileDescriptionString(activity, message) + VCardName));
}
+ private void displayRichLinkMessage(ViewHolder viewHolder, final Message message, boolean darkBackground) {
+ viewHolder.audioPlayer.setVisibility(View.GONE);
+ viewHolder.image.setVisibility(View.GONE);
+ viewHolder.gifImage.setVisibility(View.GONE);
+ boolean showLinksInside = activity.getPreferences().getBoolean(SHOW_LINKS_INSIDE, activity.getResources().getBoolean(R.bool.show_links_inside));
+ viewHolder.messageBody.setVisibility(View.VISIBLE);
+ Editable body = new SpannableStringBuilder(message.getBody().toLowerCase());
+ if (darkBackground) {
+ viewHolder.messageBody.setTextAppearance(getContext(), R.style.TextAppearance_Conversations_Body1_OnDark);
+ } else {
+ viewHolder.messageBody.setTextAppearance(getContext(), R.style.TextAppearance_Conversations_Body1);
+ }
+ MyLinkify.addLinks(body, false);
+ viewHolder.messageBody.setAutoLinkMask(0);
+ viewHolder.messageBody.setText(EmojiWrapper.transform(body));
+ if (showLinksInside) {
+ viewHolder.richlinkview.setVisibility(View.VISIBLE);
+ viewHolder.richlinkview.setLink(body.toString(), new ViewListener() {
+
+ @Override
+ public void onSuccess(boolean status) {
+ }
+
+ @Override
+ public void onError(Exception e) {
+ }
+ });
+ } else {
+ viewHolder.richlinkview.setVisibility(View.GONE);
+ }
+ }
+
private void displayLocationMessage(ViewHolder viewHolder, final Message message) {
viewHolder.audioPlayer.setVisibility(View.GONE);
viewHolder.messageBody.setVisibility(View.GONE);
String url = GeoHelper.MapPreviewUri(message);
viewHolder.image.setVisibility(View.VISIBLE);
viewHolder.gifImage.setVisibility(View.GONE);
+ viewHolder.richlinkview.setVisibility(View.GONE);
double target = metrics.density * 200;
int scaledW;
int scaledH;
@@ -681,12 +723,9 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
layoutParams.setMargins(0, (int) (metrics.density * 4), 0, (int) (metrics.density * 4));
viewHolder.image.setLayoutParams(layoutParams);
viewHolder.image.setOnClickListener(v -> showLocation(message));
- Glide
- .with(activity)
+ Picasso
+ .get()
.load(Uri.parse(url))
- .asBitmap()
- .diskCacheStrategy(DiskCacheStrategy.ALL)
- .fitCenter()
.placeholder(R.drawable.ic_map_marker_grey600_48dp)
.error(R.drawable.ic_map_marker_grey600_48dp)
.into(viewHolder.image);
@@ -702,6 +741,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
private void displayAudioMessage(ViewHolder viewHolder, Message message, boolean darkBackground) {
viewHolder.image.setVisibility(View.GONE);
viewHolder.gifImage.setVisibility(View.GONE);
+ viewHolder.richlinkview.setVisibility(View.GONE);
viewHolder.messageBody.setVisibility(View.GONE);
viewHolder.download_button.setVisibility(View.GONE);
final RelativeLayout audioPlayer = viewHolder.audioPlayer;
@@ -714,6 +754,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
viewHolder.download_button.setVisibility(View.GONE);
viewHolder.messageBody.setVisibility(View.GONE);
viewHolder.audioPlayer.setVisibility(View.GONE);
+ viewHolder.richlinkview.setVisibility(View.GONE);
DownloadableFile file = activity.xmppConnectionService.getFileBackend().getFile(message);
if (!file.exists()) {
Toast.makeText(activity, R.string.file_deleted, Toast.LENGTH_SHORT).show();
@@ -821,6 +862,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
viewHolder.edit_indicator = view.findViewById(R.id.edit_indicator);
viewHolder.image = view.findViewById(R.id.message_image);
viewHolder.gifImage = view.findViewById(R.id.message_image_gif);
+ viewHolder.richlinkview = view.findViewById(R.id.richLinkView);
viewHolder.messageBody = view.findViewById(R.id.message_body);
viewHolder.time = view.findViewById(R.id.message_time);
viewHolder.indicatorReceived = view.findViewById(R.id.indicator_received);
@@ -836,6 +878,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
viewHolder.edit_indicator = view.findViewById(R.id.edit_indicator);
viewHolder.image = view.findViewById(R.id.message_image);
viewHolder.gifImage = view.findViewById(R.id.message_image_gif);
+ viewHolder.richlinkview = view.findViewById(R.id.richLinkView);
viewHolder.messageBody = view.findViewById(R.id.message_body);
viewHolder.time = view.findViewById(R.id.message_time);
viewHolder.indicatorReceived = view.findViewById(R.id.indicator_received);
@@ -964,6 +1007,8 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
} else {
if (message.isGeoUri()) {
displayLocationMessage(viewHolder, message);
+ } else if (message.isWebUri()) {
+ displayRichLinkMessage(viewHolder, message, darkBackground);
} else if (message.bodyIsOnlyEmojis() && message.getType() != Message.TYPE_PRIVATE) {
displayEmojiMessage(viewHolder, message.getBody().trim(), darkBackground);
} else if (message.isXmppUri()) {
@@ -1130,6 +1175,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
protected Button resend_button;
protected ImageView image;
protected GifImageView gifImage;
+ protected RichLinkView richlinkview;
protected ImageView indicator;
protected ImageView indicatorReceived;
protected ImageView indicatorRead;
diff --git a/src/main/java/de/pixart/messenger/ui/util/MyLinkify.java b/src/main/java/de/pixart/messenger/ui/util/MyLinkify.java
index 4b276e392..59de9be6d 100644
--- a/src/main/java/de/pixart/messenger/ui/util/MyLinkify.java
+++ b/src/main/java/de/pixart/messenger/ui/util/MyLinkify.java
@@ -34,6 +34,7 @@ import android.text.Editable;
import android.text.util.Linkify;
import java.util.Locale;
+import java.util.regex.Pattern;
import de.pixart.messenger.ui.text.FixedURLSpan;
import de.pixart.messenger.utils.GeoHelper;
diff --git a/src/main/java/de/pixart/messenger/ui/widget/RichLinkView.java b/src/main/java/de/pixart/messenger/ui/widget/RichLinkView.java
new file mode 100644
index 000000000..29f04970d
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/ui/widget/RichLinkView.java
@@ -0,0 +1,184 @@
+package de.pixart.messenger.ui.widget;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.support.annotation.RequiresApi;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.squareup.picasso.Picasso;
+
+import de.pixart.messenger.R;
+import io.github.ponnamkarthik.richlinkpreview.MetaData;
+import io.github.ponnamkarthik.richlinkpreview.ResponseListener;
+import io.github.ponnamkarthik.richlinkpreview.RichLinkListener;
+import io.github.ponnamkarthik.richlinkpreview.RichPreview;
+import io.github.ponnamkarthik.richlinkpreview.ViewListener;
+
+/**
+ * Created by ponna on 16-01-2018.
+ */
+
+public class RichLinkView extends RelativeLayout {
+
+ private View view;
+ Context context;
+ private MetaData meta;
+
+ LinearLayout linearLayout;
+ ImageView imageView;
+ TextView textViewTitle;
+ TextView textViewDesp;
+ TextView textViewUrl;
+
+ private String main_url;
+
+ private boolean isDefaultClick = true;
+
+ private RichLinkListener richLinkListener;
+
+
+ public RichLinkView(Context context) {
+ super(context);
+ this.context = context;
+ }
+
+ public RichLinkView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ this.context = context;
+ }
+
+ public RichLinkView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ this.context = context;
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+ public RichLinkView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ this.context = context;
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ }
+
+
+ public void initView() {
+ if (findLinearLayoutChild() != null) {
+ this.view = findLinearLayoutChild();
+ } else {
+ this.view = this;
+ inflate(context, R.layout.link_layout, this);
+ }
+ linearLayout = findViewById(R.id.rich_link_card);
+ imageView = findViewById(R.id.rich_link_image);
+ textViewTitle = findViewById(R.id.rich_link_title);
+ textViewDesp = findViewById(R.id.rich_link_desp);
+ textViewUrl = findViewById(R.id.rich_link_url);
+
+ if (!meta.getImageurl().equals("") || !meta.getImageurl().isEmpty()
+ && !meta.getTitle().isEmpty() || !meta.getTitle().equals("")
+ && !meta.getUrl().isEmpty() || !meta.getUrl().equals("")
+ && !meta.getDescription().isEmpty() || !meta.getDescription().equals("")) {
+ linearLayout.setVisibility(VISIBLE);
+ } else {
+ linearLayout.setVisibility(GONE);
+ }
+ if (meta.getImageurl().equals("") || meta.getImageurl().isEmpty()) {
+ imageView.setVisibility(GONE);
+ } else {
+ imageView.setVisibility(VISIBLE);
+ Picasso.get()
+ .load(meta.getImageurl())
+ .into(imageView);
+ }
+ if (meta.getTitle().isEmpty() || meta.getTitle().equals("")) {
+ textViewTitle.setVisibility(GONE);
+ } else {
+ textViewTitle.setVisibility(VISIBLE);
+ textViewTitle.setText(meta.getTitle());
+ }
+ if (meta.getUrl().isEmpty() || meta.getUrl().equals("")) {
+ textViewUrl.setVisibility(GONE);
+ } else {
+ textViewUrl.setVisibility(GONE);
+ textViewUrl.setText(meta.getUrl());
+ }
+ if (meta.getDescription().isEmpty() || meta.getDescription().equals("")) {
+ textViewDesp.setVisibility(GONE);
+ } else {
+ textViewDesp.setVisibility(VISIBLE);
+ textViewDesp.setText(meta.getDescription());
+ }
+
+ linearLayout.setOnClickListener(view -> {
+ if (isDefaultClick) {
+ richLinkClicked();
+ } else {
+ if (richLinkListener != null) {
+ richLinkListener.onClicked(view, meta);
+ } else {
+ richLinkClicked();
+ }
+ }
+ });
+ }
+
+ private void richLinkClicked() {
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(main_url));
+ context.startActivity(intent);
+ }
+
+ public void setDefaultClickListener(boolean isDefault) {
+ isDefaultClick = isDefault;
+ }
+
+ public void setClickListener(RichLinkListener richLinkListener1) {
+ richLinkListener = richLinkListener1;
+ }
+
+ protected LinearLayout findLinearLayoutChild() {
+ if (getChildCount() > 0 && getChildAt(0) instanceof LinearLayout) {
+ return (LinearLayout) getChildAt(0);
+ }
+ return null;
+ }
+
+ public void setLinkFromMeta(MetaData metaData) {
+ meta = metaData;
+ initView();
+ }
+
+ public MetaData getMetaData() {
+ return meta;
+ }
+
+ public void setLink(String url, final ViewListener viewListener) {
+ main_url = url;
+ RichPreview richPreview = new RichPreview(new ResponseListener() {
+ @Override
+ public void onData(MetaData metaData) {
+ meta = metaData;
+ if (!meta.getTitle().isEmpty() || !meta.getTitle().equals("")) {
+ viewListener.onSuccess(true);
+ }
+ initView();
+ }
+
+ @Override
+ public void onError(Exception e) {
+ viewListener.onError(e);
+ }
+ });
+ richPreview.getPreview(url);
+ }
+}
diff --git a/src/main/java/de/pixart/messenger/utils/XmppUri.java b/src/main/java/de/pixart/messenger/utils/XmppUri.java
index 1ee90aa84..64f28cbab 100644
--- a/src/main/java/de/pixart/messenger/utils/XmppUri.java
+++ b/src/main/java/de/pixart/messenger/utils/XmppUri.java
@@ -8,6 +8,7 @@ import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
+import java.util.regex.Pattern;
import de.pixart.messenger.Config;
import rocks.xmpp.addr.Jid;
@@ -27,6 +28,8 @@ public class XmppUri {
public static final String ACTION_JOIN = "join";
public static final String ACTION_MESSAGE = "message";
+ public static Pattern XMPP_URI = Patterns.XMPP_PATTERN;
+
public XmppUri(String uri) {
try {
parse(Uri.parse(uri));
@@ -43,11 +46,6 @@ public class XmppUri {
parse(uri);
}
- public static boolean isXmppUri(String uri) {
- String scheme = Uri.parse(uri).getScheme();
- return "xmpp".equalsIgnoreCase(scheme);
- }
-
public XmppUri(Uri uri, boolean safeSource) {
this.safeSource = safeSource;
parse(uri);
diff --git a/src/main/res/layout/link_layout.xml b/src/main/res/layout/link_layout.xml
new file mode 100644
index 000000000..68e7a6cc7
--- /dev/null
+++ b/src/main/res/layout/link_layout.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/rich_link_card"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="5dp"
+ android:gravity="center"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/rich_link_image"
+ android:layout_width="80dp"
+ android:layout_height="80dp"
+ android:scaleType="centerCrop" />
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:padding="2dp">
+
+ <TextView
+ android:id="@+id/rich_link_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:padding="2dp"
+ android:textAppearance="@style/TextAppearance.Conversations.Body2"
+ tools:text="Data" />
+
+ <TextView
+ android:id="@+id/rich_link_desp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:maxLines="4"
+ android:padding="2dp"
+ android:textAppearance="@style/TextAppearance.Conversations.Status"
+ tools:text="Data" />
+
+ <TextView
+ android:id="@+id/rich_link_url"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:padding="2dp"
+ android:textAppearance="@style/TextAppearance.Conversations.Body1.Secondary"
+ android:visibility="gone"
+ tools:text="Data" />
+
+ </LinearLayout>
+</LinearLayout> \ No newline at end of file
diff --git a/src/main/res/layout/message_content.xml b/src/main/res/layout/message_content.xml
index f14f310c3..be2bbf3db 100644
--- a/src/main/res/layout/message_content.xml
+++ b/src/main/res/layout/message_content.xml
@@ -28,6 +28,11 @@
android:scaleType="centerCrop"
app:riv_corner_radius="@dimen/rounded_image_border" />
+ <de.pixart.messenger.ui.widget.RichLinkView
+ android:id="@+id/richLinkView"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
<de.pixart.messenger.ui.widget.CopyTextView
android:id="@+id/message_body"
android:layout_width="wrap_content"
diff --git a/src/main/res/values/bools.xml b/src/main/res/values/bools.xml
index 4807728ca..f5d0a43b6 100644
--- a/src/main/res/values/bools.xml
+++ b/src/main/res/values/bools.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="prefer_xmpp_avatar">true</bool>
+ <bool name="show_links_inside">true</bool>
</resources> \ No newline at end of file
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 5742775e0..3a2eb4ea7 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -823,8 +823,10 @@
<string name="enter_your_name_instructions">Please enter your nickname which will be visible to your contacts.</string>
<string name="no_name_set_instructions">No nickname set.</string>
<string name="autojoin_groupchat">Automatically join this group chat</string>
+ <string name="pref_show_links_inside">Show previews of web links in chat</string>
+ <string name="pref_show_links_inside_summary">Show previews of web links directly inside the chat view.</string>
<string name="pref_play_gif_inside">Play GIF files in chat</string>
- <string name="pref_play_gif_inside_summary">Setting this to true plays GIF files directly inside the chat view.</string>
+ <string name="pref_play_gif_inside_summary">Play GIF files directly inside the chat view.</string>
<string name="open_with">Open with…</string>
<string name="server_info_adhoc_invite">XEP-0050: Ad-Hoc Commands: user invite</string>
<string name="choose_account">Choose account</string>
diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml
index 52a957f98..15fe0fc34 100644
--- a/src/main/res/xml/preferences.xml
+++ b/src/main/res/xml/preferences.xml
@@ -77,6 +77,11 @@
android:summary="@string/pref_play_gif_inside_summary"
android:title="@string/pref_play_gif_inside" />
<CheckBoxPreference
+ android:defaultValue="@bool/show_links_inside"
+ android:key="show_links_inside"
+ android:summary="@string/pref_show_links_inside_summary"
+ android:title="@string/pref_show_links_inside" />
+ <CheckBoxPreference
android:defaultValue="@bool/prefer_xmpp_avatar"
android:key="prefer_xmpp_avatar"
android:summary="@string/pref_prefer_xmpp_avatar_summary"