From 5400aeea888f33a9fea3e5eea63536a55a578653 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Sun, 26 May 2019 18:00:27 +0400 Subject: [PATCH] Added picture loading and adding user to userlist in chat entity --- app/build.gradle | 2 + .../influence/contracts/CoreContracts.kt | 6 +- .../influence/helpers/AvatarImageLoader.java | 85 ++++++++++++------ .../influence/helpers/LocalDBWrapper.java | 5 +- .../influence/helpers/NetworkHandler.java | 7 +- .../influence/helpers/RoomTypeConverter.java | 2 +- .../influence/models/GenericMessage.java | 17 ++-- .../influence/presenters/ChatPresenter.kt | 2 +- .../presenters/DialogListPresenter.java | 14 +-- .../influence/presenters/MainPresenter.kt | 6 +- .../influence/views/ChatActivity.kt | 5 ++ .../views/fragments/DialogListFragment.kt | 7 +- .../main/res/drawable/no_image_picture.png | Bin 0 -> 748 bytes 13 files changed, 111 insertions(+), 47 deletions(-) create mode 100644 app/src/main/res/drawable/no_image_picture.png diff --git a/app/build.gradle b/app/build.gradle index dfdd45c..7cb3453 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -84,6 +84,8 @@ dependencies { implementation 'net.sourceforge.streamsupport:android-retrofuture:1.7.0' implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' implementation 'org.igniterealtime.smack:smack-experimental:4.3.3' + implementation 'com.github.bumptech.glide:glide:4.9.0' + annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0' } repositories { mavenCentral() diff --git a/app/src/main/java/io/github/chronosx88/influence/contracts/CoreContracts.kt b/app/src/main/java/io/github/chronosx88/influence/contracts/CoreContracts.kt index d9be03a..e05b927 100644 --- a/app/src/main/java/io/github/chronosx88/influence/contracts/CoreContracts.kt +++ b/app/src/main/java/io/github/chronosx88/influence/contracts/CoreContracts.kt @@ -16,9 +16,11 @@ package io.github.chronosx88.influence.contracts +import android.app.Activity import android.content.Context import android.content.Intent import android.view.MenuItem +import androidx.fragment.app.Fragment import com.stfalcon.chatkit.dialogs.DialogsListAdapter import com.stfalcon.chatkit.messages.MessagesListAdapter import io.github.chronosx88.influence.models.GenericDialog @@ -49,10 +51,11 @@ interface CoreContracts { fun loadRemoteContactList() } - interface IChatListViewContract { + interface IDialogListViewContract { fun setDialogAdapter(adapter: DialogsListAdapter) fun startActivity(intent: Intent) fun getActivityContext(): Context? + fun getFragmentObject(): Fragment } // -----MainActivity----- @@ -99,6 +102,7 @@ interface CoreContracts { interface IChatViewContract { fun setAdapter(adapter: MessagesListAdapter) fun setUserStatus(status: String) + fun getActivityObject(): Activity } // -----SettingsFragment----- diff --git a/app/src/main/java/io/github/chronosx88/influence/helpers/AvatarImageLoader.java b/app/src/main/java/io/github/chronosx88/influence/helpers/AvatarImageLoader.java index 265dba5..9b1ae7a 100644 --- a/app/src/main/java/io/github/chronosx88/influence/helpers/AvatarImageLoader.java +++ b/app/src/main/java/io/github/chronosx88/influence/helpers/AvatarImageLoader.java @@ -16,58 +16,85 @@ package io.github.chronosx88.influence.helpers; +import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.widget.ImageView; import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; import com.amulyakhare.textdrawable.TextDrawable; import com.amulyakhare.textdrawable.util.ColorGenerator; +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; import com.stfalcon.chatkit.commons.ImageLoader; import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.stringprep.XmppStringprepException; +import io.github.chronosx88.influence.R; import java9.util.concurrent.CompletableFuture; public class AvatarImageLoader implements ImageLoader { + private Fragment fragment = null; + private Activity activity = null; + + public AvatarImageLoader(Fragment fragment) { + this.fragment = fragment; + } + + public AvatarImageLoader(Activity activity) { + this.activity = activity; + } + @Override public void loadImage(ImageView imageView, @Nullable String url, @Nullable Object payload) { if(url.length() != 0) { - if(AppHelper.avatarsCache.containsKey(url)) { - byte[] avatarBytes = AppHelper.avatarsCache.get(url); - Bitmap avatar = BitmapFactory.decodeByteArray(avatarBytes, 0, avatarBytes.length); - imageView.setImageBitmap(avatar); - return; - } - String firstLetter = Character.toString(Character.toUpperCase(url.charAt(0))); - imageView.setImageDrawable(TextDrawable.builder() - .beginConfig() - .width(64) - .height(64) - .endConfig() - .buildRound(firstLetter, ColorGenerator.MATERIAL.getColor(firstLetter))); - CompletableFuture.supplyAsync(() -> { - while (AppHelper.getXmppConnection() == null); - while (AppHelper.getXmppConnection().isConnectionAlive() != true); - EntityBareJid jid = null; - try { - jid = JidCreate.entityBareFrom(url); - } catch (XmppStringprepException e) { - e.printStackTrace(); + if(!url.contains("http")) { + if(AppHelper.avatarsCache.containsKey(url)) { + byte[] avatarBytes = AppHelper.avatarsCache.get(url); + Bitmap avatar = BitmapFactory.decodeByteArray(avatarBytes, 0, avatarBytes.length); + imageView.setImageBitmap(avatar); + return; } - return AppHelper.getXmppConnection().getAvatar(jid); - }).thenAccept((avatarBytes) -> { - AppHelper.getMainUIThread().post(() -> { - if(avatarBytes != null) { - Bitmap avatar = BitmapFactory.decodeByteArray(avatarBytes, 0, avatarBytes.length); - imageView.setImageBitmap(avatar); - AppHelper.avatarsCache.put(url, avatarBytes); + String firstLetter = Character.toString(Character.toUpperCase(url.charAt(0))); + imageView.setImageDrawable(TextDrawable.builder() + .beginConfig() + .width(64) + .height(64) + .endConfig() + .buildRound(firstLetter, ColorGenerator.MATERIAL.getColor(firstLetter))); + CompletableFuture.supplyAsync(() -> { + while (AppHelper.getXmppConnection() == null); + while (AppHelper.getXmppConnection().isConnectionAlive() != true); + EntityBareJid jid = null; + try { + jid = JidCreate.entityBareFrom(url); + } catch (XmppStringprepException e) { + e.printStackTrace(); } + return AppHelper.getXmppConnection().getAvatar(jid); + }).thenAccept((avatarBytes) -> { + AppHelper.getMainUIThread().post(() -> { + if(avatarBytes != null) { + Bitmap avatar = BitmapFactory.decodeByteArray(avatarBytes, 0, avatarBytes.length); + imageView.setImageBitmap(avatar); + AppHelper.avatarsCache.put(url, avatarBytes); + } + }); }); - }); + } else { + RequestOptions requestOptions = new RequestOptions() + .placeholder(R.drawable.no_image_picture) + .error(R.drawable.no_image_picture); + if(fragment != null) { + Glide.with(fragment).setDefaultRequestOptions(requestOptions).load(url).into(imageView); + } else if(activity != null) { + Glide.with(activity).setDefaultRequestOptions(requestOptions).load(url).into(imageView); + } + } } } } diff --git a/app/src/main/java/io/github/chronosx88/influence/helpers/LocalDBWrapper.java b/app/src/main/java/io/github/chronosx88/influence/helpers/LocalDBWrapper.java index fe6aa1c..3ce84c2 100644 --- a/app/src/main/java/io/github/chronosx88/influence/helpers/LocalDBWrapper.java +++ b/app/src/main/java/io/github/chronosx88/influence/helpers/LocalDBWrapper.java @@ -21,6 +21,7 @@ import android.util.Log; import java.util.ArrayList; import java.util.List; +import io.github.chronosx88.influence.models.GenericUser; import io.github.chronosx88.influence.models.roomEntities.ChatEntity; import io.github.chronosx88.influence.models.roomEntities.MessageEntity; @@ -28,8 +29,8 @@ public class LocalDBWrapper { private static final String LOG_TAG = "LocalDBWrapper"; private static RoomHelper dbInstance = AppHelper.getChatDB(); - public static void createChatEntry(String jid, String chatName) { - dbInstance.chatDao().addChat(new ChatEntity(jid, chatName, new ArrayList<>(), 0, "")); + public static void createChatEntry(String jid, String chatName, ArrayList users) { + dbInstance.chatDao().addChat(new ChatEntity(jid, chatName, users, 0, "")); } public static long createMessageEntry(String chatID, String messageUid, String senderJid, long timestamp, String text, boolean isSent, boolean isRead) { diff --git a/app/src/main/java/io/github/chronosx88/influence/helpers/NetworkHandler.java b/app/src/main/java/io/github/chronosx88/influence/helpers/NetworkHandler.java index 18bbe8a..1edd164 100644 --- a/app/src/main/java/io/github/chronosx88/influence/helpers/NetworkHandler.java +++ b/app/src/main/java/io/github/chronosx88/influence/helpers/NetworkHandler.java @@ -45,11 +45,13 @@ import org.jxmpp.jid.Jid; import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.stringprep.XmppStringprepException; +import java.util.ArrayList; import java.util.Random; import java.util.concurrent.ExecutionException; import io.github.chronosx88.influence.R; import io.github.chronosx88.influence.models.GenericMessage; +import io.github.chronosx88.influence.models.GenericUser; import io.github.chronosx88.influence.models.appEvents.LastMessageEvent; import io.github.chronosx88.influence.models.appEvents.NewMessageEvent; import io.github.chronosx88.influence.models.appEvents.UserPresenceChangedEvent; @@ -69,7 +71,10 @@ public class NetworkHandler implements IncomingChatMessageListener, PresenceEven public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) { String chatID = chat.getXmppAddressOfChatPartner().asUnescapedString(); if(LocalDBWrapper.getChatByChatID(from.asEntityBareJidString()) == null) { - LocalDBWrapper.createChatEntry(chatID, chat.getXmppAddressOfChatPartner().asBareJid().asUnescapedString().split("@")[0]); + ArrayList users = new ArrayList<>(); + users.add(new GenericUser(AppHelper.getJid(), AppHelper.getJid().split("@")[0], AppHelper.getJid())); + users.add(new GenericUser(chat.getXmppAddressOfChatPartner().asBareJid().asUnescapedString(), chat.getXmppAddressOfChatPartner().asBareJid().asUnescapedString().split("@")[0], chat.getXmppAddressOfChatPartner().asBareJid().asUnescapedString())); + LocalDBWrapper.createChatEntry(chatID, chat.getXmppAddressOfChatPartner().asBareJid().asUnescapedString().split("@")[0], users); } long messageID = LocalDBWrapper.createMessageEntry(chatID, message.getStanzaId(), from.asUnescapedString(), TrueTime.now().getTime(), message.getBody(), true, false); int newUnreadMessagesCount = LocalDBWrapper.getChatByChatID(chatID).unreadMessagesCount + 1; diff --git a/app/src/main/java/io/github/chronosx88/influence/helpers/RoomTypeConverter.java b/app/src/main/java/io/github/chronosx88/influence/helpers/RoomTypeConverter.java index 277824a..fa56221 100644 --- a/app/src/main/java/io/github/chronosx88/influence/helpers/RoomTypeConverter.java +++ b/app/src/main/java/io/github/chronosx88/influence/helpers/RoomTypeConverter.java @@ -30,7 +30,7 @@ public class RoomTypeConverter { @TypeConverter public static ArrayList fromString(String value) { - Type listType = new TypeToken>() {}.getType(); + Type listType = new TypeToken>() {}.getType(); return new Gson().fromJson(value, listType); } diff --git a/app/src/main/java/io/github/chronosx88/influence/models/GenericMessage.java b/app/src/main/java/io/github/chronosx88/influence/models/GenericMessage.java index 0509958..ebd3dd0 100644 --- a/app/src/main/java/io/github/chronosx88/influence/models/GenericMessage.java +++ b/app/src/main/java/io/github/chronosx88/influence/models/GenericMessage.java @@ -16,26 +16,31 @@ package io.github.chronosx88.influence.models; +import androidx.annotation.Nullable; + import com.stfalcon.chatkit.commons.models.IMessage; import com.stfalcon.chatkit.commons.models.IUser; +import com.stfalcon.chatkit.commons.models.MessageContentType; import java.util.Date; import io.github.chronosx88.influence.models.roomEntities.MessageEntity; -public class GenericMessage implements IMessage { +public class GenericMessage implements IMessage, MessageContentType.Image { private long messageID; - private String messageUid; private IUser author; private long timestamp; private String text; + private String imageUrl; public GenericMessage(MessageEntity messageEntity) { this.messageID = messageEntity.messageID; - this.messageUid = messageEntity.messageUid; this.author = new GenericUser(messageEntity.senderJid, messageEntity.senderJid, messageEntity.senderJid); this.timestamp = messageEntity.timestamp; this.text = messageEntity.text; + if(messageEntity.text.contains("http") && messageEntity.text.contains(".jpg")) { + imageUrl = messageEntity.text; + } } @Override @@ -58,7 +63,9 @@ public class GenericMessage implements IMessage { return new Date(timestamp); } - public String getMessageUid() { - return messageUid; + @Nullable + @Override + public String getImageUrl() { + return imageUrl; } } diff --git a/app/src/main/java/io/github/chronosx88/influence/presenters/ChatPresenter.kt b/app/src/main/java/io/github/chronosx88/influence/presenters/ChatPresenter.kt index 1cef65b..fcbebb3 100644 --- a/app/src/main/java/io/github/chronosx88/influence/presenters/ChatPresenter.kt +++ b/app/src/main/java/io/github/chronosx88/influence/presenters/ChatPresenter.kt @@ -55,7 +55,7 @@ class ChatPresenter(private val view: CoreContracts.IChatViewContract, private v gson = Gson() val holdersConfig = MessageHolders() holdersConfig.setIncomingTextLayout(R.layout.item_incoming_text_message_custom) - chatAdapter = MessagesListAdapter(AppHelper.getJid(), holdersConfig, AvatarImageLoader()) + chatAdapter = MessagesListAdapter(AppHelper.getJid(), holdersConfig, AvatarImageLoader(view.getActivityObject())) chatAdapter.setLoadMoreListener { page, _ -> loadMoreMessages() } view.setAdapter(chatAdapter) getUserStatus() diff --git a/app/src/main/java/io/github/chronosx88/influence/presenters/DialogListPresenter.java b/app/src/main/java/io/github/chronosx88/influence/presenters/DialogListPresenter.java index 6087941..1beff5e 100644 --- a/app/src/main/java/io/github/chronosx88/influence/presenters/DialogListPresenter.java +++ b/app/src/main/java/io/github/chronosx88/influence/presenters/DialogListPresenter.java @@ -38,6 +38,7 @@ import io.github.chronosx88.influence.helpers.LocalDBWrapper; import io.github.chronosx88.influence.logic.DialogListLogic; import io.github.chronosx88.influence.models.GenericDialog; import io.github.chronosx88.influence.models.GenericMessage; +import io.github.chronosx88.influence.models.GenericUser; import io.github.chronosx88.influence.models.appEvents.AuthenticationStatusEvent; import io.github.chronosx88.influence.models.appEvents.LastMessageEvent; import io.github.chronosx88.influence.models.appEvents.NewChatEvent; @@ -48,10 +49,9 @@ import java8.util.stream.StreamSupport; import java9.util.concurrent.CompletableFuture; public class DialogListPresenter implements CoreContracts.IDialogListPresenterContract { - private ConcurrentHashMap avatarsMap = new ConcurrentHashMap<>(); - private CoreContracts.IChatListViewContract view; + private CoreContracts.IDialogListViewContract view; private CoreContracts.IDialogListLogicContract logic; - private DialogsListAdapter dialogListAdapter = new DialogsListAdapter<>(R.layout.item_dialog_custom, new AvatarImageLoader()); + private DialogsListAdapter dialogListAdapter; private Comparator dialogComparator = (dialog1, dialog2) -> { if(dialog2.getLastMessage() != null && dialog1.getLastMessage() != null) { return Long.compare(dialog2.getLastMessage().getCreatedAt().getTime(), dialog1.getLastMessage().getCreatedAt().getTime()); @@ -64,8 +64,9 @@ public class DialogListPresenter implements CoreContracts.IDialogListPresenterCo return 0; }; - public DialogListPresenter(CoreContracts.IChatListViewContract view) { + public DialogListPresenter(CoreContracts.IDialogListViewContract view) { this.view = view; + dialogListAdapter = new DialogsListAdapter<>(R.layout.item_dialog_custom, new AvatarImageLoader(view.getFragmentObject())); dialogListAdapter.setOnDialogClickListener(dialog -> openChat(dialog.getId())); dialogListAdapter.setOnDialogLongClickListener(dialog -> { AlertDialog.Builder builder = new AlertDialog.Builder(view.getActivityContext()); @@ -147,7 +148,10 @@ public class DialogListPresenter implements CoreContracts.IDialogListPresenterCo if(contacts != null) { StreamSupport.stream(contacts).forEach(contact -> { String chatID = contact.getJid().asUnescapedString(); - LocalDBWrapper.createChatEntry(chatID, contact.getName() == null ? contact.getJid().asUnescapedString().split("@")[0] : contact.getName()); + ArrayList users = new ArrayList<>(); + users.add(new GenericUser(AppHelper.getJid(), AppHelper.getJid().split("@")[0], AppHelper.getJid())); + users.add(new GenericUser(chatID, contact.getName() == null ? contact.getJid().asUnescapedString().split("@")[0] : contact.getName(), chatID)); + LocalDBWrapper.createChatEntry(chatID, contact.getName() == null ? contact.getJid().asUnescapedString().split("@")[0] : contact.getName(), users); GenericDialog dialog = new GenericDialog(LocalDBWrapper.getChatByChatID(chatID)); MessageEntity messageEntity = LocalDBWrapper.getLastMessage(chatID); if(messageEntity != null) { diff --git a/app/src/main/java/io/github/chronosx88/influence/presenters/MainPresenter.kt b/app/src/main/java/io/github/chronosx88/influence/presenters/MainPresenter.kt index be6a562..b5f254f 100644 --- a/app/src/main/java/io/github/chronosx88/influence/presenters/MainPresenter.kt +++ b/app/src/main/java/io/github/chronosx88/influence/presenters/MainPresenter.kt @@ -23,6 +23,7 @@ import io.github.chronosx88.influence.contracts.CoreContracts import io.github.chronosx88.influence.helpers.AppHelper import io.github.chronosx88.influence.helpers.LocalDBWrapper import io.github.chronosx88.influence.logic.MainLogic +import io.github.chronosx88.influence.models.GenericUser import io.github.chronosx88.influence.models.appEvents.AuthenticationStatusEvent import io.github.chronosx88.influence.models.appEvents.NewChatEvent import io.github.chronosx88.influence.views.LoginActivity @@ -47,7 +48,10 @@ class MainPresenter(private val view: CoreContracts.IMainViewContract) : CoreCon view.showSnackbar(AppHelper.getContext().getString(R.string.invalid_jid_error)) return } - LocalDBWrapper.createChatEntry(username, username.split("@")[0]) + val users = ArrayList() + users.add(GenericUser(AppHelper.getJid(), AppHelper.getJid().split("@")[0], AppHelper.getJid())) + users.add(GenericUser(username, username.split("@")[0], AppHelper.getJid())) + LocalDBWrapper.createChatEntry(username, username.split("@")[0], users) EventBus.getDefault().post(NewChatEvent(username)) } diff --git a/app/src/main/java/io/github/chronosx88/influence/views/ChatActivity.kt b/app/src/main/java/io/github/chronosx88/influence/views/ChatActivity.kt index 6b57823..f0f610c 100644 --- a/app/src/main/java/io/github/chronosx88/influence/views/ChatActivity.kt +++ b/app/src/main/java/io/github/chronosx88/influence/views/ChatActivity.kt @@ -16,6 +16,7 @@ package io.github.chronosx88.influence.views +import android.app.Activity import android.content.Intent import android.graphics.BitmapFactory import android.os.Bundle @@ -122,4 +123,8 @@ class ChatActivity : AppCompatActivity(), CoreContracts.IChatViewContract { super.onResume() presenter!!.loadRecentPageMessages() } + + override fun getActivityObject(): Activity { + return this + } } diff --git a/app/src/main/java/io/github/chronosx88/influence/views/fragments/DialogListFragment.kt b/app/src/main/java/io/github/chronosx88/influence/views/fragments/DialogListFragment.kt index 2543496..8c43593 100644 --- a/app/src/main/java/io/github/chronosx88/influence/views/fragments/DialogListFragment.kt +++ b/app/src/main/java/io/github/chronosx88/influence/views/fragments/DialogListFragment.kt @@ -16,6 +16,7 @@ package io.github.chronosx88.influence.views.fragments +import android.app.Activity import android.content.Context import android.os.Bundle import android.view.LayoutInflater @@ -30,7 +31,7 @@ import io.github.chronosx88.influence.models.GenericDialog import io.github.chronosx88.influence.presenters.DialogListPresenter -class DialogListFragment : Fragment(), CoreContracts.IChatListViewContract { +class DialogListFragment : Fragment(), CoreContracts.IDialogListViewContract { private lateinit var presenter: CoreContracts.IDialogListPresenterContract private lateinit var dialogList: DialogsList @@ -62,4 +63,8 @@ class DialogListFragment : Fragment(), CoreContracts.IChatListViewContract { presenter.onStop() super.onStop() } + + override fun getFragmentObject(): Fragment { + return this + } } diff --git a/app/src/main/res/drawable/no_image_picture.png b/app/src/main/res/drawable/no_image_picture.png new file mode 100644 index 0000000000000000000000000000000000000000..0558c9322a0d527f5eb9d42d371c1bbbed156b05 GIT binary patch literal 748 zcmV006240{{R3IW!vp0000UP)t-s|NsBF zxw*>9%G1-+#l^+j+uQi~_~z#3@$vD$zrSOIEc*Ze0*OgPK~#9!?b}Oh6Hyq(@t4$@ zob8hfHoLUK0e1$mbZJCfcck8SgBG>BikHS+6gOFp3-#j~%bVxkQv9 z(2>NG76|l1;%Wam-jhuo1Gp*iw1ZYji@23L0EV)$J)kS=v67XnR9X3UlB=&Y$H4ce z$}7_sm>V4FuKbFHZmzk~ee4)&u6%`3UvuR(=jSTy_Ib^yLu~k;PmxY-hk5; z&ue{^9r;(fpX;bRy{Pgftd7cyE}rh8ldGs~!Rh-`0#-$30%zBs67w-NRGI>nNB)#^ zRzsy^sGRvzF2>YQd4f{MpK`%!s5I{2{*>jI3M%D888h{!ELjbe=I>|+{*-P^1(nji z4Ga#&o6@lwDkc5+?34IYu8gUn^3tCMtjMCdOStS?GYg77Ts@O8IwJAMTMP=5>Yg77TD!6z8*xHmHt61@9;acj-6PQLYvXVpv3j5Sr(w@lniZw9@US@k|Pg{sQh#S@h545}(?TV^Qr#(FCg zEa|FTy?Ca!a%IZ|O{mQDRxU4|KyT%8%d82N2^3eli)WfEt1S~Wq4JCB%2p#Po3Ujx zDtYniR>_NBx5{Q+{LT60CJX1={{}|s|1VpOsBFfT&8XzX|DPo2fg)4Hf7)YkcN6!v z@Jxz96Q1vp5dz(jh)xk^kV{1E0zrOCRG-79Jd>!*2muZyGV}Q1rXD;OA|fIpA|fIp eA|fKXa=!tOT~AfYbhjY@0000