Skip to content

Commit

Permalink
Store messages in the chatChannel Object
Browse files Browse the repository at this point in the history
  • Loading branch information
Sheikah45 committed Nov 18, 2023
1 parent 9c9a89f commit 0bbcce1
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 130 deletions.
101 changes: 59 additions & 42 deletions src/main/java/com/faforever/client/chat/ChannelTabController.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ public class ChannelTabController extends AbstractChatTabController {

private final ObservableValue<ChannelTopic> channelTopic = chatChannel.flatMap(ChatChannel::topicProperty);
private final ObservableValue<ObservableList<ChatChannelUser>> users = chatChannel.map(ChatChannel::getUsers)
.orElse(FXCollections.emptyObservableList());
.orElse(
FXCollections.emptyObservableList());
private final ListChangeListener<ChatChannelUser> channelUserListChangeListener = this::updateChangedUsersStyles;


Expand All @@ -110,51 +111,58 @@ public ChannelTabController(WebViewConfigurer webViewConfigurer, LoginService lo
@Override
public void initialize() {
super.initialize();
JavaFxUtil.bindManagedToVisible(topicPane, chatUserList, changeTopicTextButton, topicTextField, cancelChangesTopicTextButton, topicText, topicCharactersLimitLabel, chatMessageSearchContainer);
JavaFxUtil.bindManagedToVisible(topicPane, chatUserList, changeTopicTextButton, topicTextField,
cancelChangesTopicTextButton, topicText, topicCharactersLimitLabel,
chatMessageSearchContainer);
JavaFxUtil.bind(topicCharactersLimitLabel.visibleProperty(), topicTextField.visibleProperty());
JavaFxUtil.bind(cancelChangesTopicTextButton.visibleProperty(), topicTextField.visibleProperty());
JavaFxUtil.bind(chatUserList.visibleProperty(), userListVisibilityToggleButton.selectedProperty());

BooleanExpression tabPaneShowing = BooleanExpression.booleanExpression(getRoot().tabPaneProperty()
.flatMap(
uiService::createShowingProperty));
ObservableValue<Boolean> showing = getRoot().selectedProperty()
.and(BooleanExpression.booleanExpression(getRoot().tabPaneProperty()
.flatMap(uiService::createShowingProperty)));
.and(tabPaneShowing);

userListVisibilityToggleButton.selectedProperty().bindBidirectional(chatPrefs.playerListShownProperty());
topicTextField.setTextFormatter(new TextFormatter<>(change -> change.getControlNewText()
.length() <= TOPIC_CHARACTERS_LIMIT ? change : null));
.length() <= TOPIC_CHARACTERS_LIMIT ? change : null));

topicCharactersLimitLabel.textProperty()
.bind(topicTextField.textProperty()
.length()
.map(length -> String.format("%d / %d", length.intValue(), TOPIC_CHARACTERS_LIMIT))
.when(showing));
.bind(topicTextField.textProperty()
.length()
.map(length -> String.format("%d / %d", length.intValue(),
TOPIC_CHARACTERS_LIMIT))
.when(showing));

topicPane.visibleProperty()
.bind(topicText.visibleProperty()
.or(changeTopicTextButton.visibleProperty())
.or(topicTextField.visibleProperty())
.when(showing));
.bind(topicText.visibleProperty()
.or(changeTopicTextButton.visibleProperty())
.or(topicTextField.visibleProperty())
.when(showing));

root.idProperty().bind(channelName.when(showing));
root.textProperty().bind(channelName.map(name -> name.replaceFirst("^#", "")).when(showing));
root.textProperty().bind(channelName.map(name -> name.replaceFirst("^#", "")).when(tabPaneShowing));

chatUserListController.chatChannelProperty().bind(chatChannel);

ObservableValue<Boolean> isModerator = chatChannel.map(channel -> channel.getUser(loginService.getUsername())
.orElse(null)).flatMap(ChatChannelUser::moderatorProperty).orElse(false);
.orElse(null))
.flatMap(ChatChannelUser::moderatorProperty)
.orElse(false);
changeTopicTextButton.visibleProperty()
.bind(BooleanExpression.booleanExpression(isModerator)
.and(topicTextField.visibleProperty().not())
.when(showing));
.bind(BooleanExpression.booleanExpression(isModerator)
.and(topicTextField.visibleProperty().not())
.when(showing));

chatMessageSearchTextField.textProperty().addListener((SimpleChangeListener<String>) this::highlightText);

