浏览代码

Merge pull request #399 from nextcloud/fix-398

Fix #398
Mario Đanić 6 年之前
父节点
当前提交
7bb0c79b89
共有 26 个文件被更改,包括 420 次插入218 次删除
  1. 13 7
      app/build.gradle
  2. 21 11
      app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java
  3. 4 4
      app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.java
  4. 2 2
      app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.java
  5. 19 20
      app/src/main/java/com/nextcloud/talk/adapters/messages/MagicPreviewMessageViewHolder.java
  6. 20 0
      app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.java
  7. 22 45
      app/src/main/java/com/nextcloud/talk/controllers/ChatController.java
  8. 1 1
      app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.java
  9. 1 1
      app/src/main/java/com/nextcloud/talk/jobs/AccountRemovalWorker.java
  10. 1 1
      app/src/main/java/com/nextcloud/talk/jobs/CapabilitiesWorker.java
  11. 1 1
      app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java
  12. 1 1
      app/src/main/java/com/nextcloud/talk/jobs/PushRegistrationWorker.java
  13. 1 1
      app/src/main/java/com/nextcloud/talk/jobs/SignalingSettingsJob.java
  14. 1 1
      app/src/main/java/com/nextcloud/talk/jobs/WebsocketConnectionsWorker.java
  15. 75 0
      app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java
  16. 79 0
      app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java
  17. 42 0
      app/src/main/java/com/nextcloud/talk/utils/OkHttpNetworkFetcherWithCache.java
  18. 54 1
      app/src/main/java/com/nextcloud/talk/utils/TextMatchers.java
  19. 0 32
      app/src/main/res/drawable/shape_preview_text_incoming_message.xml
  20. 0 32
      app/src/main/res/drawable/shape_preview_text_outcoming_message.xml
  21. 22 19
      app/src/main/res/layout/item_custom_incoming_preview_message.xml
  22. 2 1
      app/src/main/res/layout/item_custom_incoming_text_message.xml
  23. 30 36
      app/src/main/res/layout/item_custom_outcoming_preview_message.xml
  24. 0 1
      app/src/main/res/layout/item_custom_outcoming_text_message.xml
  25. 1 0
      app/src/main/res/layout/view_message_input.xml
  26. 7 0
      app/src/main/res/values/strings.xml

+ 13 - 7
app/build.gradle

@@ -107,10 +107,10 @@ dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar'])
     implementation 'androidx.appcompat:appcompat:1.0.2'
     implementation 'com.google.android.material:material:1.0.0'
-    implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha2'
+    implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3'
     implementation 'androidx.emoji:emoji-bundled:1.0.0'
     implementation 'org.michaelevans.colorart:library:0.0.3'
-    implementation "android.arch.work:work-runtime:${workVersion}"
+    implementation "android.arch.work:work-runtime:1.0.0-beta01"
     implementation "android.arch.work:work-firebase:${workVersion}"
     androidTestImplementation "android.arch.work:work-testing:${workVersion}"
 
