mirror of
https://github.com/ChronosX88/Influence.git
synced 2024-11-23 18:12:18 +00:00
Made global (in memory) avatar cache and round avatars in ChatActivity
This commit is contained in:
parent
6c83e7d9e0
commit
cebfb33ff8
@ -30,6 +30,8 @@ import androidx.room.Room;
|
|||||||
import com.instacart.library.truetime.TrueTime;
|
import com.instacart.library.truetime.TrueTime;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import io.github.chronosx88.influence.LoginCredentials;
|
import io.github.chronosx88.influence.LoginCredentials;
|
||||||
import io.github.chronosx88.influence.XMPPConnection;
|
import io.github.chronosx88.influence.XMPPConnection;
|
||||||
@ -49,6 +51,7 @@ public class AppHelper extends MultiDexApplication {
|
|||||||
private static LoginCredentials currentLoginCredentials;
|
private static LoginCredentials currentLoginCredentials;
|
||||||
private static Handler mainUIThreadHandler;
|
private static Handler mainUIThreadHandler;
|
||||||
private static ServiceConnection serviceConnection;
|
private static ServiceConnection serviceConnection;
|
||||||
|
public final static Map<String, byte[]> avatarsCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
@ -107,12 +110,14 @@ public class AppHelper extends MultiDexApplication {
|
|||||||
private static void initTrueTime() {
|
private static void initTrueTime() {
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
boolean isTrueTimeIsOn = false;
|
boolean isTrueTimeIsOn = false;
|
||||||
while(!isTrueTimeIsOn) {
|
int count = 0;
|
||||||
|
while(!isTrueTimeIsOn && count <= 10) {
|
||||||
try {
|
try {
|
||||||
TrueTime.build().withNtpHost(DEFAULT_NTP_SERVER).initialize();
|
TrueTime.build().withNtpHost(DEFAULT_NTP_SERVER).initialize();
|
||||||
isTrueTimeIsOn = true;
|
isTrueTimeIsOn = true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -21,10 +21,12 @@ import com.amulyakhare.textdrawable.TextDrawable
|
|||||||
import com.amulyakhare.textdrawable.util.ColorGenerator
|
import com.amulyakhare.textdrawable.util.ColorGenerator
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.stfalcon.chatkit.commons.ImageLoader
|
import com.stfalcon.chatkit.commons.ImageLoader
|
||||||
|
import com.stfalcon.chatkit.messages.MessageHolders
|
||||||
import com.stfalcon.chatkit.messages.MessagesListAdapter
|
import com.stfalcon.chatkit.messages.MessagesListAdapter
|
||||||
import io.github.chronosx88.influence.R
|
import io.github.chronosx88.influence.R
|
||||||
import io.github.chronosx88.influence.contracts.CoreContracts
|
import io.github.chronosx88.influence.contracts.CoreContracts
|
||||||
import io.github.chronosx88.influence.helpers.AppHelper
|
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.helpers.LocalDBWrapper
|
||||||
import io.github.chronosx88.influence.logic.ChatLogic
|
import io.github.chronosx88.influence.logic.ChatLogic
|
||||||
import io.github.chronosx88.influence.models.GenericMessage
|
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.logic = ChatLogic(LocalDBWrapper.getChatByChatID(chatID)!!)
|
||||||
this.chatEntity = LocalDBWrapper.getChatByChatID(chatID)
|
this.chatEntity = LocalDBWrapper.getChatByChatID(chatID)
|
||||||
gson = Gson()
|
gson = Gson()
|
||||||
chatAdapter = MessagesListAdapter(AppHelper.getJid(), ImageLoader { imageView, url, _ ->
|
val holdersConfig = MessageHolders()
|
||||||
val firstLetter = Character.toString(Character.toUpperCase(url!!.get(0)))
|
holdersConfig.setIncomingTextLayout(R.layout.item_incoming_text_message_custom)
|
||||||
imageView.setImageDrawable(TextDrawable.builder()
|
chatAdapter = MessagesListAdapter(AppHelper.getJid(), holdersConfig, AvatarImageLoader())
|
||||||
.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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
view.setAdapter(chatAdapter)
|
view.setAdapter(chatAdapter)
|
||||||
EventBus.getDefault().register(this)
|
EventBus.getDefault().register(this)
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import io.github.chronosx88.influence.R;
|
import io.github.chronosx88.influence.R;
|
||||||
import io.github.chronosx88.influence.contracts.CoreContracts;
|
import io.github.chronosx88.influence.contracts.CoreContracts;
|
||||||
import io.github.chronosx88.influence.helpers.AppHelper;
|
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.helpers.LocalDBWrapper;
|
||||||
import io.github.chronosx88.influence.logic.DialogListLogic;
|
import io.github.chronosx88.influence.logic.DialogListLogic;
|
||||||
import io.github.chronosx88.influence.models.GenericDialog;
|
import io.github.chronosx88.influence.models.GenericDialog;
|
||||||
@ -60,42 +61,7 @@ public class DialogListPresenter implements CoreContracts.IDialogListPresenterCo
|
|||||||
private ConcurrentHashMap<String, byte[]> avatarsMap = new ConcurrentHashMap<>();
|
private ConcurrentHashMap<String, byte[]> avatarsMap = new ConcurrentHashMap<>();
|
||||||
private CoreContracts.IChatListViewContract view;
|
private CoreContracts.IChatListViewContract view;
|
||||||
private CoreContracts.IDialogListLogicContract logic;
|
private CoreContracts.IDialogListLogicContract logic;
|
||||||
private DialogsListAdapter<GenericDialog> dialogListAdapter = new DialogsListAdapter<>(R.layout.item_dialog_custom, (imageView, url, payload) -> {
|
private DialogsListAdapter<GenericDialog> dialogListAdapter = new DialogsListAdapter<>(R.layout.item_dialog_custom, new AvatarImageLoader());
|
||||||
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 Comparator<GenericDialog> dialogComparator = (dialog1, dialog2) -> Long.compare(dialog2.getLastMessage().getCreatedAt().getTime(), dialog1.getLastMessage().getCreatedAt().getTime());
|
private Comparator<GenericDialog> dialogComparator = (dialog1, dialog2) -> Long.compare(dialog2.getLastMessage().getCreatedAt().getTime(), dialog1.getLastMessage().getCreatedAt().getTime());
|
||||||
|
|
||||||
public DialogListPresenter(CoreContracts.IChatListViewContract view) {
|
public DialogListPresenter(CoreContracts.IChatListViewContract view) {
|
||||||
@ -147,7 +113,7 @@ public class DialogListPresenter implements CoreContracts.IDialogListPresenterCo
|
|||||||
Intent intent = new Intent(AppHelper.getContext(), ChatActivity.class);
|
Intent intent = new Intent(AppHelper.getContext(), ChatActivity.class);
|
||||||
intent.putExtra("chatID", chatID);
|
intent.putExtra("chatID", chatID);
|
||||||
intent.putExtra("chatName", LocalDBWrapper.getChatByChatID(chatID).chatName);
|
intent.putExtra("chatName", LocalDBWrapper.getChatByChatID(chatID).chatName);
|
||||||
intent.putExtra("chatAvatar", avatarsMap.get(chatID));
|
intent.putExtra("chatAvatar", AppHelper.avatarsCache.get(chatID));
|
||||||
view.startActivity(intent);
|
view.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginTop="8dp">
|
||||||
|
|
||||||
|
<de.hdodenhof.circleimageview.CircleImageView
|
||||||
|
android:id="@id/messageUserAvatar"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginRight="8dp"/>
|
||||||
|
|
||||||
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
|
android:id="@id/bubble"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="@dimen/message_incoming_bubble_margin_right"
|
||||||
|
android:layout_marginRight="@dimen/message_incoming_bubble_margin_right"
|
||||||
|
android:layout_toEndOf="@id/messageUserAvatar"
|
||||||
|
android:layout_toRightOf="@id/messageUserAvatar"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:alignContent="stretch"
|
||||||
|
app:alignItems="stretch"
|
||||||
|
app:flexWrap="wrap"
|
||||||
|
app:justifyContent="flex_end">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@id/messageText"
|
||||||
|
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_marginLeft="8dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
app:layout_alignSelf="center"/>
|
||||||
|
|
||||||
|
</com.google.android.flexbox.FlexboxLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
Loading…
Reference in New Issue
Block a user