From 8b681105d19743b7417d3837f616b022de268330 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Wed, 20 Feb 2019 22:38:51 +0100 Subject: improve RichPreview --- build.gradle | 1 - .../pixart/messenger/ui/ConversationFragment.java | 86 ------ .../messenger/ui/adapter/MessageAdapter.java | 33 +- .../pixart/messenger/ui/widget/RichLinkView.java | 60 ++-- .../java/de/pixart/messenger/utils/MetaData.java | 74 +++++ .../de/pixart/messenger/utils/RichPreview.java | 333 ++++++++++++++------- src/main/res/drawable-hdpi/ic_web_grey600_48.png | Bin 0 -> 476 bytes src/main/res/drawable-mdpi/ic_web_grey600_48.png | Bin 0 -> 345 bytes src/main/res/drawable-xhdpi/ic_web_grey600_48.png | Bin 0 -> 788 bytes src/main/res/drawable-xxhdpi/ic_web_grey600_48.png | Bin 0 -> 1014 bytes .../res/drawable-xxxhdpi/ic_web_grey600_48.png | Bin 0 -> 2346 bytes src/main/res/layout/link_layout.xml | 26 +- src/main/res/layout/message_content.xml | 3 +- 13 files changed, 366 insertions(+), 250 deletions(-) create mode 100644 src/main/java/de/pixart/messenger/utils/MetaData.java create mode 100644 src/main/res/drawable-hdpi/ic_web_grey600_48.png create mode 100644 src/main/res/drawable-mdpi/ic_web_grey600_48.png create mode 100644 src/main/res/drawable-xhdpi/ic_web_grey600_48.png create mode 100644 src/main/res/drawable-xxhdpi/ic_web_grey600_48.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_web_grey600_48.png diff --git a/build.gradle b/build.gradle index 948383663..8750aed83 100644 --- a/build.gradle +++ b/build.gradle @@ -81,7 +81,6 @@ dependencies { 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 'io.github.ponnamkarthik:richlinkpreview:1.0.9' implementation 'com.squareup.picasso:picasso:2.71828' implementation 'com.squareup.okhttp3:okhttp:3.13.1' } diff --git a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java index 12b1a5059..975e4f768 100644 --- a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java +++ b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java @@ -173,8 +173,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke public Uri mPendingEditorContent = null; public FragmentConversationBinding binding; protected MessageAdapter messageListAdapter; - protected Message lastHistoryMessage = null; - SimpleDateFormat sdf = new SimpleDateFormat("EEEE, dd. MMM yyyy", Locale.getDefault()); private String lastMessageUuid = null; private Conversation conversation; private Toast messageLoaderToast; @@ -682,21 +680,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke return -1; } - private ScrollState getScrollPosition(int pos, View view) { - final ListView listView = this.binding.messagesView; - if (listView.getCount() == 0 || listView.getLastVisiblePosition() == listView.getCount() - 1) { - return null; - } else { - //final int pos = listView.getFirstVisiblePosition(); - //final View view = listView.getChildAt(0); - if (view == null) { - return null; - } else { - return new ScrollState(pos, view.getTop()); - } - } - } - private ScrollState getScrollPosition() { final ListView listView = this.binding == null ? null : this.binding.messagesView; if (listView == null || listView.getCount() == 0 || listView.getLastVisiblePosition() == listView.getCount() - 1) { @@ -2958,75 +2941,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke return true; } - public Message searchHistory(String query) { - return searchHistory(query, null); - } - - public Message searchHistory(String query, Boolean ascendingSearch) { - return searchHistory(query, lastHistoryMessage, ascendingSearch); - } - - /** - * Search through history from message basis either ascending or descending - * - * @param query search term - * @param basis message to start from. If null, start from last recent message - * @param ascendingSearch do we want to ascend or descend in our search? - * If this is null, ascend to first match and return. - * @return match or null - */ - public Message searchHistory(String query, Message basis, Boolean ascendingSearch) { - int entryIndex; - Message message; - lastHistoryMessage = basis; - if (messageList.size() == 0) { - return null; - } - if (basis == null) { - entryIndex = messageList.size() - 1; - } else { - int in = getIndexOf(basis.getUuid(), messageList); - entryIndex = (in != -1 ? in : messageList.size() - 1); - } - - int firstMatchIndex = entryIndex; - boolean entryIndexWasMatch = true; - do { - message = messageList.get(firstMatchIndex); - if (message.getType() == Message.TYPE_TEXT && messageContainsQuery(message, query)) { - lastHistoryMessage = message; - break; - } - entryIndexWasMatch = false; - firstMatchIndex = (messageList.size() + firstMatchIndex - 1) % messageList.size(); - } while (entryIndex != firstMatchIndex); - - if (!entryIndexWasMatch && entryIndex == firstMatchIndex) { - //No matches - return null; - } - - if (ascendingSearch != null) { - int direction = ascendingSearch ? -1 : 1; - int nextMatchIndex = firstMatchIndex; - do { - nextMatchIndex = (messageList.size() + nextMatchIndex + direction) % messageList.size(); - message = messageList.get(nextMatchIndex); - if (message.getType() == Message.TYPE_TEXT && messageContainsQuery(message, query)) { - lastHistoryMessage = message; - break; - } - } while (nextMatchIndex != entryIndex); - } - - if (lastHistoryMessage != null) { - int pos = getIndexOf(lastHistoryMessage.getUuid(), messageList); - setScrollPosition(getScrollPosition(pos, getView()), null); - this.binding.messagesView.setSelection(pos); - } - return lastHistoryMessage; - } - private boolean messageContainsQuery(Message m, String q) { return m != null && m.getMergedBody().toString().toLowerCase().contains(q.toLowerCase()); } 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 8a2ca0b4d..8b93793c3 100644 --- a/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java +++ b/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java @@ -75,12 +75,13 @@ import de.pixart.messenger.utils.CryptoHelper; import de.pixart.messenger.utils.EmojiWrapper; import de.pixart.messenger.utils.Emoticons; import de.pixart.messenger.utils.GeoHelper; +import de.pixart.messenger.utils.RichPreview; 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 android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static de.pixart.messenger.ui.SettingsActivity.PLAY_GIF_INSIDE; import static de.pixart.messenger.ui.SettingsActivity.SHOW_LINKS_INSIDE; @@ -104,6 +105,8 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie private OnContactPictureClicked mOnContactPictureClickedListener; private OnContactPictureLongClicked mOnContactPictureLongClickedListener; private boolean mIndicateReceived = false; + private boolean mPlayGifInside = false; + private boolean mShowLinksInside = false; private OnQuoteListener onQuoteListener; public MessageAdapter(XmppActivity activity, List messages) { @@ -671,7 +674,6 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie 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()); if (darkBackground) { @@ -685,10 +687,22 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie viewHolder.messageBody.setTextIsSelectable(true); viewHolder.messageBody.setMovementMethod(ClickableMovementMethod.getInstance()); listSelectionManager.onUpdate(viewHolder.messageBody, message); - boolean dataSaverDisabled = activity.xmppConnectionService.isDataSaverDisabled(); - if (showLinksInside && dataSaverDisabled) { - viewHolder.richlinkview.setVisibility(View.VISIBLE); - viewHolder.richlinkview.setLink(body.toString(), new ViewListener() { + final boolean dataSaverDisabled = activity.xmppConnectionService.isDataSaverDisabled(); + viewHolder.richlinkview.setVisibility(View.VISIBLE); + if (mShowLinksInside) { + double target = metrics.density * 200; + int scaledH; + if (Math.max(100, 100) * metrics.density <= target) { + scaledH = (int) (100 * metrics.density); + } else if (Math.max(100, 100) <= target) { + scaledH = 100; + } else { + scaledH = (int) (100 / ((double) 100 / target)); + } + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(WRAP_CONTENT, scaledH); + layoutParams.setMargins(0, (int) (metrics.density * 4), 0, (int) (metrics.density * 4)); + viewHolder.richlinkview.setLayoutParams(layoutParams); + viewHolder.richlinkview.setLink(body.toString(), message.getUuid(), dataSaverDisabled, new RichPreview.ViewListener() { @Override public void onSuccess(boolean status) { @@ -696,6 +710,8 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie @Override public void onError(Exception e) { + e.printStackTrace(); + viewHolder.richlinkview.setVisibility(View.GONE); } }); } else { @@ -765,8 +781,7 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie return; } String mime = file.getMimeType(); - boolean playGifInside = activity.getPreferences().getBoolean(PLAY_GIF_INSIDE, activity.getResources().getBoolean(R.bool.play_gif_inside)); - if (mime != null && mime.equals("image/gif") && playGifInside) { + if (mime != null && mime.equals("image/gif") && mPlayGifInside) { Log.d(Config.LOGTAG, "Gif Image file"); viewHolder.image.setVisibility(View.GONE); viewHolder.gifImage.setVisibility(View.VISIBLE); @@ -1151,6 +1166,8 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie public void updatePreferences() { SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(activity); this.mIndicateReceived = p.getBoolean("indicate_received", activity.getResources().getBoolean(R.bool.indicate_received)); + this.mPlayGifInside = p.getBoolean(PLAY_GIF_INSIDE, activity.getResources().getBoolean(R.bool.play_gif_inside)); + this.mShowLinksInside = p.getBoolean(SHOW_LINKS_INSIDE, activity.getResources().getBoolean(R.bool.show_links_inside)); } public void setHighlightedTerm(List terms) { diff --git a/src/main/java/de/pixart/messenger/ui/widget/RichLinkView.java b/src/main/java/de/pixart/messenger/ui/widget/RichLinkView.java index 5a78e76b0..dbe6a4629 100644 --- a/src/main/java/de/pixart/messenger/ui/widget/RichLinkView.java +++ b/src/main/java/de/pixart/messenger/ui/widget/RichLinkView.java @@ -6,6 +6,7 @@ import android.net.Uri; import android.os.Build; import android.support.annotation.RequiresApi; import android.util.AttributeSet; +import android.util.DisplayMetrics; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; @@ -15,12 +16,9 @@ import android.widget.TextView; import com.squareup.picasso.Picasso; import de.pixart.messenger.R; -import de.pixart.messenger.services.XmppConnectionService; +import de.pixart.messenger.utils.MetaData; import de.pixart.messenger.utils.RichPreview; -import io.github.ponnamkarthik.richlinkpreview.MetaData; -import io.github.ponnamkarthik.richlinkpreview.ResponseListener; -import io.github.ponnamkarthik.richlinkpreview.RichLinkListener; -import io.github.ponnamkarthik.richlinkpreview.ViewListener; + /** * Created by ponna on 16-01-2018. @@ -36,15 +34,12 @@ public class RichLinkView extends RelativeLayout { ImageView imageView; TextView textViewTitle; TextView textViewDesp; - TextView textViewUrl; private String main_url; private boolean isDefaultClick = true; - private RichLinkListener richLinkListener; - - private XmppConnectionService mXmppConnectionService; + private RichPreview.RichLinkListener richLinkListener; public RichLinkView(Context context) { super(context); @@ -73,7 +68,7 @@ public class RichLinkView extends RelativeLayout { } - public void initView() { + public void initView(final boolean dataSaverDisabled) { if (findLinearLayoutChild() != null) { this.view = findLinearLayoutChild(); } else { @@ -84,36 +79,43 @@ public class RichLinkView extends RelativeLayout { 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); - + imageView.setAdjustViewBounds(true); 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); + linearLayout.setVisibility(VISIBLE); } - if (meta.getImageurl().equals("") || meta.getImageurl().isEmpty()) { - imageView.setVisibility(GONE); + if (!meta.getImageurl().equals("") && !meta.getImageurl().isEmpty()) { + if (!dataSaverDisabled) { + Picasso.get() + .load(R.drawable.ic_web_grey600_48) + .into(imageView); + } else { + imageView.setVisibility(VISIBLE); + Picasso.get() + .load(meta.getImageurl()) + .resize(80, 80) + .onlyScaleDown() + .centerInside() + .placeholder(R.drawable.ic_web_grey600_48) + .into(imageView); + } } else { imageView.setVisibility(VISIBLE); Picasso.get() - .load(meta.getImageurl()) + .load(R.drawable.ic_web_grey600_48) .into(imageView); } if (meta.getTitle().isEmpty() || meta.getTitle().equals("")) { - textViewTitle.setVisibility(GONE); + textViewTitle.setVisibility(VISIBLE); + textViewTitle.setText(meta.getUrl()); } 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 { @@ -143,7 +145,7 @@ public class RichLinkView extends RelativeLayout { isDefaultClick = isDefault; } - public void setClickListener(RichLinkListener richLinkListener1) { + public void setClickListener(RichPreview.RichLinkListener richLinkListener1) { richLinkListener = richLinkListener1; } @@ -156,23 +158,23 @@ public class RichLinkView extends RelativeLayout { public void setLinkFromMeta(MetaData metaData) { meta = metaData; - initView(); + initView(true); } public MetaData getMetaData() { return meta; } - public void setLink(String url, final ViewListener viewListener) { + public void setLink(final String url, final String filename, final boolean dataSaverDisabled, final RichPreview.ViewListener viewListener) { main_url = url; - RichPreview richPreview = new RichPreview(new ResponseListener() { + RichPreview richPreview = new RichPreview(new RichPreview.ResponseListener() { @Override public void onData(MetaData metaData) { meta = metaData; if (!meta.getTitle().isEmpty() || !meta.getTitle().equals("")) { viewListener.onSuccess(true); } - initView(); + initView(dataSaverDisabled); } @Override @@ -180,6 +182,6 @@ public class RichLinkView extends RelativeLayout { viewListener.onError(e); } }); - richPreview.getPreview(url); + richPreview.getPreview(url, filename, context); } } diff --git a/src/main/java/de/pixart/messenger/utils/MetaData.java b/src/main/java/de/pixart/messenger/utils/MetaData.java new file mode 100644 index 000000000..7d6940f4a --- /dev/null +++ b/src/main/java/de/pixart/messenger/utils/MetaData.java @@ -0,0 +1,74 @@ +package de.pixart.messenger.utils; + +/** + * Created by ponna on 16-01-2018. + */ + +import java.io.Serializable; + +public class MetaData implements Serializable { + + private String url = ""; + private String imageurl = ""; + private String title = ""; + private String description = ""; + private String sitename = ""; + private String mediatype = ""; + private String favicon = ""; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getImageurl() { + return imageurl; + } + + public void setImageurl(String imageurl) { + this.imageurl = imageurl; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getSitename() { + return sitename; + } + + public void setSitename(String sitename) { + this.sitename = sitename; + } + + public String getMediatype() { + return mediatype; + } + + public void setMediatype(String mediatype) { + this.mediatype = mediatype; + } + + public String getFavicon() { + return favicon; + } + + public void setFavicon(String favicon) { + this.favicon = favicon; + } +} \ No newline at end of file diff --git a/src/main/java/de/pixart/messenger/utils/RichPreview.java b/src/main/java/de/pixart/messenger/utils/RichPreview.java index 639a02c8d..63835228d 100644 --- a/src/main/java/de/pixart/messenger/utils/RichPreview.java +++ b/src/main/java/de/pixart/messenger/utils/RichPreview.java @@ -1,19 +1,28 @@ package de.pixart.messenger.utils; +import android.content.Context; import android.os.AsyncTask; +import android.view.View; import android.webkit.URLUtil; +import org.json.JSONObject; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStreamReader; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.net.URI; import java.net.URISyntaxException; -import io.github.ponnamkarthik.richlinkpreview.MetaData; -import io.github.ponnamkarthik.richlinkpreview.ResponseListener; +import de.pixart.messenger.Config; /** * Created by ponna on 16-01-2018. @@ -21,134 +30,78 @@ import io.github.ponnamkarthik.richlinkpreview.ResponseListener; public class RichPreview { - MetaData metaData; - ResponseListener responseListener; - String url; + private static final String RICH_LINK_METADATA = "richlink_meta_data"; + private MetaData metaData; + private ResponseListener responseListener; + private String url; + private String filename; + private Context context; public RichPreview(ResponseListener responseListener) { this.responseListener = responseListener; metaData = new MetaData(); } - public void getPreview(String url) { + public void getPreview(final String url, final String filename, final Context context) { this.url = url; - new RichPreview.getData().execute(); + this.filename = filename; + this.context = context; + new getData().execute(); } private class getData extends AsyncTask { @Override protected Void doInBackground(Void... params) { - Document doc = null; + FileInputStream fis = null; + ObjectInputStream is = null; + final File file = new File(context.getCacheDir(), RICH_LINK_METADATA + "/" + filename); try { - doc = Jsoup.connect(url) - .timeout(30 * 1000) - .get(); - - Elements elements = doc.getElementsByTag("meta"); - - // getTitle doc.select("meta[property=og:title]") - String title = doc.select("meta[property=og:title]").attr("content"); - - if (title == null || title.isEmpty()) { - title = doc.title(); + fis = new FileInputStream(file); + InputStreamReader isr = new InputStreamReader(fis); + BufferedReader bufferedReader = new BufferedReader(isr); + StringBuilder sb = new StringBuilder(); + String line; + while ((line = bufferedReader.readLine()) != null) { + sb.append(line); } - metaData.setTitle(title); - - //getDescription - String description = doc.select("meta[name=description]").attr("content"); - if (description.isEmpty() || description == null) { - description = doc.select("meta[name=Description]").attr("content"); + String string = sb.substring(sb.indexOf("{"), sb.lastIndexOf("}") + 1); + JSONObject json = new JSONObject(string); + if (json.has("url")) { + metaData.setUrl(json.getString("url")); } - if (description.isEmpty() || description == null) { - description = doc.select("meta[property=og:description]").attr("content"); + if (json.has("imageurl")) { + metaData.setImageurl(json.getString("imageurl")); } - if (description.isEmpty() || description == null) { - description = ""; + if (json.has("title")) { + metaData.setTitle(json.getString("title")); } - metaData.setDescription(description); - - - // getMediaType - Elements mediaTypes = doc.select("meta[name=medium]"); - String type = ""; - if (mediaTypes.size() > 0) { - String media = mediaTypes.attr("content"); - - type = media.equals("image") ? "photo" : media; - } else { - type = doc.select("meta[property=og:type]").attr("content"); - } - metaData.setMediatype(type); - - - //getImages - Elements imageElements = doc.select("meta[property=og:image]"); - if (imageElements.size() > 0) { - String image = imageElements.attr("content"); - if (!image.isEmpty()) { - metaData.setImageurl(resolveURL(url, image)); - } + if (json.has("description")) { + metaData.setDescription(json.getString("description")); } - if (metaData.getImageurl().isEmpty()) { - String src = doc.select("link[rel=image_src]").attr("href"); - if (!src.isEmpty()) { - metaData.setImageurl(resolveURL(url, src)); - } else { - src = doc.select("link[rel=apple-touch-icon]").attr("href"); - if (!src.isEmpty()) { - metaData.setImageurl(resolveURL(url, src)); - metaData.setFavicon(resolveURL(url, src)); - } else { - src = doc.select("link[rel=icon]").attr("href"); - if (!src.isEmpty()) { - metaData.setImageurl(resolveURL(url, src)); - metaData.setFavicon(resolveURL(url, src)); - } - } - } + if (json.has("sitename")) { + metaData.setSitename(json.getString("sitename")); } - - //Favicon - String src = doc.select("link[rel=apple-touch-icon]").attr("href"); - if (!src.isEmpty()) { - metaData.setFavicon(resolveURL(url, src)); - } else { - src = doc.select("link[rel=icon]").attr("href"); - if (!src.isEmpty()) { - metaData.setFavicon(resolveURL(url, src)); - } + if (json.has("mediatype")) { + metaData.setMediatype(json.getString("mediatype")); } - - for (Element element : elements) { - if (element.hasAttr("property")) { - String str_property = element.attr("property").toString().trim(); - if (str_property.equals("og:url")) { - metaData.setUrl(element.attr("content").toString()); - } - if (str_property.equals("og:site_name")) { - metaData.setSitename(element.attr("content").toString()); - } - } + if (json.has("favicon")) { + metaData.setFavicon(json.getString("favicon")); } - - if (metaData.getUrl().equals("") || metaData.getUrl().isEmpty()) { - URI uri = null; - try { - uri = new URI(url); - } catch (URISyntaxException e) { - e.printStackTrace(); + } catch (Exception e) { + retrieveMeta(url, context); + e.printStackTrace(); + } finally { + try { + if (fis != null) { + fis.close(); } - if (url == null) { - metaData.setUrl(url); - } else { - metaData.setUrl(uri != null ? uri.getHost() : null); + if (is != null) { + is.close(); } + } catch (Exception e) { + e.printStackTrace(); } - - } catch (IOException e) { - e.printStackTrace(); - responseListener.onError(new Exception("No Html Received from " + url + " Check your Internet " + e.getLocalizedMessage())); } return null; } @@ -174,5 +127,173 @@ public class RichPreview { return base_uri != null ? base_uri.toString() : null; } } -} + private void saveMeta(MetaData metaData, Context context) { + final File file = new File(context.getCacheDir(), RICH_LINK_METADATA + "/" + filename); + file.getParentFile().mkdirs(); + FileOutputStream fos = null; + ObjectOutputStream oos = null; + boolean keep = true; + try { + fos = new FileOutputStream(file); + oos = new ObjectOutputStream(fos); + JSONObject json = new JSONObject(); + json.put("url", metaData.getUrl()); + json.put("imageurl", metaData.getImageurl()); + json.put("title", metaData.getTitle()); + json.put("description", metaData.getDescription()); + json.put("sitename", metaData.getSitename()); + json.put("mediatype", metaData.getMediatype()); + json.put("favicon", metaData.getFavicon()); + oos.writeObject(json.toString()); + } catch (Exception e) { + e.printStackTrace(); + keep = false; + } finally { + try { + if (oos != null) oos.close(); + if (fos != null) fos.close(); + if (!keep) file.delete(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private void retrieveMeta(String url, Context context) { + Document doc = null; + try { + doc = Jsoup.connect(url) + .timeout(Config.CONNECT_TIMEOUT * 1000) + .get(); + } catch (IOException e) { + e.printStackTrace(); + } + + Elements elements = null; + if (doc != null) { + elements = doc.getElementsByTag("meta"); + + // getTitle doc.select("meta[property=og:title]") + String title = doc.select("meta[property=og:title]").attr("content"); + + if (title == null || title.isEmpty()) { + title = doc.title(); + } + metaData.setTitle(title); + + //getDescription + String description = doc.select("meta[name=description]").attr("content"); + if (description == null || description.isEmpty()) { + description = doc.select("meta[name=Description]").attr("content"); + } + if (description == null || description.isEmpty()) { + description = doc.select("meta[property=og:description]").attr("content"); + } + if (description == null || description.isEmpty()) { + description = ""; + } + metaData.setDescription(description); + + + // getMediaType + Elements mediaTypes = doc.select("meta[name=medium]"); + String type = ""; + if (mediaTypes.size() > 0) { + String media = mediaTypes.attr("content"); + + type = media.equals("image") ? "photo" : media; + } else { + type = doc.select("meta[property=og:type]").attr("content"); + } + metaData.setMediatype(type); + + + //getImages + Elements imageElements = doc.select("meta[property=og:image]"); + if (imageElements.size() > 0) { + String image = imageElements.attr("content"); + if (!image.isEmpty()) { + metaData.setImageurl(resolveURL(url, image)); + } + } + if (metaData.getImageurl().isEmpty()) { + String src = doc.select("link[rel=image_src]").attr("href"); + if (!src.isEmpty()) { + metaData.setImageurl(resolveURL(url, src)); + } else { + src = doc.select("link[rel=apple-touch-icon]").attr("href"); + if (!src.isEmpty()) { + metaData.setImageurl(resolveURL(url, src)); + metaData.setFavicon(resolveURL(url, src)); + } else { + src = doc.select("link[rel=icon]").attr("href"); + if (!src.isEmpty()) { + metaData.setImageurl(resolveURL(url, src)); + metaData.setFavicon(resolveURL(url, src)); + } + } + } + } + + //Favicon + String src = doc.select("link[rel=apple-touch-icon]").attr("href"); + if (!src.isEmpty()) { + metaData.setFavicon(resolveURL(url, src)); + } else { + src = doc.select("link[rel=icon]").attr("href"); + if (!src.isEmpty()) { + metaData.setFavicon(resolveURL(url, src)); + } + } + } + + if (elements != null) { + for (Element element : elements) { + if (element.hasAttr("property")) { + String str_property = element.attr("property").trim(); + if (str_property.equals("og:url")) { + metaData.setUrl(element.attr("content")); + } + if (str_property.equals("og:site_name")) { + metaData.setSitename(element.attr("content")); + } + } + } + } + + if (metaData.getUrl().equals("") || metaData.getUrl().isEmpty()) { + URI uri = null; + try { + uri = new URI(url); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + if (url == null) { + metaData.setUrl(url); + } else { + metaData.setUrl(uri != null ? uri.getHost() : null); + } + } + saveMeta(metaData, context); + } + + public interface ResponseListener { + + void onData(MetaData metaData); + + void onError(Exception e); + } + + public interface RichLinkListener { + + void onClicked(View view, MetaData meta); + } + + public interface ViewListener { + + void onSuccess(boolean status); + + void onError(Exception e); + } +} \ No newline at end of file diff --git a/src/main/res/drawable-hdpi/ic_web_grey600_48.png b/src/main/res/drawable-hdpi/ic_web_grey600_48.png new file mode 100644 index 000000000..6f5d6d238 Binary files /dev/null and b/src/main/res/drawable-hdpi/ic_web_grey600_48.png differ diff --git a/src/main/res/drawable-mdpi/ic_web_grey600_48.png b/src/main/res/drawable-mdpi/ic_web_grey600_48.png new file mode 100644 index 000000000..0aa17eabf Binary files /dev/null and b/src/main/res/drawable-mdpi/ic_web_grey600_48.png differ diff --git a/src/main/res/drawable-xhdpi/ic_web_grey600_48.png b/src/main/res/drawable-xhdpi/ic_web_grey600_48.png new file mode 100644 index 000000000..51d89ff49 Binary files /dev/null and b/src/main/res/drawable-xhdpi/ic_web_grey600_48.png differ diff --git a/src/main/res/drawable-xxhdpi/ic_web_grey600_48.png b/src/main/res/drawable-xxhdpi/ic_web_grey600_48.png new file mode 100644 index 000000000..cab977e14 Binary files /dev/null and b/src/main/res/drawable-xxhdpi/ic_web_grey600_48.png differ diff --git a/src/main/res/drawable-xxxhdpi/ic_web_grey600_48.png b/src/main/res/drawable-xxxhdpi/ic_web_grey600_48.png new file mode 100644 index 000000000..095e00936 Binary files /dev/null and b/src/main/res/drawable-xxxhdpi/ic_web_grey600_48.png differ diff --git a/src/main/res/layout/link_layout.xml b/src/main/res/layout/link_layout.xml index 68e7a6cc7..bdd7469be 100644 --- a/src/main/res/layout/link_layout.xml +++ b/src/main/res/layout/link_layout.xml @@ -5,27 +5,26 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" - android:gravity="center" - android:orientation="horizontal"> + android:gravity="center"> + android:orientation="vertical"> @@ -33,23 +32,12 @@ - - \ 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 be2bbf3db..bf96cef95 100644 --- a/src/main/res/layout/message_content.xml +++ b/src/main/res/layout/message_content.xml @@ -31,7 +31,8 @@ + android:layout_height="wrap_content" + android:maxHeight="80dp" />