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

Add reactions to Two Party Private messages #2355

Merged
merged 7 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import bisq.chat.reactions.BisqEasyOfferbookMessageReaction;
import bisq.chat.reactions.ChatMessageReaction;
import bisq.chat.reactions.CommonPublicChatMessageReaction;
import bisq.chat.reactions.TwoPartyPrivateChatMessageReaction;
import bisq.chat.two_party.TwoPartyPrivateChatMessage;
import bisq.common.proto.NetworkStorageWhiteList;
import bisq.network.p2p.message.NetworkMessageResolver;
Expand Down Expand Up @@ -78,6 +79,7 @@ public static void config() {
// Abstract classes
NetworkMessageResolver.addResolver("chat.ChatMessage", ChatMessage.getNetworkMessageResolver());
NetworkMessageResolver.addResolver("trade.TradeMessage", TradeMessage.getNetworkMessageResolver());
NetworkMessageResolver.addResolver("chat.ChatMessageReaction", ChatMessageReaction.getNetworkMessageResolver());

// Final classes
NetworkMessageResolver.addResolver("user.AuthorizeAccountAgeRequest", AuthorizeAccountAgeRequest.getNetworkMessageResolver());
Expand Down Expand Up @@ -113,6 +115,7 @@ public static void config() {
// ChatMessageReaction subclasses
NetworkStorageWhiteList.add(CommonPublicChatMessageReaction.class);
NetworkStorageWhiteList.add(BisqEasyOfferbookMessageReaction.class);
NetworkStorageWhiteList.add(TwoPartyPrivateChatMessageReaction.class);

// From network module. As it is used as mailbox message we add it here as well.
NetworkStorageWhiteList.add(AckMessage.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@
import bisq.chat.Citation;
import bisq.chat.bisqeasy.BisqEasyOfferMessage;
import bisq.chat.bisqeasy.offerbook.BisqEasyOfferbookMessage;
import bisq.chat.common.CommonPublicChatMessage;
import bisq.chat.priv.PrivateChatMessage;
import bisq.chat.pub.PublicChatChannel;
import bisq.chat.pub.PublicChatMessage;
import bisq.chat.reactions.ChatMessageReaction;
import bisq.chat.reactions.Reaction;
import bisq.common.locale.LanguageRepository;
Expand Down Expand Up @@ -183,9 +181,8 @@ public ChatMessageListItem(M chatMessage,

// TODO: Release all the listeners when destroying this object

if (shouldShowReactions()) {
PublicChatMessage publicChatMessage = (PublicChatMessage) chatMessage;
userReactionsPin = Optional.ofNullable(publicChatMessage.getChatMessageReactions().addObserver(new CollectionObserver<ChatMessageReaction>() {
if (chatMessage.canShowReactions()) {
userReactionsPin = Optional.ofNullable(chatMessage.getChatMessageReactions().addObserver(new CollectionObserver<>() {
@Override
public void add(ChatMessageReaction element) {
int reactionIdx = element.getReactionId();
Expand Down Expand Up @@ -398,12 +395,6 @@ public double getReputationStarCount() {
return reputationScoreDisplay.getNumberOfStars();
}

public boolean shouldShowReactions() {
return chatMessage instanceof PublicChatMessage
&& (chatMessage instanceof CommonPublicChatMessage
|| (chatMessage instanceof BisqEasyOfferMessage && !((BisqEasyOfferMessage) chatMessage).hasBisqEasyOffer()));
}

private boolean hasBisqEasyOfferWithDirection(Direction direction) {
if (chatMessage instanceof BisqEasyOfferMessage) {
BisqEasyOfferMessage bisqEasyOfferMessage = (BisqEasyOfferMessage) chatMessage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import bisq.chat.reactions.CommonPublicChatMessageReaction;
import bisq.chat.reactions.Reaction;
import bisq.chat.two_party.TwoPartyPrivateChatChannel;
import bisq.chat.two_party.TwoPartyPrivateChatMessage;
import bisq.common.observable.Pin;
import bisq.common.observable.collection.CollectionObserver;
import bisq.desktop.ServiceProvider;
Expand Down Expand Up @@ -438,21 +439,18 @@ public void doLeaveChannel() {
});
}

public void onReactMessage(ChatMessage chatMessage, Reaction reaction) {
checkArgument(chatMessage instanceof PublicChatMessage && (chatMessage instanceof CommonPublicChatMessage
|| (chatMessage instanceof BisqEasyOfferMessage && !((BisqEasyOfferMessage) chatMessage).hasBisqEasyOffer())),
"Not possible to react to a message of type %s.", chatMessage.getClass());
public void onReactMessage(ChatMessage chatMessage, Reaction reaction, ChatChannel<?> chatChannel) {
checkArgument(chatMessage.canShowReactions(), "Not possible to react to a message of type %s.", chatMessage.getClass());

UserIdentity userIdentity = userIdentityService.getSelectedUserIdentity();
PublicChatMessage publicChatMessage = (PublicChatMessage) chatMessage;
Optional<ChatMessageReaction> chatMessageReaction = publicChatMessage.getChatMessageReactions().stream()
Optional<ChatMessageReaction> chatMessageReaction = chatMessage.getChatMessageReactions().stream()
.filter(chatReaction -> Objects.equals(chatReaction.getUserProfileId(), userIdentity.getId())
&& chatReaction.getReactionId() == reaction.ordinal())
.findAny();

chatMessageReaction.ifPresentOrElse(
messageReaction -> deleteChatMessageReaction(messageReaction, userIdentity),
() -> publishChatMessageReaction(publicChatMessage, reaction, userIdentity));
() -> publishChatMessageReaction(chatMessage, reaction, userIdentity, chatChannel));
}

public void highlightOfferChatMessage(@Nullable ChatMessage message) {
Expand Down Expand Up @@ -635,13 +633,19 @@ public void clear() {
});
}

private void publishChatMessageReaction(PublicChatMessage chatMessage, Reaction reaction, UserIdentity userIdentity) {
private void publishChatMessageReaction(ChatMessage chatMessage, Reaction reaction, UserIdentity userIdentity,
ChatChannel<?> chatChannel) {
if (chatMessage instanceof CommonPublicChatMessage) {
chatService.getCommonPublicChatChannelServices().get(model.getChatChannelDomain())
.publishChatMessageReaction((CommonPublicChatMessage) chatMessage, reaction, userIdentity);
} else if (chatMessage instanceof BisqEasyOfferbookMessage) {
chatService.getBisqEasyOfferbookChannelService()
.publishChatMessageReaction((BisqEasyOfferbookMessage) chatMessage, reaction, userIdentity);
} else if (chatMessage instanceof TwoPartyPrivateChatMessage) {
checkArgument(chatChannel instanceof TwoPartyPrivateChatChannel, "Channel needs to be of type TwoPartyPrivateChatChannel.");
TwoPartyPrivateChatChannel channel = (TwoPartyPrivateChatChannel) chatChannel;
chatService.getTwoPartyPrivateChatChannelServices().get(model.getChatChannelDomain())
.sendTextMessageReaction((TwoPartyPrivateChatMessage) chatMessage, channel, reaction);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import bisq.chat.ChatMessage;
import bisq.chat.Citation;
import bisq.chat.bisqeasy.offerbook.BisqEasyOfferbookMessage;
import bisq.chat.common.CommonPublicChatMessage;
import bisq.chat.reactions.Reaction;
import bisq.desktop.common.threading.UIThread;
import bisq.desktop.common.utils.ClipboardUtil;
Expand Down Expand Up @@ -153,8 +152,8 @@ protected void setUpActions() {
}
});

reactMenu.setVisible(item.shouldShowReactions());
reactMenu.setManaged(item.shouldShowReactions());
reactMenu.setVisible(item.getChatMessage().canShowReactions());
reactMenu.setManaged(item.getChatMessage().canShowReactions());

HBox.setMargin(copyAction, ACTION_ITEMS_MARGIN);
HBox.setMargin(reactMenu, ACTION_ITEMS_MARGIN);
Expand Down Expand Up @@ -308,7 +307,7 @@ private void setUpReactMenu() {
}

private void toggleReaction(Reaction reaction) {
controller.onReactMessage(item.getChatMessage(), reaction);
controller.onReactMessage(item.getChatMessage(), reaction, item.getChatChannel());
reactMenu.hideMenu();
}
}
21 changes: 20 additions & 1 deletion chat/src/main/java/bisq/chat/ChatChannelService.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package bisq.chat;

import bisq.chat.reactions.ChatMessageReaction;
import bisq.common.application.Service;
import bisq.common.observable.collection.ObservableArray;
import bisq.network.NetworkService;
Expand Down Expand Up @@ -119,4 +120,22 @@ public Optional<C> getDefaultChannel() {
}

protected abstract String getChannelTitlePostFix(ChatChannel<? extends ChatMessage> chatChannel);
}

protected void addMessageReaction(ChatMessageReaction chatMessageReaction, M message) {
if (bannedUserService.isUserProfileBanned(chatMessageReaction.getUserProfileId())) {
log.warn("Reaction ignored as sender is banned.");
return;
}
synchronized (getPersistableStore()) {
message.getChatMessageReactions().add(chatMessageReaction);
}
persist();
}

protected void removeMessageReaction(ChatMessageReaction chatMessageReaction, M message) {
synchronized (getPersistableStore()) {
message.getChatMessageReactions().remove(chatMessageReaction);
}
persist();
}
}
10 changes: 9 additions & 1 deletion chat/src/main/java/bisq/chat/ChatMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
import bisq.chat.bisqeasy.offerbook.BisqEasyOfferbookMessage;
import bisq.chat.bisqeasy.open_trades.BisqEasyOpenTradeMessage;
import bisq.chat.common.CommonPublicChatMessage;
import bisq.chat.reactions.ChatMessageReaction;
import bisq.chat.two_party.TwoPartyPrivateChatMessage;
import bisq.common.observable.collection.ObservableSet;
import bisq.common.proto.NetworkProto;
import bisq.common.proto.ProtoResolver;
import bisq.common.proto.UnresolvableProtobufMessageException;
Expand Down Expand Up @@ -203,4 +205,10 @@ public boolean isMyMessage(UserIdentityService userIdentityService) {
public int compareTo(@Nonnull ChatMessage o) {
return id.compareTo(o.getId());
}
}

public abstract <R extends ChatMessageReaction> ObservableSet<R> getChatMessageReactions();

public boolean canShowReactions() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@

import bisq.chat.ChatChannelDomain;
import bisq.chat.Citation;
import bisq.chat.common.CommonPublicChatMessage;
import bisq.chat.pub.PublicChatChannel;
import bisq.chat.pub.PublicChatChannelService;
import bisq.chat.reactions.BisqEasyOfferbookMessageReaction;
import bisq.chat.reactions.CommonPublicChatMessageReaction;
import bisq.chat.reactions.Reaction;
import bisq.common.currency.Market;
import bisq.common.currency.MarketRepository;
import bisq.common.observable.collection.ObservableArray;
import bisq.common.util.StringUtils;
import bisq.network.NetworkService;
import bisq.network.p2p.services.data.storage.DistributedData;
import bisq.network.p2p.services.data.storage.auth.AuthenticatedData;
Expand Down Expand Up @@ -170,14 +169,13 @@ protected BisqEasyOfferbookMessageReaction createChatMessageReaction(BisqEasyOff
Reaction reaction,
UserIdentity userIdentity) {
return new BisqEasyOfferbookMessageReaction(
BisqEasyOfferbookMessageReaction.createId(message.getChannelId(),
message.getId(), reaction.ordinal(), userIdentity.getId()),
StringUtils.createUid(),
userIdentity.getId(),
message.getChannelId(),
message.getChatChannelDomain(),
message.getId(),
reaction.ordinal(),
System.currentTimeMillis());
new Date().getTime());
}

private void maybeAddPublicTradeChannel(BisqEasyOfferbookChannel channel) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public final class BisqEasyOfferbookMessage extends PublicChatMessage implements BisqEasyOfferMessage {
// Metadata needs to be symmetric with BisqEasyOfferbookMessageReaction.
@EqualsAndHashCode.Exclude
private final MetaData metaData = new MetaData(TTL_10_DAYS, LOW_PRIORITY, getClass().getSimpleName(), MAX_MAP_SIZE_10_000);
private final Optional<BisqEasyOffer> bisqEasyOffer;
Expand Down Expand Up @@ -132,4 +133,9 @@ public double getCostFactor() {
public boolean hasBisqEasyOffer() {
return bisqEasyOffer.isPresent();
}

@Override
public boolean canShowReactions() {
return bisqEasyOffer.isEmpty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Date;
import java.util.Optional;

Expand Down Expand Up @@ -110,7 +111,7 @@ private BisqEasyOpenTradeMessage(String tradeId,
ChatMessageType chatMessageType,
Optional<BisqEasyOffer> bisqEasyOffer) {
super(messageId, chatChannelDomain, channelId, senderUserProfile, receiverUserProfileId,
receiverNetworkId, text, citation, date, wasEdited, chatMessageType);
receiverNetworkId, text, citation, date, wasEdited, chatMessageType, new ArrayList<>());
this.tradeId = tradeId;
this.mediator = mediator;
this.bisqEasyOffer = bisqEasyOffer;
Expand All @@ -134,7 +135,8 @@ private BisqEasyOpenTradeMessage(String tradeId,
Optional.empty(),
new Date().getTime(),
false,
chatMessageType);
chatMessageType,
new ArrayList<>());
this.tradeId = tradeId;
this.mediator = mediator;
this.bisqEasyOffer = Optional.of(bisqEasyOffer);
Expand Down Expand Up @@ -199,5 +201,4 @@ public double getCostFactor() {
public boolean hasBisqEasyOffer() {
return bisqEasyOffer.isPresent();
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,12 @@ protected CommonPublicChatMessageReaction createChatMessageReaction(CommonPublic
Reaction reaction,
UserIdentity userIdentity) {
return new CommonPublicChatMessageReaction(
CommonPublicChatMessageReaction.createId(message.getChannelId(),
message.getId(), reaction.ordinal(), userIdentity.getId()),
StringUtils.createUid(),
userIdentity.getId(),
message.getChannelId(),
message.getChatChannelDomain(),
message.getId(),
reaction.ordinal(),
System.currentTimeMillis());
new Date().getTime());
}
}
14 changes: 10 additions & 4 deletions chat/src/main/java/bisq/chat/common/CommonPublicChatMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public final class CommonPublicChatMessage extends PublicChatMessage {
// Metadata needs to be symmetric with CommonPublicChatMessageReaction.
@EqualsAndHashCode.Exclude
private final MetaData metaData = new MetaData(TTL_10_DAYS, LOW_PRIORITY, getClass().getSimpleName(), MAX_MAP_SIZE_10_000);

Expand Down Expand Up @@ -100,9 +101,9 @@ private bisq.chat.protobuf.CommonPublicChatMessage.Builder getCommonPublicChatMe
}

public static CommonPublicChatMessage fromProto(bisq.chat.protobuf.ChatMessage baseProto) {
Optional<Citation> citation = baseProto.hasCitation() ?
Optional.of(Citation.fromProto(baseProto.getCitation())) :
Optional.empty();
Optional<Citation> citation = baseProto.hasCitation()
? Optional.of(Citation.fromProto(baseProto.getCitation()))
: Optional.empty();
return new CommonPublicChatMessage(
baseProto.getId(),
ChatChannelDomain.fromProto(baseProto.getChatChannelDomain()),
Expand All @@ -119,4 +120,9 @@ public static CommonPublicChatMessage fromProto(bisq.chat.protobuf.ChatMessage b
public double getCostFactor() {
return 0.3;
}
}

@Override
public boolean canShowReactions() {
return true;
}
}
Loading
Loading