Skip to content

Commit

Permalink
Merge pull request #3032 from axpoems/add-offerbook-messagetype-filter
Browse files Browse the repository at this point in the history
Add message type filter to offerbook
  • Loading branch information
axpoems authored Nov 25, 2024
2 parents 13b00ef + 99cf4cc commit 6108035
Show file tree
Hide file tree
Showing 16 changed files with 198 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import bisq.desktop.main.content.chat.ChatController;
import bisq.i18n.Res;
import bisq.presentation.formatters.PriceFormatter;
import bisq.settings.ChatMessageType;
import bisq.settings.CookieKey;
import bisq.settings.FavouriteMarketsService;
import bisq.settings.SettingsService;
Expand Down Expand Up @@ -73,7 +74,7 @@ public final class BisqEasyOfferbookController extends ChatController<BisqEasyOf
private OfferbookListController offerbookListController;
private Pin bisqEasyPrivateTradeChatChannelsPin, selectedChannelPin, marketPriceByCurrencyMapPin,
favouriteMarketsPin, showMarketSelectionListCollapsedSettingsPin,
changedNotificationPin;
changedNotificationPin, bisqEasyOfferbookMessageTypeFilterPin;
private Subscription marketSelectorSearchPin, selectedMarketFilterPin, selectedMarketSortTypePin;
private final ListChangeListener<? super MarketChannelItem> marketChannelItemListener = c -> updateFilteredMarketChannelItems();
private final Map<MarketChannelItem, ChangeListener<Number>> marketNumOffersListeners = new HashMap<>();
Expand Down Expand Up @@ -221,6 +222,9 @@ public void clear() {
}
});

bisqEasyOfferbookMessageTypeFilterPin = FxBindings.bindBiDir(model.getMessageTypeFilter())
.to(settingsService.getBisqEasyOfferbookMessageTypeFilter());

