Listening to message status changes, sending READ status updates

This commit is contained in:
Kai S. K. Engelbart 2020-02-05 07:09:25 +01:00
parent 7424cc900f
commit b6167ce166
4 changed files with 104 additions and 17 deletions

View File

@ -1,11 +1,14 @@
package envoy.client; package envoy.client;
import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import envoy.client.net.Client;
import envoy.client.ui.list.ComponentListModel; import envoy.client.ui.list.ComponentListModel;
import envoy.data.Message; import envoy.data.Message;
import envoy.data.Message.MessageStatus; import envoy.data.Message.MessageStatus;
import envoy.data.User; import envoy.data.User;
import envoy.event.MessageStatusChangeEvent;
/** /**
* Represents a chat between two {@link User}s <br> * Represents a chat between two {@link User}s <br>
@ -49,13 +52,24 @@ public class Chat implements Serializable {
* {@code READ} starting from the bottom and stopping once a read message is * {@code READ} starting from the bottom and stopping once a read message is
* found. * found.
* *
* @param client the client instance used to notify the server about the message
* status changes
* @throws IOException if a {@link MessageStatusChangeEvent} could not be
* delivered to the server
* @since Envoy v0.3-alpha * @since Envoy v0.3-alpha
*/ */
public void read() { public void read(Client client) throws IOException {
for (int i = model.size() - 1; i >= 0; --i) for (int i = model.size() - 1; i >= 0; --i) {
if (model.get(i).getSenderId() == recipient.getId()) { final Message m = model.get(i);
if (model.get(i).getStatus() == MessageStatus.READ) break; if (m.getSenderId() == recipient.getId()) {
else model.get(i).setStatus(MessageStatus.READ); if (m.getStatus() == MessageStatus.READ) break;
else {
m.setStatus(MessageStatus.READ);
// TODO: Cache events in offline mode
client.sendEvent(new MessageStatusChangeEvent(m));
}
}
} }
} }

View File

@ -13,7 +13,9 @@ import envoy.client.Config;
import envoy.client.database.LocalDb; import envoy.client.database.LocalDb;
import envoy.client.util.EnvoyLog; import envoy.client.util.EnvoyLog;
import envoy.data.*; import envoy.data.*;
import envoy.event.Event;
import envoy.event.IdGeneratorRequest; import envoy.event.IdGeneratorRequest;
import envoy.event.MessageStatusChangeEvent;
import envoy.util.SerializationUtils; import envoy.util.SerializationUtils;
/** /**
@ -103,19 +105,21 @@ public class Client implements Closeable {
// Relay cached unread messages // Relay cached unread messages
cache.setProcessor(receivedMessageProcessor); cache.setProcessor(receivedMessageProcessor);
// TODO: Status handling // Process message status changes
receiver.registerProcessor(MessageStatusChangeEvent.class, new MessageStatusChangeEventProcessor());
// Process message ID generation // Process message ID generation
receiver.registerProcessor(IdGenerator.class, localDb::setIdGenerator); receiver.registerProcessor(IdGenerator.class, localDb::setIdGenerator);
// Request a generator if none is present // Request a generator if none is present or the existing one is consumed
if (!localDb.hasIdGenerator() || !localDb.getIdGenerator().hasNext()) requestIdGenerator(); if (!localDb.hasIdGenerator() || !localDb.getIdGenerator().hasNext()) requestIdGenerator();
return cache; return cache;
} }
/** /**
* Sends a message to the server. * Sends a message to the server. The message's status will be incremented once
* it was delivered successfully.
* *
* @param message the message to send * @param message the message to send
* @throws IOException if the message does not reach the server * @throws IOException if the message does not reach the server
@ -126,6 +130,14 @@ public class Client implements Closeable {
message.nextStatus(); message.nextStatus();
} }
/**
* Sends an event to the server.
*
* @param evt the event to send
* @throws IOException if the event did not reach the server
*/
public void sendEvent(Event<?> evt) throws IOException { writeObject(evt); }
/** /**
* Requests a new {@link IdGenerator} from the server. * Requests a new {@link IdGenerator} from the server.
* *

View File

@ -0,0 +1,38 @@
package envoy.client.net;
import java.util.function.Consumer;
import java.util.logging.Logger;
import envoy.client.util.EnvoyLog;
import envoy.data.Message.MessageStatus;
import envoy.event.EventBus;
import envoy.event.MessageStatusChangeEvent;
/**
* Project: <strong>envoy-client</strong><br>
* File: <strong>MessageStatusChangeEventProcessor.java</strong><br>
* Created: <strong>4 Feb 2020</strong><br>
*
* @author Kai S. K. Engelbart
* @since Envoy v0.3-alpha
*/
public class MessageStatusChangeEventProcessor implements Consumer<MessageStatusChangeEvent> {
private static final Logger logger = EnvoyLog.getLogger(MessageStatusChangeEventProcessor.class.getSimpleName());
/**
* Dispatches a {@link MessageStatusChangeEvent} if the status is
* {@code RECEIVED} or {@code READ}.
*
* @param evt the status change event
* @since Envoy v0.3-alpha
*/
@Override
public void accept(MessageStatusChangeEvent evt) {
if (evt.get().ordinal() <= MessageStatus.RECEIVED.ordinal()) logger.info("Received invalid message status change " + evt);
else {
logger.info("Received " + evt.toString());
EventBus.getInstance().dispatch(evt);
}
}
}

