fix javafx thread errors and improve chat performance
This commit is contained in:
parent
e7a77a8670
commit
e04b780397
5 changed files with 103 additions and 97 deletions
|
@ -4,24 +4,36 @@ import fr.insa.clavardator.db.DatabaseController;
|
|||
import fr.insa.clavardator.users.CurrentUser;
|
||||
import fr.insa.clavardator.users.PeerUser;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class ChatHistory {
|
||||
private final DatabaseController db;
|
||||
private final PeerUser user;
|
||||
private final ObservableList<Message> history;
|
||||
private final ArrayList<HistoryLoadedCallback> historyListener;
|
||||
private final ArrayList<MessageAddedCallback> messageListener;
|
||||
private ArrayList<Message> history;
|
||||
private final ArrayList<Message> fakeHistory;
|
||||
|
||||
|
||||
public ChatHistory(PeerUser user) {
|
||||
this.user = user;
|
||||
db = new DatabaseController();
|
||||
this.historyListener = new ArrayList<>();
|
||||
this.messageListener = new ArrayList<>();
|
||||
history = FXCollections.observableArrayList();
|
||||
historyListener = new ArrayList<>();
|
||||
fakeHistory = new ArrayList<>();
|
||||
CurrentUser currentUser = CurrentUser.getInstance();
|
||||
try {
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
|
||||
fakeHistory.add(new Message(user, currentUser, format.parse("2021-01-01 10:00:00"), "Coucou toi"));
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void addHistoryLoadedListener(HistoryLoadedCallback listener) {
|
||||
|
@ -32,67 +44,50 @@ public class ChatHistory {
|
|||
historyListener.remove(listener);
|
||||
}
|
||||
|
||||
public void addMessageAddedListener(MessageAddedCallback listener) {
|
||||
messageListener.add(listener);
|
||||
}
|
||||
|
||||
public void removeMessageAddedListener(MessageAddedCallback listener) {
|
||||
messageListener.remove(listener);
|
||||
}
|
||||
|
||||
private void notifyHistoryLoaded() {
|
||||
historyListener.forEach(l -> l.onHistoryLoaded(user, history));
|
||||
}
|
||||
|
||||
private void notifyMessageAdded(Message message) {
|
||||
messageListener.forEach(l -> l.onMessageAdded(user, message));
|
||||
historyListener.forEach(l -> l.onHistoryLoaded(user));
|
||||
}
|
||||
|
||||
public void load() {
|
||||
if (history == null) {
|
||||
// TODO remove after tests
|
||||
CurrentUser currentUser = CurrentUser.getInstance();
|
||||
history = new ArrayList<>();
|
||||
history.add(new Message(user, currentUser, new Date(), "Coucou toi"));
|
||||
history.add(new Message(currentUser, user, new Date(),"Coucou " + user.getUsername()));
|
||||
history.add(new Message(user, currentUser, new Date(),"oui"));
|
||||
history.add(new Message(currentUser, user, new Date(),"merci"));
|
||||
// db.getChatHistory(new Date(), new Date(), // TODO: put actual date
|
||||
// db.getChatHistory(new Date(), new Date(), // TODO: put actual date
|
||||
// newHistory -> {
|
||||
// history = newHistory;
|
||||
// notifyHistoryLoaded();
|
||||
// });
|
||||
}
|
||||
Timer t = new Timer();
|
||||
t.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
Platform.runLater(() -> notifyHistoryLoaded());
|
||||
Platform.runLater(() -> {
|
||||
history.addAll(fakeHistory);
|
||||
history.sort((message, t1) -> (int) (message.getDate().getTime() - t1.getDate().getTime()));
|
||||
});
|
||||
notifyHistoryLoaded();
|
||||
t.cancel();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
public ObservableList<Message> getHistory() {
|
||||
return history;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
*/
|
||||
public void addMessage(Message message) {
|
||||
db.addMessage(message, () -> {
|
||||
if (history == null) {
|
||||
history = new ArrayList<>();
|
||||
}
|
||||
history.add(message);
|
||||
notifyMessageAdded(message);
|
||||
});
|
||||
}
|
||||
|
||||
public interface MessageAddedCallback {
|
||||
void onMessageAdded(PeerUser user, Message message);
|
||||
Platform.runLater(() -> history.add(message));
|
||||
// db.addMessage(message, () -> {
|
||||
// if (history == null) {
|
||||
// history = new ArrayList<>();
|
||||
// }
|
||||
// history.add(message);
|
||||
// notifyMessageAdded(message);
|
||||
// });
|
||||
}
|
||||
|
||||
public interface HistoryLoadedCallback {
|
||||
void onHistoryLoaded(PeerUser user, ArrayList<Message> history);
|
||||
void onHistoryLoaded(PeerUser user);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,16 +7,14 @@ import fr.insa.clavardator.ui.LoadingScreenController;
|
|||
import fr.insa.clavardator.ui.NoSelectionModel;
|
||||
import fr.insa.clavardator.users.PeerUser;
|
||||
import fr.insa.clavardator.util.ErrorCallback;
|
||||
import fr.insa.clavardator.util.Log;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.ListView;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class ChatController implements Initializable {
|
||||
|
@ -29,13 +27,16 @@ public class ChatController implements Initializable {
|
|||
private ChatHeaderController chatHeaderController;
|
||||
@FXML
|
||||
private LoadingScreenController loadingController;
|
||||
|
||||
@FXML
|
||||
private VBox chatContainer;
|
||||
@FXML
|
||||
private VBox emptyContainer;
|
||||
|
||||
private PeerUser remoteUser;
|
||||
private final ChatHistory.HistoryLoadedCallback onHistoryLoaded = (PeerUser user) -> {
|
||||
if (user.equals(remoteUser)) {
|
||||
setState(State.DONE);
|
||||
}
|
||||
};
|
||||
|
||||
public void addAttachmentListener(ButtonPressEvent listener) {
|
||||
chatFooterController.addAttachmentListener(listener);
|
||||
|
@ -53,31 +54,25 @@ public class ChatController implements Initializable {
|
|||
if (this.remoteUser != null) {
|
||||
final ChatHistory oldHistory = this.remoteUser.getHistory();
|
||||
oldHistory.removeHistoryLoadedListener(onHistoryLoaded);
|
||||
oldHistory.removeMessageAddedListener(onMessageAdded);
|
||||
}
|
||||
|
||||
final ChatHistory history = remoteUser.getHistory();
|
||||
history.addHistoryLoadedListener(onHistoryLoaded);
|
||||
history.addMessageAddedListener(onMessageAdded);
|
||||
messageList.setItems(history.getHistory());
|
||||
messageList.getItems().addListener((ListChangeListener<? super Message>) (c) -> {
|
||||
c.next();
|
||||
scrollToEnd();
|
||||
});
|
||||
history.load();
|
||||
this.remoteUser = remoteUser;
|
||||
}
|
||||
|
||||
private final ChatHistory.HistoryLoadedCallback onHistoryLoaded = (PeerUser user, ArrayList<Message> messages) -> {
|
||||
if (user.equals(remoteUser)) {
|
||||
messageList.setItems(FXCollections.observableArrayList(messages));
|
||||
messageList.scrollTo(messageList.getItems().size() - 1);
|
||||
setState(State.DONE);
|
||||
private void scrollToEnd() {
|
||||
final int size = messageList.getItems().size();
|
||||
if (size > 0) {
|
||||
Platform.runLater(() -> messageList.scrollTo(size - 1));
|
||||
}
|
||||
};
|
||||
|
||||
private final ChatHistory.MessageAddedCallback onMessageAdded = (PeerUser user, Message message) -> {
|
||||
Log.v(this.getClass().getSimpleName(), "Message added: " + message.getText());
|
||||
Platform.runLater(() -> {
|
||||
messageList.getItems().add(message);
|
||||
messageList.scrollTo(messageList.getItems().size() - 1);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
private void setState(State state) {
|
||||
switch (state) {
|
||||
|
|
|
@ -1,31 +1,36 @@
|
|||
package fr.insa.clavardator.ui.chat;
|
||||
|
||||
import fr.insa.clavardator.chat.Message;
|
||||
import fr.insa.clavardator.users.CurrentUser;
|
||||
import fr.insa.clavardator.users.User;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.ListCell;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class MessageListItemCell extends ListCell<Message> {
|
||||
|
||||
private MessageListItemController messageListItemController;
|
||||
private Node view;
|
||||
|
||||
public MessageListItemCell() {
|
||||
setStyle("-fx-padding: 0px");
|
||||
FXMLLoader cellLoader = new FXMLLoader(getClass().getResource("messageListItem.fxml"));
|
||||
try {
|
||||
view = cellLoader.load();
|
||||
messageListItemController = cellLoader.getController();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateItem(Message item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null) {
|
||||
try {
|
||||
FXMLLoader cellLoader = new FXMLLoader(getClass().getResource("messageListItem.fxml"));
|
||||
setGraphic(cellLoader.load());
|
||||
final MessageListItemController userListItemController = cellLoader.getController();
|
||||
userListItemController.setMessage(item);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (item == null || empty) {
|
||||
setGraphic(null);
|
||||
} else {
|
||||
setGraphic(view);
|
||||
messageListItemController.setMessage(item);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,6 +15,8 @@ import java.util.ResourceBundle;
|
|||
|
||||
public class MessageListItemController implements Initializable {
|
||||
|
||||
private Message currentMessage;
|
||||
|
||||
@FXML
|
||||
private VBox container;
|
||||
@FXML
|
||||
|
@ -28,14 +30,19 @@ public class MessageListItemController implements Initializable {
|
|||
}
|
||||
|
||||
public void setMessage(Message message) {
|
||||
button.setText(message.getText());
|
||||
timestamp.setText(DateFormat.getTimeInstance().format(message.getDate()));
|
||||
if (message.getSender().id == CurrentUser.getInstance().getId()) {
|
||||
container.setAlignment(Pos.CENTER_RIGHT);
|
||||
button.getStyleClass().add("message-self");
|
||||
} else {
|
||||
container.setAlignment(Pos.CENTER_LEFT);
|
||||
button.getStyleClass().add("message-other");
|
||||
if (!message.equals(currentMessage)) {
|
||||
currentMessage = message;
|
||||
button.setText(message.getText());
|
||||
timestamp.setText(DateFormat.getTimeInstance().format(message.getDate()));
|
||||
if (message.getSender().id == CurrentUser.getInstance().getId()) {
|
||||
container.setAlignment(Pos.CENTER_RIGHT);
|
||||
button.getStyleClass().remove("message-other");
|
||||
button.getStyleClass().add("message-self");
|
||||
} else {
|
||||
container.setAlignment(Pos.CENTER_LEFT);
|
||||
button.getStyleClass().remove("message-self");
|
||||
button.getStyleClass().add("message-other");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package fr.insa.clavardator.ui.users;
|
|||
import fr.insa.clavardator.ui.UserSelectedEvent;
|
||||
import fr.insa.clavardator.users.PeerUser;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.ListCell;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -10,9 +11,18 @@ import java.io.IOException;
|
|||
public class UserListItemCell extends ListCell<PeerUser> {
|
||||
|
||||
private UserSelectedEvent listener;
|
||||
private UserListItemController userListItemController;
|
||||
private Node view;
|
||||
|
||||
public UserListItemCell() {
|
||||
setStyle("-fx-padding: 0px");
|
||||
FXMLLoader cellLoader = new FXMLLoader(getClass().getResource("userListItem.fxml"));
|
||||
try {
|
||||
view = cellLoader.load();
|
||||
userListItemController = cellLoader.getController();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnUserSelectedListener(UserSelectedEvent listener) {
|
||||
|
@ -22,23 +32,17 @@ public class UserListItemCell extends ListCell<PeerUser> {
|
|||
@Override
|
||||
protected void updateItem(PeerUser item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (!empty && item != null) {
|
||||
final FXMLLoader cellLoader = new FXMLLoader(getClass().getResource("userListItem.fxml"));
|
||||
try {
|
||||
setGraphic(cellLoader.load());
|
||||
UserListItemController userListItemController = cellLoader.getController();
|
||||
userListItemController.setUser(item);
|
||||
userListItemController.setOnPressListener(() -> {
|
||||
if (listener != null) {
|
||||
listener.onSelected(item);
|
||||
}
|
||||
});
|
||||
userListItemController.setSelected(isSelected());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
if (item == null || empty) {
|
||||
setGraphic(null);
|
||||
} else {
|
||||
setGraphic(view);
|
||||
userListItemController.setUser(item);
|
||||
userListItemController.setOnPressListener(() -> {
|
||||
if (listener != null) {
|
||||
listener.onSelected(item);
|
||||
}
|
||||
});
|
||||
userListItemController.setSelected(isSelected());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue