From 68d30293ff43942113176078809aeed08813c7b3 Mon Sep 17 00:00:00 2001 From: Thilo Molitor Date: Sat, 9 Nov 2024 04:40:19 +0100 Subject: [PATCH] Revert "6.4.6-rc1" --- Monal/Classes/ActiveChatsViewController.h | 2 +- Monal/Classes/ActiveChatsViewController.m | 19 ++------ Monal/Classes/HelperTools.m | 4 -- Monal/Classes/MLDelayableTimer.m | 27 +---------- Monal/Classes/MLMessageProcessor.m | 46 ++++--------------- Monal/Classes/MLStream.m | 12 +++-- Monal/Classes/MonalAppDelegate.m | 8 ++-- Monal/Classes/NotificationDebugging.swift | 14 +----- Monal/Classes/chatViewController.m | 3 +- .../NotificationService/NotificationService.m | 2 - 10 files changed, 30 insertions(+), 107 deletions(-) diff --git a/Monal/Classes/ActiveChatsViewController.h b/Monal/Classes/ActiveChatsViewController.h index 1f24caf553..0cab6291e6 100644 --- a/Monal/Classes/ActiveChatsViewController.h +++ b/Monal/Classes/ActiveChatsViewController.h @@ -24,8 +24,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, weak) IBOutlet UIBarButtonItem* settingsButton; @property (weak, nonatomic) IBOutlet UIBarButtonItem* spinnerButton; @property (nonatomic, weak) IBOutlet UIBarButtonItem* composeButton; +@property (nonatomic, strong) chatViewController* currentChatViewController; @property (nonatomic, strong) UIActivityIndicatorView* spinner; -@property (atomic, readonly) chatViewController* _Nullable currentChatView; -(void) showCallContactNotFoundAlert:(NSString*) jid; -(void) callContact:(MLContact*) contact withUIKitSender:(_Nullable id) sender; diff --git a/Monal/Classes/ActiveChatsViewController.m b/Monal/Classes/ActiveChatsViewController.m index 31bb7ec756..b9628b7f1a 100755 --- a/Monal/Classes/ActiveChatsViewController.m +++ b/Monal/Classes/ActiveChatsViewController.m @@ -361,13 +361,13 @@ -(void) refreshDisplay dispatch_async(dispatch_get_main_queue(), ^{ //make sure we don't display a chat view for a disabled account - if([MLNotificationManager sharedInstance].currentContact != nil) + if(self.currentChatViewController != nil && self.currentChatViewController.contact != nil) { BOOL found = NO; for(NSDictionary* accountDict in [[DataLayer sharedInstance] enabledAccountList]) { - NSNumber* accountID = accountDict[kAccountID]; - if([MLNotificationManager sharedInstance].currentContact.accountID.intValue == accountID.intValue) + NSNumber* accountNo = accountDict[kAccountID]; + if(self.currentChatViewController.contact.accountId.intValue == accountNo.intValue) found = YES; } if(!found) @@ -879,7 +879,6 @@ -(void) presentSplitPlaceholder UIViewController* detailsViewController = [[SwiftuiInterface new] makeViewWithName:@"ChatPlaceholder"]; [self showDetailViewController:detailsViewController sender:self]; } - [MLNotificationManager sharedInstance].currentContact = nil; } -(void) showNotificationSettings @@ -1095,6 +1094,7 @@ -(void) prepareForSegue:(UIStoryboardSegue*) segue sender:(id) sender UIBarButtonItem* barButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil]; self.navigationItem.backBarButtonItem = barButtonItem; [chatVC setupWithContact:sender]; + self.currentChatViewController = chatVC; } else if([segue.identifier isEqualToString:@"showDetails"]) { @@ -1513,17 +1513,6 @@ -(void) dismissRecursorWithViewControllers:(NSMutableArray*) viewControllers ani } } --(chatViewController* _Nullable) currentChatView -{ - NSArray* controllers = ((UINavigationController*)self.splitViewController.viewControllers[0]).viewControllers; - chatViewController* chatView = nil; - if(controllers.count > 1) - chatView = [((UINavigationController*)controllers[1]).viewControllers firstObject]; - if(![chatView isKindOfClass:NSClassFromString(@"chatViewController")]) - chatView = nil; - return chatView; -} - -(void) scrollToContact:(MLContact*) contact { __block NSIndexPath* indexPath = nil; diff --git a/Monal/Classes/HelperTools.m b/Monal/Classes/HelperTools.m index aac8558eb3..6c1fcb886f 100644 --- a/Monal/Classes/HelperTools.m +++ b/Monal/Classes/HelperTools.m @@ -2352,12 +2352,8 @@ +(NSString*) encodeRandomResource u_int32_t i=arc4random(); #if TARGET_OS_MACCATALYST NSString* resource = [NSString stringWithFormat:@"Monal-macOS.%@", [self hexadecimalString:[NSData dataWithBytes: &i length: sizeof(i)]]]; -#else -#if IS_QUICKSY - NSString* resource = [NSString stringWithFormat:@"Quicksy-iOS.%@", [self hexadecimalString:[NSData dataWithBytes: &i length: sizeof(i)]]]; #else NSString* resource = [NSString stringWithFormat:@"Monal-iOS.%@", [self hexadecimalString:[NSData dataWithBytes: &i length: sizeof(i)]]]; -#endif #endif return resource; } diff --git a/Monal/Classes/MLDelayableTimer.m b/Monal/Classes/MLDelayableTimer.m index ad7dceefca..bf3ed5e691 100644 --- a/Monal/Classes/MLDelayableTimer.m +++ b/Monal/Classes/MLDelayableTimer.m @@ -52,10 +52,7 @@ -(void) start return; } DDLogDebug(@"Starting timer: %@", self); - //scheduling and unscheduling of a timer must be done from the same thread --> use our runloop - [self scheduleBlockInRunLoop:^{ - [[HelperTools getExtraRunloopWithIdentifier:MLRunLoopIdentifierTimer] addTimer:self->_wrappedTimer forMode:NSRunLoopCommonModes]; - }]; + [[HelperTools getExtraRunloopWithIdentifier:MLRunLoopIdentifierTimer] addTimer:_wrappedTimer forMode:NSRunLoopCommonModes]; } } @@ -134,28 +131,8 @@ -(void) invalidate return; } //DDLogVerbose(@"Invalidating timer: %@", self); - //scheduling and unscheduling of a timer must be done from the same thread --> use our runloop - [self scheduleBlockInRunLoop:^{ - [self->_wrappedTimer invalidate]; - }]; + [_wrappedTimer invalidate]; } } --(void) scheduleBlockInRunLoop:(monal_void_block_t) block -{ - NSRunLoop* runLoop = [HelperTools getExtraRunloopWithIdentifier:MLRunLoopIdentifierTimer]; -// NSCondition* condition = [NSCondition new]; -// [condition lock]; - CFRunLoopPerformBlock([runLoop getCFRunLoop], (__bridge CFStringRef)NSDefaultRunLoopMode, ^{ - block(); -// [condition lock]; -// [condition signal]; -// [condition unlock]; - }); - CFRunLoopWakeUp([runLoop getCFRunLoop]); //trigger wakeup of runloop to execute the block as soon as possible -// //wait for our block to finish executing -// [condition wait]; -// [condition unlock]; -} - @end diff --git a/Monal/Classes/MLMessageProcessor.m b/Monal/Classes/MLMessageProcessor.m index ead09d4415..b7059261ed 100644 --- a/Monal/Classes/MLMessageProcessor.m +++ b/Monal/Classes/MLMessageProcessor.m @@ -124,7 +124,7 @@ +(MLMessage* _Nullable) processMessage:(XMPPMessage*) messageNode andOuterMessag } //ignore messages from our own device, see this github issue: https://github.com/monal-im/Monal/issues/941 - if(!isMLhistory && [messageNode.from isEqualToString:account.connectionProperties.identity.fullJid] && [messageNode.toUser isEqualToString:account.connectionProperties.identity.jid]) + if(![messageNode check:@"/"] && !isMLhistory && [messageNode.from isEqualToString:account.connectionProperties.identity.fullJid] && [messageNode.toUser isEqualToString:account.connectionProperties.identity.jid]) return nil; //handle incoming jmi calls (TODO: add entry to local history, once the UI for this is implemented) @@ -207,10 +207,8 @@ +(MLMessage* _Nullable) processMessage:(XMPPMessage*) messageNode andOuterMessag //ignore muc PMs (after discussion with holger we don't want to support that) if( - ![messageNode check:@"/"] && - [messageNode check:@"{http://jabber.org/protocol/muc#user}x"] && - ![messageNode check:@"{http://jabber.org/protocol/muc#user}x/invite"] && - [messageNode check:@"body#"] + ![messageNode check:@"/"] && [messageNode check:@"{http://jabber.org/protocol/muc#user}x"] && + ![messageNode check:@"{http://jabber.org/protocol/muc#user}x/invite"] && [messageNode check:@"body#"] ) { DDLogWarn(@"Ignoring muc pm marked as such..."); @@ -244,7 +242,6 @@ +(MLMessage* _Nullable) processMessage:(XMPPMessage*) messageNode andOuterMessag DDLogVerbose(@"Not a carbon copy of a muc pm for contact: %@", carbonTestContact); } - 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 @@ -275,9 +272,9 @@ +(MLMessage* _Nullable) processMessage:(XMPPMessage*) messageNode andOuterMessag //check stanza-id @by according to the rules outlined in XEP-0359 if(!stanzaid) { - if(!possiblyUnknownContact.isMuc && [messageNode check:@"{urn:xmpp:sid:0}stanza-id", account.connectionProperties.identity.jid]) + if(![messageNode check:@"/"] && [messageNode check:@"{urn:xmpp:sid:0}stanza-id", account.connectionProperties.identity.jid]) stanzaid = [messageNode findFirst:@"{urn:xmpp:sid:0}stanza-id@id", account.connectionProperties.identity.jid]; - else if(possiblyUnknownContact.isMuc && [messageNode check:@"{urn:xmpp:sid:0}stanza-id", messageNode.fromUser] && [[account.mucProcessor getRoomFeaturesForMuc:messageNode.fromUser] containsObject:@"urn:xmpp:sid:0"]) + else if([messageNode check:@"/"] && [messageNode check:@"{urn:xmpp:sid:0}stanza-id", messageNode.fromUser] && [[account.mucProcessor getRoomFeaturesForMuc:messageNode.fromUser] containsObject:@"urn:xmpp:sid:0"]) stanzaid = [messageNode findFirst:@"{urn:xmpp:sid:0}stanza-id@id", messageNode.fromUser]; } @@ -316,35 +313,15 @@ +(MLMessage* _Nullable) processMessage:(XMPPMessage*) messageNode andOuterMessag NSString* actualFrom = messageNode.fromUser; NSString* participantJid = nil; NSString* occupantId = nil; - if(possiblyUnknownContact.isMuc) + if([messageNode check:@"/"] && messageNode.fromResource) { - actualFrom = messageNode.fromResource ?: @""; - - ownNick = [[DataLayer sharedInstance] ownNickNameforMuc:messageNode.fromUser forAccount:account.accountID]; - ownOccupantId = [[DataLayer sharedInstance] getOwnOccupantIdForMuc:messageNode.fromUser onAccountID:account.accountID]; - - //occupant ids are widely supported now and allow us to have a stable identifier of every muc participant, - //even if it is a semi-anonymous channel - if([[account.mucProcessor getRoomFeaturesForMuc:messageNode.fromUser] containsObject:@"urn:xmpp:occupant-id:0"] && [messageNode check:@"{urn:xmpp:occupant-id:0}occupant-id@id"]) - { - occupantId = [messageNode findFirst:@"{urn:xmpp:occupant-id:0}occupant-id@id"]; - NSDictionary* mucParticipant = [[DataLayer sharedInstance] getParticipantForOccupant:occupantId inRoom:messageNode.fromUser forAccountID:account.accountID]; - //we will be able to get to know the real jid, if this is a group or we are the channel admin - participantJid = mucParticipant ? mucParticipant[@"participant_jid"] : nil; - } - + ownNick = [[DataLayer sharedInstance] ownNickNameforMuc:messageNode.fromUser forAccount:account.accountNo]; + actualFrom = messageNode.fromResource; //mam catchups will contain a muc#user item listing the jid of the participant //this can't be reconstructed from *current* participant lists because someone new could have taken the same nick //we don't accept this in non-mam context to make sure this can't be spoofed somehow - //we also don't do that, if this was a message from the bare muc jid - //NOTE: this will override the participantJid extracted using the occupantId above, - //NOTE: but those should ALWAYS be the same (that's the exact purpose of occupant ids) - if([outerMessageNode check:@"{urn:xmpp:mam:2}result"] && ![@"" isEqualToString:actualFrom]) - participantJid = [messageNode findFirst:@"{http://jabber.org/protocol/muc#user}x/item@jid"]; - - //try to get the jid of the current participant if the occupant-id based approach above did not work - //but don't do so, if this was a message from the bare muc jid - if(![outerMessageNode check:@"{urn:xmpp:mam:2}result"] && occupantId == nil && participantJid == nil && ![@"" isEqualToString:actualFrom]) + participantJid = [messageNode findFirst:@"//{http://jabber.org/protocol/muc#user}x/item@jid"]; + if(![outerMessageNode check:@"{urn:xmpp:mam:2}result"] || participantJid == nil) { if([[account.mucProcessor getRoomFeaturesForMuc:messageNode.fromUser] containsObject:@"urn:xmpp:occupant-id:0"] && [messageNode check:@"{urn:xmpp:occupant-id:0}occupant-id@id"]) { @@ -590,9 +567,6 @@ +(MLMessage* _Nullable) processMessage:(XMPPMessage*) messageNode andOuterMessag else if([lowercaseBody hasPrefix:@"https://"]) messageType = kMessageTypeUrl; } - //messages from the bare muc jid are classified as status messages - if(possiblyUnknownContact.isMuc && [@"" isEqualToString:actualFrom]) - messageType = kMessageTypeStatus; DDLogInfo(@"Got message of type: %@", messageType); if(body) diff --git a/Monal/Classes/MLStream.m b/Monal/Classes/MLStream.m index b38cce82a9..1070be770b 100644 --- a/Monal/Classes/MLStream.m +++ b/Monal/Classes/MLStream.m @@ -50,7 +50,7 @@ @interface MLInputStream() //(mutexes can not be unlocked in a thread different from the one it got locked in and NSLock internally uses mutext --> both can not be used) dispatch_semaphore_t _read_sem; } -@property (atomic, readonly) void (^incoming_data_handler)(NSData* _Nullable, BOOL, NSError* _Nullable); +@property (atomic, readonly) void (^incoming_data_handler)(NSData* _Nullable, BOOL, NSError* _Nullable, BOOL allow_next_read); @end @interface MLOutputStream() @@ -89,7 +89,7 @@ -(instancetype) initWithSharedState:(MLSharedStreamState*) shared //this handler will be called by the schedule_read method //since the framer swallows all data, nw_connection_receive() and the framer cannot race against each other and deliver reordered data weakify(self); - _incoming_data_handler = ^(NSData* _Nullable content, BOOL is_complete, NSError* _Nullable st_error) { + _incoming_data_handler = ^(NSData* _Nullable content, BOOL is_complete, NSError* _Nullable st_error, BOOL allow_next_read) { strongify(self); if(self == nil) return; @@ -142,7 +142,7 @@ -(instancetype) initWithSharedState:(MLSharedStreamState*) shared [self generateEvent:NSStreamEventEndEncountered]; //try to read again - if(!is_complete && !generate_bytes_available_event) + if(!is_complete && !generate_bytes_available_event && allow_next_read) [self schedule_read]; }; return self; @@ -235,7 +235,8 @@ -(void) schedule_read DDLogDebug(@"now calling nw_framer_parse_input inside framer queue"); nw_framer_parse_input(self.shared_state.framer, 1, BUFFER_SIZE, nil, ^size_t(uint8_t* buffer, size_t buffer_length, bool is_complete) { DDLogDebug(@"nw_framer_parse_input got callback with is_complete:%@, length=%zu", bool2str(is_complete), (unsigned long)buffer_length); - self.incoming_data_handler([NSData dataWithBytes:buffer length:buffer_length], is_complete, nil); + //we only want to allow new calls to schedule_read if we received some data --> set last arg accordingly + self.incoming_data_handler([NSData dataWithBytes:buffer length:buffer_length], is_complete, nil, buffer_length > 0); return buffer_length; }); }); @@ -248,7 +249,8 @@ -(void) schedule_read NSError* st_error = nil; if(receive_error) st_error = (NSError*)CFBridgingRelease(nw_error_copy_cf_error(receive_error)); - self.incoming_data_handler((NSData*)content, is_complete, st_error); + //we always want to allow new calls to schedule_read --> set last arg to YES + self.incoming_data_handler((NSData*)content, is_complete, st_error, YES); }); } } diff --git a/Monal/Classes/MonalAppDelegate.m b/Monal/Classes/MonalAppDelegate.m index 7769e3ac82..a32ddbb052 100644 --- a/Monal/Classes/MonalAppDelegate.m +++ b/Monal/Classes/MonalAppDelegate.m @@ -1972,10 +1972,10 @@ -(void) sendAllOutboxes monal_id_block_t cleanup = ^(NSDictionary* payload) { [[DataLayer sharedInstance] deleteShareSheetPayloadWithId:payload[@"id"]]; [[MLNotificationQueue currentQueue] postNotificationName:kMonalRefresh object:nil userInfo:nil]; - if(self.activeChats.currentChatView != nil) + if(self.activeChats.currentChatViewController != nil) { - [self.activeChats.currentChatView scrollToBottomAnimated:NO]; - [self.activeChats.currentChatView hideUploadHUD]; + [self.activeChats.currentChatViewController scrollToBottomAnimated:NO]; + [self.activeChats.currentChatViewController hideUploadHUD]; } //send next item (if there is one left) [self sendAllOutboxes]; @@ -2007,7 +2007,7 @@ -(void) sendAllOutboxes else if([payload[@"type"] isEqualToString:@"image"] || [payload[@"type"] isEqualToString:@"file"] || [payload[@"type"] isEqualToString:@"contact"] || [payload[@"type"] isEqualToString:@"audiovisual"]) { DDLogInfo(@"Got %@ upload: %@", payload[@"type"], payload[@"data"]); - [self.activeChats.currentChatView showUploadHUD]; + [self.activeChats.currentChatViewController showUploadHUD]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ $call(payload[@"data"], $ID(account), $BOOL(encrypted), $ID(completion, (^(NSString* url, NSString* mimeType, NSNumber* size, NSError* error) { dispatch_async(dispatch_get_main_queue(), ^{ diff --git a/Monal/Classes/NotificationDebugging.swift b/Monal/Classes/NotificationDebugging.swift index ebe6bdcbfa..3dc7396466 100644 --- a/Monal/Classes/NotificationDebugging.swift +++ b/Monal/Classes/NotificationDebugging.swift @@ -8,11 +8,6 @@ import OrderedCollections -class NotificationDebuggingDefaultsDB: ObservableObject { - @defaultsDB("lastAppexStart") - var lastAppexStart: Date? -} - struct NotificationDebugging: View { private let applePushEnabled: Bool private let applePushToken: String @@ -24,25 +19,18 @@ struct NotificationDebugging: View { @State private var showPushToken = false @State private var selectedPushServer: String - - @ObservedObject var notificationDebuggingDefaultsDB = NotificationDebuggingDefaultsDB() var body: some View { Form { Group { Section(header: Text("Status").font(.title3)) { - VStack(alignment: .leading, spacing:10) { + VStack(alignment: .leading) { buildNotificationStateLabel(Text("Apple Push Service"), isWorking: self.applePushEnabled); Divider() Text("Apple push service should always be on. If it is off, your device can not talk to Apple's server.").foregroundColor(Color(UIColor.secondaryLabel)).font(.footnote) if !self.applePushEnabled, let apnsError = MLXMPPManager.sharedInstance().apnsError { Text("Error: \(String(describing:apnsError))").foregroundColor(.red).font(.footnote) } - if let lastAppexStart = notificationDebuggingDefaultsDB.lastAppexStart { - Text("Last incoming push: \(String(describing:lastAppexStart))").foregroundColor(.gray).font(.footnote) - } else { - Text("Last incoming push: unknown").foregroundColor(.gray).font(.footnote) - } }.onTapGesture(count: 2, perform: { showPushToken = true }).alert(isPresented: $showPushToken) { diff --git a/Monal/Classes/chatViewController.m b/Monal/Classes/chatViewController.m index b9ce268932..8a689dbe58 100644 --- a/Monal/Classes/chatViewController.m +++ b/Monal/Classes/chatViewController.m @@ -3560,8 +3560,7 @@ -(NSInteger)collectionView:(nonnull UICollectionView*) collectionView numberOfIt -(void) notifyUploadQueueRemoval:(NSUInteger) index { - if(index >= self.uploadQueue.count) - return; + MLAssert(index < self.uploadQueue.count, @"index is only allowed to be smaller than uploadQueue.count"); [self.uploadMenuView performBatchUpdates:^{ [self deleteQueueItemAtIndex:index]; } completion:^(BOOL finished) { diff --git a/Monal/NotificationService/NotificationService.m b/Monal/NotificationService/NotificationService.m index c25f3052ca..6bb79c6e57 100644 --- a/Monal/NotificationService/NotificationService.m +++ b/Monal/NotificationService/NotificationService.m @@ -441,8 +441,6 @@ +(void) initialize if(warnUnclean) DDLogError(@"detected unclean appex shutdown!"); - [[HelperTools defaultsDB] setObject:[NSDate now] forKey:@"lastAppexStart"]; - //mark this appex as unclean (will be cleared directly before calling exit(0)) [NotificationService setAppexCleanShutdownStatus:NO]; }