model.getMarketChannelItems().forEach(item -> {
ChangeListener<Number> numberChangeListener = (obs, oldValue, newValue) -> updateFilteredMarketChannelItems();
item.getNumOffers().addListener(numberChangeListener);
Expand All @@ -241,6 +245,7 @@ public void onDeactivate() {
selectedMarketSortTypePin.unsubscribe();
favouriteMarketsPin.unbind();
changedNotificationPin.unbind();
bisqEasyOfferbookMessageTypeFilterPin.unbind();

model.getMarketChannelItems().removeListener(marketChannelItemListener);
marketNumOffersListeners.forEach((item, changeListener) -> item.getNumOffers().removeListener(changeListener));
Expand Down Expand Up @@ -309,6 +314,10 @@ void toggleMarketSelectionList() {
model.getShowMarketSelectionListCollapsed().set(!model.getShowMarketSelectionListCollapsed().get());
}

void setMessageTypeFilter(ChatMessageType messageType) {
model.getMessageTypeFilter().set(messageType);
}

private void createMarketChannels() {
List<MarketChannelItem> marketChannelItems = bisqEasyOfferbookChannelService.getChannels().stream()
.map(channel -> new MarketChannelItem(channel, favouriteMarketsService, chatNotificationService))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import bisq.bisq_easy.BisqEasyMarketFilter;
import bisq.chat.ChatChannelDomain;
import bisq.desktop.main.content.chat.ChatModel;
import bisq.settings.ChatMessageType;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyBooleanProperty;
Expand Down Expand Up @@ -53,6 +54,7 @@ public final class BisqEasyOfferbookModel extends ChatModel {
private final StringProperty marketPrice = new SimpleStringProperty();
private final StringProperty fiatAmountTitle = new SimpleStringProperty();
private final BooleanProperty showMarketSelectionListCollapsed = new SimpleBooleanProperty();
private final ObjectProperty<ChatMessageType> messageTypeFilter = new SimpleObjectProperty<>(ChatMessageType.ALL);

@Setter
private ReadOnlyBooleanProperty showOfferListExpanded;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import bisq.desktop.main.content.chat.ChatView;
import bisq.desktop.main.content.components.MarketImageComposition;
import bisq.i18n.Res;
import bisq.settings.ChatMessageType;
import javafx.beans.binding.Bindings;
import javafx.collections.ListChangeListener;
import javafx.css.PseudoClass;
Expand Down Expand Up @@ -61,11 +62,12 @@ public final class BisqEasyOfferbookView extends ChatView<BisqEasyOfferbookView,
private Subscription marketsTableViewSelectionPin, selectedMarketChannelItemPin, selectedMarketFilterPin,
selectedMarketSortTypePin, marketSelectorSearchPin, favouritesTableViewHeightChangedPin,
favouritesTableViewSelectionPin, shouldShowAppliedFiltersPin,
showOfferListExpandedPin, showMarketSelectionListCollapsedPin;
showOfferListExpandedPin, showMarketSelectionListCollapsedPin, messageTypeFilterPin;
private Button createOfferButton;
private DropdownMenu sortAndFilterMarketsMenu;
private SortAndFilterMarketsDropdownMenuItem<MarketSortType> sortByMostOffers, sortByNameAZ, sortByNameZA;
private SortAndFilterMarketsDropdownMenuItem<BisqEasyMarketFilter> filterShowAll, filterWithOffers, filterFavourites;
private DropdownMenu sortAndFilterMarketsMenu, messageTypeFilterMenu;
private SortAndFilterDropdownMenuItem<MarketSortType> sortByMostOffers, sortByNameAZ, sortByNameZA;
private SortAndFilterDropdownMenuItem<BisqEasyMarketFilter> filterShowAll, filterWithOffers, filterFavourites;
private SortAndFilterDropdownMenuItem<ChatMessageType> showAllMessages, showOnlyOfferMessages, showOnlyTextMessages;
private Label channelHeaderIcon, marketPrice, removeWithOffersFilter, removeFavouritesFilter,
collapsedMarketSelectionListTitle, marketSelectionListTitle;
private HBox appliedFiltersSection, withOffersDisplayHint, onlyFavouritesDisplayHint;
Expand Down Expand Up @@ -177,6 +179,8 @@ protected void onViewAttached() {
}
});

messageTypeFilterPin = EasyBind.subscribe(getModel().getMessageTypeFilter(), this::updateMessageTypeFilter);

sortByMostOffers.setOnAction(e -> getController().onSortMarkets(MarketSortType.NUM_OFFERS));
sortByNameAZ.setOnAction(e -> getController().onSortMarkets(MarketSortType.ASC));
sortByNameZA.setOnAction(e -> getController().onSortMarkets(MarketSortType.DESC));
Expand All @@ -185,6 +189,10 @@ protected void onViewAttached() {
filterShowAll.setOnAction(e -> getModel().getSelectedMarketsFilter().set(ALL));
filterFavourites.setOnAction(e -> getModel().getSelectedMarketsFilter().set(FAVOURITES));

showAllMessages.setOnAction(e -> getController().setMessageTypeFilter(showAllMessages.getMenuItem()));
showOnlyOfferMessages.setOnAction(e -> getController().setMessageTypeFilter(showOnlyOfferMessages.getMenuItem()));
showOnlyTextMessages.setOnAction(e -> getController().setMessageTypeFilter(showOnlyTextMessages.getMenuItem()));

createOfferButton.setOnAction(e -> getController().onCreateOffer());

removeWithOffersFilter.setOnMouseClicked(e -> getModel().getSelectedMarketsFilter().set(ALL));
Expand Down Expand Up @@ -236,6 +244,7 @@ protected void onViewDetached() {
selectedMarketFilterPin.unsubscribe();
selectedMarketSortTypePin.unsubscribe();
favouritesTableViewHeightChangedPin.unsubscribe();
messageTypeFilterPin.unsubscribe();
shouldShowAppliedFiltersPin.unsubscribe();
showOfferListExpandedPin.unsubscribe();
showMarketSelectionListCollapsedPin.unsubscribe();
Expand All @@ -246,6 +255,9 @@ protected void onViewDetached() {
filterWithOffers.setOnAction(null);
filterShowAll.setOnAction(null);
filterFavourites.setOnAction(null);
showAllMessages.setOnAction(null);
showOnlyOfferMessages.setOnAction(null);
showOnlyTextMessages.setOnAction(null);
createOfferButton.setOnAction(null);

removeWithOffersFilter.setOnMouseClicked(null);
Expand Down Expand Up @@ -418,11 +430,11 @@ private DropdownMenu createAndGetSortAndFilterMarketsMenu() {
// Sorting options
DropdownTitleMenuItem sortTitle = new DropdownTitleMenuItem(
Res.get("bisqEasy.offerbook.dropdownMenu.sortAndFilterMarkets.sortTitle"));
sortByMostOffers = new SortAndFilterMarketsDropdownMenuItem<>("check-white", "check-white",
sortByMostOffers = new SortAndFilterDropdownMenuItem<>("check-white", "check-white",
Res.get("bisqEasy.offerbook.dropdownMenu.sortAndFilterMarkets.mostOffers"), MarketSortType.NUM_OFFERS);
sortByNameAZ = new SortAndFilterMarketsDropdownMenuItem<>("check-white", "check-white",
sortByNameAZ = new SortAndFilterDropdownMenuItem<>("check-white", "check-white",
Res.get("bisqEasy.offerbook.dropdownMenu.sortAndFilterMarkets.nameAZ"), MarketSortType.ASC);
sortByNameZA = new SortAndFilterMarketsDropdownMenuItem<>("check-white", "check-white",
sortByNameZA = new SortAndFilterDropdownMenuItem<>("check-white", "check-white",
Res.get("bisqEasy.offerbook.dropdownMenu.sortAndFilterMarkets.nameZA"), MarketSortType.DESC);

// Separator
Expand All @@ -431,11 +443,11 @@ private DropdownMenu createAndGetSortAndFilterMarketsMenu() {
// Filter options
DropdownTitleMenuItem filterTitle = new DropdownTitleMenuItem(
Res.get("bisqEasy.offerbook.dropdownMenu.sortAndFilterMarkets.filterTitle"));
filterWithOffers = new SortAndFilterMarketsDropdownMenuItem<>("check-white", "check-white",
filterWithOffers = new SortAndFilterDropdownMenuItem<>("check-white", "check-white",
Res.get("bisqEasy.offerbook.dropdownMenu.sortAndFilterMarkets.withOffers"), WITH_OFFERS);
filterFavourites = new SortAndFilterMarketsDropdownMenuItem<>("check-white", "check-white",
filterFavourites = new SortAndFilterDropdownMenuItem<>("check-white", "check-white",
Res.get("bisqEasy.offerbook.dropdownMenu.sortAndFilterMarkets.favourites"), FAVOURITES);
filterShowAll = new SortAndFilterMarketsDropdownMenuItem<>("check-white", "check-white",
filterShowAll = new SortAndFilterDropdownMenuItem<>("check-white", "check-white",
Res.get("bisqEasy.offerbook.dropdownMenu.sortAndFilterMarkets.all"), ALL);

dropdownMenu.addMenuItems(sortTitle, sortByMostOffers, sortByNameAZ, sortByNameZA, separator, filterTitle,
Expand Down Expand Up @@ -472,7 +484,8 @@ private void addChatBox() {
centerVBox.setFillWidth(true);

searchBox.getStyleClass().add("offerbook-search-box");
HBox subheaderContent = new HBox(30, searchBox, Spacer.fillHBox());
messageTypeFilterMenu = createAndGetMessageTypeFilterMenu();
HBox subheaderContent = new HBox(30, searchBox, Spacer.fillHBox(), messageTypeFilterMenu);
subheaderContent.getStyleClass().add("offerbook-subheader-content");
HBox.setHgrow(subheaderContent, Priority.ALWAYS);

Expand All @@ -487,16 +500,32 @@ private void addChatBox() {
centerVBox.setAlignment(Pos.CENTER);
}

private DropdownMenu createAndGetMessageTypeFilterMenu() {
DropdownMenu dropdownMenu = new DropdownMenu("chevron-drop-menu-grey", "chevron-drop-menu-white", false);
dropdownMenu.setTooltip(Res.get("bisqEasy.offerbook.dropdownMenu.messageTypeFilter.tooltip"));
dropdownMenu.getStyleClass().add("dropdown-offer-list-payment-filter-menu");

showAllMessages = new SortAndFilterDropdownMenuItem<>("check-white", "check-white",
Res.get("bisqEasy.offerbook.dropdownMenu.messageTypeFilter.all"), ChatMessageType.ALL);
showOnlyOfferMessages = new SortAndFilterDropdownMenuItem<>("check-white", "check-white",
Res.get("bisqEasy.offerbook.dropdownMenu.messageTypeFilter.offers"), ChatMessageType.OFFER);
showOnlyTextMessages = new SortAndFilterDropdownMenuItem<>("check-white", "check-white",
Res.get("bisqEasy.offerbook.dropdownMenu.messageTypeFilter.text"), ChatMessageType.TEXT);

dropdownMenu.addMenuItems(showAllMessages, showOnlyOfferMessages, showOnlyTextMessages);
return dropdownMenu;
}

private void updateSelectedMarketFilter(BisqEasyMarketFilter bisqEasyMarketFilter) {
if (bisqEasyMarketFilter == null) {
return;
}

//noinspection unchecked
sortAndFilterMarketsMenu.getMenuItems().stream()
.filter(menuItem -> menuItem instanceof SortAndFilterMarketsDropdownMenuItem &&
((SortAndFilterMarketsDropdownMenuItem<?>) menuItem).getMenuItem() instanceof BisqEasyMarketFilter)
.map(menuItem -> (SortAndFilterMarketsDropdownMenuItem<BisqEasyMarketFilter>) menuItem)
.filter(menuItem -> menuItem instanceof SortAndFilterDropdownMenuItem &&
((SortAndFilterDropdownMenuItem<?>) menuItem).getMenuItem() instanceof BisqEasyMarketFilter)
.map(menuItem -> (SortAndFilterDropdownMenuItem<BisqEasyMarketFilter>) menuItem)
.forEach(menuItem -> menuItem.updateSelection(bisqEasyMarketFilter == menuItem.getMenuItem()));

marketsTableView.getSelectionModel().select(getModel().getSelectedMarketChannelItem().get());
Expand All @@ -509,9 +538,9 @@ private void updateMarketSortType(MarketSortType marketSortType) {

//noinspection unchecked
sortAndFilterMarketsMenu.getMenuItems().stream()
.filter(menuItem -> menuItem instanceof SortAndFilterMarketsDropdownMenuItem &&
((SortAndFilterMarketsDropdownMenuItem<?>) menuItem).getMenuItem() instanceof MarketSortType)
.map(menuItem -> (SortAndFilterMarketsDropdownMenuItem<MarketSortType>) menuItem)
.filter(menuItem -> menuItem instanceof SortAndFilterDropdownMenuItem &&
((SortAndFilterDropdownMenuItem<?>) menuItem).getMenuItem() instanceof MarketSortType)
.map(menuItem -> (SortAndFilterDropdownMenuItem<MarketSortType>) menuItem)
.forEach(menuItem -> menuItem.updateSelection(marketSortType == menuItem.getMenuItem()));
}

Expand All @@ -522,13 +551,34 @@ private void updateAppliedFiltersSectionStyles(boolean shouldShowAppliedFilters)
: "market-selection-no-filters");
}

void updateMessageTypeFilter(ChatMessageType messageType) {
messageTypeFilterMenu.setLabelAsContent(getMessageTypeAsString(messageType));

//noinspection unchecked
messageTypeFilterMenu.getMenuItems().stream()
.filter(menuItem -> menuItem instanceof SortAndFilterDropdownMenuItem &&
((SortAndFilterDropdownMenuItem<?>) menuItem).getMenuItem() instanceof ChatMessageType)
.map(menuItem -> (SortAndFilterDropdownMenuItem<ChatMessageType>) menuItem)
.forEach(menuItem -> menuItem.updateSelection(messageType == menuItem.getMenuItem()));
}

private String getMessageTypeAsString(ChatMessageType messageType) {
if (messageType == ChatMessageType.OFFER) {
return Res.get("bisqEasy.offerbook.dropdownMenu.messageTypeFilter.offers");
}
if (messageType == ChatMessageType.TEXT) {
return Res.get("bisqEasy.offerbook.dropdownMenu.messageTypeFilter.text");
}
return Res.get("bisqEasy.offerbook.dropdownMenu.messageTypeFilter.all");
}

@Getter
private static final class SortAndFilterMarketsDropdownMenuItem<T> extends DropdownBisqMenuItem {
private static final class SortAndFilterDropdownMenuItem<T> extends DropdownBisqMenuItem {
private static final PseudoClass SELECTED_PSEUDO_CLASS = PseudoClass.getPseudoClass("selected");

private final T menuItem;

SortAndFilterMarketsDropdownMenuItem(String defaultIconId, String activeIconId, String text, T menuItem) {
SortAndFilterDropdownMenuItem(String defaultIconId, String activeIconId, String text, T menuItem) {
super(defaultIconId, activeIconId, text);

this.menuItem = menuItem;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import bisq.presentation.formatters.AmountFormatter;
import bisq.presentation.formatters.PercentageFormatter;
import bisq.presentation.formatters.PriceFormatter;
import bisq.settings.ChatMessageType;
import bisq.settings.SettingsService;
import bisq.support.mediation.MediationRequestService;
import bisq.trade.bisq_easy.BisqEasyTrade;
Expand Down Expand Up @@ -393,6 +394,17 @@ public void reset() {

public void publishOffer() {
UserIdentity userIdentity = userIdentityService.getSelectedUserIdentity();

String dontShowAgainId = "sendOfferMsgTextOnlyWarn";
boolean hasShowOnlyTextFilter = settingsService.getBisqEasyOfferbookMessageTypeFilter().get() == ChatMessageType.TEXT;
if (hasShowOnlyTextFilter) {
new Popup().information(Res.get("chat.message.send.textMsgOnly.warn"))
.actionButtonText(Res.get("confirmation.yes"))
.onAction(() -> settingsService.getBisqEasyOfferbookMessageTypeFilter().set(ChatMessageType.ALL))
.closeButtonText(Res.get("confirmation.no"))
.dontShowAgainId(dontShowAgainId)
.show();
}
bisqEasyOfferbookChannelService.publishChatMessage(model.getMyOfferMessage(), userIdentity)
.thenAccept(result -> UIThread.run(() -> {
model.getShowCreateOfferSuccess().set(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import bisq.desktop.main.content.chat.message_container.list.ChatMessagesListController;
import bisq.desktop.main.content.components.UserProfileSelection;
import bisq.i18n.Res;
import bisq.settings.ChatMessageType;
import bisq.settings.SettingsService;
import bisq.user.identity.UserIdentity;
import bisq.user.identity.UserIdentityService;
Expand Down Expand Up @@ -263,10 +264,11 @@ private void doSendMessage(String text) {

if (chatChannel instanceof BisqEasyOfferbookChannel) {
String dontShowAgainId = "sendMsgOfferOnlyWarn";
if (settingsService.getOffersOnly().get()) {
boolean hasShowOnlyOffersFilter = settingsService.getBisqEasyOfferbookMessageTypeFilter().get() == ChatMessageType.OFFER;
if (hasShowOnlyOffersFilter) {
new Popup().information(Res.get("chat.message.send.offerOnly.warn"))
.actionButtonText(Res.get("confirmation.yes"))
.onAction(() -> settingsService.getOffersOnly().set(false))
.onAction(() -> settingsService.getBisqEasyOfferbookMessageTypeFilter().set(ChatMessageType.ALL))
.closeButtonText(Res.get("confirmation.no"))
.dontShowAgainId(dontShowAgainId)
.show();
Expand Down
Loading

0 comments on commit 6108035

Please sign in to comment.