From aa28b3897fe6f330b39b4002a72078d7adbb6289 Mon Sep 17 00:00:00 2001 From: Thilo Molitor Date: Fri, 13 Oct 2023 18:11:56 +0200 Subject: [PATCH 01/10] Ignore muc messages if we already have an 1:1 contact for this jid --- Monal/Classes/MLMessageProcessor.m | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Monal/Classes/MLMessageProcessor.m b/Monal/Classes/MLMessageProcessor.m index 0b0e7c7bc4..9ca0c08e02 100644 --- a/Monal/Classes/MLMessageProcessor.m +++ b/Monal/Classes/MLMessageProcessor.m @@ -233,10 +233,17 @@ +(MLMessage* _Nullable) processMessage:(XMPPMessage*) messageNode andOuterMessag DDLogVerbose(@"Not a carbon copy of a muc pm for contact: %@", carbonTestContact); } + NSString* possibleUnkownContact; + if([messageNode.fromUser isEqualToString:account.connectionProperties.identity.jid]) + possibleUnkownContact = messageNode.toUser; + else + possibleUnkownContact = messageNode.fromUser; + if(([messageNode check:@"/"] || [messageNode check:@"{http://jabber.org/protocol/muc#user}x"]) && ![messageNode check:@"{http://jabber.org/protocol/muc#user}x/invite"]) { - // Ignore all group chat msgs from unkown groups - if([[DataLayer sharedInstance] isContactInList:messageNode.fromUser forAccount:account.accountNo] == NO) + // Ignore all group chat msgs from unkown groups or 1:1 chats + MLContact* mucTestContact = [MLContact createContactFromJid:possibleUnkownContact andAccountNo:account.accountNo]; + if([[DataLayer sharedInstance] isContactInList:messageNode.fromUser forAccount:account.accountNo] == NO || !mucTestContact.isGroup) { // ignore message DDLogWarn(@"Ignoring groupchat message from %@", messageNode.toUser); @@ -245,12 +252,6 @@ +(MLMessage* _Nullable) processMessage:(XMPPMessage*) messageNode andOuterMessag } else { - NSString* possibleUnkownContact; - if([messageNode.fromUser isEqualToString:account.connectionProperties.identity.jid]) - possibleUnkownContact = messageNode.toUser; - else - possibleUnkownContact = messageNode.fromUser; - // handle KeyTransportMessages directly without adding a 1:1 buddy if([messageNode check:@"{eu.siacs.conversations.axolotl}encrypted/header"] == YES && [messageNode check:@"{eu.siacs.conversations.axolotl}encrypted/payload#"] == NO) { From 49708f2eba1285a64861ecdfa81f090c1dfaa5be Mon Sep 17 00:00:00 2001 From: lissine Date: Sat, 14 Oct 2023 16:19:37 +0100 Subject: [PATCH 02/10] Show the correct letter in own dummy profile pictures --- Monal/Classes/MLImageManager.m | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Monal/Classes/MLImageManager.m b/Monal/Classes/MLImageManager.m index 925254413b..97cc9543d4 100644 --- a/Monal/Classes/MLImageManager.m +++ b/Monal/Classes/MLImageManager.m @@ -7,6 +7,7 @@ // #import "MLImageManager.h" +#import "MLXMPPManager.h" #import "HelperTools.h" #import "DataLayer.h" #import "AESGcm.h" @@ -180,7 +181,16 @@ -(UIImage*) outboundImage -(UIImage*) generateDummyIconForContact:(MLContact*) contact { - NSString* contactLetter = [[[contact contactDisplayName] substringToIndex:1] uppercaseString]; + NSString* contactLetter; + + if(contact.isSelfChat) + { + xmpp* account = [[MLXMPPManager sharedInstance] getConnectedAccountForID:contact.accountId]; + contactLetter = [[[MLContact ownDisplayNameForAccount:account] substringToIndex:1] uppercaseString]; + } + else + contactLetter = [[[contact contactDisplayName] substringToIndex:1] uppercaseString]; + UIColor* background = [HelperTools generateColorFromJid:contact.contactJid]; UIColor* foreground = [UIColor blackColor]; if(![background isLightColor]) From 8a982e56e3122135d9c22ab41c083f23ee9279a7 Mon Sep 17 00:00:00 2001 From: lissine Date: Sat, 14 Oct 2023 17:31:16 +0100 Subject: [PATCH 03/10] Server details: fix XEP-0215 support status --- Monal/Classes/MLIQProcessor.m | 3 +++ Monal/Classes/MLServerDetails.m | 2 +- Monal/Classes/MLXMPPConnection.h | 1 + Monal/Classes/xmpp.m | 8 ++++++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Monal/Classes/MLIQProcessor.m b/Monal/Classes/MLIQProcessor.m index 6c79d880a2..ea1a63ffee 100644 --- a/Monal/Classes/MLIQProcessor.m +++ b/Monal/Classes/MLIQProcessor.m @@ -526,6 +526,9 @@ +(BOOL) processRosterWithAccount:(xmpp*) account andIqNode:(XMPPIQ*) iqNode if([features containsObject:@"urn:xmpp:ping"]) account.connectionProperties.supportsPing = YES; + if([features containsObject:@"urn:xmpp:extdisco:2"]) + account.connectionProperties.supportsExternalServiceDiscovery = YES; + if([features containsObject:@"urn:xmpp:blocking"]) { account.connectionProperties.supportsBlocking = YES; diff --git a/Monal/Classes/MLServerDetails.m b/Monal/Classes/MLServerDetails.m index 1b4dea7f9d..854765e697 100644 --- a/Monal/Classes/MLServerDetails.m +++ b/Monal/Classes/MLServerDetails.m @@ -85,7 +85,7 @@ -(void) checkServerCaps:(MLXMPPConnection*) connection [self.serverCaps addObject:@{ @"Title":NSLocalizedString(@"XEP-0215: External Service Discovery", @""), @"Description":NSLocalizedString(@"XMPP protocol extension for discovering services external to the XMPP network, like STUN or TURN servers needed for A/V calls.", @""), - @"Color": connection.supportsPing ? @"Green" : @"Red" + @"Color": connection.supportsExternalServiceDiscovery ? @"Green" : @"Red" }]; // supportsRosterVersion diff --git a/Monal/Classes/MLXMPPConnection.h b/Monal/Classes/MLXMPPConnection.h index bf2202c5d9..75856aca68 100644 --- a/Monal/Classes/MLXMPPConnection.h +++ b/Monal/Classes/MLXMPPConnection.h @@ -54,6 +54,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) BOOL supportsBlocking; @property (nonatomic, assign) BOOL supportsPing; +@property (nonatomic, assign) BOOL supportsExternalServiceDiscovery; @property (nonatomic, assign) BOOL supportsPubSub; @property (nonatomic, assign) BOOL supportsPubSubMax; @property (nonatomic, assign) BOOL supportsModernPubSub; diff --git a/Monal/Classes/xmpp.m b/Monal/Classes/xmpp.m index dafffa7ac5..e31ad83a31 100644 --- a/Monal/Classes/xmpp.m +++ b/Monal/Classes/xmpp.m @@ -3333,6 +3333,7 @@ -(void) realPersistState [values setObject:[NSNumber numberWithBool:self.connectionProperties.supportsModernPubSub] forKey:@"supportsModernPubSub"]; [values setObject:[NSNumber numberWithBool:self.connectionProperties.supportsHTTPUpload] forKey:@"supportsHTTPUpload"]; [values setObject:[NSNumber numberWithBool:self.connectionProperties.supportsPing] forKey:@"supportsPing"]; + [values setObject:[NSNumber numberWithBool:self.connectionProperties.supportsExternalServiceDiscovery] forKey:@"supportsExternalServiceDiscovery"]; [values setObject:[NSNumber numberWithBool:self.connectionProperties.supportsRosterPreApproval] forKey:@"supportsRosterPreApproval"]; [values setObject:[NSNumber numberWithBool:self.connectionProperties.supportsBlocking] forKey:@"supportsBlocking"]; [values setObject:[NSNumber numberWithBool:self.connectionProperties.accountDiscoDone] forKey:@"accountDiscoDone"]; @@ -3531,6 +3532,12 @@ -(void) realReadState self.connectionProperties.supportsPing = supportsPing.boolValue; } + if([dic objectForKey:@"supportsExternalServiceDiscovery"]) + { + NSNumber* supportsExternalServiceDiscovery = [dic objectForKey:@"supportsExternalServiceDiscovery"]; + self.connectionProperties.supportsExternalServiceDiscovery = supportsExternalServiceDiscovery.boolValue; + } + if([dic objectForKey:@"lastInteractionDate"]) _lastInteractionDate = [dic objectForKey:@"lastInteractionDate"]; @@ -3826,6 +3833,7 @@ -(void) initSession self.connectionProperties.supportsModernPubSub = NO; self.connectionProperties.supportsHTTPUpload = NO; self.connectionProperties.supportsPing = NO; + self.connectionProperties.supportsExternalServiceDiscovery = NO; self.connectionProperties.supportsRosterPreApproval = NO; //clear list of running mam queries From 5063da2b6075333999183692fa8c145a5a1eedab Mon Sep 17 00:00:00 2001 From: lissine Date: Sat, 14 Oct 2023 18:43:10 +0100 Subject: [PATCH 04/10] Server details: sort features by XEP number --- Monal/Classes/MLServerDetails.m | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Monal/Classes/MLServerDetails.m b/Monal/Classes/MLServerDetails.m index 854765e697..5a43557321 100644 --- a/Monal/Classes/MLServerDetails.m +++ b/Monal/Classes/MLServerDetails.m @@ -60,6 +60,14 @@ - (void)didReceiveMemoryWarning { -(void) checkServerCaps:(MLXMPPConnection*) connection { + // supportsPubSub + [self.serverCaps addObject:@{ + // see MLIQProcessor.m multiple xep required for pubsub + @"Title":NSLocalizedString(@"XEP-0163 Personal Eventing Protocol", @""), + @"Description":NSLocalizedString(@"This specification defines semantics for using the XMPP publish-subscribe protocol to broadcast state change events associated with an instant messaging and presence account.", @""), + @"Color": connection.supportsPubSub ? (connection.supportsModernPubSub ? @"Green" : @"Yellow") : @"Red" + }]; + // supportsBlocking [self.serverCaps addObject:@{ @"Title":NSLocalizedString(@"XEP-0191: Blocking Command", @""), @@ -137,14 +145,6 @@ -(void) checkServerCaps:(MLXMPPConnection*) connection @"Color": connection.supportsRosterPreApproval ? @"Green" : @"Red" }]; - // supportsPubSub - [self.serverCaps addObject:@{ - // see MLIQProcessor.m multiple xep required for pubsub - @"Title":NSLocalizedString(@"XEP-0163 Personal Eventing Protocol", @""), - @"Description":NSLocalizedString(@"This specification defines semantics for using the XMPP publish-subscribe protocol to broadcast state change events associated with an instant messaging and presence account.", @""), - @"Color": connection.supportsPubSub ? (connection.supportsModernPubSub ? @"Green" : @"Yellow") : @"Red" - }]; - // supportsSSDP [self.serverCaps addObject:@{ // see MLIQProcessor.m multiple xep required for pubsub From 8c6eec0d1d2e554f5791138b81896784002351fc Mon Sep 17 00:00:00 2001 From: lissine Date: Sat, 14 Oct 2023 22:01:03 +0100 Subject: [PATCH 05/10] http-file-upload: use the latest namespace when getting max-file-size This fixes Monal's reported maximum file size being zero, for servers that don't advertise support for the old namespace. Tested working with Prosody, Ejabberd, Openfire and Tigase. --- Monal/Classes/MLIQProcessor.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Monal/Classes/MLIQProcessor.m b/Monal/Classes/MLIQProcessor.m index ea1a63ffee..8265fed37c 100644 --- a/Monal/Classes/MLIQProcessor.m +++ b/Monal/Classes/MLIQProcessor.m @@ -540,7 +540,7 @@ +(BOOL) processRosterWithAccount:(xmpp*) account andIqNode:(XMPPIQ*) iqNode DDLogInfo(@"supports http upload with server: %@", iqNode.from); account.connectionProperties.supportsHTTPUpload = YES; account.connectionProperties.uploadServer = iqNode.from; - account.connectionProperties.uploadSize = [[iqNode findFirst:@"{http://jabber.org/protocol/disco#info}query/\\{urn:xmpp:http:upload}result@max-file-size\\|int"] integerValue]; + account.connectionProperties.uploadSize = [[iqNode findFirst:@"{http://jabber.org/protocol/disco#info}query/\\{urn:xmpp:http:upload:0}result@max-file-size\\|int"] integerValue]; DDLogInfo(@"Upload max filesize: %lu", account.connectionProperties.uploadSize); } $$ @@ -553,7 +553,7 @@ +(BOOL) processRosterWithAccount:(xmpp*) account andIqNode:(XMPPIQ*) iqNode DDLogInfo(@"supports http upload with server: %@", iqNode.from); account.connectionProperties.supportsHTTPUpload = YES; account.connectionProperties.uploadServer = iqNode.from; - account.connectionProperties.uploadSize = [[iqNode findFirst:@"{http://jabber.org/protocol/disco#info}query/\\{urn:xmpp:http:upload}result@max-file-size\\|int"] integerValue]; + account.connectionProperties.uploadSize = [[iqNode findFirst:@"{http://jabber.org/protocol/disco#info}query/\\{urn:xmpp:http:upload:0}result@max-file-size\\|int"] integerValue]; DDLogInfo(@"Upload max filesize: %lu", account.connectionProperties.uploadSize); } From 492e11cc31f92d1338d6e9ee544af2838fd69036 Mon Sep 17 00:00:00 2001 From: lissine Date: Sun, 15 Oct 2023 21:03:28 +0100 Subject: [PATCH 06/10] Contact details: update wording mostly improvements when viewing details of an MUC --- Monal/Classes/BackgroundSettings.swift | 2 +- Monal/Classes/ContactDetails.swift | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Monal/Classes/BackgroundSettings.swift b/Monal/Classes/BackgroundSettings.swift index f5bd3ad035..bbb0985c9f 100644 --- a/Monal/Classes/BackgroundSettings.swift +++ b/Monal/Classes/BackgroundSettings.swift @@ -125,7 +125,7 @@ struct BackgroundSettings: View { } } } - .navigationBarTitle(contact != nil ? Text("Contact Background") : Text("Default Background")) + .navigationBarTitle(contact != nil ? Text("Chat Background") : Text("Default Background")) .onChange(of:inputImage) { _ in MLImageManager.sharedInstance().saveBackgroundImageData(inputImage?.pngData(), for:self.contact?.obj) } diff --git a/Monal/Classes/ContactDetails.swift b/Monal/Classes/ContactDetails.swift index 31a3685489..32c5177399 100644 --- a/Monal/Classes/ContactDetails.swift +++ b/Monal/Classes/ContactDetails.swift @@ -49,18 +49,15 @@ struct ContactDetails: View { if(contact.isMuted) { Image(systemName: "bell.slash.fill") .foregroundColor(.red) - Text("Contact is muted") - .foregroundColor(.accentColor) + contact.isGroup ? Text("Notifications disabled") : Text("Contact is muted") } else if(contact.isGroup && contact.isMentionOnly) { Image(systemName: "bell.badge") .foregroundColor(.accentColor) - Text("Group/Channel is mention only") - .foregroundColor(.accentColor) + Text("Notify only when mentioned") } else { Image(systemName: "bell.fill") .foregroundColor(.green) - Text("Contact is not muted") - .foregroundColor(.accentColor) + contact.isGroup ? Text("Notify on all messages") : Text("Contact is not muted") } } } @@ -115,7 +112,7 @@ struct ContactDetails: View { #endif if(!contact.isGroup && !contact.isSelfChat) { - TextField("Change Nickname", text: $contact.nickNameView) + TextField("Rename Contact", text: $contact.nickNameView) .textFieldStyle(RoundedBorderTextFieldStyle()) .addClearButton(text:$contact.nickNameView) } @@ -157,7 +154,7 @@ struct ContactDetails: View { } NavigationLink(destination: LazyClosureView(BackgroundSettings(contact:contact, delegate:delegate))) { - Text("Change Contact Background") + Text("Change Chat Background") } } .listStyle(.plain) From f89b8c2bdce353fa5b1b5f51b38ed8c2528d7aff Mon Sep 17 00:00:00 2001 From: lissine Date: Sun, 15 Oct 2023 21:20:33 +0100 Subject: [PATCH 07/10] Drop `Block Contact` button from MUC details view --- Monal/Classes/ContactDetails.swift | 60 +++++++++++++++--------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/Monal/Classes/ContactDetails.swift b/Monal/Classes/ContactDetails.swift index 32c5177399..cb59cef99d 100644 --- a/Monal/Classes/ContactDetails.swift +++ b/Monal/Classes/ContactDetails.swift @@ -161,37 +161,39 @@ struct ContactDetails: View { Section { // the destructive section... if !contact.isSelfChat { - Button(action: { - if(!contact.isBlocked) { - showingBlockContactConfirmation = true - } else { - showingCannotBlockAlert = !contact.obj.toggleBlocked(!contact.isBlocked) + if !contact.isGroup { + Button(action: { + if(!contact.isBlocked) { + showingBlockContactConfirmation = true + } else { + showingCannotBlockAlert = !contact.obj.toggleBlocked(!contact.isBlocked) + } + }) { + if(!contact.isBlocked) { + Text("Block Contact") + .foregroundColor(.red) + } else { + Text("Unblock Contact") + } } - }) { - if(!contact.isBlocked) { - Text("Block Contact") - .foregroundColor(.red) - } else { - Text("Unblock Contact") + .alert(isPresented: $showingCannotBlockAlert) { + Alert(title: Text("Blocking/Unblocking Not Supported"), message: Text("The server does not support blocking (XEP-0191)."), dismissButton: .default(Text("Close"))) + } + .actionSheet(isPresented: $showingBlockContactConfirmation) { + ActionSheet( + title: Text("Block Contact"), + message: Text("Do you really want to block this contact? You won't receive any messages from this contact."), + buttons: [ + .cancel(), + .destructive( + Text("Yes"), + action: { + showingCannotBlockAlert = !contact.obj.toggleBlocked(!contact.isBlocked) + } + ) + ] + ) } - } - .alert(isPresented: $showingCannotBlockAlert) { - Alert(title: Text("Blocking/Unblocking Not Supported"), message: Text("The server does not support blocking (XEP-0191)."), dismissButton: .default(Text("Close"))) - } - .actionSheet(isPresented: $showingBlockContactConfirmation) { - ActionSheet( - title: Text("Block Contact"), - message: Text("Do you really want to block this contact? You won't receive any messages from this contact."), - buttons: [ - .cancel(), - .destructive( - Text("Yes"), - action: { - showingCannotBlockAlert = !contact.obj.toggleBlocked(!contact.isBlocked) - } - ) - ] - ) } Group { From 18c9f7ff4e63e2fd09e1001764dad4adc5bc304d Mon Sep 17 00:00:00 2001 From: lissine Date: Sun, 15 Oct 2023 23:11:10 +0100 Subject: [PATCH 08/10] Contact Details: make profile pictures a bit smaller --- Monal/Classes/ContactDetailsHeader.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Monal/Classes/ContactDetailsHeader.swift b/Monal/Classes/ContactDetailsHeader.swift index 4f9af126c4..c657df9b09 100644 --- a/Monal/Classes/ContactDetailsHeader.swift +++ b/Monal/Classes/ContactDetailsHeader.swift @@ -22,7 +22,7 @@ struct ContactDetailsHeader: View { Spacer() Image(uiImage: contact.avatar) .resizable() - .frame(minWidth: 100, idealWidth: 150, maxWidth: 200, minHeight: 100, idealHeight: 150, maxHeight: 200, alignment: .center) + .frame(width: 150, height: 150, alignment: .center) .scaledToFit() .shadow(radius: 7) Spacer() From cf93c7d39f987fef6a0ffe847de830eb49024f9b Mon Sep 17 00:00:00 2001 From: lissine Date: Sun, 15 Oct 2023 23:36:21 +0100 Subject: [PATCH 09/10] Don't scroll down the chat view after using ImageViewer in full screen. --- Monal/Classes/chatViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Monal/Classes/chatViewController.m b/Monal/Classes/chatViewController.m index fd47eac18a..a115264390 100644 --- a/Monal/Classes/chatViewController.m +++ b/Monal/Classes/chatViewController.m @@ -2335,7 +2335,7 @@ -(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath if([info[@"mimeType"] hasPrefix:@"image/gif"]) animatedImageData = [NSData dataWithContentsOfFile:info[@"cacheFile"]]; UIViewController* imageViewer = [[SwiftuiInterface new] makeImageViewer:image withFilename:info[@"filename"] andAnimatedImageData:animatedImageData]; - imageViewer.modalPresentationStyle = UIModalPresentationFullScreen; + imageViewer.modalPresentationStyle = UIModalPresentationOverFullScreen; [self presentViewController:imageViewer animated:YES completion:^{}]; }); } From dc54e57935364fea13f8f6f2f755e5f6e142441c Mon Sep 17 00:00:00 2001 From: Friedrich Altheide <11352905+FriedrichAltheide@users.noreply.github.com> Date: Mon, 16 Oct 2023 17:58:27 +0200 Subject: [PATCH 10/10] Revert "Drop `Block Contact` button from MUC details view" This reverts commit f89b8c2bdce353fa5b1b5f51b38ed8c2528d7aff. --- Monal/Classes/ContactDetails.swift | 60 +++++++++++++++--------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/Monal/Classes/ContactDetails.swift b/Monal/Classes/ContactDetails.swift index cb59cef99d..32c5177399 100644 --- a/Monal/Classes/ContactDetails.swift +++ b/Monal/Classes/ContactDetails.swift @@ -161,40 +161,38 @@ struct ContactDetails: View { Section { // the destructive section... if !contact.isSelfChat { - if !contact.isGroup { - Button(action: { - if(!contact.isBlocked) { - showingBlockContactConfirmation = true - } else { - showingCannotBlockAlert = !contact.obj.toggleBlocked(!contact.isBlocked) - } - }) { - if(!contact.isBlocked) { - Text("Block Contact") - .foregroundColor(.red) - } else { - Text("Unblock Contact") - } - } - .alert(isPresented: $showingCannotBlockAlert) { - Alert(title: Text("Blocking/Unblocking Not Supported"), message: Text("The server does not support blocking (XEP-0191)."), dismissButton: .default(Text("Close"))) + Button(action: { + if(!contact.isBlocked) { + showingBlockContactConfirmation = true + } else { + showingCannotBlockAlert = !contact.obj.toggleBlocked(!contact.isBlocked) } - .actionSheet(isPresented: $showingBlockContactConfirmation) { - ActionSheet( - title: Text("Block Contact"), - message: Text("Do you really want to block this contact? You won't receive any messages from this contact."), - buttons: [ - .cancel(), - .destructive( - Text("Yes"), - action: { - showingCannotBlockAlert = !contact.obj.toggleBlocked(!contact.isBlocked) - } - ) - ] - ) + }) { + if(!contact.isBlocked) { + Text("Block Contact") + .foregroundColor(.red) + } else { + Text("Unblock Contact") } } + .alert(isPresented: $showingCannotBlockAlert) { + Alert(title: Text("Blocking/Unblocking Not Supported"), message: Text("The server does not support blocking (XEP-0191)."), dismissButton: .default(Text("Close"))) + } + .actionSheet(isPresented: $showingBlockContactConfirmation) { + ActionSheet( + title: Text("Block Contact"), + message: Text("Do you really want to block this contact? You won't receive any messages from this contact."), + buttons: [ + .cancel(), + .destructive( + Text("Yes"), + action: { + showingCannotBlockAlert = !contact.obj.toggleBlocked(!contact.isBlocked) + } + ) + ] + ) + } Group { if(contact.isInRoster) {