Use ObservableList in LocalDB and Chat, reduce amount of UI refreshes
This commit is contained in:
@ -3,6 +3,8 @@ package envoy.client.data;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import javafx.collections.*;
|
||||
|
||||
import envoy.client.net.WriteProxy;
|
||||
import envoy.data.*;
|
||||
import envoy.data.Message.MessageStatus;
|
||||
@ -19,8 +21,9 @@ import envoy.event.MessageStatusChange;
|
||||
*/
|
||||
public class Chat implements Serializable {
|
||||
|
||||
protected final Contact recipient;
|
||||
protected final List<Message> messages = new ArrayList<>();
|
||||
protected final Contact recipient;
|
||||
|
||||
protected transient ObservableList<Message> messages = FXCollections.observableArrayList();
|
||||
|
||||
protected int unreadAmount;
|
||||
|
||||
@ -29,7 +32,7 @@ public class Chat implements Serializable {
|
||||
*/
|
||||
protected transient long lastWritingEvent;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final long serialVersionUID = 2L;
|
||||
|
||||
/**
|
||||
* Provides the list of messages that the recipient receives.
|
||||
@ -41,6 +44,16 @@ public class Chat implements Serializable {
|
||||
*/
|
||||
public Chat(Contact recipient) { this.recipient = recipient; }
|
||||
|
||||
private void readObject(ObjectInputStream stream) throws ClassNotFoundException, IOException {
|
||||
stream.defaultReadObject();
|
||||
messages = FXCollections.observableList((List<Message>) stream.readObject());
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream stream) throws IOException {
|
||||
stream.defaultWriteObject();
|
||||
stream.writeObject(new ArrayList<>(messages));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() { return String.format("%s[recipient=%s,messages=%d]", getClass().getSimpleName(), recipient, messages.size()); }
|
||||
|
||||
@ -72,11 +85,9 @@ public class Chat implements Serializable {
|
||||
*
|
||||
* @param writeProxy the write proxy instance used to notify the server about
|
||||
* the message status changes
|
||||
* @throws IOException if a {@link MessageStatusChange} could not be
|
||||
* delivered to the server
|
||||
* @since Envoy Client v0.3-alpha
|
||||
*/
|
||||
public void read(WriteProxy writeProxy) throws IOException {
|
||||
public void read(WriteProxy writeProxy) {
|
||||
for (int i = messages.size() - 1; i >= 0; --i) {
|
||||
final Message m = messages.get(i);
|
||||
if (m.getSenderID() == recipient.getID()) if (m.getStatus() == MessageStatus.READ) break;
|
||||
@ -127,7 +138,7 @@ public class Chat implements Serializable {
|
||||
* @return all messages in the current chat
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
public List<Message> getMessages() { return messages; }
|
||||
public ObservableList<Message> getMessages() { return messages; }
|
||||
|
||||
/**
|
||||
* @return the recipient of a message
|
||||
|
@ -1,6 +1,5 @@
|
||||
package envoy.client.data;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
|
||||
import envoy.client.net.WriteProxy;
|
||||
@ -32,7 +31,7 @@ public final class GroupChat extends Chat {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(WriteProxy writeProxy) throws IOException {
|
||||
public void read(WriteProxy writeProxy) {
|
||||
for (int i = messages.size() - 1; i >= 0; --i) {
|
||||
final GroupMessage gmsg = (GroupMessage) messages.get(i);
|
||||
if (gmsg.getSenderID() != sender.getID()) if (gmsg.getMemberStatuses().get(sender.getID()) == MessageStatus.READ) break;
|
||||
|
@ -7,6 +7,8 @@ import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.logging.*;
|
||||
|
||||
import javafx.collections.*;
|
||||
|
||||
import envoy.client.event.EnvoyCloseEvent;
|
||||
import envoy.data.*;
|
||||
import envoy.data.Message.MessageStatus;
|
||||
@ -30,12 +32,12 @@ import dev.kske.eventbus.EventListener;
|
||||
public final class LocalDB implements EventListener {
|
||||
|
||||
// Data
|
||||
private User user;
|
||||
private Map<String, User> users = Collections.synchronizedMap(new HashMap<>());
|
||||
private List<Chat> chats = Collections.synchronizedList(new ArrayList<>());
|
||||
private IDGenerator idGenerator;
|
||||
private CacheMap cacheMap = new CacheMap();
|
||||
private String authToken;
|
||||
private User user;
|
||||
private Map<String, User> users = Collections.synchronizedMap(new HashMap<>());
|
||||
private ObservableList<Chat> chats = FXCollections.observableArrayList();
|
||||
private IDGenerator idGenerator;
|
||||
private CacheMap cacheMap = new CacheMap();
|
||||
private String authToken;
|
||||
|
||||
// State management
|
||||
private Instant lastSync = Instant.EPOCH;
|
||||
@ -129,7 +131,7 @@ public final class LocalDB implements EventListener {
|
||||
if (user == null) throw new IllegalStateException("Client user is null, cannot initialize user storage");
|
||||
userFile = new File(dbDir, user.getID() + ".db");
|
||||
try (var in = new ObjectInputStream(new FileInputStream(userFile))) {
|
||||
chats = (List<Chat>) in.readObject();
|
||||
chats = FXCollections.observableList((List<Chat>) in.readObject());
|
||||
cacheMap = (CacheMap) in.readObject();
|
||||
lastSync = (Instant) in.readObject();
|
||||
} finally {
|
||||
@ -189,8 +191,8 @@ public final class LocalDB implements EventListener {
|
||||
SerializationUtils.write(usersFile, users);
|
||||
|
||||
// Save user data and last sync time stamp
|
||||
if (user != null)
|
||||
SerializationUtils.write(userFile, chats, cacheMap, Context.getInstance().getClient().isOnline() ? Instant.now() : lastSync);
|
||||
if (user != null) SerializationUtils
|
||||
.write(userFile, new ArrayList<>(chats), cacheMap, Context.getInstance().getClient().isOnline() ? Instant.now() : lastSync);
|
||||
|
||||
// Save last login information
|
||||
if (authToken != null) SerializationUtils.write(lastLoginFile, user, authToken);
|
||||
@ -212,10 +214,12 @@ public final class LocalDB implements EventListener {
|
||||
logger.warning("The groupMessage has the unexpected status " + msg.getStatus());
|
||||
}
|
||||
|
||||
@Event(priority = 150, includeSubtypes = true)
|
||||
private void onMessageStatusChange(MessageStatusChange evt) {
|
||||
// TODO: Cancel event once EventBus is updated
|
||||
if (evt.get().ordinal() < MessageStatus.RECEIVED.ordinal()) logger.warning("Received invalid " + evt);
|
||||
@Event(priority = 150)
|
||||
private void onMessageStatusChange(MessageStatusChange evt) { getMessage(evt.getID()).ifPresent(msg -> msg.setStatus(evt.get())); }
|
||||
|
||||
@Event(priority = 150)
|
||||
private void onGroupMessageStatusChange(GroupMessageStatusChange evt) {
|
||||
this.<GroupMessage>getMessage(evt.getID()).ifPresent(msg -> msg.getMemberStatuses().replace(evt.getMemberID(), evt.get()));
|
||||
}
|
||||
|
||||
@Event(priority = 150)
|
||||
@ -249,8 +253,8 @@ public final class LocalDB implements EventListener {
|
||||
* @return an optional containing the message
|
||||
* @since Envoy Client v0.1-beta
|
||||
*/
|
||||
public Optional<Message> getMessage(long id) {
|
||||
return chats.stream().map(Chat::getMessages).flatMap(List::stream).filter(m -> m.getID() == id).findAny();
|
||||
public <T extends Message> Optional<T> getMessage(long id) {
|
||||
return (Optional<T>) chats.stream().map(Chat::getMessages).flatMap(List::stream).filter(m -> m.getID() == id).findAny();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -267,12 +271,7 @@ public final class LocalDB implements EventListener {
|
||||
* sender
|
||||
* @since Envoy Client v0.1-alpha
|
||||
**/
|
||||
public List<Chat> getChats() { return chats; }
|
||||
|
||||
/**
|
||||
* @param chats the chats to set
|
||||
*/
|
||||
public void setChats(List<Chat> chats) { this.chats = chats; }
|
||||
public ObservableList<Chat> getChats() { return chats; }
|
||||
|
||||
/**
|
||||
* @return the {@link User} who initialized the local database
|
||||
|
Reference in New Issue
Block a user