From 93c762fba9ac2179239268fb83b104232c3ed7df Mon Sep 17 00:00:00 2001 From: axpoems <145597137+axpoems@users.noreply.github.com> Date: Sun, 14 Jul 2024 08:42:56 +0200 Subject: [PATCH 1/5] Remove always showing failed delivery state --- .../list/ChatMessageListItem.java | 4 ---- .../list/message_box/BubbleMessageBox.java | 15 ++------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/ChatMessageListItem.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/ChatMessageListItem.java index 3bd8b89cfe..eaafbabdc3 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/ChatMessageListItem.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/ChatMessageListItem.java @@ -110,7 +110,6 @@ public final class ChatMessageListItem mapPins = new HashSet<>(); private final Set statusPins = new HashSet<>(); private final BooleanProperty shouldShowTryAgain = new SimpleBooleanProperty(); - private final BooleanProperty hasFailedDeliveryStatus = new SimpleBooleanProperty(); private final SimpleObjectProperty messageDeliveryStatusNode = new SimpleObjectProperty<>(); private Optional resendMessageService; private ImageView successfulDeliveryIcon, pendingDeliveryIcon, addedToMailboxIcon, failedDeliveryIcon; @@ -344,7 +343,6 @@ private void updateMessageStatus(String messageId, Observable { ChatMessageListItem.this.messageId = messageId; boolean shouldShowTryAgain = false; - boolean hasFailedDeliveryStatus = false; if (status != null) { Label statusLabel = new Label(); statusLabel.setTooltip(new BisqTooltip(Res.get("chat.message.deliveryState." + status.name()))); @@ -366,13 +364,11 @@ private void updateMessageStatus(String messageId, Observable service.canManuallyResendMessage(messageId)).orElse(false); - hasFailedDeliveryStatus = true; break; } messageDeliveryStatusNode.set(statusLabel); } this.shouldShowTryAgain.set(shouldShowTryAgain); - this.hasFailedDeliveryStatus.set(hasFailedDeliveryStatus); }); })); }); diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/BubbleMessageBox.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/BubbleMessageBox.java index fab8ef23d6..145a33badc 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/BubbleMessageBox.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/BubbleMessageBox.java @@ -62,7 +62,7 @@ public abstract class BubbleMessageBox extends MessageBox { private static final List REACTIONS = Arrays.asList(Reaction.THUMBS_UP, Reaction.THUMBS_DOWN, Reaction.HAPPY, Reaction.LAUGH, Reaction.HEART, Reaction.PARTY); - private final Subscription showHighlightedPin, hasFailedDeliveryStatusPin; + private final Subscription showHighlightedPin; protected final ChatMessageListItem> item; protected final ListView>> list; protected final ChatMessagesListController controller; @@ -118,14 +118,6 @@ public BubbleMessageBox(ChatMessageListItem { - if (deliveryFailed) { - dateTimeHBox.setVisible(true); - } else { - showDateTimeAndActionsMenu(false); - } - }); - reactionMenuItems.forEach(this::updateIsReactionSelected); } @@ -191,7 +183,6 @@ public void cleanup() { showHighlightedPin.unsubscribe(); reactMenuPin.unsubscribe(); - hasFailedDeliveryStatusPin.unsubscribe(); activeReactionsDisplayHBox.dispose(); } @@ -205,9 +196,7 @@ private void showDateTimeAndActionsMenu(boolean shouldShow) { actionsHBox.setVisible(true); } else { if ((moreActionsMenu == null || !moreActionsMenu.getIsMenuShowing().get()) && !reactMenu.getIsMenuShowing().get()) { - if (!item.getHasFailedDeliveryStatus().get()) { - dateTimeHBox.setVisible(false); - } + dateTimeHBox.setVisible(false); actionsHBox.setVisible(false); } } From 4d60f876ef7e6798b17578108636804fb787d981 Mon Sep 17 00:00:00 2001 From: axpoems <145597137+axpoems@users.noreply.github.com> Date: Sun, 14 Jul 2024 09:00:28 +0200 Subject: [PATCH 2/5] Always show message delivery status --- .../list/message_box/BubbleMessageBox.java | 10 ++++------ .../list/message_box/MyOfferMessageBox.java | 2 +- .../list/message_box/MyTextMessageBox.java | 3 +-- .../list/message_box/PeerTextMessageBox.java | 4 ++-- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/BubbleMessageBox.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/BubbleMessageBox.java index 145a33badc..c83f6e08a5 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/BubbleMessageBox.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/BubbleMessageBox.java @@ -75,7 +75,7 @@ public abstract class BubbleMessageBox extends MessageBox { private Subscription reactMenuPin; protected List reactionMenuItems = new ArrayList<>(); protected Label supportedLanguages, userName, dateTime, message; - protected HBox dateTimeHBox, userNameAndDateHBox, messageBgHBox, messageHBox; + protected HBox userNameAndDateHBox, messageBgHBox, messageHBox; protected VBox userProfileIconVbox; protected BisqMenuItem copyAction; protected DropdownMenu moreActionsMenu; @@ -127,9 +127,7 @@ protected void setUpUserNameAndDateTime() { dateTime = new Label(); dateTime.getStyleClass().addAll("text-fill-grey-dimmed", "font-size-09", "font-light"); dateTime.setText(item.getDate()); - dateTimeHBox = new HBox(10, dateTime); - dateTimeHBox.setVisible(false); - dateTimeHBox.setAlignment(Pos.CENTER); + dateTime.setVisible(false); } private void setUpUserProfileIcon() { @@ -192,11 +190,11 @@ private void showDateTimeAndActionsMenu(boolean shouldShow) { if ((moreActionsMenu != null && moreActionsMenu.getIsMenuShowing().get()) || reactMenu.getIsMenuShowing().get()) { return; } - dateTimeHBox.setVisible(true); + dateTime.setVisible(true); actionsHBox.setVisible(true); } else { if ((moreActionsMenu == null || !moreActionsMenu.getIsMenuShowing().get()) && !reactMenu.getIsMenuShowing().get()) { - dateTimeHBox.setVisible(false); + dateTime.setVisible(false); actionsHBox.setVisible(false); } } diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/MyOfferMessageBox.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/MyOfferMessageBox.java index f46c1ead42..97136179cf 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/MyOfferMessageBox.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/MyOfferMessageBox.java @@ -73,7 +73,7 @@ public MyOfferMessageBox(ChatMessageListItem { if (!isShowing && !isHover()) { - dateTimeHBox.setVisible(false); + dateTime.setVisible(false); actionsHBox.setVisible(false); } }); From bb6a1cb9117cff2f90a1d3504b5553cc94c571d5 Mon Sep 17 00:00:00 2001 From: axpoems <145597137+axpoems@users.noreply.github.com> Date: Sun, 14 Jul 2024 10:22:55 +0200 Subject: [PATCH 3/5] Fix selection marker --- .../list/ChatMessageListItem.java | 20 ++++---- .../message_container/list/ReactionItem.java | 47 ++++++++++++------- .../ActiveReactionsDisplayBox.java | 29 ++++++++---- 3 files changed, 61 insertions(+), 35 deletions(-) diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/ChatMessageListItem.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/ChatMessageListItem.java index eaafbabdc3..b8f9b11c3b 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/ChatMessageListItem.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/ChatMessageListItem.java @@ -116,8 +116,9 @@ public final class ChatMessageListItem userReactionsPin = Optional.empty(); + private final Pin userIdentityPin; private final HashMap userReactions = new HashMap<>(); + private Optional userReactionsPin = Optional.empty(); public ChatMessageListItem(M chatMessage, C chatChannel, @@ -172,7 +173,8 @@ public ChatMessageListItem(M chatMessage, lastSeen = senderUserProfile.map(userProfileService::getLastSeen).orElse(-1L); lastSeenAsString = TimeFormatter.formatAge(lastSeen); - // TODO: Release all the listeners when destroying this object + userIdentityPin = userIdentityService.getSelectedUserIdentityObservable().addObserver(userIdentity -> UIThread.run(this::onUserIdentity)); + createAndAddSubscriptionToUserReactions(userProfileService); initializeDeliveryStatusIcons(); addSubscriptionToMessageDeliveryStatus(networkService); @@ -196,6 +198,7 @@ public void dispose() { mapPins.forEach(Pin::unbind); statusPins.forEach(Pin::unbind); userReactionsPin.ifPresent(Pin::unbind); + userIdentityPin.unbind(); } public boolean hasTradeChatOffer() { @@ -380,7 +383,8 @@ private void createAndAddSubscriptionToUserReactions(UserProfileService userProf } // Create all the ReactionItems - Arrays.stream(Reaction.values()).forEach(reaction -> userReactions.put(reaction, new ReactionItem(reaction))); + UserProfile selectedUserProfile = userIdentityService.getSelectedUserIdentity().getUserProfile(); + Arrays.stream(Reaction.values()).forEach(reaction -> userReactions.put(reaction, new ReactionItem(reaction, selectedUserProfile))); // Subscribe to changes userReactionsPin = Optional.ofNullable(chatMessage.getChatMessageReactions().addObserver(new CollectionObserver<>() { @@ -391,7 +395,7 @@ public void add(ChatMessageReaction element) { Optional userProfile = userProfileService.findUserProfile(element.getUserProfileId()); userProfile.ifPresent(profile -> { if (!userProfileService.isChatUserIgnored(profile)) { - userReactions.get(reaction).addUser(element, profile, isMyUser(profile)); + userReactions.get(reaction).addUser(element, profile); } }); } @@ -403,7 +407,7 @@ public void remove(Object element) { Reaction reaction = getReactionFromOrdinal(chatMessageReaction.getReactionId()); if (userReactions.containsKey(reaction)) { Optional userProfile = userProfileService.findUserProfile(chatMessageReaction.getUserProfileId()); - userProfile.ifPresent(profile -> userReactions.get(reaction).removeUser(profile, isMyUser(profile))); + userProfile.ifPresent(profile -> userReactions.get(reaction).removeUser(profile)); } } @@ -419,8 +423,8 @@ private static Reaction getReactionFromOrdinal(int ordinal) { return Reaction.values()[ordinal]; } - private boolean isMyUser(UserProfile profile) { - UserProfile myProfile = userIdentityService.getSelectedUserIdentity().getUserProfile(); - return myProfile.equals(profile); + private void onUserIdentity() { + UserProfile selectedUserProfile = userIdentityService.getSelectedUserIdentity().getUserProfile(); + userReactions.forEach((key, value) -> value.setSelectedUserProfile(selectedUserProfile)); } } diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/ReactionItem.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/ReactionItem.java index f76031960f..90292792bd 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/ReactionItem.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/ReactionItem.java @@ -38,14 +38,32 @@ public class ReactionItem { private long firstAdded; private final SimpleIntegerProperty count = new SimpleIntegerProperty(0); private final SimpleBooleanProperty selected = new SimpleBooleanProperty(false); - Set users = new HashSet<>(); + private final Set users = new HashSet<>(); + private UserProfile selectedUserProfile; - ReactionItem(Reaction reaction) { + ReactionItem(Reaction reaction, UserProfile selectedUserProfile) { this.reaction = reaction; + this.selectedUserProfile = selectedUserProfile; this.iconId = reaction.toString().replace("_", "").toLowerCase(); } - void addUser(ChatMessageReaction chatMessageReaction, UserProfile userProfile, boolean isMyUser) { + public boolean hasActiveReactions() { + return !users.isEmpty(); + } + + public String getCountAsString() { + long count = users.size(); + if (count < 2) { + return ""; + } + return count < 100 ? String.valueOf(count) : "+99"; + } + + public static Comparator firstAddedComparator() { + return Comparator.comparingLong(ReactionItem::getFirstAdded); + } + + void addUser(ChatMessageReaction chatMessageReaction, UserProfile userProfile) { if (hasReactionBeenRemoved(chatMessageReaction)) { return; } @@ -54,27 +72,20 @@ void addUser(ChatMessageReaction chatMessageReaction, UserProfile userProfile, b firstAdded = chatMessageReaction.getDate(); } - selected.set(isMyUser); users.add(userProfile); count.set(users.size()); + updateSelected(); } - void removeUser(UserProfile userProfile, boolean isMyUser) { - selected.set(!isMyUser); + void removeUser(UserProfile userProfile) { users.remove(userProfile); count.set(users.size()); + updateSelected(); } - public boolean hasActiveReactions() { - return !users.isEmpty(); - } - - public String getCountAsString() { - long count = users.size(); - if (count == 1) { - return ""; - } - return count < 100 ? String.valueOf(count) : "+99"; + void setSelectedUserProfile(UserProfile selectedUserProfile) { + this.selectedUserProfile = selectedUserProfile; + updateSelected(); } private boolean hasReactionBeenRemoved(ChatMessageReaction chatMessageReaction) { @@ -82,7 +93,7 @@ private boolean hasReactionBeenRemoved(ChatMessageReaction chatMessageReaction) && ((PrivateChatMessageReaction) chatMessageReaction).isRemoved()); } - public static Comparator firstAddedComparator() { - return Comparator.comparingLong(ReactionItem::getFirstAdded); + private void updateSelected() { + selected.set(getUsers().contains(selectedUserProfile)); } } diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/reactions_box/ActiveReactionsDisplayBox.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/reactions_box/ActiveReactionsDisplayBox.java index 34a0328071..3575030e6f 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/reactions_box/ActiveReactionsDisplayBox.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/reactions_box/ActiveReactionsDisplayBox.java @@ -38,7 +38,8 @@ public class ActiveReactionsDisplayBox extends HBox { private final ObservableList reactionItems = FXCollections.observableArrayList(); private final FilteredList filteredReactionItems = new FilteredList<>(reactionItems, ReactionItem::hasActiveReactions); private final SortedList sortedReactionItems = new SortedList<>(filteredReactionItems); - private final Map> itemChangeListeners = new HashMap<>(); + private final Map> itemCountChangeListener = new HashMap<>(); + private final Map> itemSelectedChangeListener = new HashMap<>(); private final ListChangeListener listChangeListener; private final ToggleReaction toggleReaction; @@ -63,19 +64,31 @@ public void dispose() { } private void addItemListeners(ReactionItem item) { - ChangeListener listener = (obs, oldValue, newValue) -> { + ChangeListener numberChangeListener = (obs, oldValue, newValue) -> { int idx = reactionItems.indexOf(item); if (idx >= 0) { reactionItems.set(idx, item); } }; - item.getCount().addListener(listener); - itemChangeListeners.put(item, listener); + item.getCount().addListener(numberChangeListener); + itemCountChangeListener.put(item, numberChangeListener); + + ChangeListener booleanChangeListener = (obs, oldValue, newValue) -> { + int idx = reactionItems.indexOf(item); + if (idx >= 0) { + reactionItems.set(idx, item); + } + }; + item.getSelected().addListener(booleanChangeListener); + itemSelectedChangeListener.put(item, booleanChangeListener); } private void removeItemListeners() { - itemChangeListeners.forEach((item, listener) -> { - item.getCount().removeListener(listener); + itemCountChangeListener.forEach((item, changeListener) -> { + item.getCount().removeListener(changeListener); + }); + itemSelectedChangeListener.forEach((item, changeListener) -> { + item.getSelected().removeListener(changeListener); }); } @@ -93,7 +106,7 @@ private static final class ActiveReactionMenuItem extends BisqMenuItem { private ReactionItem reactionItem; private ToggleReaction toggleReaction; - public ActiveReactionMenuItem(ReactionItem reactionItem, ToggleReaction toggleReaction) { + private ActiveReactionMenuItem(ReactionItem reactionItem, ToggleReaction toggleReaction) { this(reactionItem.getIconId()); this.reactionItem = reactionItem; @@ -112,8 +125,6 @@ private void addStyleClasses() { getStyleClass().add("active-reaction-menu-item"); if (reactionItem.getSelected().get()) { getStyleClass().add("active-reaction-selected"); - } else { - getStyleClass().remove("active-reaction-selected"); } } } From 8512a6318816ab235adc6f5b390d680d5276318d Mon Sep 17 00:00:00 2001 From: axpoems <145597137+axpoems@users.noreply.github.com> Date: Sun, 14 Jul 2024 12:33:58 +0200 Subject: [PATCH 4/5] Add new react menu box --- .../components/controls/DrawerMenu.java | 2 +- .../list/message_box/BubbleMessageBox.java | 112 ++++++------------ .../list/message_box/MyTextMessageBox.java | 9 +- .../list/message_box/PeerTextMessageBox.java | 3 +- .../list/reactions_box/ReactMenuBox.java | 102 ++++++++++++++++ .../desktop/src/main/resources/css/chat.css | 2 +- 6 files changed, 141 insertions(+), 89 deletions(-) create mode 100644 apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/reactions_box/ReactMenuBox.java diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/components/controls/DrawerMenu.java b/apps/desktop/desktop/src/main/java/bisq/desktop/components/controls/DrawerMenu.java index fda547d12c..6221a3180b 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/components/controls/DrawerMenu.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/components/controls/DrawerMenu.java @@ -36,7 +36,7 @@ public class DrawerMenu extends HBox { private static final String SLIDE_LEFT_CSS_STYLE = "slide-left"; private final Button menuButton = new Button(); - private final HBox itemsHBox = new HBox(); + protected final HBox itemsHBox = new HBox(); private final ImageView defaultIcon, hoverIcon, activeIcon; @Getter private final BooleanProperty isMenuShowing = new SimpleBooleanProperty(false); diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/BubbleMessageBox.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/BubbleMessageBox.java index c83f6e08a5..992ae469ab 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/BubbleMessageBox.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/BubbleMessageBox.java @@ -26,15 +26,14 @@ import bisq.desktop.common.utils.ImageUtil; import bisq.desktop.components.controls.BisqMenuItem; import bisq.desktop.components.controls.BisqTooltip; -import bisq.desktop.components.controls.DrawerMenu; import bisq.desktop.components.controls.DropdownMenu; import bisq.desktop.main.content.chat.message_container.list.ChatMessageListItem; import bisq.desktop.main.content.chat.message_container.list.ChatMessagesListController; import bisq.desktop.main.content.chat.message_container.list.reactions_box.ActiveReactionsDisplayBox; +import bisq.desktop.main.content.chat.message_container.list.reactions_box.ReactMenuBox; import bisq.desktop.main.content.chat.message_container.list.reactions_box.ToggleReaction; import bisq.desktop.main.content.components.UserProfileIcon; import bisq.i18n.Res; -import javafx.css.PseudoClass; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Cursor; @@ -43,12 +42,10 @@ import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; -import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.Subscription; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -59,7 +56,7 @@ public abstract class BubbleMessageBox extends MessageBox { protected static final double CHAT_MESSAGE_BOX_MAX_WIDTH = 630; // TODO: it should be 510 because of reactions on min size protected static final double OFFER_MESSAGE_USER_ICON_SIZE = 70; protected static final Insets ACTION_ITEMS_MARGIN = new Insets(2, 0, -2, 0); - private static final List REACTIONS = Arrays.asList(Reaction.THUMBS_UP, Reaction.THUMBS_DOWN, Reaction.HAPPY, + private static final List REACTIONS_ORDER = Arrays.asList(Reaction.THUMBS_UP, Reaction.THUMBS_DOWN, Reaction.HAPPY, Reaction.LAUGH, Reaction.HEART, Reaction.PARTY); private final Subscription showHighlightedPin; @@ -68,12 +65,11 @@ public abstract class BubbleMessageBox extends MessageBox { protected final ChatMessagesListController controller; protected final UserProfileIcon userProfileIcon = new UserProfileIcon(60); protected final HBox actionsHBox = new HBox(5); - protected final ActiveReactionsDisplayBox activeReactionsDisplayHBox; protected final VBox quotedMessageVBox, contentVBox; protected final BisqMenuItem deleteAction = new BisqMenuItem("delete-t-grey", "delete-t-red"); - protected DrawerMenu reactMenu; private Subscription reactMenuPin; - protected List reactionMenuItems = new ArrayList<>(); + protected ActiveReactionsDisplayBox activeReactionsDisplayHBox; + protected ReactMenuBox reactMenuBox; protected Label supportedLanguages, userName, dateTime, message; protected HBox userNameAndDateHBox, messageBgHBox, messageHBox; protected VBox userProfileIconVbox; @@ -89,11 +85,11 @@ public BubbleMessageBox(ChatMessageListItem { + private void setUpReactions() { + // Active Reactions Display + ToggleReaction toggleReactionDisplayMenuFunction = reactionItem -> + controller.onReactMessage(item.getChatMessage(), reactionItem.getReaction(), item.getChatChannel()); + activeReactionsDisplayHBox = new ActiveReactionsDisplayBox(item.getUserReactions().values(), toggleReactionDisplayMenuFunction); + + // React Menu + ToggleReaction toggleReactionReactMenuFunction = reactionItem -> { + controller.onReactMessage(item.getChatMessage(), reactionItem.getReaction(), item.getChatChannel()); + reactMenuBox.hideMenu(); + }; + reactMenuBox = new ReactMenuBox(item.getUserReactions(), REACTIONS_ORDER, toggleReactionReactMenuFunction, + "react-grey", "react-white", "react-green"); + reactMenuBox.setTooltip(Res.get("action.react")); + reactMenuBox.setVisible(item.getChatMessage().canShowReactions()); + reactMenuBox.setManaged(item.getChatMessage().canShowReactions()); + + reactMenuPin = EasyBind.subscribe(reactMenuBox.getIsMenuShowing(), isShowing -> { if (!isShowing && !isHover()) { showDateTimeAndActionsMenu(false); } }); + } - reactMenu.setVisible(item.getChatMessage().canShowReactions()); - reactMenu.setManaged(item.getChatMessage().canShowReactions()); - + protected void setUpActions() { + copyAction = new BisqMenuItem("copy-grey", "copy-white"); + copyAction.useIconOnly(); + copyAction.setTooltip(Res.get("action.copyToClipboard")); + actionsHBox.setVisible(false); HBox.setMargin(copyAction, ACTION_ITEMS_MARGIN); - HBox.setMargin(reactMenu, ACTION_ITEMS_MARGIN); + HBox.setMargin(reactMenuBox, ACTION_ITEMS_MARGIN); } protected void addActionsHandlers() { @@ -177,36 +184,28 @@ public void cleanup() { setOnMouseEntered(null); setOnMouseExited(null); - reactionMenuItems.forEach(menuItem -> menuItem.setOnAction(null)); - showHighlightedPin.unsubscribe(); reactMenuPin.unsubscribe(); activeReactionsDisplayHBox.dispose(); + reactMenuBox.dispose(); } private void showDateTimeAndActionsMenu(boolean shouldShow) { if (shouldShow) { - if ((moreActionsMenu != null && moreActionsMenu.getIsMenuShowing().get()) || reactMenu.getIsMenuShowing().get()) { + if ((moreActionsMenu != null && moreActionsMenu.getIsMenuShowing().get()) || reactMenuBox.getIsMenuShowing().get()) { return; } dateTime.setVisible(true); actionsHBox.setVisible(true); } else { - if ((moreActionsMenu == null || !moreActionsMenu.getIsMenuShowing().get()) && !reactMenu.getIsMenuShowing().get()) { + if ((moreActionsMenu == null || !moreActionsMenu.getIsMenuShowing().get()) && !reactMenuBox.getIsMenuShowing().get()) { dateTime.setVisible(false); actionsHBox.setVisible(false); } } } - private ActiveReactionsDisplayBox createAndGetActiveReactionsDisplayBox() { - ToggleReaction toggleReactionFunction = reactionItem -> { - controller.onReactMessage(item.getChatMessage(), reactionItem.getReaction(), item.getChatChannel()); - }; - return new ActiveReactionsDisplayBox(item.getUserReactions().values(), toggleReactionFunction); - } - private Label createAndGetSupportedLanguagesLabel() { Label label = new Label(); if (item.isBisqEasyPublicChatMessageWithOffer()) { @@ -285,49 +284,4 @@ protected static void onCopyMessage(ChatMessage chatMessage) { protected static void onCopyMessage(String chatMessageText) { ClipboardUtil.copyToClipboard(chatMessageText); } - - private DrawerMenu createAndGetReactMenu() { - DrawerMenu drawerMenu = new DrawerMenu("react-grey", "react-white", "react-green"); - drawerMenu.setTooltip(Res.get("action.react")); - drawerMenu.getStyleClass().add("react-menu"); - return drawerMenu; - } - - private void setUpReactMenu() { - REACTIONS.forEach(reaction -> { - String iconId = reaction.toString().replace("_", "").toLowerCase(); - ReactionMenuItem reactionMenuItem = new ReactionMenuItem(iconId, reaction); - reactionMenuItem.setOnAction(e -> toggleReaction(reactionMenuItem)); - reactionMenuItems.add(reactionMenuItem); - }); - } - - private void toggleReaction(ReactionMenuItem reactionMenuItem) { - controller.onReactMessage(item.getChatMessage(), reactionMenuItem.getReaction(), item.getChatChannel()); - reactMenu.hideMenu(); - updateIsReactionSelected(reactionMenuItem); - } - - private void updateIsReactionSelected(ReactionMenuItem reactionMenuItem) { - reactionMenuItem.setIsReactionSelected(item.hasAddedReaction(reactionMenuItem.getReaction())); - } - - @Getter - public static final class ReactionMenuItem extends BisqMenuItem { - private static final PseudoClass SELECTED_PSEUDO_CLASS = PseudoClass.getPseudoClass("selected"); - - private final Reaction reaction; - - public ReactionMenuItem(String iconId, Reaction reaction) { - super(iconId, iconId); - - this.reaction = reaction; - useIconOnly(24); - getStyleClass().add("reaction-menu-item"); - } - - public void setIsReactionSelected(boolean isSelected) { - pseudoClassStateChanged(SELECTED_PSEUDO_CLASS, isSelected); - } - } } diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/MyTextMessageBox.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/MyTextMessageBox.java index 4e45958221..1e8f637092 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/MyTextMessageBox.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/message_box/MyTextMessageBox.java @@ -37,8 +37,6 @@ import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.Subscription; -import java.util.Collections; - public final class MyTextMessageBox extends BubbleMessageBox { private final static String EDITED_POST_FIX = " " + Res.get("chat.message.wasEdited"); @@ -65,7 +63,7 @@ public MyTextMessageBox(ChatMessageListItem. + */ + +package bisq.desktop.main.content.chat.message_container.list.reactions_box; + +import bisq.chat.reactions.Reaction; +import bisq.desktop.components.controls.BisqMenuItem; +import bisq.desktop.components.controls.DrawerMenu; +import bisq.desktop.main.content.chat.message_container.list.ReactionItem; +import javafx.beans.value.ChangeListener; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.css.PseudoClass; +import javafx.scene.Node; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ReactMenuBox extends DrawerMenu { + private final Map> itemSelectedChangeListener = new HashMap<>(); + + public ReactMenuBox(HashMap reactionItems, List orderedReactions, ToggleReaction toggleReaction, + String defaultIconId, String hoverIconId, String activeIconId) { + super(defaultIconId, hoverIconId, activeIconId); + + List reactionMenuItems = new ArrayList<>(); + orderedReactions.forEach(reaction -> { + if (reactionItems.containsKey(reaction)) { + ReactionItem reactionItem = reactionItems.get(reaction); + ReactionMenuItem reactionMenuItem = new ReactionMenuItem(reactionItem, toggleReaction); + reactionMenuItems.add(reactionMenuItem); + addItemListener(reactionItem, reactionMenuItem); + } + }); + addItems(reactionMenuItems); + + getStyleClass().add("react-menu-box"); + } + + public void dispose() { + removeItemListeners(); + } + + public void reverseReactionsDisplayOrder() { + ObservableList items = itemsHBox.getChildren(); + FXCollections.reverse(items); + } + + private void addItemListener(ReactionItem reactionItem, ReactionMenuItem reactionMenuItem) { + ChangeListener booleanChangeListener = (obs, oldValue, newValue) -> reactionMenuItem.setIsReactionSelected(newValue);; + reactionItem.getSelected().addListener(booleanChangeListener); + itemSelectedChangeListener.put(reactionItem, booleanChangeListener); + } + + private void removeItemListeners() { + itemSelectedChangeListener.forEach((item, changeListener) -> item.getSelected().removeListener(changeListener)); + } + + @Getter + private static final class ReactionMenuItem extends BisqMenuItem { + private static final PseudoClass SELECTED_PSEUDO_CLASS = PseudoClass.getPseudoClass("selected"); + + private ReactionItem reactionItem; + private ToggleReaction toggleReaction; + + private ReactionMenuItem(ReactionItem reactionItem, ToggleReaction toggleReaction) { + this(reactionItem.getIconId()); + + this.reactionItem = reactionItem; + this.toggleReaction = toggleReaction; + useIconOnly(24); + getStyleClass().add("reaction-menu-item"); + setOnAction(e -> toggleReaction.execute(reactionItem)); + setIsReactionSelected(reactionItem.getSelected().get()); + } + + private ReactionMenuItem(String iconId) { + super(iconId, iconId); + } + + private void setIsReactionSelected(boolean isSelected) { + pseudoClassStateChanged(SELECTED_PSEUDO_CLASS, isSelected); + } + } +} diff --git a/apps/desktop/desktop/src/main/resources/css/chat.css b/apps/desktop/desktop/src/main/resources/css/chat.css index 303391c857..e1564637ac 100644 --- a/apps/desktop/desktop/src/main/resources/css/chat.css +++ b/apps/desktop/desktop/src/main/resources/css/chat.css @@ -155,7 +155,7 @@ -fx-font-family: "IBM Plex Sans Light"; } -.chat-message-content-box .react-menu .drawer-menu-items .bisq-menu-item:hover { +.chat-message-content-box .react-menu-box .drawer-menu-items .bisq-menu-item:hover { -fx-background-color: -bisq-dark-grey-50 !important; } From 14c49cb9e37d39952b2daae291710b43786381bc Mon Sep 17 00:00:00 2001 From: axpoems <145597137+axpoems@users.noreply.github.com> Date: Sun, 14 Jul 2024 12:56:16 +0200 Subject: [PATCH 5/5] Refactor: remove additional space --- .../list/reactions_box/ActiveReactionsDisplayBox.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/reactions_box/ActiveReactionsDisplayBox.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/reactions_box/ActiveReactionsDisplayBox.java index 3575030e6f..b0c7a3f4ed 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/reactions_box/ActiveReactionsDisplayBox.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/reactions_box/ActiveReactionsDisplayBox.java @@ -106,7 +106,7 @@ private static final class ActiveReactionMenuItem extends BisqMenuItem { private ReactionItem reactionItem; private ToggleReaction toggleReaction; - private ActiveReactionMenuItem(ReactionItem reactionItem, ToggleReaction toggleReaction) { + private ActiveReactionMenuItem(ReactionItem reactionItem, ToggleReaction toggleReaction) { this(reactionItem.getIconId()); this.reactionItem = reactionItem;