chatPrefs.hideFoeMessagesProperty()
.when(showing)
.addListener((SimpleChangeListener<Boolean>) this::hideFoeMessages);
.when(showing)
.addListener((SimpleChangeListener<Boolean>) this::hideFoeMessages);
chatPrefs.chatColorModeProperty()
.when(showing)
.addListener((SimpleInvalidationListener) () -> users.getValue().forEach(this::updateUserMessageColor));
.when(showing)
.addListener((SimpleInvalidationListener) () -> users.getValue().forEach(this::updateUserMessageColor));
channelTopic.addListener(((observable, oldValue, newValue) -> updateChannelTopic(oldValue, newValue)));
users.addListener((observable, oldValue, newValue) -> {
if (oldValue != null) {
Expand All @@ -173,11 +181,13 @@ public void initialize() {

public AutoCompletionHelper getAutoCompletionHelper() {
return new AutoCompletionHelper(currentWord -> users.getValue()
.stream()
.map(ChatChannelUser::getUsername)
.filter(username -> username.toLowerCase(US).startsWith(currentWord.toLowerCase()))
.sorted()
.collect(Collectors.toList()));
.stream()
.map(ChatChannelUser::getUsername)
.filter(username -> username.toLowerCase(US)
.startsWith(
currentWord.toLowerCase()))
.sorted()
.collect(Collectors.toList()));
}

private void highlightText(String newValue) {
Expand All @@ -190,9 +200,9 @@ private void highlightText(String newValue) {

private void hideFoeMessages(boolean shouldHide) {
users.getValue()
.stream()
.filter(user -> user.getCategories().stream().anyMatch(status -> status == ChatUserCategory.FOE))
.forEach(user -> updateUserMessageVisibility(user, shouldHide));
.stream()
.filter(user -> user.getCategories().stream().anyMatch(status -> status == ChatUserCategory.FOE))
.forEach(user -> updateUserMessageVisibility(user, shouldHide));
}

private void updateChangedUsersStyles(Change<? extends ChatChannelUser> change) {
Expand Down Expand Up @@ -247,7 +257,8 @@ private void updateChannelTopic(ChannelTopic oldTopic, ChannelTopic newTopic) {

if (oldTopic != null) {
String oldTopicContent = oldTopic.content();
onChatMessage(new ChatMessage(Instant.now(), newTopic.author(), i18n.get("chat.topicUpdated", oldTopicContent, newTopicContent)));
onChatMessage(new ChatMessage(Instant.now(), newTopic.author(),
i18n.get("chat.topicUpdated", oldTopicContent, newTopicContent)));
}
}

Expand Down Expand Up @@ -282,12 +293,14 @@ private void updateUserMessageColor(ChatChannelUser user) {

private void updateUserMessageVisibility(ChatChannelUser user, boolean shouldHide) {
String displayPropertyValue = shouldHide ? "none" : "";
fxApplicationThreadExecutor.execute(() -> callJsMethod("updateUserMessageDisplay", user.getUsername(), displayPropertyValue));
fxApplicationThreadExecutor.execute(
() -> callJsMethod("updateUserMessageDisplay", user.getUsername(), displayPropertyValue));
}

private void updateStyleClass(ChatChannelUser user) {
user.getPlayer()
.ifPresentOrElse(player -> removeUserMessageStyleClass(user, CSS_CLASS_CHAT_ONLY), () -> addUserMessageStyleClass(user, CSS_CLASS_CHAT_ONLY));
.ifPresentOrElse(player -> removeUserMessageStyleClass(user, CSS_CLASS_CHAT_ONLY),
() -> addUserMessageStyleClass(user, CSS_CLASS_CHAT_ONLY));
if (user.isModerator()) {
addUserMessageStyleClass(user, MODERATOR_STYLE_CLASS);
} else {
Expand All @@ -296,32 +309,36 @@ private void updateStyleClass(ChatChannelUser user) {
}

private void addUserMessageStyleClass(ChatChannelUser user, String styleClass) {
fxApplicationThreadExecutor.execute(() -> callJsMethod("addUserMessageClass", String.format(USER_STYLE_CLASS, user.getUsername()), styleClass));
fxApplicationThreadExecutor.execute(
() -> callJsMethod("addUserMessageClass", String.format(USER_STYLE_CLASS, user.getUsername()), styleClass));
}

private void removeUserMessageStyleClass(ChatChannelUser user, String styleClass) {
if (StringUtils.isNotBlank(styleClass)) {
fxApplicationThreadExecutor.execute(() -> callJsMethod("removeUserMessageClass", String.format(USER_STYLE_CLASS, user.getUsername()), styleClass));
fxApplicationThreadExecutor.execute(
() -> callJsMethod("removeUserMessageClass", String.format(USER_STYLE_CLASS, user.getUsername()),
styleClass));
}
}

@Override
protected String getMessageCssClass(String login) {
return chatService.getOrCreateChatUser(login, channelName.getValue())
.isModerator() ? MODERATOR_STYLE_CLASS : super.getMessageCssClass(login);
.isModerator() ? MODERATOR_STYLE_CLASS : super.getMessageCssClass(login);
}

@Override
protected void onMention(ChatMessage chatMessage) {
if (notificationPrefs.getNotifyOnAtMentionOnlyEnabled() && !chatMessage.message()
.contains("@" + loginService.getUsername())) {
.contains(
"@" + loginService.getUsername())) {
return;
}

if (playerService.getPlayerByNameIfOnline(chatMessage.username())
.map(PlayerBean::getSocialStatus)
.map(FOE::equals)
.orElse(false)) {
.map(PlayerBean::getSocialStatus)
.map(FOE::equals)
.orElse(false)) {
log.debug("Ignored ping from {}", chatMessage.username());
} else if (!hasFocus()) {
audioService.playChatMentionSound();
Expand All @@ -339,8 +356,8 @@ protected String getInlineStyle(String username) {
}

if (chatPrefs.isHideFoeMessages() && user.getCategories()
.stream()
.anyMatch(category -> category == ChatUserCategory.FOE)) {
.stream()
.anyMatch(category -> category == ChatUserCategory.FOE)) {
return "display: none;";
} else {
return user.getColor().map(color -> String.format("color: %s;", JavaFxUtil.toRgbCode(color))).orElse("");
Expand Down
38 changes: 21 additions & 17 deletions src/main/java/com/faforever/client/chat/ChatChannel.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Set;
Expand All @@ -25,11 +24,24 @@ public class ChatChannel {
@Getter
private final String name;

private final ObservableMap<String, ChatChannelUser> usernameToChatUser = FXCollections.synchronizedObservableMap(FXCollections.observableHashMap());
private final ObservableList<ChatChannelUser> users = JavaFxUtil.attachListToMap(FXCollections.synchronizedObservableList(FXCollections.observableArrayList(item -> new Observable[]{item.categoriesProperty(), item.colorProperty(), item.moderatorProperty()})), usernameToChatUser);
private final ObservableMap<String, ChatChannelUser> usernameToChatUser = FXCollections.synchronizedObservableMap(
FXCollections.observableHashMap());
private final ObservableList<ChatChannelUser> users = JavaFxUtil.attachListToMap(
FXCollections.synchronizedObservableList(FXCollections.observableArrayList(
item -> new Observable[]{item.categoriesProperty(), item.colorProperty(), item.moderatorProperty()})),
usernameToChatUser);
private final ObjectProperty<ChannelTopic> topic = new SimpleObjectProperty<>(new ChannelTopic("", ""));
private final Set<Consumer<ChatMessage>> messageListeners = new HashSet<>();
private final List<ChatMessage> unprocessedMessages = new ArrayList<>();
private final List<ChatMessage> messages = new ArrayList<>();

private int maxNumMessages = Integer.MAX_VALUE;

public void setMaxNumMessages(int maxNumMessages) {
this.maxNumMessages = maxNumMessages;
if (messages.size() > maxNumMessages) {
messages.subList(0, messages.size() - maxNumMessages).clear();
}
}

public ChannelTopic getTopic() {
return topic.get();
Expand Down Expand Up @@ -76,24 +88,16 @@ public Optional<ChatChannelUser> getUser(String username) {
}

public void addMessage(ChatMessage message) {
if (messageListeners.isEmpty()) {
unprocessedMessages.add(message);
}
messages.add(message);
messageListeners.forEach(chatMessageConsumer -> chatMessageConsumer.accept(message));
if (messages.size() > maxNumMessages) {
messages.remove(0);
}
}

public void addMessageListener(Consumer<ChatMessage> messageListener) {
messageListeners.add(messageListener);
drainUnprocessed();
}

private void drainUnprocessed() {
Iterator<ChatMessage> unprocessedIterator = unprocessedMessages.iterator();
while (unprocessedIterator.hasNext()) {
ChatMessage message = unprocessedIterator.next();
messageListeners.forEach(chatMessageConsumer -> chatMessageConsumer.accept(message));
unprocessedIterator.remove();
}
messages.forEach(messageListener);
}

public void removeMessageListener(Consumer<ChatMessage> messageListener) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public void initialize() {
super.initialize();

chatService.addChannelsListener(channelChangeListener);
chatService.getChannels().forEach(this::onChannelJoined);

JavaFxUtil.addAndTriggerListener(chatService.connectionStateProperty(), (SimpleChangeListener<ConnectionState>) this::onConnectionStateChange);

Expand Down
Loading

0 comments on commit 0bbcce1

Please sign in to comment.