Add working leaving of a group

Additionally fixed a two bugs:
- one group member will no longer show "1 members"
- deletion of empty groups no longer throws an exception
This commit is contained in:
Leon Hofmeister 2020-10-16 20:21:22 +02:00 committed by KSKE Git
parent ebe19c00c9
commit a0812f193e
Signed by: Käfer & Engelbart Git
GPG Key ID: 70F2F9206EDC1FCE
8 changed files with 66 additions and 34 deletions

View File

@ -379,12 +379,27 @@ public final class LocalDB implements EventListener {
*/
public void setUserAndMergeContacts(User user) {
this.user = user;
if (contactsChanged)
if (contactsChanged) {
final var contacts = user.getContacts();
// Mark chats as disabled if a contact is no longer in this users contact list
changedChats = chats.stream()
.filter(not(chat -> user.getContacts().contains(chat.getRecipient())))
final var changedUserChats = chats.stream()
.filter(not(chat -> contacts.contains(chat.getRecipient())))
.peek(chat -> { chat.setDisabled(true); logger.log(Level.INFO, String.format("Marked %s as blocked.", chat.getRecipient())); });
// Also update groups with a different member count
final var changedGroupChats = contacts.stream().filter(Group.class::isInstance).flatMap(group -> {
final var potentialChat = getChat(group.getID());
if (potentialChat.isEmpty()) return Stream.empty();
final var chat = potentialChat.get();
if (group.getContacts().size() != chat.getRecipient().getContacts().size()) {
logger.log(Level.INFO, "Removed one (or more) members from " + group);
return Stream.of(chat);
} else return Stream.empty();
});
changedChats = Stream.concat(changedUserChats, changedGroupChats);
}
}
/**

View File

@ -16,5 +16,7 @@ public final class GroupSizeLabel extends Label {
* @param recipient the group whose members to show
* @since Envoy Client v0.3-beta
*/
public GroupSizeLabel(Group recipient) { super(recipient.getContacts().size() + " members"); }
public GroupSizeLabel(Group recipient) {
super(recipient.getContacts().size() + " member" + (recipient.getContacts().size() != 1 ? "s" : ""));
}
}

View File

