Merge pull request #159 from informatik-ag-ngl/b/online_status
Fixed two bugs regarding status changes
This commit is contained in:
		@@ -10,8 +10,8 @@ import java.util.logging.Logger;
 | 
				
			|||||||
import envoy.util.EnvoyLog;
 | 
					import envoy.util.EnvoyLog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Stores elements in a queue to process them later.<br>
 | 
					 * Stores elements in a queue to process them later.
 | 
				
			||||||
 * <br>
 | 
					 * <p>
 | 
				
			||||||
 * Project: <strong>envoy-client</strong><br>
 | 
					 * Project: <strong>envoy-client</strong><br>
 | 
				
			||||||
 * File: <strong>Cache.java</strong><br>
 | 
					 * File: <strong>Cache.java</strong><br>
 | 
				
			||||||
 * Created: <strong>6 Feb 2020</strong><br>
 | 
					 * Created: <strong>6 Feb 2020</strong><br>
 | 
				
			||||||
@@ -40,6 +40,9 @@ public class Cache<T> implements Consumer<T>, Serializable {
 | 
				
			|||||||
		elements.offer(element);
 | 
							elements.offer(element);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public String toString() { return String.format("Cache[elements=" + elements + "]"); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Sets the processor to which cached elements are relayed.
 | 
						 * Sets the processor to which cached elements are relayed.
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,11 +20,11 @@ import envoy.event.NameChange;
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
public abstract class LocalDB {
 | 
					public abstract class LocalDB {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected User								user;
 | 
						protected User							user;
 | 
				
			||||||
	protected Map<String, Contact>				users			= new HashMap<>();
 | 
						protected Map<String, Contact>			users			= new HashMap<>();
 | 
				
			||||||
	protected List<Chat>						chats			= new ArrayList<>();
 | 
						protected List<Chat>					chats			= new ArrayList<>();
 | 
				
			||||||
	protected IDGenerator						idGenerator;
 | 
						protected IDGenerator					idGenerator;
 | 
				
			||||||
	protected Cache<Message>					messageCache	= new Cache<>();
 | 
						protected Cache<Message>				messageCache	= new Cache<>();
 | 
				
			||||||
	protected Cache<MessageStatusChange>	statusCache		= new Cache<>();
 | 
						protected Cache<MessageStatusChange>	statusCache		= new Cache<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
@@ -66,6 +66,25 @@ public abstract class LocalDB {
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	public void loadIDGenerator() {}
 | 
						public void loadIDGenerator() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Synchronizes the contact list of the client user with the chat and user
 | 
				
			||||||
 | 
						 * storage.
 | 
				
			||||||
 | 
						 * 
 | 
				
			||||||
 | 
						 * @since Envoy Client v0.1-beta
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public void synchronize() {
 | 
				
			||||||
 | 
							user.getContacts().stream().filter(u -> u instanceof User && !users.containsKey(u.getName())).forEach(u -> users.put(u.getName(), u));
 | 
				
			||||||
 | 
							users.put(user.getName(), user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Synchronize user status data
 | 
				
			||||||
 | 
							for (Contact contact : users.values())
 | 
				
			||||||
 | 
								if (contact instanceof User)
 | 
				
			||||||
 | 
									getChat(contact.getID()).ifPresent(chat -> { ((User) chat.getRecipient()).setStatus(((User) contact).getStatus()); });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Create missing chats
 | 
				
			||||||
 | 
							user.getContacts().stream().filter(u -> !u.equals(user) && getChat(u.getID()).isEmpty()).map(Chat::new).forEach(chats::add);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * @return a {@code Map<String, User>} of all users stored locally with their
 | 
						 * @return a {@code Map<String, User>} of all users stored locally with their
 | 
				
			||||||
	 *         user names as keys
 | 
						 *         user names as keys
 | 
				
			||||||
@@ -73,11 +92,6 @@ public abstract class LocalDB {
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	public Map<String, Contact> getUsers() { return users; }
 | 
						public Map<String, Contact> getUsers() { return users; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * @param users the users to set
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	public void setUsers(Map<String, Contact> users) { this.users = users; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * @return all saved {@link Chat} objects that list the client user as the
 | 
						 * @return all saved {@link Chat} objects that list the client user as the
 | 
				
			||||||
	 *         sender
 | 
						 *         sender
 | 
				
			||||||
@@ -162,9 +176,7 @@ public abstract class LocalDB {
 | 
				
			|||||||
	 * @return an optional containing the chat
 | 
						 * @return an optional containing the chat
 | 
				
			||||||
	 * @since Envoy Client v0.1-beta
 | 
						 * @since Envoy Client v0.1-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public Optional<Chat> getChat(long recipientID) {
 | 
						public Optional<Chat> getChat(long recipientID) { return chats.stream().filter(c -> c.getRecipient().getID() == recipientID).findAny(); }
 | 
				
			||||||
		return chats.stream().filter(c -> c.getRecipient().getID() == recipientID).findAny();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Performs a contact name change if the corresponding contact is present.
 | 
						 * Performs a contact name change if the corresponding contact is present.
 | 
				
			||||||
@@ -200,13 +212,4 @@ public abstract class LocalDB {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Creates a new {@link Chat} for all {@link Contact}s that do not have a chat.
 | 
					 | 
				
			||||||
	 * 
 | 
					 | 
				
			||||||
	 * @since Envoy Client v0.1-beta
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	public void createMissingChats() {
 | 
					 | 
				
			||||||
		users.values().stream().filter(u -> !u.equals(user) && getChat(u.getID()).isEmpty()).map(Chat::new).forEach(chats::add);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,9 +3,6 @@ package envoy.client.net;
 | 
				
			|||||||
import java.io.Closeable;
 | 
					import java.io.Closeable;
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
import java.net.Socket;
 | 
					import java.net.Socket;
 | 
				
			||||||
import java.util.HashMap;
 | 
					 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
import java.util.Set;
 | 
					 | 
				
			||||||
import java.util.concurrent.TimeoutException;
 | 
					import java.util.concurrent.TimeoutException;
 | 
				
			||||||
import java.util.logging.Level;
 | 
					import java.util.logging.Level;
 | 
				
			||||||
import java.util.logging.Logger;
 | 
					import java.util.logging.Logger;
 | 
				
			||||||
@@ -42,9 +39,8 @@ public class Client implements Closeable {
 | 
				
			|||||||
	private boolean		online;
 | 
						private boolean		online;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Asynchronously initialized during handshake
 | 
						// Asynchronously initialized during handshake
 | 
				
			||||||
	private volatile User					sender;
 | 
						private volatile User		sender;
 | 
				
			||||||
	private volatile Set<? extends Contact>	contacts;
 | 
						private volatile boolean	rejected;
 | 
				
			||||||
	private volatile boolean				rejected;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Configuration, logging and event management
 | 
						// Configuration, logging and event management
 | 
				
			||||||
	private static final ClientConfig	config		= ClientConfig.getInstance();
 | 
						private static final ClientConfig	config		= ClientConfig.getInstance();
 | 
				
			||||||
@@ -73,9 +69,9 @@ public class Client implements Closeable {
 | 
				
			|||||||
	 *                              waiting for the handshake response
 | 
						 *                              waiting for the handshake response
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public void performHandshake(LoginCredentials credentials, Cache<Message> receivedMessageCache,
 | 
						public void performHandshake(LoginCredentials credentials, Cache<Message> receivedMessageCache,
 | 
				
			||||||
			Cache<MessageStatusChange> receivedMessageStatusChangeCache)
 | 
								Cache<MessageStatusChange> receivedMessageStatusChangeCache) throws TimeoutException, IOException, InterruptedException {
 | 
				
			||||||
			throws TimeoutException, IOException, InterruptedException {
 | 
					 | 
				
			||||||
		if (online) throw new IllegalStateException("Handshake has already been performed successfully");
 | 
							if (online) throw new IllegalStateException("Handshake has already been performed successfully");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Establish TCP connection
 | 
							// Establish TCP connection
 | 
				
			||||||
		logger.log(Level.FINER, String.format("Attempting connection to server %s:%d...", config.getServer(), config.getPort()));
 | 
							logger.log(Level.FINER, String.format("Attempting connection to server %s:%d...", config.getServer(), config.getPort()));
 | 
				
			||||||
		socket = new Socket(config.getServer(), config.getPort());
 | 
							socket = new Socket(config.getServer(), config.getPort());
 | 
				
			||||||
@@ -85,7 +81,7 @@ public class Client implements Closeable {
 | 
				
			|||||||
		receiver = new Receiver(socket.getInputStream());
 | 
							receiver = new Receiver(socket.getInputStream());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Register user creation processor, contact list processor and message cache
 | 
							// Register user creation processor, contact list processor and message cache
 | 
				
			||||||
		receiver.registerProcessor(User.class, sender -> { this.sender = sender; contacts = sender.getContacts(); });
 | 
							receiver.registerProcessor(User.class, sender -> this.sender = sender);
 | 
				
			||||||
		receiver.registerProcessor(Message.class, receivedMessageCache);
 | 
							receiver.registerProcessor(Message.class, receivedMessageCache);
 | 
				
			||||||
		receiver.registerProcessor(MessageStatusChange.class, receivedMessageStatusChangeCache);
 | 
							receiver.registerProcessor(MessageStatusChange.class, receivedMessageStatusChangeCache);
 | 
				
			||||||
		receiver.registerProcessor(HandshakeRejection.class, evt -> { rejected = true; eventBus.dispatch(evt); });
 | 
							receiver.registerProcessor(HandshakeRejection.class, evt -> { rejected = true; eventBus.dispatch(evt); });
 | 
				
			||||||
@@ -142,12 +138,12 @@ public class Client implements Closeable {
 | 
				
			|||||||
	 *                     requested from the server
 | 
						 *                     requested from the server
 | 
				
			||||||
	 * @since Envoy Client v0.2-alpha
 | 
						 * @since Envoy Client v0.2-alpha
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public void initReceiver(LocalDB localDB, Cache<Message> receivedMessageCache,
 | 
						public void initReceiver(LocalDB localDB, Cache<Message> receivedMessageCache, Cache<MessageStatusChange> receivedMessageStatusChangeCache)
 | 
				
			||||||
			Cache<MessageStatusChange> receivedMessageStatusChangeCache) throws IOException {
 | 
								throws IOException {
 | 
				
			||||||
		checkOnline();
 | 
							checkOnline();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Process incoming messages
 | 
							// Process incoming messages
 | 
				
			||||||
		final ReceivedMessageProcessor			receivedMessageProcessor			= new ReceivedMessageProcessor();
 | 
							final ReceivedMessageProcessor		receivedMessageProcessor			= new ReceivedMessageProcessor();
 | 
				
			||||||
		final MessageStatusChangeProcessor	messageStatusChangeEventProcessor	= new MessageStatusChangeProcessor();
 | 
							final MessageStatusChangeProcessor	messageStatusChangeEventProcessor	= new MessageStatusChangeProcessor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		receiver.registerProcessor(Message.class, receivedMessageProcessor);
 | 
							receiver.registerProcessor(Message.class, receivedMessageProcessor);
 | 
				
			||||||
@@ -182,8 +178,7 @@ public class Client implements Closeable {
 | 
				
			|||||||
			try {
 | 
								try {
 | 
				
			||||||
				sendEvent(evt.get());
 | 
									sendEvent(evt.get());
 | 
				
			||||||
			} catch (final IOException e) {
 | 
								} catch (final IOException e) {
 | 
				
			||||||
				e.printStackTrace();
 | 
									logger.log(Level.WARNING, "An error occurred when trying to send " + evt, e);
 | 
				
			||||||
				logger.log(Level.WARNING, "An error occurred when trying to send Event " + evt, e);
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -234,19 +229,6 @@ public class Client implements Closeable {
 | 
				
			|||||||
		writeObject(new IDGeneratorRequest());
 | 
							writeObject(new IDGeneratorRequest());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * @return a {@code Map<String, User>} of all users on the server with their
 | 
					 | 
				
			||||||
	 *         user names as keys
 | 
					 | 
				
			||||||
	 * @since Envoy Client v0.2-alpha
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	public Map<String, Contact> getUsers() {
 | 
					 | 
				
			||||||
		checkOnline();
 | 
					 | 
				
			||||||
		final Map<String, Contact> users = new HashMap<>();
 | 
					 | 
				
			||||||
		contacts.forEach(u -> users.put(u.getName(), u));
 | 
					 | 
				
			||||||
		users.put(sender.getName(), sender);
 | 
					 | 
				
			||||||
		return users;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public void close() throws IOException { if (online) socket.close(); }
 | 
						public void close() throws IOException { if (online) socket.close(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -259,7 +241,7 @@ public class Client implements Closeable {
 | 
				
			|||||||
	private void checkOnline() { if (!online) throw new IllegalStateException("Client is not online"); }
 | 
						private void checkOnline() { if (!online) throw new IllegalStateException("Client is not online"); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * @return the sender object that represents this client.
 | 
						 * @return the {@link User} as which this client is logged in
 | 
				
			||||||
	 * @since Envoy Client v0.1-alpha
 | 
						 * @since Envoy Client v0.1-alpha
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public User getSender() { return sender; }
 | 
						public User getSender() { return sender; }
 | 
				
			||||||
@@ -282,16 +264,4 @@ public class Client implements Closeable {
 | 
				
			|||||||
	 * @since Envoy Client v0.2-alpha
 | 
						 * @since Envoy Client v0.2-alpha
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public boolean isOnline() { return online; }
 | 
						public boolean isOnline() { return online; }
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * @return the contacts of this {@link Client}
 | 
					 | 
				
			||||||
	 * @since Envoy Client v0.3-alpha
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	public Set<? extends Contact> getContacts() { return contacts; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * @param contacts the contacts to set
 | 
					 | 
				
			||||||
	 * @since Envoy Client v0.3-alpha
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	public void setContacts(Set<? extends Contact> contacts) { this.contacts = contacts; }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,7 +79,6 @@ public class Receiver extends Thread {
 | 
				
			|||||||
			// Connection probably closed by client.
 | 
								// Connection probably closed by client.
 | 
				
			||||||
		} catch (final Exception e) {
 | 
							} catch (final Exception e) {
 | 
				
			||||||
			logger.log(Level.SEVERE, "Error on receiver thread", e);
 | 
								logger.log(Level.SEVERE, "Error on receiver thread", e);
 | 
				
			||||||
			e.printStackTrace();
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,9 +47,6 @@ public class WriteProxy {
 | 
				
			|||||||
			try {
 | 
								try {
 | 
				
			||||||
				logger.log(Level.FINER, "Sending cached " + msg);
 | 
									logger.log(Level.FINER, "Sending cached " + msg);
 | 
				
			||||||
				client.sendMessage(msg);
 | 
									client.sendMessage(msg);
 | 
				
			||||||
 | 
					 | 
				
			||||||
				// Update message state to SENT in localDB
 | 
					 | 
				
			||||||
				localDB.getMessage(msg.getID()).ifPresent(Message::nextStatus);
 | 
					 | 
				
			||||||
			} catch (final IOException e) {
 | 
								} catch (final IOException e) {
 | 
				
			||||||
				logger.log(Level.SEVERE, "Could not send cached message: ", e);
 | 
									logger.log(Level.SEVERE, "Could not send cached message: ", e);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -164,13 +164,13 @@ public final class ChatScene {
 | 
				
			|||||||
	private void userListClicked() {
 | 
						private void userListClicked() {
 | 
				
			||||||
		final Contact user = userList.getSelectionModel().getSelectedItem();
 | 
							final Contact user = userList.getSelectionModel().getSelectedItem();
 | 
				
			||||||
		if (user != null && (currentChat == null || !user.equals(currentChat.getRecipient()))) {
 | 
							if (user != null && (currentChat == null || !user.equals(currentChat.getRecipient()))) {
 | 
				
			||||||
 | 
								logger.log(Level.FINEST, "Loading chat with " + user);
 | 
				
			||||||
			contactLabel.setText(user.getName());
 | 
								contactLabel.setText(user.getName());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// LEON: JFC <===> JAVA FRIED CHICKEN <=/=> Java Foundation Classes
 | 
								// LEON: JFC <===> JAVA FRIED CHICKEN <=/=> Java Foundation Classes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Load the chat or create a new one and add it to the LocalDB
 | 
								// Load the chat
 | 
				
			||||||
			currentChat = localDB.getChat(user.getID())
 | 
								currentChat = localDB.getChat(user.getID()).get();
 | 
				
			||||||
				.orElseGet(() -> { final var chat = new Chat(user); localDB.getChats().add(chat); return chat; });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			messageList.setItems(FXCollections.observableList(currentChat.getMessages()));
 | 
								messageList.setItems(FXCollections.observableList(currentChat.getMessages()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,9 +11,7 @@ import javafx.fxml.FXML;
 | 
				
			|||||||
import javafx.scene.control.*;
 | 
					import javafx.scene.control.*;
 | 
				
			||||||
import javafx.scene.control.Alert.AlertType;
 | 
					import javafx.scene.control.Alert.AlertType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import envoy.client.data.Cache;
 | 
					import envoy.client.data.*;
 | 
				
			||||||
import envoy.client.data.ClientConfig;
 | 
					 | 
				
			||||||
import envoy.client.data.LocalDB;
 | 
					 | 
				
			||||||
import envoy.client.net.Client;
 | 
					import envoy.client.net.Client;
 | 
				
			||||||
import envoy.client.ui.SceneContext;
 | 
					import envoy.client.ui.SceneContext;
 | 
				
			||||||
import envoy.client.ui.Startup;
 | 
					import envoy.client.ui.Startup;
 | 
				
			||||||
@@ -183,7 +181,6 @@ public final class LoginScene {
 | 
				
			|||||||
		} catch (final FileNotFoundException e) {
 | 
							} catch (final FileNotFoundException e) {
 | 
				
			||||||
			// The local database file has not yet been created, probably first login
 | 
								// The local database file has not yet been created, probably first login
 | 
				
			||||||
		} catch (final Exception e) {
 | 
							} catch (final Exception e) {
 | 
				
			||||||
			e.printStackTrace();
 | 
					 | 
				
			||||||
			new Alert(AlertType.ERROR, "Error while loading local database: " + e + "\nChats will not be stored locally.").showAndWait();
 | 
								new Alert(AlertType.ERROR, "Error while loading local database: " + e + "\nChats will not be stored locally.").showAndWait();
 | 
				
			||||||
			logger.log(Level.WARNING, "Could not load local database: ", e);
 | 
								logger.log(Level.WARNING, "Could not load local database: ", e);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -191,15 +188,18 @@ public final class LoginScene {
 | 
				
			|||||||
		// Initialize write proxy
 | 
							// Initialize write proxy
 | 
				
			||||||
		final var writeProxy = client.createWriteProxy(localDB);
 | 
							final var writeProxy = client.createWriteProxy(localDB);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (client.isOnline()) {
 | 
							localDB.synchronize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Save all users to the local database and flush cache
 | 
							if (client.isOnline()) {
 | 
				
			||||||
			localDB.setUsers(client.getUsers());
 | 
					 | 
				
			||||||
			localDB.createMissingChats();
 | 
					 | 
				
			||||||
			writeProxy.flushCache();
 | 
								writeProxy.flushCache();
 | 
				
			||||||
		} else
 | 
							} else
 | 
				
			||||||
			// Set all contacts to offline mode
 | 
								// Set all contacts to offline mode
 | 
				
			||||||
			localDB.getUsers().values().stream().filter(User.class::isInstance).map(User.class::cast).forEach(u -> u.setStatus(UserStatus.OFFLINE));
 | 
								localDB.getChats()
 | 
				
			||||||
 | 
									.stream()
 | 
				
			||||||
 | 
									.map(Chat::getRecipient)
 | 
				
			||||||
 | 
									.filter(User.class::isInstance)
 | 
				
			||||||
 | 
									.map(User.class::cast)
 | 
				
			||||||
 | 
									.forEach(u -> u.setStatus(UserStatus.OFFLINE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Load ChatScene
 | 
							// Load ChatScene
 | 
				
			||||||
		sceneContext.pop();
 | 
							sceneContext.pop();
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user