@@ -154,11 +154,11 @@ dependencies {
 
     implementation 'net.orange-box.storebox:storebox-lib:1.4.0'
 
-    compileOnly "org.projectlombok:lombok:1.18.2"
-    annotationProcessor "org.projectlombok:lombok:1.18.2"
+    compileOnly "org.projectlombok:lombok:1.18.4"
+    annotationProcessor "org.projectlombok:lombok:1.18.4"
 
-    implementation 'com.jakewharton:butterknife:9.0.0-rc1'
-    annotationProcessor 'com.jakewharton:butterknife-compiler:9.0.0-rc1'
+    implementation 'com.jakewharton:butterknife:9.0.0-rc2'
+    annotationProcessor 'com.jakewharton:butterknife-compiler:9.0.0-rc2'
 
     implementation 'com.github.HITGIF:TextFieldBoxes:1.4.3'
 
@@ -168,6 +168,11 @@ dependencies {
     implementation 'com.github.bumptech.glide:glide:4.8.0'
     annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
     implementation 'com.github.bumptech.glide:okhttp3-integration:4.8.0@aar'
+    implementation 'com.facebook.fresco:fresco:1.11.0'
+    implementation 'com.facebook.fresco:animated-webp:1.11.0'
+    implementation 'com.facebook.fresco:webpsupport:1.11.0'
+    implementation 'com.facebook.fresco:animated-gif:1.11.0'
+    implementation "com.facebook.fresco:imagepipeline-okhttp3:1.11.0"
     implementation 'org.webrtc:google-webrtc:1.0.23295'
     implementation "org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}"
 
@@ -181,7 +186,7 @@ dependencies {
 
     implementation 'com.github.wooplr:Spotlight:1.3'
 
-    implementation 'com.github.mario:Chatkit:31d75fd532'
+    implementation 'com.github.mario:chatkit:628c909ef4'
 
     implementation 'com.otaliastudios:autocomplete:1.1.0'
 
@@ -194,6 +199,7 @@ dependencies {
 
     implementation 'uk.co.chrisjenx:calligraphy:2.3.0'
 
+    implementation group: 'eu.medsea.mimeutil', name: 'mime-util', version: '2.1.3'
     testImplementation 'junit:junit:4.12'
     androidTestImplementation ('androidx.test.espresso:espresso-core:3.1.0-alpha4', {
         exclude group: 'com.android.support', module: 'support-annotations'

+ 21 - 11
app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java

@@ -40,6 +40,7 @@ import com.bumptech.glide.request.RequestOptions;
 import com.nextcloud.talk.R;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.models.database.UserEntity;
+import com.nextcloud.talk.models.json.chat.ChatMessage;
 import com.nextcloud.talk.models.json.rooms.Conversation;
 import com.nextcloud.talk.utils.ApiUtils;
 import com.nextcloud.talk.utils.glide.GlideApp;
@@ -125,7 +126,7 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
             holder.dialogUnreadBubble.setVisibility(View.GONE);
         }
 
-        String authorDisplayName = "";
+        String authorDisplayName;
 
         if (conversation.isHasPassword()) {
             holder.passwordProtectedRoomImageView.setVisibility(View.VISIBLE);
@@ -144,38 +145,45 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
             holder.dialogDate.setText(DateUtils.getRelativeTimeSpanString(conversation.getLastActivity() * 1000L,
                     System.currentTimeMillis(), 0, DateUtils.FORMAT_ABBREV_RELATIVE));
 
-            if (conversation.getType() == Conversation.RoomType.ROOM_TYPE_ONE_TO_ONE_CALL || !(TextUtils.isEmpty(conversation.getLastMessage().getSystemMessage()))) {
+            if (!TextUtils.isEmpty(conversation.getLastMessage().getSystemMessage())) {
                 holder.dialogLastMessageUserAvatar.setVisibility(View.GONE);
                 holder.dialogLastMessage.setText(conversation.getLastMessage().getText());
             } else {
-                holder.dialogLastMessageUserAvatar.setVisibility(View.VISIBLE);
                 if (conversation.getLastMessage().getActorId().equals(userEntity.getUserId())) {
-                    authorDisplayName = context.getString(R.string.nc_chat_you) + ": ";
+                    authorDisplayName = context.getString(R.string.nc_chat_you);
                 } else {
                     if (!TextUtils.isEmpty(conversation.getLastMessage().getActorDisplayName())) {
-                        authorDisplayName = conversation.getLastMessage().getActorDisplayName() + ": ";
+                        authorDisplayName = conversation.getLastMessage().getActorDisplayName();
                     } else {
-                        authorDisplayName = context.getString(R.string.nc_nick_guest) + ": ";
+                        authorDisplayName = context.getString(R.string.nc_nick_guest);
                     }
                 }
 
-                String fullString = authorDisplayName + conversation.getLastMessage().getText();
+                if (conversation.getLastMessage().getMessageType().equals(ChatMessage.MessageType.REGULAR_TEXT_MESSAGE)) {
+                    authorDisplayName += ": ";
+                } else {
+                    authorDisplayName += " ";
+                }
+
+                String fullString = authorDisplayName + conversation.getLastMessage().getLastMessageDisplayText();
                 Spannable spannableString = new SpannableString(fullString);
                 final StyleSpan boldStyleSpan = new StyleSpan(Typeface.BOLD);
-                spannableString.setSpan(boldStyleSpan, 0, fullString.indexOf(":") + 1, Spannable
-                        .SPAN_INCLUSIVE_INCLUSIVE);
+                spannableString.setSpan(boldStyleSpan, 0, fullString.indexOf(" "), Spannable
+                        .SPAN_INCLUSIVE_EXCLUSIVE);
 
                 holder.dialogLastMessage.setText(spannableString);
-                holder.dialogLastMessageUserAvatar.setVisibility(View.VISIBLE);
 
                 int smallAvatarSize = Math.round(context.getResources().getDimension(R.dimen.small_item_height));
 
                 if (conversation.getLastMessage().getActorType().equals("guests")) {
+                    holder.dialogLastMessageUserAvatar.setVisibility(View.VISIBLE);
                     TextDrawable drawable = TextDrawable.builder().beginConfig().bold()
                             .endConfig().buildRound(String.valueOf(authorDisplayName.charAt(0)),
                                     context.getResources().getColor(R.color.nc_grey));
                     holder.dialogLastMessageUserAvatar.setImageDrawable(drawable);
-                } else {
+                } else if (conversation.getLastMessage().getActorId().equals(userEntity.getUserId())
+                        || !conversation.getType().equals(Conversation.RoomType.ROOM_TYPE_ONE_TO_ONE_CALL)) {
+                    holder.dialogLastMessageUserAvatar.setVisibility(View.VISIBLE);
                     GlideUrl glideUrl = new GlideUrl(ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
                             conversation.getLastMessage().getActorId(), R.dimen.small_item_height), new LazyHeaders.Builder()
                             .setHeader("Accept", "image/*")
@@ -190,6 +198,8 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
                             .override(smallAvatarSize, smallAvatarSize)
                             .apply(RequestOptions.bitmapTransform(new CircleCrop()))
                             .into(holder.dialogLastMessageUserAvatar);
+                } else {
+                    holder.dialogLastMessageUserAvatar.setVisibility(View.GONE);
                 }
             }
 

+ 4 - 4
app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.java

@@ -33,16 +33,16 @@ import android.view.View;
 import android.widget.TextView;
 
 import com.amulyakhare.textdrawable.TextDrawable;
+import com.facebook.drawee.view.SimpleDraweeView;
 import com.google.android.flexbox.FlexboxLayout;
 import com.kevalpatel2106.emoticongifkeyboard.widget.EmoticonTextView;
 import com.nextcloud.talk.R;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.models.json.chat.ChatMessage;
 import com.nextcloud.talk.utils.DisplayUtils;
-import com.nextcloud.talk.utils.EmojiDetection;
+import com.nextcloud.talk.utils.TextMatchers;
 import com.nextcloud.talk.utils.database.user.UserUtils;
 import com.stfalcon.chatkit.messages.MessageHolders;
-import com.stfalcon.chatkit.utils.ShapeImageView;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -65,7 +65,7 @@ public class MagicIncomingTextMessageViewHolder
     EmoticonTextView messageText;
 
     @BindView(R.id.messageUserAvatar)
-    ShapeImageView messageUserAvatarView;
+    SimpleDraweeView messageUserAvatarView;
 
     @BindView(R.id.messageTime)
     TextView messageTimeView;
@@ -156,7 +156,7 @@ public class MagicIncomingTextMessageViewHolder
                 }
             }
 
-        } else if (EmojiDetection.isMessageWithSingleEmoticonOnly(context, message.getText())) {
+        } else if (TextMatchers.isMessageWithSingleEmoticonOnly(context, message.getText())) {
             messageString.setSpan(new RelativeSizeSpan(2.5f), 0, messageString.length(),
                     Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
             layoutParams.setWrapBefore(true);

+ 2 - 2
app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.java

@@ -37,7 +37,7 @@ import com.nextcloud.talk.R;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.models.json.chat.ChatMessage;
 import com.nextcloud.talk.utils.DisplayUtils;
-import com.nextcloud.talk.utils.EmojiDetection;
+import com.nextcloud.talk.utils.TextMatchers;
 import com.nextcloud.talk.utils.database.user.UserUtils;
 import com.stfalcon.chatkit.messages.MessageHolders;
 
@@ -106,7 +106,7 @@ public class MagicOutcomingTextMessageViewHolder extends MessageHolders.Outcomin
                 }
             }
 
-        } else if (EmojiDetection.isMessageWithSingleEmoticonOnly(context, message.getText())) {
+        } else if (TextMatchers.isMessageWithSingleEmoticonOnly(context, message.getText())) {
             messageString.setSpan(new RelativeSizeSpan(2.5f), 0, messageString.length(),
                     Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
             layoutParams.setWrapBefore(true);

+ 19 - 20
app/src/main/java/com/nextcloud/talk/adapters/messages/MagicPreviewMessageViewHolder.java

@@ -20,6 +20,7 @@
 
 package com.nextcloud.talk.adapters.messages;
 
+import android.annotation.SuppressLint;
 import android.content.Intent;
 import android.net.Uri;
 import android.view.View;
@@ -28,8 +29,8 @@ import android.widget.TextView;
 import com.nextcloud.talk.R;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.models.json.chat.ChatMessage;
+import com.nextcloud.talk.utils.DisplayUtils;
 import com.stfalcon.chatkit.messages.MessageHolders;
-import com.stfalcon.chatkit.utils.RoundedImageView;
 
 import butterknife.BindView;
 import butterknife.ButterKnife;
@@ -44,6 +45,7 @@ public class MagicPreviewMessageViewHolder extends MessageHolders.IncomingImageM
         ButterKnife.bind(this, itemView);
     }
 
+    @SuppressLint("SetTextI18n")
     @Override
     public void onBind(ChatMessage message) {
         super.onBind(message);
@@ -51,31 +53,28 @@ public class MagicPreviewMessageViewHolder extends MessageHolders.IncomingImageM
         if (userAvatar != null) {
             if (message.isGrouped) {
                 userAvatar.setVisibility(View.INVISIBLE);
-                ((RoundedImageView) image).setCorners(R.dimen.message_bubble_corners_radius, R.dimen.message_bubble_corners_radius, 0, 0);
             } else {
                 userAvatar.setVisibility(View.VISIBLE);
             }
         }
 
-
-        if (message.getUser().getId().equals(message.activeUserId)) {
-            time.setTextColor(NextcloudTalkApplication.getSharedApplication().getResources().getColor(R.color.white60));
-            if (!message.isGrouped) {
-                ((RoundedImageView) image).setCorners(R.dimen.message_bubble_corners_radius, 0, 0, 0);
-            }
+        if (message.getMessageType() == ChatMessage.MessageType.SINGLE_NC_ATTACHMENT_MESSAGE) {
+            // it's a preview for a Nextcloud share
+            messageText.setText(message.getSelectedIndividualHashMap().get("name"));
+            DisplayUtils.setClickableString(message.getSelectedIndividualHashMap().get("name"), message.getSelectedIndividualHashMap().get("link"), messageText);
+            image.setOnClickListener(v -> {
+                Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(message.getSelectedIndividualHashMap().get("link")));
+                browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                NextcloudTalkApplication.getSharedApplication().getApplicationContext().startActivity(browserIntent);
+            });
+        } else if (message.getMessageType() == ChatMessage.MessageType.SINGLE_LINK_GIPHY_MESSAGE){
+            messageText.setText("GIPHY");
+            DisplayUtils.setClickableString("GIPHY", "https://giphy.com", messageText);
+        } else if (message.getMessageType() == ChatMessage.MessageType.SINGLE_LINK_TENOR_MESSAGE) {
+            messageText.setText("Tenor");
+            DisplayUtils.setClickableString("Tenor", "https://tenor.com", messageText);
         } else {
-            time.setTextColor(NextcloudTalkApplication.getSharedApplication().getResources().getColor(R.color.warm_grey_four));
-            if (!message.isGrouped) {
-                ((RoundedImageView) image).setCorners(0, R.dimen.message_bubble_corners_radius, 0, 0);
-            }
+            messageText.setText("");
         }
-
-
-        messageText.setText(message.getSelectedIndividualHashMap().get("name"));
-        image.setOnClickListener(v -> {
-            Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(message.getSelectedIndividualHashMap().get("link")));
-            browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            NextcloudTalkApplication.getSharedApplication().getApplicationContext().startActivity(browserIntent);
-        });
     }
 }

+ 20 - 0
app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.java

@@ -24,6 +24,9 @@ import android.content.Context;
 import android.os.Build;
 import android.util.Log;
 
+import com.facebook.cache.disk.DiskCacheConfig;
+import com.facebook.drawee.backends.pipeline.Fresco;
+import com.facebook.imagepipeline.core.ImagePipelineConfig;
 import com.nextcloud.talk.dagger.modules.BusModule;
 import com.nextcloud.talk.dagger.modules.ContextModule;
 import com.nextcloud.talk.dagger.modules.DatabaseModule;
@@ -35,6 +38,7 @@ import com.nextcloud.talk.jobs.SignalingSettingsJob;
 import com.nextcloud.talk.utils.ClosedInterfaceImpl;
 import com.nextcloud.talk.utils.DeviceUtils;
 import com.nextcloud.talk.utils.DisplayUtils;
+import com.nextcloud.talk.utils.OkHttpNetworkFetcherWithCache;
 import com.nextcloud.talk.utils.database.arbitrarystorage.ArbitraryStorageModule;
 import com.nextcloud.talk.utils.database.user.UserModule;
 import com.nextcloud.talk.webrtc.MagicWebRTCUtils;
@@ -45,6 +49,7 @@ import org.webrtc.voiceengine.WebRtcAudioUtils;
 
 import java.util.concurrent.TimeUnit;
 
+import javax.inject.Inject;
 import javax.inject.Singleton;
 
 import androidx.lifecycle.LifecycleObserver;
@@ -55,6 +60,7 @@ import androidx.work.PeriodicWorkRequest;
 import androidx.work.WorkManager;
 import autodagger.AutoComponent;
 import autodagger.AutoInjector;
+import okhttp3.OkHttpClient;
 import uk.co.chrisjenx.calligraphy.CalligraphyConfig;
 
 @AutoComponent(
@@ -71,6 +77,9 @@ import uk.co.chrisjenx.calligraphy.CalligraphyConfig;
 @Singleton
 @AutoInjector(NextcloudTalkApplication.class)
 public class NextcloudTalkApplication extends MultiDexApplication implements LifecycleObserver {
+    @Inject
+    OkHttpClient okHttpClient;
+
     private static final String TAG = NextcloudTalkApplication.class.getSimpleName();
 
     //region Singleton
@@ -124,6 +133,17 @@ public class NextcloudTalkApplication extends MultiDexApplication implements Lif
 
         componentApplication.inject(this);
 
+        ImagePipelineConfig imagePipelineConfig = ImagePipelineConfig.newBuilder(this)
+                .setNetworkFetcher(new OkHttpNetworkFetcherWithCache(okHttpClient))
+                .setMainDiskCacheConfig(DiskCacheConfig.newBuilder(this)
+                        .setMaxCacheSize(0)
+                        .setMaxCacheSizeOnLowDiskSpace(0)
+                        .setMaxCacheSizeOnVeryLowDiskSpace(0)
+                        .build())
+                .build();
+
+        Fresco.initialize(this, imagePipelineConfig);
+
         new ClosedInterfaceImpl().providerInstallerInstallIfNeededAsync();
         DeviceUtils.ignoreSpecialBatteryFeatures();
 

+ 22 - 45
app/src/main/java/com/nextcloud/talk/controllers/ChatController.java

@@ -25,10 +25,10 @@ import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.Context;
 import android.content.Intent;
-import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.text.Editable;
@@ -43,21 +43,18 @@ import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AbsListView;
-import android.widget.ImageView;
 import android.widget.ProgressBar;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
-import com.amulyakhare.textdrawable.TextDrawable;
 import com.bluelinelabs.conductor.RouterTransaction;
 import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
-import com.bumptech.glide.load.DataSource;
-import com.bumptech.glide.load.engine.DiskCacheStrategy;
-import com.bumptech.glide.load.engine.GlideException;
-import com.bumptech.glide.load.resource.bitmap.CircleCrop;
-import com.bumptech.glide.request.RequestListener;
-import com.bumptech.glide.request.RequestOptions;
-import com.bumptech.glide.request.target.Target;
+import com.facebook.drawee.backends.pipeline.Fresco;
+import com.facebook.drawee.interfaces.DraweeController;
+import com.facebook.drawee.view.SimpleDraweeView;
+import com.facebook.imagepipeline.common.RotationOptions;
+import com.facebook.imagepipeline.request.ImageRequest;
+import com.facebook.imagepipeline.request.ImageRequestBuilder;
 import com.nextcloud.talk.R;
 import com.nextcloud.talk.activities.MagicCallActivity;
 import com.nextcloud.talk.adapters.messages.MagicIncomingTextMessageViewHolder;
@@ -80,11 +77,11 @@ import com.nextcloud.talk.models.json.rooms.RoomOverall;
 import com.nextcloud.talk.models.json.rooms.RoomsOverall;
 import com.nextcloud.talk.presenters.MentionAutocompletePresenter;
 import com.nextcloud.talk.utils.ApiUtils;
+import com.nextcloud.talk.utils.DisplayUtils;
 import com.nextcloud.talk.utils.KeyboardUtils;
 import com.nextcloud.talk.utils.NotificationUtils;
 import com.nextcloud.talk.utils.bundle.BundleKeys;
 import com.nextcloud.talk.utils.database.user.UserUtils;
-import com.nextcloud.talk.utils.glide.GlideApp;
 import com.nextcloud.talk.utils.singletons.ApplicationWideCurrentRoomHolder;
 import com.otaliastudios.autocomplete.Autocomplete;
 import com.otaliastudios.autocomplete.AutocompleteCallback;
@@ -97,7 +94,6 @@ import com.stfalcon.chatkit.messages.MessageInput;
 import com.stfalcon.chatkit.messages.MessagesList;
 import com.stfalcon.chatkit.messages.MessagesListAdapter;
 import com.stfalcon.chatkit.utils.DateFormatter;
-import com.stfalcon.chatkit.utils.RoundedImageView;
 import com.webianks.library.PopupBubble;
 
 import org.parceler.Parcels;
@@ -113,7 +109,6 @@ import java.util.concurrent.TimeUnit;
 import javax.inject.Inject;
 
 import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 import autodagger.AutoInjector;
@@ -326,38 +321,20 @@ public class ChatController extends BaseController implements MessagesListAdapte
 
             adapter = new MessagesListAdapter<>(conversationUser.getUserId(), messageHolders, new ImageLoader() {
                 @Override
-                public void loadImage(ImageView imageView, String url) {
-                    if (!(imageView instanceof RoundedImageView)) {
-                        GlideApp.with(NextcloudTalkApplication.getSharedApplication().getApplicationContext())
-                                .asBitmap()
-                                .diskCacheStrategy(DiskCacheStrategy.NONE)
-                                .load(url)
-                                .centerInside()
-                                .override(imageView.getMeasuredWidth(), imageView.getMeasuredHeight())
-                                .apply(RequestOptions.bitmapTransform(new CircleCrop()))
-                                .listener(new RequestListener<Bitmap>() {
-                                    @Override
-                                    public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
-                                        TextDrawable drawable = TextDrawable.builder().beginConfig().bold()
-                                                .endConfig().buildRound("?", getResources().getColor(R.color.nc_grey));
-                                        imageView.setImageDrawable(drawable);
-                                        return true;
-                                    }
-
-                                    @Override
-                                    public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
-                                        return false;
-                                    }
-                                })
-                                .into(imageView);
-                    } else {
-                        GlideApp.with(NextcloudTalkApplication.getSharedApplication().getApplicationContext())
-                                .asBitmap()
-                                .diskCacheStrategy(DiskCacheStrategy.NONE)
-                                .override(480, 480)
-                                .load(url)
-                                .into(imageView);
-                    }
+                public void loadImage(SimpleDraweeView imageView, String url) {
+                    ImageRequest request = ImageRequestBuilder.newBuilderWithSource(Uri.parse(url))
+                            .setProgressiveRenderingEnabled(true)
+                            .setRotationOptions(RotationOptions.autoRotate())
+                            .disableDiskCache()
+                            .build();
+
+                    DraweeController draweeController = Fresco.newDraweeControllerBuilder()
+                            .setImageRequest(request)
+                            .setControllerListener(DisplayUtils.getImageControllerListener(imageView))
+                            .setOldController(imageView.getController())
+                            .setAutoPlayAnimations(true)
+                            .build();
+                    imageView.setController(draweeController);
                 }
             });
         } else {

+ 1 - 1
app/src/main/java/com/nextcloud/talk/dagger/modules/RestModule.java

@@ -251,7 +251,7 @@ public class RestModule {
         }
     }
 
-    private class HeadersInterceptor implements Interceptor {
+    public static class HeadersInterceptor implements Interceptor {
 
         @Override
         public Response intercept(@NonNull Chain chain) throws IOException {

+ 1 - 1
app/src/main/java/com/nextcloud/talk/jobs/AccountRemovalWorker.java

@@ -249,6 +249,6 @@ public class AccountRemovalWorker extends Worker {
             }
         }
 
-        return Result.SUCCESS;
+        return Result.success();
     }
 }

+ 1 - 1
app/src/main/java/com/nextcloud/talk/jobs/CapabilitiesWorker.java

@@ -163,6 +163,6 @@ public class CapabilitiesWorker extends Worker {
                     });
         }
 
