Move context menu from ChatScene globally to ChatControl specific
Additionally fixed a small bug in UserCreationProcessor and when deleting a contact offline
This commit is contained in:
		| @@ -1,12 +1,13 @@ | ||||
| package envoy.client.ui.control; | ||||
|  | ||||
| import javafx.geometry.*; | ||||
| import javafx.scene.control.Label; | ||||
| import javafx.scene.control.*; | ||||
| import javafx.scene.image.Image; | ||||
| import javafx.scene.layout.*; | ||||
|  | ||||
| import envoy.client.data.*; | ||||
| import envoy.client.util.IconUtil; | ||||
| import envoy.client.util.*; | ||||
| import envoy.data.User; | ||||
|  | ||||
| /** | ||||
|  * Displays a chat using a contact control for the recipient and a label for the | ||||
| @@ -16,7 +17,7 @@ import envoy.client.util.IconUtil; | ||||
|  * @author Leon Hofmeister | ||||
|  * @since Envoy Client v0.1-beta | ||||
|  */ | ||||
| public final class ChatControl extends HBox { | ||||
| public final class ChatControl extends Label { | ||||
|  | ||||
| 	private static final Image userIcon = IconUtil.loadIconThemeSensitive("user_icon", 32), | ||||
| 			groupIcon = IconUtil.loadIconThemeSensitive("group_icon", 32); | ||||
| @@ -31,25 +32,35 @@ public final class ChatControl extends HBox { | ||||
| 		setAlignment(Pos.CENTER_LEFT); | ||||
| 		setPadding(new Insets(0, 0, 3, 0)); | ||||
|  | ||||
| 		final var	menu		= new ContextMenu(); | ||||
| 		final var	removeMI	= new MenuItem(); | ||||
| 		removeMI | ||||
| 			.setText(chat.isDisabled() ? "Delete " : chat.getRecipient() instanceof User ? "Block " : "Leave group " + chat.getRecipient().getName()); | ||||
| 		removeMI.setOnAction(chat.isDisabled() ? e -> UserUtil.deleteContact(chat.getRecipient()) : e -> UserUtil.blockContact(chat.getRecipient())); | ||||
| 		menu.getItems().add(removeMI); | ||||
| 		setContextMenu(menu); | ||||
|  | ||||
| 		final var display = new HBox(); | ||||
|  | ||||
| 		// Profile picture | ||||
| 		final var contactProfilePic = new ProfilePicImageView(chat instanceof GroupChat ? groupIcon : userIcon, 32); | ||||
| 		getChildren().add(contactProfilePic); | ||||
| 		display.getChildren().add(contactProfilePic); | ||||
|  | ||||
| 		// Spacing | ||||
| 		final var leftSpacing = new Region(); | ||||
| 		leftSpacing.setPrefSize(8, 0); | ||||
| 		leftSpacing.setMinSize(8, 0); | ||||
| 		leftSpacing.setMaxSize(8, 0); | ||||
| 		getChildren().add(leftSpacing); | ||||
| 		display.getChildren().add(leftSpacing); | ||||
|  | ||||
| 		// Contact control | ||||
| 		getChildren().add(new ContactControl(chat.getRecipient())); | ||||
| 		display.getChildren().add(new ContactControl(chat.getRecipient())); | ||||
|  | ||||
| 		// Unread messages | ||||
| 		if (chat.getUnreadAmount() != 0) { | ||||
| 			final var spacing = new Region(); | ||||
| 			setHgrow(spacing, Priority.ALWAYS); | ||||
| 			getChildren().add(spacing); | ||||
| 			HBox.setHgrow(spacing, Priority.ALWAYS); | ||||
| 			display.getChildren().add(spacing); | ||||
| 			final var unreadMessagesLabel = new Label(Integer.toString(chat.getUnreadAmount())); | ||||
| 			unreadMessagesLabel.setMinSize(15, 15); | ||||
| 			final var vbox = new VBox(); | ||||
| @@ -57,9 +68,11 @@ public final class ChatControl extends HBox { | ||||
| 			unreadMessagesLabel.setAlignment(Pos.CENTER); | ||||
| 			unreadMessagesLabel.getStyleClass().add("unread-messages-amount"); | ||||
| 			vbox.getChildren().add(unreadMessagesLabel); | ||||
| 			getChildren().add(vbox); | ||||
| 			display.getChildren().add(vbox); | ||||
| 		} | ||||
|  | ||||
| 		setGraphic(display); | ||||
|  | ||||
| 		// Set background depending on whether it is disabled or not | ||||
| 		getStyleClass().add(chat.isDisabled() ? "disabled-chat" : "list-element"); | ||||
| 	} | ||||
|   | ||||
| @@ -91,9 +91,6 @@ public final class ChatScene implements EventListener, Restorable { | ||||
| 	@FXML | ||||
| 	private Label topBarStatusLabel; | ||||
|  | ||||
| 	@FXML | ||||
| 	private MenuItem deleteContactMenuItem; | ||||
|  | ||||
| 	@FXML | ||||
| 	private ImageView attachmentView; | ||||
|  | ||||
| @@ -278,12 +275,13 @@ public final class ChatScene implements EventListener, Restorable { | ||||
| 	@Event | ||||
| 	private void onGroupResize(GroupResize resize) { | ||||
| 		final var chatFound = localDB.getChat(resize.getGroupID()); | ||||
| 		if (chatFound.isEmpty()) return; | ||||
| 		Platform.runLater(() -> { | ||||
| 			chatList.refresh(); | ||||
|  | ||||
| 			// Update the top-bar status label if all conditions apply | ||||
| 			if (currentChat != null && currentChat.getRecipient().equals(chatFound.get().getRecipient())) | ||||
| 				chatFound.ifPresent(chat -> topBarStatusLabel.setText(chat.getRecipient().getContacts().size() + " members")); | ||||
| 				topBarStatusLabel.setText(chatFound.get().getRecipient().getContacts().size() + " members"); | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| @@ -348,7 +346,6 @@ public final class ChatScene implements EventListener, Restorable { | ||||
| 			final var scrollIndex = messageList.getItems().size() - currentChat.getUnreadAmount(); | ||||
| 			messageList.scrollTo(scrollIndex); | ||||
| 			logger.log(Level.FINEST, "Loading chat with " + user + " at index " + scrollIndex); | ||||
| 			deleteContactMenuItem.setText("Delete " + user.getName()); | ||||
|  | ||||
| 			// Read the current chat | ||||
| 			currentChat.read(writeProxy); | ||||
| @@ -746,18 +743,6 @@ public final class ChatScene implements EventListener, Restorable { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Context menu actions | ||||
|  | ||||
| 	@FXML | ||||
| 	private void blockOrDeleteContact() { | ||||
| 		final var selectedChat = chatList.getSelectionModel().getSelectedItem(); | ||||
|  | ||||
| 		if (selectedChat == null) return; | ||||
| 		// If a contact has already been blocked deletes this chat else only blocks him | ||||
| 		if (selectedChat.isDisabled()) UserUtil.deleteContact(selectedChat.getRecipient()); | ||||
| 		else UserUtil.blockContact(selectedChat.getRecipient()); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Redesigns the UI when the {@link Chat} of the given contact has been marked | ||||
| 	 * as disabled. | ||||
|   | ||||
| @@ -102,7 +102,7 @@ public final class UserUtil { | ||||
| 	 * @since Envoy Client v0.3-beta | ||||
| 	 */ | ||||
| 	public static void deleteContact(Contact delete) { | ||||
| 		if (!context.getClient().isOnline() || delete == null) return; | ||||
| 		if (delete == null) return; | ||||
| 		else { | ||||
| 			final var alert = new Alert(AlertType.CONFIRMATION); | ||||
| 			alert.setContentText("Are you sure you want to delete " + delete.getName() | ||||
|   | ||||
| @@ -126,15 +126,6 @@ | ||||
| 										<ListView id="chat-list" fx:id="chatList" | ||||
| 											focusTraversable="false" onMouseClicked="#chatListClicked" | ||||
| 											prefWidth="316.0" VBox.vgrow="ALWAYS"> | ||||
| 											<contextMenu> | ||||
| 												<ContextMenu anchorLocation="CONTENT_TOP_LEFT"> | ||||
| 													<items> | ||||
| 														<MenuItem fx:id="deleteContactMenuItem" | ||||
| 															mnemonicParsing="false" onAction="#blockOrDeleteContact" | ||||
| 															text="Delete" /> | ||||
| 													</items> | ||||
| 												</ContextMenu> | ||||
| 											</contextMenu> | ||||
| 											<padding> | ||||
| 												<Insets bottom="5.0" left="5.0" right="2.0" top="5.0" /> | ||||
| 											</padding> | ||||
|   | ||||
| @@ -51,7 +51,7 @@ public final class Startup { | ||||
| 						new UserStatusChangeProcessor(), | ||||
| 						new IDGeneratorRequestProcessor(), | ||||
| 						new UserSearchProcessor(), | ||||
| 						new ContactOperationProcessor(), | ||||
| 						new UserOperationProcessor(), | ||||
| 						new IsTypingProcessor(), | ||||
| 						new NameChangeProcessor(), | ||||
| 						new ProfilePicChangeProcessor(), | ||||
|   | ||||
| @@ -2,11 +2,13 @@ package envoy.server.data; | ||||
|  | ||||
| import java.time.Instant; | ||||
| import java.util.List; | ||||
| import java.util.logging.Level; | ||||
|  | ||||
| import javax.persistence.*; | ||||
|  | ||||
| import envoy.data.User.UserStatus; | ||||
| import envoy.server.net.ConnectionManager; | ||||
| import envoy.util.EnvoyLog; | ||||
|  | ||||
| /** | ||||
|  * Contains operations used for persistence. | ||||
| @@ -240,17 +242,24 @@ public final class PersistenceManager { | ||||
| 	 * @since Envoy Server Standalone v0.1-alpha | ||||
| 	 */ | ||||
| 	public void addContactBidirectional(long contactID1, long contactID2) { | ||||
| 		addContactBidirectional(getContactByID(contactID1), getContactByID(contactID2)); | ||||
| 	} | ||||
|  | ||||
| 		// Get users by ID | ||||
| 		final var	c1	= getContactByID(contactID1); | ||||
| 		final var	c2	= getContactByID(contactID2); | ||||
| 	/** | ||||
| 	 * Adds a contact to the contact list of another contact and vice versa. | ||||
| 	 * | ||||
| 	 * @param contact1 the first contact | ||||
| 	 * @param contact2 the second contact | ||||
| 	 * @since Envoy Server v0.3-beta | ||||
| 	 */ | ||||
| 	public void addContactBidirectional(Contact contact1, Contact contact2) { | ||||
|  | ||||
| 		// Add users to each others contact list | ||||
| 		c1.getContacts().add(c2); | ||||
| 		c2.getContacts().add(c1); | ||||
| 		contact1.getContacts().add(contact2); | ||||
| 		contact2.getContacts().add(contact1); | ||||
|  | ||||
| 		// Synchronize changes with the database | ||||
| 		transaction(() -> { entityManager.merge(c1); entityManager.merge(c2); }); | ||||
| 		transaction(() -> { entityManager.merge(contact1); entityManager.merge(contact2); }); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| @@ -261,17 +270,24 @@ public final class PersistenceManager { | ||||
| 	 * @since Envoy Server v0.3-beta | ||||
| 	 */ | ||||
| 	public void removeContactBidirectional(long contactID1, long contactID2) { | ||||
| 		removeContactBidirectional(getContactByID(contactID1), getContactByID(contactID2)); | ||||
| 	} | ||||
|  | ||||
| 		// Get users by ID | ||||
| 		final var	c1	= getContactByID(contactID1); | ||||
| 		final var	c2	= getContactByID(contactID2); | ||||
| 	/** | ||||
| 	 * Removes a contact from the contact list of another contact and vice versa. | ||||
| 	 * | ||||
| 	 * @param contact1 the first contact | ||||
| 	 * @param contact2 the second contact | ||||
| 	 * @since Envoy Server v0.3-beta | ||||
| 	 */ | ||||
| 	public void removeContactBidirectional(Contact contact1, Contact contact2) { | ||||
|  | ||||
| 		// Remove users from each others contact list | ||||
| 		c1.getContacts().remove(c2); | ||||
| 		c2.getContacts().remove(c1); | ||||
| 		contact1.getContacts().remove(contact2); | ||||
| 		contact2.getContacts().remove(contact1); | ||||
|  | ||||
| 		// Synchronize changes with the database | ||||
| 		transaction(() -> { entityManager.merge(c1); entityManager.merge(c2); }); | ||||
| 		transaction(() -> { entityManager.merge(contact1); entityManager.merge(contact2); }); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| @@ -311,6 +327,14 @@ public final class PersistenceManager { | ||||
| 				entityManagerRelatedAction.run(); | ||||
| 				transaction.commit(); | ||||
| 			} | ||||
| 		} catch (final RollbackException e2) { | ||||
|  | ||||
| 			// Apparently a major problem exists. Discard faulty transaction and then go on. | ||||
| 			if (transaction.isActive()) { | ||||
| 				transaction.rollback(); | ||||
| 				EnvoyLog.getLogger(PersistenceManager.class) | ||||
| 					.log(Level.SEVERE, "Could not perform transaction, hence discarding it. It's likely that a serious issue exists."); | ||||
| 			} else throw e2; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import static envoy.server.Startup.config; | ||||
| import java.util.HashSet; | ||||
|  | ||||
| import envoy.event.*; | ||||
| import envoy.server.data.*; | ||||
| import envoy.server.data.PersistenceManager; | ||||
| import envoy.server.net.*; | ||||
|  | ||||
| /** | ||||
| @@ -27,18 +27,12 @@ public final class GroupCreationProcessor implements ObjectProcessor<GroupCreati | ||||
| 		final envoy.server.data.Group group = new envoy.server.data.Group(); | ||||
| 		group.setName(groupCreation.get()); | ||||
| 		group.setContacts(new HashSet<>()); | ||||
| 		groupCreation.getInitialMemberIDs().stream().map(persistenceManager::getUserByID).forEach(group.getContacts()::add); | ||||
| 		group.getContacts().add(persistenceManager.getContactByID(connectionManager.getUserIDBySocketID(socketID))); | ||||
| 		group.getContacts().forEach(c -> c.getContacts().add(group)); | ||||
| 		group.getContacts().add(persistenceManager.getUserByID(connectionManager.getUserIDBySocketID(socketID))); | ||||
| 		persistenceManager.addContact(group); | ||||
| 		final var resultGroup = group.toCommon(); | ||||
| 		group.getContacts() | ||||
| 		groupCreation.getInitialMemberIDs() | ||||
| 			.stream() | ||||
| 			.map(Contact::getID) | ||||
| 			.filter(connectionManager::isOnline) | ||||
| 			.map(connectionManager::getSocketID) | ||||
| 			.forEach(memberSocketID -> writeProxy.write(memberSocketID, new GroupCreationResult(resultGroup))); | ||||
| 		writeProxy.write(socketID, new GroupCreationResult(resultGroup)); | ||||
| 			.map(persistenceManager::getUserByID) | ||||
| 			.forEach(member -> persistenceManager.addContactBidirectional(member, group)); | ||||
| 		persistenceManager.addContactBidirectional(persistenceManager.getUserByID(connectionManager.getUserIDBySocketID(socketID)), group); | ||||
| 		writeProxy.writeToOnlineContacts(group.getContacts(), new GroupCreationResult(group.toCommon())); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import java.util.logging.*; | ||||
| 
 | ||||
| import envoy.event.ElementOperation; | ||||
| import envoy.event.contact.UserOperation; | ||||
| import envoy.server.data.*; | ||||
| import envoy.server.data.PersistenceManager; | ||||
| import envoy.server.net.*; | ||||
| import envoy.util.EnvoyLog; | ||||
| 
 | ||||
| @@ -13,10 +13,10 @@ import envoy.util.EnvoyLog; | ||||
|  * @author Kai S. K. Engelbart | ||||
|  * @since Envoy Server Standalone v0.1-alpha | ||||
|  */ | ||||
| public final class ContactOperationProcessor implements ObjectProcessor<UserOperation> { | ||||
| public final class UserOperationProcessor implements ObjectProcessor<UserOperation> { | ||||
| 
 | ||||
| 	private static final ConnectionManager	connectionManager	= ConnectionManager.getInstance(); | ||||
| 	private static final Logger				logger				= EnvoyLog.getLogger(ContactOperationProcessor.class); | ||||
| 	private static final Logger				logger				= EnvoyLog.getLogger(UserOperationProcessor.class); | ||||
| 	private static final PersistenceManager	persistenceManager	= PersistenceManager.getInstance(); | ||||
| 
 | ||||
| 	@Override | ||||
| @@ -38,35 +38,15 @@ public final class ContactOperationProcessor implements ObjectProcessor<UserOper | ||||
| 				// Remove the relationships and notify sender if he logs in using another | ||||
| 				// LocalDB | ||||
| 				persistenceManager.removeContactBidirectional(userID, contactID); | ||||
| 				final var contact = persistenceManager.getContactByID(contactID); | ||||
| 				sender.setLatestContactDeletion(Instant.now()); | ||||
| 
 | ||||
| 				// The sender wants to remove a normal contact | ||||
| 				if (contact instanceof User) { | ||||
| 				// Notify the removed contact on next startup(s) of this deletion | ||||
| 				persistenceManager.getUserByID(contactID).setLatestContactDeletion(Instant.now()); | ||||
| 
 | ||||
| 					// Notify the removed contact on next startup(s) of this deletion | ||||
| 					persistenceManager.getUserByID(contactID).setLatestContactDeletion(Instant.now()); | ||||
| 
 | ||||
| 					// Notify the removed contact if online | ||||
| 					if (connectionManager.isOnline(contactID)) | ||||
| 						writeProxy.write(connectionManager.getSocketID(contactID), new UserOperation(sender.toCommon(), ElementOperation.REMOVE)); | ||||
| 				} else { | ||||
| 
 | ||||
| 					// The sender wants to be removed from a Group | ||||
| 					final var group = persistenceManager.getGroupByID(contactID); | ||||
| 
 | ||||
| 					// The group has no more members and hence will be deleted | ||||
| 					if (group.getContacts().isEmpty()) persistenceManager.deleteContact(group); | ||||
| 					else { | ||||
| 
 | ||||
| 						// Informing the other members | ||||
| 						writeProxy.writeToOnlineContacts(group.getContacts(), new UserOperation(sender.toCommon(), ElementOperation.REMOVE)); | ||||
| 						group.getContacts().forEach(c -> ((User) c).setLatestContactDeletion(Instant.now())); | ||||
| 					} | ||||
| 				} | ||||
| 				// Notify the removed contact if online | ||||
| 				if (connectionManager.isOnline(contactID)) | ||||
| 					writeProxy.write(connectionManager.getSocketID(contactID), new UserOperation(sender.toCommon(), ElementOperation.REMOVE)); | ||||
| 				break; | ||||
| 			default: | ||||
| 				logger.warning(String.format("Received %s with an unsupported operation.", evt)); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 KSKE Git
						KSKE Git