@ -281,7 +281,8 @@ public final class ChatScene implements EventListener, Restorable {
// Update the top-bar status label if all conditions apply
if (currentChat != null && currentChat.getRecipient().equals(chatFound.get().getRecipient()))
topBarStatusLabel.setText(chatFound.get().getRecipient().getContacts().size() + " members");
topBarStatusLabel.setText(chatFound.get().getRecipient().getContacts().size() + " member"
+ (currentChat.getRecipient().getContacts().size() != 1 ? "s" : ""));
});
}
@ -383,7 +384,8 @@ public final class ChatScene implements EventListener, Restorable {
topBarStatusLabel.setVisible(true);
recipientProfilePic.setImage(IconUtil.loadIconThemeSensitive("user_icon", 43));
} else {
topBarStatusLabel.setText(currentChat.getRecipient().getContacts().size() + " members");
topBarStatusLabel.setText(currentChat.getRecipient().getContacts().size() + " member"
+ (currentChat.getRecipient().getContacts().size() != 1 ? "s" : ""));
topBarStatusLabel.getStyleClass().clear();
recipientProfilePic.setImage(IconUtil.loadIconThemeSensitive("group_icon", 43));
}
@ -752,7 +754,13 @@ public final class ChatScene implements EventListener, Restorable {
* @since Envoy Client v0.3-beta
*/
public void disableChat(Contact recipient, boolean refreshChatList) {
if (refreshChatList) chatList.refresh();
if (refreshChatList) {
chatList.refresh();
// Decrement member count for groups
if (recipient instanceof Group)
topBarStatusLabel.setText(recipient.getContacts().size() + " member" + (recipient.getContacts().size() != 1 ? "s" : ""));
}
if (currentChat != null && currentChat.getRecipient().equals(recipient)) {
messageTextArea.setDisable(true);
voiceButton.setDisable(true);

View File

@ -82,15 +82,19 @@ public final class UserUtil {
if (!context.getClient().isOnline() || block == null) return;
else {
final var alert = new Alert(AlertType.CONFIRMATION);
alert.setContentText("Are you sure you want to block " + block.getName() + "?");
alert.setContentText("Are you sure you want to " + (block instanceof User ? "block " : "leave group ") + block.getName() + "?");
AlertHelper.confirmAction(alert, () -> {
context.getClient()
.send(block instanceof User ? new UserOperation((User) block, ElementOperation.REMOVE)
: new GroupResize(context.getLocalDB().getUser(), (Group) block, ElementOperation.REMOVE));
context.getLocalDB().getChat(block.getID()).ifPresent(chat -> chat.setDisabled(true));
if (block instanceof User) logger.log(Level.INFO, "A user was blocked.");
else {
block.getContacts().remove(context.getLocalDB().getUser());
logger.log(Level.INFO, "The user left a group.");
}
final var controller = context.getSceneContext().getController();
if (controller instanceof ChatScene) ((ChatScene) controller).disableChat(block, true);
logger.log(Level.INFO, "A contact was blocked.");
});
}
}

View File

@ -49,6 +49,7 @@ public final class Startup {
new MessageStatusChangeProcessor(),
new GroupMessageStatusChangeProcessor(),
new UserStatusChangeProcessor(),
new GroupResizeProcessor(),
new IDGeneratorRequestProcessor(),
new UserSearchProcessor(),
new UserOperationProcessor(),

View File

@ -51,7 +51,7 @@ public class Message {
@Id
protected long id;
@ManyToOne
@ManyToOne(cascade = CascadeType.REMOVE)
@JoinColumn
protected User sender;

View File

@ -105,11 +105,6 @@ public final class PersistenceManager {
// Remove this contact from the contact list of his contacts
for (final var remainingContact : contact.getContacts())
remainingContact.getContacts().remove(contact);
// Delete messages sent or received by this contact
entityManager.createQuery("DELETE FROM Message m WHERE (m.sender = :contact OR m.recipient = :contact )")
.setParameter("contact", contact)
.executeUpdate();
});
remove(contact);
}

View File

@ -1,8 +1,12 @@
package envoy.server.processors;
import java.time.Instant;
import java.util.logging.Level;
import envoy.event.GroupResize;
import envoy.server.data.*;
import envoy.server.net.*;
import envoy.server.net.ObjectWriteProxy;
import envoy.util.EnvoyLog;
/**
* @author Maximilian Käfer
@ -11,34 +15,37 @@ import envoy.server.net.*;
public final class GroupResizeProcessor implements ObjectProcessor<GroupResize> {
private static final PersistenceManager persistenceManager = PersistenceManager.getInstance();
private static final ConnectionManager connectionManager = ConnectionManager.getInstance();
@Override
public void process(GroupResize groupResize, long socketID, ObjectWriteProxy writeProxy) {
// Acquire the group to resize from the database
var group = persistenceManager.getGroupByID(groupResize.getGroupID());
final var group = persistenceManager.getGroupByID(groupResize.getGroupID());
final var sender = persistenceManager.getUserByID(groupResize.get().getID());
// Perform the desired operation
switch (groupResize.getOperation()) {
case ADD:
group.getContacts().add(persistenceManager.getUserByID(groupResize.get().getID()));
break;
persistenceManager.addContactBidirectional(sender, group);
writeProxy.writeToOnlineContacts(group.getContacts(), group.toCommon());
return;
case REMOVE:
group.getContacts().remove(persistenceManager.getUserByID(groupResize.get().getID()));
break;
persistenceManager.removeContactBidirectional(sender, group);
sender.setLatestContactDeletion(Instant.now());
// The group has no more members and hence will be deleted
if (group.getContacts().isEmpty()) {
EnvoyLog.getLogger(GroupResizeProcessor.class).log(Level.INFO, "Deleting now empty group " + group.getName());
persistenceManager.deleteContact(group);
} else {
// Informing the other members
writeProxy.writeToOnlineContacts(group.getContacts(), groupResize);
group.getContacts().forEach(c -> ((User) c).setLatestContactDeletion(Instant.now()));
}
// Update the group in the database
persistenceManager.updateContact(group);
// Send the updated group to all of its members
var commonGroup = group.toCommon();
group.getContacts()
.stream()
.map(Contact::getID)
.filter(connectionManager::isOnline)
.map(connectionManager::getSocketID)
.forEach(memberSocketID -> writeProxy.write(memberSocketID, commonGroup));
group.getContacts().remove(persistenceManager.getUserByID(groupResize.get().getID()));
return;
}
}
}