View File

@ -3,6 +3,7 @@ package envoy.client.ui;
import java.awt.*; import java.awt.*;
import java.awt.event.KeyAdapter; import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.io.IOException;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -19,9 +20,11 @@ import envoy.client.ui.list.ComponentList;
import envoy.client.ui.settings.SettingsScreen; import envoy.client.ui.settings.SettingsScreen;
import envoy.client.util.EnvoyLog; import envoy.client.util.EnvoyLog;
import envoy.data.Message; import envoy.data.Message;
import envoy.data.Message.MessageStatus;
import envoy.data.MessageBuilder; import envoy.data.MessageBuilder;
import envoy.data.User; import envoy.data.User;
import envoy.event.EventBus; import envoy.event.EventBus;
import envoy.event.MessageStatusChangeEvent;
/** /**
* Project: <strong>envoy-client</strong><br> * Project: <strong>envoy-client</strong><br>
@ -173,7 +176,12 @@ public class ChatWindow extends JFrame {
currentChat = localDb.getChats().stream().filter(chat -> chat.getRecipient().getId() == user.getId()).findFirst().get(); currentChat = localDb.getChats().stream().filter(chat -> chat.getRecipient().getId() == user.getId()).findFirst().get();
// Read current Chat // Read current Chat
currentChat.read(); try {
currentChat.read(client);
} catch (IOException e) {
e.printStackTrace();
logger.log(Level.WARNING, "Could notify server about message status change", e);
}
// Set chat title // Set chat title
textPane.setText(currentChat.getRecipient().getName()); textPane.setText(currentChat.getRecipient().getName());
@ -213,6 +221,26 @@ public class ChatWindow extends JFrame {
repaint(); repaint();
}); });
// Listen to message status changes
EventBus.getInstance().register(MessageStatusChangeEvent.class, (evt) -> {
final long id = ((MessageStatusChangeEvent) evt).getId();
final MessageStatus status = (MessageStatus) evt.get();
for (Chat c : localDb.getChats())
for (Message m : c.getModel())
if (m.getId() == id) {
// Update message status
m.setStatus(status);
// Update model and scroll down if current chat
if (c == currentChat) {
messageList.setModel(currentChat.getModel());
scrollPane.setChatOpened(true);
}
}
});
revalidate(); revalidate();
} }
@ -286,10 +314,7 @@ public class ChatWindow extends JFrame {
if (!localDb.getIdGenerator().hasNext()) client.requestIdGenerator(); if (!localDb.getIdGenerator().hasNext()) client.requestIdGenerator();
} catch (Exception e) { } catch (Exception e) {
JOptionPane.showMessageDialog(this, JOptionPane.showMessageDialog(this, "Error sending message:\n" + e.toString(), "Message sending error", JOptionPane.ERROR_MESSAGE);
"Error sending message:\n" + e.toString(),
"Message sending error",
JOptionPane.ERROR_MESSAGE);
e.printStackTrace(); e.printStackTrace();
} }
} }
@ -320,9 +345,7 @@ public class ChatWindow extends JFrame {
* @param client the {@link Client} used to send and receive messages * @param client the {@link Client} used to send and receive messages
* @since Envoy v0.2-alpha * @since Envoy v0.2-alpha
*/ */
public void setClient(Client client) { public void setClient(Client client) { this.client = client; }
this.client = client;
}
/** /**
* Sets the {@link LocalDb} used by this {@link ChatWindow}. After * Sets the {@link LocalDb} used by this {@link ChatWindow}. After