diff --git a/.github/workflows/beta.build-push.yml b/.github/workflows/beta.build-push.yml index 55d160087a..2ef6806c0e 100644 --- a/.github/workflows/beta.build-push.yml +++ b/.github/workflows/beta.build-push.yml @@ -24,7 +24,7 @@ jobs: EXPORT_OPTIONS_IOS: "../scripts/exportOptions/Beta_iOS_ExportOptions.plist" # Steps represent a sequence of tasks that will be executed as part of the job steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: clean: true submodules: true @@ -75,22 +75,22 @@ jobs: run: ./scripts/uploadNonAlpha.sh beta - name: Publish catalyst to appstore connect run: xcrun altool --upload-app --file ./Monal/build/app/Monal.pkg --type macos --asc-provider S8D843U34Y -u "$(cat /Users/ci/apple_connect_upload_mail.txt)" -p "$(cat /Users/ci/apple_connect_upload_secret.txt)" --primary-bundle-id org.monal-im.prod.catalyst.monal - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: monal-catalyst path: Monal/build/app/Monal.zip if-no-files-found: error - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: monal-ios path: Monal/build/ipa/Monal.ipa if-no-files-found: error - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: monal-catalyst-dsym path: Monal/build/macos_Monal.xcarchive/dSYMs if-no-files-found: error - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: monal-ios-dsym path: Monal/build/ios_Monal.xcarchive/dSYMs diff --git a/.github/workflows/develop-push.yml b/.github/workflows/develop-push.yml index 1543b133ce..16492bc84a 100644 --- a/.github/workflows/develop-push.yml +++ b/.github/workflows/develop-push.yml @@ -24,7 +24,7 @@ jobs: EXPORT_OPTIONS_IOS: "../scripts/exportOptions/Alpha_iOS_ExportOptions.plist" # Steps represent a sequence of tasks that will be executed as part of the job steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: clean: true submodules: true @@ -60,22 +60,22 @@ jobs: run: xcrun notarytool submit ./Monal/build/app/Monal.zip --wait --team-id S8D843U34Y --key "/Users/ci/appstoreconnect/apiKey.p8" --key-id "$(cat /Users/ci/appstoreconnect/apiKeyId.txt)" --issuer "$(cat /Users/ci/appstoreconnect/apiIssuerId.txt)" - name: Update monal homebrew alpha repo run: scripts/updateAlphaHomebrew.sh - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: monal-catalyst path: Monal/build/app/Monal.tar if-no-files-found: error - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: monal-ios path: Monal/build/ipa/Monal.ipa if-no-files-found: error - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: monal-catalyst-dsym path: Monal/build/macos_Monal.xcarchive/dSYMs if-no-files-found: error - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: monal-ios-dsym path: Monal/build/ios_Monal.xcarchive/dSYMs diff --git a/.github/workflows/stable.build-push.yml b/.github/workflows/stable.build-push.yml index 0a2e31c9e4..f1bff59cc6 100644 --- a/.github/workflows/stable.build-push.yml +++ b/.github/workflows/stable.build-push.yml @@ -24,7 +24,7 @@ jobs: EXPORT_OPTIONS_IOS: "../scripts/exportOptions/Stable_iOS_ExportOptions.plist" # Steps represent a sequence of tasks that will be executed as part of the job steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: clean: true submodules: true @@ -73,22 +73,22 @@ jobs: run: xcrun altool --upload-app --file ./Monal/build/app/Monal.pkg --type macos --asc-provider S8D843U34Y -u "$(cat /Users/ci/apple_connect_upload_mail.txt)" -p "$(cat /Users/ci/apple_connect_upload_secret.txt)" --primary-bundle-id maccatalyst.G7YU7X7KRJ.SworIM # - name: Update xmpp.org client list with new timestamp # run: ./scripts/push_xmpp.org.sh - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: monal-catalyst-pkg path: Monal/build/app/Monal.pkg if-no-files-found: error - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: monal-ios path: Monal/build/ipa/Monal.ipa if-no-files-found: error - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: monal-catalyst-dsym path: Monal/build/macos_Monal.xcarchive/dSYMs if-no-files-found: error - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: monal-ios-dsym path: Monal/build/ios_Monal.xcarchive/dSYMs diff --git a/Monal/Classes/ContactList.swift b/Monal/Classes/ContactList.swift new file mode 100644 index 0000000000..e0c1792a83 --- /dev/null +++ b/Monal/Classes/ContactList.swift @@ -0,0 +1,83 @@ +// +// ContactList.swift +// Monal +// +// Created by Jan on 15.12.22. +// Copyright © 2022 monal-im.org. All rights reserved. +// + +import SwiftUI +import monalxmpp + +struct ContactEntry: View { + let contact : MLContact + + var body:some View { + ZStack(alignment: .topLeading) { + HStack(alignment: .center) { + Image(uiImage: contact.avatar) + .resizable() + .frame(width: 40, height: 40, alignment: .center) + VStack(alignment: .leading) { + Text(contact.contactDisplayName as String) + Text(contact.contactJid as String).font(.footnote).opacity(0.6) + } + } + } + } +} + +struct ContactList: View { + @State var contacts : [MLContact] + @State var selectedContact : MLContact? + @State var searchFieldInput = "" + + func matchesSearch(contact : MLContact) -> Bool { + // TODO better lookup + if searchFieldInput.isEmpty == true { + return true + } else { + return contact.contactDisplayName.lowercased().contains(searchFieldInput.lowercased()) || + contact.contactJid.contains(searchFieldInput.lowercased()) + } + } + + var body: some View { + if(contacts.isEmpty) { + Text("No contacts to show :(") + .navigationTitle("Contact Lists") + } else { + List { + Section { + TextField("Search contacts", text: $searchFieldInput) + } + ForEach(contacts, id: \.self) { contact in + if matchesSearch(contact: contact) { + ContactEntry(contact: contact) + } + } + .onDelete { + print(contacts.remove(atOffsets: $0)) + } + .onInsert(of: [""], perform: { _,_ in + }) + } + .listStyle(.inset) + .navigationBarTitle("Contact List", displayMode: .inline) + .toolbar { + EditButton() + } + } + } +} + +struct ContactList_Previews: PreviewProvider { + static var previews: some View { + ContactList(contacts: [ + MLContact.makeDummyContact(0), + MLContact.makeDummyContact(1), + MLContact.makeDummyContact(2), + MLContact.makeDummyContact(3)] + ) + } +} diff --git a/Monal/Classes/ContactsViewController.m b/Monal/Classes/ContactsViewController.m index a76551ba1a..c3ba01055e 100644 --- a/Monal/Classes/ContactsViewController.m +++ b/Monal/Classes/ContactsViewController.m @@ -47,7 +47,13 @@ -(void) openAddContacts:(id)sender [self presentViewController:addContactMenuView animated:YES completion:^{}]; } --(void) openContactRequests:(id)sender +-(void) openCreateGroup:(id) sender +{ + UIViewController* createGroupView = [[SwiftuiInterface new] makeViewWithName:@"CreateGroup"]; + [self presentViewController:createGroupView animated:YES completion:^{}]; +} + +-(void) openContactRequests:(id) sender { UIViewController* contactRequestsView = [[SwiftuiInterface new] makeViewWithName:@"ContactRequests"]; [self presentViewController:contactRequestsView animated:YES completion:^{}]; @@ -99,7 +105,15 @@ -(void) viewDidLoad addContact.image = [UIImage systemImageNamed:@"person.fill.badge.plus"]; [addContact setAction:@selector(openAddContacts:)]; +#ifdef IS_ALPHA + UIBarButtonItem* createGroup = [[UIBarButtonItem alloc] init]; + createGroup.image = [UIImage systemImageNamed:@"person.3.fill"]; + [createGroup setAction:@selector(openCreateGroup:)]; + self.navigationItem.rightBarButtonItems = [[NSArray alloc] initWithObjects:addContact, [[UIBarButtonItem alloc] init], createGroup, nil]; +#else self.navigationItem.rightBarButtonItems = [[NSArray alloc] initWithObjects:addContact, [UIBarButtonItem new], nil]; +#endif + [self configureContactRequestsImage]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleContactUpdate) name:kMonalContactRemoved object:nil]; diff --git a/Monal/Classes/CreateGroupMenu.swift b/Monal/Classes/CreateGroupMenu.swift new file mode 100644 index 0000000000..f55f1f01a5 --- /dev/null +++ b/Monal/Classes/CreateGroupMenu.swift @@ -0,0 +1,116 @@ +// +// AddContactMenu.swift +// Monal +// +// Created by Jan on 27.10.22. +// Copyright © 2022 monal-im.org. All rights reserved. +// + +import MobileCoreServices +import UniformTypeIdentifiers +import SwiftUI +import monalxmpp + +struct CreateGroupMenu: View { + var delegate: SheetDismisserProtocol + + @State private var connectedAccounts: [xmpp] + @State private var selectedAccount: Int + @State private var groupName: String = "" + + @State private var showAlert = false + // note: dismissLabel is not accessed but defined at the .alert() section + @State private var alertPrompt = AlertPrompt(dismissLabel: Text("Close")) + + @ObservedObject private var overlay = LoadingOverlayState() + + @State private var showQRCodeScanner = false + @State private var success = false + + private let dismissWithNewGroup: (MLContact) -> () + + init(delegate: SheetDismisserProtocol, dismissWithNewGroup: @escaping (MLContact) -> (), prefillJid: String = "", preauthToken:String? = nil) { + // FIXME + self.delegate = delegate + self.dismissWithNewGroup = dismissWithNewGroup + self.groupName = prefillJid + // self.preauthToken = preauthToken + + let connectedAccounts = MLXMPPManager.sharedInstance().connectedXMPP as! [xmpp] + self.connectedAccounts = connectedAccounts + self.selectedAccount = connectedAccounts.first != nil ? 0 : -1; + } + + // FIXME duplicate code from WelcomeLogIn.swift, maybe move to SwiftuiHelpers + + private func errorAlert(title: Text, message: Text = Text("")) { + alertPrompt.title = title + alertPrompt.message = message + showAlert = true + } + + private func successAlert(title: Text, message: Text) { + alertPrompt.title = title + alertPrompt.message = message + self.success = true // < dismiss entire view on close + showAlert = true + } + + private var buttonColor: Color { + return Color(UIColor.systemBlue) + } + + var body: some View { + Form { + if(connectedAccounts.isEmpty) { + Text("Please make sure at least one account has connected before trying to create new group.") + .foregroundColor(.secondary) + } + else + { + Section() { + if(connectedAccounts.count > 1) { + Picker("Use account", selection: $selectedAccount) { + ForEach(Array(self.connectedAccounts.enumerated()), id: \.element) { idx, account in + Text(account.connectionProperties.identity.jid).tag(idx) + } + } + .pickerStyle(.menu) + } + TextField("Group Name (optional)", text: $groupName) + .autocorrectionDisabled() + .autocapitalization(.none) + .addClearButton(text:$groupName) + + NavigationLink(destination: LazyClosureView(ContactList(contacts: DataLayer.sharedInstance().contactList() as! [MLContact])), label: { + Text("Group Members") + }) + } + Section { + Button(action: {}, label: { + Text("Create new group") + }) + } + } + } + .alert(isPresented: $showAlert) { + Alert(title: alertPrompt.title, message: alertPrompt.message, dismissButton:.default(Text("Close"), action: { + showAlert = false + if self.success == true { + // TODO dismissWithNewGroup + } + })) + } + .addLoadingOverlay(overlay) + .navigationBarTitle("Create new group", displayMode: .inline) + .navigationViewStyle(.stack) + } +} + +struct CreateGroupMenu_Previews: PreviewProvider { + static var delegate = SheetDismisserProtocol() + static var previews: some View { + CreateGroupMenu(delegate: delegate, dismissWithNewGroup: { c in + }) + } +} diff --git a/Monal/Classes/HelperTools.m b/Monal/Classes/HelperTools.m index ee92c5ebde..1f8ecc562a 100644 --- a/Monal/Classes/HelperTools.m +++ b/Monal/Classes/HelperTools.m @@ -344,10 +344,23 @@ +(NSString*) extractXMPPError:(XMPPStanza*) stanza withDescription:(NSString*) d +(void) initSystem { - [self configureLogging]; + BOOL enableDefaultLogAndCrashFramework = YES; +#ifdef TARGET_IPHONE_SIMULATOR + // Automatically switch between the debug technique of TMolitor and FAltheide + enableDefaultLogAndCrashFramework = [[HelperTools defaultsDB] boolForKey: @"udpLoggerEnabled"]; +#endif + if(enableDefaultLogAndCrashFramework) + { + [self configureLogging]; + [self installCrashHandler]; + [self installExceptionHandler]; + } + else + { + [self configureXcodeLogging]; + } [SwiftHelpers initSwiftHelpers]; - [self installCrashHandler]; - [self installExceptionHandler]; + [self activityLog]; } @@ -357,7 +370,7 @@ +(void) configureDefaultAudioSession NSError* error; DDLogDebug(@"configuring default audio session..."); AVAudioSessionCategoryOptions options = 0; - //options |= AVAudioSessionCategoryOptionMixWithOthers; + options |= AVAudioSessionCategoryOptionMixWithOthers; //options |= AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers; //options |= AVAudioSessionCategoryOptionAllowBluetooth; //options |= AVAudioSessionCategoryOptionAllowBluetoothA2DP; @@ -1264,17 +1277,14 @@ +(void) scheduleBackgroundTask:(BOOL) force } else { - if(@available(iOS 17.0, macCatalyst 17.0, *)) - { - //cancel existing task (if any) - [BGTaskScheduler.sharedScheduler cancelTaskRequestWithIdentifier:kBackgroundRefreshingTask]; - } + //cancel existing task (if any) + [BGTaskScheduler.sharedScheduler cancelTaskRequestWithIdentifier:kBackgroundRefreshingTask]; //new task BGAppRefreshTaskRequest* refreshingRequest = [[BGAppRefreshTaskRequest alloc] initWithIdentifier:kBackgroundRefreshingTask]; //on ios<17 do the same like the corona warn app from germany which leads to this hint: https://developer.apple.com/forums/thread/134031 - if(@available(iOS 17.0, macCatalyst 17.0, *)) - refreshingRequest.earliestBeginDate = [NSDate dateWithTimeIntervalSinceNow:BGFETCH_DEFAULT_INTERVAL]; - else +// if(@available(iOS 17.0, macCatalyst 17.0, *)) +// refreshingRequest.earliestBeginDate = [NSDate dateWithTimeIntervalSinceNow:BGFETCH_DEFAULT_INTERVAL]; +// else refreshingRequest.earliestBeginDate = nil; if(![[BGTaskScheduler sharedScheduler] submitTaskRequest:refreshingRequest error:&error]) { @@ -1573,6 +1583,11 @@ +(void) flushLogsWithTimeout:(double) timeout [MLUDPLogger flushWithTimeout:timeout]; } ++(void) configureXcodeLogging +{ + [DDLog addLogger:[DDTTYLogger sharedInstance]]; +} + +(void) configureLogging { //don't log to the console (aka stderr) to not create loops with our redirected stderr diff --git a/Monal/Classes/MLAutoDownloadFiletransferSettingViewController.m b/Monal/Classes/MLAutoDownloadFiletransferSettingViewController.m index 3946285e73..45729bc7d7 100644 --- a/Monal/Classes/MLAutoDownloadFiletransferSettingViewController.m +++ b/Monal/Classes/MLAutoDownloadFiletransferSettingViewController.m @@ -11,7 +11,8 @@ enum MLAutoDownloadFiletransferSettingViewController { FiletransferSettingsGeneralSettings, - FiletransferSettingsAdvancedSettings, + FiletransferSettingsAdvancedDownloadSettings, + FiletransferSettingsAdvancedUploadSettings, FiletransferSettingSectionCnt }; @@ -33,7 +34,7 @@ - (void)viewDidLoad { self.navigationItem.title = NSLocalizedString(@"Auto-Download Media", @""); } --(nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section +-(nullable NSString*) tableView:(UITableView*) tableView titleForHeaderInSection:(NSInteger) section { NSString* sectionTitle = nil; switch(section) @@ -41,8 +42,11 @@ -(nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection case FiletransferSettingsGeneralSettings: sectionTitle = NSLocalizedString(@"General File Transfer Settings", @""); break; - case FiletransferSettingsAdvancedSettings: - sectionTitle = NSLocalizedString(@"Maximum File Transfer Size", @""); + case FiletransferSettingsAdvancedDownloadSettings: + sectionTitle = NSLocalizedString(@"Download Settings", @""); + break; + case FiletransferSettingsAdvancedUploadSettings: + sectionTitle = NSLocalizedString(@"Upload Settings", @""); break; default: break; @@ -62,8 +66,10 @@ -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) { case FiletransferSettingsGeneralSettings: return 1; - case FiletransferSettingsAdvancedSettings: - return 3; + case FiletransferSettingsAdvancedDownloadSettings: + return 2; + case FiletransferSettingsAdvancedUploadSettings: + return 1; default: unreachable(); break; @@ -91,8 +97,8 @@ -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NS unreachable(); } break; - case FiletransferSettingsAdvancedSettings: - switch (indexPath.row) + case FiletransferSettingsAdvancedDownloadSettings: + switch(indexPath.row) { case 0: { @@ -100,7 +106,7 @@ -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NS // byte -> mb float mb = sliderValue / 1024 / 1024; labelToUpdate.text = [NSString stringWithFormat:NSLocalizedString(@"Load over WiFi upto: %.fMB", @""), mb]; - + return mb; } withUpdateFunc:^(UILabel* labelToUpdate, float sliderValue) { float newValue = roundf(sliderValue); @@ -115,7 +121,7 @@ -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NS // byte -> mb float mb = sliderValue / 1024 / 1024; labelToUpdate.text = [NSString stringWithFormat:NSLocalizedString(@"Load over cellular upto: %.fMB", @""), mb]; - + return mb; } withUpdateFunc:^(UILabel* labelToUpdate, float sliderValue) { float newValue = roundf(sliderValue); @@ -125,15 +131,23 @@ -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NS }]; break; } - case 2: + default: + unreachable(); + break; + } + break; + case FiletransferSettingsAdvancedUploadSettings: + switch(indexPath.row) + { + case 0: { - [cell initCell:NSLocalizedString(@"Image Quality", @"") withSliderDefaultsKey:@"ImageUploadQuality" minValue:0.33f maxValue:1.0 withLoadFunc:^(UILabel* labelToUpdate, float sliderValue) { + [cell initCell:NSLocalizedString(@"Image Upload Quality", @"") withSliderDefaultsKey:@"ImageUploadQuality" minValue:0.33f maxValue:1.0 withLoadFunc:^(UILabel* labelToUpdate, float sliderValue) { float rate = roundf(sliderValue * 100) / 100; - labelToUpdate.text = [NSString stringWithFormat:NSLocalizedString(@"Image Quality: %.2f", @""), rate]; + labelToUpdate.text = [NSString stringWithFormat:NSLocalizedString(@"Image Upload Quality: %.2f", @""), rate]; return rate; } withUpdateFunc:^(UILabel* labelToUpdate, float sliderValue) { float rate = roundf(sliderValue * 100) / 100; - labelToUpdate.text = [NSString stringWithFormat:NSLocalizedString(@"Image Quality: %.2f", @""), rate]; + labelToUpdate.text = [NSString stringWithFormat:NSLocalizedString(@"Image Upload Quality: %.2f", @""), rate]; return rate; }]; break; @@ -149,7 +163,7 @@ -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NS return cell; } --(void)sliderValueChanged:(UISlider*) slider +-(void) sliderValueChanged:(UISlider*) slider { int maxFileSize = (int)slider.value; [sliderResultLabel setText:[NSString stringWithFormat:@"%d MB", maxFileSize]]; @@ -157,7 +171,7 @@ -(void)sliderValueChanged:(UISlider*) slider [[HelperTools defaultsDB] setInteger:(maxFileSize * 1024 * 1024) forKey:@"AutodownloadFiletransfersMaxSize"]; } --(void)updateUI +-(void) updateUI { BOOL isAutodownloadFiletransfers = [[HelperTools defaultsDB] boolForKey:@"AutodownloadFiletransfers"]; [slider setUserInteractionEnabled:isAutodownloadFiletransfers]; diff --git a/Monal/Classes/MLMessageProcessor.m b/Monal/Classes/MLMessageProcessor.m index 9ca0c08e02..5267e6f86c 100644 --- a/Monal/Classes/MLMessageProcessor.m +++ b/Monal/Classes/MLMessageProcessor.m @@ -774,7 +774,7 @@ +(MLMessage* _Nullable) processMessage:(XMPPMessage*) messageNode andOuterMessag } } } - + return message; } diff --git a/Monal/Classes/MLMucProcessor.m b/Monal/Classes/MLMucProcessor.m index 1dd7161fe7..f15d2aa8de 100644 --- a/Monal/Classes/MLMucProcessor.m +++ b/Monal/Classes/MLMucProcessor.m @@ -93,11 +93,11 @@ -(NSDictionary*) getInternalState @synchronized(_stateLockObject) { NSDictionary* state = @{ @"version": CURRENT_MUC_STATE_VERSION, - @"roomFeatures": _roomFeatures, - @"joining": _joining, - @"firstJoin": _firstJoin, + @"roomFeatures": [_roomFeatures copy], + @"joining": [_joining copy], + @"firstJoin": [_firstJoin copy], @"lastPing": _lastPing, - @"noUpdateBookmarks": _noUpdateBookmarks, + @"noUpdateBookmarks": [_noUpdateBookmarks copy], @"hasFetchedBookmarks": @(_hasFetchedBookmarks), }; //DDLogVerbose(@"Returning MUC state: %@", state); diff --git a/Monal/Classes/MLPrivacySettingsViewController.m b/Monal/Classes/MLPrivacySettingsViewController.m index ef7dd62e9d..0364417b9d 100644 --- a/Monal/Classes/MLPrivacySettingsViewController.m +++ b/Monal/Classes/MLPrivacySettingsViewController.m @@ -166,7 +166,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N } case 10: { - [cell initTapCell:NSLocalizedString(@"Auto-Download Media Settings", @"")]; + [cell initTapCell:NSLocalizedString(@"Media Upload & Download Settings", @"")]; break; } case 11: diff --git a/Monal/Classes/MLServerDetails.m b/Monal/Classes/MLServerDetails.m index 5a43557321..4e6c9bfcf9 100644 --- a/Monal/Classes/MLServerDetails.m +++ b/Monal/Classes/MLServerDetails.m @@ -13,6 +13,7 @@ @interface MLServerDetails () @property (nonatomic, strong) NSMutableArray* serverCaps; +@property (nonatomic, strong) NSMutableArray* stunTurnServers; @property (nonatomic, strong) NSMutableArray* srvRecords; @property (nonatomic, strong) NSMutableArray* tlsVersions; @property (nonatomic, strong) NSMutableArray* saslMethods; @@ -24,6 +25,7 @@ @implementation MLServerDetails enum MLServerDetailsSections { SUPPORTED_SERVER_XEPS_SECTION, + VOIP_SECTION, SRV_RECORS_SECTION, TLS_SECTION, SASL_SECTION, @@ -31,14 +33,20 @@ @implementation MLServerDetails ML_SERVER_DETAILS_SECTIONS_CNT }; -- (void)viewDidLoad { +#define SERVER_DETAILS_COLOR_OK @"Blue" +#define SERVER_DETAILS_COLOR_NON_IDEAL @"Orange" +#define SERVER_DETAILS_COLOR_ERROR @"Red" + +- (void) viewDidLoad +{ [super viewDidLoad]; } --(void) viewWillAppear:(BOOL)animated +-(void) viewWillAppear:(BOOL) animated { [super viewWillAppear:animated]; self.serverCaps = [NSMutableArray new]; + self.stunTurnServers = [NSMutableArray new]; self.srvRecords = [NSMutableArray new]; self.tlsVersions = [NSMutableArray new]; self.saslMethods = [NSMutableArray new]; @@ -52,6 +60,8 @@ -(void) viewWillAppear:(BOOL)animated [self checkTLSVersions:self.xmppAccount.connectionProperties]; [self checkSASLMethods:self.xmppAccount.connectionProperties]; [self checkChannelBindingTypes:self.xmppAccount.connectionProperties]; + + [self checkStunServers:self.xmppAccount.connectionProperties.discoveredStunTurnServers]; } - (void)didReceiveMemoryWarning { @@ -65,84 +75,84 @@ -(void) checkServerCaps:(MLXMPPConnection*) connection // 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" + @"Color": connection.supportsPubSub ? (connection.supportsModernPubSub ? SERVER_DETAILS_COLOR_OK : SERVER_DETAILS_COLOR_NON_IDEAL) : SERVER_DETAILS_COLOR_ERROR }]; // supportsBlocking [self.serverCaps addObject:@{ @"Title":NSLocalizedString(@"XEP-0191: Blocking Command", @""), @"Description":NSLocalizedString(@"XMPP protocol extension for communications blocking.", @""), - @"Color": connection.supportsBlocking ? @"Green" : @"Red" + @"Color": connection.supportsBlocking ? SERVER_DETAILS_COLOR_OK : SERVER_DETAILS_COLOR_ERROR }]; // supportsSM3 [self.serverCaps addObject:@{ @"Title":NSLocalizedString(@"XEP-0198: Stream Management", @""), @"Description":NSLocalizedString(@"Resume a stream when disconnected. Results in faster reconnect and saves battery life.", @""), - @"Color": connection.supportsSM3 ? @"Green" : @"Red" + @"Color": connection.supportsSM3 ? SERVER_DETAILS_COLOR_OK : SERVER_DETAILS_COLOR_ERROR }]; // supportsPing [self.serverCaps addObject:@{ @"Title":NSLocalizedString(@"XEP-0199: XMPP Ping", @""), @"Description":NSLocalizedString(@"XMPP protocol extension for sending application-level pings over XML streams.", @""), - @"Color": connection.supportsPing ? @"Green" : @"Red" + @"Color": connection.supportsPing ? SERVER_DETAILS_COLOR_OK : SERVER_DETAILS_COLOR_ERROR }]; // supportsExternalServiceDiscovery [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.supportsExternalServiceDiscovery ? @"Green" : @"Red" + @"Color": connection.supportsExternalServiceDiscovery ? SERVER_DETAILS_COLOR_OK : SERVER_DETAILS_COLOR_ERROR }]; // supportsRosterVersion [self.serverCaps addObject:@{ @"Title":NSLocalizedString(@"XEP-0237: Roster Versioning", @""), @"Description":NSLocalizedString(@"Defines a proposed modification to the XMPP roster protocol that enables versioning of rosters such that the server will not send the roster to the client if the roster has not been modified.", @""), - @"Color": connection.supportsRosterVersion ? @"Green" : @"Red" + @"Color": connection.supportsRosterVersion ? SERVER_DETAILS_COLOR_OK : SERVER_DETAILS_COLOR_ERROR }]; // usingCarbons2 [self.serverCaps addObject:@{ @"Title":NSLocalizedString(@"XEP-0280: Message Carbons", @""), @"Description":NSLocalizedString(@"Synchronize your messages on all loggedin devices.", @""), - @"Color": connection.usingCarbons2 ? @"Green" : @"Red" + @"Color": connection.usingCarbons2 ? SERVER_DETAILS_COLOR_OK : SERVER_DETAILS_COLOR_ERROR }]; // supportsMam2 [self.serverCaps addObject:@{ @"Title":NSLocalizedString(@"XEP-0313: Message Archive Management", @""), @"Description":NSLocalizedString(@"Access message archives on the server.", @""), - @"Color": connection.supportsMam2 ? @"Green" : @"Red" + @"Color": connection.supportsMam2 ? SERVER_DETAILS_COLOR_OK : SERVER_DETAILS_COLOR_ERROR }]; // supportsClientState [self.serverCaps addObject:@{ @"Title":NSLocalizedString(@"XEP-0352: Client State Indication", @""), @"Description":NSLocalizedString(@"Indicate when a particular device is active or inactive. Saves battery.", @""), - @"Color": connection.supportsClientState ? @"Green" : @"Red" + @"Color": connection.supportsClientState ? SERVER_DETAILS_COLOR_OK : SERVER_DETAILS_COLOR_ERROR }]; // supportsPush / pushEnabled [self.serverCaps addObject:@{ @"Title":NSLocalizedString(@"XEP-0357: Push Notifications", @""), @"Description":NSLocalizedString(@"Receive push notifications via Apple even when disconnected. Vastly improves reliability.", @""), - @"Color": connection.supportsPush ? (connection.pushEnabled ? @"Green" : @"Yellow") : @"Red" + @"Color": connection.supportsPush ? (connection.pushEnabled ? SERVER_DETAILS_COLOR_OK : SERVER_DETAILS_COLOR_NON_IDEAL) : SERVER_DETAILS_COLOR_ERROR }]; // supportsHTTPUpload [self.serverCaps addObject:@{ @"Title":NSLocalizedString(@"XEP-0363: HTTP File Upload", @""), @"Description":[NSString stringWithFormat:NSLocalizedString(@"Upload files to the server to share with others. (Maximum allowed size of files reported by the server: %@)", @""), [HelperTools bytesToHuman:connection.uploadSize]], - @"Color": connection.supportsHTTPUpload ? @"Green" : @"Red" + @"Color": connection.supportsHTTPUpload ? SERVER_DETAILS_COLOR_OK : SERVER_DETAILS_COLOR_ERROR }]; // supportsRosterPreApproval [self.serverCaps addObject:@{ @"Title":NSLocalizedString(@"XEP-0379: Pre-Authenticated Roster Subscription", @""), @"Description":NSLocalizedString(@"Defines a protocol and URI scheme for pre-authenticated roster links that allow a third party to automatically obtain the user's presence subscription.", @""), - @"Color": connection.supportsRosterPreApproval ? @"Green" : @"Red" + @"Color": connection.supportsRosterPreApproval ? SERVER_DETAILS_COLOR_OK : SERVER_DETAILS_COLOR_ERROR }]; // supportsSSDP @@ -150,17 +160,42 @@ -(void) checkServerCaps:(MLXMPPConnection*) connection // see MLIQProcessor.m multiple xep required for pubsub @"Title":NSLocalizedString(@"XEP-0474: SASL SCRAM Downgrade Protection", @""), @"Description":NSLocalizedString(@"This specification provides a way to secure the SASL and SASL2 handshakes against method and channel-binding downgrades.", @""), - @"Color": connection.supportsSSDP ? @"Green" : @"Red" + @"Color": connection.supportsSSDP ? SERVER_DETAILS_COLOR_OK : SERVER_DETAILS_COLOR_ERROR }]; } +-(void) checkStunServers:(NSMutableArray*) stunTurnServers +{ + for(NSDictionary* service in stunTurnServers) + { + NSString* color; + if(service[@"type"] && ([service[@"type"] isEqualToString:@"stun"] || [service[@"type"] isEqualToString:@"turn"])) + { + color = SERVER_DETAILS_COLOR_OK; + } + else if(service[@"type"] && ([service[@"type"] isEqualToString:@"stuns"] || [service[@"type"] isEqualToString:@"turns"])) + { + color = SERVER_DETAILS_COLOR_OK; + } + else + { + color = SERVER_DETAILS_COLOR_ERROR; + } + [self.stunTurnServers addObject:@{ + @"Title": service[@"type"], + @"Description": [NSString stringWithFormat:@"%@:%@", service[@"host"], service[@"port"]], + @"Color": color + }]; + } +} + -(void) convertSRVRecordsToReadable { BOOL foundCurrentConn = NO; if(self.xmppAccount.discoveredServersList == nil || self.xmppAccount.discoveredServersList.count == 0) { - [self.srvRecords addObject:@{@"Title": NSLocalizedString(@"None", @""), @"Description":NSLocalizedString(@"This server does not have any SRV records in DNS.", @""), @"Color":@"Red"}]; + [self.srvRecords addObject:@{@"Title": NSLocalizedString(@"None", @""), @"Description":NSLocalizedString(@"This server does not have any SRV records in DNS.", @""), @"Color":SERVER_DETAILS_COLOR_ERROR}]; return; } @@ -177,14 +212,14 @@ -(void) convertSRVRecordsToReadable self.xmppAccount.connectionProperties.server.connectPort == port && self.xmppAccount.connectionProperties.server.isDirectTLS == [[srvEntry objectForKey:@"isSecure"] boolValue]) { - entryColor = @"Green"; + entryColor = SERVER_DETAILS_COLOR_OK; foundCurrentConn = YES; } else if(!foundCurrentConn) { // Set the color of all connections entries that failed to red // discoveredServersList is sorted. Therfore all entries before foundCurrentConn == YES have failed - entryColor = @"Red"; + entryColor = SERVER_DETAILS_COLOR_ERROR; } [self.srvRecords addObject:@{@"Title": [NSString stringWithFormat:NSLocalizedString(@"Server: %@", @""), hostname], @"Description": [NSString stringWithFormat:NSLocalizedString(@"Port: %@, Direct TLS: %@, Priority: %@", @""), port, isSecure, prio], @"Color": entryColor}]; @@ -194,8 +229,8 @@ -(void) convertSRVRecordsToReadable -(void) checkTLSVersions:(MLXMPPConnection*) connection { DDLogVerbose(@"connection uses tls version: %@", connection.tlsVersion); - [self.tlsVersions addObject:@{@"Title": NSLocalizedString(@"TLS 1.2", @""), @"Description":NSLocalizedString(@"Older, slower, but still secure TLS version", @""), @"Color":([@"1.2" isEqualToString:connection.tlsVersion] ? @"Green" : @"None")}]; - [self.tlsVersions addObject:@{@"Title": NSLocalizedString(@"TLS 1.3", @""), @"Description":NSLocalizedString(@"Newest TLS version which is faster than TLS 1.2", @""), @"Color":([@"1.3" isEqualToString:connection.tlsVersion] ? @"Green" : @"None")}]; + [self.tlsVersions addObject:@{@"Title": NSLocalizedString(@"TLS 1.2", @""), @"Description":NSLocalizedString(@"Older, slower, but still secure TLS version", @""), @"Color":([@"1.2" isEqualToString:connection.tlsVersion] ? SERVER_DETAILS_COLOR_OK : @"None")}]; + [self.tlsVersions addObject:@{@"Title": NSLocalizedString(@"TLS 1.3", @""), @"Description":NSLocalizedString(@"Newest TLS version which is faster than TLS 1.2", @""), @"Color":([@"1.3" isEqualToString:connection.tlsVersion] ? SERVER_DETAILS_COLOR_OK : @"None")}]; DDLogVerbose(@"tls versions: %@", self.tlsVersions); } @@ -204,7 +239,7 @@ -(void) checkSASLMethods:(MLXMPPConnection*) connection DDLogVerbose(@"saslMethods: %@", connection.saslMethods); if(connection.saslMethods == nil || connection.saslMethods.count == 0) { - [self.saslMethods addObject:@{@"Title": NSLocalizedString(@"None", @""), @"Description":NSLocalizedString(@"This server does not support modern SASL2 authentication.", @""), @"Color":@"Red"}]; + [self.saslMethods addObject:@{@"Title": NSLocalizedString(@"None", @""), @"Description":NSLocalizedString(@"This server does not support modern SASL2 authentication.", @""), @"Color":SERVER_DETAILS_COLOR_ERROR}]; return; } for(NSString* method in [connection.saslMethods.allKeys sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"self" ascending:YES]]]) @@ -220,7 +255,7 @@ -(void) checkSASLMethods:(MLXMPPConnection*) connection description = NSLocalizedString(@"Salted Challenge Response Authentication Mechanism using the given Hash Method additionally secured by Channel-Binding", @""); else if([method hasPrefix:@"SCRAM-"]) description = NSLocalizedString(@"Salted Challenge Response Authentication Mechanism using the given Hash Method", @""); - [self.saslMethods addObject:@{@"Title": [NSString stringWithFormat:NSLocalizedString(@"Method: %@", @""), method], @"Description":description, @"Color":(used ? @"Green" : (!supported ? @"Yellow" : @"None"))}]; + [self.saslMethods addObject:@{@"Title": [NSString stringWithFormat:NSLocalizedString(@"Method: %@", @""), method], @"Description":description, @"Color":(used ? SERVER_DETAILS_COLOR_OK : (!supported ? SERVER_DETAILS_COLOR_NON_IDEAL : @"None"))}]; } } @@ -229,7 +264,7 @@ -(void) checkChannelBindingTypes:(MLXMPPConnection*) connection DDLogVerbose(@"channelBindingTypes: %@", connection.channelBindingTypes); if(connection.channelBindingTypes == nil || connection.channelBindingTypes.count == 0) { - [self.channelBindingTypes addObject:@{@"Title": NSLocalizedString(@"None", @""), @"Description":NSLocalizedString(@"This server does not support any modern channel-binding to secure against MITM attacks on the TLS layer.", @""), @"Color":@"Red"}]; + [self.channelBindingTypes addObject:@{@"Title": NSLocalizedString(@"None", @""), @"Description":NSLocalizedString(@"This server does not support any modern channel-binding to secure against MITM attacks on the TLS layer.", @""), @"Color":SERVER_DETAILS_COLOR_ERROR}]; return; } NSArray* supportedChannelBindingTypes = self.xmppAccount.supportedChannelBindingTypes; @@ -242,7 +277,7 @@ -(void) checkChannelBindingTypes:(MLXMPPConnection*) connection description = NSLocalizedString(@"Secure channel-binding defined for TLS1.3 and some TLS1.2 connections.", @""); else if([type isEqualToString:@"tls-server-end-point"]) description = NSLocalizedString(@"Weakest channel-binding type, not securing against stolen certs/keys, but detects wrongly issued certs.", @""); - [self.channelBindingTypes addObject:@{@"Title": [NSString stringWithFormat:NSLocalizedString(@"Type: %@", @""), type], @"Description":description, @"Color":(used ? @"Green" : (!supported ? @"Yellow" : @"None"))}]; + [self.channelBindingTypes addObject:@{@"Title": [NSString stringWithFormat:NSLocalizedString(@"Type: %@", @""), type], @"Description":description, @"Color":(used ? SERVER_DETAILS_COLOR_OK : (!supported ? SERVER_DETAILS_COLOR_NON_IDEAL : @"None"))}]; } } @@ -257,6 +292,8 @@ -(NSInteger) tableView:(UITableView*) tableView numberOfRowsInSection:(NSInteger { if(section == SUPPORTED_SERVER_XEPS_SECTION) return (NSInteger)self.serverCaps.count; + else if(section == VOIP_SECTION) + return (NSInteger)self.stunTurnServers.count; else if(section == SRV_RECORS_SECTION) return (NSInteger)self.srvRecords.count; else if(section == TLS_SECTION) @@ -275,6 +312,8 @@ -(UITableViewCell*) tableView:(UITableView*) tableView cellForRowAtIndexPath:(NS NSDictionary* dic; if(indexPath.section == SUPPORTED_SERVER_XEPS_SECTION) dic = [self.serverCaps objectAtIndex:(NSUInteger)indexPath.row]; + if(indexPath.section == VOIP_SECTION) + dic = [self.stunTurnServers objectAtIndex:(NSUInteger)indexPath.row]; else if(indexPath.section == SRV_RECORS_SECTION) dic = [self.srvRecords objectAtIndex:(NSUInteger)indexPath.row]; else if(indexPath.section == TLS_SECTION) @@ -295,12 +334,12 @@ -(UITableViewCell*) tableView:(UITableView*) tableView cellForRowAtIndexPath:(NS cell.textLabel.backgroundColor = UIColor.clearColor; cell.detailTextLabel.backgroundColor = UIColor.clearColor; - if([entryColor isEqualToString:@"Green"]) - [cell setBackgroundColor:[UIColor colorWithRed:0 green:0.8 blue:0 alpha:0.2]]; - else if([entryColor isEqualToString:@"Red"]) - [cell setBackgroundColor:[UIColor colorWithRed:0.8 green:0 blue:0 alpha:0.2]]; - else if([entryColor isEqualToString:@"Yellow"]) - [cell setBackgroundColor:[UIColor colorWithRed:1.0 green:1.0 blue:0 alpha:0.2]]; + if([entryColor isEqualToString:SERVER_DETAILS_COLOR_OK]) + [cell setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0.9 alpha:0.2]]; + else if([entryColor isEqualToString:SERVER_DETAILS_COLOR_ERROR]) + [cell setBackgroundColor:[UIColor colorWithRed:1.0 green:0 blue:0 alpha:0.2]]; + else if([entryColor isEqualToString:SERVER_DETAILS_COLOR_NON_IDEAL]) + [cell setBackgroundColor:[UIColor colorWithRed:0.99 green:0.95 blue:0 alpha:0.2]]; else [cell setBackgroundColor:nil]; } @@ -311,14 +350,16 @@ -(NSString*) tableView:(UITableView*) tableView titleForHeaderInSection:(NSInteg { if(section == SUPPORTED_SERVER_XEPS_SECTION) return NSLocalizedString(@"These are the modern XMPP capabilities Monal detected on your server after you have logged in.", @""); + if(section == VOIP_SECTION) + return NSLocalizedString(@"These are STUN and TURN services announced by your server. (blue entries are used by monal)", @""); else if(section == SRV_RECORS_SECTION) return NSLocalizedString(@"These are SRV resource records found for your domain.", @""); else if(section == TLS_SECTION) return NSLocalizedString(@"These are the TLS versions supported by Monal, the one used to connect to your server will be green.", @""); else if(section == SASL_SECTION) - return NSLocalizedString(@"These are the SASL2 methods your server supports (used one in green, yellow ones unsupported by Monal).", @""); + return NSLocalizedString(@"These are the SASL2 methods your server supports (used one in blue, orange ones unsupported by Monal).", @""); else if(section == CB_SECTION) - return NSLocalizedString(@"These are the channel-binding types your server supports to detect attacks on the TLS layer (used one in green, yellow ones unsupported by Monal).", @""); + return NSLocalizedString(@"These are the channel-binding types your server supports to detect attacks on the TLS layer (used one in blue, orange ones unsupported by Monal).", @""); return @""; } diff --git a/Monal/Classes/MLStream.m b/Monal/Classes/MLStream.m index ae6b9fec4d..766e3d06f9 100644 --- a/Monal/Classes/MLStream.m +++ b/Monal/Classes/MLStream.m @@ -43,7 +43,7 @@ -(void) generateEvent:(NSStreamEvent) event; @interface MLInputStream() { - NSData* _buf; + NSMutableData* _buf; BOOL _reading; } @property (atomic, readonly) void (^incoming_data_handler)(NSData* _Nullable, BOOL, NSError* _Nullable); @@ -77,7 +77,7 @@ @implementation MLInputStream -(instancetype) initWithSharedState:(MLSharedStreamState*) shared { self = [super initWithSharedState:shared]; - _buf = [NSData new]; + _buf = [NSMutableData new]; _reading = NO; //this handler will be called by our framer or the schedule_read method @@ -96,7 +96,9 @@ -(instancetype) initWithSharedState:(MLSharedStreamState*) shared { if([content length] > 0) { - self->_buf = content; + @synchronized(self->_buf) { + [self->_buf appendData:content]; + } [self generateEvent:NSStreamEventHasBytesAvailable]; } } @@ -130,32 +132,46 @@ -(NSInteger) read:(uint8_t*) buffer maxLength:(NSUInteger) len if(self.closed || !self.open_called || !self.shared_state.open) return -1; } - if(len > [_buf length]) - len = [_buf length]; - [_buf getBytes:buffer length:len]; - if(len < [_buf length]) - { - _buf = [_buf subdataWithRange:NSMakeRange(len, [_buf length]-len)]; - [self generateEvent:NSStreamEventHasBytesAvailable]; + BOOL was_smaller = NO; + @synchronized(self->_buf) { + if(len > [_buf length]) + len = [_buf length]; + [_buf getBytes:buffer length:len]; + if(len < [_buf length]) + { + NSData* to_append = [_buf subdataWithRange:NSMakeRange(len, [_buf length]-len)]; + [_buf setLength:0]; + [_buf appendData:to_append]; + was_smaller = YES; + } + else + { + [_buf setLength:0]; + was_smaller = NO; + } } + //this has to be done outside of our @synchronized block + if(was_smaller) + [self generateEvent:NSStreamEventHasBytesAvailable]; else - { - _buf = [NSData new]; [self schedule_read]; - } return len; } -(BOOL) getBuffer:(uint8_t* _Nullable *) buffer length:(NSUInteger*) len { - *len = [_buf length]; - *buffer = (uint8_t* _Nullable)[_buf bytes]; - return YES; + @synchronized(_buf) { + *len = [_buf length]; + *buffer = (uint8_t* _Nullable)[_buf bytes]; + return YES; + } } -(BOOL) hasBytesAvailable { - return _buf && [_buf length]; + @synchronized(_buf) { + return _buf && [_buf length]; + } } -(NSStreamStatus) streamStatus @@ -389,7 +405,7 @@ +(void) connectWithSNIDomain:(NSString*) SNIDomain connectHost:(NSString*) host //create simple framer and append it to our stack __block int startupCounter = 0; //workaround for some weird apple stuff, see below - nw_protocol_definition_t starttls_framer_definition = nw_framer_create_definition("starttls_framer", NW_FRAMER_CREATE_FLAGS_DEFAULT, ^(nw_framer_t framer) { + nw_protocol_definition_t starttls_framer_definition = nw_framer_create_definition([[[NSUUID UUID] UUIDString] UTF8String], NW_FRAMER_CREATE_FLAGS_DEFAULT, ^(nw_framer_t framer) { //we don't need any locking for our counter because all framers will be started in the same internal network queue int framerId = startupCounter; startupCounter++; diff --git a/Monal/Classes/SwiftuiHelpers.swift b/Monal/Classes/SwiftuiHelpers.swift index 645e21dedf..bd9bc8390d 100644 --- a/Monal/Classes/SwiftuiHelpers.swift +++ b/Monal/Classes/SwiftuiHelpers.swift @@ -473,6 +473,10 @@ class SwiftuiInterface : NSObject { host.rootView = AnyView(UIKitWorkaround(WelcomeLogIn(delegate:delegate))) case "ContactRequests": host.rootView = AnyView(AddTopLevelNavigation(withDelegate: delegate, to: ContactRequestsMenu(delegate: delegate))) + case "CreateGroup": + host.rootView = AnyView(AddTopLevelNavigation(withDelegate: delegate, to: CreateGroupMenu(delegate: delegate, dismissWithNewGroup: { contact in + // FIXME + }))) case "ChatPlaceholder": host.rootView = AnyView(ChatPlaceholder()) default: diff --git a/Monal/Classes/xmpp.m b/Monal/Classes/xmpp.m index 85e032121c..81401488b9 100644 --- a/Monal/Classes/xmpp.m +++ b/Monal/Classes/xmpp.m @@ -50,7 +50,7 @@ @import WebRTC; #define STATE_VERSION 9 -#define CONNECT_TIMEOUT 12.0 +#define CONNECT_TIMEOUT 7.0 #define IQ_TIMEOUT 60.0 NSString* const kQueueID = @"queueID"; NSString* const kStanza = @"stanza"; @@ -2256,6 +2256,9 @@ -(void) processInput:(MLXMLNode*) parsedStanza withDelayedReplay:(BOOL) delayedR [self sendPresence]; } + //enable push in case our token has changed + [self enablePush]; + //ping all mucs to check if we are still connected (XEP-0410) [self.mucProcessor pingAllMucs]; @@ -3341,7 +3344,7 @@ -(void) realPersistState [values setObject:persistentIqHandlers forKey:@"iqHandlers"]; @synchronized(self->_reconnectionHandlers) { - [values setObject:self->_reconnectionHandlers forKey:@"reconnectionHandlers"]; + [values setObject:[self->_reconnectionHandlers copy] forKey:@"reconnectionHandlers"]; } [values setValue:[self.connectionProperties.serverFeatures copy] forKey:@"serverFeatures"]; @@ -3352,8 +3355,8 @@ -(void) realPersistState [values setObject:[self.pubsub getInternalData] forKey:@"pubsubData"]; [values setObject:[self.mucProcessor getInternalState] forKey:@"mucState"]; - [values setObject:self->_runningCapsQueries forKey:@"runningCapsQueries"]; - [values setObject:self->_runningMamQueries forKey:@"runningMamQueries"]; + [values setObject:[self->_runningCapsQueries copy] forKey:@"runningCapsQueries"]; + [values setObject:[self->_runningMamQueries copy] forKey:@"runningMamQueries"]; [values setObject:[NSNumber numberWithBool:self->_loggedInOnce] forKey:@"loggedInOnce"]; [values setObject:[NSNumber numberWithBool:self.connectionProperties.usingCarbons2] forKey:@"usingCarbons2"]; [values setObject:[NSNumber numberWithBool:self.connectionProperties.supportsBookmarksCompat] forKey:@"supportsBookmarksCompat"]; diff --git a/Monal/Images.xcassets/AlphaAppIcon.appiconset/128.png b/Monal/Images.xcassets/AlphaAppIcon.appiconset/128.png deleted file mode 100644 index 9544abd309..0000000000 Binary files a/Monal/Images.xcassets/AlphaAppIcon.appiconset/128.png and /dev/null differ diff --git a/Monal/Images.xcassets/AlphaAppIcon.appiconset/16.png b/Monal/Images.xcassets/AlphaAppIcon.appiconset/16.png deleted file mode 100644 index 012bddf0be..0000000000 Binary files a/Monal/Images.xcassets/AlphaAppIcon.appiconset/16.png and /dev/null differ diff --git a/Monal/Images.xcassets/AlphaAppIcon.appiconset/256.png b/Monal/Images.xcassets/AlphaAppIcon.appiconset/256.png deleted file mode 100644 index fe838c90c7..0000000000 Binary files a/Monal/Images.xcassets/AlphaAppIcon.appiconset/256.png and /dev/null differ diff --git a/Monal/Images.xcassets/AlphaAppIcon.appiconset/32.png b/Monal/Images.xcassets/AlphaAppIcon.appiconset/32.png deleted file mode 100644 index ce59a53ad9..0000000000 Binary files a/Monal/Images.xcassets/AlphaAppIcon.appiconset/32.png and /dev/null differ diff --git a/Monal/Images.xcassets/AlphaAppIcon.appiconset/512.png b/Monal/Images.xcassets/AlphaAppIcon.appiconset/512.png deleted file mode 100644 index b5321c021d..0000000000 Binary files a/Monal/Images.xcassets/AlphaAppIcon.appiconset/512.png and /dev/null differ diff --git a/Monal/Images.xcassets/AlphaAppIcon.appiconset/64.png b/Monal/Images.xcassets/AlphaAppIcon.appiconset/64.png deleted file mode 100644 index b443078e5a..0000000000 Binary files a/Monal/Images.xcassets/AlphaAppIcon.appiconset/64.png and /dev/null differ diff --git a/Monal/Images.xcassets/AlphaAppIcon.appiconset/Contents.json b/Monal/Images.xcassets/AlphaAppIcon.appiconset/Contents.json index 3cd2bbf406..9a1cf9c542 100644 --- a/Monal/Images.xcassets/AlphaAppIcon.appiconset/Contents.json +++ b/Monal/Images.xcassets/AlphaAppIcon.appiconset/Contents.json @@ -1,67 +1,25 @@ { "images" : [ { - "filename" : "ios_1024.png", + "filename" : "Monal-ios_1024.png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" }, { - "filename" : "16.png", - "idiom" : "mac", - "scale" : "1x", - "size" : "16x16" - }, - { - "filename" : "32.png", - "idiom" : "mac", - "scale" : "2x", - "size" : "16x16" - }, - { - "filename" : "32.png", - "idiom" : "mac", - "scale" : "1x", - "size" : "32x32" - }, - { - "filename" : "64.png", - "idiom" : "mac", - "scale" : "2x", - "size" : "32x32" - }, - { - "filename" : "128.png", - "idiom" : "mac", - "scale" : "1x", - "size" : "128x128" - }, - { - "filename" : "256.png", - "idiom" : "mac", - "scale" : "2x", - "size" : "128x128" - }, - { - "filename" : "256.png", - "idiom" : "mac", - "scale" : "1x", - "size" : "256x256" - }, - { - "filename" : "512.png", + "filename" : "Monal-macos-512.png", "idiom" : "mac", "scale" : "2x", "size" : "256x256" }, { - "filename" : "512.png", + "filename" : "Monal-macos-512.png", "idiom" : "mac", "scale" : "1x", "size" : "512x512" }, { - "filename" : "1024.png", + "filename" : "Monal-macos-1024.png", "idiom" : "mac", "scale" : "2x", "size" : "512x512" diff --git a/Monal/Images.xcassets/AlphaAppIcon.appiconset/1024.png b/Monal/Images.xcassets/AlphaAppIcon.appiconset/Monal-ios_1024.png similarity index 100% rename from Monal/Images.xcassets/AlphaAppIcon.appiconset/1024.png rename to Monal/Images.xcassets/AlphaAppIcon.appiconset/Monal-ios_1024.png diff --git a/Monal/Images.xcassets/AlphaAppIcon.appiconset/Monal-macos-1024.png b/Monal/Images.xcassets/AlphaAppIcon.appiconset/Monal-macos-1024.png new file mode 100644 index 0000000000..d14dc4c803 Binary files /dev/null and b/Monal/Images.xcassets/AlphaAppIcon.appiconset/Monal-macos-1024.png differ diff --git a/Monal/Images.xcassets/AlphaAppIcon.appiconset/Monal-macos-512.png b/Monal/Images.xcassets/AlphaAppIcon.appiconset/Monal-macos-512.png new file mode 100644 index 0000000000..2653f8eab8 Binary files /dev/null and b/Monal/Images.xcassets/AlphaAppIcon.appiconset/Monal-macos-512.png differ diff --git a/Monal/Images.xcassets/AlphaAppIcon.appiconset/ios_1024.png b/Monal/Images.xcassets/AlphaAppIcon.appiconset/ios_1024.png deleted file mode 100644 index 1592da5b15..0000000000 Binary files a/Monal/Images.xcassets/AlphaAppIcon.appiconset/ios_1024.png and /dev/null differ diff --git a/Monal/Monal.xcodeproj/project.pbxproj b/Monal/Monal.xcodeproj/project.pbxproj index 0a46648240..4ff92a30f2 100644 --- a/Monal/Monal.xcodeproj/project.pbxproj +++ b/Monal/Monal.xcodeproj/project.pbxproj @@ -172,6 +172,8 @@ C1049189261301530054AC9E /* MonalXMPPUnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1049188261301530054AC9E /* MonalXMPPUnitTests.swift */; }; C104918B261301530054AC9E /* monalxmpp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26CC579223A0867400ABB92A /* monalxmpp.framework */; }; C1049199261301710054AC9E /* MLCryptoTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1049198261301710054AC9E /* MLCryptoTest.swift */; }; + C117F7E12B086390001F2BC6 /* CreateGroupMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D88BB76295BB6DC00FB30BA /* CreateGroupMenu.swift */; }; + C117F7E22B0863B3001F2BC6 /* ContactList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D631822294BAB1D00026BE7 /* ContactList.swift */; }; C12436142434AB5D00B8F074 /* MLAttributedLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = C12436132434AB5D00B8F074 /* MLAttributedLabel.m */; }; C13A0BCE26E78B7B00987E29 /* ContactDetailsHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = C19C919A26E26AF000F8CC57 /* ContactDetailsHeader.swift */; }; C13EBB8E24DC685C008AADDA /* MLPrivacySettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C13EBB8D24DC685C008AADDA /* MLPrivacySettingsViewController.m */; }; @@ -500,10 +502,12 @@ 3D27D955290B0BB60014748B /* AddContactMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddContactMenu.swift; sourceTree = ""; }; 3D27D957290B0BC80014748B /* ContactRequestsMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactRequestsMenu.swift; sourceTree = ""; }; 3D5A91412842B4AE008CE57E /* MemberList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemberList.swift; sourceTree = ""; }; + 3D631822294BAB1D00026BE7 /* ContactList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactList.swift; sourceTree = ""; }; 3D65B78C27234B74005A30F4 /* ContactDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactDetails.swift; sourceTree = ""; }; 3D65B790272350F0005A30F4 /* SwiftuiHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftuiHelpers.swift; sourceTree = ""; }; 3D7D352228626CB80042C5E5 /* LoadingOverlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingOverlay.swift; sourceTree = ""; }; 3D85E586282AE523006F5B3A /* OmemoQrCodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OmemoQrCodeView.swift; sourceTree = ""; }; + 3D88BB76295BB6DC00FB30BA /* CreateGroupMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateGroupMenu.swift; sourceTree = ""; }; 3DC5035B2822F5220064C8A7 /* OmemoKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OmemoKeys.swift; sourceTree = ""; }; 3EB7A7084FA9A8F68A3D251C /* Pods-MonalXMPPUnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MonalXMPPUnitTests.debug.xcconfig"; path = "Target Support Files/Pods-MonalXMPPUnitTests/Pods-MonalXMPPUnitTests.debug.xcconfig"; sourceTree = ""; }; 4049F81F60EA5B7A57A4E9C6 /* Pods-NotificationService.beta.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.beta.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.beta.xcconfig"; sourceTree = ""; }; @@ -1049,7 +1053,9 @@ 26A78ED623C2B59400C7CF40 /* MLPlaceholderViewController.h */, 26A78ED723C2B59400C7CF40 /* MLPlaceholderViewController.m */, 84FC375828981A5600634E3E /* PasswordMigration.swift */, + 3D631822294BAB1D00026BE7 /* ContactList.swift */, 3D27D955290B0BB60014748B /* AddContactMenu.swift */, + 3D88BB76295BB6DC00FB30BA /* CreateGroupMenu.swift */, 3D27D957290B0BC80014748B /* ContactRequestsMenu.swift */, 846DF27B2937FAA600AAB9C0 /* ChatPlaceholder.swift */, 841898AB2957DBAC00FEC77D /* RichAlert.swift */, @@ -2013,6 +2019,7 @@ 841B6F1A297B18720074F9B7 /* AccountPicker.swift in Sources */, 3D65B791272350F0005A30F4 /* SwiftuiHelpers.swift in Sources */, C1A80DA424D9552400B99E01 /* MLChatViewHelper.m in Sources */, + C117F7E22B0863B3001F2BC6 /* ContactList.swift in Sources */, 1D60589B0D05DD56006BFB54 /* main.m in Sources */, 1D3623260D0F684500981E51 /* MonalAppDelegate.m in Sources */, 26158AF21FFA6E4500E53BDC /* MLWebViewController.m in Sources */, @@ -2052,6 +2059,7 @@ C13A0BCE26E78B7B00987E29 /* ContactDetailsHeader.swift in Sources */, 3D85E587282AE523006F5B3A /* OmemoQrCodeView.swift in Sources */, 849A53E4287135B2007E941A /* MLVoIPProcessor.m in Sources */, + C117F7E12B086390001F2BC6 /* CreateGroupMenu.swift in Sources */, 26D59D9320714F32006F1DEE /* UIColor+Theme.m in Sources */, 3D7D352328626CB80042C5E5 /* LoadingOverlay.swift in Sources */, 26D7C05E23D6AFD800CA123C /* MLChatInputContainer.m in Sources */, @@ -2592,7 +2600,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 14.0; LLVM_LTO = YES; MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 6.0.1; + MARKETING_VERSION = 6.0.2; SDKROOT = iphoneos; SUPPORTS_MACCATALYST = YES; SWIFT_VERSION = 5.0; @@ -2894,7 +2902,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 14.0; LLVM_LTO = YES; MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 6.0.1; + MARKETING_VERSION = 6.0.2; SDKROOT = iphoneos; SUPPORTS_MACCATALYST = YES; SWIFT_VERSION = 5.0; @@ -3041,7 +3049,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 14.0; LLVM_LTO = YES; MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 6.0.1; + MARKETING_VERSION = 6.0.2; ONLY_ACTIVE_ARCH = YES; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = iphoneos; @@ -3302,7 +3310,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 14.0; LLVM_LTO = YES; MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 6.0.1; + MARKETING_VERSION = 6.0.2; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = iphoneos; SUPPORTS_MACCATALYST = YES; @@ -3657,7 +3665,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 14.0; LLVM_LTO = NO; MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 6.0.1; + MARKETING_VERSION = 6.0.2; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = iphoneos; SUPPORTS_MACCATALYST = YES; @@ -4007,7 +4015,7 @@ repositoryURL = "https://github.com/scinfu/SwiftSoup.git"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 2.4.3; + minimumVersion = 2.6.1; }; }; C1F5C7AD2777638B0001F295 /* XCRemoteSwiftPackageReference "swift-collections" */ = { @@ -4015,7 +4023,7 @@ repositoryURL = "https://github.com/apple/swift-collections.git"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 1.0.2; + minimumVersion = 1.0.5; }; }; /* End XCRemoteSwiftPackageReference section */ diff --git a/Monal/Podfile.lock b/Monal/Podfile.lock index 6504da7458..b64713e28d 100644 --- a/Monal/Podfile.lock +++ b/Monal/Podfile.lock @@ -71,9 +71,9 @@ PODS: - MarqueeLabel (~> 4.3.0) - SnapKit (~> 5.6.0) - SAMKeychain (1.5.3) - - SDWebImage (5.18.3): - - SDWebImage/Core (= 5.18.3) - - SDWebImage/Core (5.18.3) + - SDWebImage (5.18.5): + - SDWebImage/Core (= 5.18.5) + - SDWebImage/Core (5.18.5) - SignalProtocolC (2.3.3) - SignalProtocolObjC (1.1.1): - SignalProtocolC (~> 2.3.3) @@ -145,7 +145,7 @@ SPEC CHECKSUMS: MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406 NotificationBannerSwift: dce54ded532b26e30cd8e7f4d80e124a0f2ba7d1 SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c - SDWebImage: 96e0c18ef14010b7485210e92fac888587ebb958 + SDWebImage: 7ac2b7ddc5e8484c79aa90fc4e30b149d6a2c88f SignalProtocolC: 8092866e45b663a6bc3e45a8d13bad2571dbf236 SignalProtocolObjC: 1beb46b1d35733e7ab96a919f88bac20ec771c73 SnapKit: e01d52ebb8ddbc333eefe2132acf85c8227d9c25 @@ -155,4 +155,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 99af97fbdbc651c2f1c5558cb9ba7107ef30aa28 -COCOAPODS: 1.14.2 +COCOAPODS: 1.14.3 diff --git a/rust/Cargo.lock b/rust/Cargo.lock index c6daf92718..2af4906a25 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -138,9 +138,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.24" +version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ad981d6c340a49cdc40a1028d9c6084ec7e9fa33fcb839cab656a267071e234" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ "bitflags 2.4.1", "errno",