Fix several bugs
These are: - not immediately updating ChatScene if a contact was blocked and both are online - ContactSearchTab showing previously entered text on reopening (without showing suggestions) - users not getting notified if someone else blocked them while they were offline - no logger statements in UserUtil Still to do: - Move ContextMenu from chatList to ChatControl - Test behavior for groups
This commit is contained in:
parent
7bdcfad08c
commit
a91181b4dd
@ -57,7 +57,9 @@ public class Chat implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() { return String.format("%s[recipient=%s,messages=%d]", getClass().getSimpleName(), recipient, messages.size()); }
|
public String toString() {
|
||||||
|
return String.format("%s[recipient=%s,messages=%d, disabled=%b]", getClass().getSimpleName(), recipient, messages.size(), disabled);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a hash code based on the recipient.
|
* Generates a hash code based on the recipient.
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package envoy.client.data;
|
package envoy.client.data;
|
||||||
|
|
||||||
|
import static java.util.function.Predicate.not;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.channels.*;
|
import java.nio.channels.*;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.*;
|
import java.util.logging.*;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.collections.*;
|
import javafx.collections.*;
|
||||||
@ -35,12 +38,13 @@ public final class LocalDB implements EventListener {
|
|||||||
|
|
||||||
// Data
|
// Data
|
||||||
private User user;
|
private User user;
|
||||||
private Map<String, User> users = Collections.synchronizedMap(new HashMap<>());
|
private Map<String, User> users = Collections.synchronizedMap(new HashMap<>());
|
||||||
private ObservableList<Chat> chats = FXCollections.observableArrayList();
|
private ObservableList<Chat> chats = FXCollections.observableArrayList();
|
||||||
private IDGenerator idGenerator;
|
private IDGenerator idGenerator;
|
||||||
private CacheMap cacheMap = new CacheMap();
|
private CacheMap cacheMap = new CacheMap();
|
||||||
private String authToken;
|
private String authToken;
|
||||||
private Set<? extends Contact> originalContacts = Set.of();
|
private boolean contactsChanged;
|
||||||
|
private Stream<Chat> changedChats;
|
||||||
|
|
||||||
// Auto save timer
|
// Auto save timer
|
||||||
private Timer autoSaver;
|
private Timer autoSaver;
|
||||||
@ -138,7 +142,19 @@ public final class LocalDB implements EventListener {
|
|||||||
if (user == null) throw new IllegalStateException("Client user is null, cannot initialize user storage");
|
if (user == null) throw new IllegalStateException("Client user is null, cannot initialize user storage");
|
||||||
userFile = new File(dbDir, user.getID() + ".db");
|
userFile = new File(dbDir, user.getID() + ".db");
|
||||||
try (var in = new ObjectInputStream(new FileInputStream(userFile))) {
|
try (var in = new ObjectInputStream(new FileInputStream(userFile))) {
|
||||||
chats = FXCollections.observableList((List<Chat>) in.readObject());
|
chats = FXCollections.observableList((List<Chat>) in.readObject());
|
||||||
|
|
||||||
|
// Some chats have changed and should not be overridden by the saved values
|
||||||
|
if (changedChats != null) {
|
||||||
|
changedChats.forEach(chat -> {
|
||||||
|
final var chatIndex = chats.indexOf(chat);
|
||||||
|
if (chatIndex == -1) return;
|
||||||
|
else chats.set(chatIndex, chat);
|
||||||
|
});
|
||||||
|
|
||||||
|
// loadUserData can get called two (or more?) times during application lifecycle
|
||||||
|
changedChats = null;
|
||||||
|
}
|
||||||
cacheMap = (CacheMap) in.readObject();
|
cacheMap = (CacheMap) in.readObject();
|
||||||
lastSync = (Instant) in.readObject();
|
lastSync = (Instant) in.readObject();
|
||||||
} finally {
|
} finally {
|
||||||
@ -324,7 +340,7 @@ public final class LocalDB implements EventListener {
|
|||||||
private void onOwnStatusChange(OwnStatusChange statusChange) { user.setStatus(statusChange.get()); }
|
private void onOwnStatusChange(OwnStatusChange statusChange) { user.setStatus(statusChange.get()); }
|
||||||
|
|
||||||
@Event(eventType = ContactsChangedSinceLastLogin.class, priority = 500)
|
@Event(eventType = ContactsChangedSinceLastLogin.class, priority = 500)
|
||||||
private void onContactsChangedSinceLastLogin() { if (user != null) originalContacts = user.getContacts(); }
|
private void onContactsChangedSinceLastLogin() { if (user != null) contactsChanged = true; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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
|
||||||
@ -363,13 +379,12 @@ public final class LocalDB implements EventListener {
|
|||||||
*/
|
*/
|
||||||
public void setUserAndMergeContacts(User user) {
|
public void setUserAndMergeContacts(User user) {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
if (originalContacts.isEmpty()) return;
|
if (contactsChanged)
|
||||||
else {
|
|
||||||
|
|
||||||
// mark all chats of deleted contacts
|
// Mark chats as disabled if a contact is no longer in this users contact list
|
||||||
originalContacts.removeAll(user.getContacts());
|
changedChats = chats.stream()
|
||||||
originalContacts.forEach(contact -> getChat(contact.getID()).ifPresent(chat -> chat.setDisabled(true)));
|
.filter(not(chat -> user.getContacts().contains(chat.getRecipient())))
|
||||||
}
|
.peek(chat -> { chat.setDisabled(true); logger.log(Level.INFO, String.format("Marked %s as blocked.", chat.getRecipient())); });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -272,8 +272,7 @@ public final class ChatScene implements EventListener, Restorable {
|
|||||||
@Event
|
@Event
|
||||||
private void onUserOperation(UserOperation operation) {
|
private void onUserOperation(UserOperation operation) {
|
||||||
// All ADD dependant logic resides in LocalDB
|
// All ADD dependant logic resides in LocalDB
|
||||||
if (operation.getOperationType().equals(ElementOperation.REMOVE))
|
if (operation.getOperationType().equals(ElementOperation.REMOVE)) Platform.runLater(() -> disableChat(operation.get(), true));
|
||||||
if (currentChat != null && currentChat.getRecipient().equals(operation.get())) Platform.runLater(this::resetState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Event
|
@Event
|
||||||
|
@ -124,5 +124,8 @@ public class ContactSearchTab implements EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void backButtonClicked() { eventBus.dispatch(new BackEvent()); }
|
private void backButtonClicked() {
|
||||||
|
searchBar.setText("");
|
||||||
|
eventBus.dispatch(new BackEvent());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ public class GroupCreationTab implements EventListener {
|
|||||||
.map(User.class::cast)
|
.map(User.class::cast)
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
resizeQuickSelectSpace(0);
|
resizeQuickSelectSpace(0);
|
||||||
quickSelectList.addEventFilter(MouseEvent.MOUSE_PRESSED, evt -> evt.consume());
|
quickSelectList.addEventFilter(MouseEvent.MOUSE_PRESSED, MouseEvent::consume);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -238,7 +238,7 @@ public class GroupCreationTab implements EventListener {
|
|||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
switch (operation.getOperationType()) {
|
switch (operation.getOperationType()) {
|
||||||
case ADD:
|
case ADD:
|
||||||
userList.getItems().add((User) operation.get());
|
userList.getItems().add(operation.get());
|
||||||
break;
|
break;
|
||||||
case REMOVE:
|
case REMOVE:
|
||||||
userList.getItems().removeIf(operation.get()::equals);
|
userList.getItems().removeIf(operation.get()::equals);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package envoy.client.util;
|
package envoy.client.util;
|
||||||
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.*;
|
||||||
|
|
||||||
import javafx.scene.control.Alert;
|
import javafx.scene.control.Alert;
|
||||||
import javafx.scene.control.Alert.AlertType;
|
import javafx.scene.control.Alert.AlertType;
|
||||||
@ -26,7 +26,8 @@ import dev.kske.eventbus.EventBus;
|
|||||||
*/
|
*/
|
||||||
public final class UserUtil {
|
public final class UserUtil {
|
||||||
|
|
||||||
private static final Context context = Context.getInstance();
|
private static final Context context = Context.getInstance();
|
||||||
|
private static final Logger logger = EnvoyLog.getLogger(UserUtil.class);
|
||||||
|
|
||||||
private UserUtil() {}
|
private UserUtil() {}
|
||||||
|
|
||||||
@ -46,6 +47,7 @@ public final class UserUtil {
|
|||||||
EventBus.getInstance().dispatch(new EnvoyCloseEvent());
|
EventBus.getInstance().dispatch(new EnvoyCloseEvent());
|
||||||
EventBus.getInstance().dispatch(new Logout());
|
EventBus.getInstance().dispatch(new Logout());
|
||||||
context.getSceneContext().load(SceneInfo.LOGIN_SCENE);
|
context.getSceneContext().load(SceneInfo.LOGIN_SCENE);
|
||||||
|
logger.log(Level.INFO, "A logout occurred.");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +65,7 @@ public final class UserUtil {
|
|||||||
else {
|
else {
|
||||||
EventBus.getInstance().dispatch(new OwnStatusChange(newStatus));
|
EventBus.getInstance().dispatch(new OwnStatusChange(newStatus));
|
||||||
if (context.getClient().isOnline()) context.getClient().send(new UserStatusChange(context.getLocalDB().getUser().getID(), newStatus));
|
if (context.getClient().isOnline()) context.getClient().send(new UserStatusChange(context.getLocalDB().getUser().getID(), newStatus));
|
||||||
|
logger.log(Level.INFO, "A manual status change occurred.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +90,7 @@ public final class UserUtil {
|
|||||||
context.getLocalDB().getChat(block.getID()).ifPresent(chat -> chat.setDisabled(true));
|
context.getLocalDB().getChat(block.getID()).ifPresent(chat -> chat.setDisabled(true));
|
||||||
final var controller = context.getSceneContext().getController();
|
final var controller = context.getSceneContext().getController();
|
||||||
if (controller instanceof ChatScene) ((ChatScene) controller).disableChat(block, true);
|
if (controller instanceof ChatScene) ((ChatScene) controller).disableChat(block, true);
|
||||||
|
logger.log(Level.INFO, "A contact was blocked.");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,6 +112,7 @@ public final class UserUtil {
|
|||||||
context.getLocalDB().getChats().removeIf(chat -> chat.getRecipient().equals(delete));
|
context.getLocalDB().getChats().removeIf(chat -> chat.getRecipient().equals(delete));
|
||||||
if (context.getSceneContext().getController() instanceof ChatScene)
|
if (context.getSceneContext().getController() instanceof ChatScene)
|
||||||
((ChatScene) context.getSceneContext().getController()).resetState();
|
((ChatScene) context.getSceneContext().getController()).resetState();
|
||||||
|
logger.log(Level.INFO, "A contact with all his messages was deleted.");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user