29
29
import bisq .chat .Citation ;
30
30
import bisq .chat .bisq_easy .BisqEasyOfferMessage ;
31
31
import bisq .chat .bisq_easy .offerbook .BisqEasyOfferbookMessage ;
32
+ import bisq .chat .bisq_easy .open_trades .BisqEasyOpenTradeMessage ;
32
33
import bisq .chat .priv .PrivateChatMessage ;
33
34
import bisq .chat .pub .PublicChatChannel ;
34
35
import bisq .chat .reactions .ChatMessageReaction ;
35
36
import bisq .chat .reactions .Reaction ;
36
37
import bisq .common .currency .Market ;
37
38
import bisq .common .data .Pair ;
39
+ import bisq .common .data .Triple ;
38
40
import bisq .common .locale .LanguageRepository ;
39
41
import bisq .common .observable .Observable ;
40
42
import bisq .common .observable .Pin ;
50
52
import bisq .i18n .Res ;
51
53
import bisq .network .NetworkService ;
52
54
import bisq .network .identity .NetworkId ;
55
+ import bisq .network .p2p .services .confidential .ack .AckRequestingMessage ;
53
56
import bisq .network .p2p .services .confidential .ack .MessageDeliveryStatus ;
54
57
import bisq .network .p2p .services .confidential .resend .ResendMessageService ;
55
58
import bisq .offer .Direction ;
73
76
import javafx .beans .property .BooleanProperty ;
74
77
import javafx .beans .property .SimpleBooleanProperty ;
75
78
import javafx .beans .property .SimpleObjectProperty ;
76
- import javafx .scene .Node ;
77
- import javafx .scene .control .Label ;
78
79
import javafx .scene .image .ImageView ;
79
80
import lombok .EqualsAndHashCode ;
80
81
import lombok .Getter ;
@@ -108,17 +109,14 @@ public final class ChatMessageListItem<M extends ChatMessage, C extends ChatChan
108
109
private final ReputationScore reputationScore ;
109
110
private final ReputationScoreDisplay reputationScoreDisplay = new ReputationScoreDisplay ();
110
111
private final boolean offerAlreadyTaken ;
111
- @ Nullable
112
- private String messageId ;
113
112
private final MarketPriceService marketPriceService ;
114
113
private final UserIdentityService userIdentityService ;
115
114
private final BooleanProperty showHighlighted = new SimpleBooleanProperty ();
116
115
117
116
// Delivery status
118
117
private final Set <Pin > mapPins = new HashSet <>();
119
118
private final Set <Pin > statusPins = new HashSet <>();
120
- private final BooleanProperty shouldShowTryAgain = new SimpleBooleanProperty ();
121
- private final SimpleObjectProperty <Node > messageDeliveryStatusNode = new SimpleObjectProperty <>();
119
+ private final SimpleObjectProperty <Map <String , Triple <MessageDeliveryStatus , String , Boolean >>> messageDeliveryStatusByPeerProfileId = new SimpleObjectProperty <>();
122
120
private final Optional <ResendMessageService > resendMessageService ;
123
121
private ImageView successfulDeliveryIcon , connectingDeliveryIcon , pendingDeliveryIcon , addedToMailboxIcon , failedDeliveryIcon ;
124
122
private BisqMenuItem tryAgainMenuItem ;
@@ -349,9 +347,30 @@ private void initializeDeliveryStatusIcons() {
349
347
private void addSubscriptionToMessageDeliveryStatus (NetworkService networkService ) {
350
348
mapPins .add (networkService .getMessageDeliveryStatusByMessageId ().addObserver (new HashMapObserver <>() {
351
349
@ Override
352
- public void put (String messageId , Observable <MessageDeliveryStatus > value ) {
353
- if (messageId .equals (chatMessage .getId ())) {
354
- updateMessageStatus (messageId , value );
350
+ public void put (String ackRequestingMessageId , Observable <MessageDeliveryStatus > value ) {
351
+ if (chatMessage instanceof AckRequestingMessage ackRequestingMessage ) {
352
+ String messageId = ackRequestingMessageId ;
353
+ String chatMessageId = ackRequestingMessage .getAckRequestingMessageId ();
354
+ String peersProfileId = null ;
355
+ String separator = BisqEasyOpenTradeMessage .ACK_REQUESTING_MESSAGE_ID_SEPARATOR ;
356
+ if (chatMessage instanceof BisqEasyOpenTradeMessage bisqEasyOpenTradeMessage ) {
357
+ // In case of a bisqEasyOpenTradeMessage we use the message id and receiver id separated with a '_'.
358
+ // This allows us to handle the ACK messages separately to know when the message was received by
359
+ // both the peer and the mediator (in case of mediation).
360
+ if (messageId .contains (separator )) {
361
+ String [] parts = messageId .split (separator );
362
+ messageId = parts [0 ];
363
+ peersProfileId = parts [1 ];
364
+ }
365
+ if (chatMessageId .contains (separator )) {
366
+ String [] parts = chatMessageId .split (separator );
367
+ chatMessageId = parts [0 ];
368
+ }
369
+ }
370
+
371
+ if (messageId .equals (chatMessageId )) {
372
+ updateMessageStatus (ackRequestingMessageId , value , peersProfileId );
373
+ }
355
374
}
356
375
}
357
376
@@ -370,39 +389,20 @@ public void clear() {
370
389
}));
371
390
}
372
391
373
- private void updateMessageStatus (String messageId , Observable <MessageDeliveryStatus > value ) {
392
+ private void updateMessageStatus (String ackRequestingMessageId ,
393
+ Observable <MessageDeliveryStatus > value ,
394
+ @ Nullable String peersProfileId ) {
374
395
// Delay to avoid ConcurrentModificationException
375
396
UIThread .runOnNextRenderFrame (() -> statusPins .add (value .addObserver (status -> UIThread .run (() -> {
376
- ChatMessageListItem .this .messageId = messageId ;
377
- boolean shouldShowTryAgain = false ;
378
- if (status != null ) {
379
- Label statusLabel = new Label ();
380
- statusLabel .setTooltip (new BisqTooltip (Res .get ("chat.message.deliveryState." + status .name ())));
381
- switch (status ) {
382
- // Successful delivery
383
- case ACK_RECEIVED :
384
- case MAILBOX_MSG_RECEIVED :
385
- statusLabel .setGraphic (successfulDeliveryIcon );
386
- break ;
387
- // Pending delivery
388
- case CONNECTING :
389
- statusLabel .setGraphic (connectingDeliveryIcon );
390
- break ;
391
- case SENT :
392
- case TRY_ADD_TO_MAILBOX :
393
- statusLabel .setGraphic (pendingDeliveryIcon );
394
- break ;
395
- case ADDED_TO_MAILBOX :
396
- statusLabel .setGraphic (addedToMailboxIcon );
397
- break ;
398
- case FAILED :
399
- statusLabel .setGraphic (failedDeliveryIcon );
400
- shouldShowTryAgain = resendMessageService .map (service -> service .canManuallyResendMessage (messageId )).orElse (false );
401
- break ;
402
- }
403
- messageDeliveryStatusNode .set (statusLabel );
397
+ Map <String , Triple <MessageDeliveryStatus , String , Boolean >> map = messageDeliveryStatusByPeerProfileId .get ();
398
+ if (map == null ) {
399
+ map = new HashMap <>();
404
400
}
405
- this .shouldShowTryAgain .set (shouldShowTryAgain );
401
+ boolean canManuallyResendMessage = status == MessageDeliveryStatus .FAILED &&
402
+ resendMessageService .map (service -> service .canManuallyResendMessage (ackRequestingMessageId )).orElse (false );
403
+ map .put (peersProfileId , new Triple <>(status , ackRequestingMessageId , canManuallyResendMessage ));
404
+ messageDeliveryStatusByPeerProfileId .set (null ); // trigger update by setting it to null
405
+ messageDeliveryStatusByPeerProfileId .set (map );
406
406
}))));
407
407
}
408
408
0 commit comments