package envoy.client.ui.controller; import java.util.function.Consumer; import java.util.logging.Level; import java.util.logging.Logger; import javafx.application.Platform; import javafx.fxml.FXML; import javafx.scene.control.*; import javafx.scene.control.Alert.AlertType; import envoy.client.data.LocalDB; import envoy.client.event.SendEvent; import envoy.client.ui.ClearableTextField; import envoy.client.ui.SceneContext; import envoy.client.ui.listcell.ContactControl; import envoy.client.ui.listcell.ListCellFactory; import envoy.data.User; import envoy.event.ElementOperation; import envoy.event.EventBus; import envoy.event.contact.ContactOperation; import envoy.event.contact.UserSearchRequest; import envoy.event.contact.UserSearchResult; import envoy.util.EnvoyLog; /** * Provides a search bar in which a user name (substring) can be entered. The * users with a matching name are then displayed inside a list view. A * {@link UserSearchRequest} is sent on every keystroke. *

* The actual search algorithm is implemented on the server. *

* To create a group, a button is available that loads the * {@link GroupCreationScene}. *

* Project: envoy-client
* File: ContactSearchScene.java
* Created: 07.06.2020
* * @author Leon Hofmeister * @author Maximilian Käfer * @since Envoy Client v0.1-beta */ public class ContactSearchTab { @FXML private TextArea searchBar; @FXML private ListView userList; private SceneContext sceneContext; private LocalDB localDB; private Alert alert = new Alert(AlertType.CONFIRMATION); private User currentlySelectedUser; private final Consumer handler = e -> { final var contact = e.get(); if (e.getOperationType() == ElementOperation.ADD) Platform.runLater(() -> { userList.getItems().remove(contact); if (currentlySelectedUser != null && currentlySelectedUser.equals(contact) && alert.isShowing()) alert.close(); }); }; private static final EventBus eventBus = EventBus.getInstance(); private static final Logger logger = EnvoyLog.getLogger(ChatScene.class); /** * @param sceneContext enables the user to return to the chat scene * @param localDB the local database to which new contacts are added * @since Envoy Client v0.1-beta */ public void initializeData(SceneContext sceneContext, LocalDB localDB) { this.sceneContext = sceneContext; this.localDB = localDB; } @FXML private void initialize() { userList.setCellFactory(new ListCellFactory<>(ContactControl::new)); eventBus.register(UserSearchResult.class, response -> Platform.runLater(() -> { userList.getItems().clear(); userList.getItems().addAll(response.get()); })); eventBus.register(ContactOperation.class, handler); } /** * Disables the clear and search button if no text is present in the search bar. * * @since Envoy Client v0.1-beta */ @FXML private void sendRequest() { final var text = searchBar.getText().strip(); if (!text.isBlank()) eventBus.dispatch(new SendEvent(new UserSearchRequest(text))); else userList.getItems().clear(); } /** * Clears the text in the search bar and the items shown in the list. * Additionally disables both clear and search button. * * @since Envoy Client v0.1-beta */ @FXML private void clear() { searchBar.setText(null); userList.getItems().clear(); } /** * Sends an {@link ContactOperation} for the selected user to the * server. * * @since Envoy Client v0.1-beta */ @FXML private void userListClicked() { final var user = userList.getSelectionModel().getSelectedItem(); if (user != null) { currentlySelectedUser = user; alert = new Alert(AlertType.CONFIRMATION); alert.setTitle("Add User to Contact List"); alert.setHeaderText("Add the user " + currentlySelectedUser.getName() + " to your contact list?"); // Normally, this would be total BS (we are already on the FX Thread), however // it could be proven that the creation of this dialog wrapped in // Platform.runLater is less error-prone than without it Platform.runLater(() -> alert.showAndWait().filter(btn -> btn == ButtonType.OK).ifPresent(btn -> { final var event = new ContactOperation(currentlySelectedUser, ElementOperation.ADD); // Sends the event to the server eventBus.dispatch(new SendEvent(event)); // Removes the chosen user and updates the UI userList.getItems().remove(currentlySelectedUser); eventBus.dispatch(event); logger.log(Level.INFO, "Added user " + currentlySelectedUser); })); } } // @FXML // private void newGroupButtonClicked() { // sceneContext.load(SceneContext.SceneInfo.GROUP_CREATION_SCENE); // sceneContext.getController().initializeData(sceneContext, localDB); // } // @FXML // private void backButtonClicked() { sceneContext.pop(); } }