-        return Result.SUCCESS;
+        return Result.success();
     }
 }

+ 1 - 1
app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java

@@ -509,6 +509,6 @@ public class NotificationWorker extends Worker {
         } catch (Exception exception) {
             Log.d(TAG, "Something went very wrong " + exception.getLocalizedMessage());
         }
-        return Result.SUCCESS;
+        return Result.success();
     }
 }

+ 1 - 1
app/src/main/java/com/nextcloud/talk/jobs/PushRegistrationWorker.java

@@ -42,6 +42,6 @@ public class PushRegistrationWorker extends Worker {
         pushUtils.generateRsa2048KeyPair();
         pushUtils.pushRegistrationToServer();
 
-        return Result.SUCCESS;
+        return Result.success();
     }
 }

+ 1 - 1
app/src/main/java/com/nextcloud/talk/jobs/SignalingSettingsJob.java

@@ -155,6 +155,6 @@ public class SignalingSettingsJob extends Worker {
         OneTimeWorkRequest websocketConnectionsWorker = new OneTimeWorkRequest.Builder(WebsocketConnectionsWorker.class).build();
         WorkManager.getInstance().enqueue(websocketConnectionsWorker);
 
-        return Result.SUCCESS;
+        return Result.success();
     }
 }

+ 1 - 1
app/src/main/java/com/nextcloud/talk/jobs/WebsocketConnectionsWorker.java

