Commit 1a19e91d authored by Yusuke Iwaki's avatar Yusuke Iwaki

Merge branch 'message_url_attachment' into develop

parents 621937c6 44ca5cc9
......@@ -97,8 +97,8 @@ dependencies {
compile 'com.google.firebase:firebase-core:10.0.0'
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.okhttp3
compile rootProject.ext.picasso
compile 'com.facebook.stetho:stetho:1.4.1'
compile 'com.facebook.stetho:stetho-okhttp3:1.4.1'
......
......@@ -23,7 +23,9 @@ import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.model.SyncState;
import chat.rocket.android.model.ddp.Message;
import chat.rocket.android.model.ddp.RoomSubscription;
import chat.rocket.android.model.ddp.User;
import chat.rocket.android.model.internal.LoadMessageProcedure;
import chat.rocket.android.model.internal.Session;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.realm_helper.RealmModelListAdapter;
import chat.rocket.android.realm_helper.RealmObjectObserver;
......@@ -48,6 +50,8 @@ public class RoomFragment extends AbstractChatRoomFragment
private String roomId;
private RealmObjectObserver<RoomSubscription> roomObserver;
private String hostname;
private String userId;
private String token;
private LoadMoreScrollListener scrollListener;
private RealmObjectObserver<LoadMessageProcedure> procedureObserver;
private MessageComposerManager messageComposerManager;
......@@ -79,6 +83,10 @@ public class RoomFragment extends AbstractChatRoomFragment
.equalTo("serverConfigId", serverConfigId)
.isNotNull("hostname")
.findFirst()).getHostname();
userId = realmHelper.executeTransactionForRead(realm ->
User.queryCurrentUser(realm).findFirst()).get_id();
token = realmHelper.executeTransactionForRead(realm ->
realm.where(Session.class).equalTo("sessionId", Session.DEFAULT_ID).findFirst()).getToken();
roomObserver = realmHelper
.createObjectObserver(realm -> realm.where(RoomSubscription.class).equalTo("rid", roomId))
.setOnUpdateListener(this::onRenderRoom);
......@@ -102,7 +110,7 @@ public class RoomFragment extends AbstractChatRoomFragment
realm -> realm.where(Message.class)
.equalTo("rid", roomId)
.findAllSorted("ts", Sort.DESCENDING),
context -> new MessageListAdapter(context, hostname)
context -> new MessageListAdapter(context, hostname, userId, token)
);
listView.setAdapter(adapter);
adapter.setOnItemClickListener(this);
......
......@@ -15,12 +15,16 @@ import java.util.List;
public class MessageListAdapter
extends ExtRealmModelListAdapter<Message, PairedMessage, MessageViewHolder> {
private final String hostname;
private final String userId;
private final String token;
private boolean hasNext;
private boolean isLoaded;
public MessageListAdapter(Context context, String hostname) {
public MessageListAdapter(Context context, String hostname, String userId, String token) {
super(context);
this.hostname = hostname;
this.userId = userId;
this.token = token;
}
/**
......@@ -53,7 +57,7 @@ public class MessageListAdapter
}
@Override protected MessageViewHolder onCreateRealmModelViewHolder(int viewType, View itemView) {
return new MessageViewHolder(itemView, hostname);
return new MessageViewHolder(itemView, hostname, userId, token);
}
@Override protected List<PairedMessage> mapResultsToViewModel(List<Message> results) {
......
......@@ -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.
......@@ -21,23 +23,32 @@ public class MessageViewHolder extends RealmModelViewHolder<PairedMessage> {
private final TextView timestamp;
private final View userAndTimeContainer;
private final String hostname;
private final String userId;
private final String token;
private final RocketChatMessageLayout body;
private final RocketChatMessageUrlsLayout urls;
private final RocketChatMessageAttachmentsLayout attachments;
private final View newDayContainer;
private final TextView newDayText;
/**
* constructor WITH hostname.
*/
public MessageViewHolder(View itemView, String hostname) {
public MessageViewHolder(View itemView, String hostname, String userId, String token) {
super(itemView);
avatar = (ImageView) itemView.findViewById(R.id.user_avatar);
username = (TextView) itemView.findViewById(R.id.username);
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;
this.userId = userId;
this.token = token;
}
/**
......@@ -48,7 +59,9 @@ public class MessageViewHolder extends RealmModelViewHolder<PairedMessage> {
.avatarInto(avatar, hostname)
.usernameInto(username)
.timestampInto(timestamp)
.bodyInto(body);
.bodyInto(body)
.urlsInto(urls)
.attachmentsInto(attachments, hostname, userId, token);
if (pairedMessage.target != null) {
int syncstate = pairedMessage.target.getSyncstate();
......
package chat.rocket.android.model.ddp;
import chat.rocket.android.model.SyncState;
import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
import org.json.JSONException;
......@@ -23,8 +22,8 @@ public class Message extends RealmObject {
private String msg;
private User u;
private boolean groupable;
private RealmList<MessageAttachment> attachments;
private RealmList<MessageUrl> urls;
private String attachments; //JSONArray.
private String urls; //JSONArray.
public String get_id() {
return _id;
......@@ -90,19 +89,19 @@ public class Message extends RealmObject {
this.groupable = groupable;
}
public RealmList<MessageAttachment> getAttachments() {
public String getAttachments() {
return attachments;
}
public void setAttachments(RealmList<MessageAttachment> attachments) {
public void setAttachments(String attachments) {
this.attachments = attachments;
}
public RealmList<MessageUrl> getUrls() {
public String getUrls() {
return urls;
}
public void setUrls(RealmList<MessageUrl> urls) {
public void setUrls(String urls) {
this.urls = urls;
}
......
package chat.rocket.android.model.ddp;
import io.realm.RealmObject;
/**
* Attachment.
*/
@SuppressWarnings({"PMD.ShortClassName", "PMD.ShortVariable",
"PMD.MethodNamingConventions", "PMD.VariableNamingConventions"})
public class MessageAttachment extends RealmObject {
private String title;
private String title_url;
private String image_url;
private String image_type;
private String image_size;
}
package chat.rocket.android.model.ddp;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
/**
* Url.
*/
@SuppressWarnings({"PMD.ShortClassName", "PMD.ShortVariable",
"PMD.MethodNamingConventions", "PMD.VariableNamingConventions"})
public class MessageUrl extends RealmObject {
@PrimaryKey private String url;
private String parsedUrl;
}
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,46 @@ 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,
String hostname, String userId, String token) {
if (!shouldHandle(attachmentsLayout)) {
return this;
}
String attachments = object.getAttachments();
if (TextUtils.isEmpty(attachments)) {
attachmentsLayout.setVisibility(View.GONE);
} else {
attachmentsLayout.setVisibility(View.VISIBLE);
attachmentsLayout.setHostname(hostname);
attachmentsLayout.setCredential(userId, token);
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,9 @@ 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'
okhttp3 = 'com.squareup.okhttp3:okhttp:3.4.1'
picasso = 'com.squareup.picasso:picasso:2.5.2'
picasso2Okhttp3Downloader = 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
}
subprojects { project ->
......
......@@ -40,4 +40,7 @@ dependencies {
compile rootProject.ext.supportAppCompat
compile rootProject.ext.supportDesign
compile 'org.nibor.autolink:autolink:0.5.0'
compile rootProject.ext.okhttp3
compile rootProject.ext.picasso
compile rootProject.ext.picasso2Okhttp3Downloader
}
package chat.rocket.android.widget.helper;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
*/
public interface ImageFormat {
String PNG = "image/png";
String JPG = "image/jpg";
String JPEG = "image/jpeg";
String WEBP = "image/webp";
List<String> SUPPORTED_LIST = Collections.unmodifiableList(new ArrayList<String>() {
{
add(PNG);
add(JPG);
add(JPEG);
add(WEBP);
}
});
}
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 chat.rocket.android.widget.helper.ImageFormat;
import com.jakewharton.picasso.OkHttp3Downloader;
import com.squareup.picasso.Picasso;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
*/
public class RocketChatMessageAttachmentsLayout extends LinearLayout {
private LayoutInflater inflater;
private String hostname;
private String attachmentsString;
private String userId;
private String token;
private OkHttp3Downloader downloader;
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 setHostname(String hostname) {
this.hostname = hostname;
}
public void setCredential(String userId, String token) {
this.userId = userId;
this.token = token;
}
private OkHttp3Downloader getDownloader() {
if (downloader == null) {
Interceptor interceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
// uid/token is required to download attachment files.
// see: RocketChat:lib/fileUpload.coffee
Request newRequest = chain.request().newBuilder()
.header("Cookie", "rc_uid=" + userId + ";rc_token=" + token)
.build();
return chain.proceed(newRequest);
}
};
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
downloader = new OkHttp3Downloader(okHttpClient);
}
return downloader;
}
public void setAttachments(String attachmentsString) {
if (this.attachmentsString != null && this.attachmentsString.equals(attachmentsString)) {
return;
}
this.attachmentsString = 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 {
if (attachmentObj.isNull("image_url")) {
return;
}
String imageURL = attachmentObj.getString("image_url");
String imageType = attachmentObj.getString("image_type");
if (TextUtils.isEmpty(imageURL)
|| !imageType.startsWith("image/")
|| !ImageFormat.SUPPORTED_LIST.contains(imageType)) {
return;
}
View attachmentView = inflater.inflate(R.layout.message_inline_attachment, this, false);
new Picasso.Builder(getContext())
.downloader(getDownloader())
.build()
.load(absolutize(imageURL))
.placeholder(R.drawable.image_dummy)
.error(R.drawable.image_error)
.into((ImageView) attachmentView.findViewById(R.id.image));
TextView titleView = (TextView) attachmentView.findViewById(R.id.title);
if (attachmentObj.isNull("title")) {
titleView.setVisibility(View.GONE);
} else {
titleView.setVisibility(View.VISIBLE);
titleView.setText(attachmentObj.getString("title"));
if (attachmentObj.isNull("title_link")) {
titleView.setOnClickListener(null);
titleView.setClickable(false);
} else {
final String link = absolutize(attachmentObj.getString("title_link"));
titleView.setOnClickListener(new OnClickListener() {
@Override public void onClick(View view) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(link));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
view.getContext().startActivity(intent);
}
});
}
}
addView(attachmentView);
}
private String absolutize(String url) {
return url.startsWith("/") ? "https://" + hostname + url : url;
}
}
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 chat.rocket.android.widget.helper.ImageFormat;
import com.squareup.picasso.Picasso;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
*/
public class RocketChatMessageUrlsLayout extends LinearLayout {
private LayoutInflater inflater;
private String urlsString;
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) {
if (this.urlsString != null && this.urlsString.equals(urlsString)) {
return;
}
this.urlsString = 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/") && ImageFormat.SUPPORTED_LIST.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:layout_margin="4dp"
android:padding="4dp">
<View
android:layout_width="3dp"
android:layout_height="match_parent"
android:layout_marginRight="5dp"
android:background="@color/inline_attachment_quote_line"/>
<LinearLayout
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<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.MessageAttachment.Title"
android:background="?attr/selectableItemBackground"/>
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxHeight="200dp"
android:layout_marginTop="4dp"
android:layout_marginRight="8dp"
android:adjustViewBounds="true"
android:scaleType="fitStart"/>
</LinearLayout>
</LinearLayout>
<?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="@color/inline_attachment_quote_line"/>
<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.MessageAttachment.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.MessageAttachment.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,25 @@
<item name="android:textStyle">bold</item>
</style>
<style name="TextAppearance.RocketChat.MessageAttachment" parent="TextAppearance.AppCompat.Body1"/>
<style name="TextAppearance.RocketChat.MessageAttachment.Title" parent="TextAppearance.AppCompat.Title">
<item name="android:textSize">14sp</item>
<item name="android:textColor">?android:attr/textColorLink</item>
</style>
<style name="TextAppearance.RocketChat.MessageAttachment.Description">
<item name="android:textSize">12sp</item>
</style>
<style name="TextAppearance.RocketChat.MessageAttachment.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_quote_line">#FFCCCCCC</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