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:
parent
ebe19c00c9
commit
a0812f193e
@ -379,12 +379,27 @@ public final class LocalDB implements EventListener {
|
|||||||
*/
|
*/
|
||||||
public void setUserAndMergeContacts(User user) {
|
public void setUserAndMergeContacts(User user) {
|
||||||
this.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
|
// Mark chats as disabled if a contact is no longer in this users contact list
|
||||||
changedChats = chats.stream()
|
final var changedUserChats = chats.stream()
|
||||||
.filter(not(chat -> user.getContacts().contains(chat.getRecipient())))
|
.filter(not(chat -> contacts.contains(chat.getRecipient())))
|
||||||
.peek(chat -> { chat.setDisabled(true); logger.log(Level.INFO, String.format("Marked %s as blocked.", 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,5 +16,7 @@ public final class GroupSizeLabel extends Label {
|
|||||||
* @param recipient the group whose members to show
|
* @param recipient the group whose members to show
|
||||||
* @since Envoy Client v0.3-beta
|
* @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" : ""));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,7 +281,8 @@ public final class ChatScene implements EventListener, Restorable {
|
|||||||
|
|
||||||
// Update the top-bar status label if all conditions apply
|
// Update the top-bar status label if all conditions apply
|
||||||
if (currentChat != null && currentChat.getRecipient().equals(chatFound.get().getRecipient()))
|
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);
|
topBarStatusLabel.setVisible(true);
|
||||||
recipientProfilePic.setImage(IconUtil.loadIconThemeSensitive("user_icon", 43));
|
recipientProfilePic.setImage(IconUtil.loadIconThemeSensitive("user_icon", 43));
|
||||||
} else {
|
} else {
|
||||||
topBarStatusLabel.setText(currentChat.getRecipient().getContacts().size() + " members");
|
topBarStatusLabel.setText(currentChat.getRecipient().getContacts().size() + " member"
|
||||||
|
+ (currentChat.getRecipient().getContacts().size() != 1 ? "s" : ""));
|
||||||
topBarStatusLabel.getStyleClass().clear();
|
topBarStatusLabel.getStyleClass().clear();
|
||||||
recipientProfilePic.setImage(IconUtil.loadIconThemeSensitive("group_icon", 43));
|
recipientProfilePic.setImage(IconUtil.loadIconThemeSensitive("group_icon", 43));
|
||||||
}
|
}
|
||||||
@ -752,7 +754,13 @@ public final class ChatScene implements EventListener, Restorable {
|
|||||||
* @since Envoy Client v0.3-beta
|
* @since Envoy Client v0.3-beta
|
||||||
*/
|
*/
|
||||||
public void disableChat(Contact recipient, boolean refreshChatList) {
|
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)) {
|
if (currentChat != null && currentChat.getRecipient().equals(recipient)) {
|
||||||
messageTextArea.setDisable(true);
|
messageTextArea.setDisable(true);
|
||||||
voiceButton.setDisable(true);
|
voiceButton.setDisable(true);
|
||||||
|
@ -82,15 +82,19 @@ public final class UserUtil {
|
|||||||
if (!context.getClient().isOnline() || block == null) return;
|
if (!context.getClient().isOnline() || block == null) return;
|
||||||
else {
|
else {
|
||||||
final var alert = new Alert(AlertType.CONFIRMATION);
|
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, () -> {
|
AlertHelper.confirmAction(alert, () -> {
|
||||||
context.getClient()
|
context.getClient()
|
||||||
.send(block instanceof User ? new UserOperation((User) block, ElementOperation.REMOVE)
|
.send(block instanceof User ? new UserOperation((User) block, ElementOperation.REMOVE)
|
||||||
: new GroupResize(context.getLocalDB().getUser(), (Group) block, ElementOperation.REMOVE));
|
: new GroupResize(context.getLocalDB().getUser(), (Group) block, ElementOperation.REMOVE));
|
||||||
context.getLocalDB().getChat(block.getID()).ifPresent(chat -> chat.setDisabled(true));
|
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();
|
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.");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,7 @@ public final class Startup {
|
|||||||
new MessageStatusChangeProcessor(),
|
new MessageStatusChangeProcessor(),
|
||||||
new GroupMessageStatusChangeProcessor(),
|
new GroupMessageStatusChangeProcessor(),
|
||||||
new UserStatusChangeProcessor(),
|
new UserStatusChangeProcessor(),
|
||||||
|
new GroupResizeProcessor(),
|
||||||
new IDGeneratorRequestProcessor(),
|
new IDGeneratorRequestProcessor(),
|
||||||
new UserSearchProcessor(),
|
new UserSearchProcessor(),
|
||||||
new UserOperationProcessor(),
|
new UserOperationProcessor(),
|
||||||
|
@ -51,7 +51,7 @@ public class Message {
|
|||||||
@Id
|
@Id
|
||||||
protected long id;
|
protected long id;
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne(cascade = CascadeType.REMOVE)
|
||||||
@JoinColumn
|
@JoinColumn
|
||||||
protected User sender;
|
protected User sender;
|
||||||
|
|
||||||
|
@ -105,11 +105,6 @@ public final class PersistenceManager {
|
|||||||
// Remove this contact from the contact list of his contacts
|
// Remove this contact from the contact list of his contacts
|
||||||
for (final var remainingContact : contact.getContacts())
|
for (final var remainingContact : contact.getContacts())
|
||||||
remainingContact.getContacts().remove(contact);
|
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);
|
remove(contact);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
package envoy.server.processors;
|
package envoy.server.processors;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import envoy.event.GroupResize;
|
import envoy.event.GroupResize;
|
||||||
import envoy.server.data.*;
|
import envoy.server.data.*;
|
||||||
import envoy.server.net.*;
|
import envoy.server.net.ObjectWriteProxy;
|
||||||
|
import envoy.util.EnvoyLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Maximilian Käfer
|
* @author Maximilian Käfer
|
||||||
@ -11,34 +15,37 @@ import envoy.server.net.*;
|
|||||||
public final class GroupResizeProcessor implements ObjectProcessor<GroupResize> {
|
public final class GroupResizeProcessor implements ObjectProcessor<GroupResize> {
|
||||||
|
|
||||||
private static final PersistenceManager persistenceManager = PersistenceManager.getInstance();
|
private static final PersistenceManager persistenceManager = PersistenceManager.getInstance();
|
||||||
private static final ConnectionManager connectionManager = ConnectionManager.getInstance();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(GroupResize groupResize, long socketID, ObjectWriteProxy writeProxy) {
|
public void process(GroupResize groupResize, long socketID, ObjectWriteProxy writeProxy) {
|
||||||
|
|
||||||
// Acquire the group to resize from the database
|
// 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
|
// Perform the desired operation
|
||||||
switch (groupResize.getOperation()) {
|
switch (groupResize.getOperation()) {
|
||||||
case ADD:
|
case ADD:
|
||||||
group.getContacts().add(persistenceManager.getUserByID(groupResize.get().getID()));
|
persistenceManager.addContactBidirectional(sender, group);
|
||||||
break;
|
writeProxy.writeToOnlineContacts(group.getContacts(), group.toCommon());
|
||||||
|
return;
|
||||||
case REMOVE:
|
case REMOVE:
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
|
||||||
group.getContacts().remove(persistenceManager.getUserByID(groupResize.get().getID()));
|
group.getContacts().remove(persistenceManager.getUserByID(groupResize.get().getID()));
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user