From cebfb33ff820a06eda2a79414d1ad1ffb38e9f5d Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Fri, 24 May 2019 16:05:11 +0400 Subject: [PATCH] Made global (in memory) avatar cache and round avatars in ChatActivity --- .../influence/helpers/AppHelper.java | 7 +- .../influence/helpers/AvatarImageLoader.java | 73 +++++++++++++++++++ .../influence/presenters/ChatPresenter.kt | 30 ++------ .../presenters/DialogListPresenter.java | 40 +--------- .../item_incoming_text_message_custom.xml | 66 +++++++++++++++++ 5 files changed, 153 insertions(+), 63 deletions(-) create mode 100644 app/src/main/java/io/github/chronosx88/influence/helpers/AvatarImageLoader.java create mode 100644 app/src/main/res/layout/item_incoming_text_message_custom.xml diff --git a/app/src/main/java/io/github/chronosx88/influence/helpers/AppHelper.java b/app/src/main/java/io/github/chronosx88/influence/helpers/AppHelper.java index 668af74..0bc1a65 100644 --- a/app/src/main/java/io/github/chronosx88/influence/helpers/AppHelper.java +++ b/app/src/main/java/io/github/chronosx88/influence/helpers/AppHelper.java @@ -30,6 +30,8 @@ import androidx.room.Room; import com.instacart.library.truetime.TrueTime; import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import io.github.chronosx88.influence.LoginCredentials; import io.github.chronosx88.influence.XMPPConnection; @@ -49,6 +51,7 @@ public class AppHelper extends MultiDexApplication { private static LoginCredentials currentLoginCredentials; private static Handler mainUIThreadHandler; private static ServiceConnection serviceConnection; + public final static Map avatarsCache = new ConcurrentHashMap<>(); @Override public void onCreate() { @@ -107,12 +110,14 @@ public class AppHelper extends MultiDexApplication { private static void initTrueTime() { new Thread(() -> { boolean isTrueTimeIsOn = false; - while(!isTrueTimeIsOn) { + int count = 0; + while(!isTrueTimeIsOn && count <= 10) { try { TrueTime.build().withNtpHost(DEFAULT_NTP_SERVER).initialize(); isTrueTimeIsOn = true; } catch (IOException e) { e.printStackTrace(); + count++; } } }).start(); 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 new file mode 100644 index 0000000..265dba5 --- /dev/null +++ b/app/src/main/java/io/github/chronosx88/influence/helpers/AvatarImageLoader.java @@ -0,0 +1,73 @@ +/* + * Copyright 2019 ChronosX88 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.github.chronosx88.influence.helpers; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.widget.ImageView; + +import androidx.annotation.Nullable; + +import com.amulyakhare.textdrawable.TextDrawable; +import com.amulyakhare.textdrawable.util.ColorGenerator; +import com.stfalcon.chatkit.commons.ImageLoader; + +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; + +import java9.util.concurrent.CompletableFuture; + +public class AvatarImageLoader implements ImageLoader { + @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(); + } + 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); + } + }); + }); + } + } +} 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 92d9a3f..3eed4b3 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 @@ -21,10 +21,12 @@ import com.amulyakhare.textdrawable.TextDrawable import com.amulyakhare.textdrawable.util.ColorGenerator import com.google.gson.Gson import com.stfalcon.chatkit.commons.ImageLoader +import com.stfalcon.chatkit.messages.MessageHolders import com.stfalcon.chatkit.messages.MessagesListAdapter import io.github.chronosx88.influence.R import io.github.chronosx88.influence.contracts.CoreContracts import io.github.chronosx88.influence.helpers.AppHelper +import io.github.chronosx88.influence.helpers.AvatarImageLoader import io.github.chronosx88.influence.helpers.LocalDBWrapper import io.github.chronosx88.influence.logic.ChatLogic import io.github.chronosx88.influence.models.GenericMessage @@ -50,31 +52,9 @@ class ChatPresenter(private val view: CoreContracts.IChatViewContract, private v this.logic = ChatLogic(LocalDBWrapper.getChatByChatID(chatID)!!) this.chatEntity = LocalDBWrapper.getChatByChatID(chatID) gson = Gson() - chatAdapter = MessagesListAdapter(AppHelper.getJid(), ImageLoader { imageView, url, _ -> - val firstLetter = Character.toString(Character.toUpperCase(url!!.get(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) ; - var jid: EntityBareJid? = null - try { - jid = JidCreate.entityBareFrom(url) - } catch (e: XmppStringprepException) { - e.printStackTrace() - } - - AppHelper.getXmppConnection().getAvatar(jid) }.thenAccept { avatarBytes -> AppHelper.getMainUIThread().post { - if (avatarBytes != null) { - val avatar = BitmapFactory.decodeByteArray(avatarBytes, 0, avatarBytes.size) - imageView.setImageBitmap(avatar) - } - } - } - }) + val holdersConfig = MessageHolders() + holdersConfig.setIncomingTextLayout(R.layout.item_incoming_text_message_custom) + chatAdapter = MessagesListAdapter(AppHelper.getJid(), holdersConfig, AvatarImageLoader()) view.setAdapter(chatAdapter) EventBus.getDefault().register(this) } 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 11907b4..36b6e9d 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 @@ -43,6 +43,7 @@ import java.util.concurrent.ConcurrentHashMap; import io.github.chronosx88.influence.R; import io.github.chronosx88.influence.contracts.CoreContracts; import io.github.chronosx88.influence.helpers.AppHelper; +import io.github.chronosx88.influence.helpers.AvatarImageLoader; import io.github.chronosx88.influence.helpers.LocalDBWrapper; import io.github.chronosx88.influence.logic.DialogListLogic; import io.github.chronosx88.influence.models.GenericDialog; @@ -60,42 +61,7 @@ public class DialogListPresenter implements CoreContracts.IDialogListPresenterCo private ConcurrentHashMap avatarsMap = new ConcurrentHashMap<>(); private CoreContracts.IChatListViewContract view; private CoreContracts.IDialogListLogicContract logic; - private DialogsListAdapter dialogListAdapter = new DialogsListAdapter<>(R.layout.item_dialog_custom, (imageView, url, payload) -> { - if(url.length() != 0) { - if(avatarsMap.containsKey(url)) { - byte[] avatarBytes = avatarsMap.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(); - } - return AppHelper.getXmppConnection().getAvatar(jid); - }).thenAccept((avatarBytes) -> { - AppHelper.getMainUIThread().post(() -> { - if(avatarBytes != null) { - Bitmap avatar = BitmapFactory.decodeByteArray(avatarBytes, 0, avatarBytes.length); - imageView.setImageBitmap(avatar); - avatarsMap.put(url, avatarBytes); - } - }); - }); - } - }); + private DialogsListAdapter dialogListAdapter = new DialogsListAdapter<>(R.layout.item_dialog_custom, new AvatarImageLoader()); private Comparator dialogComparator = (dialog1, dialog2) -> Long.compare(dialog2.getLastMessage().getCreatedAt().getTime(), dialog1.getLastMessage().getCreatedAt().getTime()); public DialogListPresenter(CoreContracts.IChatListViewContract view) { @@ -147,7 +113,7 @@ public class DialogListPresenter implements CoreContracts.IDialogListPresenterCo Intent intent = new Intent(AppHelper.getContext(), ChatActivity.class); intent.putExtra("chatID", chatID); intent.putExtra("chatName", LocalDBWrapper.getChatByChatID(chatID).chatName); - intent.putExtra("chatAvatar", avatarsMap.get(chatID)); + intent.putExtra("chatAvatar", AppHelper.avatarsCache.get(chatID)); view.startActivity(intent); } diff --git a/app/src/main/res/layout/item_incoming_text_message_custom.xml b/app/src/main/res/layout/item_incoming_text_message_custom.xml new file mode 100644 index 0000000..274b6ce --- /dev/null +++ b/app/src/main/res/layout/item_incoming_text_message_custom.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + \ No newline at end of file