Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use new tab based design for common chats #1502

Merged
merged 21 commits into from
Dec 17, 2023

Conversation

axpoems
Copy link
Contributor

@axpoems axpoems commented Dec 10, 2023

Fix #1279

Public chats:
image

Private chats:
image

Worst case scenario - With domain events, which has the most channels, all of them with notifications, and the smallest possible screen:
image

I will make follow-up PRs with some minor UI improvements.

@HenrikJannsen
Copy link
Contributor

HenrikJannsen commented Dec 11, 2023

I think for the private chats we could use the same design as in trade private chats (list above the chat for selecting the peer).
Maybe we should graphically differentiate the Private chats from the others?
Also maybe we should keep the icons to the public chats (not sure though...).
We can consider also to remove not essentially needed public rooms to make it less crowded.

@HenrikJannsen
Copy link
Contributor

HenrikJannsen commented Dec 11, 2023

I think in events we can remove: No-KYC services, and Node projects as those are more static content anyway and events should have some live-feeling with updates.
Podcasts could be removed IMO as well.
Then we don't need the wrapped layout.

Also Discussions can be removed at about 4 public channels (markets and/or economy would be removal candidates IMO).

@axpoems
Copy link
Contributor Author

axpoems commented Dec 11, 2023

@HenrikJannsen - thanks for the input.

I think for the private chats we could use the same design as in trade private chats (list above the chat for selecting the peer).

I made this mock-up as a proposal design to unify private chats everywhere.

private_chats

To optimize space usage and considering the nature of chat interfaces, I propose using side-by-side columns (users list and chat box), which I believe is more efficient than a stacked arrangement like that of 'Bisq Easy Private Chats'. With a stacked layout, as the number of chats increases, the chat box could become very small. Or a fixed-size layout would require scrolling, which may not be the best user-experience approach IMO. A left side vertical column for the users seem to offer the best trade-off here. Also, upon looking of various chat applications, this is always the layout design of choice.

What do you think?

Maybe we should graphically differentiate the Private chats from the others?

I have to think about this. Not sure if it's necessary. I will explore some options.

Also maybe we should keep the icons to the public chats (not sure though...).

I was planning on adding them, but space was an issue. I will revisit this now that we are removing tabs.

Then we don't need the wrapped layout.

Agree. I will remove that.

@HenrikJannsen
Copy link
Contributor

Agree to the left side nav arguments regarding private chat. A reason at the trade chat was as its very similar to the open trade layout. Here I think a left nav is no option as we need more info of the trade to be shown and the trade process UI requires more horizontal space. But I agree that the normal private chats should be the same everywhere and I dont see strong arguments to stick with the way how its done in bisq easy pm.

@axpoems
Copy link
Contributor Author

axpoems commented Dec 14, 2023

  • Public chats

image

  • Private chats (now with the same design everywhere)

When there are no conversations:
image

With conversations:
image

A private chat inside a domain:
image

The same, but showing info:
image

@HenrikJannsen
Copy link
Contributor

Looks great!
Here some comments, but feel free to address those in a new PR, we don't need to get all perfect in one shot.

The space above the tabs is a bit high. I think its better to have it the same as in offerbook.
We could move the search/info/help icons down below the tab line. The search could be removed IMO or hidden and only shown as overlay when the user clicks a search icon.
Alternatively we could show the main menu name as headline, but I think thats redundant. Or use a header (see below...).

The meetup has the same icon as events. Maybe we can find a replacement there. Same for support/gen support.
I think order at support would be better: General support, Questions, Fraud report (maybe we find a better term here, as it sounds maybe too alerting).
At events maybe we need make Trade a bit more clear. Intention is that ppl oraganize to local trade events, but not sure if any term is clear enough to describe that. Flash-trade? Satoshi-squares? If we would show a header below the tab line similar as in offerbook we would have some options to make a short description of the channel. That header could than serve also as host for the info/help/search icons.

The icon used at off topic looks more like trade and the trade icon looks more like markets. Not sure if there is a good fit for off-topic of the current icons...

Maybe "Chat peers" would be better than "Peers"?

The selection at the left nav in private chats has a dark border left and right. I think without border it would be more in line with other design. But I understand that the grey tone with the background might be then too close. Maybe a very dark grey could work?

