Commit fef9ccd9 authored by Yusuke Iwaki's avatar Yusuke Iwaki

show urls in message.

parent b022e68b
......@@ -98,7 +98,7 @@ dependencies {
compile 'com.google.firebase:firebase-crash:10.0.0'
compile 'com.squareup.okhttp3:okhttp:3.4.1'
compile 'com.squareup.picasso:picasso:2.5.2'
compile rootProject.ext.picasso
compile 'com.facebook.stetho:stetho:1.4.1'
compile 'com.facebook.stetho:stetho-okhttp3:1.4.1'
......
......@@ -10,7 +10,9 @@ import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.model.SyncState;
import chat.rocket.android.realm_helper.RealmModelViewHolder;
import chat.rocket.android.renderer.MessageRenderer;
import chat.rocket.android.widget.message.RocketChatMessageAttachmentsLayout;
import chat.rocket.android.widget.message.RocketChatMessageLayout;
import chat.rocket.android.widget.message.RocketChatMessageUrlsLayout;
/**
* View holder of NORMAL chat message.
......@@ -22,6 +24,8 @@ public class MessageViewHolder extends RealmModelViewHolder<PairedMessage> {
private final View userAndTimeContainer;
private final String hostname;
private final RocketChatMessageLayout body;
private final RocketChatMessageUrlsLayout urls;
private final RocketChatMessageAttachmentsLayout attachments;
private final View newDayContainer;
private final TextView newDayText;
......@@ -35,6 +39,9 @@ public class MessageViewHolder extends RealmModelViewHolder<PairedMessage> {
timestamp = (TextView) itemView.findViewById(R.id.timestamp);
userAndTimeContainer = itemView.findViewById(R.id.user_and_timestamp_container);
body = (RocketChatMessageLayout) itemView.findViewById(R.id.message_body);
urls = (RocketChatMessageUrlsLayout) itemView.findViewById(R.id.message_urls);
attachments =
(RocketChatMessageAttachmentsLayout) itemView.findViewById(R.id.message_attachments);
newDayContainer = itemView.findViewById(R.id.newday_container);
newDayText = (TextView) itemView.findViewById(R.id.newday_text);
this.hostname = hostname;
......@@ -48,7 +55,9 @@ public class MessageViewHolder extends RealmModelViewHolder<PairedMessage> {
.avatarInto(avatar, hostname)
.usernameInto(username)
.timestampInto(timestamp)
.bodyInto(body);
.bodyInto(body)
.urlsInto(urls)
.attachmentsInto(attachments);
if (pairedMessage.target != null) {
int syncstate = pairedMessage.target.getSyncstate();
......
package chat.rocket.android.renderer;
import android.content.Context;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import chat.rocket.android.R;
import chat.rocket.android.helper.DateTime;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.model.SyncState;
import chat.rocket.android.model.ddp.Message;
import chat.rocket.android.widget.message.RocketChatMessageAttachmentsLayout;
import chat.rocket.android.widget.message.RocketChatMessageLayout;
import chat.rocket.android.widget.message.RocketChatMessageUrlsLayout;
/**
* Renderer for Message model.
......@@ -77,4 +81,43 @@ public class MessageRenderer extends AbstractRenderer<Message> {
return this;
}
/**
* show urls in RocketChatMessageUrlsLayout.
*/
public MessageRenderer urlsInto(RocketChatMessageUrlsLayout urlsLayout) {
if (!shouldHandle(urlsLayout)) {
return this;
}
String urls = object.getUrls();
if (TextUtils.isEmpty(urls)) {
urlsLayout.setVisibility(View.GONE);
} else {
urlsLayout.setVisibility(View.VISIBLE);
urlsLayout.setUrls(urls);
}
return this;
}
/**
* show urls in RocketChatMessageUrlsLayout.
*/
public MessageRenderer attachmentsInto(RocketChatMessageAttachmentsLayout attachmentsLayout) {
if (!shouldHandle(attachmentsLayout)) {
return this;
}
String attachments = object.getAttachments();
if (TextUtils.isEmpty(attachments)) {
attachmentsLayout.setVisibility(View.GONE);
} else {
attachmentsLayout.setVisibility(View.VISIBLE);
attachmentsLayout.setAttachments(attachments);
}
return this;
}
}
......@@ -56,6 +56,14 @@
android:id="@+id/message_body"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<chat.rocket.android.widget.message.RocketChatMessageUrlsLayout
android:id="@+id/message_urls"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<chat.rocket.android.widget.message.RocketChatMessageAttachmentsLayout
android:id="@+id/message_attachments"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
......@@ -17,6 +17,7 @@ ext {
rxJava = 'io.reactivex:rxjava:1.2.2'
boltsTask = 'com.parse.bolts:bolts-tasks:1.4.0'
timber = 'com.jakewharton.timber:timber:4.3.1'
picasso = 'com.squareup.picasso:picasso:2.5.2'
}
subprojects { project ->
......
......@@ -40,4 +40,5 @@ dependencies {
compile rootProject.ext.supportAppCompat
compile rootProject.ext.supportDesign
compile 'org.nibor.autolink:autolink:0.5.0'
compile rootProject.ext.picasso
}
package chat.rocket.android.widget.message;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.LinearLayout;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
*/
public class RocketChatMessageAttachmentsLayout extends LinearLayout {
private LayoutInflater inflater;
public RocketChatMessageAttachmentsLayout(Context context) {
super(context);
initialize(context, null);
}
public RocketChatMessageAttachmentsLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context, attrs);
}
public RocketChatMessageAttachmentsLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public RocketChatMessageAttachmentsLayout(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initialize(context, attrs);
}
private void initialize(Context context, AttributeSet attrs) {
inflater = LayoutInflater.from(context);
setOrientation(VERTICAL);
}
public void setAttachments(String attachmentsString) {
removeAllViews();
try {
JSONArray attachments = new JSONArray(attachmentsString);
for (int i = 0; i < attachments.length(); i++) {
JSONObject attachment = attachments.getJSONObject(i);
appendAttachmentView(attachment);
}
} catch (JSONException exception) {
return;
}
}
private void appendAttachmentView(JSONObject attachmentObj) throws JSONException {
}
}
package chat.rocket.android.widget.message;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import chat.rocket.android.widget.R;
import com.squareup.picasso.Picasso;
import java.util.HashSet;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
*/
public class RocketChatMessageUrlsLayout extends LinearLayout {
private static final HashSet<String> SUPPORTED_IMAGE_FORMATS = new HashSet<String>() {
{
add("image/png");
add("image/jpg");
add("image/jpeg");
add("image/webp");
}
};
private LayoutInflater inflater;
public RocketChatMessageUrlsLayout(Context context) {
super(context);
initialize(context, null);
}
public RocketChatMessageUrlsLayout(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context, attrs);
}
public RocketChatMessageUrlsLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public RocketChatMessageUrlsLayout(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initialize(context, attrs);
}
private void initialize(Context context, AttributeSet attrs) {
inflater = LayoutInflater.from(context);
setOrientation(VERTICAL);
}
public void setUrls(String urlsString) {
removeAllViews();
try {
JSONArray urls = new JSONArray(urlsString);
for (int i = 0; i < urls.length(); i++) {
JSONObject url = urls.getJSONObject(i);
appendUrlView(url);
}
} catch (JSONException exception) {
return;
}
}
private void appendUrlView(JSONObject urlObj) throws JSONException {
final String url = urlObj.getString("url");
String contentType = urlObj.getJSONObject("headers").getString("contentType");
if (contentType.startsWith("image/") && SUPPORTED_IMAGE_FORMATS.contains(contentType)) {
View inlineImage = inflater.inflate(R.layout.message_inline_image, this, false);
Picasso.with(getContext())
.load(url)
.placeholder(R.drawable.image_dummy)
.error(R.drawable.image_error)
.into((ImageView) inlineImage.findViewById(R.id.message_inline_image));
addView(inlineImage);
}
// see Rocket.Chat:packages/rocketchat-oembed/client/oembedUrlWidget.coffee
if (!urlObj.isNull("meta")) {
JSONObject meta = urlObj.getJSONObject("meta");
String title = null;
if (!meta.isNull("ogTitle")) {
title = meta.getString("ogTitle");
} else if (!meta.isNull("twitterTitle")) {
title = meta.getString("twitterTitle");
} else if (!meta.isNull("pageTitle")) {
title = meta.getString("pageTitle");
}
String description = null;
if (!meta.isNull("ogDescription")) {
description = meta.getString("ogDescription");
} else if (!meta.isNull("twitterDescription")) {
description = meta.getString("twitterDescription");
} else if (!meta.isNull("description")) {
description = meta.getString("description");
}
if (description != null) {
if (description.startsWith("\"")) {
description = description.substring(1);
}
if (description.endsWith("\"")) {
description = description.substring(0, description.length() - 1);
}
}
String imageURL = null;
if (!meta.isNull("ogImage")) {
imageURL = meta.getString("ogImage");
} else if (!meta.isNull("twitterImage")) {
imageURL = meta.getString("twitterImage");
}
String host = urlObj.getJSONObject("parsedUrl").getString("host");
View embedUrl = inflater.inflate(R.layout.message_inline_embed_url, this, false);
((TextView) embedUrl.findViewById(R.id.hostname)).setText(host);
((TextView) embedUrl.findViewById(R.id.title)).setText(title);
((TextView) embedUrl.findViewById(R.id.description)).setText(description);
ImageView image = (ImageView) embedUrl.findViewById(R.id.image);
if (TextUtils.isEmpty(imageURL)) {
image.setVisibility(View.GONE);
} else {
Picasso.with(getContext())
.load(imageURL)
.placeholder(R.drawable.image_dummy)
.error(R.drawable.image_error)
.into(image);
image.setVisibility(View.VISIBLE);
}
embedUrl.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(intent);
}
});
addView(embedUrl);
}
}
}
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="80dp"
android:height="45dp"
android:viewportWidth="80.0"
android:viewportHeight="45.0">
<path
android:pathData="M0,0h80v45h-80z"
android:strokeColor="#00000000"
android:fillColor="#C3D1DA"
android:strokeWidth="1"/>
<path
android:pathData="M43.99,16.75C44.34,16.75 44.64,16.87 44.88,17.12C45.13,17.36 45.25,17.66 45.25,18.01L45.25,26.74C45.25,27.09 45.13,27.39 44.88,27.63C44.64,27.88 44.34,28 43.99,28L35.26,28C34.91,28 34.61,27.88 34.37,27.63C34.12,27.39 34,27.09 34,26.74L34,18.01C34,17.66 34.12,17.36 34.37,17.12C34.61,16.87 34.91,16.75 35.26,16.75L43.99,16.75ZM43.99,26.74L43.99,18.01L35.26,18.01L35.26,26.74L43.99,26.74ZM40.86,22.55L43.05,25.51L36.2,25.51L37.9,23.28L39.13,24.78L40.86,22.55Z"
android:strokeColor="#00000000"
android:fillColor="#5D8298"
android:strokeWidth="1"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="80dp"
android:height="45dp"
android:viewportWidth="80.0"
android:viewportHeight="45.0">
<path
android:pathData="M0,0h80v45h-80z"
android:strokeColor="#00000000"
android:fillColor="#C3D1DA"
android:strokeWidth="1"/>
<path
android:pathData="M33,28L39.88,16.13L46.74,28L33,28ZM40.5,26.13L40.5,24.87L39.24,24.87L39.24,26.13L40.5,26.13ZM40.5,23.63L40.5,21.12L39.24,21.12L39.24,23.63L40.5,23.63Z"
android:strokeColor="#00000000"
android:fillColor="#5D8298"
android:strokeWidth="1"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<stroke android:color="@color/inline_attachment_box_outline" android:width="1dp"/>
<solid android:color="@color/inline_attachment_box_background"/>
<corners android:radius="2dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="?attr/selectableItemBackground"
android:layout_margin="4dp"
android:padding="4dp">
<View
android:layout_width="3dp"
android:layout_height="match_parent"
android:layout_marginEnd="5dp"
android:background="#FFCCCCCC"/>
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxHeight="60dp"
android:layout_marginTop="2dp"
android:layout_marginEnd="8dp"
android:adjustViewBounds="true"
android:scaleType="fitStart"/>
<LinearLayout
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/hostname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
android:enabled="false"/>
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
android:textAppearance="@style/TextAppearance.RocketChat.MessageUrl.Title"/>
<TextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
android:textAppearance="@style/TextAppearance.RocketChat.MessageUrl.Description"/>
</LinearLayout>
</LinearLayout>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/inline_attachment_background"
android:layout_margin="4dp"
android:padding="4dp">
<ImageView
android:id="@+id/message_inline_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxHeight="200dp"
android:adjustViewBounds="true"
android:scaleType="fitStart"/>
</FrameLayout>
......@@ -10,7 +10,24 @@
<item name="android:textStyle">bold</item>
</style>
<style name="TextAppearance.RocketChat.MessageUrl" parent="TextAppearance.AppCompat.Body1"/>
<style name="TextAppearance.RocketChat.MessageUrl.Title" parent="TextAppearance.AppCompat.Title">
<item name="android:textSize">14sp</item>
<item name="android:textColor">?android:attr/textColorLink</item>
</style>
<style name="TextAppearance.RocketChat.MessageUrl.Description">
<item name="android:textSize">12sp</item>
</style>
<style name="TextAppearance.RocketChat.MessageUrl.Hostname"
parent="TextAppearance.AppCompat.Caption">
<item name="android:textSize">8sp</item>
</style>
<color name="highlight_text_color">#333</color>
<color name="highlight_text_background_color">#f8f8f8</color>
<color name="highlight_text_border_color">#ccc</color>
<color name="inline_attachment_box_outline">#FFF0F0F0</color>
<color name="inline_attachment_box_background">@android:color/white</color>
</resources>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment