Made showing last message ans changed default NTP server

This commit is contained in:
ChronosX88 2019-05-24 14:33:06 +04:00
parent 0168cc5ad8
commit 6cc21659d2
10 changed files with 122 additions and 34 deletions

View File

@ -40,7 +40,7 @@ import io.github.chronosx88.influence.XMPPConnection;
public class AppHelper extends MultiDexApplication { public class AppHelper extends MultiDexApplication {
private static Application instance; private static Application instance;
public final static String APP_NAME = "Influence"; public final static String APP_NAME = "Influence";
public final static String DEFAULT_NTP_SERVER = "0.europe.pool.ntp.org"; public final static String DEFAULT_NTP_SERVER = "time.apple.com";
private static String jid; private static String jid;
private static RoomHelper chatDB; private static RoomHelper chatDB;

View File

@ -79,4 +79,9 @@ public class LocalDBWrapper {
dbInstance.messageDao().clearMessages(); dbInstance.messageDao().clearMessages();
dbInstance.chatDao().clearChats(); dbInstance.chatDao().clearChats();
} }
public static MessageEntity getLastMessage(String chatID) {
long messageID = dbInstance.messageDao().getLastMessageByChatID(chatID);
return getMessageByID(messageID);
}
} }

View File

@ -24,6 +24,8 @@ import org.jivesoftware.smack.chat2.IncomingChatMessageListener;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.EntityBareJid;
import io.github.chronosx88.influence.models.GenericMessage;
import io.github.chronosx88.influence.models.appEvents.LastMessageEvent;
import io.github.chronosx88.influence.models.appEvents.NewMessageEvent; import io.github.chronosx88.influence.models.appEvents.NewMessageEvent;
public class NetworkHandler implements IncomingChatMessageListener { public class NetworkHandler implements IncomingChatMessageListener {
@ -37,5 +39,6 @@ public class NetworkHandler implements IncomingChatMessageListener {
long messageID = LocalDBWrapper.createMessageEntry(chat.getXmppAddressOfChatPartner().asUnescapedString(), from.asUnescapedString(), TrueTime.now().getTime(), message.getBody(), true, false); long messageID = LocalDBWrapper.createMessageEntry(chat.getXmppAddressOfChatPartner().asUnescapedString(), from.asUnescapedString(), TrueTime.now().getTime(), message.getBody(), true, false);
EventBus.getDefault().post(new NewMessageEvent(chat.getXmppAddressOfChatPartner().toString(), messageID)); EventBus.getDefault().post(new NewMessageEvent(chat.getXmppAddressOfChatPartner().toString(), messageID));
EventBus.getDefault().post(new LastMessageEvent(chat.getXmppAddressOfChatPartner().toString(), new GenericMessage(LocalDBWrapper.getMessageByID(messageID))));
} }
} }

View File

@ -22,6 +22,8 @@ import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.stringprep.XmppStringprepException; import org.jxmpp.stringprep.XmppStringprepException;
import java.io.IOException;
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.LocalDBWrapper; import io.github.chronosx88.influence.helpers.LocalDBWrapper;
@ -49,6 +51,13 @@ public class ChatLogic implements CoreContracts.IChatLogicContract {
return null; return null;
} }
AppHelper.getXmppConnection().sendMessage(jid, text); AppHelper.getXmppConnection().sendMessage(jid, text);
while (!TrueTime.isInitialized()) {
try {
TrueTime.build().initialize();
} catch (IOException e) {
e.printStackTrace();
}
}
long messageID = LocalDBWrapper.createMessageEntry(chatID, AppHelper.getJid(), TrueTime.now().getTime(), text, false, false); long messageID = LocalDBWrapper.createMessageEntry(chatID, AppHelper.getJid(), TrueTime.now().getTime(), text, false, false);
return LocalDBWrapper.getMessageByID(messageID); return LocalDBWrapper.getMessageByID(messageID);
} else { } else {

View File

@ -31,7 +31,7 @@ public class GenericMessage implements IMessage {
public GenericMessage(MessageEntity messageEntity) { public GenericMessage(MessageEntity messageEntity) {
this.messageID = messageEntity.messageID; this.messageID = messageEntity.messageID;
this.author = new GenericUser(messageEntity.senderJid, messageEntity.senderJid, ""); this.author = new GenericUser(messageEntity.senderJid, messageEntity.senderJid, messageEntity.senderJid);
this.timestamp = messageEntity.timestamp; this.timestamp = messageEntity.timestamp;
this.text = messageEntity.text; this.text = messageEntity.text;
} }

View File

@ -0,0 +1,29 @@
/*
* 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.models.appEvents;
import com.stfalcon.chatkit.commons.models.IMessage;
public class LastMessageEvent {
public final String chatID;
public final IMessage message;
public LastMessageEvent(String chatID, IMessage message) {
this.chatID = chatID;
this.message = message;
}
}

View File

@ -47,4 +47,7 @@ public interface MessageDao {
@Query("DELETE FROM messages") @Query("DELETE FROM messages")
void clearMessages(); void clearMessages();
@Query("SELECT messageID FROM messages WHERE jid = :chatID GROUP BY :chatID HAVING MAX(messageID)")
long getLastMessageByChatID(String chatID);
} }

View File

@ -28,6 +28,7 @@ import io.github.chronosx88.influence.helpers.AppHelper
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
import io.github.chronosx88.influence.models.appEvents.LastMessageEvent
import io.github.chronosx88.influence.models.appEvents.NewMessageEvent import io.github.chronosx88.influence.models.appEvents.NewMessageEvent
import io.github.chronosx88.influence.models.roomEntities.ChatEntity import io.github.chronosx88.influence.models.roomEntities.ChatEntity
import io.github.chronosx88.influence.models.roomEntities.MessageEntity import io.github.chronosx88.influence.models.roomEntities.MessageEntity
@ -81,7 +82,9 @@ class ChatPresenter(private val view: CoreContracts.IChatViewContract, private v
override fun sendMessage(text: String): Boolean { override fun sendMessage(text: String): Boolean {
val message: MessageEntity? = logic.sendMessage(text) val message: MessageEntity? = logic.sendMessage(text)
if(message != null) { if(message != null) {
chatAdapter.addToStart(GenericMessage(message), true) val message = GenericMessage(message)
chatAdapter.addToStart(message, true)
EventBus.getDefault().post(LastMessageEvent(chatEntity!!.jid, message))
return true return true
} }
return false return false

View File

@ -28,12 +28,15 @@ import com.stfalcon.chatkit.dialogs.DialogsListAdapter;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.jivesoftware.smack.roster.RosterEntry; import org.jivesoftware.smack.roster.RosterEntry;
import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.stringprep.XmppStringprepException; import org.jxmpp.stringprep.XmppStringprepException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -43,9 +46,12 @@ import io.github.chronosx88.influence.helpers.AppHelper;
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;
import io.github.chronosx88.influence.models.GenericMessage;
import io.github.chronosx88.influence.models.appEvents.AuthenticationStatusEvent; import io.github.chronosx88.influence.models.appEvents.AuthenticationStatusEvent;
import io.github.chronosx88.influence.models.appEvents.LastMessageEvent;
import io.github.chronosx88.influence.models.appEvents.NewChatEvent; import io.github.chronosx88.influence.models.appEvents.NewChatEvent;
import io.github.chronosx88.influence.models.appEvents.NewMessageEvent; import io.github.chronosx88.influence.models.appEvents.NewMessageEvent;
import io.github.chronosx88.influence.models.roomEntities.MessageEntity;
import io.github.chronosx88.influence.views.ChatActivity; import io.github.chronosx88.influence.views.ChatActivity;
import java8.util.stream.StreamSupport; import java8.util.stream.StreamSupport;
import java9.util.concurrent.CompletableFuture; import java9.util.concurrent.CompletableFuture;
@ -55,33 +61,42 @@ public class DialogListPresenter implements CoreContracts.IDialogListPresenterCo
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, (imageView, url, payload) -> {
String firstLetter = Character.toString(Character.toUpperCase(url.charAt(0))); if(url.length() != 0) {
imageView.setImageDrawable(TextDrawable.builder() if(avatarsMap.containsKey(url)) {
.beginConfig() byte[] avatarBytes = avatarsMap.get(url);
.width(64) Bitmap avatar = BitmapFactory.decodeByteArray(avatarBytes, 0, avatarBytes.length);
.height(64) imageView.setImageBitmap(avatar);
.endConfig() return;
.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); String firstLetter = Character.toString(Character.toUpperCase(url.charAt(0)));
}).thenAccept((avatarBytes) -> { imageView.setImageDrawable(TextDrawable.builder()
AppHelper.getMainUIThread().post(() -> { .beginConfig()
if(avatarBytes != null) { .width(64)
Bitmap avatar = BitmapFactory.decodeByteArray(avatarBytes, 0, avatarBytes.length); .height(64)
imageView.setImageBitmap(avatar); .endConfig()
avatarsMap.put(url, avatarBytes); .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());
public DialogListPresenter(CoreContracts.IChatListViewContract view) { public DialogListPresenter(CoreContracts.IChatListViewContract view) {
this.view = view; this.view = view;
@ -104,18 +119,27 @@ public class DialogListPresenter implements CoreContracts.IDialogListPresenterCo
ArrayList<GenericDialog> dialogs = new ArrayList<>(); ArrayList<GenericDialog> dialogs = new ArrayList<>();
StreamSupport.stream(logic.loadLocalChats()) StreamSupport.stream(logic.loadLocalChats())
.forEach(chatEntity -> dialogs.add(new GenericDialog(chatEntity))); .forEach(chatEntity -> dialogs.add(new GenericDialog(chatEntity)));
StreamSupport.stream(dialogs)
.forEach(dialog -> {
MessageEntity messageEntity = LocalDBWrapper.getLastMessage(dialog.getId());
if(messageEntity != null) {
dialog.setLastMessage(new GenericMessage(messageEntity));
}
});
dialogListAdapter.setItems(dialogs); dialogListAdapter.setItems(dialogs);
dialogListAdapter.sort(dialogComparator);
loadRemoteContactList(); loadRemoteContactList();
}
@Override
public void onStart() {
EventBus.getDefault().register(this); EventBus.getDefault().register(this);
} }
@Override
public void onStart() {
}
@Override @Override
public void onStop() { public void onStop() {
EventBus.getDefault().unregister(this);
} }
@Override @Override
@ -154,11 +178,23 @@ public class DialogListPresenter implements CoreContracts.IDialogListPresenterCo
AppHelper.getMainUIThread().post(() -> { AppHelper.getMainUIThread().post(() -> {
if(contacts != null) { if(contacts != null) {
StreamSupport.stream(contacts).forEach(contact -> { StreamSupport.stream(contacts).forEach(contact -> {
LocalDBWrapper.createChatEntry(contact.getJid().asUnescapedString(), contact.getName() == null ? contact.getJid().asUnescapedString().split("@")[0] : contact.getName()); String chatID = contact.getJid().asUnescapedString();
dialogListAdapter.upsertItem(new GenericDialog(LocalDBWrapper.getChatByChatID(contact.getJid().asUnescapedString()))); LocalDBWrapper.createChatEntry(chatID, contact.getName() == null ? contact.getJid().asUnescapedString().split("@")[0] : contact.getName());
GenericDialog dialog = new GenericDialog(LocalDBWrapper.getChatByChatID(chatID));
MessageEntity messageEntity = LocalDBWrapper.getLastMessage(chatID);
if(messageEntity != null) {
dialog.setLastMessage(new GenericMessage(messageEntity));
}
dialogListAdapter.upsertItem(dialog);
}); });
} }
}); });
}); });
} }
@Subscribe(threadMode = ThreadMode.MAIN)
public void onLastMessage(LastMessageEvent event) {
dialogListAdapter.updateDialogWithMessage(event.chatID, event.message);
dialogListAdapter.sort(dialogComparator);
}
} }

View File

@ -73,7 +73,7 @@
android:layout_toRightOf="@id/dialogAvatar" android:layout_toRightOf="@id/dialogAvatar"
android:layout_toStartOf="@+id/dialogUnreadBubble"> android:layout_toStartOf="@+id/dialogUnreadBubble">
<com.stfalcon.chatkit.utils.ShapeImageView <de.hdodenhof.circleimageview.CircleImageView
android:id="@id/dialogLastMessageUserAvatar" android:id="@id/dialogLastMessageUserAvatar"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"