The Bisq and BTC icons are a bit small. Also markets. For the BTC icon the typical tilted version with a circle might be also better.
I am also not so sure if the support icon is clearly enough recognizable. Maybe some other icon which is more typical for support would be better.

If we use a header, we could also consider to use colored icons in larger size, similar as the markets in offerbook. I guess the design could benefit from a few light color drops (as in trade protocols).

The leave button gets truncated in small width if info sidebar is open at private chats.

@HenrikJannsen
Copy link
Contributor

Some code remarks (I add it here not in the commits, as I looked over the whole code change and finding the commit would be extra effort):

TabButton line 91: label.widthProperty().addListener -> we should use either weak listeners or remove it.

I think ChatSearchService should not be handled like a domain service. I will send you a patch with an alternative design suggestion.

@axpoems
Copy link
Contributor Author

axpoems commented Dec 14, 2023

Thanks for the quick review!

Here some comments, but feel free to address those in a new PR, we don't need to get all perfect in one shot.

Yes, I would prefer to work on a new PR. Some comments follow, though:

The space above the tabs is a bit high. I think its better to have it the same as in offerbook.

My idea here was to put the search inside the tab line as you mention, and put it where it is now when the space is too small. However, I really like your idea of doing it similar to offerbook. I also have some small improvements I would like to make there, so perhaps we could align them both in a new PR.

If we would show a header below the tab line similar as in offerbook we would have some options to make a short description of the channel. That header could than serve also as host for the info/help/search icons.

Yes, sound good. Let's do that together with the above.

Maybe "Chat peers" would be better than "Peers"?

I have changed this and also "Private chats" to "Chat window". I wasn't convinced with this header either.

image

The selection at the left nav in private chats has a dark border left and right. I think without border it would be more in line with other design. But I understand that the grey tone with the background might be then too close. Maybe a very dark grey could work?

I will review this selection in the next PR.

If we use a header, we could also consider to use colored icons in larger size, similar as the markets in offerbook. I guess the design could benefit from a few light color drops (as in trade protocols).

Yeah. I will look at that then.

The leave button gets truncated in small width if info sidebar is open at private chats.

I don't particularly like this button, I think it looks too big. I would like to look for a better solution for this.

TabButton line 91: label.widthProperty().addListener -> we should use either weak listeners or remove it.

I added this in order to wrap the words dynamically when changing the window size. Since we removed channels instead, this is not necessary anymore. I have therefore deleted it.