@@ -81,6 +81,6 @@ public class WebsocketConnectionsWorker extends Worker {
             }
         }
 
-        return Result.SUCCESS;
+        return Result.success();
     }
 }

+ 75 - 0
app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java

@@ -19,20 +19,26 @@
  */
 package com.nextcloud.talk.models.json.chat;
 
+import android.text.TextUtils;
+
 import com.bluelinelabs.logansquare.annotation.JsonField;
 import com.bluelinelabs.logansquare.annotation.JsonIgnore;
 import com.bluelinelabs.logansquare.annotation.JsonObject;
 import com.nextcloud.talk.R;
+import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.models.json.converters.EnumSystemMessageTypeConverter;
 import com.nextcloud.talk.utils.ApiUtils;
+import com.nextcloud.talk.utils.TextMatchers;
 import com.stfalcon.chatkit.commons.models.IMessage;
 import com.stfalcon.chatkit.commons.models.IUser;
 import com.stfalcon.chatkit.commons.models.MessageContentType;
 
 import org.parceler.Parcel;
 
+import java.util.Arrays;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
@@ -43,6 +49,22 @@ import lombok.Data;
 @Data
 @JsonObject
 public class ChatMessage implements IMessage, MessageContentType, MessageContentType.Image {
+    List<MessageType> messageTypesToIgnore = Arrays.asList(MessageType.REGULAR_TEXT_MESSAGE,
+            MessageType.SYSTEM_MESSAGE, MessageType.SINGLE_LINK_VIDEO_MESSAGE,
+            MessageType.SINGLE_LINK_AUDIO_MESSAGE, MessageType.SINGLE_LINK_MESSAGE);
+
+    private boolean hasFileAttachment() {
+        if (messageParameters != null && messageParameters.size() > 0) {
+            for (String key : messageParameters.keySet()) {
+                Map<String, String> individualHashMap = messageParameters.get(key);
+                if (individualHashMap.get("type").equals("file")) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
 
     @Nullable
     @Override
@@ -59,9 +81,38 @@ public class ChatMessage implements IMessage, MessageContentType, MessageContent
             }
         }
 
+        if (!messageTypesToIgnore.contains(getMessageType())) {
+            return getMessage().trim();
+        }
+
         return null;
     }
 
+    public MessageType getMessageType() {
+        if (!TextUtils.isEmpty(getSystemMessage())) {
+            return MessageType.SYSTEM_MESSAGE;
+        }
+
+        if (hasFileAttachment()) {
+            return MessageType.SINGLE_NC_ATTACHMENT_MESSAGE;
+        }
+
+        return TextMatchers.getMessageTypeFromString(getText());
+    }
+
+    public enum MessageType {
+        REGULAR_TEXT_MESSAGE,
+        SYSTEM_MESSAGE,
+        SINGLE_LINK_GIPHY_MESSAGE,
+        SINGLE_LINK_TENOR_MESSAGE,
+        SINGLE_LINK_GIF_MESSAGE,
+        SINGLE_LINK_MESSAGE,
+        SINGLE_LINK_VIDEO_MESSAGE,
+        SINGLE_LINK_IMAGE_MESSAGE,
+        SINGLE_LINK_AUDIO_MESSAGE,
+        SINGLE_NC_ATTACHMENT_MESSAGE,
+    }
+
     public enum SystemMessageType {
         DUMMY,
         CONVERSATION_CREATED,
@@ -139,6 +190,30 @@ public class ChatMessage implements IMessage, MessageContentType, MessageContent
         return ChatUtils.getParsedMessage(getMessage(), getMessageParameters());
     }
 
+    public String getLastMessageDisplayText() {
+        if (getMessageType().equals(MessageType.REGULAR_TEXT_MESSAGE) || getMessageType().equals(MessageType.SYSTEM_MESSAGE)) {
+            return getText();
+        } else {
+            if (getMessageType().equals(MessageType.SINGLE_LINK_GIPHY_MESSAGE)
+                    || getMessageType().equals(MessageType.SINGLE_LINK_TENOR_MESSAGE)
+                    || getMessageType().equals(MessageType.SINGLE_LINK_GIF_MESSAGE)) {
+                return (NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_sent_a_gif));
+            } else if (getMessageType().equals(MessageType.SINGLE_NC_ATTACHMENT_MESSAGE)) {
+                return (NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_sent_an_attachment));
+            } else if (getMessageType().equals(MessageType.SINGLE_LINK_MESSAGE)) {
+                return (NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_sent_a_link));
+            } else if (getMessageType().equals(MessageType.SINGLE_LINK_AUDIO_MESSAGE)) {
+                return (NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_sent_an_audio));
+            } else if (getMessageType().equals(MessageType.SINGLE_LINK_VIDEO_MESSAGE)) {
+                return (NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_sent_a_video));
+            } else if (getMessageType().equals(MessageType.SINGLE_LINK_IMAGE_MESSAGE)) {
+                return (NextcloudTalkApplication.getSharedApplication().getString(R.string.nc_sent_an_image));
+            }
+        }
+
+        return "";
+    }
+
     @Override
     public IUser getUser() {
         return new IUser() {

+ 79 - 0
app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java

@@ -22,19 +22,33 @@ package com.nextcloud.talk.utils;
 
 import android.annotation.SuppressLint;
 import android.content.Context;
+import android.content.Intent;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.graphics.Typeface;
+import android.graphics.drawable.Animatable;
 import android.graphics.drawable.Drawable;
+import android.net.Uri;
 import android.os.Build;
 import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.TextPaint;
 import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
 import android.text.style.AbsoluteSizeSpan;
+import android.text.style.ClickableSpan;
 import android.text.style.ForegroundColorSpan;
 import android.text.style.StyleSpan;
 import android.util.DisplayMetrics;
 import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
 
+import com.facebook.drawee.controller.ControllerListener;
+import com.facebook.drawee.view.SimpleDraweeView;
+import com.facebook.imagepipeline.image.ImageInfo;
 import com.nextcloud.talk.R;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 
@@ -47,6 +61,8 @@ import java.util.regex.Pattern;
 import androidx.annotation.ColorInt;
 import androidx.annotation.ColorRes;
 import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.appcompat.widget.AppCompatDrawableManager;
 import androidx.core.content.ContextCompat;
 import androidx.core.graphics.drawable.DrawableCompat;
@@ -55,6 +71,69 @@ public class DisplayUtils {
 
     private static final String TAG = "DisplayUtils";
 
+    public static void setClickableString(String string, String url, TextView textView){
+        SpannableString spannableString = new SpannableString(string);
+        spannableString.setSpan(new ClickableSpan() {
+            @Override
+            public void onClick(@NonNull View widget) {
+                Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+                browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                NextcloudTalkApplication.getSharedApplication().getApplicationContext().startActivity(browserIntent);
+            }
+
+            @Override
+            public void updateDrawState(TextPaint ds) {
+                super.updateDrawState(ds);
+                ds.setUnderlineText(false);
+            }
+        }, 0, string.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+        textView.setText(spannableString);
+        textView.setMovementMethod(LinkMovementMethod.getInstance());
+    }
+
+    private static void updateViewSize(@Nullable ImageInfo imageInfo, SimpleDraweeView draweeView) {
+        if (imageInfo != null) {
+            draweeView.getLayoutParams().width = imageInfo.getWidth() > 480 ? 480 : imageInfo.getWidth();
+            draweeView.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
+            draweeView.setAspectRatio((float) imageInfo.getWidth() / imageInfo.getHeight());
+            draweeView.requestLayout();
+        }
+    }
+
+    public static ControllerListener getImageControllerListener(SimpleDraweeView draweeView) {
+        return new ControllerListener() {
+            @Override
+            public void onSubmit(String id, Object callerContext) {
+
+            }
+
+            @Override
+            public void onFinalImageSet(String id, @javax.annotation.Nullable Object imageInfo, @javax.annotation.Nullable Animatable animatable) {
+                updateViewSize((ImageInfo)imageInfo, draweeView);
+            }
+
+            @Override
+            public void onIntermediateImageSet(String id, @javax.annotation.Nullable Object imageInfo) {
+                updateViewSize((ImageInfo) imageInfo, draweeView);
+            }
+
+            @Override
+            public void onIntermediateImageFailed(String id, Throwable throwable) {
+
+            }
+
+            @Override
+            public void onFailure(String id, Throwable throwable) {
+
+            }
+
+            @Override
+            public void onRelease(String id) {
+
+            }
+        };
+    }
+
     public static float convertDpToPixel(float dp, Context context) {
         Resources resources = context.getResources();
         DisplayMetrics metrics = resources.getDisplayMetrics();

+ 42 - 0
app/src/main/java/com/nextcloud/talk/utils/OkHttpNetworkFetcherWithCache.java

@@ -0,0 +1,42 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.talk.utils;
+
+import com.facebook.imagepipeline.backends.okhttp3.OkHttpNetworkFetcher;
+
+import java.util.concurrent.Executor;
+
+import okhttp3.Call;
+import okhttp3.OkHttpClient;
+
+public class OkHttpNetworkFetcherWithCache extends OkHttpNetworkFetcher {
+    public OkHttpNetworkFetcherWithCache(OkHttpClient okHttpClient) {
+        super(okHttpClient);
+    }
+
+    public OkHttpNetworkFetcherWithCache(Call.Factory callFactory, Executor cancellationExecutor) {
+        super(callFactory, cancellationExecutor);
+    }
+
+    public OkHttpNetworkFetcherWithCache(Call.Factory callFactory, Executor cancellationExecutor, boolean disableOkHttpCache) {
+        super(callFactory, cancellationExecutor, true);
+    }
+}

+ 54 - 1
app/src/main/java/com/nextcloud/talk/utils/EmojiDetection.java → app/src/main/java/com/nextcloud/talk/utils/TextMatchers.java

@@ -25,25 +25,78 @@ package com.nextcloud.talk.utils;
 import android.content.Context;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Patterns;
 
 import com.nextcloud.talk.R;
+import com.nextcloud.talk.models.json.chat.ChatMessage;
 
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import eu.medsea.mimeutil.MimeUtil;
+import eu.medsea.mimeutil.detector.ExtensionMimeDetector;
+import eu.medsea.mimeutil.detector.MagicMimeMimeDetector;
+import eu.medsea.mimeutil.detector.OpendesktopMimeDetector;
 
-public final class EmojiDetection {
+public final class TextMatchers {
 
     private static final String TAG = "EmojiDetection";
 
     private static Pattern regexPattern;
 
+    public static ChatMessage.MessageType getMessageTypeFromString(@NonNull final String text) {
+        List<String> links = new ArrayList<>();
+        Matcher m = Patterns.WEB_URL.matcher(text);
+        while (m.find()) {
+            String url = m.group();
+            links.add(url);
+        }
+
+        if (links.size() == 1 && text.trim().length() == links.get(0).length()) {
+            String specialLink = links.get(0);
+            if (specialLink.startsWith("https://media.giphy.com/") && specialLink.endsWith(".gif")) {
+                return ChatMessage.MessageType.SINGLE_LINK_GIPHY_MESSAGE;
+            } else if (specialLink.contains("tenor.com/") &&
+                    Pattern.compile("https://media.*\\.tenor\\.com.*\\.gif.*",
+                            Pattern.CASE_INSENSITIVE).matcher(specialLink).matches()) {
+                return ChatMessage.MessageType.SINGLE_LINK_TENOR_MESSAGE;
+            } else {
+                if (specialLink.contains("?")) {
+                    specialLink = specialLink.substring(0, specialLink.indexOf("?"));
+                }
+                MimeUtil.registerMimeDetector(MagicMimeMimeDetector.class.getName());
+                MimeUtil.registerMimeDetector(ExtensionMimeDetector.class.getName());
+                MimeUtil.registerMimeDetector(OpendesktopMimeDetector.class.getName());
+
+                String mimeType = MimeUtil.getMostSpecificMimeType(MimeUtil.getMimeTypes(specialLink)).toString();
+                if (mimeType.startsWith("image/")) {
+                    if (mimeType.equalsIgnoreCase("image/gif")) {
+                        return ChatMessage.MessageType.SINGLE_LINK_GIF_MESSAGE;
+                    } else {
+                        return ChatMessage.MessageType.SINGLE_LINK_IMAGE_MESSAGE;
+                    }
+                } else if (mimeType.startsWith("video/")) {
+                    return ChatMessage.MessageType.SINGLE_LINK_VIDEO_MESSAGE;
+                } else if (mimeType.startsWith("audio/")) {
+                    return ChatMessage.MessageType.SINGLE_LINK_AUDIO_MESSAGE;
+                }
+
+                return ChatMessage.MessageType.SINGLE_LINK_MESSAGE;
+            }
+        }
+
+        // if we have 0 or more than 1 link, we're a regular message
+        return ChatMessage.MessageType.REGULAR_TEXT_MESSAGE;
+    }
+
     public static boolean isMessageWithSingleEmoticonOnly(@NonNull final Context context,
                                                           @Nullable final CharSequence text) {
 

+ 0 - 32
app/src/main/res/drawable/shape_preview_text_incoming_message.xml

@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Nextcloud Talk application
-  ~
-  ~ @author Mario Danic
-  ~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
-  ~
-  ~ This program is free software: you can redistribute it and/or modify
-  ~ it under the terms of the GNU General Public License as published by
-  ~ the Free Software Foundation, either version 3 of the License, or
-  ~ at your option) any later version.
-  ~
-  ~ This program is distributed in the hope that it will be useful,
-  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
-  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  ~ GNU General Public License for more details.
-  ~
-  ~ You should have received a copy of the GNU General Public License
-  ~ along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-       android:shape="rectangle">
-
-    <corners
-        android:topLeftRadius="0dp"
-        android:bottomRightRadius="@dimen/message_bubble_corners_radius"
-        android:bottomLeftRadius="@dimen/message_bubble_corners_radius"
-        android:topRightRadius="0dp" />
-
-    <solid android:color="@color/white_two" />
-</shape>

+ 0 - 32
app/src/main/res/drawable/shape_preview_text_outcoming_message.xml

@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Nextcloud Talk application
-  ~
-  ~ @author Mario Danic
-  ~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
-  ~
-  ~ This program is free software: you can redistribute it and/or modify
-  ~ it under the terms of the GNU General Public License as published by
-  ~ the Free Software Foundation, either version 3 of the License, or
-  ~ at your option) any later version.
-  ~
-  ~ This program is distributed in the hope that it will be useful,
-  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
-  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  ~ GNU General Public License for more details.
-  ~
-  ~ You should have received a copy of the GNU General Public License
-  ~ along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-       android:shape="rectangle">
-
-    <corners
-        android:topLeftRadius="6dp"
-        android:bottomRightRadius="6dp"
-        android:bottomLeftRadius="@dimen/message_bubble_corners_radius"
-        android:topRightRadius="0dp" />
-
-    <solid android:color="@color/colorPrimary" />
-</shape>

+ 22 - 19
app/src/main/res/layout/item_custom_incoming_preview_message.xml

@@ -19,6 +19,8 @@
   -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_marginStart="16dp"
@@ -26,24 +28,27 @@
     android:layout_marginEnd="16dp"
     android:layout_marginBottom="2dp">
 
-    <com.stfalcon.chatkit.utils.ShapeImageView
+    <com.facebook.drawee.view.SimpleDraweeView
         android:id="@id/messageUserAvatar"
         android:layout_width="40dp"
         android:layout_height="40dp"
+        android:layout_alignParentStart="true"
         android:layout_alignParentTop="true"
-        android:layout_marginEnd="8dp" />
+        android:layout_marginEnd="8dp"
+        app:roundAsCircle="true" />
 
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_toEndOf="@id/messageUserAvatar"
-        android:background="@drawable/shape_preview_text_incoming_message">
+        android:layout_toEndOf="@id/messageUserAvatar">
 
-        <com.stfalcon.chatkit.utils.RoundedImageView
+        <com.facebook.drawee.view.SimpleDraweeView
             android:id="@id/image"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:adjustViewBounds="true" />
+            android:layout_width="480px"
+            android:layout_height="480px"
+            android:adjustViewBounds="true"
+            app:actualImageScaleType="fitCenter"
+            tools:ignore="PxUsage" />
 
         <RelativeLayout
             android:layout_width="wrap_content"
@@ -51,30 +56,28 @@
             android:layout_below="@id/image"
             android:layout_alignStart="@+id/image"
             android:layout_alignEnd="@id/image"
-            android:layout_margin="8dp">
+            android:layout_marginTop="8dp"
+            android:layout_marginBottom="8dp">
 
             <com.kevalpatel2106.emoticongifkeyboard.widget.EmoticonTextView
                 android:id="@id/messageText"
                 android:layout_width="wrap_content"
+                android:textColorLink="@color/warm_grey_four"
                 android:layout_height="wrap_content"
-                android:textColor="@color/dark_grey_two"
+                android:autoLink="all"
+                android:textColor="@color/warm_grey_four"
                 android:textIsSelectable="true"
-                android:textSize="14sp" />
-
-            <View
-                android:id="@id/imageOverlay"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
+                android:textSize="12sp" />
 
             <TextView
                 android:id="@id/messageTime"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_below="@id/messageText"
-                android:layout_alignParentEnd="true" />
+                android:layout_alignParentEnd="true"
+                android:textColor="@color/warm_grey_four" />
 
         </RelativeLayout>
 
     </RelativeLayout>
 
-</RelativeLayout>
+</RelativeLayout>

+ 2 - 1
app/src/main/res/layout/item_custom_incoming_text_message.xml

@@ -27,10 +27,11 @@
     android:layout_marginRight="16dp"
     android:layout_marginBottom="2dp">
 
-    <com.stfalcon.chatkit.utils.ShapeImageView
+    <com.facebook.drawee.view.SimpleDraweeView
         android:id="@id/messageUserAvatar"
         android:layout_width="40dp"
         android:layout_height="40dp"
+        app:roundAsCircle="true"
         android:layout_alignParentTop="true"
         android:layout_marginEnd="8dp" />
 

+ 30 - 36
app/src/main/res/layout/item_custom_outcoming_preview_message.xml

@@ -19,55 +19,49 @@
   -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_marginStart="16dp"
     android:layout_marginTop="2dp"
     android:layout_marginEnd="16dp"
     android:layout_marginBottom="2dp">
 
+    <com.facebook.drawee.view.SimpleDraweeView
+        android:id="@id/image"
+        android:layout_width="480px"
+        android:layout_height="480px"
+        app:actualImageScaleType="fitCenter"
+        android:adjustViewBounds="true"
+        android:layout_alignParentEnd="true"
+        tools:ignore="PxUsage" />
+
     <RelativeLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_alignParentEnd="true"
-        android:background="@drawable/shape_preview_text_outcoming_message">
+        android:layout_below="@id/image"
+        android:layout_alignStart="@+id/image"
+        android:layout_alignEnd="@id/image"
+        android:layout_marginTop="8dp"
+        android:layout_marginBottom="8dp">
 
-        <com.stfalcon.chatkit.utils.RoundedImageView
-            android:id="@id/image"
+        <com.kevalpatel2106.emoticongifkeyboard.widget.EmoticonTextView
+            android:id="@id/messageText"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:adjustViewBounds="true" />
+            android:autoLink="all"
+            android:textColorLink="@color/warm_grey_four"
+            android:textColor="@color/warm_grey_four"
+            android:textIsSelectable="true"
+            android:textSize="12sp" />
 
-        <RelativeLayout
+        <TextView
+            android:id="@id/messageTime"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_below="@id/image"
-            android:layout_alignStart="@+id/image"
-            android:layout_alignEnd="@id/image"
-            android:layout_margin="8dp">
-
-            <com.kevalpatel2106.emoticongifkeyboard.widget.EmoticonTextView
-                android:id="@id/messageText"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:textColor="@color/nc_outcoming_text_default"
-                android:textIsSelectable="true"
-                android:textSize="14sp" />
-
-            <View
-                android:id="@id/imageOverlay"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
-
-            <TextView
-                android:id="@id/messageTime"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_below="@id/messageText"
-                android:layout_alignParentEnd="true"
-                android:textColor="@color/white60" />
-
-        </RelativeLayout>
-
+            android:layout_alignParentEnd="true"
+            android:textColor="@color/warm_grey_four" />
     </RelativeLayout>
-</RelativeLayout>
+
+</RelativeLayout>

+ 0 - 1
app/src/main/res/layout/item_custom_outcoming_text_message.xml

@@ -44,7 +44,6 @@
             android:layout_height="wrap_content"
             android:layout_alignWithParentIfMissing="true"
             android:textColorHighlight="@color/nc_grey"
-
             android:textIsSelectable="true" />
 
         <TextView

+ 1 - 0
app/src/main/res/layout/view_message_input.xml

@@ -53,6 +53,7 @@
         android:id="@id/messageSendButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:scaleType="fitCenter"
         android:layout_alignParentEnd="true"
         android:layout_centerVertical="true" />
 

+ 7 - 0
app/src/main/res/values/strings.xml

@@ -180,6 +180,13 @@
     <string name="nc_new_messages">New messages</string>
     <string name="nc_no_messages_yet">No messages yet</string>
     <string name="nc_chat_you">You</string>
+    <string name="nc_sent_a_link">sent a link.</string>
+    <string name="nc_sent_a_gif">sent a GIF.</string>
+    <string name="nc_sent_an_attachment">sent an attachment.</string>
+    <string name="nc_sent_an_audio">sent an audio.</string>
+    <string name="nc_sent_a_video">sent a video.</string>
+    <string name="nc_sent_an_image">sent an image.</string>
+
 
     <!-- Contacts endless loading -->
     <string name="nc_no_more_load_retry">No more items to load. Refresh to retry.</string>