feat: sync chat with user selection
This commit is contained in:
parent
657ab85915
commit
ca8e267fb3
14 changed files with 131 additions and 59 deletions
|
@ -1,42 +1,60 @@
|
|||
package fr.insa.clavardator.chat;
|
||||
|
||||
import fr.insa.clavardator.db.DatabaseController;
|
||||
import fr.insa.clavardator.users.User;
|
||||
import fr.insa.clavardator.users.CurrentUser;
|
||||
import fr.insa.clavardator.users.PeerUser;
|
||||
import fr.insa.clavardator.users.UserList;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
||||
public class ChatHistory {
|
||||
private final DatabaseController db;
|
||||
private final User user;
|
||||
private ArrayList<Message> history = new ArrayList<>();
|
||||
private final PeerUser user;
|
||||
private final ArrayList<HistoryLoadedCallback> historyListener;
|
||||
private final ArrayList<MessageAddedCallback> messageListener;
|
||||
private ArrayList<Message> history;
|
||||
|
||||
public ChatHistory(User user) {
|
||||
public ChatHistory(PeerUser user) {
|
||||
this.user = user;
|
||||
db = new DatabaseController(user);
|
||||
this.historyListener = new ArrayList<>();
|
||||
this.messageListener = new ArrayList<>();
|
||||
}
|
||||
|
||||
// Make this class observable
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
|
||||
public void addObserver(PropertyChangeListener listener) {
|
||||
pcs.addPropertyChangeListener(listener);
|
||||
public void addHistoryLoadedListener(HistoryLoadedCallback listener) {
|
||||
historyListener.add(listener);
|
||||
}
|
||||
|
||||
public void removeObserver(PropertyChangeListener listener) {
|
||||
pcs.removePropertyChangeListener(listener);
|
||||
public void addMessageAddedListener(MessageAddedCallback listener) {
|
||||
messageListener.add(listener);
|
||||
}
|
||||
|
||||
private void notifyHistoryLoaded() {
|
||||
historyListener.forEach(l -> l.onHistoryLoaded(history));
|
||||
}
|
||||
|
||||
private void getHistory() {
|
||||
db.getChatHistory(new Date(), new Date(), // TODO: put actual date
|
||||
newHistory -> {
|
||||
ArrayList<Message> oldHistory = history;
|
||||
history = newHistory;
|
||||
pcs.firePropertyChange("history", oldHistory, history); // Does this work?
|
||||
});
|
||||
private void notifyMessageAdded(Message message) {
|
||||
messageListener.forEach(l -> l.onMessageAdded(message));
|
||||
}
|
||||
|
||||
public void load() {
|
||||
if (history == null) {
|
||||
// TODO remove after tests
|
||||
CurrentUser currentUser = new CurrentUser("Moi", new UserList());
|
||||
history = new ArrayList<>();
|
||||
history.add(new Message(user, currentUser, "Coucou toi"));
|
||||
history.add(new Message(currentUser, user, "Coucou " + user.getUsername()));
|
||||
history.add(new Message(user, currentUser, "oui"));
|
||||
history.add(new Message(currentUser, user, "merci"));
|
||||
notifyHistoryLoaded();
|
||||
// db.getChatHistory(new Date(), new Date(), // TODO: put actual date
|
||||
// newHistory -> {
|
||||
// history = newHistory;
|
||||
// notifyHistoryLoaded();
|
||||
// });
|
||||
} else {
|
||||
notifyHistoryLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -44,12 +62,18 @@ public class ChatHistory {
|
|||
* @param message
|
||||
*/
|
||||
public void addMessage(Message message) {
|
||||
db.addMessage(message, new DatabaseController.MessageCallback() {
|
||||
@Override
|
||||
public void onMessageSaved(Message savedMessage) {
|
||||
history.add(savedMessage);
|
||||
pcs.firePropertyChange("history", null, history);
|
||||
}
|
||||
db.addMessage(message, () -> {
|
||||
history.add(message);
|
||||
notifyMessageAdded(message);
|
||||
});
|
||||
}
|
||||
|
||||
public interface MessageAddedCallback {
|
||||
void onMessageAdded(Message message);
|
||||
}
|
||||
|
||||
public interface HistoryLoadedCallback {
|
||||
void onHistoryLoaded(ArrayList<Message> history);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
package fr.insa.clavardator.chat;
|
||||
|
||||
import fr.insa.clavardator.users.CurrentUser;
|
||||
import fr.insa.clavardator.users.User;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Message implements Serializable {
|
||||
private String text;
|
||||
private final User recipient;
|
||||
private final User sender;
|
||||
private final String text;
|
||||
|
||||
public Message(User sender, User recipient) {
|
||||
this(sender, recipient, "");
|
||||
|
|
|
@ -57,6 +57,6 @@ public class DatabaseController {
|
|||
}
|
||||
|
||||
public interface MessageCallback {
|
||||
void onMessageSaved(Message history);
|
||||
void onMessageSaved();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package fr.insa.clavardator.ui;
|
|||
|
||||
import fr.insa.clavardator.ui.chat.ChatController;
|
||||
import fr.insa.clavardator.ui.users.UserListController;
|
||||
import fr.insa.clavardator.users.CurrentUser;
|
||||
import fr.insa.clavardator.users.UserList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
|
||||
|
@ -17,11 +19,13 @@ public class MainController implements Initializable {
|
|||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb) {
|
||||
chatController.setCurrentUser(new CurrentUser("Moi", new UserList()));
|
||||
userListController.addRefreshUserListener(() -> {
|
||||
System.out.println("refresh event");
|
||||
});
|
||||
userListController.addUserSelectedListener((user) -> {
|
||||
System.out.println(user.getUsername());
|
||||
chatController.setRemoteUser(user);
|
||||
});
|
||||
chatController.addAttachmentListener(() -> {
|
||||
System.out.println("attach event");
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package fr.insa.clavardator.ui;
|
||||
|
||||
import fr.insa.clavardator.users.User;
|
||||
import fr.insa.clavardator.users.PeerUser;
|
||||
|
||||
public interface UserSelectedEvent {
|
||||
public void onSelected(User user);
|
||||
void onSelected(PeerUser user);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package fr.insa.clavardator.ui.chat;
|
||||
|
||||
import fr.insa.clavardator.chat.ChatHistory;
|
||||
import fr.insa.clavardator.chat.Message;
|
||||
import fr.insa.clavardator.ui.ButtonPressEvent;
|
||||
import fr.insa.clavardator.ui.NoSelectionModel;
|
||||
import fr.insa.clavardator.users.ActiveUser;
|
||||
import fr.insa.clavardator.users.CurrentUser;
|
||||
import fr.insa.clavardator.users.PeerUser;
|
||||
import javafx.collections.FXCollections;
|
||||
|
@ -12,6 +14,7 @@ import javafx.fxml.Initializable;
|
|||
import javafx.scene.control.ListView;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class ChatController implements Initializable {
|
||||
|
@ -40,25 +43,32 @@ public class ChatController implements Initializable {
|
|||
|
||||
|
||||
public void setCurrentUser(CurrentUser currentUser) {
|
||||
this.chatHeaderController.setCurrentUser(currentUser);
|
||||
this.currentUser = currentUser;
|
||||
}
|
||||
|
||||
public void setRemoteUser(PeerUser remoteUser) {
|
||||
this.remoteUser = remoteUser;
|
||||
loadMessageList();
|
||||
this.chatHeaderController.setRemoteUser(remoteUser);
|
||||
this.chatFooterController.setEnabled(remoteUser instanceof ActiveUser);
|
||||
|
||||
final ChatHistory history = remoteUser.getHistory();
|
||||
history.addHistoryLoadedListener(this::onHistoryLoaded);
|
||||
history.addMessageAddedListener(this::onMessageAdded);
|
||||
history.load();
|
||||
}
|
||||
|
||||
private void loadMessageList() {
|
||||
ObservableList<Message> messages = FXCollections.observableArrayList(
|
||||
new Message(remoteUser, currentUser, "Messsssage 1"),
|
||||
new Message(remoteUser, currentUser, "Messsssage 2"),
|
||||
new Message(currentUser, remoteUser, "Messsssage 3"),
|
||||
new Message(remoteUser, currentUser, "Messsssage 4")
|
||||
);
|
||||
messageList.setItems(messages);
|
||||
private void onHistoryLoaded(ArrayList<Message> messages) {
|
||||
messageList.setItems(FXCollections.observableArrayList(messages));
|
||||
messageList.scrollTo(messageList.getItems().size() - 1);
|
||||
}
|
||||
|
||||
private void onMessageAdded(Message message) {
|
||||
messageList.getItems().add(message);
|
||||
messageList.scrollTo(messageList.getItems().size() - 1);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb) {
|
||||
messageList.setItems(null);
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package fr.insa.clavardator.ui.chat;
|
||||
|
||||
import fr.insa.clavardator.ui.ButtonPressEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
@ -10,6 +12,9 @@ import java.util.ResourceBundle;
|
|||
|
||||
public class ChatFooterController implements Initializable {
|
||||
|
||||
@FXML
|
||||
private HBox container;
|
||||
|
||||
private List<ButtonPressEvent> attachmentListeners;
|
||||
private List<ButtonPressEvent> sendListeners;
|
||||
|
||||
|
@ -27,6 +32,10 @@ public class ChatFooterController implements Initializable {
|
|||
sendListeners.forEach(ButtonPressEvent::onPress);
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
container.setDisable(!enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
attachmentListeners = new ArrayList<>();
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
package fr.insa.clavardator.ui.chat;
|
||||
|
||||
import fr.insa.clavardator.ui.ButtonPressEvent;
|
||||
import fr.insa.clavardator.ui.users.UserActiveIndicatorController;
|
||||
import fr.insa.clavardator.users.CurrentUser;
|
||||
import fr.insa.clavardator.users.PeerUser;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.Label;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
@ -10,8 +15,18 @@ import java.util.ResourceBundle;
|
|||
|
||||
public class ChatHeaderController implements Initializable {
|
||||
|
||||
@FXML
|
||||
private Label currentUsernameLabel;
|
||||
@FXML
|
||||
private Label remoteUsernameLabel;
|
||||
@FXML
|
||||
private UserActiveIndicatorController indicatorController;
|
||||
|
||||
private List<ButtonPressEvent> editListeners;
|
||||
|
||||
private CurrentUser currentUser;
|
||||
private PeerUser remoteUser;
|
||||
|
||||
public void addEditListener(ButtonPressEvent listener) {
|
||||
editListeners.add(listener);
|
||||
}
|
||||
|
@ -27,4 +42,16 @@ public class ChatHeaderController implements Initializable {
|
|||
public void initialize(URL location, ResourceBundle resources) {
|
||||
editListeners = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void setCurrentUser(CurrentUser currentUser) {
|
||||
this.currentUser = currentUser;
|
||||
currentUsernameLabel.setText(currentUser.getUsername());
|
||||
}
|
||||
|
||||
public void setRemoteUser(PeerUser remoteUser) {
|
||||
this.remoteUser = remoteUser;
|
||||
remoteUsernameLabel.setText(remoteUser.getUsername());
|
||||
indicatorController.setUser(remoteUser);
|
||||
indicatorController.setSize(10.0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,4 +28,8 @@ public class UserActiveIndicatorController implements Initializable {
|
|||
}
|
||||
}
|
||||
|
||||
public void setSize(double value) {
|
||||
circle.setRadius(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ public class UserListController implements Initializable {
|
|||
final private List<ButtonPressEvent> refreshUserListeners;
|
||||
final private List<UserSelectedEvent> userSelectedListeners;
|
||||
@FXML
|
||||
private ListView<User> userList;
|
||||
private ListView<PeerUser> userList;
|
||||
|
||||
public UserListController() {
|
||||
super();
|
||||
|
@ -43,7 +43,7 @@ public class UserListController implements Initializable {
|
|||
refreshUserListeners.forEach(ButtonPressEvent::onPress);
|
||||
}
|
||||
|
||||
private void onUserSelected(@org.jetbrains.annotations.NotNull User user) {
|
||||
private void onUserSelected(@org.jetbrains.annotations.NotNull PeerUser user) {
|
||||
final User currentSelectedUser = userList.getSelectionModel().getSelectedItem();
|
||||
if (!user.equals(currentSelectedUser)) {
|
||||
userList.getSelectionModel().select(user);
|
||||
|
@ -53,7 +53,7 @@ public class UserListController implements Initializable {
|
|||
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb) {
|
||||
ObservableList<User> activeList = null;
|
||||
ObservableList<PeerUser> activeList = null;
|
||||
try {
|
||||
activeList = FXCollections.observableArrayList(
|
||||
new PeerUser("Dodo0"),
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package fr.insa.clavardator.ui.users;
|
||||
|
||||
import fr.insa.clavardator.ui.UserSelectedEvent;
|
||||
import fr.insa.clavardator.users.User;
|
||||
import fr.insa.clavardator.users.PeerUser;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.control.ListCell;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class UserListItemCell extends ListCell<User> {
|
||||
public class UserListItemCell extends ListCell<PeerUser> {
|
||||
|
||||
private UserSelectedEvent listener;
|
||||
|
||||
|
@ -20,7 +20,7 @@ public class UserListItemCell extends ListCell<User> {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void updateItem(User item, boolean empty) {
|
||||
protected void updateItem(PeerUser item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (!empty && item != null) {
|
||||
final FXMLLoader cellLoader = new FXMLLoader(getClass().getResource("userListItem.fxml"));
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<HBox xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="fr.insa.clavardator.ui.chat.ChatFooterController"
|
||||
stylesheets="@../styles.css" styleClass="container" alignment="CENTER" spacing="10.0">
|
||||
stylesheets="@../styles.css" styleClass="container" alignment="CENTER" spacing="10.0" fx:id="container">
|
||||
<padding>
|
||||
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/>
|
||||
</padding>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<Insets left="20" right="20"/>
|
||||
</padding>
|
||||
<Label text="Connecté en tant que : "/>
|
||||
<Label text="<USERNAME>"/>
|
||||
<Label text="<USERNAME>" fx:id="currentUsernameLabel"/>
|
||||
<JFXButton mnemonicParsing="false" onMouseClicked="#onEditPress">
|
||||
<graphic>
|
||||
<FontIcon iconLiteral="fas-user-edit" iconSize="24"/>
|
||||
|
@ -32,7 +32,7 @@
|
|||
<padding>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
|
||||
</padding>
|
||||
<Circle radius="7.0" styleClass="active-user-dot"/>
|
||||
<Label text="USER NAME" styleClass="current-user"/>
|
||||
<fx:include source="../users/userActiveIndicator.fxml" fx:id="indicator" />
|
||||
<Label text="USER NAME" styleClass="current-user" fx:id="remoteUsernameLabel"/>
|
||||
</HBox>
|
||||
</VBox>
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import java.lang.*?>
|
||||
<?import java.util.*?>
|
||||
<?import javafx.scene.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
|
||||
<?import javafx.scene.shape.Circle?>
|
||||
<AnchorPane xmlns="http://javafx.com/javafx"
|
||||
<HBox xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="fr.insa.clavardator.ui.users.UserActiveIndicatorController"
|
||||
stylesheets="@../styles.css"
|
||||
styleClass="inner">
|
||||
stylesheets="@../styles.css" alignment="CENTER">
|
||||
<Circle fx:id="circle" radius="5.0" styleClass="active-user-dot"/>
|
||||
</AnchorPane>
|
||||
</HBox>
|
||||
|
|
Loading…
Reference in a new issue