When it comes to the icons, I have created a new issue (#1514) with all the things you pointed out. I will work on it.

@HenrikJannsen
Copy link
Contributor

Here is my suggestion to replace the ChatSearchService.

To use a small component for the toolbox items helps also to keep the main view more light weight.
As we only want to share the toolbox features I think its more natural to use that component as shared object and to pass it to the child controllers.

But the complicate hierarchy here smells as a UX issue. If we would move the toolbox to a header bar in the chat view those problems are gone as the toolbox functionality sits right at the view where its operating on.

Here the patch:

Index: apps/desktop/desktop/src/main/java/bisq/desktop/main/content/common_chat/ChatSearchService.java
===================================================================
diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/common_chat/ChatSearchService.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/common_chat/ChatSearchService.java
deleted file mode 100644
--- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/common_chat/ChatSearchService.java	(revision abb0ed2b63c2e636a9b33a6bbccfd73e66563cf8)
+++ /dev/null	(revision abb0ed2b63c2e636a9b33a6bbccfd73e66563cf8)
@@ -1,50 +0,0 @@
-/*
- * This file is part of Bisq.
- *
- * Bisq is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or (at
- * your option) any later version.
- *
- * Bisq is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with Bisq. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package bisq.desktop.main.content.common_chat;
-
-import javafx.beans.property.SimpleObjectProperty;
-import javafx.beans.property.SimpleStringProperty;
-import javafx.beans.property.StringProperty;
-import lombok.Getter;
-
-@Getter
-public class ChatSearchService {
-    private final StringProperty searchText = new SimpleStringProperty();
-    private final SimpleObjectProperty<Runnable> onHelpRequested = new SimpleObjectProperty<>();
-    private final SimpleObjectProperty<Runnable> onInfoRequested = new SimpleObjectProperty<>();
-
-    public void setOnHelpRequested(Runnable action) {
-        onHelpRequested.set(action);
-    }
-
-    public void setOnInfoRequested(Runnable action) {
-        onInfoRequested.set(action);
-    }
-
-    public void triggerHelpRequested() {
-        if (onHelpRequested.get() != null) {
-            onHelpRequested.get().run();
-        }
-    }
-
-    public void triggerInfoRequested() {
-        if (onInfoRequested.get() != null) {
-            onInfoRequested.get().run();
-        }
-    }
-}
Index: apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/private_chats/BisqEasyPrivateChatsController.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/private_chats/BisqEasyPrivateChatsController.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/private_chats/BisqEasyPrivateChatsController.java
--- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/private_chats/BisqEasyPrivateChatsController.java	(revision abb0ed2b63c2e636a9b33a6bbccfd73e66563cf8)
+++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/private_chats/BisqEasyPrivateChatsController.java	(date 1702576438926)
@@ -23,11 +23,13 @@
 import bisq.desktop.main.content.chat.chats.PrivateChatsController;
 import lombok.extern.slf4j.Slf4j;
 
+import java.util.Optional;
+
 @Slf4j
-public class BisqEasyPrivateChatsController extends PrivateChatsController<BisqEasyPrivateChatsView, BisqEasyPrivateChatsModel> {
+public class BisqEasyPrivateChatsController extends PrivateChatsController {
 
     public BisqEasyPrivateChatsController(ServiceProvider serviceProvider) {
-        super(serviceProvider, ChatChannelDomain.BISQ_EASY_PRIVATE_CHAT, NavigationTarget.BISQ_EASY_PRIVATE_CHAT);
+        super(serviceProvider, ChatChannelDomain.BISQ_EASY_PRIVATE_CHAT, NavigationTarget.BISQ_EASY_PRIVATE_CHAT, Optional.empty());
     }
 
     @Override
Index: apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatContainerController.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatContainerController.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatContainerController.java
--- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatContainerController.java	(revision abb0ed2b63c2e636a9b33a6bbccfd73e66563cf8)
+++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatContainerController.java	(date 1702577156093)
@@ -34,7 +34,6 @@
 import bisq.desktop.main.content.chat.chats.PrivateChatsController;
 import bisq.desktop.main.content.chat.chats.PublicChatController;
 import bisq.desktop.main.content.common_chat.Channel;
-import bisq.desktop.main.content.common_chat.ChatSearchService;
 import lombok.Getter;
 import lombok.extern.slf4j.Slf4j;
 
@@ -52,8 +51,7 @@
     private final CommonPublicChatChannelService commonPublicChatChannelService;
     private final TwoPartyPrivateChatChannelService twoPartyPrivateChatChannelService;
     private final ChatChannelSelectionService chatChannelSelectionService;
-    @Getter
-    private final ChatSearchService chatSearchService;
+    private final ChatToolbox chatToolbox;
     private Pin selectedChannelPin;
     private Pin changedChatNotificationPin;
 
@@ -66,10 +64,11 @@
         commonPublicChatChannelService = chatService.getCommonPublicChatChannelServices().get(chatChannelDomain);
         twoPartyPrivateChatChannelService = chatService.getTwoPartyPrivateChatChannelServices().get(chatChannelDomain);
         chatChannelSelectionService = chatService.getChatChannelSelectionServices().get(chatChannelDomain);
-        chatSearchService = serviceProvider.getChatSearchService();
 
         createChannels();
-        view = new ChatContainerView(model, this);
+
+        chatToolbox = new ChatToolbox();
+        view = new ChatContainerView(model, this, chatToolbox.getRoot());
 
         model.getSelectedTabButton().addListener(observable -> {
             TabButton tabButton = model.getSelectedTabButton().get();
@@ -113,8 +112,6 @@
                 channel -> UIThread.run(() -> handleSelectedChannelChanged(channel)));
         chatNotificationService.getNotConsumedNotifications().forEach(this::handleNotification);
         changedChatNotificationPin = chatNotificationService.getChangedNotification().addObserver(this::handleNotification);
-        chatSearchService.getSearchText().set("");
-        model.getSearchText().bindBidirectional(chatSearchService.getSearchText());
     }
 
     @Override
@@ -123,7 +120,6 @@
 
         selectedChannelPin.unbind();
         changedChatNotificationPin.unbind();
-        model.getSearchText().unbindBidirectional(chatSearchService.getSearchText());
     }
 
     private void handleNotification(ChatNotification notification) {
@@ -168,7 +164,7 @@
     }
 
     protected void handleSelectedChannelChanged(ChatChannel<? extends ChatMessage> chatChannel) {
-        chatSearchService.getSearchText().set("");
+        chatToolbox.resetSearchText();
 
         Channel channel = findOrCreateChannelItem(chatChannel);
         if (channel != null) {
@@ -205,13 +201,13 @@
             case EVENTS_TRADEEVENTS:
             case SUPPORT_SUPPORT:
             case SUPPORT_QUESTIONS:
-            case SUPPORT_REPORTS:{
-                return Optional.of(new PublicChatController(serviceProvider, channelDomain, navigationTarget));
+            case SUPPORT_REPORTS: {
+                return Optional.of(new PublicChatController(serviceProvider, channelDomain, navigationTarget, Optional.of(chatToolbox)));
             }
             case DISCUSSION_PRIVATECHATS:
             case EVENTS_PRIVATECHATS:
             case SUPPORT_PRIVATECHATS: {
-                return Optional.of(new PrivateChatsController(serviceProvider, channelDomain, navigationTarget));
+                return Optional.of(new PrivateChatsController(serviceProvider, channelDomain, navigationTarget, Optional.of(chatToolbox)));
             }
             default: {
                 return Optional.empty();
Index: apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatContainerModel.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatContainerModel.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatContainerModel.java
--- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatContainerModel.java	(revision abb0ed2b63c2e636a9b33a6bbccfd73e66563cf8)
+++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatContainerModel.java	(date 1702577155947)
@@ -21,7 +21,10 @@
 import bisq.chat.ChatChannelDomain;
 import bisq.desktop.main.content.ContentTabModel;
 import bisq.desktop.main.content.common_chat.Channel;
-import javafx.beans.property.*;
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.property.SimpleObjectProperty;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableMap;
 import lombok.Getter;
@@ -35,7 +38,6 @@
     ObjectProperty<Channel> selectedChannel = new SimpleObjectProperty<>();
     private final BooleanProperty hasSelectedChannel = new SimpleBooleanProperty();
     Channel previousSelectedChannel;
-    private final StringProperty searchText = new SimpleStringProperty();
 
     public ChatContainerModel(ChatChannelDomain chatChannelDomain) {
         this.chatChannelDomain = chatChannelDomain;
Index: apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatToolbox.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatToolbox.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatToolbox.java
new file mode 100644
--- /dev/null	(date 1702576935684)
+++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatToolbox.java	(date 1702576935684)
@@ -0,0 +1,141 @@
+/*
+ * This file is part of Bisq.
+ *
+ * Bisq is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * Bisq is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Bisq. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package bisq.desktop.main.content.chat.navigation;
+
+import bisq.desktop.components.controls.BisqIconButton;
+import bisq.desktop.components.controls.SearchBox;
+import bisq.i18n.Res;
+import javafx.beans.property.ReadOnlyStringProperty;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+import javafx.geometry.Pos;
+import javafx.scene.control.Button;
+import javafx.scene.layout.HBox;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Optional;
+
+public class ChatToolbox {
+    private final Controller controller;
+
+    public ChatToolbox() {
+        controller = new Controller();
+    }
+
+    public HBox getRoot() {
+        return controller.getView().getRoot();
+    }
+
+    public ReadOnlyStringProperty searchTextProperty() {
+        return controller.model.getSearchText();
+    }
+
+    public void resetSearchText() {
+        controller.resetSearchText();
+    }
+
+    public void setOnOpenHelpHandler(Runnable onOpenHelpHandler) {
+        controller.setOnOpenHelpHandler(onOpenHelpHandler);
+    }
+
+    public void setOnToggleChannelInfoHandler(Runnable onToggleChannelInfoHandler) {
+        controller.setOnToggleChannelInfoHandler(onToggleChannelInfoHandler);
+    }
+
+    @Slf4j
+    public static class Controller implements bisq.desktop.common.view.Controller {
+        @Getter
+        private final View view;
+        private final Model model;
+        private Optional<Runnable> onOpenHelpHandler = Optional.empty();
+        private Optional<Runnable> onToggleChannelInfoHandler = Optional.empty();
+
+        private Controller() {
+            model = new Model();
+            view = new View(model, this);
+        }
+
+        private void resetSearchText() {
+            model.getSearchText().set("");
+        }
+
+        private void setOnOpenHelpHandler(Runnable onOpenHelpHandler) {
+            this.onOpenHelpHandler = Optional.of(onOpenHelpHandler);
+        }
+
+        private void setOnToggleChannelInfoHandler(Runnable onToggleChannelInfoHandler) {
+            this.onToggleChannelInfoHandler = Optional.of(onToggleChannelInfoHandler);
+        }
+
+        @Override
+        public void onActivate() {
+            model.getSearchText().set("");
+        }
+
+        @Override
+        public void onDeactivate() {
+        }
+
+
+        private void onOpenHelp() {
+            onOpenHelpHandler.ifPresent(Runnable::run);
+        }
+
+        private void onToggleChannelInfo() {
+            onToggleChannelInfoHandler.ifPresent(Runnable::run);
+        }
+    }
+
+    @Getter
+    private static class Model implements bisq.desktop.common.view.Model {
+        private final StringProperty searchText = new SimpleStringProperty();
+    }
+
+    @Slf4j
+    private static class View extends bisq.desktop.common.view.View<HBox, Model, Controller> {
+        private final SearchBox searchBox;
+        private final Button helpButton, infoButton;
+
+        private View(Model model, Controller controller) {
+            super(new HBox(7), model, controller);
+
+            root.setAlignment(Pos.CENTER_RIGHT);
+
+            searchBox = new SearchBox();
+            helpButton = BisqIconButton.createIconButton("icon-help", Res.get("chat.topMenu.chatRules.tooltip"));
+            infoButton = BisqIconButton.createIconButton("icon-info", Res.get("chat.topMenu.channelInfoIcon.tooltip"));
+
+            root.getChildren().addAll(searchBox, helpButton, infoButton);
+        }
+
+        @Override
+        protected void onViewAttached() {
+            searchBox.textProperty().bindBidirectional(model.getSearchText());
+            helpButton.setOnAction(e -> controller.onOpenHelp());
+            infoButton.setOnAction(e -> controller.onToggleChannelInfo());
+        }
+
+        @Override
+        protected void onViewDetached() {
+            searchBox.textProperty().unbindBidirectional(model.getSearchText());
+            helpButton.setOnAction(null);
+            infoButton.setOnAction(null);
+        }
+    }
+}
\ No newline at end of file
Index: apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatContainerView.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatContainerView.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatContainerView.java
--- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatContainerView.java	(revision abb0ed2b63c2e636a9b33a6bbccfd73e66563cf8)
+++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/navigation/ChatContainerView.java	(date 1702576708719)
@@ -20,26 +20,22 @@
 import bisq.desktop.common.view.Controller;
 import bisq.desktop.common.view.Model;
 import bisq.desktop.common.view.View;
-import bisq.desktop.components.controls.BisqIconButton;
-import bisq.desktop.components.controls.SearchBox;
 import bisq.desktop.main.content.ContentTabView;
 import bisq.i18n.Res;
 import javafx.geometry.Insets;
-import javafx.geometry.Pos;
 import javafx.scene.Parent;
-import javafx.scene.control.Button;
 import javafx.scene.layout.HBox;
 import javafx.scene.layout.VBox;
 import lombok.extern.slf4j.Slf4j;
 
 @Slf4j
 public class ChatContainerView extends ContentTabView<ChatContainerModel, ChatContainerController> {
-    private SearchBox searchBox;
-    private Button infoButton;
 
-    public ChatContainerView(ChatContainerModel model, ChatContainerController controller) {
+    public ChatContainerView(ChatContainerModel model, ChatContainerController controller, HBox toolboxRoot) {
         super(model, controller);
 
+        topBox.getChildren().add(0, toolboxRoot);
+
         model.getChannels().values().stream().sorted().forEach(channel ->
                 addTab(channel.getChannelTitle(), channel.getNavigationTarget(), channel.getIconId())
         );
@@ -55,23 +51,11 @@
 
     @Override
     protected void setupTopBox() {
-        searchBox = new SearchBox();
-        Button helpButton = BisqIconButton.createIconButton("icon-help", Res.get("chat.topMenu.chatRules.tooltip"));
-        helpButton.setOnAction(e -> controller.getChatSearchService().triggerHelpRequested());
-
-        infoButton = BisqIconButton.createIconButton("icon-info", Res.get("chat.topMenu.channelInfoIcon.tooltip"));
-        infoButton.setOnAction(e -> controller.getChatSearchService().triggerInfoRequested());
-
-        HBox searchInfo = new HBox(searchBox, helpButton, infoButton);
-        searchInfo.setSpacing(7);
-        searchInfo.setAlignment(Pos.CENTER_RIGHT);
-        HBox.setMargin(searchInfo, new Insets(0, 0, 10, 0));
-
         tabs.setFillHeight(true);
         tabs.setSpacing(46);
         VBox.setMargin(tabs, new Insets(0, 0, 11, 0));
 
-        topBox = new VBox(12, searchInfo, tabs);
+        topBox = new VBox(12, tabs);
         topBox.setMinHeight(115);
         topBox.setPadding(DEFAULT_TOP_PANE_PADDING);
     }
@@ -79,18 +63,10 @@
     @Override
     protected void onViewAttached() {
         super.onViewAttached();
-
-        searchBox.textProperty().bindBidirectional(model.getSearchText());
-        infoButton.visibleProperty().bind(model.getHasSelectedChannel());
-        infoButton.managedProperty().bind(model.getHasSelectedChannel());
     }
 
     @Override
     protected void onViewDetached() {
         super.onViewDetached();
-
-        searchBox.textProperty().unbindBidirectional(model.getSearchText());
-        infoButton.visibleProperty().unbind();
-        infoButton.managedProperty().unbind();
     }
 }
Index: apps/desktop/desktop/src/main/java/bisq/desktop/ServiceProvider.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/ServiceProvider.java b/apps/desktop/desktop/src/main/java/bisq/desktop/ServiceProvider.java
--- a/apps/desktop/desktop/src/main/java/bisq/desktop/ServiceProvider.java	(revision abb0ed2b63c2e636a9b33a6bbccfd73e66563cf8)
+++ b/apps/desktop/desktop/src/main/java/bisq/desktop/ServiceProvider.java	(date 1702576114605)
@@ -28,7 +28,6 @@
 import bisq.bonded_roles.BondedRolesService;
 import bisq.chat.ChatService;
 import bisq.contract.ContractService;
-import bisq.desktop.main.content.common_chat.ChatSearchService;
 import bisq.identity.IdentityService;
 import bisq.network.NetworkService;
 import bisq.offer.OfferService;
@@ -68,7 +67,6 @@
     private final TradeService tradeService;
     private final UpdaterService updaterService;
     private final BisqEasyService bisqEasyService;
-    private final ChatSearchService chatSearchService;
 
     public ServiceProvider(ShutDownHandler shutDownHandler,
                            ApplicationService.Config config,
@@ -88,8 +86,7 @@
                            SendNotificationService sendNotificationService,
                            TradeService tradeService,
                            UpdaterService updaterService,
-                           BisqEasyService bisqEasyService,
-                           ChatSearchService chatSearchService) {
+                           BisqEasyService bisqEasyService) {
         this.shutDownHandler = shutDownHandler;
         this.config = config;
         this.persistenceService = persistenceService;
@@ -109,6 +106,5 @@
         this.tradeService = tradeService;
         this.updaterService = updaterService;
         this.bisqEasyService = bisqEasyService;
-        this.chatSearchService = chatSearchService;
     }
 }
Index: apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/chats/PublicChatController.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/chats/PublicChatController.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/chats/PublicChatController.java
--- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/chats/PublicChatController.java	(revision abb0ed2b63c2e636a9b33a6bbccfd73e66563cf8)
+++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/chats/PublicChatController.java	(date 1702576935675)
@@ -20,16 +20,19 @@
 import bisq.bisq_easy.NavigationTarget;
 import bisq.chat.ChatChannelDomain;
 import bisq.desktop.ServiceProvider;
+import bisq.desktop.main.content.chat.navigation.ChatToolbox;
 import bisq.desktop.main.content.common_chat.CommonChatController;
 import lombok.extern.slf4j.Slf4j;
 
+import java.util.Optional;
+
 @Slf4j
 public class PublicChatController extends CommonChatController<PublicChatView, PublicChatModel> {
-    public PublicChatController(
-            ServiceProvider serviceProvider,
-            ChatChannelDomain chatChannelDomain,
-            NavigationTarget navigationTarget) {
-        super(serviceProvider, chatChannelDomain, navigationTarget);
+    public PublicChatController(ServiceProvider serviceProvider,
+                                ChatChannelDomain chatChannelDomain,
+                                NavigationTarget navigationTarget,
+                                Optional<ChatToolbox> toolbox) {
+        super(serviceProvider, chatChannelDomain, navigationTarget, toolbox);
     }
 
     @Override
Index: apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/chats/PrivateChatsController.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/chats/PrivateChatsController.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/chats/PrivateChatsController.java
--- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/chats/PrivateChatsController.java	(revision abb0ed2b63c2e636a9b33a6bbccfd73e66563cf8)
+++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/chats/PrivateChatsController.java	(date 1702576935688)
@@ -27,6 +27,7 @@
 import bisq.desktop.ServiceProvider;
 import bisq.desktop.common.observable.FxBindings;
 import bisq.desktop.common.threading.UIThread;
+import bisq.desktop.main.content.chat.navigation.ChatToolbox;
 import bisq.desktop.main.content.common_chat.CommonChatController;
 import bisq.user.profile.UserProfile;
 import bisq.user.reputation.ReputationService;
@@ -34,16 +35,20 @@
 import org.fxmisc.easybind.EasyBind;
 import org.fxmisc.easybind.Subscription;
 
+import java.util.Optional;
+
 @Slf4j
-public class PrivateChatsController<V extends PrivateChatsView, M extends PrivateChatsModel>
-        extends CommonChatController<PrivateChatsView, PrivateChatsModel> {
+public class PrivateChatsController extends CommonChatController<PrivateChatsView, PrivateChatsModel> {
     private final TwoPartyPrivateChatChannelService channelService;
     private final ReputationService reputationService;
     private Pin channelItemPin, channelsPin;
     private Subscription openPrivateChatsPin;
 
-    public PrivateChatsController(ServiceProvider serviceProvider, ChatChannelDomain chatChannelDomain, NavigationTarget navigationTarget) {
-        super(serviceProvider, chatChannelDomain, navigationTarget);
+    public PrivateChatsController(ServiceProvider serviceProvider,
+                                  ChatChannelDomain chatChannelDomain,
+                                  NavigationTarget navigationTarget,
+                                  Optional<ChatToolbox> toolbox) {
+        super(serviceProvider, chatChannelDomain, navigationTarget, toolbox);
 
         channelService = chatService.getTwoPartyPrivateChatChannelServices().get(chatChannelDomain);
         reputationService = serviceProvider.getUserService().getReputationService();
Index: apps/desktop/desktop/src/main/java/bisq/desktop/main/content/common_chat/CommonChatController.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/common_chat/CommonChatController.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/common_chat/CommonChatController.java
--- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/common_chat/CommonChatController.java	(revision abb0ed2b63c2e636a9b33a6bbccfd73e66563cf8)
+++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/common_chat/CommonChatController.java	(date 1702576935680)
@@ -24,6 +24,7 @@
 import bisq.desktop.ServiceProvider;
 import bisq.desktop.common.view.Controller;
 import bisq.desktop.main.content.chat.ChatController;
+import bisq.desktop.main.content.chat.navigation.ChatToolbox;
 import lombok.extern.slf4j.Slf4j;
 import org.fxmisc.easybind.EasyBind;
 import org.fxmisc.easybind.Subscription;
@@ -33,15 +34,18 @@
 @Slf4j
 public abstract class CommonChatController<V extends CommonChatView<V, M>, M extends CommonChatModel>
         extends ChatController<V, M> implements Controller {
-    private final ChatSearchService chatSearchService;
+    private final Optional<ChatToolbox> toolbox;
     protected ChatChannelSelectionService selectionService;
     private Subscription searchTextPin;
     private Pin selectedChannelPin;
 
-    public CommonChatController(ServiceProvider serviceProvider, ChatChannelDomain chatChannelDomain, NavigationTarget navigationTarget) {
+    public CommonChatController(ServiceProvider serviceProvider,
+                                ChatChannelDomain chatChannelDomain,
+                                NavigationTarget navigationTarget,
+                                Optional<ChatToolbox> toolbox) {
         super(serviceProvider, chatChannelDomain, navigationTarget);
 
-        chatSearchService = serviceProvider.getChatSearchService();
+        this.toolbox = toolbox;
     }
 
     @Override
@@ -52,17 +56,23 @@
     @Override
     public void onActivate() {
         selectedChannelPin = selectionService.getSelectedChannel().addObserver(this::selectedChannelChanged);
-        searchTextPin = EasyBind.subscribe(chatSearchService.getSearchText(), searchText ->
-                chatMessagesComponent.setSearchPredicate(item ->
-                    searchText == null || searchText.isEmpty() || item.match(searchText)));
-        chatSearchService.setOnHelpRequested(this::onOpenHelp);
-        chatSearchService.setOnInfoRequested(this::onToggleChannelInfo);
+
+        toolbox.ifPresent(chatToolbox -> {
+            searchTextPin = EasyBind.subscribe(chatToolbox.searchTextProperty(), searchText ->
+                    chatMessagesComponent.setSearchPredicate(item ->
+                            searchText == null || searchText.isEmpty() || item.match(searchText)));
+
+            chatToolbox.setOnOpenHelpHandler(this::onOpenHelp);
+            chatToolbox.setOnToggleChannelInfoHandler(this::onToggleChannelInfo);
+        });
     }
 
     @Override
     public void onDeactivate() {
         selectedChannelPin.unbind();
-        searchTextPin.unsubscribe();
+        if (searchTextPin != null) {
+            searchTextPin.unsubscribe();
+        }
     }
 
     @Override
Index: apps/desktop/desktop-app/src/main/java/bisq/desktop_app/DesktopApplicationService.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/apps/desktop/desktop-app/src/main/java/bisq/desktop_app/DesktopApplicationService.java b/apps/desktop/desktop-app/src/main/java/bisq/desktop_app/DesktopApplicationService.java
--- a/apps/desktop/desktop-app/src/main/java/bisq/desktop_app/DesktopApplicationService.java	(revision abb0ed2b63c2e636a9b33a6bbccfd73e66563cf8)
+++ b/apps/desktop/desktop-app/src/main/java/bisq/desktop_app/DesktopApplicationService.java	(date 1702576114626)
@@ -29,7 +29,6 @@
 import bisq.contract.ContractService;
 import bisq.desktop.ServiceProvider;
 import bisq.desktop.State;
-import bisq.desktop.main.content.common_chat.ChatSearchService;
 import bisq.identity.IdentityService;
 import bisq.network.NetworkService;
 import bisq.network.NetworkServiceConfig;
@@ -191,8 +190,7 @@
                 sendNotificationService,
                 tradeService,
                 updaterService,
-                bisqEasyService,
-                new ChatSearchService());
+                bisqEasyService);
     }
 
     @Override

Copy link
Contributor

@HenrikJannsen HenrikJannsen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NACK

There is missing some changes from the patch. See also https://github.com/HenrikJannsen/bisq2/tree/ChatSearchService-alternative

@axpoems
Copy link
Contributor Author

axpoems commented Dec 16, 2023

@HenrikJannsen - there was an issue with the patch you sent me (git apply was reporting that the patch was corrupted). I used the commit from your branch instead and added the changes yesterday in my latest force-pushed.
I have tested it, and it is working well.

Copy link
Contributor

@HenrikJannsen HenrikJannsen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK

Copy link
Contributor

@alvasw alvasw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK

@alvasw alvasw merged commit d4d4a7b into bisq-network:main Dec 17, 2023
15 checks passed
@axpoems axpoems deleted the refactor-chat branch December 30, 2023 07:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use new tab based design for common chats
3 participants